1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Merge pull request #37644 from AntaresS/handle-cgroups

propagate the dockerd cgroup-parent config to buildkitd
This commit is contained in:
Tibor Vass 2018-09-13 14:19:45 -07:00 committed by GitHub
commit 9d276b8afd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 575 additions and 46 deletions

View file

@ -50,10 +50,11 @@ func init() {
// Opt is option struct required for creating the builder // Opt is option struct required for creating the builder
type Opt struct { type Opt struct {
SessionManager *session.Manager SessionManager *session.Manager
Root string Root string
Dist images.DistributionServices Dist images.DistributionServices
NetworkController libnetwork.NetworkController NetworkController libnetwork.NetworkController
DefaultCgroupParent string
} }
// Builder can build using BuildKit backend // Builder can build using BuildKit backend

View file

@ -102,7 +102,7 @@ func newController(rt http.RoundTripper, opt Opt) (*control.Controller, error) {
return nil, err return nil, err
} }
exec, err := newExecutor(root, opt.NetworkController) exec, err := newExecutor(root, opt.DefaultCgroupParent, opt.NetworkController)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -19,15 +19,16 @@ import (
const networkName = "bridge" const networkName = "bridge"
func newExecutor(root string, net libnetwork.NetworkController) (executor.Executor, error) { func newExecutor(root, cgroupParent string, net libnetwork.NetworkController) (executor.Executor, error) {
networkProviders := map[pb.NetMode]network.Provider{ networkProviders := map[pb.NetMode]network.Provider{
pb.NetMode_UNSET: &bridgeProvider{NetworkController: net}, pb.NetMode_UNSET: &bridgeProvider{NetworkController: net},
pb.NetMode_HOST: network.NewHostProvider(), pb.NetMode_HOST: network.NewHostProvider(),
pb.NetMode_NONE: network.NewNoneProvider(), pb.NetMode_NONE: network.NewNoneProvider(),
} }
return runcexecutor.New(runcexecutor.Opt{ return runcexecutor.New(runcexecutor.Opt{
Root: filepath.Join(root, "executor"), Root: filepath.Join(root, "executor"),
CommandCandidates: []string{"docker-runc", "runc"}, CommandCandidates: []string{"docker-runc", "runc"},
DefaultCgroupParent: cgroupParent,
}, networkProviders) }, networkProviders)
} }

View file

@ -10,7 +10,7 @@ import (
"github.com/moby/buildkit/executor" "github.com/moby/buildkit/executor"
) )
func newExecutor(_ string, _ libnetwork.NetworkController) (executor.Executor, error) { func newExecutor(_, _ string, _ libnetwork.NetworkController) (executor.Executor, error) {
return &winExecutor{}, nil return &winExecutor{}, nil
} }

View file

