build: Add per-step CPU and memory resource limits#3876
Conversation
crazy-max
left a comment
There was a problem hiding this comment.
Thanks but I don't think Buildx should expose this as seven new top-level build flags and seven independent bake fields.
Can we make the Buildx API a single extensible resource collection instead? For CLI, I think --resource fits better with existing repeatable buildx flags:
--resource=memory=2g --resource=memory-swap=4g --resource=cpu-quota=50000
For bake, I think this should mirror that as one target field, like:
resources = ["memory=2g", "memory-swap=4g", "cpu-quota=50000"]That keeps the user-facing API smaller, matches the existing repeatable key/value style, and avoids adding a new flag and bake field every time BuildKit grows another resource knob.
I also don't think we should add these to Compose x-bake. New Compose build fields should be added upstream in https://github.com/compose-spec/compose-spec first and implemented in https://github.com/compose-spec/compose-go, then Buildx can consume them from the normal Compose build model. Expanding x-bake for new fields moves the schema in the wrong place and we plan to deprecate it: #3025
Thanks for the review. So the existing: flags.StringVarP(&ignore, "memory", "m", "", "Memory limit")
flags.MarkHidden("memory")
flags.StringVar(&ignore, "memory-swap", "", `Swap limit equal to memory plus swap: "-1" to enable unlimited swap`)
flags.MarkHidden("memory-swap")
flags.Int64VarP(&ignoreInt, "cpu-shares", "c", 0, "CPU shares (relative weight)")
flags.MarkHidden("cpu-shares")
flags.Int64Var(&ignoreInt, "cpu-period", 0, "Limit the CPU CFS (Completely Fair Scheduler) period")
flags.MarkHidden("cpu-period")
flags.Int64Var(&ignoreInt, "cpu-quota", 0, "Limit the CPU CFS (Completely Fair Scheduler) quota")
flags.MarkHidden("cpu-quota")
flags.StringVar(&ignore, "cpuset-cpus", "", `CPUs in which to allow execution ("0-3", "0,1")`)
flags.MarkHidden("cpuset-cpus")
flags.StringVar(&ignore, "cpuset-mems", "", `MEMs in which to allow execution ("0-3", "0,1")`)
flags.MarkHidden("cpuset-mems")should stay there, right? or do we want to remove it as well? |
7be227d to
f3d3173
Compare
|
I think we want to keep the existing flags (and connect them with For the bake format, I guess it should be a struct (or double format like the cache and output options). |
|
@jirimoravcik Sorry if it was not clear but yes we can keep the existing flags as @tonistiigi explained above. |
e92893f to
2f56a6b
Compare
| CPUSetMems *string `json:"cpuset-mems,omitempty"` | ||
| } | ||
|
|
||
| func (r *ResourcesConfig) Merge(other *ResourcesConfig) *ResourcesConfig { |
There was a problem hiding this comment.
This should avoid mutating either input and shouldn't return other directly.
Target.Merge uses this while resolving inherited targets. If a base target has resources, the current Merge can share the base target's *ResourcesConfig pointer with the resolved child. If the child also sets one resource field, r.Merge(other) mutates that shared config, so the child value can leak into the base target or into another target inheriting the same base.
Can we make this return a fresh ResourcesConfig (or clone before merging), and add a test with two targets inheriting the same base where only one child overrides a resource field?
There was a problem hiding this comment.
It now returns a fresh ResourcesConfig. Added a test (fails with the old logic, passes with the new one)
Port of moby/buildkit#6569 to buildx. Adds --memory, --memory-swap, --cpu-shares, --cpu-period, --cpu-quota, --cpuset-cpus, and --cpuset-mems flags to build, plus the equivalent bake target attributes and compose x-bake fields. Signed-off-by: Jiří Moravčík <jiri.moravcik@gmail.com>
2f56a6b to
80b2293
Compare
| } else { | ||
| t.Ulimits = o.ArrValue | ||
| } | ||
| case "resources": |
There was a problem hiding this comment.
The override keys seem to be undocumented in docs/reference/bake
There was a problem hiding this comment.
Ah yeah indeed should be done in https://docs.docker.com/build/bake/overrides/
| fmt.Fprintf(tw, "Resource Limits:\t%s\n", out.Config.Ulimit) | ||
| } | ||
| if out.Config.Memory != "" { | ||
| fmt.Fprintf(tw, "Memory:\t%s\n", out.Config.Memory) |
There was a problem hiding this comment.
These fields should have friendlier printing than just big integer.
| if len(keys) != 3 { | ||
| return nil, errors.Errorf("invalid key %s, resources requires name", parts[0]) | ||
| } | ||
| if len(parts) == 2 { |
There was a problem hiding this comment.
nit: this is already guaranteed by the len check in L582
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [buildx](https://github.com/docker/buildx) | | minor | `v0.34.1` → `v0.35.0` | | [buildx](https://github.com/docker/buildx) | uses-with | minor | `v0.34.1` → `v0.35.0` | --- ### Release Notes <details> <summary>docker/buildx (buildx)</summary> ### [`v0.35.0`](https://github.com/docker/buildx/releases/tag/v0.35.0) [Compare Source](docker/buildx@v0.34.1...v0.35.0-rc2) buildx 0.35.0 Welcome to the v0.35.0 release of buildx! Please try out the release binaries and report any issues at <https://github.com/docker/buildx/issues>. ##### Contributors - CrazyMax - Tõnis Tiigi - Sebastiaan van Stijn - Areeb Ahmed - Jiří Moravčík - Sopho Merkviladze - Akihiro Suda - Jonathan A. Sternberg ##### Notable Changes - Local output now supports a `mode=delete` attribute for build and bake commands. This mode replaces the destination directory with the build result instead of merging it. Similar to the `--delete` flag in rsync. For safety, this mode is only allowed if the destination directory is a subdirectory of the working directory. To export to other destinations, `--allow=buildx.local.delete` needs to be provided or the action confirmed by the user in the TUI. When exporting multi-platform results, this mode requires BuildKit v0.31.0+. [#​3883](docker/buildx#3883) - Source policies now support the new exec proxy feature of BuildKit v0.31.0+ that captures the network traffic of your build steps. To opt in to network proxy, your Dockerfile.rego source policy needs to return `caps: { "exec.proxy": true }` in the evaluation decision. After opting in, you can control what network requests are allowed to be made by the run steps with policy rules for regular `input.http` sources, similar to how this was done for direct HTTP build sources before. You can also opt in your whole builder with `--buildkitd-flags '--proxy-network'` in `buildx create`. [#​3895](docker/buildx#3895) - Resource limits can now be set for CPU and memory using the `--resource` flag in `build` and the `resource` key in `bake` commands. This feature requires BuildKit v0.31.0+ and Dockerfile v1.25.0+. [#​3876](docker/buildx#3876) [#​3900](docker/buildx#3900) - Fix possible "closed channel" panic. [#​3886](docker/buildx#3886) ##### Dependency Changes - **github.com/aws/aws-sdk-go-v2** v1.41.7 -> v1.42.0 - **github.com/aws/aws-sdk-go-v2/config** v1.32.17 -> v1.32.24 - **github.com/aws/aws-sdk-go-v2/credentials** v1.19.16 -> v1.19.23 - **github.com/aws/aws-sdk-go-v2/feature/ec2/imds** v1.18.23 -> v1.18.29 - **github.com/aws/aws-sdk-go-v2/internal/configsources** v1.4.23 -> v1.4.29 - **github.com/aws/aws-sdk-go-v2/internal/endpoints/v2** v2.7.23 -> v2.7.29 - **github.com/aws/aws-sdk-go-v2/internal/v4a** v1.4.24 -> v1.4.30 - **github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding** v1.13.9 -> v1.13.12 - **github.com/aws/aws-sdk-go-v2/service/internal/presigned-url** v1.13.23 -> v1.13.29 - **github.com/aws/aws-sdk-go-v2/service/signin** v1.0.11 -> v1.1.5 - **github.com/aws/aws-sdk-go-v2/service/sso** v1.30.17 -> v1.31.3 - **github.com/aws/aws-sdk-go-v2/service/ssooidc** v1.35.21 -> v1.36.6 - **github.com/aws/aws-sdk-go-v2/service/sts** v1.42.1 -> v1.43.3 - **github.com/aws/smithy-go** v1.25.1 -> v1.27.2 - **github.com/containerd/containerd/v2** v2.2.3 -> v2.2.4 - **github.com/containerd/continuity** v0.4.5 -> v0.5.0 - **github.com/containerd/platforms** v1.0.0-rc.2 -> v1.0.0-rc.4 - **github.com/containerd/typeurl/v2** v2.2.3 -> v2.3.0 - **github.com/docker/cli** v29.4.3 -> v29.5.3 - **github.com/docker/distribution** v2.8.3 ***new*** - **github.com/docker/docker-credential-helpers** v0.9.5 -> v0.9.8 - **github.com/go-openapi/analysis** v0.24.3 -> v0.25.2 - **github.com/go-openapi/jsonpointer** v0.22.5 -> v0.23.1 - **github.com/go-openapi/jsonreference** v0.21.5 -> v0.21.6 - **github.com/go-openapi/runtime** v0.29.3 -> v0.32.3 - **github.com/go-openapi/runtime/server-middleware** v0.30.0 ***new*** - **github.com/go-openapi/spec** v0.22.4 -> v0.22.5 - **github.com/go-openapi/strfmt** v0.26.1 -> v0.26.3 - **github.com/go-openapi/swag** v0.25.5 -> v0.26.0 - **github.com/go-openapi/swag/cmdutils** v0.25.5 -> v0.26.0 - **github.com/go-openapi/swag/conv** v0.25.5 -> v0.26.0 - **github.com/go-openapi/swag/fileutils** v0.25.5 -> v0.26.0 - **github.com/go-openapi/swag/jsonname** v0.25.5 -> v0.26.0 - **github.com/go-openapi/swag/jsonutils** v0.25.5 -> v0.26.0 - **github.com/go-openapi/swag/loading** v0.25.5 -> v0.26.0 - **github.com/go-openapi/swag/mangling** v0.25.5 -> v0.26.0 - **github.com/go-openapi/swag/netutils** v0.25.5 -> v0.26.0 - **github.com/go-openapi/swag/stringutils** v0.25.5 -> v0.26.0 - **github.com/go-openapi/swag/typeutils** v0.25.5 -> v0.26.0 - **github.com/go-openapi/swag/yamlutils** v0.25.5 -> v0.26.0 - **github.com/go-openapi/validate** v0.25.2 -> v0.25.3 - **github.com/google/certificate-transparency-go** v1.3.2 -> v1.3.3 - **github.com/google/go-containerregistry** v0.20.7 -> v0.21.6 - **github.com/gorilla/mux** v1.8.1 ***new*** - **github.com/grpc-ecosystem/grpc-gateway/v2** v2.28.0 -> v2.29.0 - **github.com/in-toto/attestation** v1.1.2 -> v1.2.0 - **github.com/moby/buildkit** v0.30.0 -> v0.31.0 - **github.com/moby/policy-helpers** [`a39d601`](docker/buildx@a39d60132186) -> [`d5411a9`](docker/buildx@d5411a945cfc) - **github.com/moby/sys/sequential** v0.6.0 -> v0.7.0 - **github.com/pelletier/go-toml/v2** v2.2.4 -> v2.3.1 - **github.com/prometheus/common** v0.66.1 -> v0.67.5 - **github.com/prometheus/procfs** v0.17.0 -> v0.20.1 - **github.com/secure-systems-lab/go-securesystemslib** v0.10.0 -> v0.11.0 - **github.com/sigstore/protobuf-specs** v0.5.0 -> v0.5.1 - **github.com/sigstore/rekor** v1.5.0 -> v1.5.2 - **github.com/sigstore/rekor-tiles/v2** v2.0.1 -> [`5d098a2`](docker/buildx@5d098a2b6443) - **github.com/sigstore/sigstore** v1.10.5 -> v1.10.8 - **github.com/sigstore/sigstore-go** v1.1.4 -> v1.2.1 - **github.com/sigstore/timestamp-authority/v2** v2.0.6 -> v2.1.2 - **github.com/theupdateframework/go-tuf/v2** v2.4.1 -> v2.4.2 - **github.com/tonistiigi/fsutil** [`a2aa163`](docker/buildx@a2aa163d723f) -> [`0257b33`](docker/buildx@0257b3308df4) - **github.com/transparency-dev/formats** [`404c0d5`](docker/buildx@404c0d5b696c) -> v0.1.1 - **github.com/youmark/pkcs8** [`a2c0da2`](docker/buildx@a2c0da244d78) ***new*** - **go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc** v0.68.0 -> v0.69.0 - **go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace** v0.68.0 -> v0.69.0 - **go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp** v0.68.0 -> v0.69.0 - **go.opentelemetry.io/otel** v1.43.0 -> v1.44.0 - **go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc** v1.43.0 -> v1.44.0 - **go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp** v1.43.0 -> v1.44.0 - **go.opentelemetry.io/otel/exporters/otlp/otlptrace** v1.43.0 -> v1.44.0 - **go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc** v1.43.0 -> v1.44.0 - **go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp** v1.43.0 -> v1.44.0 - **go.opentelemetry.io/otel/exporters/stdout/stdouttrace** v1.42.0 -> v1.44.0 - **go.opentelemetry.io/otel/metric** v1.43.0 -> v1.44.0 - **go.opentelemetry.io/otel/sdk** v1.43.0 -> v1.44.0 - **go.opentelemetry.io/otel/sdk/metric** v1.43.0 -> v1.44.0 - **go.opentelemetry.io/otel/trace** v1.43.0 -> v1.44.0 - **go.yaml.in/yaml/v2** v2.4.3 -> v2.4.4 - **google.golang.org/genproto/googleapis/api** [`6f92a3b`](docker/buildx@6f92a3bedf2d) -> [`3dc84a4`](docker/buildx@3dc84a4a5aaa) - **google.golang.org/genproto/googleapis/rpc** [`6f92a3b`](docker/buildx@6f92a3bedf2d) -> [`3dc84a4`](docker/buildx@3dc84a4a5aaa) - **google.golang.org/grpc** v1.80.0 -> v1.81.1 - **google.golang.org/grpc/cmd/protoc-gen-go-grpc** v1.5.1 -> v1.6.1 - **k8s.io/klog/v2** v2.130.1 -> v2.140.0 Previous release can be found at [v0.34.1](https://github.com/docker/buildx/releases/tag/v0.34.1) </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - Between 12:00 AM and 03:59 AM (`* 0-3 * * *`) - Automerge - Between 12:00 AM and 03:59 AM (`* 0-3 * * *`) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNTIuMSIsInVwZGF0ZWRJblZlciI6IjQzLjI1Mi4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJLaW5kL0RlcGVuZGVuY3lVcGRhdGUiLCJydW4tZW5kLXRvLWVuZC10ZXN0cyJdfQ==--> Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1603
Port of moby/buildkit#6569 to buildx. Adds
--resourcerow with things like--memory,--memory-swap,--cpu-shares,--cpu-period,--cpu-quota,--cpuset-cpus, and--cpuset-memsto build, plus the equivalent bake target attributes