From 3f77141d45b5175870a26fecf8095aeea051f8c8 Mon Sep 17 00:00:00 2001 From: wenxuanW Date: Thu, 2 Apr 2026 14:07:13 -0700 Subject: [PATCH] Support kubelet node ip flag configuration --- components/kubelet/action.pb.go | 105 ++++++++++++------ components/kubelet/action.proto | 1 + .../assets/20-flex-node-node-config.conf | 2 +- .../kubelet/v20260301/kubelet_service.go | 1 + pkg/bootstrapper/components.go | 10 ++ pkg/config/structs.go | 1 + 6 files changed, 85 insertions(+), 35 deletions(-) diff --git a/components/kubelet/action.pb.go b/components/kubelet/action.pb.go index 75d645b6..fac53e07 100644 --- a/components/kubelet/action.pb.go +++ b/components/kubelet/action.pb.go @@ -862,13 +862,11 @@ func (x *NodeAuthInfo) ClearBootstrapTokenCredential() { } } -const ( - NodeAuthInfo_AuthInfo_not_set_case case_NodeAuthInfo_AuthInfo = 0 - NodeAuthInfo_ArcCredential_case case_NodeAuthInfo_AuthInfo = 1 - NodeAuthInfo_MsiCredential_case case_NodeAuthInfo_AuthInfo = 2 - NodeAuthInfo_ServicePrincipalCredential_case case_NodeAuthInfo_AuthInfo = 3 - NodeAuthInfo_BootstrapTokenCredential_case case_NodeAuthInfo_AuthInfo = 4 -) +const NodeAuthInfo_AuthInfo_not_set_case case_NodeAuthInfo_AuthInfo = 0 +const NodeAuthInfo_ArcCredential_case case_NodeAuthInfo_AuthInfo = 1 +const NodeAuthInfo_MsiCredential_case case_NodeAuthInfo_AuthInfo = 2 +const NodeAuthInfo_ServicePrincipalCredential_case case_NodeAuthInfo_AuthInfo = 3 +const NodeAuthInfo_BootstrapTokenCredential_case case_NodeAuthInfo_AuthInfo = 4 func (x *NodeAuthInfo) WhichAuthInfo() case_NodeAuthInfo_AuthInfo { if x == nil { @@ -1176,6 +1174,9 @@ type StartKubeletServiceSpec struct { xxx_hidden_NodeAuthInfo *NodeAuthInfo `protobuf:"bytes,2,opt,name=node_auth_info,json=nodeAuthInfo"` xxx_hidden_NodeLabels map[string]string `protobuf:"bytes,3,rep,name=node_labels,json=nodeLabels" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` xxx_hidden_KubeletConfig *KubeletConfig `protobuf:"bytes,4,opt,name=kubelet_config,json=kubeletConfig"` + xxx_hidden_NodeIp *string `protobuf:"bytes,5,opt,name=node_ip,json=nodeIp"` + XXX_raceDetectHookData protoimpl.RaceDetectHookData + XXX_presence [1]uint32 unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1233,6 +1234,16 @@ func (x *StartKubeletServiceSpec) GetKubeletConfig() *KubeletConfig { return nil } +func (x *StartKubeletServiceSpec) GetNodeIp() string { + if x != nil { + if x.xxx_hidden_NodeIp != nil { + return *x.xxx_hidden_NodeIp + } + return "" + } + return "" +} + func (x *StartKubeletServiceSpec) SetControlPlane(v *ControlPlane) { x.xxx_hidden_ControlPlane = v } @@ -1249,6 +1260,11 @@ func (x *StartKubeletServiceSpec) SetKubeletConfig(v *KubeletConfig) { x.xxx_hidden_KubeletConfig = v } +func (x *StartKubeletServiceSpec) SetNodeIp(v string) { + x.xxx_hidden_NodeIp = &v + protoimpl.X.SetPresent(&(x.XXX_presence[0]), 4, 5) +} + func (x *StartKubeletServiceSpec) HasControlPlane() bool { if x == nil { return false @@ -1270,6 +1286,13 @@ func (x *StartKubeletServiceSpec) HasKubeletConfig() bool { return x.xxx_hidden_KubeletConfig != nil } +func (x *StartKubeletServiceSpec) HasNodeIp() bool { + if x == nil { + return false + } + return protoimpl.X.Present(&(x.XXX_presence[0]), 4) +} + func (x *StartKubeletServiceSpec) ClearControlPlane() { x.xxx_hidden_ControlPlane = nil } @@ -1282,6 +1305,11 @@ func (x *StartKubeletServiceSpec) ClearKubeletConfig() { x.xxx_hidden_KubeletConfig = nil } +func (x *StartKubeletServiceSpec) ClearNodeIp() { + protoimpl.X.ClearPresent(&(x.XXX_presence[0]), 4) + x.xxx_hidden_NodeIp = nil +} + type StartKubeletServiceSpec_builder struct { _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. @@ -1289,6 +1317,7 @@ type StartKubeletServiceSpec_builder struct { NodeAuthInfo *NodeAuthInfo NodeLabels map[string]string KubeletConfig *KubeletConfig + NodeIp *string } func (b0 StartKubeletServiceSpec_builder) Build() *StartKubeletServiceSpec { @@ -1299,6 +1328,10 @@ func (b0 StartKubeletServiceSpec_builder) Build() *StartKubeletServiceSpec { x.xxx_hidden_NodeAuthInfo = b.NodeAuthInfo x.xxx_hidden_NodeLabels = b.NodeLabels x.xxx_hidden_KubeletConfig = b.KubeletConfig + if b.NodeIp != nil { + protoimpl.X.SetPresentNonAtomic(&(x.XXX_presence[0]), 4, 5) + x.xxx_hidden_NodeIp = b.NodeIp + } return m0 } @@ -1335,6 +1368,7 @@ func (x *StartKubeletServiceStatus) ProtoReflect() protoreflect.Message { type StartKubeletServiceStatus_builder struct { _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + } func (b0 StartKubeletServiceStatus_builder) Build() *StartKubeletServiceStatus { @@ -1495,6 +1529,7 @@ func (x *ResetKubeletSpec) ProtoReflect() protoreflect.Message { type ResetKubeletSpec_builder struct { _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + } func (b0 ResetKubeletSpec_builder) Build() *ResetKubeletSpec { @@ -1537,6 +1572,7 @@ func (x *ResetKubeletStatus) ProtoReflect() protoreflect.Message { type ResetKubeletStatus_builder struct { _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + } func (b0 ResetKubeletStatus_builder) Build() *ResetKubeletStatus { @@ -1697,6 +1733,7 @@ func (x *StopKubeletServiceSpec) ProtoReflect() protoreflect.Message { type StopKubeletServiceSpec_builder struct { _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + } func (b0 StopKubeletServiceSpec_builder) Build() *StopKubeletServiceSpec { @@ -1739,6 +1776,7 @@ func (x *StopKubeletServiceStatus) ProtoReflect() protoreflect.Message { type StopKubeletServiceStatus_builder struct { _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + } func (b0 StopKubeletServiceStatus_builder) Build() *StopKubeletServiceStatus { @@ -1792,13 +1830,14 @@ const file_components_kubelet_action_proto_rawDesc = "" + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\x1a?\n" + "\x11EvictionHardEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\xb3\x03\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\xcc\x03\n" + "\x17StartKubeletServiceSpec\x12N\n" + "\rcontrol_plane\x18\x01 \x01(\v2).aks.flex.components.kubelet.ControlPlaneR\fcontrolPlane\x12O\n" + "\x0enode_auth_info\x18\x02 \x01(\v2).aks.flex.components.kubelet.NodeAuthInfoR\fnodeAuthInfo\x12e\n" + "\vnode_labels\x18\x03 \x03(\v2D.aks.flex.components.kubelet.StartKubeletServiceSpec.NodeLabelsEntryR\n" + "nodeLabels\x12Q\n" + - "\x0ekubelet_config\x18\x04 \x01(\v2*.aks.flex.components.kubelet.KubeletConfigR\rkubeletConfig\x1a=\n" + + "\x0ekubelet_config\x18\x04 \x01(\v2*.aks.flex.components.kubelet.KubeletConfigR\rkubeletConfig\x12\x17\n" + + "\anode_ip\x18\x05 \x01(\tR\x06nodeIp\x1a=\n" + "\x0fNodeLabelsEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\x1b\n" + @@ -1816,31 +1855,29 @@ const file_components_kubelet_action_proto_rawDesc = "" + "\x16StopKubeletServiceSpec\"\x1a\n" + "\x18StopKubeletServiceStatusB1Z/github.com/Azure/AKSFlexNode/components/kubeletb\beditionsp\xe9\a" -var ( - file_components_kubelet_action_proto_msgTypes = make([]protoimpl.MessageInfo, 19) - file_components_kubelet_action_proto_goTypes = []any{ - (*StartKubeletService)(nil), // 0: aks.flex.components.kubelet.StartKubeletService - (*KubeletArcCredential)(nil), // 1: aks.flex.components.kubelet.KubeletArcCredential - (*KubeletMSICredential)(nil), // 2: aks.flex.components.kubelet.KubeletMSICredential - (*KubeletServicePrincipalCredential)(nil), // 3: aks.flex.components.kubelet.KubeletServicePrincipalCredential - (*KubeletBootstrapTokenCredential)(nil), // 4: aks.flex.components.kubelet.KubeletBootstrapTokenCredential - (*ControlPlane)(nil), // 5: aks.flex.components.kubelet.ControlPlane - (*NodeAuthInfo)(nil), // 6: aks.flex.components.kubelet.NodeAuthInfo - (*KubeletConfig)(nil), // 7: aks.flex.components.kubelet.KubeletConfig - (*StartKubeletServiceSpec)(nil), // 8: aks.flex.components.kubelet.StartKubeletServiceSpec - (*StartKubeletServiceStatus)(nil), // 9: aks.flex.components.kubelet.StartKubeletServiceStatus - (*ResetKubelet)(nil), // 10: aks.flex.components.kubelet.ResetKubelet - (*ResetKubeletSpec)(nil), // 11: aks.flex.components.kubelet.ResetKubeletSpec - (*ResetKubeletStatus)(nil), // 12: aks.flex.components.kubelet.ResetKubeletStatus - (*StopKubeletService)(nil), // 13: aks.flex.components.kubelet.StopKubeletService - (*StopKubeletServiceSpec)(nil), // 14: aks.flex.components.kubelet.StopKubeletServiceSpec - (*StopKubeletServiceStatus)(nil), // 15: aks.flex.components.kubelet.StopKubeletServiceStatus - nil, // 16: aks.flex.components.kubelet.KubeletConfig.KubeReservedEntry - nil, // 17: aks.flex.components.kubelet.KubeletConfig.EvictionHardEntry - nil, // 18: aks.flex.components.kubelet.StartKubeletServiceSpec.NodeLabelsEntry - (*api.Metadata)(nil), // 19: aks.flex.components.api.Metadata - } -) +var file_components_kubelet_action_proto_msgTypes = make([]protoimpl.MessageInfo, 19) +var file_components_kubelet_action_proto_goTypes = []any{ + (*StartKubeletService)(nil), // 0: aks.flex.components.kubelet.StartKubeletService + (*KubeletArcCredential)(nil), // 1: aks.flex.components.kubelet.KubeletArcCredential + (*KubeletMSICredential)(nil), // 2: aks.flex.components.kubelet.KubeletMSICredential + (*KubeletServicePrincipalCredential)(nil), // 3: aks.flex.components.kubelet.KubeletServicePrincipalCredential + (*KubeletBootstrapTokenCredential)(nil), // 4: aks.flex.components.kubelet.KubeletBootstrapTokenCredential + (*ControlPlane)(nil), // 5: aks.flex.components.kubelet.ControlPlane + (*NodeAuthInfo)(nil), // 6: aks.flex.components.kubelet.NodeAuthInfo + (*KubeletConfig)(nil), // 7: aks.flex.components.kubelet.KubeletConfig + (*StartKubeletServiceSpec)(nil), // 8: aks.flex.components.kubelet.StartKubeletServiceSpec + (*StartKubeletServiceStatus)(nil), // 9: aks.flex.components.kubelet.StartKubeletServiceStatus + (*ResetKubelet)(nil), // 10: aks.flex.components.kubelet.ResetKubelet + (*ResetKubeletSpec)(nil), // 11: aks.flex.components.kubelet.ResetKubeletSpec + (*ResetKubeletStatus)(nil), // 12: aks.flex.components.kubelet.ResetKubeletStatus + (*StopKubeletService)(nil), // 13: aks.flex.components.kubelet.StopKubeletService + (*StopKubeletServiceSpec)(nil), // 14: aks.flex.components.kubelet.StopKubeletServiceSpec + (*StopKubeletServiceStatus)(nil), // 15: aks.flex.components.kubelet.StopKubeletServiceStatus + nil, // 16: aks.flex.components.kubelet.KubeletConfig.KubeReservedEntry + nil, // 17: aks.flex.components.kubelet.KubeletConfig.EvictionHardEntry + nil, // 18: aks.flex.components.kubelet.StartKubeletServiceSpec.NodeLabelsEntry + (*api.Metadata)(nil), // 19: aks.flex.components.api.Metadata +} var file_components_kubelet_action_proto_depIdxs = []int32{ 19, // 0: aks.flex.components.kubelet.StartKubeletService.metadata:type_name -> aks.flex.components.api.Metadata 8, // 1: aks.flex.components.kubelet.StartKubeletService.spec:type_name -> aks.flex.components.kubelet.StartKubeletServiceSpec diff --git a/components/kubelet/action.proto b/components/kubelet/action.proto index 15667588..fbe1cdb1 100644 --- a/components/kubelet/action.proto +++ b/components/kubelet/action.proto @@ -69,6 +69,7 @@ message StartKubeletServiceSpec { NodeAuthInfo node_auth_info = 2; map node_labels = 3; KubeletConfig kubelet_config = 4; + string node_ip = 5; } message StartKubeletServiceStatus { diff --git a/components/kubelet/v20260301/assets/20-flex-node-node-config.conf b/components/kubelet/v20260301/assets/20-flex-node-node-config.conf index 5565d59a..9266d5da 100644 --- a/components/kubelet/v20260301/assets/20-flex-node-node-config.conf +++ b/components/kubelet/v20260301/assets/20-flex-node-node-config.conf @@ -4,5 +4,5 @@ # You may create a higher-numbered drop-in (e.g. 90-custom-node-config.conf) # to append or override individual env vars. [Service] -Environment="KUBELET_NODE_CONFIG_ARGS=--node-labels={{.NodeLabels}} --v={{.Verbosity}} --client-ca-file={{.ClientCAFile}}{{range .ClusterDNS}} --cluster-dns={{.}}{{end}}" +Environment="KUBELET_NODE_CONFIG_ARGS=--node-labels={{.NodeLabels}} --v={{.Verbosity}} --client-ca-file={{.ClientCAFile}}{{range .ClusterDNS}} --cluster-dns={{.}}{{end}}{{if .NodeIP}} --node-ip={{.NodeIP}}{{end}}" Environment="KUBELET_TUNING_ARGS=--eviction-hard={{.EvictionHard}} --kube-reserved={{.KubeReserved}} --image-gc-high-threshold={{.ImageGCHighThreshold}} --image-gc-low-threshold={{.ImageGCLowThreshold}} --max-pods={{.MaxPods}}" diff --git a/components/kubelet/v20260301/kubelet_service.go b/components/kubelet/v20260301/kubelet_service.go index 65b2911c..0efbd463 100644 --- a/components/kubelet/v20260301/kubelet_service.go +++ b/components/kubelet/v20260301/kubelet_service.go @@ -79,6 +79,7 @@ func (s *startKubeletServiceAction) ensureSystemdUnit( "ImageGCHighThreshold": kubeletConfig.GetImageGcHighThreshold(), "ImageGCLowThreshold": kubeletConfig.GetImageGcLowThreshold(), "MaxPods": kubeletConfig.GetMaxPods(), + "NodeIP": spec.GetNodeIp(), }) if err != nil { return err diff --git a/pkg/bootstrapper/components.go b/pkg/bootstrapper/components.go index 6c6f98a4..a0cd0e72 100644 --- a/pkg/bootstrapper/components.go +++ b/pkg/bootstrapper/components.go @@ -77,6 +77,15 @@ func ptr[T any](value T) *T { return &value } +// ptrOrNil returns nil if value is the zero value for T, otherwise returns a pointer to value. +func ptrOrNil[T comparable](value T) *T { + var zero T + if value == zero { + return nil + } + return &value +} + func componentAction(name string) *api.Metadata { return api.Metadata_builder{Name: &name}.Build() } @@ -297,6 +306,7 @@ var startKubelet resolveActionFunc[*kubelet.StartKubeletService] = func( ClusterDns: []string{cfg.Node.Kubelet.DNSServiceIP}, MaxPods: ptr(int32(cfg.Node.MaxPods)), }.Build(), + NodeIp: ptrOrNil(cfg.Node.Kubelet.NodeIP), }.Build() return kubelet.StartKubeletService_builder{ diff --git a/pkg/config/structs.go b/pkg/config/structs.go index e2b21907..5495db2b 100644 --- a/pkg/config/structs.go +++ b/pkg/config/structs.go @@ -132,6 +132,7 @@ type KubeletConfig struct { DNSServiceIP string `json:"dnsServiceIP"` // Cluster DNS service IP (default: 10.0.0.10 for AKS) ServerURL string `json:"serverURL"` // Kubernetes API server URL CACertData string `json:"caCertData"` // Base64-encoded CA certificate data + NodeIP string `json:"nodeIP"` // IP address to advertise as the node's primary IP (--node-ip kubelet flag) } // PathsConfig holds file system paths used by the agent for Kubernetes and CNI configurations.