Configuring BuildKit for High Performance
Optimizing BuildKit performance is essential for a smooth development experience with Okteto. A high-performance BuildKit setup accelerates image builds, test executions, and deploy commands when using Remote Execution.
1. Dedicated Node Pool for BuildKit
BuildKit is resource-intensive. We recommend deploying BuildKit in a dedicated node pool for optimal performance and to minimize interference from other workloads.
To deploy BuildKit on a dedicated build pool, you can add taints and tolerations to the BuildKit node pool in Kubernetes, and then add the following settings to your Okteto Helm configuration:
buildkit:
nodeSelectors:
okteto-node-pool: build
tolerations:
- effect: NoSchedule
key: okteto-node-pool
operator: Equal
value: build
2. Scale Vertically: Increase CPUs for Faster Builds
BuildKit performance depends heavily on allocated CPU and memory resources. Start with 2 nodes for higher availability, with the following recommended instance types (4 CPUs and 16GB RAM):
- Amazon Web Services:
m6a.xlarge - Google Cloud Platform:
t2d-standard-4 - Microsoft Azure Cloud Platform:
Standard_D4as_v5
Set the replicaCount to match the number of nodes in the BuildKit node pool:
buildkit:
replicaCount: 2
Monitor performance and adjust node resources as needed. For instance, upgrading your BuildKit nodes to 8 CPUs and 32 GB of memory each can provide approximately a 2x performance improvement 😎.
3. Configure SSD Storage
BuildKit is I/O intensive, especially for pulling, extracting, and pushing container images. Using a SSD storage class can significantly improve your BuildKit performance.
buildkit:
persistence:
enabled: true
class: <<your-ssd-storage-class>>
You may also increase the size of the BuildKit cache to increase the number of BuildKit cache hits (default: 100 GB):
buildkit:
persistence:
enabled: true
size: 200Gi
4. Enable HPA to Optimize Performance and Costs
Horizontal Pod Autoscaler (HPA) dynamically adjusts the number of BuildKit pods based on active build workloads. This ensures you have enough capacity during peak times while reducing costs during idle periods.
Okteto supports the following metrics for HPA scaling:
okteto_build_active_builds- Number of active builds (recommended)okteto_build_cpu_pressure- CPU pressure in 10-second intervalsokteto_build_memory_usage- Memory usage as a percentage out of 100%okteto_build_io_pressure- I/O pressure in 10-second intervals
By default, HPA is configured to scale based on the okteto_build_active_builds metric, with the following settings:
buildkit:
hpa:
enabled: true
min: 1
max: 5
metrics:
- type: Pods
pods:
metric:
name: okteto_build_active_builds
target:
type: AverageValue
averageValue: "0.99"
behavior:
scaleUp:
policies:
- type: Pods
value: 1
periodSeconds: 30
scaleDown:
stabilizationWindowSeconds: 600
policies:
- type: Pods
value: 1
periodSeconds: 150
This configuration:
- Scales up quickly (within 30 seconds) when build pressure increases
- Scales down conservatively (pod by pod every 10 minutes) to avoid thrashing
- Maintains between 1 and 5 BuildKit pods based on active builds
Okteto includes a built-in metrics adapter that exposes BuildKit metrics via the v1beta2.custom.metrics.k8s.io API. This adapter is automatically deployed when HPA is enabled.
If you're already using your own custom metrics adapter (such as Prometheus Adapter), you can disable Okteto's built-in adapter by setting buildkit.hpa.adapter.enabled: false in your Helm configuration. In that case, you can scrape metrics directly from the BuildKit pods on port 8080. All metrics have the okteto_build prefix.
5. Save Costs with Spot Instances (optional)
Use spot instances to reduce costs while maintaining sufficient resources for BuildKit.
Ensure high availability by configuring at least 2 nodes across different zones.
The Okteto CLI automatically retries any command if interrupted by BuildKit instance termination or failure to minimize the effect of using spot instances. If using remote execution, it is very important to ensure that your deploy/test/destroy commands are idempotent, as commands may run again if a node terminates during the execution of the deploy or destroy operations.
6. Follow Best Practices for Dockerfiles and Remote Execution
Even the best BuildKit setup cannot compensate for un-optimized Dockerfiles or inefficient Remote Execution configurations. To make the most of your BuildKit configuration, we have the following recommendations:
- Adhere to Dockerfile best practices.
- Reduce file transfer times to BuildKit by using .dockerignore and .oktetoignore files.
- Use BuildKit cache mounts to persist cache folders between image builds. This can significantly speed up build times by caching dependencies and build artifacts.
- Use Test Container caches to persist cache folders between test executions. This ensures that test dependencies are cached, reducing the time taken for subsequent test runs.