pkg/api/addons.go (998 lines of code) (raw):

// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. package api import ( "fmt" "strconv" "strings" "github.com/Azure/aks-engine-azurestack/pkg/api/common" "github.com/Azure/aks-engine-azurestack/pkg/helpers/to" log "github.com/sirupsen/logrus" ) func (cs *ContainerService) setAddonsConfig(isUpgrade bool) { var o *OrchestratorProfile if cs.Properties != nil { o = cs.Properties.OrchestratorProfile } cloudSpecConfig := cs.GetCloudSpecConfig() specConfig := cloudSpecConfig.KubernetesSpecConfig kubernetesImageBase := specConfig.MCRKubernetesImageBase if o.KubernetesConfig.KubernetesImageBase != "" { kubernetesImageBase = o.KubernetesConfig.KubernetesImageBase } k8sComponents := GetK8sComponentsByVersionMap(o.KubernetesConfig)[o.OrchestratorVersion] defaultTillerAddonsConfig := KubernetesAddon{ Name: common.TillerAddonName, Enabled: to.BoolPtr(DefaultTillerAddonEnabled), Containers: []KubernetesContainerSpec{ { Name: common.TillerAddonName, CPURequests: "50m", MemoryRequests: "150Mi", CPULimits: "50m", MemoryLimits: "150Mi", Image: specConfig.TillerImageBase + k8sComponents[common.TillerAddonName], }, }, Config: map[string]string{ "max-history": strconv.Itoa(DefaultTillerMaxHistory), }, } defaultClusterAutoscalerAddonsConfig := KubernetesAddon{ Name: common.ClusterAutoscalerAddonName, Enabled: to.BoolPtr(DefaultClusterAutoscalerAddonEnabled && !cs.Properties.IsAzureStackCloud()), Mode: AddonModeEnsureExists, Config: map[string]string{ "scan-interval": "1m", "expendable-pods-priority-cutoff": "-10", "ignore-daemonsets-utilization": "false", "ignore-mirror-pods-utilization": "false", "max-autoprovisioned-node-group-count": "15", "max-empty-bulk-delete": "10", "max-failing-time": "15m0s", "max-graceful-termination-sec": "600", "max-inactivity": "10m0s", "max-node-provision-time": "15m0s", "max-nodes-total": "0", "max-total-unready-percentage": "45", "memory-total": "0:6400000", "min-replica-count": "0", "new-pod-scale-up-delay": "0s", "node-autoprovisioning-enabled": "false", "ok-total-unready-count": "3", "scale-down-candidates-pool-min-count": "50", "scale-down-candidates-pool-ratio": "0.1", "scale-down-delay-after-add": "10m0s", "scale-down-delay-after-delete": "1m", "scale-down-delay-after-failure": "3m0s", "scale-down-enabled": "true", "scale-down-non-empty-candidates-count": "30", "scale-down-unneeded-time": "10m0s", "scale-down-unready-time": "20m0s", "scale-down-utilization-threshold": "0.5", "skip-nodes-with-local-storage": "false", "skip-nodes-with-system-pods": "true", "stderrthreshold": "2", "unremovable-node-recheck-timeout": "5m0s", "v": "3", "write-status-configmap": "true", "balance-similar-node-groups": "true", }, Containers: []KubernetesContainerSpec{ { Name: common.ClusterAutoscalerAddonName, CPURequests: "100m", MemoryRequests: "300Mi", CPULimits: "100m", MemoryLimits: "300Mi", Image: kubernetesImageBase + k8sComponents[common.ClusterAutoscalerAddonName], }, }, Pools: makeDefaultClusterAutoscalerAddonPoolsConfig(cs), } defaultSMBFlexVolumeAddonsConfig := KubernetesAddon{ Name: common.SMBFlexVolumeAddonName, Enabled: to.BoolPtr(DefaultSMBFlexVolumeAddonEnabled && common.IsKubernetesVersionGe(o.OrchestratorVersion, "1.8.0") && !cs.Properties.IsAzureStackCloud()), Containers: []KubernetesContainerSpec{ { Name: common.SMBFlexVolumeAddonName, CPURequests: "50m", MemoryRequests: "100Mi", CPULimits: "50m", MemoryLimits: "100Mi", Image: k8sComponents[common.SMBFlexVolumeAddonName], }, }, } defaultDashboardAddonsConfig := KubernetesAddon{ Name: common.DashboardAddonName, Enabled: to.BoolPtr(DefaultDashboardAddonEnabled), Containers: []KubernetesContainerSpec{ { Name: common.DashboardAddonName, CPURequests: "300m", MemoryRequests: "150Mi", CPULimits: "300m", MemoryLimits: "150Mi", Image: k8sComponents[common.DashboardAddonName], }, { Name: common.DashboardMetricsScraperContainerName, CPURequests: "300m", MemoryRequests: "150Mi", CPULimits: "300m", MemoryLimits: "150Mi", Image: k8sComponents[common.DashboardMetricsScraperContainerName], }, }, } defaultMetricsServerAddonsConfig := KubernetesAddon{ Name: common.MetricsServerAddonName, Enabled: to.BoolPtr(DefaultMetricsServerAddonEnabled), Mode: AddonModeReconcile, Containers: []KubernetesContainerSpec{ { Name: common.MetricsServerAddonName, Image: kubernetesImageBase + k8sComponents[common.MetricsServerAddonName], }, }, } if !common.IsKubernetesVersionGe(o.OrchestratorVersion, "1.16.0") { defaultMetricsServerAddonsConfig.Mode = AddonModeEnsureExists } defaultNVIDIADevicePluginAddonsConfig := KubernetesAddon{ Name: common.NVIDIADevicePluginAddonName, Enabled: to.BoolPtr(cs.Properties.IsNvidiaDevicePluginCapable() && !cs.Properties.IsAzureStackCloud()), Containers: []KubernetesContainerSpec{ { Name: common.NVIDIADevicePluginAddonName, // from https://github.com/kubernetes/kubernetes/blob/master/cluster/addons/device-plugins/nvidia-gpu/daemonset.yaml#L44 CPURequests: "50m", MemoryRequests: "100Mi", CPULimits: "50m", MemoryLimits: "100Mi", Image: specConfig.NVIDIAImageBase + k8sComponents[common.NVIDIADevicePluginAddonName], }, }, } defaultIPMasqAgentAddonsConfig := KubernetesAddon{ Name: common.IPMASQAgentAddonName, Enabled: to.BoolPtr(DefaultIPMasqAgentAddonEnabled && o.KubernetesConfig.NetworkPlugin != NetworkPluginCilium && o.KubernetesConfig.NetworkPlugin != NetworkPluginAntrea), Containers: []KubernetesContainerSpec{ { Name: common.IPMASQAgentAddonName, CPURequests: "50m", MemoryRequests: "50Mi", CPULimits: "50m", MemoryLimits: "250Mi", Image: kubernetesImageBase + k8sComponents[common.IPMASQAgentAddonName], }, }, Config: map[string]string{ "non-masquerade-cidr": cs.Properties.GetNonMasqueradeCIDR(), "non-masq-cni-cidr": cs.Properties.GetAzureCNICidr(), "secondary-non-masquerade-cidr": cs.Properties.GetSecondaryNonMasqueradeCIDR(), "enable-ipv6": strconv.FormatBool(cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6DualStack") || cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6Only")), }, } defaultAzureNetworkPolicyAddonsConfig := KubernetesAddon{ Name: common.AzureNetworkPolicyAddonName, Enabled: to.BoolPtr(o.KubernetesConfig.NetworkPlugin == NetworkPluginAzure && o.KubernetesConfig.NetworkPolicy == NetworkPolicyAzure), Mode: AddonModeReconcile, Containers: []KubernetesContainerSpec{ { Name: common.AzureNetworkPolicyAddonName, Image: k8sComponents[common.AzureNetworkPolicyAddonName], CPURequests: "10m", MemoryRequests: "20Mi", CPULimits: "100m", MemoryLimits: "200Mi", }, }, } if !common.IsKubernetesVersionGe(o.OrchestratorVersion, "1.16.0") { defaultAzureNetworkPolicyAddonsConfig.Mode = AddonModeEnsureExists } defaultCloudNodeManagerAddonsConfig := KubernetesAddon{ Name: common.CloudNodeManagerAddonName, Enabled: to.BoolPtr(cs.Properties.ShouldEnableAzureCloudAddon(common.CloudNodeManagerAddonName)), Containers: []KubernetesContainerSpec{ { Name: common.CloudNodeManagerAddonName, Image: specConfig.MCRKubernetesImageBase + k8sComponents[common.CloudNodeManagerAddonName], }, }, } defaultsCalicoDaemonSetAddonsConfig := KubernetesAddon{ Name: common.CalicoAddonName, Enabled: to.BoolPtr(o.KubernetesConfig.NetworkPolicy == NetworkPolicyCalico), Config: map[string]string{ "logSeverityScreen": "info", "usageReportingEnabled": "true", }, Containers: []KubernetesContainerSpec{ { Name: common.CalicoTyphaComponentName, Image: specConfig.CalicoImageBase + k8sComponents[common.CalicoTyphaComponentName], }, { Name: common.CalicoCNIComponentName, Image: specConfig.CalicoImageBase + k8sComponents[common.CalicoCNIComponentName], }, { Name: common.CalicoNodeComponentName, Image: specConfig.CalicoImageBase + k8sComponents[common.CalicoNodeComponentName], }, { Name: common.CalicoPod2DaemonComponentName, Image: specConfig.CalicoImageBase + k8sComponents[common.CalicoPod2DaemonComponentName], }, { Name: common.CalicoClusterAutoscalerComponentName, Image: k8sComponents[common.CalicoClusterAutoscalerComponentName], }, }, } defaultsCiliumAddonsConfig := KubernetesAddon{ Name: common.CiliumAddonName, Enabled: to.BoolPtr(o.KubernetesConfig.NetworkPolicy == NetworkPolicyCilium), Containers: []KubernetesContainerSpec{ { Name: common.CiliumAgentContainerName, Image: k8sComponents[common.CiliumAgentContainerName], }, { Name: common.CiliumCleanStateContainerName, Image: k8sComponents[common.CiliumCleanStateContainerName], }, { Name: common.CiliumOperatorContainerName, Image: k8sComponents[common.CiliumOperatorContainerName], }, { Name: common.CiliumEtcdOperatorContainerName, Image: k8sComponents[common.CiliumEtcdOperatorContainerName], }, }, } defaultsAntreaDaemonSetAddonsConfig := KubernetesAddon{ Name: common.AntreaAddonName, Enabled: to.BoolPtr(o.KubernetesConfig.NetworkPolicy == NetworkPolicyAntrea), Config: map[string]string{ "serviceCidr": o.KubernetesConfig.ServiceCIDR, "trafficEncapMode": common.AntreaDefaultTrafficEncapMode, "installCniCmd": common.AntreaDefaultInstallCniCmd, }, Containers: []KubernetesContainerSpec{ { Name: common.AntreaControllerContainerName, Image: k8sComponents[common.AntreaControllerContainerName], CPURequests: "200m", }, { Name: common.AntreaAgentContainerName, Image: k8sComponents[common.AntreaAgentContainerName], CPURequests: "200m", }, { Name: common.AntreaOVSContainerName, Image: k8sComponents[common.AntreaOVSContainerName], CPURequests: "200m", }, { Name: common.AntreaInstallCNIContainerName, Image: k8sComponents["antrea"+common.AntreaInstallCNIContainerName], CPURequests: "100m", }, }, } // Set NetworkPolicyOnly mode when azure cni is enabled if o.KubernetesConfig.NetworkPolicy == NetworkPolicyAntrea && o.IsAzureCNI() { defaultsAntreaDaemonSetAddonsConfig.Config["trafficEncapMode"] = common.AntreaNetworkPolicyOnlyMode defaultsAntreaDaemonSetAddonsConfig.Config["installCniCmd"] = common.AntreaInstallCniChainCmd } defaultsAADPodIdentityAddonsConfig := KubernetesAddon{ Name: common.AADPodIdentityAddonName, Enabled: to.BoolPtr(DefaultAADPodIdentityAddonEnabled && !cs.Properties.IsAzureStackCloud()), Config: map[string]string{ "probePort": "8085", }, Containers: []KubernetesContainerSpec{ { Name: common.NMIContainerName, Image: k8sComponents[common.NMIContainerName], CPURequests: "100m", MemoryRequests: "256Mi", CPULimits: "200m", MemoryLimits: "512Mi", }, { Name: common.MICContainerName, Image: k8sComponents[common.MICContainerName], CPURequests: "100m", MemoryRequests: "256Mi", CPULimits: "200m", MemoryLimits: "1024Mi", }, }, } defaultsAzurePolicyAddonsConfig := KubernetesAddon{ Name: common.AzurePolicyAddonName, Enabled: to.BoolPtr(DefaultAzurePolicyAddonEnabled && !cs.Properties.IsAzureStackCloud()), Config: map[string]string{ "auditInterval": "60", "constraintViolationsLimit": "100", }, Containers: []KubernetesContainerSpec{ { Name: common.AzurePolicyAddonName, Image: k8sComponents[common.AzurePolicyAddonName], CPURequests: "30m", MemoryRequests: "50Mi", CPULimits: "100m", MemoryLimits: "200Mi", }, { Name: common.GatekeeperContainerName, Image: k8sComponents[common.GatekeeperContainerName], CPURequests: "100m", MemoryRequests: "256Mi", CPULimits: "1000m", MemoryLimits: "512Mi", }, }, } defaultNodeProblemDetectorConfig := KubernetesAddon{ Name: common.NodeProblemDetectorAddonName, Enabled: to.BoolPtr(DefaultNodeProblemDetectorAddonEnabled), Config: map[string]string{ "customPluginMonitor": "/config/kernel-monitor-counter.json,/config/systemd-monitor-counter.json", "systemLogMonitor": "/config/kernel-monitor.json,/config/docker-monitor.json,/config/systemd-monitor.json", "systemStatsMonitor": "/config/system-stats-monitor.json", "versionLabel": "v0.8.4", }, Containers: []KubernetesContainerSpec{ { Name: common.NodeProblemDetectorAddonName, Image: k8sComponents[common.NodeProblemDetectorAddonName], CPURequests: "20m", MemoryRequests: "20Mi", CPULimits: "200m", MemoryLimits: "100Mi", }, }, } defaultAppGwAddonsConfig := KubernetesAddon{ Name: common.AppGwIngressAddonName, Enabled: to.BoolPtr(DefaultAppGwIngressAddonEnabled), Config: map[string]string{ "appgw-subnet": "", "appgw-sku": "WAF_v2", "appgw-private-ip": "", }, } defaultAzureDiskCSIDriverAddonsConfig := KubernetesAddon{ Name: common.AzureDiskCSIDriverAddonName, Enabled: to.BoolPtr(DefaultAzureDiskCSIDriverAddonEnabled && cs.Properties.ShouldEnableAzureCloudAddon(common.AzureDiskCSIDriverAddonName)), Containers: []KubernetesContainerSpec{ { Name: common.CSIProvisionerContainerName, Image: specConfig.MCRKubernetesImageBase + getCSISidecarComponent(common.AzureDiskCSIDriverAddonName, common.CSIProvisionerContainerName, k8sComponents), CPURequests: "10m", MemoryRequests: "20Mi", CPULimits: "2", MemoryLimits: "2Gi", }, { Name: common.CSIAttacherContainerName, Image: specConfig.MCRKubernetesImageBase + getCSISidecarComponent(common.AzureDiskCSIDriverAddonName, common.CSIAttacherContainerName, k8sComponents), CPURequests: "10m", MemoryRequests: "20Mi", CPULimits: "2", MemoryLimits: "2Gi", }, { Name: common.CSILivenessProbeContainerName, Image: specConfig.MCRKubernetesImageBase + getCSISidecarComponent(common.AzureDiskCSIDriverAddonName, common.CSILivenessProbeContainerName, k8sComponents), CPURequests: "10m", MemoryRequests: "20Mi", CPULimits: "2", MemoryLimits: "2Gi", }, { Name: common.CSINodeDriverRegistrarContainerName, Image: specConfig.MCRKubernetesImageBase + getCSISidecarComponent(common.AzureDiskCSIDriverAddonName, common.CSINodeDriverRegistrarContainerName, k8sComponents), CPURequests: "10m", MemoryRequests: "20Mi", CPULimits: "2", MemoryLimits: "2Gi", }, { Name: common.CSILivenessProbeWindowsContainerName, Image: specConfig.MCRKubernetesImageBase + getCSISidecarComponent(common.AzureDiskCSIDriverAddonName, common.CSILivenessProbeWindowsContainerName, k8sComponents), CPURequests: "10m", MemoryRequests: "20Mi", CPULimits: "2", MemoryLimits: "2Gi", }, { Name: common.CSINodeDriverRegistrarWindowsContainerName, Image: specConfig.MCRKubernetesImageBase + getCSISidecarComponent(common.AzureDiskCSIDriverAddonName, common.CSINodeDriverRegistrarWindowsContainerName, k8sComponents), CPURequests: "10m", MemoryRequests: "20Mi", CPULimits: "2", MemoryLimits: "2Gi", }, { Name: common.CSISnapshotterContainerName, Image: specConfig.MCRKubernetesImageBase + getCSISidecarComponent(common.AzureDiskCSIDriverAddonName, common.CSISnapshotterContainerName, k8sComponents), CPURequests: "10m", MemoryRequests: "20Mi", CPULimits: "2", MemoryLimits: "2Gi", }, { Name: common.CSISnapshotControllerContainerName, Image: specConfig.MCRKubernetesImageBase + getCSISidecarComponent(common.AzureDiskCSIDriverAddonName, common.CSISnapshotControllerContainerName, k8sComponents), CPURequests: "10m", MemoryRequests: "20Mi", CPULimits: "2", MemoryLimits: "2Gi", }, { Name: common.CSIResizerContainerName, Image: specConfig.MCRKubernetesImageBase + getCSISidecarComponent(common.AzureDiskCSIDriverAddonName, common.CSIResizerContainerName, k8sComponents), CPURequests: "10m", MemoryRequests: "20Mi", CPULimits: "2", MemoryLimits: "2Gi", }, { Name: common.CSIAzureDiskContainerName, Image: specConfig.MCRKubernetesImageBase + getCSISidecarComponent(common.AzureDiskCSIDriverAddonName, common.CSIAzureDiskContainerName, k8sComponents), CPURequests: "10m", MemoryRequests: "20Mi", CPULimits: "2", MemoryLimits: "2Gi", }, }, } defaultAzureFileCSIDriverAddonsConfig := KubernetesAddon{ Name: common.AzureFileCSIDriverAddonName, Enabled: to.BoolPtr(DefaultAzureFileCSIDriverAddonEnabled && cs.Properties.ShouldEnableAzureCloudAddon(common.AzureFileCSIDriverAddonName) && !cs.Properties.IsAzureStackCloud()), Containers: []KubernetesContainerSpec{ { Name: common.CSIProvisionerContainerName, Image: specConfig.MCRKubernetesImageBase + getCSISidecarComponent(common.AzureFileCSIDriverAddonName, common.CSIProvisionerContainerName, k8sComponents), CPURequests: "10m", MemoryRequests: "20Mi", CPULimits: "2", MemoryLimits: "2Gi", }, { Name: common.CSIAttacherContainerName, Image: specConfig.MCRKubernetesImageBase + getCSISidecarComponent(common.AzureFileCSIDriverAddonName, common.CSIAttacherContainerName, k8sComponents), CPURequests: "10m", MemoryRequests: "20Mi", CPULimits: "2", MemoryLimits: "2Gi", }, { Name: common.CSILivenessProbeContainerName, Image: specConfig.MCRKubernetesImageBase + getCSISidecarComponent(common.AzureFileCSIDriverAddonName, common.CSILivenessProbeContainerName, k8sComponents), CPURequests: "10m", MemoryRequests: "20Mi", CPULimits: "2", MemoryLimits: "2Gi", }, { Name: common.CSINodeDriverRegistrarContainerName, Image: specConfig.MCRKubernetesImageBase + getCSISidecarComponent(common.AzureFileCSIDriverAddonName, common.CSINodeDriverRegistrarContainerName, k8sComponents), CPURequests: "10m", MemoryRequests: "20Mi", CPULimits: "2", MemoryLimits: "2Gi", }, { Name: common.CSILivenessProbeWindowsContainerName, Image: specConfig.MCRKubernetesImageBase + getCSISidecarComponent(common.AzureFileCSIDriverAddonName, common.CSILivenessProbeWindowsContainerName, k8sComponents), CPURequests: "10m", MemoryRequests: "20Mi", CPULimits: "2", MemoryLimits: "2Gi", }, { Name: common.CSINodeDriverRegistrarWindowsContainerName, Image: specConfig.MCRKubernetesImageBase + getCSISidecarComponent(common.AzureFileCSIDriverAddonName, common.CSINodeDriverRegistrarWindowsContainerName, k8sComponents), CPURequests: "10m", MemoryRequests: "20Mi", CPULimits: "2", MemoryLimits: "2Gi", }, { Name: common.CSISnapshotterContainerName, Image: specConfig.MCRKubernetesImageBase + getCSISidecarComponent(common.AzureFileCSIDriverAddonName, common.CSISnapshotterContainerName, k8sComponents), CPURequests: "10m", MemoryRequests: "20Mi", CPULimits: "2", MemoryLimits: "2Gi", }, { Name: common.CSIResizerContainerName, Image: specConfig.MCRKubernetesImageBase + getCSISidecarComponent(common.AzureFileCSIDriverAddonName, common.CSIResizerContainerName, k8sComponents), CPURequests: "10m", MemoryRequests: "20Mi", CPULimits: "2", MemoryLimits: "2Gi", }, { Name: common.CSIAzureFileContainerName, Image: specConfig.MCRKubernetesImageBase + getCSISidecarComponent(common.AzureFileCSIDriverAddonName, common.CSIAzureFileContainerName, k8sComponents), CPURequests: "10m", MemoryRequests: "20Mi", CPULimits: "2", MemoryLimits: "2Gi", }, }, } defaultKubeDNSAddonsConfig := KubernetesAddon{ Name: common.KubeDNSAddonName, Enabled: to.BoolPtr(DefaultKubeDNSAddonEnabled), Config: map[string]string{ "domain": o.KubernetesConfig.KubeletConfig["--cluster-domain"], "clusterIP": o.KubernetesConfig.DNSServiceIP, }, Containers: []KubernetesContainerSpec{ { Name: "kubedns", Image: kubernetesImageBase + k8sComponents[common.KubeDNSAddonName], }, { Name: common.DNSMasqComponentName, Image: kubernetesImageBase + k8sComponents[common.DNSMasqComponentName], }, { Name: "sidecar", Image: kubernetesImageBase + k8sComponents[common.DNSSidecarComponentName], }, }, } defaultCorednsAddonsConfig := KubernetesAddon{ Name: common.CoreDNSAddonName, Enabled: to.BoolPtr(DefaultCoreDNSAddonEnabled), Config: map[string]string{ "domain": o.KubernetesConfig.KubeletConfig["--cluster-domain"], "clusterIP": o.KubernetesConfig.DNSServiceIP, "cores-per-replica": "512", "nodes-per-replica": "32", "min-replicas": "1", }, Containers: []KubernetesContainerSpec{ { Name: common.CoreDNSAddonName, Image: kubernetesImageBase + k8sComponents[common.CoreDNSAddonName], }, { Name: common.CoreDNSAutoscalerName, Image: k8sComponents[common.CoreDNSAutoscalerName], }, }, } // set host network to true for single stack IPv6 as the the nameserver is currently // IPv4 only. By setting it to host network, we can leverage the host routes to successfully // resolve dns. if cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6Only") { defaultCorednsAddonsConfig.Config["use-host-network"] = "true" } // If we have any explicit coredns or kube-dns configuration in the addons array if getAddonsIndexByName(o.KubernetesConfig.Addons, common.KubeDNSAddonName) != -1 || getAddonsIndexByName(o.KubernetesConfig.Addons, common.CoreDNSAddonName) != -1 { // Ensure we don't we don't prepare an addons spec w/ both kube-dns and coredns enabled if o.KubernetesConfig.IsAddonEnabled(common.KubeDNSAddonName) { defaultCorednsAddonsConfig.Enabled = to.BoolPtr(false) } } defaultKubeProxyAddonsConfig := KubernetesAddon{ Name: common.KubeProxyAddonName, Enabled: to.BoolPtr(DefaultKubeProxyAddonEnabled), Config: map[string]string{ "cluster-cidr": o.KubernetesConfig.ClusterSubnet, "proxy-mode": string(o.KubernetesConfig.ProxyMode), "featureGates": cs.Properties.GetKubeProxyFeatureGates(), }, Containers: []KubernetesContainerSpec{ { Name: common.KubeProxyAddonName, Image: kubernetesImageBase + k8sComponents[common.KubeProxyAddonName] + kubeProxyImageSuffix(*cs), }, }, } // set bind address, healthz and metric bind address to :: explicitly for // single stack IPv6 cluster as it is single stack IPv6 on dual stack host if cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6Only") { defaultKubeProxyAddonsConfig.Config["bind-address"] = "::" defaultKubeProxyAddonsConfig.Config["healthz-bind-address"] = "::" defaultKubeProxyAddonsConfig.Config["metrics-bind-address"] = "::1" } pspAddonEnabled := !common.ShouldDisablePodSecurityPolicyAddon(o.OrchestratorVersion) defaultPodSecurityPolicyAddonsConfig := KubernetesAddon{ Name: common.PodSecurityPolicyAddonName, Enabled: to.BoolPtr(pspAddonEnabled), } defaultAuditPolicyAddonsConfig := KubernetesAddon{ Name: common.AuditPolicyAddonName, Enabled: to.BoolPtr(true), } defaultAzureCloudProviderAddonsConfig := KubernetesAddon{ Name: common.AzureCloudProviderAddonName, Enabled: to.BoolPtr(true), } defaultAADDefaultAdminGroupAddonsConfig := KubernetesAddon{ Name: common.AADAdminGroupAddonName, Enabled: to.BoolPtr(cs.Properties.HasAADAdminGroupID()), Config: map[string]string{ "adminGroupID": cs.Properties.GetAADAdminGroupID(), }, } defaultFlannelAddonsConfig := KubernetesAddon{ Name: common.FlannelAddonName, Enabled: to.BoolPtr(false), Containers: []KubernetesContainerSpec{ { Name: common.KubeFlannelContainerName, Image: k8sComponents[common.KubeFlannelContainerName], }, { Name: common.FlannelInstallCNIContainerName, Image: k8sComponents["flannel"+common.FlannelInstallCNIContainerName], }, }, } defaultScheduledMaintenanceAddonsConfig := KubernetesAddon{ Name: common.ScheduledMaintenanceAddonName, Enabled: to.BoolPtr(false), Containers: []KubernetesContainerSpec{ { Name: common.KubeRBACProxyContainerName, Image: k8sComponents[common.KubeRBACProxyContainerName], }, { Name: common.ScheduledMaintenanceManagerContainerName, Image: k8sComponents[common.ScheduledMaintenanceManagerContainerName], }, }, } defaultSecretsStoreCSIDriverAddonsConfig := KubernetesAddon{ Name: common.SecretsStoreCSIDriverAddonName, Config: map[string]string{ "metricsPort": "8095", "enableSecretRotation": "false", "rotationPollInterval": "2m", }, Enabled: to.BoolPtr(DefaultSecretStoreCSIDriverAddonEnabled && common.IsKubernetesVersionGe(o.OrchestratorVersion, "1.16.0")), Containers: []KubernetesContainerSpec{ { Name: common.CSILivenessProbeContainerName, Image: specConfig.MCRKubernetesImageBase + k8sComponents[common.CSILivenessProbeContainerName], CPURequests: "10m", MemoryRequests: "20Mi", CPULimits: "200m", MemoryLimits: "200Mi", }, { Name: common.CSINodeDriverRegistrarContainerName, Image: specConfig.MCRKubernetesImageBase + k8sComponents[common.CSINodeDriverRegistrarContainerName], CPURequests: "10m", MemoryRequests: "20Mi", CPULimits: "200m", MemoryLimits: "200Mi", }, { Name: common.CSISecretsStoreDriverContainerName, Image: specConfig.MCRKubernetesImageBase + k8sComponents[common.CSISecretsStoreDriverContainerName], CPURequests: "50m", MemoryRequests: "100Mi", CPULimits: "200m", MemoryLimits: "200Mi", }, { Name: common.CSISecretsStoreProviderAzureContainerName, Image: specConfig.MCRKubernetesImageBase + k8sComponents[common.CSISecretsStoreProviderAzureContainerName], CPURequests: "50m", MemoryRequests: "100Mi", CPULimits: "200m", MemoryLimits: "200Mi", }, }, } defaultAzureArcOnboardingAddonsConfig := KubernetesAddon{ Name: common.AzureArcOnboardingAddonName, Enabled: to.BoolPtr(DefaultAzureArcOnboardingAddonEnabled), Containers: []KubernetesContainerSpec{ { Name: common.AzureArcOnboardingAddonName, Image: k8sComponents[common.AzureArcOnboardingAddonName], }, }, } // Allow folks to simply enable kube-dns at cluster creation time without also requiring that coredns be explicitly disabled if !isUpgrade && o.KubernetesConfig.IsAddonEnabled(common.KubeDNSAddonName) { defaultCorednsAddonsConfig.Enabled = to.BoolPtr(false) } defaultAddons := []KubernetesAddon{ defaultTillerAddonsConfig, defaultClusterAutoscalerAddonsConfig, defaultSMBFlexVolumeAddonsConfig, defaultDashboardAddonsConfig, defaultMetricsServerAddonsConfig, defaultNVIDIADevicePluginAddonsConfig, defaultAzureNetworkPolicyAddonsConfig, defaultCloudNodeManagerAddonsConfig, defaultIPMasqAgentAddonsConfig, defaultsCalicoDaemonSetAddonsConfig, defaultsCiliumAddonsConfig, defaultsAADPodIdentityAddonsConfig, defaultAppGwAddonsConfig, defaultAzureDiskCSIDriverAddonsConfig, defaultAzureFileCSIDriverAddonsConfig, defaultsAzurePolicyAddonsConfig, defaultNodeProblemDetectorConfig, defaultKubeDNSAddonsConfig, defaultCorednsAddonsConfig, defaultKubeProxyAddonsConfig, defaultPodSecurityPolicyAddonsConfig, defaultAuditPolicyAddonsConfig, defaultAzureCloudProviderAddonsConfig, defaultAADDefaultAdminGroupAddonsConfig, defaultsAntreaDaemonSetAddonsConfig, defaultFlannelAddonsConfig, defaultScheduledMaintenanceAddonsConfig, defaultSecretsStoreCSIDriverAddonsConfig, defaultAzureArcOnboardingAddonsConfig, } // Add default addons specification, if no user-provided spec exists if o.KubernetesConfig.Addons == nil { o.KubernetesConfig.Addons = defaultAddons } else { for _, addon := range defaultAddons { o.KubernetesConfig.Addons = appendAddonIfNotPresent(o.KubernetesConfig.Addons, addon) } } // Ensure cloud-node-manager and CSI components are enabled on appropriate upgrades if isUpgrade && cs.Properties.ShouldEnableAzureCloudAddon(common.AzureDiskCSIDriverAddonName) && cs.Properties.ShouldEnableAzureCloudAddon(common.AzureFileCSIDriverAddonName) && cs.Properties.ShouldEnableAzureCloudAddon(common.CloudNodeManagerAddonName) { componentry := map[string]KubernetesAddon{ common.AzureDiskCSIDriverAddonName: defaultAzureDiskCSIDriverAddonsConfig, common.AzureFileCSIDriverAddonName: defaultAzureFileCSIDriverAddonsConfig, common.CloudNodeManagerAddonName: defaultCloudNodeManagerAddonsConfig, } for name, config := range componentry { if i := getAddonsIndexByName(o.KubernetesConfig.Addons, name); i > -1 { if !to.Bool(o.KubernetesConfig.Addons[i].Enabled) { o.KubernetesConfig.Addons[i] = config } } } } // Ensure cloud-node-manager is enabled on appropriate upgrades for Azure Stack cloud if isUpgrade && cs.Properties.IsAzureStackCloud() && to.Bool(cs.Properties.OrchestratorProfile.KubernetesConfig.UseCloudControllerManager) { // Force enabling cloud-node-manager addon if i := getAddonsIndexByName(o.KubernetesConfig.Addons, common.CloudNodeManagerAddonName); i > -1 { o.KubernetesConfig.Addons[i] = defaultCloudNodeManagerAddonsConfig } } // Back-compat for older addon specs of cluster-autoscaler if isUpgrade { i := getAddonsIndexByName(o.KubernetesConfig.Addons, common.ClusterAutoscalerAddonName) if i > -1 && to.Bool(o.KubernetesConfig.Addons[i].Enabled) { if o.KubernetesConfig.Addons[i].Pools == nil { log.Warnf("This cluster upgrade operation will enable the per-pool cluster-autoscaler addon.\n") var pools []AddonNodePoolsConfig for i, p := range cs.Properties.AgentPoolProfiles { pool := AddonNodePoolsConfig{ Name: p.Name, Config: map[string]string{ "min-nodes": strconv.Itoa(p.Count), "max-nodes": strconv.Itoa(p.Count), }, } if i == 0 { originalMinNodes := o.KubernetesConfig.Addons[i].Config["min-nodes"] originalMaxNodes := o.KubernetesConfig.Addons[i].Config["max-nodes"] if originalMinNodes != "" { pool.Config["min-nodes"] = originalMinNodes delete(o.KubernetesConfig.Addons[i].Config, "min-nodes") } if originalMaxNodes != "" { pool.Config["max-nodes"] = originalMaxNodes delete(o.KubernetesConfig.Addons[i].Config, "max-nodes") } } log.Warnf("cluster-autoscaler will configure pool \"%s\" with min-nodes=%s, and max-nodes=%s.\n", pool.Name, pool.Config["min-nodes"], pool.Config["max-nodes"]) pools = append(pools, pool) } o.KubernetesConfig.Addons[i].Pools = pools log.Warnf("You may modify the pool configurations via `kubectl edit deployment cluster-autoscaler -n kube-system`.\n") log.Warnf("Look for the `--nodes=` configuration flags (see below) in the deployment spec:\n") log.Warnf("\n%s", GetClusterAutoscalerNodesConfig(o.KubernetesConfig.Addons[i], cs)) } } } // Back-compat for pre-1.12 clusters built before kube-dns and coredns were converted to user-configurable addons // Migrate to coredns unless coredns is explicitly set to false if isUpgrade && common.IsKubernetesVersionGe(o.OrchestratorVersion, "1.12.0") { // If we don't have coredns in our addons array at all, this means we're in a legacy scenario and we want to migrate from kube-dns to coredns if i := getAddonsIndexByName(o.KubernetesConfig.Addons, common.CoreDNSAddonName); i == -1 { o.KubernetesConfig.Addons[i].Enabled = to.BoolPtr(true) // Ensure we don't we don't prepare an addons spec w/ both kube-dns and coredns enabled if j := getAddonsIndexByName(o.KubernetesConfig.Addons, common.KubeDNSAddonName); j > -1 { o.KubernetesConfig.Addons[j].Enabled = to.BoolPtr(false) } } } // Deal with legacy Azure CNI networkmonitor addon configuration if isUpgrade { // Force disabling of the deprecated Azure CNI networkmonitor addon if i := getAddonsIndexByName(o.KubernetesConfig.Addons, common.AzureCNINetworkMonitorAddonName); i > -1 { o.KubernetesConfig.Addons[i].Enabled = to.BoolPtr(false) } } // Honor customKubeProxyImage field if o.KubernetesConfig.CustomKubeProxyImage != "" { if i := getAddonsIndexByName(o.KubernetesConfig.Addons, common.KubeProxyAddonName); i > -1 { o.KubernetesConfig.Addons[i].Containers[0].Image = o.KubernetesConfig.CustomKubeProxyImage } } for _, addon := range defaultAddons { synthesizeAddonsConfig(o.KubernetesConfig.Addons, addon, isUpgrade) } if len(o.KubernetesConfig.PodSecurityPolicyConfig) > 0 && isUpgrade { if base64Data, ok := o.KubernetesConfig.PodSecurityPolicyConfig["data"]; ok { if i := getAddonsIndexByName(o.KubernetesConfig.Addons, common.PodSecurityPolicyAddonName); i > -1 { if o.KubernetesConfig.Addons[i].Data == "" { o.KubernetesConfig.Addons[i].Data = base64Data } } } } // Specific back-compat business logic for calico addon // Ensure addon is set to Enabled w/ proper containers config no matter what if NetworkPolicy == calico i := getAddonsIndexByName(o.KubernetesConfig.Addons, common.CalicoAddonName) if isUpgrade && o.KubernetesConfig.NetworkPolicy == NetworkPolicyCalico && i > -1 && o.KubernetesConfig.Addons[i].Enabled != to.BoolPtr(true) { j := getAddonsIndexByName(defaultAddons, common.CalicoAddonName) // Ensure calico is statically set to enabled o.KubernetesConfig.Addons[i].Enabled = to.BoolPtr(true) // Assume addon configuration was pruned due to an inherited enabled=false, so re-apply default values o.KubernetesConfig.Addons[i] = assignDefaultAddonVals(o.KubernetesConfig.Addons[i], defaultAddons[j], isUpgrade) } // Support back-compat configuration for Azure NetworkPolicy, which no longer ships with a "telemetry" container starting w/ 1.16.0 if isUpgrade && o.KubernetesConfig.NetworkPolicy == NetworkPolicyAzure && common.IsKubernetesVersionGe(o.OrchestratorVersion, "1.16.0") { i = getAddonsIndexByName(o.KubernetesConfig.Addons, common.AzureNetworkPolicyAddonName) var hasTelemetryContainerConfig bool var prunedContainersConfig []KubernetesContainerSpec if i > -1 { for _, c := range o.KubernetesConfig.Addons[i].Containers { if c.Name == common.AzureVnetTelemetryContainerName { hasTelemetryContainerConfig = true } else { prunedContainersConfig = append(prunedContainersConfig, c) } } if hasTelemetryContainerConfig { o.KubernetesConfig.Addons[i].Containers = prunedContainersConfig } } } // Specific back-compat business logic for deprecated "kube-proxy-daemonset" addon if i := getAddonsIndexByName(o.KubernetesConfig.Addons, "kube-proxy-daemonset"); i > -1 { if to.Bool(o.KubernetesConfig.Addons[i].Enabled) { if j := getAddonsIndexByName(o.KubernetesConfig.Addons, common.KubeProxyAddonName); j > -1 { // Copy data from deprecated addon spec to the current "kube-proxy" addon o.KubernetesConfig.Addons[j] = KubernetesAddon{ Name: common.KubeProxyAddonName, Enabled: to.BoolPtr(true), Data: o.KubernetesConfig.Addons[i].Data, } } } // Remove deprecated "kube-proxy-daemonset addon" o.KubernetesConfig.Addons = append(o.KubernetesConfig.Addons[:i], o.KubernetesConfig.Addons[i+1:]...) } // Enable pod-security-policy addon during upgrade scenarios, unless explicitly disabled or v1.25+ if common.ShouldDisablePodSecurityPolicyAddon(o.OrchestratorVersion) { if i := getAddonsIndexByName(o.KubernetesConfig.Addons, common.PodSecurityPolicyAddonName); i > -1 { o.KubernetesConfig.Addons[i].Enabled = to.BoolPtr(false) } } else if isUpgrade && !o.KubernetesConfig.IsAddonDisabled(common.PodSecurityPolicyAddonName) { if i := getAddonsIndexByName(o.KubernetesConfig.Addons, common.PodSecurityPolicyAddonName); i > -1 { o.KubernetesConfig.Addons[i].Enabled = to.BoolPtr(true) } } } func appendAddonIfNotPresent(addons []KubernetesAddon, addon KubernetesAddon) []KubernetesAddon { i := getAddonsIndexByName(addons, addon.Name) if i < 0 { return append(addons, addon) } return addons } func getAddonsIndexByName(addons []KubernetesAddon, name string) int { for i := range addons { if addons[i].Name == name { return i } } return -1 } // assignDefaultAddonVals will assign default values to addon from defaults, for each property in addon that has a zero value func assignDefaultAddonVals(addon, defaults KubernetesAddon, isUpgrade bool) KubernetesAddon { if addon.Enabled == nil { addon.Enabled = defaults.Enabled } if !to.Bool(addon.Enabled) { return KubernetesAddon{ Name: addon.Name, Enabled: addon.Enabled, } } if addon.Data != "" { return KubernetesAddon{ Name: addon.Name, Enabled: addon.Enabled, Data: addon.Data, } } if addon.Mode == "" { addon.Mode = defaults.Mode } for i := range defaults.Containers { c := addon.GetAddonContainersIndexByName(defaults.Containers[i].Name) if c < 0 { addon.Containers = append(addon.Containers, defaults.Containers[i]) } else { if addon.Containers[c].Image == "" || isUpgrade { addon.Containers[c].Image = defaults.Containers[i].Image } if addon.Containers[c].CPURequests == "" { addon.Containers[c].CPURequests = defaults.Containers[i].CPURequests } if addon.Containers[c].MemoryRequests == "" { addon.Containers[c].MemoryRequests = defaults.Containers[i].MemoryRequests } if addon.Containers[c].CPULimits == "" { addon.Containers[c].CPULimits = defaults.Containers[i].CPULimits } if addon.Containers[c].MemoryLimits == "" { addon.Containers[c].MemoryLimits = defaults.Containers[i].MemoryLimits } } } // For pools-specific configuration, we only take the defaults if we have zero user-provided pools configuration if len(addon.Pools) == 0 { addon.Pools = append(addon.Pools, defaults.Pools...) } for key, val := range defaults.Config { if addon.Config == nil { addon.Config = make(map[string]string) } if v, ok := addon.Config[key]; !ok || v == "" { addon.Config[key] = val } } return addon } func synthesizeAddonsConfig(addons []KubernetesAddon, addon KubernetesAddon, isUpgrade bool) { i := getAddonsIndexByName(addons, addon.Name) if i >= 0 { addons[i] = assignDefaultAddonVals(addons[i], addon, isUpgrade) } } func makeDefaultClusterAutoscalerAddonPoolsConfig(cs *ContainerService) []AddonNodePoolsConfig { var ret []AddonNodePoolsConfig for _, pool := range cs.Properties.AgentPoolProfiles { ret = append(ret, AddonNodePoolsConfig{ Name: pool.Name, Config: map[string]string{ "min-nodes": strconv.Itoa(pool.Count), "max-nodes": strconv.Itoa(pool.Count), }, }) } return ret } // GetClusterAutoscalerNodesConfig returns the cluster-autoscaler runtime configuration flag for a nodepool func GetClusterAutoscalerNodesConfig(addon KubernetesAddon, cs *ContainerService) string { var ret string for _, pool := range addon.Pools { nodepoolName := cs.Properties.GetAgentVMPrefix(cs.Properties.GetAgentPoolByName(pool.Name), cs.Properties.GetAgentPoolIndexByName(pool.Name)) ret += fmt.Sprintf(" - --nodes=%s:%s:%s\n", pool.Config["min-nodes"], pool.Config["max-nodes"], nodepoolName) } if ret != "" { ret = strings.TrimRight(ret, "\n") } return ret } func getCSISidecarComponent(csiDriverName, csiSidecarName string, k8sComponents map[string]string) string { if _, ok := csiSidecarComponentsOverrides[csiDriverName]; ok { if c, ok := csiSidecarComponentsOverrides[csiDriverName][csiSidecarName]; ok { return c } } return k8sComponents[csiSidecarName] } // kubeProxyImageSuffix returns '-azs' if target cloud is Azure Stack and Kubernetes version is lower than v1.16.0. // Otherwise, it returns empty string. // Azure Stack needs the '-azs' suffix so kube-proxy's manifests uses the custom hyperkube image present in the VHD func kubeProxyImageSuffix(cs ContainerService) string { if cs.Properties.IsAzureStackCloud() && !common.IsKubernetesVersionGe(cs.Properties.OrchestratorProfile.OrchestratorVersion, "1.21.0") { return common.AzureStackSuffix } return "" }