@ -46,6 +46,7 @@ import (
type Opt struct { type Opt struct {
ID string ID string
Labels map[string]string Labels map[string]string
GCPolicy []client.PruneInfo
SessionManager *session.Manager SessionManager *session.Manager
MetadataStore *metadata.Store MetadataStore *metadata.Store
Executor executor.Executor Executor executor.Executor
@ -130,6 +131,11 @@ func (w *Worker) Platforms() []ocispec.Platform {
return []ocispec.Platform{platforms.DefaultSpec()} return []ocispec.Platform{platforms.DefaultSpec()}
} }
// GCPolicy returns automatic GC Policy
func (w *Worker) GCPolicy() []client.PruneInfo {
return w.Opt.GCPolicy
}
// LoadRef loads a reference by ID // LoadRef loads a reference by ID
func (w *Worker) LoadRef(id string) (cache.ImmutableRef, error) { func (w *Worker) LoadRef(id string) (cache.ImmutableRef, error) {
return w.CacheManager.Get(context.TODO(), id) return w.CacheManager.Get(context.TODO(), id)
@ -176,8 +182,8 @@ func (w *Worker) DiskUsage(ctx context.Context, opt client.DiskUsageInfo) ([]*cl
} }
// Prune deletes reclaimable build cache // Prune deletes reclaimable build cache
func (w *Worker) Prune(ctx context.Context, ch chan client.UsageInfo, info client.PruneInfo) error { func (w *Worker) Prune(ctx context.Context, ch chan client.UsageInfo, info ...client.PruneInfo) error {
return w.CacheManager.Prune(ctx, ch, info) return w.CacheManager.Prune(ctx, ch, info...)
} }
// Exporter returns exporter by name // Exporter returns exporter by name

View file

@ -259,7 +259,7 @@ type routerOptions struct {
cluster *cluster.Cluster cluster *cluster.Cluster
} }
func newRouterOptions(config *config.Config, daemon *daemon.Daemon) (routerOptions, error) { func newRouterOptions(config *config.Config, d *daemon.Daemon) (routerOptions, error) {
opts := routerOptions{} opts := routerOptions{}
sm, err := session.NewManager() sm, err := session.NewManager()
if err != nil { if err != nil {
@ -280,21 +280,23 @@ func newRouterOptions(config *config.Config, daemon *daemon.Daemon) (routerOptio
return opts, errors.Wrap(err, "failed to create fscache") return opts, errors.Wrap(err, "failed to create fscache")
} }
manager, err := dockerfile.NewBuildManager(daemon.BuilderBackend(), sm, buildCache, daemon.IdentityMapping()) manager, err := dockerfile.NewBuildManager(d.BuilderBackend(), sm, buildCache, d.IdentityMapping())
if err != nil { if err != nil {
return opts, err return opts, err
} }
cgroupParent := newCgroupParent(config)
bk, err := buildkit.New(buildkit.Opt{ bk, err := buildkit.New(buildkit.Opt{
SessionManager: sm, SessionManager: sm,
Root: filepath.Join(config.Root, "buildkit"), Root: filepath.Join(config.Root, "buildkit"),
Dist: daemon.DistributionServices(), Dist: d.DistributionServices(),
NetworkController: daemon.NetworkController(), NetworkController: d.NetworkController(),
DefaultCgroupParent: cgroupParent,
}) })
if err != nil { if err != nil {
return opts, err return opts, err
} }
bb, err := buildbackend.NewBackend(daemon.ImageService(), manager, buildCache, bk) bb, err := buildbackend.NewBackend(d.ImageService(), manager, buildCache, bk)
if err != nil { if err != nil {
return opts, errors.Wrap(err, "failed to create buildmanager") return opts, errors.Wrap(err, "failed to create buildmanager")
} }
@ -303,8 +305,8 @@ func newRouterOptions(config *config.Config, daemon *daemon.Daemon) (routerOptio
buildBackend: bb, buildBackend: bb,
buildCache: buildCache, buildCache: buildCache,
buildkit: bk, buildkit: bk,
features: daemon.Features(), features: d.Features(),
daemon: daemon, daemon: d,
}, nil }, nil
} }

View file

@ -13,6 +13,7 @@ import (
"github.com/containerd/containerd/runtime/v1/linux" "github.com/containerd/containerd/runtime/v1/linux"
"github.com/docker/docker/cmd/dockerd/hack" "github.com/docker/docker/cmd/dockerd/hack"
"github.com/docker/docker/daemon" "github.com/docker/docker/daemon"
"github.com/docker/docker/daemon/config"
"github.com/docker/docker/libcontainerd/supervisor" "github.com/docker/docker/libcontainerd/supervisor"
"github.com/docker/libnetwork/portallocator" "github.com/docker/libnetwork/portallocator"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
@ -107,3 +108,18 @@ func wrapListeners(proto string, ls []net.Listener) []net.Listener {
} }
return ls return ls
} }
func newCgroupParent(config *config.Config) string {
cgroupParent := "docker"
useSystemd := daemon.UsingSystemd(config)
if useSystemd {
cgroupParent = "system.slice"
}
if config.CgroupParent != "" {
cgroupParent = config.CgroupParent
}
if useSystemd {
cgroupParent = cgroupParent + ":" + "docker" + ":"
}
return cgroupParent
}

View file

