From 284ac24eb61e3ff64c9bbaf638e580dfac0f862d Mon Sep 17 00:00:00 2001 From: Cyrill Troxler Date: Sun, 19 Jan 2025 15:37:14 +0100 Subject: [PATCH 1/2] feat: pass logger to all manager components --- activator/activator_test.go | 3 ++- activator/bpf.go | 7 ++++--- cmd/manager/main.go | 16 +++++++++------- manager/pod_labeller.go | 4 ++-- manager/pod_labeller_test.go | 2 +- manager/pod_scaler.go | 4 ++-- manager/redirector_attacher.go | 30 ++++++++++++++++-------------- manager/status.go | 24 ++++++++++++------------ 8 files changed, 48 insertions(+), 42 deletions(-) diff --git a/activator/activator_test.go b/activator/activator_test.go index 32d3850..c4e7c9b 100644 --- a/activator/activator_test.go +++ b/activator/activator_test.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "io" + "log/slog" "net" "net/http" "net/http/httptest" @@ -31,7 +32,7 @@ func TestActivator(t *testing.T) { s, err := NewServer(ctx, nn) require.NoError(t, err) - bpf, err := InitBPF(os.Getpid()) + bpf, err := InitBPF(os.Getpid(), slog.Default()) require.NoError(t, err) require.NoError(t, bpf.AttachRedirector("lo")) diff --git a/activator/bpf.go b/activator/bpf.go index af823e1..599b0ca 100644 --- a/activator/bpf.go +++ b/activator/bpf.go @@ -25,9 +25,10 @@ type BPF struct { objs *bpfObjects qdiscs []*netlink.GenericQdisc filters []*netlink.BpfFilter + log *slog.Logger } -func InitBPF(pid int) (*BPF, error) { +func InitBPF(pid int, log *slog.Logger) (*BPF, error) { // Allow the current process to lock memory for eBPF resources. if err := rlimit.RemoveMemlock(); err != nil { return nil, err @@ -49,7 +50,7 @@ func InitBPF(pid int) (*BPF, error) { return nil, fmt.Errorf("loading objects: %w", err) } - return &BPF{pid: pid, objs: &objs}, nil + return &BPF{pid: pid, log: log, objs: &objs}, nil } func (bpf *BPF) Cleanup() error { @@ -68,7 +69,7 @@ func (bpf *BPF) Cleanup() error { } } - slog.Info("deleting", "path", PinPath(bpf.pid)) + bpf.log.Info("deleting", "path", PinPath(bpf.pid)) return os.RemoveAll(PinPath(bpf.pid)) } diff --git a/cmd/manager/main.go b/cmd/manager/main.go index c64a10b..a9f8161 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -25,16 +25,18 @@ var ( func main() { flag.Parse() + opts := &slog.HandlerOptions{} if *debug { - slog.SetLogLoggerLevel(slog.LevelDebug) + opts.Level = slog.LevelDebug } - slog.Info("starting manager", "metrics-addr", *metricsAddr) + log := slog.New(slog.NewJSONHandler(os.Stdout, opts)) + log.Info("starting manager", "metrics-addr", *metricsAddr) ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer stop() - if err := manager.AttachRedirectors(ctx); err != nil { - slog.Error("attaching redirectors", "err", err) + if err := manager.AttachRedirectors(ctx, log); err != nil { + log.Error("attaching redirectors", "err", err) os.Exit(1) } @@ -46,13 +48,13 @@ func main() { podHandlers := []manager.PodHandler{} if *statusLabels { - podHandlers = append(podHandlers, manager.NewPodLabeller()) + podHandlers = append(podHandlers, manager.NewPodLabeller(log)) } if *inPlaceScaling { - podHandlers = append(podHandlers, manager.NewPodScaler()) + podHandlers = append(podHandlers, manager.NewPodScaler(log)) } - if err := manager.StartSubscribers(ctx, podHandlers...); err != nil { + if err := manager.StartSubscribers(ctx, log, podHandlers...); err != nil { slog.Error("starting subscribers", "err", err) os.Exit(1) } diff --git a/manager/pod_labeller.go b/manager/pod_labeller.go index 72d6e6f..ab706ca 100644 --- a/manager/pod_labeller.go +++ b/manager/pod_labeller.go @@ -17,8 +17,8 @@ type PodLabeller struct { log *slog.Logger } -func NewPodLabeller() *PodLabeller { - log := slog.With("component", "podupdater") +func NewPodLabeller(log *slog.Logger) *PodLabeller { + log = log.With("component", "podupdater") log.Info("init") return &PodLabeller{log: log} } diff --git a/manager/pod_labeller_test.go b/manager/pod_labeller_test.go index 8a400b2..52aa35f 100644 --- a/manager/pod_labeller_test.go +++ b/manager/pod_labeller_test.go @@ -55,7 +55,7 @@ func TestPodLabeller(t *testing.T) { pod := newPod(nil) pod.SetLabels(tc.beforeEvent) - if err := NewPodLabeller().Handle( + if err := NewPodLabeller(slog.Default()).Handle( context.Background(), &v1.ContainerStatus{ Name: pod.Spec.Containers[0].Name, diff --git a/manager/pod_scaler.go b/manager/pod_scaler.go index 830fc4f..14843dc 100644 --- a/manager/pod_scaler.go +++ b/manager/pod_scaler.go @@ -27,8 +27,8 @@ type PodScaler struct { log *slog.Logger } -func NewPodScaler() *PodScaler { - log := slog.With("component", "podscaler") +func NewPodScaler(log *slog.Logger) *PodScaler { + log = log.With("component", "podscaler") log.Info("init") return &PodScaler{log: log} } diff --git a/manager/redirector_attacher.go b/manager/redirector_attacher.go index 57e1439..e8d4e85 100644 --- a/manager/redirector_attacher.go +++ b/manager/redirector_attacher.go @@ -19,6 +19,7 @@ import ( type Redirector struct { sync.Mutex activators map[int]*activator.BPF + log *slog.Logger } // AttachRedirectors scans the zeropod maps path in the bpf file system for @@ -28,30 +29,31 @@ type Redirector struct { // can be found it attaches the redirector BPF programs to the network // interfaces of the sandbox. The directories are expected to be created by // the zeropod shim on startup. -func AttachRedirectors(ctx context.Context) error { +func AttachRedirectors(ctx context.Context, log *slog.Logger) error { r := &Redirector{ activators: make(map[int]*activator.BPF), + log: log, } if _, err := os.Stat(activator.MapsPath()); os.IsNotExist(err) { - slog.Info("maps path not found, creating", "path", activator.MapsPath()) + r.log.Info("maps path not found, creating", "path", activator.MapsPath()) if err := os.Mkdir(activator.MapsPath(), os.ModePerm); err != nil { return err } } - pids, err := getSandboxPids() + pids, err := r.getSandboxPids() if err != nil { return err } if len(pids) == 0 { - slog.Info("no sandbox pids found") + r.log.Info("no sandbox pids found") } for _, pid := range pids { if _, err := os.Stat(netNSPath(pid)); os.IsNotExist(err) { - slog.Info("net ns not found, removing leftover pid", "path", netNSPath(pid)) + r.log.Info("net ns not found, removing leftover pid", "path", netNSPath(pid)) os.RemoveAll(activator.PinPath(pid)) continue } @@ -87,27 +89,27 @@ func (r *Redirector) watchForSandboxPids(ctx context.Context) error { pid, err := strconv.Atoi(filepath.Base(event.Name)) if err != nil { - slog.Warn("unable to parse pid from added name", "name", filepath.Base(event.Name)) + r.log.Warn("unable to parse pid from added name", "name", filepath.Base(event.Name)) break } switch event.Op { case fsnotify.Create: if err := r.attachRedirector(pid); err != nil { - slog.Error("unable to attach redirector", "pid", pid) + r.log.Error("unable to attach redirector", "pid", pid) } case fsnotify.Remove: r.Lock() if act, ok := r.activators[pid]; ok { - slog.Info("cleaning up activator", "pid", pid) + r.log.Info("cleaning up activator", "pid", pid) if err := act.Cleanup(); err != nil { - slog.Error("error cleaning up redirector", "err", err) + r.log.Error("error cleaning up redirector", "err", err) } } r.Unlock() } case err := <-watcher.Errors: - slog.Error("watch error", "err", err) + r.log.Error("watch error", "err", err) case <-ctx.Done(): return nil } @@ -115,7 +117,7 @@ func (r *Redirector) watchForSandboxPids(ctx context.Context) error { } func (r *Redirector) attachRedirector(pid int) error { - bpf, err := activator.InitBPF(pid) + bpf, err := activator.InitBPF(pid, r.log) if err != nil { return fmt.Errorf("unable to initialize BPF: %w", err) } @@ -132,7 +134,7 @@ func (r *Redirector) attachRedirector(pid int) error { // TODO: is this really always eth0? // as for loopback, this is required for port-forwarding to work ifaces := []string{"eth0", "lo"} - slog.Info("attaching redirector for sandbox", "pid", pid, "links", ifaces) + r.log.Info("attaching redirector for sandbox", "pid", pid, "links", ifaces) return bpf.AttachRedirector(ifaces...) }); err != nil { return err @@ -145,7 +147,7 @@ func netNSPath(pid int) string { return fmt.Sprintf("/hostproc/%d/ns/net", pid) } -func getSandboxPids() ([]int, error) { +func (r *Redirector) getSandboxPids() ([]int, error) { f, err := os.Open(activator.MapsPath()) if err != nil { if errors.Is(err, os.ErrNotExist) { @@ -167,7 +169,7 @@ func getSandboxPids() ([]int, error) { intPid, err := strconv.Atoi(dir) if err != nil { - slog.Warn("unable to parse pid from dir name", "name", dir) + r.log.Warn("unable to parse pid from dir name", "name", dir) continue } intPids = append(intPids, intPid) diff --git a/manager/status.go b/manager/status.go index ea6514e..f561a59 100644 --- a/manager/status.go +++ b/manager/status.go @@ -49,7 +49,7 @@ type subscriber struct { podHandlers []PodHandler } -func StartSubscribers(ctx context.Context, podHandlers ...PodHandler) error { +func StartSubscribers(ctx context.Context, log *slog.Logger, podHandlers ...PodHandler) error { cfg, err := config.GetConfig() if err != nil { return fmt.Errorf("getting client config: %w", err) @@ -73,19 +73,19 @@ func StartSubscribers(ctx context.Context, podHandlers ...PodHandler) error { for _, sock := range socks { sock := sock go func() { - if err := subscribe(ctx, filepath.Join(task.ShimSocketPath, sock.Name()), kube, podHandlers); err != nil { - slog.Error("error subscribing", "sock", sock.Name(), "err", err) + if err := subscribe(ctx, log, filepath.Join(task.ShimSocketPath, sock.Name()), kube, podHandlers); err != nil { + log.Error("error subscribing", "sock", sock.Name(), "err", err) } }() } - go watchForShims(ctx, kube, podHandlers) + go watchForShims(ctx, log, kube, podHandlers) return nil } -func subscribe(ctx context.Context, sock string, kube client.Client, handlers []PodHandler) error { - slog.With("sock", sock).Info("subscribing to status events") +func subscribe(ctx context.Context, log *slog.Logger, sock string, kube client.Client, handlers []PodHandler) error { + log.With("sock", sock).Info("subscribing to status events") shimClient, err := newShimClient(ctx, sock) if err != nil { return err @@ -97,7 +97,7 @@ func subscribe(ctx context.Context, sock string, kube client.Client, handlers [] } s := subscriber{ - log: slog.With("sock", sock), + log: log.With("sock", sock), kube: kube, subscribeClient: subscribeClient, podHandlers: handlers, @@ -142,7 +142,7 @@ func (s *subscriber) receive(ctx context.Context) error { } break } - clog := slog.With("container", status.Name, "pod", status.PodName, + clog := s.log.With("container", status.Name, "pod", status.PodName, "namespace", status.PodNamespace, "phase", status.Phase) if err := s.onStatus(ctx, status); err != nil { clog.Error("handling status update", "err", err) @@ -185,7 +185,7 @@ func (s *subscriber) handlePod(ctx context.Context, status *v1.ContainerStatus) return nil } -func watchForShims(ctx context.Context, kube client.Client, podHandlers []PodHandler) error { +func watchForShims(ctx context.Context, log *slog.Logger, kube client.Client, podHandlers []PodHandler) error { watcher, err := fsnotify.NewWatcher() if err != nil { return err @@ -202,13 +202,13 @@ func watchForShims(ctx context.Context, kube client.Client, podHandlers []PodHan switch event.Op { case fsnotify.Create: go func() { - if err := subscribe(ctx, event.Name, kube, podHandlers); err != nil { - slog.Error("error subscribing", "sock", event.Name, "err", err) + if err := subscribe(ctx, log, event.Name, kube, podHandlers); err != nil { + log.Error("error subscribing", "sock", event.Name, "err", err) } }() } case err := <-watcher.Errors: - slog.Error("watch error", "err", err) + log.Error("watch error", "err", err) case <-ctx.Done(): return nil } From e3e069de0e4e8df17e206e9a42fe22a4f4134add Mon Sep 17 00:00:00 2001 From: Cyrill Troxler Date: Sun, 19 Jan 2025 19:47:30 +0100 Subject: [PATCH 2/2] feat: add support for resizing on Kubernetes 1.32 The resizing of running pods has changed slighly with 1.32. There's a new feature gate that needs to be enabled to get the containerStatuses field. Also instead of just updating the pod spec, the resource update now needs to be done using the pods/resize subresource. To be compatible with 1.27-1.31, it will fall back to using a normal update call if the resize fails with a not found. --- .github/workflows/ci.yml | 2 +- api/shim/v1/shim.pb.go | 159 +++++++++-------------------------- config/pod-updater/rbac.yaml | 1 + e2e/kind.yaml | 2 + e2e/setup_test.go | 5 +- go.mod | 25 +++--- go.sum | 74 ++++++++-------- manager/pod_labeller.go | 2 +- manager/pod_scaler.go | 10 +-- manager/status.go | 40 +++++++-- 10 files changed, 133 insertions(+), 187 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c40066a..2de50df 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,7 +48,7 @@ jobs: - name: Install protoc-gen-go run: | - go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.31 + go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.36.3 go install github.com/containerd/ttrpc/cmd/protoc-gen-go-ttrpc@v1.2.4 - uses: awalsh128/cache-apt-pkgs-action@v1 diff --git a/api/shim/v1/shim.pb.go b/api/shim/v1/shim.pb.go index c94d8aa..9b53d93 100644 --- a/api/shim/v1/shim.pb.go +++ b/api/shim/v1/shim.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 +// protoc-gen-go v1.36.3 // protoc v3.21.12 // source: shim.proto @@ -69,20 +69,17 @@ func (ContainerPhase) EnumDescriptor() ([]byte, []int) { } type MetricsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Empty *emptypb.Empty `protobuf:"bytes,1,opt,name=empty,proto3" json:"empty,omitempty"` unknownFields protoimpl.UnknownFields - - Empty *emptypb.Empty `protobuf:"bytes,1,opt,name=empty,proto3" json:"empty,omitempty"` + sizeCache protoimpl.SizeCache } func (x *MetricsRequest) Reset() { *x = MetricsRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_shim_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_shim_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *MetricsRequest) String() string { @@ -93,7 +90,7 @@ func (*MetricsRequest) ProtoMessage() {} func (x *MetricsRequest) ProtoReflect() protoreflect.Message { mi := &file_shim_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -116,20 +113,17 @@ func (x *MetricsRequest) GetEmpty() *emptypb.Empty { } type SubscribeStatusRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Empty *emptypb.Empty `protobuf:"bytes,1,opt,name=empty,proto3" json:"empty,omitempty"` unknownFields protoimpl.UnknownFields - - Empty *emptypb.Empty `protobuf:"bytes,1,opt,name=empty,proto3" json:"empty,omitempty"` + sizeCache protoimpl.SizeCache } func (x *SubscribeStatusRequest) Reset() { *x = SubscribeStatusRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_shim_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_shim_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *SubscribeStatusRequest) String() string { @@ -140,7 +134,7 @@ func (*SubscribeStatusRequest) ProtoMessage() {} func (x *SubscribeStatusRequest) ProtoReflect() protoreflect.Message { mi := &file_shim_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -163,20 +157,17 @@ func (x *SubscribeStatusRequest) GetEmpty() *emptypb.Empty { } type MetricsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Metrics []*_go.MetricFamily `protobuf:"bytes,1,rep,name=metrics,proto3" json:"metrics,omitempty"` unknownFields protoimpl.UnknownFields - - Metrics []*_go.MetricFamily `protobuf:"bytes,1,rep,name=metrics,proto3" json:"metrics,omitempty"` + sizeCache protoimpl.SizeCache } func (x *MetricsResponse) Reset() { *x = MetricsResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_shim_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_shim_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *MetricsResponse) String() string { @@ -187,7 +178,7 @@ func (*MetricsResponse) ProtoMessage() {} func (x *MetricsResponse) ProtoReflect() protoreflect.Message { mi := &file_shim_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -210,20 +201,17 @@ func (x *MetricsResponse) GetMetrics() []*_go.MetricFamily { } type ContainerRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ContainerRequest) Reset() { *x = ContainerRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_shim_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_shim_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ContainerRequest) String() string { @@ -234,7 +222,7 @@ func (*ContainerRequest) ProtoMessage() {} func (x *ContainerRequest) ProtoReflect() protoreflect.Message { mi := &file_shim_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -257,24 +245,21 @@ func (x *ContainerRequest) GetId() string { } type ContainerStatus struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + PodName string `protobuf:"bytes,3,opt,name=pod_name,json=podName,proto3" json:"pod_name,omitempty"` + PodNamespace string `protobuf:"bytes,4,opt,name=pod_namespace,json=podNamespace,proto3" json:"pod_namespace,omitempty"` + Phase ContainerPhase `protobuf:"varint,5,opt,name=phase,proto3,enum=zeropod.shim.v1.ContainerPhase" json:"phase,omitempty"` unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - PodName string `protobuf:"bytes,3,opt,name=pod_name,json=podName,proto3" json:"pod_name,omitempty"` - PodNamespace string `protobuf:"bytes,4,opt,name=pod_namespace,json=podNamespace,proto3" json:"pod_namespace,omitempty"` - Phase ContainerPhase `protobuf:"varint,5,opt,name=phase,proto3,enum=zeropod.shim.v1.ContainerPhase" json:"phase,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ContainerStatus) Reset() { *x = ContainerStatus{} - if protoimpl.UnsafeEnabled { - mi := &file_shim_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_shim_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ContainerStatus) String() string { @@ -285,7 +270,7 @@ func (*ContainerStatus) ProtoMessage() {} func (x *ContainerStatus) ProtoReflect() protoreflect.Message { mi := &file_shim_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -410,7 +395,7 @@ func file_shim_proto_rawDescGZIP() []byte { var file_shim_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_shim_proto_msgTypes = make([]protoimpl.MessageInfo, 5) -var file_shim_proto_goTypes = []interface{}{ +var file_shim_proto_goTypes = []any{ (ContainerPhase)(0), // 0: zeropod.shim.v1.ContainerPhase (*MetricsRequest)(nil), // 1: zeropod.shim.v1.MetricsRequest (*SubscribeStatusRequest)(nil), // 2: zeropod.shim.v1.SubscribeStatusRequest @@ -443,68 +428,6 @@ func file_shim_proto_init() { if File_shim_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_shim_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MetricsRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_shim_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SubscribeStatusRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_shim_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MetricsResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_shim_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ContainerRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_shim_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ContainerStatus); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/config/pod-updater/rbac.yaml b/config/pod-updater/rbac.yaml index 0bc9b66..d6452ee 100644 --- a/config/pod-updater/rbac.yaml +++ b/config/pod-updater/rbac.yaml @@ -8,6 +8,7 @@ rules: - "" resources: - pods + - pods/resize verbs: - get - update diff --git a/e2e/kind.yaml b/e2e/kind.yaml index 8209778..2f4dae9 100644 --- a/e2e/kind.yaml +++ b/e2e/kind.yaml @@ -2,8 +2,10 @@ kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 featureGates: InPlacePodVerticalScaling: true + InPlacePodVerticalScalingAllocatedStatus: true nodes: - role: control-plane + image: kindest/node:v1.32.0@sha256:c48c62eac5da28cdadcf560d1d8616cfa6783b58f0d94cf63ad1bf49600cb027 extraMounts: - hostPath: /proc containerPath: /host/proc diff --git a/e2e/setup_test.go b/e2e/setup_test.go index ef04f3d..b4bc388 100644 --- a/e2e/setup_test.go +++ b/e2e/setup_test.go @@ -126,7 +126,8 @@ func startKind(t testing.TB, name string, port int) (c *rest.Config, err error) cluster.CreateWithV1Alpha4Config(&v1alpha4.Cluster{ Name: name, FeatureGates: map[string]bool{ - "InPlacePodVerticalScaling": true, + "InPlacePodVerticalScaling": true, + "InPlacePodVerticalScalingAllocatedStatus": true, }, Nodes: []v1alpha4.Node{{ Labels: map[string]string{zeropod.NodeLabel: "true"}, @@ -150,7 +151,7 @@ func startKind(t testing.TB, name string, port int) (c *rest.Config, err error) }, }}, }), - cluster.CreateWithNodeImage("kindest/node:v1.29.2"), + cluster.CreateWithNodeImage("kindest/node:v1.32.0@sha256:c48c62eac5da28cdadcf560d1d8616cfa6783b58f0d94cf63ad1bf49600cb027"), cluster.CreateWithRetain(false), cluster.CreateWithKubeconfigPath(f.Name()), cluster.CreateWithWaitForReady(time.Minute*2), diff --git a/go.mod b/go.mod index 3fed88b..fd43e13 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/containerd/errdefs v0.1.0 github.com/containerd/go-runc v1.0.0 github.com/containerd/log v0.1.0 - github.com/containerd/ttrpc v1.2.5 + github.com/containerd/ttrpc v1.2.7 github.com/containerd/typeurl/v2 v2.2.0 github.com/containernetworking/plugins v1.5.1 github.com/coreos/go-systemd/v22 v22.5.0 @@ -31,12 +31,12 @@ require ( github.com/vishvananda/netlink v1.3.0 golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 golang.org/x/sys v0.28.0 - google.golang.org/protobuf v1.34.2 - k8s.io/api v0.31.1 - k8s.io/apimachinery v0.31.1 - k8s.io/client-go v0.31.1 - k8s.io/utils v0.0.0-20240921022957-49e7df575cb6 - sigs.k8s.io/controller-runtime v0.19.0 + google.golang.org/protobuf v1.36.3 + k8s.io/api v0.32.0 + k8s.io/apimachinery v0.32.0 + k8s.io/client-go v0.32.0 + k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 + sigs.k8s.io/controller-runtime v0.20.0 sigs.k8s.io/kind v0.19.0 sigs.k8s.io/kustomize/api v0.16.0 sigs.k8s.io/kustomize/kyaml v0.16.0 @@ -91,7 +91,7 @@ require ( github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-isatty v0.0.17 // indirect github.com/moby/locker v1.0.1 // indirect - github.com/moby/spdystream v0.4.0 // indirect + github.com/moby/spdystream v0.5.0 // indirect github.com/moby/sys/mountinfo v0.7.2 // indirect github.com/moby/sys/sequential v0.6.0 // indirect github.com/moby/sys/signal v0.7.1 // indirect @@ -126,20 +126,19 @@ require ( golang.org/x/sync v0.10.0 // indirect golang.org/x/term v0.27.0 // indirect golang.org/x/text v0.21.0 // indirect - golang.org/x/time v0.6.0 // indirect + golang.org/x/time v0.7.0 // indirect google.golang.org/genproto v0.0.0-20240924160255-9d4c2d233b61 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240924160255-9d4c2d233b61 // indirect google.golang.org/grpc v1.67.0 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/evanphx/json-patch.v5 v5.6.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/cri-api v0.31.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kube-openapi v0.0.0-20240903163716-9e1beecbcb38 // indirect - sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect + k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect + sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect sigs.k8s.io/yaml v1.4.0 // indirect tags.cncf.io/container-device-interface v0.8.0 // indirect tags.cncf.io/container-device-interface/specs-go v0.8.0 // indirect diff --git a/go.sum b/go.sum index 7061091..e829091 100644 --- a/go.sum +++ b/go.sum @@ -58,8 +58,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/containerd/ttrpc v1.2.5 h1:IFckT1EFQoFBMG4c3sMdT8EP3/aKfumK1msY+Ze4oLU= -github.com/containerd/ttrpc v1.2.5/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= +github.com/containerd/ttrpc v1.2.7 h1:qIrroQvuOL9HQ1X6KHe2ohc7p+HP/0VE6XPU7elJRqQ= +github.com/containerd/ttrpc v1.2.7/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= github.com/containerd/typeurl/v2 v2.2.0 h1:6NBDbQzr7I5LHgp34xAXYF5DOTQDn05X58lsPEmzLso= github.com/containerd/typeurl/v2 v2.2.0/go.mod h1:8XOOxnyatxSWuG8OfsZXVnAF4iZfedjS/8UHSPJnX4g= github.com/containernetworking/cni v1.1.2 h1:wtRGZVv7olUHMOqouPpn3cXJWpJgM6+EUl31EQbXALQ= @@ -157,8 +157,8 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k= -github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= +github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo= +github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 h1:SJ+NtwL6QaZ21U+IrK7d0gGgpjGGvd2kz+FzTHVzdqI= github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2/go.mod h1:Tv1PlzqC9t8wNnpPdctvtSUOPUUg4SHeE6vR1Ir2hmg= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= @@ -220,8 +220,8 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34fGzaAZGFW22KVZDfyrYW+QABMrWnJBnSs= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= -github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8= -github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= +github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU= +github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= @@ -250,10 +250,10 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= -github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= -github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= -github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= +github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM= +github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= +github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4= +github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= @@ -363,8 +363,8 @@ go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -428,8 +428,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= -golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= +golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -438,8 +438,8 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE= -golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= +golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= +golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -469,8 +469,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= +google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -483,42 +483,40 @@ gopkg.in/evanphx/json-patch.v5 v5.6.0/go.mod h1:/kvTRh1TVm5wuM6OkHxqXtE/1nUZZpih gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -k8s.io/api v0.31.1 h1:Xe1hX/fPW3PXYYv8BlozYqw63ytA92snr96zMW9gWTU= -k8s.io/api v0.31.1/go.mod h1:sbN1g6eY6XVLeqNsZGLnI5FwVseTrZX7Fv3O26rhAaI= -k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk= -k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk= -k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U= -k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= -k8s.io/client-go v0.31.1 h1:f0ugtWSbWpxHR7sjVpQwuvw9a3ZKLXX0u0itkFXufb0= -k8s.io/client-go v0.31.1/go.mod h1:sKI8871MJN2OyeqRlmA4W4KM9KBdBUpDLu/43eGemCg= +k8s.io/api v0.32.0 h1:OL9JpbvAU5ny9ga2fb24X8H6xQlVp+aJMFlgtQjR9CE= +k8s.io/api v0.32.0/go.mod h1:4LEwHZEf6Q/cG96F3dqR965sYOfmPM7rq81BLgsE0p0= +k8s.io/apiextensions-apiserver v0.32.0 h1:S0Xlqt51qzzqjKPxfgX1xh4HBZE+p8KKBq+k2SWNOE0= +k8s.io/apiextensions-apiserver v0.32.0/go.mod h1:86hblMvN5yxMvZrZFX2OhIHAuFIMJIZ19bTvzkP+Fmw= +k8s.io/apimachinery v0.32.0 h1:cFSE7N3rmEEtv4ei5X6DaJPHHX0C+upp+v5lVPiEwpg= +k8s.io/apimachinery v0.32.0/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= +k8s.io/client-go v0.32.0 h1:DimtMcnN/JIKZcrSrstiwvvZvLjG0aSxy8PxN8IChp8= +k8s.io/client-go v0.32.0/go.mod h1:boDWvdM1Drk4NJj/VddSLnx59X3OPgwrOo0vGbtq9+8= k8s.io/cri-api v0.31.1 h1:x0aI8yTI7Ho4c8tpuig8NwI/MRe+VhjiYyyebC2xphQ= k8s.io/cri-api v0.31.1/go.mod h1:Po3TMAYH/+KrZabi7QiwQI4a692oZcUOUThd/rqwxrI= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20240903163716-9e1beecbcb38 h1:1dWzkmJrrprYvjGwh9kEUxmcUV/CtNU8QM7h1FLWQOo= -k8s.io/kube-openapi v0.0.0-20240903163716-9e1beecbcb38/go.mod h1:coRQXBK9NxO98XUv3ZD6AK3xzHCxV6+b7lrquKwaKzA= -k8s.io/utils v0.0.0-20240921022957-49e7df575cb6 h1:MDF6h2H/h4tbzmtIKTuctcwZmY0tY9mD9fNT47QO6HI= -k8s.io/utils v0.0.0-20240921022957-49e7df575cb6/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.19.0 h1:nWVM7aq+Il2ABxwiCizrVDSlmDcshi9llbaFbC0ji/Q= -sigs.k8s.io/controller-runtime v0.19.0/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y= +k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= +k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= +k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/controller-runtime v0.20.0 h1:jjkMo29xEXH+02Md9qaVXfEIaMESSpy3TBWPrsfQkQs= +sigs.k8s.io/controller-runtime v0.20.0/go.mod h1:BrP3w158MwvB3ZbNpaAcIKkHQ7YGpYnzpoSTZ8E14WU= +sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= +sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= sigs.k8s.io/kind v0.19.0 h1:ZSUh6/kpab6fiowT6EqL4k8xSbedI2NWxyuUOtoPFe4= sigs.k8s.io/kind v0.19.0/go.mod h1:aBlbxg08cauDgZ612shr017/rZwqd7AS563FvpWKPVs= sigs.k8s.io/kustomize/api v0.16.0 h1:/zAR4FOQDCkgSDmVzV2uiFbuy9bhu3jEzthrHCuvm1g= sigs.k8s.io/kustomize/api v0.16.0/go.mod h1:MnFZ7IP2YqVyVwMWoRxPtgl/5hpA+eCCrQR/866cm5c= sigs.k8s.io/kustomize/kyaml v0.16.0 h1:6J33uKSoATlKZH16unr2XOhDI+otoe2sR3M8PDzW3K0= sigs.k8s.io/kustomize/kyaml v0.16.0/go.mod h1:xOK/7i+vmE14N2FdFyugIshB8eF6ALpy7jI87Q2nRh4= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= +sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA= +sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/manager/pod_labeller.go b/manager/pod_labeller.go index ab706ca..bb7ce72 100644 --- a/manager/pod_labeller.go +++ b/manager/pod_labeller.go @@ -18,7 +18,7 @@ type PodLabeller struct { } func NewPodLabeller(log *slog.Logger) *PodLabeller { - log = log.With("component", "podupdater") + log = log.With("component", "podlabeller") log.Info("init") return &PodLabeller{log: log} } diff --git a/manager/pod_scaler.go b/manager/pod_scaler.go index 14843dc..2a498a0 100644 --- a/manager/pod_scaler.go +++ b/manager/pod_scaler.go @@ -38,6 +38,10 @@ func (ps *PodScaler) Handle(ctx context.Context, status *v1.ContainerStatus, pod "namespace", status.PodNamespace, "phase", status.Phase) clog.Info("status event") + if err := ps.setAnnotations(pod); err != nil { + return err + } + for i, container := range pod.Spec.Containers { if container.Name != status.Name { continue @@ -61,11 +65,7 @@ func (ps *PodScaler) Handle(ctx context.Context, status *v1.ContainerStatus, pod continue } - if err := ps.setAnnotations(pod); err != nil { - return err - } - - new := ps.newRequests(initial, current, status) + new := ps.newRequests(initial, current.DeepCopy(), status) pod.Spec.Containers[i].Resources.Requests = new clog.Debug("container needs to be updated", "current", printResources(current), "new", printResources(new)) } diff --git a/manager/status.go b/manager/status.go index f561a59..95cacd8 100644 --- a/manager/status.go +++ b/manager/status.go @@ -164,18 +164,40 @@ func (s *subscriber) onStatus(ctx context.Context, status *v1.ContainerStatus) e func (s *subscriber) handlePod(ctx context.Context, status *v1.ContainerStatus) error { pod := &corev1.Pod{} podName := types.NamespacedName{Name: status.PodName, Namespace: status.PodNamespace} - if err := s.kube.Get(ctx, podName, pod); err != nil { - return fmt.Errorf("getting pod: %w", err) - } - for _, p := range s.podHandlers { - if err := p.Handle(ctx, status, pod); err != nil { - return err + if err := retry.RetryOnConflict(retry.DefaultRetry, func() error { + if err := s.kube.Get(ctx, podName, pod); err != nil { + return fmt.Errorf("getting pod: %w", err) } - } + // as a pod handler might want to resize the pod resources, we store all + // containers before calling the handlers + containersBefore := pod.DeepCopy().Spec.Containers + for _, p := range s.podHandlers { + if err := p.Handle(ctx, status, pod); err != nil { + return err + } + } + // store containers after and revert the pod spec so we can call the + // update for all other fields + containersAfter := pod.DeepCopy().Spec.Containers + pod.Spec.Containers = containersBefore - if err := retry.RetryOnConflict(retry.DefaultRetry, func() error { - return s.kube.Update(ctx, pod) + if err := s.kube.Update(ctx, pod); err != nil { + return fmt.Errorf("updating pod: %w", err) + } + // now that other field updates succeeded, we apply the containers again + // and try to resize + pod.Spec.Containers = containersAfter + if err := s.kube.SubResource("resize").Update(ctx, pod); err != nil { + if !apierrors.IsNotFound(err) { + return err + } + s.log.Info("updating pod resources using resize failed, falling back to update") + if err := s.kube.Update(ctx, pod); err != nil { + return fmt.Errorf("updating pod: %w", err) + } + } + return nil }); err != nil { if apierrors.IsInvalid(err) { s.log.Error("in-place scaling failed, ensure InPlacePodVerticalScaling feature flag is enabled")