pkg/api/defaults.go (1,041 lines of code) (raw):

// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. package api import ( "crypto/rand" "encoding/base64" "encoding/binary" "fmt" "net" "sort" "strconv" "strings" compute "github.com/Azure/azure-sdk-for-go/profile/p20200901/resourcemanager/compute/armcompute" "github.com/pkg/errors" log "github.com/sirupsen/logrus" "github.com/Azure/aks-engine-azurestack/pkg/api/common" "github.com/Azure/aks-engine-azurestack/pkg/helpers" "github.com/Azure/aks-engine-azurestack/pkg/helpers/to" "github.com/Azure/aks-engine-azurestack/pkg/versions" ) // DistroValues is a list of currently supported distros var DistroValues = []Distro{"", Ubuntu, Ubuntu1804, Ubuntu2004, Ubuntu2204, Flatcar, AKSUbuntu1604, AKSUbuntu1804, Ubuntu1804Gen2, AKSUbuntu2004, AKSUbuntu2204, ACC1604} // PropertiesDefaultsParams is the parameters when we set the properties defaults for ContainerService. type PropertiesDefaultsParams struct { IsUpgrade bool IsScale bool PkiKeySize int } // SetPropertiesDefaults for the container Properties, returns true if certs are generated func (cs *ContainerService) SetPropertiesDefaults(params PropertiesDefaultsParams) (bool, error) { properties := cs.Properties // Set custom cloud profile defaults if this cluster configuration has custom cloud profile if cs.Properties.IsCustomCloudProfile() { err := cs.setCustomCloudProfileDefaults(CustomCloudProfileDefaultsParams{ IsUpgrade: params.IsUpgrade, IsScale: params.IsScale, }) if err != nil { return false, err } } // Set master profile defaults if this cluster configuration includes master node(s) if cs.Properties.MasterProfile != nil { properties.setMasterProfileDefaults() } properties.setAgentProfileDefaults(params.IsUpgrade, params.IsScale) properties.setStorageDefaults() cs.setOrchestratorDefaults(params.IsUpgrade, params.IsScale) // Set Linux profile defaults if this cluster configuration includes Linux nodes if cs.Properties.LinuxProfile != nil { properties.setLinuxProfileDefaults() } properties.setExtensionDefaults() if cs.Properties.WindowsProfile != nil { cs.setWindowsProfileDefaults(params.IsUpgrade, params.IsScale) cs.setCSIProxyDefaults() } properties.setTelemetryProfileDefaults() certsGenerated, _, e := cs.SetDefaultCerts(DefaultCertParams{ PkiKeySize: params.PkiKeySize, }) if e != nil { return false, e } return certsGenerated, nil } // setOrchestratorDefaults for orchestrators func (cs *ContainerService) setOrchestratorDefaults(isUpgrade, isScale bool) { isUpdate := isUpgrade || isScale a := cs.Properties cloudSpecConfig := cs.GetCloudSpecConfig() if a.OrchestratorProfile == nil { a.OrchestratorProfile = &OrchestratorProfile{ OrchestratorType: Kubernetes, } } o := a.OrchestratorProfile o.OrchestratorVersion = common.GetValidPatchVersion( o.OrchestratorType, o.OrchestratorVersion, isUpdate, a.HasWindows(), a.IsAzureStackCloud()) switch o.OrchestratorType { case Kubernetes: if o.KubernetesConfig == nil { o.KubernetesConfig = &KubernetesConfig{} } // For backwards compatibility with original, overloaded "NetworkPolicy" config vector // we translate deprecated NetworkPolicy usage to the NetworkConfig equivalent // and set a default network policy enforcement configuration switch o.KubernetesConfig.NetworkPolicy { case NetworkPolicyAzure: if o.KubernetesConfig.NetworkPlugin == "" { o.KubernetesConfig.NetworkPlugin = NetworkPluginAzure o.KubernetesConfig.NetworkPolicy = DefaultNetworkPolicy } case NetworkPolicyNone: o.KubernetesConfig.NetworkPlugin = NetworkPluginKubenet o.KubernetesConfig.NetworkPolicy = DefaultNetworkPolicy case NetworkPolicyCalico: if o.KubernetesConfig.NetworkPlugin == "" { // If not specified, then set the network plugin to be kubenet // for backwards compatibility. Otherwise, use what is specified. o.KubernetesConfig.NetworkPlugin = NetworkPluginKubenet } case NetworkPolicyCilium: o.KubernetesConfig.NetworkPlugin = NetworkPluginCilium case NetworkPolicyAntrea: if o.KubernetesConfig.NetworkPlugin == "" { o.KubernetesConfig.NetworkPlugin = NetworkPluginAzure } } if a.IsAzureStackCloud() { // Azure Stack's custom hyperkube image is now hosted along with MCR images. // Forcing KubernetesImageBase/KubernetesImageBaseType. mcrKubernetesImageBase := cloudSpecConfig.KubernetesSpecConfig.MCRKubernetesImageBase if !strings.EqualFold(o.KubernetesConfig.KubernetesImageBase, mcrKubernetesImageBase) { log.Warnf("apimodel: orchestratorProfile.kubernetesConfig.kubernetesImageBase forced to \"%s\"\n", mcrKubernetesImageBase) } o.KubernetesConfig.KubernetesImageBase = cloudSpecConfig.KubernetesSpecConfig.MCRKubernetesImageBase if !strings.EqualFold(o.KubernetesConfig.KubernetesImageBaseType, common.KubernetesImageBaseTypeMCR) { log.Warnf("apimodel: orchestratorProfile.kubernetesConfig.kubernetesImageBaseType forced to \"%s\"\n", common.KubernetesImageBaseTypeMCR) } o.KubernetesConfig.KubernetesImageBaseType = common.KubernetesImageBaseTypeMCR if isUpgrade && strings.EqualFold(o.KubernetesConfig.MCRKubernetesImageBase, "mcr.microsoft.com/k8s/core/") { log.Warn("apimodel: clearing deprecated orchestratorProfile.kubernetesConfig.mcrKubernetesImageBase value\n") o.KubernetesConfig.MCRKubernetesImageBase = "" } } if isUpgrade { if (o.KubernetesConfig.KubernetesImageBase == "" || o.KubernetesConfig.KubernetesImageBase == cloudSpecConfig.KubernetesSpecConfig.KubernetesImageBase) && (o.KubernetesConfig.KubernetesImageBaseType == "" || o.KubernetesConfig.KubernetesImageBaseType == common.KubernetesImageBaseTypeGCR) { o.KubernetesConfig.KubernetesImageBase = cloudSpecConfig.KubernetesSpecConfig.MCRKubernetesImageBase o.KubernetesConfig.KubernetesImageBaseType = common.KubernetesImageBaseTypeMCR } } if o.KubernetesConfig.KubernetesImageBase == "" { o.KubernetesConfig.KubernetesImageBase = cloudSpecConfig.KubernetesSpecConfig.MCRKubernetesImageBase } else { if o.KubernetesConfig.KubernetesImageBase[len(o.KubernetesConfig.KubernetesImageBase)-1:] != "/" { o.KubernetesConfig.KubernetesImageBase += "/" } } if o.KubernetesConfig.KubernetesImageBaseType == "" { o.KubernetesConfig.KubernetesImageBaseType = common.KubernetesImageBaseTypeMCR } if o.KubernetesConfig.MCRKubernetesImageBase == "" { o.KubernetesConfig.MCRKubernetesImageBase = cloudSpecConfig.KubernetesSpecConfig.MCRKubernetesImageBase } if o.KubernetesConfig.EtcdVersion == "" { o.KubernetesConfig.EtcdVersion = DefaultEtcdVersion } else if isUpgrade { if o.KubernetesConfig.EtcdVersion != DefaultEtcdVersion { // Override (i.e., upgrade) the etcd version if the default is newer in an upgrade scenario if common.GetMinVersion([]string{o.KubernetesConfig.EtcdVersion, DefaultEtcdVersion}, true) == o.KubernetesConfig.EtcdVersion { log.Warnf("etcd will be upgraded to version %s\n", DefaultEtcdVersion) o.KubernetesConfig.EtcdVersion = DefaultEtcdVersion } } } if !isUpgrade && !isScale && !cs.Properties.IsCustomCloudProfile() && !cs.Properties.MasterProfile.IsVirtualMachineScaleSets() && o.KubernetesConfig.UseManagedIdentity == nil { o.KubernetesConfig.UseManagedIdentity = to.BoolPtr(true) } if a.HasWindows() { if o.KubernetesConfig.NetworkPlugin == "" { o.KubernetesConfig.NetworkPlugin = DefaultNetworkPluginWindows } } else { if o.KubernetesConfig.NetworkPlugin == "" { o.KubernetesConfig.NetworkPlugin = DefaultNetworkPlugin } } if o.KubernetesConfig.NetworkPlugin == NetworkPluginAzure { if o.KubernetesConfig.NetworkMode == "" { o.KubernetesConfig.NetworkMode = NetworkModeTransparent } } if o.KubernetesConfig.ContainerRuntime == "" { o.KubernetesConfig.ContainerRuntime = DefaultContainerRuntime if a.IsAzureStackCloud() && common.IsKubernetesVersionGe(o.OrchestratorVersion, "1.24.0") { log.Warnf("The docker runtime is no longer supported for v1.24+ clusters, setting ContainerRuntime to 'containerd'") o.KubernetesConfig.ContainerRuntime = Containerd } } switch o.KubernetesConfig.ContainerRuntime { case Docker: if o.KubernetesConfig.MobyVersion == "" || isUpdate { if o.KubernetesConfig.MobyVersion != DefaultMobyVersion { if isUpgrade { log.Warnf("Moby will be upgraded to version %s\n", DefaultMobyVersion) } else if isScale { log.Warnf("Any new nodes will have Moby version %s\n", DefaultMobyVersion) } } o.KubernetesConfig.MobyVersion = DefaultMobyVersion } // Moby versions >= 19.03 depend on containerd packaging (instead of the moby packages supplying their own containerd) // For that case we'll need to specify the containerd version. if versions.GreaterThanOrEqualTo(o.KubernetesConfig.MobyVersion, "19.03") && (o.KubernetesConfig.ContainerdVersion == "" || isUpdate) { if o.KubernetesConfig.ContainerdVersion != DefaultContainerdVersion { if isUpgrade { log.Warnf("containerd will be upgraded to version %s\n", DefaultContainerdVersion) } if isScale { log.Warnf("Any new nodes will have containerd version %s\n", DefaultContainerdVersion) } } o.KubernetesConfig.ContainerdVersion = DefaultContainerdVersion } case Containerd: if o.KubernetesConfig.ContainerdVersion == "" || isUpdate { if o.KubernetesConfig.ContainerdVersion != DefaultContainerdVersion { if isUpgrade { log.Warnf("containerd will be upgraded to version %s\n", DefaultContainerdVersion) } else if isScale { log.Warnf("Any new nodes will have containerd version %s\n", DefaultContainerdVersion) } } o.KubernetesConfig.ContainerdVersion = DefaultContainerdVersion } if o.KubernetesConfig.WindowsContainerdURL == "" || isUpdate { o.KubernetesConfig.WindowsContainerdURL = DefaultWindowsContainerdURL } } if o.KubernetesConfig.ClusterSubnet == "" { if o.IsAzureCNI() { // When Azure CNI is enabled, all masters, agents and pods share the same large subnet. // Except when master is VMSS, then masters and agents have separate subnets within the same large subnet. o.KubernetesConfig.ClusterSubnet = DefaultKubernetesSubnet if cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6DualStack") { o.KubernetesConfig.ClusterSubnet = strings.Join([]string{DefaultKubernetesSubnet, cs.getDefaultKubernetesClusterSubnetIPv6()}, ",") } } else { o.KubernetesConfig.ClusterSubnet = DefaultKubernetesClusterSubnet // ipv6 only cluster if cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6Only") { o.KubernetesConfig.ClusterSubnet = DefaultKubernetesClusterSubnetIPv6 } // ipv4 and ipv6 subnet for dual stack if cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6DualStack") { o.KubernetesConfig.ClusterSubnet = strings.Join([]string{DefaultKubernetesClusterSubnet, cs.getDefaultKubernetesClusterSubnetIPv6()}, ",") } } } else { // ensure 2 subnets exists if ipv6 dual stack feature is enabled if cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6DualStack") { clusterSubnets := strings.Split(o.KubernetesConfig.ClusterSubnet, ",") if len(clusterSubnets) == 1 { // if error exists, then it'll be caught by validate ip, _, err := net.ParseCIDR(clusterSubnets[0]) if err == nil { if ip.To4() != nil { // the first cidr block is ipv4, so append ipv6 clusterSubnets = append(clusterSubnets, cs.getDefaultKubernetesClusterSubnetIPv6()) } else { // first cidr has to be ipv4 if o.IsAzureCNI() { clusterSubnets = append([]string{DefaultKubernetesSubnet}, clusterSubnets...) } else { clusterSubnets = append([]string{DefaultKubernetesClusterSubnet}, clusterSubnets...) } } // only set the cluster subnet if no error has been encountered } o.KubernetesConfig.ClusterSubnet = strings.Join(clusterSubnets, ",") } } } if o.KubernetesConfig.GCHighThreshold == 0 { o.KubernetesConfig.GCHighThreshold = DefaultKubernetesGCHighThreshold } if o.KubernetesConfig.GCLowThreshold == 0 { o.KubernetesConfig.GCLowThreshold = DefaultKubernetesGCLowThreshold } if o.KubernetesConfig.DNSServiceIP == "" { o.KubernetesConfig.DNSServiceIP = DefaultKubernetesDNSServiceIP if cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6Only") { o.KubernetesConfig.DNSServiceIP = DefaultKubernetesDNSServiceIPv6 } } if o.KubernetesConfig.DockerBridgeSubnet == "" { o.KubernetesConfig.DockerBridgeSubnet = DefaultDockerBridgeSubnet } if o.KubernetesConfig.ServiceCIDR == "" { o.KubernetesConfig.ServiceCIDR = DefaultKubernetesServiceCIDR if cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6Only") { o.KubernetesConfig.ServiceCIDR = DefaultKubernetesServiceCIDRIPv6 } if cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6DualStack") { o.KubernetesConfig.ServiceCIDR = strings.Join([]string{DefaultKubernetesServiceCIDR, DefaultKubernetesServiceCIDRIPv6}, ",") } } else { if cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6DualStack") { serviceAddrs := strings.Split(o.KubernetesConfig.ServiceCIDR, ",") if len(serviceAddrs) == 1 { ip, _, err := net.ParseCIDR(serviceAddrs[0]) if err == nil { if ip.To4() != nil { // the first cidr block is ipv4, so append ipv6 serviceAddrs = append(serviceAddrs, DefaultKubernetesServiceCIDRIPv6) } else { // first cidr has to be ipv4 serviceAddrs = append([]string{DefaultKubernetesServiceCIDR}, serviceAddrs...) } } o.KubernetesConfig.ServiceCIDR = strings.Join(serviceAddrs, ",") } } } if common.IsKubernetesVersionGe(o.OrchestratorVersion, "1.14.0") { o.KubernetesConfig.CloudProviderBackoffMode = CloudProviderBackoffModeV2 if o.KubernetesConfig.CloudProviderBackoff == nil { o.KubernetesConfig.CloudProviderBackoff = to.BoolPtr(true) } } else { o.KubernetesConfig.CloudProviderBackoffMode = "v1" if o.KubernetesConfig.CloudProviderBackoff == nil { o.KubernetesConfig.CloudProviderBackoff = to.BoolPtr(false) } } // Enforce sane cloudprovider backoff defaults. a.SetCloudProviderBackoffDefaults() if o.KubernetesConfig.CloudProviderRateLimit == nil { o.KubernetesConfig.CloudProviderRateLimit = to.BoolPtr(DefaultKubernetesCloudProviderRateLimit) } // Enforce sane cloudprovider rate limit defaults. a.SetCloudProviderRateLimitDefaults() if o.KubernetesConfig.PrivateCluster == nil { o.KubernetesConfig.PrivateCluster = &PrivateCluster{} } if o.KubernetesConfig.PrivateCluster.Enabled == nil { o.KubernetesConfig.PrivateCluster.Enabled = to.BoolPtr(DefaultPrivateClusterEnabled) } if o.KubernetesConfig.PrivateCluster.EnableHostsConfigAgent == nil { o.KubernetesConfig.PrivateCluster.EnableHostsConfigAgent = to.BoolPtr(DefaultPrivateClusterHostsConfigAgentEnabled) } if "" == a.OrchestratorProfile.KubernetesConfig.EtcdDiskSizeGB { switch { case a.TotalNodes() > 20: if a.IsAzureStackCloud() { // Currently on Azure Stack max size of managed disk size is 1023GB. a.OrchestratorProfile.KubernetesConfig.EtcdDiskSizeGB = MaxAzureStackManagedDiskSize } else { a.OrchestratorProfile.KubernetesConfig.EtcdDiskSizeGB = DefaultEtcdDiskSizeGT20Nodes } case a.TotalNodes() > 10: if a.IsAzureStackCloud() { // Currently on Azure Stack max size of managed disk size is 1023GB. a.OrchestratorProfile.KubernetesConfig.EtcdDiskSizeGB = MaxAzureStackManagedDiskSize } else { a.OrchestratorProfile.KubernetesConfig.EtcdDiskSizeGB = DefaultEtcdDiskSizeGT10Nodes } case a.TotalNodes() > 3: a.OrchestratorProfile.KubernetesConfig.EtcdDiskSizeGB = DefaultEtcdDiskSizeGT3Nodes default: a.OrchestratorProfile.KubernetesConfig.EtcdDiskSizeGB = DefaultEtcdDiskSize } } if a.OrchestratorProfile.KubernetesConfig.EtcdStorageLimitGB == 0 { a.OrchestratorProfile.KubernetesConfig.EtcdStorageLimitGB = DefaultEtcdStorageLimitGB } if to.Bool(o.KubernetesConfig.EnableDataEncryptionAtRest) { if "" == a.OrchestratorProfile.KubernetesConfig.EtcdEncryptionKey { a.OrchestratorProfile.KubernetesConfig.EtcdEncryptionKey = generateEtcdEncryptionKey() } } if a.OrchestratorProfile.KubernetesConfig.PrivateJumpboxProvision() && a.OrchestratorProfile.KubernetesConfig.PrivateCluster.JumpboxProfile.OSDiskSizeGB == 0 { a.OrchestratorProfile.KubernetesConfig.PrivateCluster.JumpboxProfile.OSDiskSizeGB = DefaultJumpboxDiskSize } if a.OrchestratorProfile.KubernetesConfig.PrivateJumpboxProvision() && a.OrchestratorProfile.KubernetesConfig.PrivateCluster.JumpboxProfile.Username == "" { a.OrchestratorProfile.KubernetesConfig.PrivateCluster.JumpboxProfile.Username = DefaultJumpboxUsername } if a.OrchestratorProfile.KubernetesConfig.PrivateJumpboxProvision() && a.OrchestratorProfile.KubernetesConfig.PrivateCluster.JumpboxProfile.StorageProfile == "" { a.OrchestratorProfile.KubernetesConfig.PrivateCluster.JumpboxProfile.StorageProfile = ManagedDisks } if a.OrchestratorProfile.KubernetesConfig.EnableRbac == nil { a.OrchestratorProfile.KubernetesConfig.EnableRbac = to.BoolPtr(DefaultRBACEnabled) } if a.OrchestratorProfile.KubernetesConfig.MicrosoftAptRepositoryURL == "" { a.OrchestratorProfile.KubernetesConfig.MicrosoftAptRepositoryURL = DefaultMicrosoftAptRepositoryURL } // Upgrade scenario: // We need to force set EnableRbac to true for upgrades to 1.15.0 and greater if it was previously set to false (AKS Engine only) if !a.OrchestratorProfile.KubernetesConfig.IsRBACEnabled() && common.IsKubernetesVersionGe(o.OrchestratorVersion, "1.15.0") && isUpgrade { log.Warnf("RBAC will be enabled during upgrade to version %s\n", o.OrchestratorVersion) a.OrchestratorProfile.KubernetesConfig.EnableRbac = to.BoolPtr(true) } if a.OrchestratorProfile.KubernetesConfig.IsRBACEnabled() { a.OrchestratorProfile.KubernetesConfig.EnableAggregatedAPIs = true } else if isUpdate && a.OrchestratorProfile.KubernetesConfig.EnableAggregatedAPIs { // Upgrade scenario: // We need to force set EnableAggregatedAPIs to false if RBAC was previously disabled a.OrchestratorProfile.KubernetesConfig.EnableAggregatedAPIs = false } if a.OrchestratorProfile.KubernetesConfig.EnableSecureKubelet == nil { a.OrchestratorProfile.KubernetesConfig.EnableSecureKubelet = to.BoolPtr(DefaultSecureKubeletEnabled) } if a.OrchestratorProfile.KubernetesConfig.UseInstanceMetadata == nil { if a.IsAzureStackCloud() { a.OrchestratorProfile.KubernetesConfig.UseInstanceMetadata = to.BoolPtr(DefaultAzureStackUseInstanceMetadata) } else { a.OrchestratorProfile.KubernetesConfig.UseInstanceMetadata = to.BoolPtr(DefaultUseInstanceMetadata) } } if a.IsAzureStackCloud() && a.OrchestratorProfile.KubernetesConfig.LoadBalancerSku != DefaultAzureStackLoadBalancerSku { if a.OrchestratorProfile.KubernetesConfig.LoadBalancerSku != "" { log.Warnf("apimodel: orchestratorProfile.kubernetesConfig.LoadBalancerSku forced to \"%s\"\n", DefaultAzureStackLoadBalancerSku) } a.OrchestratorProfile.KubernetesConfig.LoadBalancerSku = DefaultAzureStackLoadBalancerSku } else if a.OrchestratorProfile.KubernetesConfig.LoadBalancerSku == "" { a.OrchestratorProfile.KubernetesConfig.LoadBalancerSku = StandardLoadBalancerSku } if strings.EqualFold(a.OrchestratorProfile.KubernetesConfig.LoadBalancerSku, BasicLoadBalancerSku) { a.OrchestratorProfile.KubernetesConfig.LoadBalancerSku = BasicLoadBalancerSku } else if strings.EqualFold(a.OrchestratorProfile.KubernetesConfig.LoadBalancerSku, StandardLoadBalancerSku) { a.OrchestratorProfile.KubernetesConfig.LoadBalancerSku = StandardLoadBalancerSku } if a.OrchestratorProfile.KubernetesConfig.LoadBalancerSku == StandardLoadBalancerSku && a.OrchestratorProfile.KubernetesConfig.ExcludeMasterFromStandardLB == nil { a.OrchestratorProfile.KubernetesConfig.ExcludeMasterFromStandardLB = to.BoolPtr(DefaultExcludeMasterFromStandardLB) } if a.OrchestratorProfile.IsAzureCNI() { if a.HasWindows() { a.OrchestratorProfile.KubernetesConfig.AzureCNIVersion = AzureCniPluginVerWindows } else { a.OrchestratorProfile.KubernetesConfig.AzureCNIVersion = AzureCniPluginVerLinux } } if a.OrchestratorProfile.KubernetesConfig.MaximumLoadBalancerRuleCount == 0 { a.OrchestratorProfile.KubernetesConfig.MaximumLoadBalancerRuleCount = DefaultMaximumLoadBalancerRuleCount } if a.OrchestratorProfile.KubernetesConfig.ProxyMode == "" { a.OrchestratorProfile.KubernetesConfig.ProxyMode = DefaultKubeProxyMode } if a.OrchestratorProfile.KubernetesConfig.LoadBalancerSku == StandardLoadBalancerSku && a.OrchestratorProfile.KubernetesConfig.OutboundRuleIdleTimeoutInMinutes == 0 { a.OrchestratorProfile.KubernetesConfig.OutboundRuleIdleTimeoutInMinutes = DefaultOutboundRuleIdleTimeoutInMinutes } if o.KubernetesConfig.LoadBalancerSku == StandardLoadBalancerSku { if o.KubernetesConfig.CloudProviderDisableOutboundSNAT == nil { o.KubernetesConfig.CloudProviderDisableOutboundSNAT = to.BoolPtr(false) } } else { // CloudProviderDisableOutboundSNAT is only valid in the context of Standard LB, statically set to false if not Standard LB o.KubernetesConfig.CloudProviderDisableOutboundSNAT = to.BoolPtr(false) } if o.KubernetesConfig.ContainerRuntimeConfig == nil { o.KubernetesConfig.ContainerRuntimeConfig = make(map[string]string) } // Master-specific defaults that depend upon OrchestratorProfile defaults if cs.Properties.MasterProfile != nil { if !cs.Properties.MasterProfile.IsCustomVNET() { if cs.Properties.OrchestratorProfile.IsAzureCNI() { // When VNET integration is enabled, all masters, agents and pods share the same large subnet. cs.Properties.MasterProfile.Subnet = o.KubernetesConfig.ClusterSubnet clusterSubnets := strings.Split(o.KubernetesConfig.ClusterSubnet, ",") if cs.Properties.IsAzureCNIDualStack() && len(clusterSubnets) > 1 { cs.Properties.MasterProfile.Subnet = clusterSubnets[0] } cs.Properties.MasterProfile.SubnetIPv6 = DefaultKubernetesMasterSubnetIPv6 // FirstConsecutiveStaticIP is not reset if it is upgrade and some value already exists if !isUpgrade || len(cs.Properties.MasterProfile.FirstConsecutiveStaticIP) == 0 { if cs.Properties.MasterProfile.IsVirtualMachineScaleSets() { cs.Properties.MasterProfile.FirstConsecutiveStaticIP = DefaultFirstConsecutiveKubernetesStaticIPVMSS cs.Properties.MasterProfile.Subnet = DefaultKubernetesMasterSubnet cs.Properties.MasterProfile.AgentSubnet = DefaultKubernetesAgentSubnetVMSS } else { cs.Properties.MasterProfile.FirstConsecutiveStaticIP = cs.Properties.MasterProfile.GetFirstConsecutiveStaticIPAddress(cs.Properties.MasterProfile.Subnet) } } } else { cs.Properties.MasterProfile.Subnet = DefaultKubernetesMasterSubnet cs.Properties.MasterProfile.SubnetIPv6 = DefaultKubernetesMasterSubnetIPv6 // FirstConsecutiveStaticIP is not reset if it is upgrade and some value already exists if !isUpgrade || len(cs.Properties.MasterProfile.FirstConsecutiveStaticIP) == 0 { if cs.Properties.MasterProfile.IsVirtualMachineScaleSets() { cs.Properties.MasterProfile.FirstConsecutiveStaticIP = DefaultFirstConsecutiveKubernetesStaticIPVMSS cs.Properties.MasterProfile.AgentSubnet = DefaultKubernetesAgentSubnetVMSS } else { cs.Properties.MasterProfile.FirstConsecutiveStaticIP = DefaultFirstConsecutiveKubernetesStaticIP } } } } // Distro assignment for masterProfile if cs.Properties.MasterProfile.ImageRef == nil { if cs.Properties.MasterProfile.Distro == "" { cs.Properties.MasterProfile.Distro = AKSUbuntu1804 if cs.Properties.IsAzureStackCloud() { cs.Properties.MasterProfile.Distro = AKSUbuntu2204 } } else if isUpgrade || isScale { if cs.Properties.MasterProfile.Distro == AKSDockerEngine || cs.Properties.MasterProfile.Distro == AKS1604Deprecated { cs.Properties.MasterProfile.Distro = AKSUbuntu1604 } else if cs.Properties.MasterProfile.Distro == AKS1804Deprecated { cs.Properties.MasterProfile.Distro = AKSUbuntu1804 } } // The AKS Distro is not available in Azure German Cloud. if cloudSpecConfig.CloudName == AzureGermanCloud { cs.Properties.MasterProfile.Distro = Ubuntu1804 if cs.Properties.IsAzureStackCloud() { cs.Properties.MasterProfile.Distro = Ubuntu2204 } } } } // Pool-specific defaults that depend upon OrchestratorProfile defaults for _, profile := range cs.Properties.AgentPoolProfiles { // configure the subnets if not in custom VNET if cs.Properties.MasterProfile != nil && !cs.Properties.MasterProfile.IsCustomVNET() { subnetCounter := 0 for _, profile := range cs.Properties.AgentPoolProfiles { if !cs.Properties.MasterProfile.IsVirtualMachineScaleSets() { profile.Subnet = cs.Properties.MasterProfile.Subnet } subnetCounter++ } } // Distro assignment for pools if profile.OSType != Windows { if profile.ImageRef == nil { if profile.Distro == "" { if profile.OSDiskSizeGB != 0 && profile.OSDiskSizeGB < VHDDiskSizeAKS { profile.Distro = Ubuntu1804 if cs.Properties.IsAzureStackCloud() { profile.Distro = Ubuntu2204 } } else { profile.Distro = AKSUbuntu1804 if cs.Properties.IsAzureStackCloud() { profile.Distro = AKSUbuntu2204 } } // Ensure deprecated distros are overridden // Previous versions of aks-engine required the docker-engine distro for N series vms, // so we need to hard override it in order to produce a working cluster in upgrade/scale contexts. } else if isUpgrade || isScale { if profile.Distro == AKSDockerEngine || profile.Distro == AKS1604Deprecated { profile.Distro = AKSUbuntu1604 } else if profile.Distro == AKS1804Deprecated { profile.Distro = AKSUbuntu1804 } } // The AKS Distro is not available in Azure German Cloud. if cloudSpecConfig.CloudName == AzureGermanCloud { profile.Distro = Ubuntu1804 if cs.Properties.IsAzureStackCloud() { profile.Distro = Ubuntu2204 } } } } // Ensure that all VMSS pools have SinglePlacementGroup set to false in Standard LB cluster scenarios if profile.AvailabilityProfile == VirtualMachineScaleSets && profile.SinglePlacementGroup == nil { if cs.Properties.OrchestratorProfile.KubernetesConfig.LoadBalancerSku == StandardLoadBalancerSku { profile.SinglePlacementGroup = to.BoolPtr(false) } else { profile.SinglePlacementGroup = to.BoolPtr(DefaultSinglePlacementGroup) } } } // Configure kubelet cs.setKubeletConfig(isUpgrade) // Configure addons cs.setAddonsConfig(isUpgrade) // Master-specific defaults that depend upon kubelet defaults // Set the default number of IP addresses allocated for masters. if cs.Properties.MasterProfile != nil { if cs.Properties.MasterProfile.IPAddressCount == 0 { // Allocate one IP address for the node. cs.Properties.MasterProfile.IPAddressCount = 1 // Allocate IP addresses for pods if VNET integration is enabled. if cs.Properties.OrchestratorProfile.IsAzureCNI() { masterMaxPods, _ := strconv.Atoi(cs.Properties.MasterProfile.KubernetesConfig.KubeletConfig["--max-pods"]) cs.Properties.MasterProfile.IPAddressCount += masterMaxPods } } } // Pool-specific defaults that depend upon kubelet defaults for _, profile := range cs.Properties.AgentPoolProfiles { // Set the default number of IP addresses allocated for agents. if profile.IPAddressCount == 0 { // Allocate one IP address for the node. profile.IPAddressCount = 1 // Allocate IP addresses for pods if VNET integration is enabled. if cs.Properties.OrchestratorProfile.IsAzureCNI() { agentPoolMaxPods, _ := strconv.Atoi(profile.KubernetesConfig.KubeletConfig["--max-pods"]) if profile.IsWindows() { profile.IPAddressCount += agentPoolMaxPods } else { profile.IPAddressCount = getPodIPAddressCountForAzureCNI(agentPoolMaxPods, o.KubernetesConfig) } } } } // Configure controller-manager cs.setControllerManagerConfig() // Configure cloud-controller-manager cs.setCloudControllerManagerConfig() // Configure apiserver cs.setAPIServerConfig() // Configure scheduler cs.setSchedulerConfig() // Configure components cs.setComponentsConfig(isUpgrade) // Configure Linux kernel runtime values via sysctl.d cs.setSysctlDConfig() } } func (p *Properties) setExtensionDefaults() { if p.ExtensionProfiles == nil { return } for _, extension := range p.ExtensionProfiles { if extension.RootURL == "" { extension.RootURL = DefaultExtensionsRootURL } } } func (p *Properties) setMasterProfileDefaults() { // set default to VMAS for now if p.MasterProfile.AvailabilityProfile == "" { p.MasterProfile.AvailabilityProfile = AvailabilitySet if p.IsAzureStackCloud() { p.MasterProfile.AvailabilityProfile = DefaultAzureStackAvailabilityProfile } } if p.MasterProfile.IsVirtualMachineScaleSets() { if p.MasterProfile.SinglePlacementGroup == nil { p.MasterProfile.SinglePlacementGroup = to.BoolPtr(DefaultSinglePlacementGroup) } } if p.MasterProfile.IsCustomVNET() && p.MasterProfile.IsVirtualMachineScaleSets() { p.MasterProfile.FirstConsecutiveStaticIP = p.MasterProfile.GetFirstConsecutiveStaticIPAddress(p.MasterProfile.VnetCidr) } if p.MasterProfile.HTTPSourceAddressPrefix == "" { p.MasterProfile.HTTPSourceAddressPrefix = "*" } if nil == p.MasterProfile.CosmosEtcd { p.MasterProfile.CosmosEtcd = to.BoolPtr(DefaultUseCosmos) } // Update default fault domain value for Azure Stack if p.IsAzureStackCloud() && p.MasterProfile.PlatformFaultDomainCount == nil { p.MasterProfile.PlatformFaultDomainCount = to.IntPtr(DefaultAzureStackFaultDomainCount) } if p.MasterProfile.PlatformUpdateDomainCount == nil { p.MasterProfile.PlatformUpdateDomainCount = to.IntPtr(3) } if p.MasterProfile.OSDiskCachingType == "" { p.MasterProfile.OSDiskCachingType = string(compute.CachingTypesReadWrite) } } func (p *Properties) setLinuxProfileDefaults() { if p.LinuxProfile.RunUnattendedUpgradesOnBootstrap == nil { if p.IsAzureStackCloud() { p.LinuxProfile.RunUnattendedUpgradesOnBootstrap = to.BoolPtr(DefaultRunUnattendedUpgradesOnBootstrapAzureStack) } else { p.LinuxProfile.RunUnattendedUpgradesOnBootstrap = to.BoolPtr(DefaultRunUnattendedUpgradesOnBootstrap) } } if p.LinuxProfile.EnableUnattendedUpgrades == nil { if p.IsAzureStackCloud() { p.LinuxProfile.EnableUnattendedUpgrades = to.BoolPtr(DefaultEnableUnattendedUpgradesAzureStack) } else { p.LinuxProfile.EnableUnattendedUpgrades = to.BoolPtr(DefaultEnableUnattendedUpgrades) } } if p.OrchestratorProfile.IsAzureCNI() && p.LinuxProfile.Eth0MTU == 0 { p.LinuxProfile.Eth0MTU = DefaultEth0MTU } } func (p *Properties) setAgentProfileDefaults(isUpgrade, isScale bool) { for i, profile := range p.AgentPoolProfiles { if profile.AvailabilityProfile == "" { profile.AvailabilityProfile = VirtualMachineScaleSets } if profile.AvailabilityProfile == VirtualMachineScaleSets { if profile.ScaleSetEvictionPolicy == "" && (profile.ScaleSetPriority == ScaleSetPriorityLow || profile.ScaleSetPriority == ScaleSetPrioritySpot) { profile.ScaleSetEvictionPolicy = ScaleSetEvictionPolicyDelete } if profile.ScaleSetPriority == ScaleSetPrioritySpot && profile.SpotMaxPrice == nil { var maximumValueFlag float64 = -1 profile.SpotMaxPrice = &maximumValueFlag } if profile.VMSSOverProvisioningEnabled == nil { profile.VMSSOverProvisioningEnabled = to.BoolPtr(DefaultVMSSOverProvisioningEnabled && !isUpgrade && !isScale) } profile.VMSSName = p.GetAgentVMPrefix(profile, i) } // set default OSType to Linux if profile.OSType == "" { profile.OSType = Linux } // Update default fault domain value for Azure Stack if p.IsAzureStackCloud() && profile.PlatformFaultDomainCount == nil { profile.PlatformFaultDomainCount = to.IntPtr(DefaultAzureStackFaultDomainCount) } if profile.PlatformUpdateDomainCount == nil { profile.PlatformUpdateDomainCount = to.IntPtr(3) } // Accelerated Networking is supported on most general purpose and compute-optimized instance sizes with 2 or more vCPUs. // These supported series are: D/DSv2 and F/Fs // All the others are not supported // On instances that support hyperthreading, Accelerated Networking is supported on VM instances with 4 or more vCPUs. // Supported series are: D/DSv3, E/ESv3, Fsv2, and Ms/Mms. if profile.AcceleratedNetworkingEnabled == nil { if p.IsAzureStackCloud() { profile.AcceleratedNetworkingEnabled = to.BoolPtr(DefaultAzureStackAcceleratedNetworking) } else { profile.AcceleratedNetworkingEnabled = to.BoolPtr(DefaultAcceleratedNetworking && !isUpgrade && !isScale && helpers.AcceleratedNetworkingSupported(profile.VMSize)) } } if profile.AcceleratedNetworkingEnabledWindows == nil { if p.IsAzureStackCloud() { // Here we are using same default variable. We will change once we will start supporting AcceleratedNetworking feature in general. profile.AcceleratedNetworkingEnabledWindows = to.BoolPtr(DefaultAzureStackAcceleratedNetworking) } else { profile.AcceleratedNetworkingEnabledWindows = to.BoolPtr(DefaultAcceleratedNetworkingWindowsEnabled && !isUpgrade && !isScale && helpers.AcceleratedNetworkingSupported(profile.VMSize)) } } if profile.AuditDEnabled == nil { profile.AuditDEnabled = to.BoolPtr(DefaultAuditDEnabled && !isUpgrade && !isScale) } if profile.PreserveNodesProperties == nil { profile.PreserveNodesProperties = to.BoolPtr(DefaultPreserveNodesProperties) } if profile.EnableVMSSNodePublicIP == nil { profile.EnableVMSSNodePublicIP = to.BoolPtr(DefaultEnableVMSSNodePublicIP) } if profile.OSDiskCachingType == "" { if profile.IsEphemeral() { profile.OSDiskCachingType = string(compute.CachingTypesReadOnly) } else { profile.OSDiskCachingType = string(compute.CachingTypesReadWrite) } } if profile.DataDiskCachingType == "" { profile.DataDiskCachingType = string(compute.CachingTypesReadOnly) } } } // ImagePublisherAndOfferMatch returns true if image publisher and offer match for specified WindowsProfile and AzureOSImageConfig objects func ImagePublisherAndOfferMatch(wp *WindowsProfile, imageConfig AzureOSImageConfig) bool { return wp.WindowsPublisher == imageConfig.ImagePublisher && wp.WindowsOffer == imageConfig.ImageOffer } // setWindowsProfileDefaults sets default WindowsProfile values func (cs *ContainerService) setWindowsProfileDefaults(isUpgrade, isScale bool) { cloudSpecConfig := cs.GetCloudSpecConfig() windowsProfile := cs.Properties.WindowsProfile if !isUpgrade && !isScale { // Allow non-default values of windowsProfile.ProvisioningScriptsPackageURL to allow for testing of updates to the scripts. if len(windowsProfile.ProvisioningScriptsPackageURL) == 0 { windowsProfile.ProvisioningScriptsPackageURL = cloudSpecConfig.KubernetesSpecConfig.WindowsProvisioningScriptsPackageURL } if len(windowsProfile.WindowsPauseImageURL) == 0 { windowsProfile.WindowsPauseImageURL = cloudSpecConfig.KubernetesSpecConfig.WindowsPauseImageURL } if windowsProfile.AlwaysPullWindowsPauseImage == nil { windowsProfile.AlwaysPullWindowsPauseImage = to.BoolPtr(cloudSpecConfig.KubernetesSpecConfig.AlwaysPullWindowsPauseImage) } if windowsProfile.SSHEnabled == nil { windowsProfile.SSHEnabled = to.BoolPtr(DefaultWindowsSSHEnabled) } // Default to aks-engine WIndows Server 2019 docker image defaultImageConfig := AKSWindowsServer2019OSImageConfig if ImagePublisherAndOfferMatch(windowsProfile, WindowsServer2019OSImageConfig) { // Use 'vanilla' Windows Server 2019 images defaultImageConfig = WindowsServer2019OSImageConfig } else if cs.Properties.OrchestratorProfile.KubernetesConfig.NeedsContainerd() { // Use to using aks-engine Windows Server 2019 conatinerD VHD defaultImageConfig = AKSWindowsServer2019ContainerDOSImageConfig } // This allows caller to use the latest ImageVersion and WindowsSku for adding a new Windows pool to an existing cluster. // We must assure that same WindowsPublisher and WindowsOffer are used in an existing cluster. if ImagePublisherAndOfferMatch(windowsProfile, defaultImageConfig) { if windowsProfile.WindowsSku == "" { windowsProfile.WindowsSku = defaultImageConfig.ImageSku } if windowsProfile.ImageVersion == "" { if windowsProfile.WindowsSku == defaultImageConfig.ImageSku { windowsProfile.ImageVersion = defaultImageConfig.ImageVersion } else { windowsProfile.ImageVersion = "latest" } } } else { if windowsProfile.WindowsPublisher == "" { windowsProfile.WindowsPublisher = defaultImageConfig.ImagePublisher } if windowsProfile.WindowsOffer == "" { windowsProfile.WindowsOffer = defaultImageConfig.ImageOffer } if windowsProfile.WindowsSku == "" { windowsProfile.WindowsSku = defaultImageConfig.ImageSku } if windowsProfile.ImageVersion == "" { // default versions are specific to a publisher/offer/sku for aks-engine VHDs aksEngineImageConfigs := []AzureOSImageConfig{AKSWindowsServer2019ContainerDOSImageConfig, AKSWindowsServer2019OSImageConfig} for _, imageConfig := range aksEngineImageConfigs { if ImagePublisherAndOfferMatch(windowsProfile, imageConfig) && windowsProfile.WindowsSku == imageConfig.ImageSku { windowsProfile.ImageVersion = imageConfig.ImageVersion break } } // set imageVersion to 'latest' if still unset if windowsProfile.ImageVersion == "" { windowsProfile.ImageVersion = "latest" } } } } else if isUpgrade { // Always set windowsProfile.ProvisioningScriptsPackerURL to the default value during upgrade. // The contents on this package must stay in sync with other powershell code in /parts/k8s and the best way to ensure that is to update the value here. windowsProfile.ProvisioningScriptsPackageURL = cloudSpecConfig.KubernetesSpecConfig.WindowsProvisioningScriptsPackageURL if len(windowsProfile.WindowsPauseImageURL) == 0 { windowsProfile.WindowsPauseImageURL = cloudSpecConfig.KubernetesSpecConfig.WindowsPauseImageURL } if windowsProfile.AlwaysPullWindowsPauseImage == nil { windowsProfile.AlwaysPullWindowsPauseImage = to.BoolPtr(cloudSpecConfig.KubernetesSpecConfig.AlwaysPullWindowsPauseImage) } // Image reference publisher and offer only can be set when you create the scale set so we keep the old values. // Reference: https://docs.microsoft.com/en-us/azure/virtual-machine-scale-sets/virtual-machine-scale-sets-upgrade-scale-set#create-time-properties windowsImageConfigs := []AzureOSImageConfig{AKSWindowsServer2019OSImageConfig, WindowsServer2019OSImageConfig} if cs.Properties.OrchestratorProfile.KubernetesConfig.NeedsContainerd() { windowsImageConfigs = []AzureOSImageConfig{AKSWindowsServer2019ContainerDOSImageConfig, WindowsServer2019OSImageConfig} } for _, imageConfig := range windowsImageConfigs { if ImagePublisherAndOfferMatch(windowsProfile, imageConfig) { if windowsProfile.ImageVersion == "" { windowsProfile.ImageVersion = imageConfig.ImageVersion } if windowsProfile.WindowsSku == "" { windowsProfile.WindowsSku = imageConfig.ImageSku } break } } } // Scale: Keep the same version to match other nodes because we have no way to rollback } // setStorageDefaults for agents func (p *Properties) setStorageDefaults() { if p.MasterProfile != nil && len(p.MasterProfile.StorageProfile) == 0 { p.MasterProfile.StorageProfile = ManagedDisks } for _, profile := range p.AgentPoolProfiles { if len(profile.StorageProfile) == 0 { profile.StorageProfile = ManagedDisks } } } func (p *Properties) setTelemetryProfileDefaults() { if p.TelemetryProfile == nil { p.TelemetryProfile = &TelemetryProfile{} } if len(p.TelemetryProfile.ApplicationInsightsKey) == 0 { p.TelemetryProfile.ApplicationInsightsKey = "" } } // DefaultCertParams is the params when we set the default certs. type DefaultCertParams struct { PkiKeySize int } // SetDefaultCerts generates and sets defaults for the container certificateProfile, returns true if certs are generated func (cs *ContainerService) SetDefaultCerts(params DefaultCertParams) (bool, []net.IP, error) { p := cs.Properties if p.MasterProfile == nil { return false, nil, nil } provided := certsAlreadyPresent(p.CertificateProfile, p.MasterProfile.Count) if areAllTrue(provided) { return false, nil, nil } var azureProdFQDNs []string for _, location := range cs.GetLocations() { azureProdFQDNs = append(azureProdFQDNs, FormatProdFQDNByLocation(p.MasterProfile.DNSPrefix, location, p.GetCustomCloudName())) } masterExtraFQDNs := append(azureProdFQDNs, p.MasterProfile.SubjectAltNames...) masterExtraFQDNs = append(masterExtraFQDNs, "localhost") firstMasterIP := net.ParseIP(p.MasterProfile.FirstConsecutiveStaticIP).To4() localhostIP := net.ParseIP("127.0.0.1").To4() if firstMasterIP == nil { return false, nil, errors.Errorf("MasterProfile.FirstConsecutiveStaticIP '%s' is an invalid IP address", p.MasterProfile.FirstConsecutiveStaticIP) } ips := []net.IP{firstMasterIP, localhostIP} // Include the Internal load balancer as well if p.MasterProfile.IsVirtualMachineScaleSets() { ips = append(ips, net.IP{firstMasterIP[0], firstMasterIP[1], byte(255), byte(DefaultInternalLbStaticIPOffset)}) } else { // Add the Internal Loadbalancer IP which is always at p known offset from the firstMasterIP ips = append(ips, net.IP{firstMasterIP[0], firstMasterIP[1], firstMasterIP[2], firstMasterIP[3] + byte(DefaultInternalLbStaticIPOffset)}) } var offsetMultiplier int if p.MasterProfile.IsVirtualMachineScaleSets() { offsetMultiplier = p.MasterProfile.IPAddressCount } else { offsetMultiplier = 1 } addr := binary.BigEndian.Uint32(firstMasterIP) for i := 1; i < p.MasterProfile.Count; i++ { newAddr := getNewAddr(addr, i, offsetMultiplier) ip := make(net.IP, 4) binary.BigEndian.PutUint32(ip, newAddr) ips = append(ips, ip) } if p.CertificateProfile == nil { p.CertificateProfile = &CertificateProfile{} } // use the specified Certificate Authority pair, or generate p new pair var caPair *helpers.PkiKeyCertPair if provided["ca"] { caPair = &helpers.PkiKeyCertPair{CertificatePem: p.CertificateProfile.CaCertificate, PrivateKeyPem: p.CertificateProfile.CaPrivateKey} } else { var err error pkiKeyCertPairParams := helpers.PkiKeyCertPairParams{ CommonName: "ca", PkiKeySize: params.PkiKeySize, } caPair, err = helpers.CreatePkiKeyCertPair(pkiKeyCertPairParams) if err != nil { return false, ips, err } p.CertificateProfile.CaCertificate = caPair.CertificatePem p.CertificateProfile.CaPrivateKey = caPair.PrivateKeyPem } serviceCIDR := p.OrchestratorProfile.KubernetesConfig.ServiceCIDR // all validation for dual stack done with primary service cidr as that is considered // the default ip family for cluster. if cs.Properties.FeatureFlags.IsFeatureEnabled("EnableIPv6DualStack") { // split service cidrs serviceCIDRs := strings.Split(serviceCIDR, ",") serviceCIDR = serviceCIDRs[0] } cidrFirstIP, err := common.CidrStringFirstIP(serviceCIDR) if err != nil { return false, ips, err } ips = append(ips, cidrFirstIP) pkiParams := helpers.PkiParams{} pkiParams.CaPair = caPair pkiParams.ClusterDomain = DefaultKubernetesClusterDomain pkiParams.ExtraFQDNs = masterExtraFQDNs pkiParams.ExtraIPs = ips pkiParams.MasterCount = p.MasterProfile.Count pkiParams.PkiKeySize = params.PkiKeySize apiServerPair, clientPair, kubeConfigPair, etcdServerPair, etcdClientPair, etcdPeerPairs, err := helpers.CreatePki(pkiParams) if err != nil { return false, ips, err } // If no Certificate Authority pair or no cert/key pair was provided, use generated cert/key pairs signed by provided Certificate Authority pair if !provided["apiserver"] || !provided["ca"] { p.CertificateProfile.APIServerCertificate = apiServerPair.CertificatePem p.CertificateProfile.APIServerPrivateKey = apiServerPair.PrivateKeyPem } if !provided["client"] || !provided["ca"] { p.CertificateProfile.ClientCertificate = clientPair.CertificatePem p.CertificateProfile.ClientPrivateKey = clientPair.PrivateKeyPem } if !provided["kubeconfig"] || !provided["ca"] { p.CertificateProfile.KubeConfigCertificate = kubeConfigPair.CertificatePem p.CertificateProfile.KubeConfigPrivateKey = kubeConfigPair.PrivateKeyPem } if !provided["etcd"] || !provided["ca"] { p.CertificateProfile.EtcdServerCertificate = etcdServerPair.CertificatePem p.CertificateProfile.EtcdServerPrivateKey = etcdServerPair.PrivateKeyPem p.CertificateProfile.EtcdClientCertificate = etcdClientPair.CertificatePem p.CertificateProfile.EtcdClientPrivateKey = etcdClientPair.PrivateKeyPem p.CertificateProfile.EtcdPeerCertificates = make([]string, p.MasterProfile.Count) p.CertificateProfile.EtcdPeerPrivateKeys = make([]string, p.MasterProfile.Count) for i, v := range etcdPeerPairs { p.CertificateProfile.EtcdPeerCertificates[i] = v.CertificatePem p.CertificateProfile.EtcdPeerPrivateKeys[i] = v.PrivateKeyPem } } return true, ips, nil } func areAllTrue(m map[string]bool) bool { for _, v := range m { if !v { return false } } return true } // getNewIP returns a new IP derived from an address plus a multiple of an offset func getNewAddr(addr uint32, count int, offsetMultiplier int) uint32 { offset := count * offsetMultiplier newAddr := addr + uint32(offset) return newAddr } // certsAlreadyPresent already present returns a map where each key is a type of cert and each value is true if that cert/key pair is user-provided func certsAlreadyPresent(c *CertificateProfile, m int) map[string]bool { g := map[string]bool{ "ca": false, "apiserver": false, "kubeconfig": false, "client": false, "etcd": false, } if c != nil { etcdPeer := true if len(c.EtcdPeerCertificates) != m || len(c.EtcdPeerPrivateKeys) != m { etcdPeer = false } else { for i, p := range c.EtcdPeerCertificates { if !(len(p) > 0) || !(len(c.EtcdPeerPrivateKeys[i]) > 0) { etcdPeer = false } } } g["ca"] = len(c.CaCertificate) > 0 && len(c.CaPrivateKey) > 0 g["apiserver"] = len(c.APIServerCertificate) > 0 && len(c.APIServerPrivateKey) > 0 g["kubeconfig"] = len(c.KubeConfigCertificate) > 0 && len(c.KubeConfigPrivateKey) > 0 g["client"] = len(c.ClientCertificate) > 0 && len(c.ClientPrivateKey) > 0 g["etcd"] = etcdPeer && len(c.EtcdClientCertificate) > 0 && len(c.EtcdClientPrivateKey) > 0 && len(c.EtcdServerCertificate) > 0 && len(c.EtcdServerPrivateKey) > 0 } return g } // combine user-provided --feature-gates vals with defaults // a minimum k8s version may be declared as required for defaults assignment func addDefaultFeatureGates(m map[string]string, version string, minVersion string, defaults string) { if minVersion == "" || common.IsKubernetesVersionGe(version, minVersion) { m["--feature-gates"] = combineValues(m["--feature-gates"], defaults) } else { m["--feature-gates"] = combineValues(m["--feature-gates"], "") } } // combineValues takes a variadic string input of strings matching a pattern []string{"foo=bar","key=val"} // and returns a single, comma-delimited, concatenated string of all key/val string values, e.g.: "foo=bar,key=val" // if more than one key is encountered, the first one is always preferred func combineValues(inputs ...string) string { valueMap := make(map[string]string) for _, input := range inputs { applyValueStringToMap(valueMap, input) } return mapToString(valueMap) } // removeInvalidFeatureGates removes specified invalid --feature-gates func removeInvalidFeatureGates(m map[string]string, invalidFeatureGates []string) { m["--feature-gates"] = removeKeys(m["--feature-gates"], invalidFeatureGates) } // removeInvalidFeatureGates removes specified invalid --feature-gates func replaceFlags(m map[string]string, replacedflags map[string]string) { for old, new := range replacedflags { if v, ok := m[old]; ok { // Create the new flag name m[new] = v // Remove the old flag name delete(m, old) } } } // removeKeys takes a input of strings matching a pattern []string{"foo=bar","key=val"} // removes from this input the given input keys e.g.: "foo" // and returns a single, comma-delimited, concatenated string of all remaining key/val string values, e.g.: "key=val" func removeKeys(input string, keysToRemove []string) string { valueMap := make(map[string]string) applyValueStringToMap(valueMap, input) for _, key := range keysToRemove { delete(valueMap, key) } return mapToString(valueMap) } func applyValueStringToMap(valueMap map[string]string, input string) { values := strings.Split(input, ",") for index := 0; index < len(values); index++ { // trim spaces (e.g. if the input was "foo=true, bar=true" - we want to drop the space after the comma) value := strings.Trim(values[index], " ") valueParts := strings.Split(value, "=") if len(valueParts) != 2 { continue } if _, ok := valueMap[valueParts[0]]; !ok { valueMap[valueParts[0]] = valueParts[1] } } } func mapToString(valueMap map[string]string) string { // Order by key for consistency keys := []string{} for key := range valueMap { keys = append(keys, key) } sort.Strings(keys) ret := []string{} for _, key := range keys { ret = append(ret, fmt.Sprintf("%s=%s", key, valueMap[key])) } return strings.Join(ret, ",") } func generateEtcdEncryptionKey() string { b := make([]byte, 32) _, _ = rand.Read(b) return base64.StdEncoding.EncodeToString(b) } // getDefaultKubernetesClusterSubnetIPv6 returns the default IPv6 cluster subnet func (cs *ContainerService) getDefaultKubernetesClusterSubnetIPv6() string { o := cs.Properties.OrchestratorProfile // In 1.17+ the default IPv6 mask size is /64 which means the cluster // subnet mask size >= /48 if common.IsKubernetesVersionGe(o.OrchestratorVersion, "1.17.0") { return DefaultKubernetesClusterSubnetIPv6 } // In 1.16, the default mask size for IPv6 is /24 which forces the cluster // subnet mask size to be strictly >= /8 return "fc00::/8" } func (cs *ContainerService) setCSIProxyDefaults() { p := cs.Properties useCloudControllerManager := p.OrchestratorProfile.KubernetesConfig != nil && to.Bool(p.OrchestratorProfile.KubernetesConfig.UseCloudControllerManager) w := p.WindowsProfile // We should enable CSI proxy if: // 1. enableCSIProxy is not defined and cloud-controller-manager // is being used on a Windows cluster or // 2. enabledCSIProxy is true // 3. csiProxyURL is defined shouldEnableCSIProxy := (w.EnableCSIProxy == nil && useCloudControllerManager) || w.IsCSIProxyEnabled() || w.CSIProxyURL != "" if shouldEnableCSIProxy { w.EnableCSIProxy = to.BoolPtr(true) if w.CSIProxyURL == "" { cloudSpecConfig := cs.GetCloudSpecConfig() w.CSIProxyURL = cloudSpecConfig.KubernetesSpecConfig.CSIProxyDownloadURL } } } func getPodIPAddressCountForAzureCNI(kubeletMaxPods int, k *KubernetesConfig) int { ret := 1 // We need at least IP address for eth0 var numHostNetworkPods int if k.IsAddonEnabled(common.AADPodIdentityAddonName) { numHostNetworkPods++ } if k.IsAddonEnabled(common.AntreaAddonName) { numHostNetworkPods++ } if k.IsAddonEnabled(common.AzureNetworkPolicyAddonName) { numHostNetworkPods++ } if k.IsAddonEnabled(common.AzureDiskCSIDriverAddonName) { numHostNetworkPods++ } if k.IsAddonEnabled(common.AzureFileCSIDriverAddonName) { numHostNetworkPods++ } if k.IsAddonEnabled(common.CalicoAddonName) { numHostNetworkPods++ } if k.IsAddonEnabled(common.CiliumAddonName) { numHostNetworkPods++ } if k.IsAddonEnabled(common.CloudNodeManagerAddonName) { numHostNetworkPods++ } if k.IsAddonEnabled(common.FlannelAddonName) { numHostNetworkPods++ } if k.IsAddonEnabled(common.IPMASQAgentAddonName) { numHostNetworkPods++ } if k.IsAddonEnabled(common.KubeProxyAddonName) { numHostNetworkPods++ } if k.IsAddonEnabled(common.SecretsStoreCSIDriverAddonName) { numHostNetworkPods++ } ret += (kubeletMaxPods - numHostNetworkPods) return ret }