From 673b40f2a4a3c0d73abdd1ce9446d05e56c72d40 Mon Sep 17 00:00:00 2001 From: Jack Francis Date: Fri, 6 Apr 2018 13:57:54 -0700 Subject: [PATCH] fix maxPods deprecation inconsistency (#2618) * fix maxPods deprecation inconsistency --- docs/clusterdefinition.md | 3 +-- docs/kubernetes/features.md | 4 +++- .../kubernetes-config/kubernetes-maxpods.json | 4 +++- parts/k8s/kubernetesmastercustomscript.sh | 6 ------ parts/k8s/kubernetesmastervars.t | 4 ++-- parts/k8s/kubernetesparams.t | 4 ++-- pkg/acsengine/defaults-kubelet.go | 3 ++- pkg/acsengine/defaults-kubelet_test.go | 21 +++++++++++++++++++ pkg/acsengine/defaults.go | 13 ++++-------- pkg/acsengine/engine.go | 1 - 10 files changed, 38 insertions(+), 25 deletions(-) diff --git a/docs/clusterdefinition.md b/docs/clusterdefinition.md index 3bc4ba5d42..af59f3bd3c 100644 --- a/docs/clusterdefinition.md +++ b/docs/clusterdefinition.md @@ -43,7 +43,6 @@ Here are the valid values for the orchestrator types: |enableDataEncryptionAtRest|no|Enable [kuberetes data encryption at rest](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/).This is currently an alpha feature. (boolean - default == false) | |etcdDiskSizeGB|no|Size in GB to assign to etcd data volume. Defaults (if no user value provided) are: 256 GB for clusters up to 3 nodes; 512 GB for clusters with between 4 and 10 nodes; 1024 GB for clusters with between 11 and 20 nodes; and 2048 GB for clusters with more than 20 nodes| |privateCluster|no|Build a cluster without public addresses assigned. See `privateClusters` [below](#feat-private-cluster).| -|maxPods|no|The maximum number of pods per node. The minimum valid value, necessary for running kube-system pods, is 5. Default value is 30 when networkPolicy equals azure, 110 otherwise.| |gcHighThreshold|no|Sets the --image-gc-high-threshold value on the kublet configuration. Default is 85. [See kubelet Garbage Collection](https://kubernetes.io/docs/concepts/cluster-administration/kubelet-garbage-collection/) | |gcLowThreshold|no|Sets the --image-gc-low-threshold value on the kublet configuration. Default is 80. [See kubelet Garbage Collection](https://kubernetes.io/docs/concepts/cluster-administration/kubelet-garbage-collection/) | |useInstanceMetadata|no|Use the Azure cloudprovider instance metadata service for appropriate resource discovery operations. Default is `true`.| @@ -166,7 +165,7 @@ Below is a list of kubelet options that acs-engine will configure by default: |"--cloud-provider"|"azure"| |"--cluster-domain"|"cluster.local"| |"--pod-infra-container-image"|"pause-amd64:"| -|"--max-pods"|"110"| +|"--max-pods"|"30", or "100" if using kubenet --network-plugin (i.e., `"networkPolicy": "none"`)| |"--eviction-hard"|"memory.available<100Mi,nodefs.available<10%,nodefs.inodesFree<5%"| |"--node-status-update-frequency"|"10s"| |"--image-gc-high-threshold"|"85"| diff --git a/docs/kubernetes/features.md b/docs/kubernetes/features.md index b580fe065c..99d76c7b0b 100644 --- a/docs/kubernetes/features.md +++ b/docs/kubernetes/features.md @@ -133,7 +133,9 @@ When using Azure integrated networking the maxPods setting will be set to 30 by ``` "kubernetesConfig": { - "maxPods": 50 + "kubeletConfig": { + "--max-pods": "50" + } } ``` diff --git a/examples/kubernetes-config/kubernetes-maxpods.json b/examples/kubernetes-config/kubernetes-maxpods.json index 69f3445e27..5aa4e7d154 100644 --- a/examples/kubernetes-config/kubernetes-maxpods.json +++ b/examples/kubernetes-config/kubernetes-maxpods.json @@ -4,7 +4,9 @@ "orchestratorProfile": { "orchestratorType": "Kubernetes", "kubernetesConfig": { - "maxPods": 20 + "kubeletConfig": { + "--max-pods": "20" + } } }, "masterProfile": { diff --git a/parts/k8s/kubernetesmastercustomscript.sh b/parts/k8s/kubernetesmastercustomscript.sh index 5de7cdf187..c12e8cb196 100644 --- a/parts/k8s/kubernetesmastercustomscript.sh +++ b/parts/k8s/kubernetesmastercustomscript.sh @@ -187,10 +187,6 @@ function ensureFilepath() { fi } -function setMaxPods () { - sed -i "s/^KUBELET_MAX_PODS=.*/KUBELET_MAX_PODS=${1}/" /etc/default/kubelet -} - function setNetworkPlugin () { sed -i "s/^KUBELET_NETWORK_PLUGIN=.*/KUBELET_NETWORK_PLUGIN=${1}/" /etc/default/kubelet } @@ -564,8 +560,6 @@ if [[ "$CONTAINER_RUNTIME" == "clear-containers" ]]; then installContainerd fi fi -echo `date`,`hostname`, setMaxPodsStart>>/opt/m -setMaxPods ${MAX_PODS} echo `date`,`hostname`, ensureContainerdStart>>/opt/m ensureContainerd echo `date`,`hostname`, ensureKubeletStart>>/opt/m diff --git a/parts/k8s/kubernetesmastervars.t b/parts/k8s/kubernetesmastervars.t index ddbedb4053..0601e58537 100644 --- a/parts/k8s/kubernetesmastervars.t +++ b/parts/k8s/kubernetesmastervars.t @@ -214,9 +214,9 @@ "mountetcdScript": "{{GetKubernetesB64Mountetcd}}", {{if not IsHostedMaster}} "provisionScriptParametersMaster": "[concat('MASTER_NODE=true TOTAL_NODES=',variables('totalNodes'),' APISERVER_PRIVATE_KEY=',variables('apiServerPrivateKey'),' CA_CERTIFICATE=',variables('caCertificate'),' CA_PRIVATE_KEY=',variables('caPrivateKey'),' MASTER_FQDN=',variables('masterFqdnPrefix'),' KUBECONFIG_CERTIFICATE=',variables('kubeConfigCertificate'),' KUBECONFIG_KEY=',variables('kubeConfigPrivateKey'),' ETCD_SERVER_CERTIFICATE=',variables('etcdServerCertificate'),' ETCD_CLIENT_CERTIFICATE=',variables('etcdClientCertificate'),' ETCD_SERVER_PRIVATE_KEY=',variables('etcdServerPrivateKey'),' ETCD_CLIENT_PRIVATE_KEY=',variables('etcdClientPrivateKey'),' ETCD_PEER_CERTIFICATES=',string(variables('etcdPeerCertificates')),' ETCD_PEER_PRIVATE_KEYS=',string(variables('etcdPeerPrivateKeys')),' ADMINUSER=',variables('username'))]", - "provisionScriptParametersCommon": "[concat('TENANT_ID=',variables('tenantID'),' HYPERKUBE_URL=',variables('kubernetesHyperkubeSpec'),' APISERVER_PUBLIC_KEY=',variables('apiserverCertificate'),' SUBSCRIPTION_ID=',variables('subscriptionId'),' RESOURCE_GROUP=',variables('resourceGroup'),' LOCATION=',variables('location'),' SUBNET=',variables('subnetName'),' NETWORK_SECURITY_GROUP=',variables('nsgName'),' VIRTUAL_NETWORK=',variables('virtualNetworkName'),' VIRTUAL_NETWORK_RESOURCE_GROUP=',variables('virtualNetworkResourceGroupName'),' ROUTE_TABLE=',variables('routeTableName'),' PRIMARY_AVAILABILITY_SET=',variables('primaryAvailabilitySetName'),' SERVICE_PRINCIPAL_CLIENT_ID=',variables('servicePrincipalClientId'),' SERVICE_PRINCIPAL_CLIENT_SECRET=',variables('singleQuote'),variables('servicePrincipalClientSecret'),variables('singleQuote'),' KUBELET_PRIVATE_KEY=',variables('clientPrivateKey'),' TARGET_ENVIRONMENT=',variables('targetEnvironment'),' NETWORK_POLICY=',variables('networkPolicy'),' FQDNSuffix=',variables('fqdnEndpointSuffix'),' VNET_CNI_PLUGINS_URL=',variables('vnetCniLinuxPluginsURL'),' CNI_PLUGINS_URL=',variables('cniPluginsURL'),' MAX_PODS=',variables('maxPods'),' CLOUDPROVIDER_BACKOFF=',variables('cloudProviderBackoff'),' CLOUDPROVIDER_BACKOFF_RETRIES=',variables('cloudProviderBackoffRetries'),' CLOUDPROVIDER_BACKOFF_EXPONENT=',variables('cloudProviderBackoffExponent'),' CLOUDPROVIDER_BACKOFF_DURATION=',variables('cloudProviderBackoffDuration'),' CLOUDPROVIDER_BACKOFF_JITTER=',variables('cloudProviderBackoffJitter'),' CLOUDPROVIDER_RATELIMIT=',variables('cloudProviderRatelimit'),' CLOUDPROVIDER_RATELIMIT_QPS=',variables('cloudProviderRatelimitQPS'),' CLOUDPROVIDER_RATELIMIT_BUCKET=',variables('cloudProviderRatelimitBucket'),' USE_MANAGED_IDENTITY_EXTENSION=',variables('useManagedIdentityExtension'),' USE_INSTANCE_METADATA=',variables('useInstanceMetadata'),' CONTAINER_RUNTIME=',variables('containerRuntime'),' KUBECONFIG_SERVER=',variables('kubeconfigServer'))]", + "provisionScriptParametersCommon": "[concat('TENANT_ID=',variables('tenantID'),' HYPERKUBE_URL=',variables('kubernetesHyperkubeSpec'),' APISERVER_PUBLIC_KEY=',variables('apiserverCertificate'),' SUBSCRIPTION_ID=',variables('subscriptionId'),' RESOURCE_GROUP=',variables('resourceGroup'),' LOCATION=',variables('location'),' SUBNET=',variables('subnetName'),' NETWORK_SECURITY_GROUP=',variables('nsgName'),' VIRTUAL_NETWORK=',variables('virtualNetworkName'),' VIRTUAL_NETWORK_RESOURCE_GROUP=',variables('virtualNetworkResourceGroupName'),' ROUTE_TABLE=',variables('routeTableName'),' PRIMARY_AVAILABILITY_SET=',variables('primaryAvailabilitySetName'),' SERVICE_PRINCIPAL_CLIENT_ID=',variables('servicePrincipalClientId'),' SERVICE_PRINCIPAL_CLIENT_SECRET=',variables('singleQuote'),variables('servicePrincipalClientSecret'),variables('singleQuote'),' KUBELET_PRIVATE_KEY=',variables('clientPrivateKey'),' TARGET_ENVIRONMENT=',variables('targetEnvironment'),' NETWORK_POLICY=',variables('networkPolicy'),' FQDNSuffix=',variables('fqdnEndpointSuffix'),' VNET_CNI_PLUGINS_URL=',variables('vnetCniLinuxPluginsURL'),' CNI_PLUGINS_URL=',variables('cniPluginsURL'),' CLOUDPROVIDER_BACKOFF=',variables('cloudProviderBackoff'),' CLOUDPROVIDER_BACKOFF_RETRIES=',variables('cloudProviderBackoffRetries'),' CLOUDPROVIDER_BACKOFF_EXPONENT=',variables('cloudProviderBackoffExponent'),' CLOUDPROVIDER_BACKOFF_DURATION=',variables('cloudProviderBackoffDuration'),' CLOUDPROVIDER_BACKOFF_JITTER=',variables('cloudProviderBackoffJitter'),' CLOUDPROVIDER_RATELIMIT=',variables('cloudProviderRatelimit'),' CLOUDPROVIDER_RATELIMIT_QPS=',variables('cloudProviderRatelimitQPS'),' CLOUDPROVIDER_RATELIMIT_BUCKET=',variables('cloudProviderRatelimitBucket'),' USE_MANAGED_IDENTITY_EXTENSION=',variables('useManagedIdentityExtension'),' USE_INSTANCE_METADATA=',variables('useInstanceMetadata'),' CONTAINER_RUNTIME=',variables('containerRuntime'),' KUBECONFIG_SERVER=',variables('kubeconfigServer'))]", {{else}} - "provisionScriptParametersCommon": "[concat('TENANT_ID=',variables('tenantID'),' HYPERKUBE_URL=',variables('kubernetesHyperkubeSpec'),' APISERVER_PUBLIC_KEY=',variables('apiserverCertificate'),' SUBSCRIPTION_ID=',variables('subscriptionId'),' RESOURCE_GROUP=',variables('resourceGroup'),' LOCATION=',variables('location'),' SUBNET=',variables('subnetName'),' NETWORK_SECURITY_GROUP=',variables('nsgName'),' VIRTUAL_NETWORK=',variables('virtualNetworkName'),' VIRTUAL_NETWORK_RESOURCE_GROUP=',variables('virtualNetworkResourceGroupName'),' ROUTE_TABLE=',variables('routeTableName'),' PRIMARY_AVAILABILITY_SET=',variables('primaryAvailabilitySetName'),' SERVICE_PRINCIPAL_CLIENT_ID=',variables('servicePrincipalClientId'),' SERVICE_PRINCIPAL_CLIENT_SECRET=',variables('singleQuote'),variables('servicePrincipalClientSecret'),variables('singleQuote'),' KUBELET_PRIVATE_KEY=',variables('clientPrivateKey'),' TARGET_ENVIRONMENT=',variables('targetEnvironment'),' NETWORK_POLICY=',variables('networkPolicy'),' FQDNSuffix=',variables('fqdnEndpointSuffix'),' VNET_CNI_PLUGINS_URL=',variables('vnetCniLinuxPluginsURL'),' CNI_PLUGINS_URL=',variables('cniPluginsURL'),' MAX_PODS=',variables('maxPods'),' CLOUDPROVIDER_BACKOFF=',variables('cloudProviderBackoff'),' CLOUDPROVIDER_BACKOFF_RETRIES=',variables('cloudProviderBackoffRetries'),' CLOUDPROVIDER_BACKOFF_EXPONENT=',variables('cloudProviderBackoffExponent'),' CLOUDPROVIDER_BACKOFF_DURATION=',variables('cloudProviderBackoffDuration'),' CLOUDPROVIDER_BACKOFF_JITTER=',variables('cloudProviderBackoffJitter'),' CLOUDPROVIDER_RATELIMIT=',variables('cloudProviderRatelimit'),' CLOUDPROVIDER_RATELIMIT_QPS=',variables('cloudProviderRatelimitQPS'),' CLOUDPROVIDER_RATELIMIT_BUCKET=',variables('cloudProviderRatelimitBucket'),' USE_MANAGED_IDENTITY_EXTENSION=',variables('useManagedIdentityExtension'),' USE_INSTANCE_METADATA=',variables('useInstanceMetadata'),' CONTAINER_RUNTIME=',variables('containerRuntime'))]", + "provisionScriptParametersCommon": "[concat('TENANT_ID=',variables('tenantID'),' HYPERKUBE_URL=',variables('kubernetesHyperkubeSpec'),' APISERVER_PUBLIC_KEY=',variables('apiserverCertificate'),' SUBSCRIPTION_ID=',variables('subscriptionId'),' RESOURCE_GROUP=',variables('resourceGroup'),' LOCATION=',variables('location'),' SUBNET=',variables('subnetName'),' NETWORK_SECURITY_GROUP=',variables('nsgName'),' VIRTUAL_NETWORK=',variables('virtualNetworkName'),' VIRTUAL_NETWORK_RESOURCE_GROUP=',variables('virtualNetworkResourceGroupName'),' ROUTE_TABLE=',variables('routeTableName'),' PRIMARY_AVAILABILITY_SET=',variables('primaryAvailabilitySetName'),' SERVICE_PRINCIPAL_CLIENT_ID=',variables('servicePrincipalClientId'),' SERVICE_PRINCIPAL_CLIENT_SECRET=',variables('singleQuote'),variables('servicePrincipalClientSecret'),variables('singleQuote'),' KUBELET_PRIVATE_KEY=',variables('clientPrivateKey'),' TARGET_ENVIRONMENT=',variables('targetEnvironment'),' NETWORK_POLICY=',variables('networkPolicy'),' FQDNSuffix=',variables('fqdnEndpointSuffix'),' VNET_CNI_PLUGINS_URL=',variables('vnetCniLinuxPluginsURL'),' CNI_PLUGINS_URL=',variables('cniPluginsURL'),' CLOUDPROVIDER_BACKOFF=',variables('cloudProviderBackoff'),' CLOUDPROVIDER_BACKOFF_RETRIES=',variables('cloudProviderBackoffRetries'),' CLOUDPROVIDER_BACKOFF_EXPONENT=',variables('cloudProviderBackoffExponent'),' CLOUDPROVIDER_BACKOFF_DURATION=',variables('cloudProviderBackoffDuration'),' CLOUDPROVIDER_BACKOFF_JITTER=',variables('cloudProviderBackoffJitter'),' CLOUDPROVIDER_RATELIMIT=',variables('cloudProviderRatelimit'),' CLOUDPROVIDER_RATELIMIT_QPS=',variables('cloudProviderRatelimitQPS'),' CLOUDPROVIDER_RATELIMIT_BUCKET=',variables('cloudProviderRatelimitBucket'),' USE_MANAGED_IDENTITY_EXTENSION=',variables('useManagedIdentityExtension'),' USE_INSTANCE_METADATA=',variables('useInstanceMetadata'),' CONTAINER_RUNTIME=',variables('containerRuntime'))]", {{end}} "generateProxyCertsScript": "{{GetKubernetesB64GenerateProxyCerts}}", "orchestratorNameVersionTag": "{{.OrchestratorProfile.OrchestratorType}}:{{.OrchestratorProfile.OrchestratorVersion}}", diff --git a/parts/k8s/kubernetesparams.t b/parts/k8s/kubernetesparams.t index 09aab08c55..349a66ac89 100644 --- a/parts/k8s/kubernetesparams.t +++ b/parts/k8s/kubernetesparams.t @@ -617,9 +617,9 @@ "type": "string" }, "maxPods": { - "defaultValue": 110, + "defaultValue": 30, "metadata": { - "description": "The maximum number of pods per node." + "description": "This param has been deprecated." }, "type": "int" }, diff --git a/pkg/acsengine/defaults-kubelet.go b/pkg/acsengine/defaults-kubelet.go index 463e797a3c..3edbe253bd 100644 --- a/pkg/acsengine/defaults-kubelet.go +++ b/pkg/acsengine/defaults-kubelet.go @@ -35,7 +35,7 @@ func setKubeletConfig(cs *api.ContainerService) { "--cluster-domain": "cluster.local", "--network-plugin": "cni", "--pod-infra-container-image": cloudSpecConfig.KubernetesSpecConfig.KubernetesImageBase + KubeConfigs[o.OrchestratorVersion]["pause"], - "--max-pods": strconv.Itoa(DefaultKubernetesKubeletMaxPods), + "--max-pods": strconv.Itoa(DefaultKubernetesMaxPodsVNETIntegrated), "--eviction-hard": DefaultKubernetesHardEvictionThreshold, "--node-status-update-frequency": KubeConfigs[o.OrchestratorVersion]["nodestatusfreq"], "--image-gc-high-threshold": strconv.Itoa(DefaultKubernetesGCHighThreshold), @@ -60,6 +60,7 @@ func setKubeletConfig(cs *api.ContainerService) { // Override default --network-plugin? if o.KubernetesConfig.NetworkPolicy == NetworkPolicyNone { o.KubernetesConfig.KubeletConfig["--network-plugin"] = NetworkPluginKubenet + o.KubernetesConfig.KubeletConfig["--max-pods"] = strconv.Itoa(DefaultKubernetesMaxPods) } // We don't support user-configurable values for the following, diff --git a/pkg/acsengine/defaults-kubelet_test.go b/pkg/acsengine/defaults-kubelet_test.go index ae7fcf2c0b..15148d993c 100644 --- a/pkg/acsengine/defaults-kubelet_test.go +++ b/pkg/acsengine/defaults-kubelet_test.go @@ -1,6 +1,7 @@ package acsengine import ( + "strconv" "testing" "github.com/Azure/acs-engine/pkg/helpers" @@ -152,3 +153,23 @@ func TestKubeletConfigEnableSecureKubelet(t *testing.T) { } } + +func TestKubeletMaxPods(t *testing.T) { + cs := createContainerService("testcluster", defaultTestClusterVer, 3, 2) + cs.Properties.OrchestratorProfile.KubernetesConfig.NetworkPolicy = NetworkPolicyAzure + setKubeletConfig(cs) + k := cs.Properties.OrchestratorProfile.KubernetesConfig.KubeletConfig + if k["--max-pods"] != strconv.Itoa(DefaultKubernetesMaxPodsVNETIntegrated) { + t.Fatalf("got unexpected '--max-pods' kubelet config value for NetworkPolicy=%s: %s", + NetworkPolicyAzure, k["--max-pods"]) + } + + cs = createContainerService("testcluster", defaultTestClusterVer, 3, 2) + cs.Properties.OrchestratorProfile.KubernetesConfig.NetworkPolicy = NetworkPolicyNone + setKubeletConfig(cs) + k = cs.Properties.OrchestratorProfile.KubernetesConfig.KubeletConfig + if k["--max-pods"] != strconv.Itoa(DefaultKubernetesMaxPods) { + t.Fatalf("got unexpected '--max-pods' kubelet config value for NetworkPolicy=%s: %s", + NetworkPolicyNone, k["--max-pods"]) + } +} diff --git a/pkg/acsengine/defaults.go b/pkg/acsengine/defaults.go index 8b64ef99e7..fb6460e0b6 100644 --- a/pkg/acsengine/defaults.go +++ b/pkg/acsengine/defaults.go @@ -365,13 +365,6 @@ func setOrchestratorDefaults(cs *api.ContainerService) { o.KubernetesConfig.ClusterSubnet = DefaultKubernetesClusterSubnet } } - if o.KubernetesConfig.MaxPods == 0 { - if o.IsAzureCNI() { - o.KubernetesConfig.MaxPods = DefaultKubernetesMaxPodsVNETIntegrated - } else { - o.KubernetesConfig.MaxPods = DefaultKubernetesMaxPods - } - } if o.KubernetesConfig.GCHighThreshold == 0 { o.KubernetesConfig.GCHighThreshold = DefaultKubernetesGCHighThreshold } @@ -572,7 +565,8 @@ func setMasterNetworkDefaults(a *api.Properties, isUpgrade bool) { // Allocate IP addresses for pods if VNET integration is enabled. if a.OrchestratorProfile.IsAzureCNI() { if a.OrchestratorProfile.OrchestratorType == api.Kubernetes { - a.MasterProfile.IPAddressCount += a.OrchestratorProfile.KubernetesConfig.MaxPods + masterMaxPods, _ := strconv.Atoi(a.MasterProfile.KubernetesConfig.KubeletConfig["--max-pods"]) + a.MasterProfile.IPAddressCount += masterMaxPods } } } @@ -616,7 +610,8 @@ func setAgentNetworkDefaults(a *api.Properties) { // Allocate IP addresses for pods if VNET integration is enabled. if a.OrchestratorProfile.IsAzureCNI() { if a.OrchestratorProfile.OrchestratorType == api.Kubernetes { - profile.IPAddressCount += a.OrchestratorProfile.KubernetesConfig.MaxPods + agentPoolMaxPods, _ := strconv.Atoi(profile.KubernetesConfig.KubeletConfig["--max-pods"]) + profile.IPAddressCount += agentPoolMaxPods } } } diff --git a/pkg/acsengine/engine.go b/pkg/acsengine/engine.go index 3f9ff48413..ec58c933a9 100644 --- a/pkg/acsengine/engine.go +++ b/pkg/acsengine/engine.go @@ -661,7 +661,6 @@ func getParameters(cs *api.ContainerService, isClassicMode bool, generatorCode s addValue(parametersMap, "cniPluginsURL", cloudSpecConfig.KubernetesSpecConfig.CNIPluginsDownloadURL) addValue(parametersMap, "vnetCniLinuxPluginsURL", cloudSpecConfig.KubernetesSpecConfig.VnetCNILinuxPluginsDownloadURL) addValue(parametersMap, "vnetCniWindowsPluginsURL", cloudSpecConfig.KubernetesSpecConfig.VnetCNIWindowsPluginsDownloadURL) - addValue(parametersMap, "maxPods", properties.OrchestratorProfile.KubernetesConfig.MaxPods) addValue(parametersMap, "gchighthreshold", properties.OrchestratorProfile.KubernetesConfig.GCHighThreshold) addValue(parametersMap, "gclowthreshold", properties.OrchestratorProfile.KubernetesConfig.GCLowThreshold) addValue(parametersMap, "etcdDownloadURLBase", cloudSpecConfig.KubernetesSpecConfig.EtcdDownloadURLBase)