@ -6,6 +6,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"github.com/docker/docker/daemon/config"
"github.com/docker/docker/libcontainerd/supervisor" "github.com/docker/docker/libcontainerd/supervisor"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
@ -83,3 +84,7 @@ func allocateDaemonPort(addr string) error {
func wrapListeners(proto string, ls []net.Listener) []net.Listener { func wrapListeners(proto string, ls []net.Listener) []net.Listener {
return ls return ls
} }
func newCgroupParent(config *config.Config) string {
return ""
}

View file

@ -26,7 +26,7 @@ github.com/imdario/mergo v0.3.6
golang.org/x/sync 1d60e4601c6fd243af51cc01ddf169918a5407ca golang.org/x/sync 1d60e4601c6fd243af51cc01ddf169918a5407ca
# buildkit # buildkit
github.com/moby/buildkit 6812dac65e0440bb75affce1fb2175e640edc15d github.com/moby/buildkit a9fe50acf16dd05d1f9877b27068884543ad7a1f
github.com/tonistiigi/fsutil b19464cd1b6a00773b4f2eb7acf9c30426f9df42 github.com/tonistiigi/fsutil b19464cd1b6a00773b4f2eb7acf9c30426f9df42
github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746 github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746
github.com/opentracing/opentracing-go 1361b9cd60be79c4c3a7fa9841b3c132e40066a7 github.com/opentracing/opentracing-go 1361b9cd60be79c4c3a7fa9841b3c132e40066a7

View file

@ -9,6 +9,7 @@
It has these top-level messages: It has these top-level messages:
WorkerRecord WorkerRecord
GCPolicy
*/ */
package moby_buildkit_v1_types package moby_buildkit_v1_types
@ -35,6 +36,7 @@ type WorkerRecord struct {
ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"` ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"`
Labels map[string]string `protobuf:"bytes,2,rep,name=Labels" json:"Labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` Labels map[string]string `protobuf:"bytes,2,rep,name=Labels" json:"Labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Platforms []pb.Platform `protobuf:"bytes,3,rep,name=platforms" json:"platforms"` Platforms []pb.Platform `protobuf:"bytes,3,rep,name=platforms" json:"platforms"`
GCPolicy []*GCPolicy `protobuf:"bytes,4,rep,name=GCPolicy" json:"GCPolicy,omitempty"`
} }
func (m *WorkerRecord) Reset() { *m = WorkerRecord{} } func (m *WorkerRecord) Reset() { *m = WorkerRecord{} }
@ -63,8 +65,56 @@ func (m *WorkerRecord) GetPlatforms() []pb.Platform {
return nil return nil
} }
func (m *WorkerRecord) GetGCPolicy() []*GCPolicy {
if m != nil {
return m.GCPolicy
}
return nil
}
type GCPolicy struct {
All bool `protobuf:"varint,1,opt,name=all,proto3" json:"all,omitempty"`
KeepDuration int64 `protobuf:"varint,2,opt,name=keepDuration,proto3" json:"keepDuration,omitempty"`
KeepBytes int64 `protobuf:"varint,3,opt,name=keepBytes,proto3" json:"keepBytes,omitempty"`
Filters []string `protobuf:"bytes,4,rep,name=filters" json:"filters,omitempty"`
}
func (m *GCPolicy) Reset() { *m = GCPolicy{} }
func (m *GCPolicy) String() string { return proto.CompactTextString(m) }
func (*GCPolicy) ProtoMessage() {}
func (*GCPolicy) Descriptor() ([]byte, []int) { return fileDescriptorWorker, []int{1} }
func (m *GCPolicy) GetAll() bool {
if m != nil {
return m.All
}
return false
}
func (m *GCPolicy) GetKeepDuration() int64 {
if m != nil {
return m.KeepDuration
}
return 0
}
func (m *GCPolicy) GetKeepBytes() int64 {
if m != nil {
return m.KeepBytes
}
return 0
}
func (m *GCPolicy) GetFilters() []string {
if m != nil {
return m.Filters
}
return nil
}
func init() { func init() {
proto.RegisterType((*WorkerRecord)(nil), "moby.buildkit.v1.types.WorkerRecord") proto.RegisterType((*WorkerRecord)(nil), "moby.buildkit.v1.types.WorkerRecord")
proto.RegisterType((*GCPolicy)(nil), "moby.buildkit.v1.types.GCPolicy")
} }
func (m *WorkerRecord) Marshal() (dAtA []byte, err error) { func (m *WorkerRecord) Marshal() (dAtA []byte, err error) {
size := m.Size() size := m.Size()
@ -116,6 +166,71 @@ func (m *WorkerRecord) MarshalTo(dAtA []byte) (int, error) {
i += n i += n
} }
} }
if len(m.GCPolicy) > 0 {
for _, msg := range m.GCPolicy {
dAtA[i] = 0x22
i++
i = encodeVarintWorker(dAtA, i, uint64(msg.Size()))
n, err := msg.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n
}
}
return i, nil
}
func (m *GCPolicy) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalTo(dAtA)
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *GCPolicy) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if m.All {
dAtA[i] = 0x8
i++
if m.All {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i++
}
if m.KeepDuration != 0 {
dAtA[i] = 0x10
i++
i = encodeVarintWorker(dAtA, i, uint64(m.KeepDuration))
}
if m.KeepBytes != 0 {
dAtA[i] = 0x18
i++
i = encodeVarintWorker(dAtA, i, uint64(m.KeepBytes))
}
if len(m.Filters) > 0 {
for _, s := range m.Filters {
dAtA[i] = 0x22
i++
l = len(s)
for l >= 1<<7 {
dAtA[i] = uint8(uint64(l)&0x7f | 0x80)
l >>= 7
i++
}
dAtA[i] = uint8(l)
i++
i += copy(dAtA[i:], s)
}
}
return i, nil return i, nil
} }
@ -149,6 +264,33 @@ func (m *WorkerRecord) Size() (n int) {
n += 1 + l + sovWorker(uint64(l)) n += 1 + l + sovWorker(uint64(l))
} }
} }
if len(m.GCPolicy) > 0 {
for _, e := range m.GCPolicy {
l = e.Size()
n += 1 + l + sovWorker(uint64(l))
}
}
return n
}
func (m *GCPolicy) Size() (n int) {
var l int
_ = l
if m.All {
n += 2
}
if m.KeepDuration != 0 {
n += 1 + sovWorker(uint64(m.KeepDuration))
}
if m.KeepBytes != 0 {
n += 1 + sovWorker(uint64(m.KeepBytes))
}
if len(m.Filters) > 0 {
for _, s := range m.Filters {
l = len(s)
n += 1 + l + sovWorker(uint64(l))
}
}
return n return n
} }
@ -372,6 +514,174 @@ func (m *WorkerRecord) Unmarshal(dAtA []byte) error {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field GCPolicy", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowWorker
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthWorker
}
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.GCPolicy = append(m.GCPolicy, &GCPolicy{})
if err := m.GCPolicy[len(m.GCPolicy)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipWorker(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthWorker
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *GCPolicy) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowWorker
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: GCPolicy: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: GCPolicy: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field All", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowWorker
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.All = bool(v != 0)
case 2:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field KeepDuration", wireType)
}
m.KeepDuration = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowWorker
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.KeepDuration |= (int64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field KeepBytes", wireType)
}
m.KeepBytes = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowWorker
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.KeepBytes |= (int64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Filters", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowWorker
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthWorker
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Filters = append(m.Filters, string(dAtA[iNdEx:postIndex]))
iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipWorker(dAtA[iNdEx:]) skippy, err := skipWorker(dAtA[iNdEx:])
@ -501,23 +811,28 @@ var (
func init() { proto.RegisterFile("worker.proto", fileDescriptorWorker) } func init() { proto.RegisterFile("worker.proto", fileDescriptorWorker) }
var fileDescriptorWorker = []byte{ var fileDescriptorWorker = []byte{
// 273 bytes of a gzipped FileDescriptorProto // 355 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x8f, 0x41, 0x4b, 0xf3, 0x40, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x91, 0xc1, 0x4e, 0xea, 0x40,
0x10, 0x86, 0xbf, 0x4d, 0x3e, 0x0b, 0xdd, 0x06, 0x91, 0x45, 0x24, 0xe4, 0x10, 0x8b, 0xa7, 0x1e, 0x14, 0x86, 0x6f, 0x5b, 0x2e, 0x97, 0x0e, 0xcd, 0x8d, 0x99, 0x18, 0xd3, 0x10, 0x83, 0x84, 0x15,
0x74, 0xb6, 0xea, 0x45, 0x3d, 0x96, 0x0a, 0x16, 0x3c, 0x48, 0x2e, 0x9e, 0xb3, 0xed, 0x36, 0x86, 0x0b, 0x9d, 0xa2, 0x6e, 0xd4, 0xb8, 0x42, 0x8c, 0x92, 0xb8, 0x20, 0xb3, 0x71, 0xdd, 0x81, 0x01,
0x24, 0xce, 0xb2, 0xd9, 0x44, 0xf2, 0x0f, 0x7b, 0xf4, 0xe2, 0x55, 0x24, 0xbf, 0x44, 0xba, 0x89, 0x9b, 0x0e, 0x9c, 0xc9, 0x74, 0x8a, 0xf6, 0x39, 0x7c, 0x29, 0x96, 0x3e, 0x81, 0x31, 0x3c, 0x89,
0x98, 0x83, 0xb7, 0x79, 0x87, 0x67, 0x1e, 0xde, 0xa1, 0xde, 0x1b, 0xea, 0x4c, 0x6a, 0x50, 0x1a, 0x99, 0x29, 0x08, 0x26, 0xba, 0x3b, 0xff, 0x9f, 0xff, 0xfb, 0xe7, 0x9c, 0x0c, 0x0a, 0x9e, 0x41,
0x0d, 0xb2, 0x93, 0x02, 0x45, 0x03, 0xa2, 0x4a, 0xf3, 0x4d, 0x96, 0x1a, 0xa8, 0x2f, 0xc1, 0x34, 0xa5, 0x5c, 0x11, 0xa9, 0x40, 0x03, 0x3e, 0x98, 0x01, 0x2b, 0x08, 0xcb, 0x13, 0x31, 0x4e, 0x13,
0x4a, 0x96, 0xc1, 0x45, 0x92, 0x9a, 0x97, 0x4a, 0xc0, 0x1a, 0x0b, 0x9e, 0x60, 0x82, 0xdc, 0xe2, 0x4d, 0x16, 0xa7, 0x44, 0x17, 0x92, 0x67, 0x8d, 0x93, 0x69, 0xa2, 0x9f, 0x72, 0x46, 0x46, 0x30,
0xa2, 0xda, 0xda, 0x64, 0x83, 0x9d, 0x3a, 0x4d, 0x70, 0x3e, 0xc0, 0xf7, 0x46, 0xfe, 0x63, 0xe4, 0x8b, 0xa6, 0x30, 0x85, 0xc8, 0xc6, 0x59, 0x3e, 0xb1, 0xca, 0x0a, 0x3b, 0x95, 0x35, 0x8d, 0xe3,
0x25, 0xe6, 0xb5, 0xd4, 0x5c, 0x09, 0x8e, 0xaa, 0xec, 0xe8, 0xb3, 0x0f, 0x42, 0xbd, 0x67, 0xdb, 0x9d, 0xb8, 0x69, 0x8c, 0x36, 0x8d, 0x51, 0x06, 0x62, 0xc1, 0x55, 0x24, 0x59, 0x04, 0x32, 0x2b,
0x22, 0x92, 0x6b, 0xd4, 0x1b, 0x76, 0x48, 0x9d, 0xd5, 0xd2, 0x27, 0x53, 0x32, 0x1b, 0x47, 0xce, 0xd3, 0xed, 0x57, 0x17, 0x05, 0x8f, 0x76, 0x0b, 0xca, 0x47, 0xa0, 0xc6, 0xf8, 0x3f, 0x72, 0x07,
0x6a, 0xc9, 0x1e, 0xe8, 0xe8, 0x31, 0x16, 0x32, 0x2f, 0x7d, 0x67, 0xea, 0xce, 0x26, 0x57, 0x73, 0xfd, 0xd0, 0x69, 0x39, 0x1d, 0x9f, 0xba, 0x83, 0x3e, 0xbe, 0x47, 0xd5, 0x87, 0x98, 0x71, 0x91,
0xf8, 0xbb, 0x26, 0x0c, 0x2d, 0xd0, 0x9d, 0xdc, 0xbf, 0x1a, 0xdd, 0x44, 0xfd, 0x3d, 0x9b, 0xd3, 0x85, 0x6e, 0xcb, 0xeb, 0xd4, 0xcf, 0xba, 0xe4, 0xe7, 0x35, 0xc9, 0x6e, 0x0b, 0x29, 0x91, 0xdb,
0xb1, 0xca, 0x63, 0xb3, 0x45, 0x5d, 0x94, 0xbe, 0x6b, 0x65, 0x1e, 0x28, 0x01, 0x4f, 0xfd, 0x72, 0xb9, 0x56, 0x05, 0x5d, 0xf3, 0xb8, 0x8b, 0x7c, 0x29, 0x62, 0x3d, 0x01, 0x35, 0xcb, 0x42, 0xcf,
0xf1, 0x7f, 0xf7, 0x79, 0xfa, 0x2f, 0xfa, 0x85, 0x82, 0x5b, 0x3a, 0x19, 0x88, 0xd8, 0x11, 0x75, 0x96, 0x05, 0x44, 0x32, 0x32, 0x5c, 0x9b, 0xbd, 0xca, 0xf2, 0xfd, 0xe8, 0x0f, 0xdd, 0x86, 0xf0,
0x33, 0xd9, 0xf4, 0xdd, 0xf6, 0x23, 0x3b, 0xa6, 0x07, 0x75, 0x9c, 0x57, 0xd2, 0x77, 0xec, 0xae, 0x35, 0xaa, 0xdd, 0xdd, 0x0c, 0x41, 0x24, 0xa3, 0x22, 0xac, 0x58, 0xa0, 0xf5, 0xdb, 0xeb, 0x9b,
0x0b, 0x77, 0xce, 0x0d, 0x59, 0x78, 0xbb, 0x36, 0x24, 0xef, 0x6d, 0x48, 0xbe, 0xda, 0x90, 0x88, 0x1c, 0xfd, 0x22, 0x1a, 0x97, 0xa8, 0xbe, 0xb3, 0x06, 0xde, 0x43, 0x5e, 0xca, 0x8b, 0xf5, 0x65,
0x91, 0x7d, 0xf6, 0xfa, 0x3b, 0x00, 0x00, 0xff, 0xff, 0xa9, 0x5c, 0x8f, 0x26, 0x71, 0x01, 0x00, 0x66, 0xc4, 0xfb, 0xe8, 0xef, 0x22, 0x16, 0x39, 0x0f, 0x5d, 0xeb, 0x95, 0xe2, 0xca, 0xbd, 0x70,
0x00, 0xda, 0x2f, 0xdb, 0x87, 0x0d, 0x17, 0x0b, 0x61, 0xb9, 0x1a, 0x35, 0x23, 0x6e, 0xa3, 0x20, 0xe5,
0x5c, 0xf6, 0x73, 0x15, 0xeb, 0x04, 0xe6, 0x16, 0xf7, 0xe8, 0x37, 0x0f, 0x1f, 0x22, 0xdf, 0xe8,
0x5e, 0xa1, 0xb9, 0x39, 0xd6, 0x04, 0xb6, 0x06, 0x0e, 0xd1, 0xbf, 0x49, 0x22, 0x34, 0x57, 0x99,
0xbd, 0xcb, 0xa7, 0x1b, 0xd9, 0x0b, 0x96, 0xab, 0xa6, 0xf3, 0xb6, 0x6a, 0x3a, 0x1f, 0xab, 0xa6,
0xc3, 0xaa, 0xf6, 0x93, 0xce, 0x3f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xfc, 0x79, 0x52, 0x6a, 0x29,
0x02, 0x00, 0x00,
} }

View file

@ -13,4 +13,12 @@ message WorkerRecord {
string ID = 1; string ID = 1;
map<string, string> Labels = 2; map<string, string> Labels = 2;
repeated pb.Platform platforms = 3 [(gogoproto.nullable) = false]; repeated pb.Platform platforms = 3 [(gogoproto.nullable) = false];
repeated GCPolicy GCPolicy = 4;
}
message GCPolicy {
bool all = 1;
int64 keepDuration = 2;
int64 keepBytes = 3;
repeated string filters = 4;
} }

View file

@ -39,7 +39,7 @@ type Accessor interface {
type Controller interface { type Controller interface {
DiskUsage(ctx context.Context, info client.DiskUsageInfo) ([]*client.UsageInfo, error) DiskUsage(ctx context.Context, info client.DiskUsageInfo) ([]*client.UsageInfo, error)
Prune(ctx context.Context, ch chan client.UsageInfo, info client.PruneInfo) error Prune(ctx context.Context, ch chan client.UsageInfo, info ...client.PruneInfo) error
GC(ctx context.Context) error GC(ctx context.Context) error
} }
@ -304,10 +304,19 @@ func (cm *cacheManager) GetMutable(ctx context.Context, id string) (MutableRef,
return rec.mref(), nil return rec.mref(), nil
} }
func (cm *cacheManager) Prune(ctx context.Context, ch chan client.UsageInfo, opt client.PruneInfo) error { func (cm *cacheManager) Prune(ctx context.Context, ch chan client.UsageInfo, opts ...client.PruneInfo) error {
cm.muPrune.Lock() cm.muPrune.Lock()
defer cm.muPrune.Unlock() defer cm.muPrune.Unlock()
for _, opt := range opts {
if err := cm.pruneOnce(ctx, ch, opt); err != nil {
return err
}
}
return nil
}
func (cm *cacheManager) pruneOnce(ctx context.Context, ch chan client.UsageInfo, opt client.PruneInfo) error {
filter, err := filters.ParseAll(opt.Filter...) filter, err := filters.ParseAll(opt.Filter...)
if err != nil { if err != nil {
return err return err

View file

@ -67,7 +67,7 @@ func (s State) Value(k interface{}) interface{} {
return s.ctx.Value(k) return s.ctx.Value(k)
} }
func (s State) SetMarhalDefaults(co ...ConstraintsOpt) State { func (s State) SetMarshalDefaults(co ...ConstraintsOpt) State {
s.opts = co s.opts = co
return s return s
} }

View file

@ -2,8 +2,10 @@ package client
import ( import (
"context" "context"
"time"
controlapi "github.com/moby/buildkit/api/services/control" controlapi "github.com/moby/buildkit/api/services/control"
apitypes "github.com/moby/buildkit/api/types"
"github.com/moby/buildkit/solver/pb" "github.com/moby/buildkit/solver/pb"
specs "github.com/opencontainers/image-spec/specs-go/v1" specs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -13,6 +15,7 @@ type WorkerInfo struct {
ID string ID string
Labels map[string]string Labels map[string]string
Platforms []specs.Platform Platforms []specs.Platform
GCPolicy []PruneInfo
} }
func (c *Client) ListWorkers(ctx context.Context, opts ...ListWorkersOption) ([]*WorkerInfo, error) { func (c *Client) ListWorkers(ctx context.Context, opts ...ListWorkersOption) ([]*WorkerInfo, error) {
@ -34,6 +37,7 @@ func (c *Client) ListWorkers(ctx context.Context, opts ...ListWorkersOption) ([]
ID: w.ID, ID: w.ID,
Labels: w.Labels, Labels: w.Labels,
Platforms: pb.ToSpecPlatforms(w.Platforms), Platforms: pb.ToSpecPlatforms(w.Platforms),
GCPolicy: fromAPIGCPolicy(w.GCPolicy),
}) })
} }
@ -47,3 +51,16 @@ type ListWorkersOption interface {
type ListWorkersInfo struct { type ListWorkersInfo struct {
Filter []string Filter []string
} }
func fromAPIGCPolicy(in []*apitypes.GCPolicy) []PruneInfo {
out := make([]PruneInfo, 0, len(in))
for _, p := range in {
out = append(out, PruneInfo{
All: p.All,
Filter: p.Filters,
KeepDuration: time.Duration(p.KeepDuration),
KeepBytes: p.KeepBytes,
})
}
return out
}

View file

@ -2,6 +2,7 @@ package control
import ( import (
"context" "context"
"sync"
"time" "time"
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
@ -17,6 +18,7 @@ import (
"github.com/moby/buildkit/solver" "github.com/moby/buildkit/solver"
"github.com/moby/buildkit/solver/llbsolver" "github.com/moby/buildkit/solver/llbsolver"
"github.com/moby/buildkit/solver/pb" "github.com/moby/buildkit/solver/pb"
"github.com/moby/buildkit/util/throttle"
"github.com/moby/buildkit/worker" "github.com/moby/buildkit/worker"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
@ -40,6 +42,8 @@ type Controller struct { // TODO: ControlService
solver *llbsolver.Solver solver *llbsolver.Solver
cache solver.CacheManager cache solver.CacheManager
gatewayForwarder *controlgateway.GatewayForwarder gatewayForwarder *controlgateway.GatewayForwarder
throttledGC func()
gcmu sync.Mutex
} }
func NewController(opt Opt) (*Controller, error) { func NewController(opt Opt) (*Controller, error) {
@ -58,6 +62,12 @@ func NewController(opt Opt) (*Controller, error) {
cache: cache, cache: cache,
gatewayForwarder: gatewayForwarder, gatewayForwarder: gatewayForwarder,
} }
c.throttledGC = throttle.ThrottleAfter(time.Minute, c.gc)
defer func() {
time.AfterFunc(time.Second, c.throttledGC)
}()
return c, nil return c, nil
} }
@ -172,6 +182,10 @@ func (c *Controller) Prune(req *controlapi.PruneRequest, stream controlapi.Contr
func (c *Controller) Solve(ctx context.Context, req *controlapi.SolveRequest) (*controlapi.SolveResponse, error) { func (c *Controller) Solve(ctx context.Context, req *controlapi.SolveRequest) (*controlapi.SolveResponse, error) {
ctx = session.NewContext(ctx, req.Session) ctx = session.NewContext(ctx, req.Session)
defer func() {
time.AfterFunc(time.Second, c.throttledGC)
}()
var expi exporter.ExporterInstance var expi exporter.ExporterInstance
// TODO: multiworker // TODO: multiworker
// This is actually tricky, as the exporter should come from the worker that has the returned reference. We may need to delay this so that the solver loads this. // This is actually tricky, as the exporter should come from the worker that has the returned reference. We may need to delay this so that the solver loads this.
@ -313,11 +327,55 @@ func (c *Controller) ListWorkers(ctx context.Context, r *controlapi.ListWorkersR
ID: w.ID(), ID: w.ID(),
Labels: w.Labels(), Labels: w.Labels(),
Platforms: pb.PlatformsFromSpec(w.Platforms()), Platforms: pb.PlatformsFromSpec(w.Platforms()),
GCPolicy: toPBGCPolicy(w.GCPolicy()),
}) })
} }
return resp, nil return resp, nil
} }
func (c *Controller) gc() {
c.gcmu.Lock()
defer c.gcmu.Unlock()
workers, err := c.opt.WorkerController.List()
if err != nil {
return
}
eg, ctx := errgroup.WithContext(context.TODO())
var size int64
ch := make(chan client.UsageInfo)
done := make(chan struct{})
go func() {
for ui := range ch {
size += ui.Size
}
close(done)
}()
for _, w := range workers {
func(w worker.Worker) {
eg.Go(func() error {
if policy := w.GCPolicy(); len(policy) > 0 {
return w.Prune(ctx, ch, policy...)
}
return nil
})
}(w)
}
err = eg.Wait()
close(ch)
if err != nil {
logrus.Errorf("gc error: %+v", err)
}
<-done
if size > 0 {
logrus.Debugf("gc cleaned up %d bytes", size)
}
}
func parseCacheExporterOpt(opt map[string]string) solver.CacheExportMode { func parseCacheExporterOpt(opt map[string]string) solver.CacheExportMode {
for k, v := range opt { for k, v := range opt {
switch k { switch k {
@ -336,3 +394,16 @@ func parseCacheExporterOpt(opt map[string]string) solver.CacheExportMode {
} }
return solver.CacheExportModeMin return solver.CacheExportModeMin
} }
func toPBGCPolicy(in []client.PruneInfo) []*apitypes.GCPolicy {
policy := make([]*apitypes.GCPolicy, 0, len(in))
for _, p := range in {
policy = append(policy, &apitypes.GCPolicy{
All: p.All,
KeepBytes: p.KeepBytes,
KeepDuration: int64(p.KeepDuration),
Filters: p.Filter,
})
}
return policy
}

View file

@ -36,6 +36,8 @@ type Opt struct {
CommandCandidates []string CommandCandidates []string
// without root privileges (has nothing to do with Opt.Root directory) // without root privileges (has nothing to do with Opt.Root directory)
Rootless bool Rootless bool
// DefaultCgroupParent is the cgroup-parent name for executor
DefaultCgroupParent string
} }
var defaultCommandCandidates = []string{"buildkit-runc", "runc"} var defaultCommandCandidates = []string{"buildkit-runc", "runc"}
@ -44,6 +46,7 @@ type runcExecutor struct {
runc *runc.Runc runc *runc.Runc
root string root string
cmd string cmd string
cgroupParent string
rootless bool rootless bool
networkProviders map[pb.NetMode]network.Provider networkProviders map[pb.NetMode]network.Provider
} }
@ -94,6 +97,7 @@ func New(opt Opt, networkProviders map[pb.NetMode]network.Provider) (executor.Ex
w := &runcExecutor{ w := &runcExecutor{
runc: runtime, runc: runtime,
root: root, root: root,
cgroupParent: opt.DefaultCgroupParent,
rootless: opt.Rootless, rootless: opt.Rootless,
networkProviders: networkProviders, networkProviders: networkProviders,
} }
@ -173,6 +177,17 @@ func (w *runcExecutor) Exec(ctx context.Context, meta executor.Meta, root cache.
if meta.ReadonlyRootFS { if meta.ReadonlyRootFS {
opts = append(opts, containerdoci.WithRootFSReadonly()) opts = append(opts, containerdoci.WithRootFSReadonly())
} }
if w.cgroupParent != "" {
var cgroupsPath string
lastSeparator := w.cgroupParent[len(w.cgroupParent)-1:]
if strings.Contains(w.cgroupParent, ".slice") && lastSeparator == ":" {
cgroupsPath = w.cgroupParent + id
} else {
cgroupsPath = filepath.Join("/", w.cgroupParent, "buildkit", id)
}
opts = append(opts, containerdoci.WithCgroup(cgroupsPath))
}
spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile, namespace, opts...) spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile, namespace, opts...)
if err != nil { if err != nil {
return err return err

View file

@ -347,7 +347,7 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State,
} }
buildContext.Output = bc.Output() buildContext.Output = bc.Output()
st := target.state.SetMarhalDefaults(llb.Platform(platformOpt.targetPlatform)) st := target.state.SetMarshalDefaults(llb.Platform(platformOpt.targetPlatform))
if !platformOpt.implicitTarget { if !platformOpt.implicitTarget {
target.image.OS = platformOpt.targetPlatform.OS target.image.OS = platformOpt.targetPlatform.OS

View file

@ -67,7 +67,11 @@ func (c *bridgeClient) Solve(ctx context.Context, req client.SolveRequest) (*cli
func (c *bridgeClient) BuildOpts() client.BuildOpts { func (c *bridgeClient) BuildOpts() client.BuildOpts {
workers := make([]client.WorkerInfo, 0, len(c.workerInfos)) workers := make([]client.WorkerInfo, 0, len(c.workerInfos))
for _, w := range c.workerInfos { for _, w := range c.workerInfos {
workers = append(workers, client.WorkerInfo(w)) workers = append(workers, client.WorkerInfo{
ID: w.ID,
Labels: w.Labels,
Platforms: w.Platforms,
})
} }
return client.BuildOpts{ return client.BuildOpts{

View file

@ -0,0 +1,58 @@
package throttle
import (
"sync"
"time"
)
// Throttle wraps a function so that internal function does not get called
// more frequently than the specified duration.
func Throttle(d time.Duration, f func()) func() {
return throttle(d, f, true)
}
// ThrottleAfter wraps a function so that internal function does not get called
// more frequently than the specified duration. The delay is added after function
// has been called.
func ThrottleAfter(d time.Duration, f func()) func() {
return throttle(d, f, false)
}
func throttle(d time.Duration, f func(), wait bool) func() {
var next, running bool
var mu sync.Mutex
return func() {
mu.Lock()
defer mu.Unlock()
next = true
if !running {
running = true
go func() {
for {
mu.Lock()
if next == false {
running = false
mu.Unlock()
return
}
if !wait {
next = false
}
mu.Unlock()
if wait {
time.Sleep(d)
mu.Lock()
next = false
mu.Unlock()
f()
} else {
f()
time.Sleep(d)
}
}
}()
}
}
}

View file

@ -20,6 +20,7 @@ type Worker interface {
ID() string ID() string
Labels() map[string]string Labels() map[string]string
Platforms() []specs.Platform Platforms() []specs.Platform
GCPolicy() []client.PruneInfo
LoadRef(id string) (cache.ImmutableRef, error) LoadRef(id string) (cache.ImmutableRef, error)
// ResolveOp resolves Vertex.Sys() to Op implementation. // ResolveOp resolves Vertex.Sys() to Op implementation.
ResolveOp(v solver.Vertex, s frontend.FrontendLLBBridge) (solver.Op, error) ResolveOp(v solver.Vertex, s frontend.FrontendLLBBridge) (solver.Op, error)
@ -28,7 +29,7 @@ type Worker interface {
Exec(ctx context.Context, meta executor.Meta, rootFS cache.ImmutableRef, stdin io.ReadCloser, stdout, stderr io.WriteCloser) error Exec(ctx context.Context, meta executor.Meta, rootFS cache.ImmutableRef, stdin io.ReadCloser, stdout, stderr io.WriteCloser) error
DiskUsage(ctx context.Context, opt client.DiskUsageInfo) ([]*client.UsageInfo, error) DiskUsage(ctx context.Context, opt client.DiskUsageInfo) ([]*client.UsageInfo, error)
Exporter(name string) (exporter.Exporter, error) Exporter(name string) (exporter.Exporter, error)
Prune(ctx context.Context, ch chan client.UsageInfo, opt client.PruneInfo) error Prune(ctx context.Context, ch chan client.UsageInfo, opt ...client.PruneInfo) error
GetRemote(ctx context.Context, ref cache.ImmutableRef, createIfNeeded bool) (*solver.Remote, error) GetRemote(ctx context.Context, ref cache.ImmutableRef, createIfNeeded bool) (*solver.Remote, error)
FromRemote(ctx context.Context, remote *solver.Remote) (cache.ImmutableRef, error) FromRemote(ctx context.Context, remote *solver.Remote) (cache.ImmutableRef, error)
} }