Skip to content

Commit

Permalink
Support for kubernetes clusters with user assigned msi (#3736)
Browse files Browse the repository at this point in the history
  • Loading branch information
kkmsft authored and jackfrancis committed Aug 30, 2018
1 parent 8592e49 commit 93a0267
Show file tree
Hide file tree
Showing 27 changed files with 1,417 additions and 5 deletions.
3 changes: 2 additions & 1 deletion Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 26 additions & 2 deletions cmd/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,8 +308,32 @@ func autofillApimodel(dc *deployCmd) error {
return err
}

useManagedIdentity := dc.containerService.Properties.OrchestratorProfile.KubernetesConfig != nil &&
dc.containerService.Properties.OrchestratorProfile.KubernetesConfig.UseManagedIdentity
k8sConfig := dc.containerService.Properties.OrchestratorProfile.KubernetesConfig

useManagedIdentity := k8sConfig != nil &&
k8sConfig.UseManagedIdentity

userAssignedID := k8sConfig != nil &&
k8sConfig.UseManagedIdentity &&
k8sConfig.UserAssignedID != ""

// Note: User assigned identity can be assigned from the ARM template, but the role assigment following that will
// fail due to a bug with the service. This code is added to wait till the newly created AAD identity is properly
// propogated.
if userAssignedID {
userID, err := dc.client.CreateUserAssignedID(dc.location, dc.resourceGroup, k8sConfig.UserAssignedID)
if err != nil {
return nil
}
// Fill up the client id for creating azure.json
k8sConfig.UserAssignedClientID = (*userID.ClientID).String()
err = dc.client.CreateRoleAssignmentSimple(ctx, dc.resourceGroup, (*userID.PrincipalID).String())
if err != nil {
return errors.Wrap(err, "apimodel: could not create role assignment for user assigned id ")
}
//TODO: Support e2e return fake user id.
return nil
}

if !useManagedIdentity {
spp := dc.containerService.Properties.ServicePrincipalProfile
Expand Down
36 changes: 36 additions & 0 deletions examples/kubernetes-msi-userassigned/kube-vma.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"apiVersion": "vlabs",
"properties": {
"orchestratorProfile": {
"orchestratorType": "Kubernetes",
"kubernetesConfig": {
"useManagedIdentity": true,
"userAssignedID": "acsenginetestid"
}
},
"masterProfile": {
"count": 1,
"dnsPrefix": "",
"vmSize": "Standard_D2_v2"
},
"agentPoolProfiles": [
{
"name": "agentpool1",
"count": 3,
"vmSize": "Standard_D2_v2",
"availabilityProfile": "AvailabilitySet",
"storageProfile": "ManagedDisks"
}
],
"linuxProfile": {
"adminUsername": "azureuser",
"ssh": {
"publicKeys": [
{
"keyData": ""
}
]
}
}
}
}
36 changes: 36 additions & 0 deletions examples/kubernetes-msi-userassigned/kube-vmss.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"apiVersion": "vlabs",
"properties": {
"orchestratorProfile": {
"orchestratorType": "Kubernetes",
"kubernetesConfig": {
"useManagedIdentity": true,
"userAssignedID": "acsenginetestid"
}
},
"masterProfile": {
"count": 1,
"dnsPrefix": "",
"vmSize": "Standard_D2_v2"
},
"agentPoolProfiles": [
{
"name": "agentpool1",
"count": 3,
"vmSize": "Standard_D2_v2",
"availabilityProfile": "VirtualMachineScaleSets",
"storageProfile": "ManagedDisks"
}
],
"linuxProfile": {
"adminUsername": "azureuser",
"ssh": {
"publicKeys": [
{
"keyData": ""
}
]
}
}
}
}
21 changes: 21 additions & 0 deletions parts/k8s/kubernetesagentresourcesvmas.t
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,14 @@
},
{{end}}
{
{{if UserAssignedIDEnabled}}
"apiVersion": "[variables('apiVersionUserMSI')]",
{{else}}
{{if .IsManagedDisks}}
"apiVersion": "[variables('apiVersionStorageManagedDisks')]",
{{else}}
"apiVersion": "[variables('apiVersionDefault')]",
{{end}}
{{end}}
"copy": {
"count": "[sub(variables('{{.Name}}Count'), variables('{{.Name}}Offset'))]",
Expand Down Expand Up @@ -177,10 +181,19 @@
"location": "[variables('location')]",
"name": "[concat(variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')))]",
{{if UseManagedIdentity}}
{{if UserAssignedIDEnabled}}
"identity": {
"type": "userAssigned",
"userAssignedIdentities": {
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities/', variables('userAssignedID'))]":{}
}
},
{{else}}
"identity": {
"type": "systemAssigned"
},
{{end}}
{{end}}
{{if and IsOpenShift (not (UseAgentCustomImage .))}}
"plan": {
"name": "[variables('{{.Name}}osImageSKU')]",
Expand Down Expand Up @@ -256,6 +269,7 @@
"type": "Microsoft.Compute/virtualMachines"
},
{{if UseManagedIdentity}}
{{if (not UserAssignedIDEnabled)}}
{
"apiVersion": "2014-10-01-preview",
"copy": {
Expand All @@ -269,6 +283,7 @@
"principalId": "[reference(concat('Microsoft.Compute/virtualMachines/', variables('{{.Name}}VMNamePrefix'), copyIndex()), '2017-03-30', 'Full').identity.principalId]"
}
},
{{end}}
{
"type": "Microsoft.Compute/virtualMachines/extensions",
"name": "[concat(variables('{{.Name}}VMNamePrefix'), copyIndex(), '/ManagedIdentityExtension')]",
Expand All @@ -278,10 +293,16 @@
},
"apiVersion": "2015-05-01-preview",
"location": "[resourceGroup().location]",
{{if UserAssignedIDEnabled}}
"dependsOn": [
"[concat('Microsoft.Compute/virtualMachines/', variables('{{.Name}}VMNamePrefix'), copyIndex())]"
],
{{else}}
"dependsOn": [
"[concat('Microsoft.Compute/virtualMachines/', variables('{{.Name}}VMNamePrefix'), copyIndex())]",
"[concat('Microsoft.Authorization/roleAssignments/', guid(concat('Microsoft.Compute/virtualMachines/', variables('{{.Name}}VMNamePrefix'), copyIndex(), 'vmidentity')))]"
],
{{end}}
"properties": {
"publisher": "Microsoft.ManagedIdentity",
"type": "ManagedIdentityExtensionForLinux",
Expand Down
11 changes: 10 additions & 1 deletion parts/k8s/kubernetesagentresourcesvmss.t
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{{if UseManagedIdentity}}
{{if and UseManagedIdentity (not UserAssignedIDEnabled)}}
{
"apiVersion": "2014-10-01-preview",
"name": "[guid(concat('Microsoft.Compute/virtualMachineScaleSets/', variables('{{.Name}}VMNamePrefix'), 'vmidentity'))]",
Expand Down Expand Up @@ -28,10 +28,19 @@
"location": "[variables('location')]",
"name": "[variables('{{.Name}}VMNamePrefix')]",
{{if UseManagedIdentity}}
{{if UserAssignedIDEnabled}}
"identity": {
"type": "userAssigned",
"identityIds": [
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities/', variables('userAssignedID'))]"
]
},
{{else}}
"identity": {
"type": "systemAssigned"
},
{{end}}
{{end}}
"sku": {
"tier": "Standard",
"capacity": "[variables('{{.Name}}Count')]",
Expand Down
8 changes: 8 additions & 0 deletions parts/k8s/kubernetesbase.t
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@
{{template "k8s/kubernetesmastervars.t" .}}
},
"resources": [
{{if UserAssignedIDEnabled}}
{
"type": "Microsoft.ManagedIdentity/userAssignedIdentities",
"name": "[variables('userAssignedID')]",
"apiVersion": "2015-08-31-PREVIEW",
"location": "[variables('location')]"
},
{{end}}
{{if IsOpenShift}}
{{template "openshift/infraresources.t" .}}
{{end}}
Expand Down
1 change: 1 addition & 0 deletions parts/k8s/kubernetesconfigs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ function configureK8s() {
"cloudProviderRateLimitQPS": ${CLOUDPROVIDER_RATELIMIT_QPS},
"cloudProviderRateLimitBucket": ${CLOUDPROVIDER_RATELIMIT_BUCKET},
"useManagedIdentityExtension": ${USE_MANAGED_IDENTITY_EXTENSION},
"userAssignedIdentityID": "${USER_ASSIGNED_IDENTITY_ID}",
"useInstanceMetadata": ${USE_INSTANCE_METADATA},
"loadBalancerSku": "${LOAD_BALANCER_SKU}",
"excludeMasterFromStandardLB": ${EXCLUDE_MASTER_FROM_STANDARD_LB},
Expand Down
21 changes: 21 additions & 0 deletions parts/k8s/kubernetesmasterresources.t
Original file line number Diff line number Diff line change
Expand Up @@ -720,10 +720,14 @@
},
{{end}}
{
{{if UserAssignedIDEnabled}}
"apiVersion": "[variables('apiVersionUserMSI')]",
{{else}}
{{if .MasterProfile.IsManagedDisks}}
"apiVersion": "[variables('apiVersionStorageManagedDisks')]",
{{else}}
"apiVersion": "[variables('apiVersionDefault')]",
{{end}}
{{end}}
"copy": {
"count": "[sub(variables('masterCount'), variables('masterOffset'))]",
Expand All @@ -747,10 +751,19 @@
"location": "[variables('location')]",
"name": "[concat(variables('masterVMNamePrefix'), copyIndex(variables('masterOffset')))]",
{{if UseManagedIdentity}}
{{if UserAssignedIDEnabled}}
"identity": {
"type": "userAssigned",
"userAssignedIdentities": {
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities/', variables('userAssignedID'))]":{}
}
},
{{else}}
"identity": {
"type": "systemAssigned"
},
{{end}}
{{end}}
{{if and IsOpenShift (not UseMasterCustomImage)}}
"plan": {
"name": "[parameters('osImageSku')]",
Expand Down Expand Up @@ -839,6 +852,7 @@
"type": "Microsoft.Compute/virtualMachines"
},
{{if UseManagedIdentity}}
{{if (not UserAssignedIDEnabled)}}
{
"apiVersion": "2014-10-01-preview",
"copy": {
Expand All @@ -852,6 +866,7 @@
"principalId": "[reference(concat('Microsoft.Compute/virtualMachines/', variables('masterVMNamePrefix'), copyIndex()), '2017-03-30', 'Full').identity.principalId]"
}
},
{{end}}
{
"type": "Microsoft.Compute/virtualMachines/extensions",
"name": "[concat(variables('masterVMNamePrefix'), copyIndex(), '/ManagedIdentityExtension')]",
Expand All @@ -861,10 +876,16 @@
},
"apiVersion": "2015-05-01-preview",
"location": "[resourceGroup().location]",
{{if (not UserAssignedIDEnabled)}}
"dependsOn": [
"[concat('Microsoft.Compute/virtualMachines/', variables('masterVMNamePrefix'), copyIndex())]",
"[concat('Microsoft.Authorization/roleAssignments/', guid(concat('Microsoft.Compute/virtualMachines/', variables('masterVMNamePrefix'), copyIndex(), 'vmidentity')))]"
],
{{else}}
"dependsOn": [
"[concat('Microsoft.Compute/virtualMachines/', variables('masterVMNamePrefix'), copyIndex())]"
],
{{end}}
"properties": {
"publisher": "Microsoft.ManagedIdentity",
"type": "ManagedIdentityExtensionForLinux",
Expand Down
7 changes: 6 additions & 1 deletion parts/k8s/kubernetesmastervars.t
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@
{{end}}
{{end}}
"useManagedIdentityExtension": "{{ UseManagedIdentity }}",
"userAssignedID": "{{UserAssignedID}}",
"userAssignedClientID": "{{UserAssignedClientID}}",
"useInstanceMetadata": "{{ UseInstanceMetadata }}",
"loadBalancerSku": "{{ LoadBalancerSku }}",
"excludeMasterFromStandardLB": "{{ ExcludeMasterFromStandardLB }}",
Expand Down Expand Up @@ -115,6 +117,9 @@
"storageAccountPrefixes": [],
"storageAccountBaseName": "",
{{end}}
{{if UserAssignedIDEnabled}}
"apiVersionUserMSI": "2018-06-01",
{{end}}
{{if .HasManagedDisks}}
"apiVersionStorageManagedDisks": "2016-04-30-preview",
{{end}}
Expand All @@ -134,7 +139,7 @@
"customSearchDomainsScript": "{{GetKubernetesB64CustomSearchDomainsScript}}",
"sshdConfig": "{{GetB64sshdConfig}}",
{{if not IsOpenShift}}
"provisionScriptParametersCommon": "[concat('ADMINUSER=',parameters('linuxAdminUsername'),' ETCD_DOWNLOAD_URL=',parameters('etcdDownloadURLBase'),' ETCD_VERSION=',parameters('etcdVersion'),' DOCKER_ENGINE_VERSION=',parameters('dockerEngineVersion'),' DOCKER_REPO=',parameters('dockerEngineDownloadRepo'),' TENANT_ID=',variables('tenantID'),' KUBERNETES_VERSION={{.OrchestratorProfile.OrchestratorVersion}} HYPERKUBE_URL=',parameters('kubernetesHyperkubeSpec'),' APISERVER_PUBLIC_KEY=',parameters('apiserverCertificate'),' SUBSCRIPTION_ID=',variables('subscriptionId'),' RESOURCE_GROUP=',variables('resourceGroup'),' LOCATION=',variables('location'),' VM_TYPE=',variables('vmType'),' 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'),' PRIMARY_SCALE_SET=',variables('primaryScaleSetName'),' SERVICE_PRINCIPAL_CLIENT_ID=',variables('servicePrincipalClientId'),' SERVICE_PRINCIPAL_CLIENT_SECRET=',variables('singleQuote'),variables('servicePrincipalClientSecret'),variables('singleQuote'),' KUBELET_PRIVATE_KEY=',parameters('clientPrivateKey'),' TARGET_ENVIRONMENT=',parameters('targetEnvironment'),' NETWORK_PLUGIN=',parameters('networkPlugin'),' VNET_CNI_PLUGINS_URL=',parameters('vnetCniLinuxPluginsURL'),' CNI_PLUGINS_URL=',parameters('cniPluginsURL'),' CLOUDPROVIDER_BACKOFF=',parameters('cloudproviderConfig').cloudProviderBackoff,' CLOUDPROVIDER_BACKOFF_RETRIES=',parameters('cloudproviderConfig').cloudProviderBackoffRetries,' CLOUDPROVIDER_BACKOFF_EXPONENT=',parameters('cloudproviderConfig').cloudProviderBackoffExponent,' CLOUDPROVIDER_BACKOFF_DURATION=',parameters('cloudproviderConfig').cloudProviderBackoffDuration,' CLOUDPROVIDER_BACKOFF_JITTER=',parameters('cloudproviderConfig').cloudProviderBackoffJitter,' CLOUDPROVIDER_RATELIMIT=',parameters('cloudproviderConfig').cloudProviderRatelimit,' CLOUDPROVIDER_RATELIMIT_QPS=',parameters('cloudproviderConfig').cloudProviderRatelimitQPS,' CLOUDPROVIDER_RATELIMIT_BUCKET=',parameters('cloudproviderConfig').cloudProviderRatelimitBucket,' USE_MANAGED_IDENTITY_EXTENSION=',variables('useManagedIdentityExtension'),' USE_INSTANCE_METADATA=',variables('useInstanceMetadata'),' LOAD_BALANCER_SKU=',variables('loadBalancerSku'),' EXCLUDE_MASTER_FROM_STANDARD_LB=',variables('excludeMasterFromStandardLB'),' CONTAINER_RUNTIME=',parameters('containerRuntime'),' CONTAINERD_DOWNLOAD_URL_BASE=',parameters('containerdDownloadURLBase'),' POD_INFRA_CONTAINER_SPEC=',parameters('kubernetesPodInfraContainerSpec'),' KMS_PROVIDER_VAULT_NAME=',variables('clusterKeyVaultName'))]",
"provisionScriptParametersCommon": "[concat('ADMINUSER=',parameters('linuxAdminUsername'),' ETCD_DOWNLOAD_URL=',parameters('etcdDownloadURLBase'),' ETCD_VERSION=',parameters('etcdVersion'),' DOCKER_ENGINE_VERSION=',parameters('dockerEngineVersion'),' DOCKER_REPO=',parameters('dockerEngineDownloadRepo'),' TENANT_ID=',variables('tenantID'),' KUBERNETES_VERSION={{.OrchestratorProfile.OrchestratorVersion}} HYPERKUBE_URL=',parameters('kubernetesHyperkubeSpec'),' APISERVER_PUBLIC_KEY=',parameters('apiserverCertificate'),' SUBSCRIPTION_ID=',variables('subscriptionId'),' RESOURCE_GROUP=',variables('resourceGroup'),' LOCATION=',variables('location'),' VM_TYPE=',variables('vmType'),' 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'),' PRIMARY_SCALE_SET=',variables('primaryScaleSetName'),' SERVICE_PRINCIPAL_CLIENT_ID=',variables('servicePrincipalClientId'),' SERVICE_PRINCIPAL_CLIENT_SECRET=',variables('singleQuote'),variables('servicePrincipalClientSecret'),variables('singleQuote'),' KUBELET_PRIVATE_KEY=',parameters('clientPrivateKey'),' TARGET_ENVIRONMENT=',parameters('targetEnvironment'),' NETWORK_PLUGIN=',parameters('networkPlugin'),' VNET_CNI_PLUGINS_URL=',parameters('vnetCniLinuxPluginsURL'),' CNI_PLUGINS_URL=',parameters('cniPluginsURL'),' CLOUDPROVIDER_BACKOFF=',parameters('cloudproviderConfig').cloudProviderBackoff,' CLOUDPROVIDER_BACKOFF_RETRIES=',parameters('cloudproviderConfig').cloudProviderBackoffRetries,' CLOUDPROVIDER_BACKOFF_EXPONENT=',parameters('cloudproviderConfig').cloudProviderBackoffExponent,' CLOUDPROVIDER_BACKOFF_DURATION=',parameters('cloudproviderConfig').cloudProviderBackoffDuration,' CLOUDPROVIDER_BACKOFF_JITTER=',parameters('cloudproviderConfig').cloudProviderBackoffJitter,' CLOUDPROVIDER_RATELIMIT=',parameters('cloudproviderConfig').cloudProviderRatelimit,' CLOUDPROVIDER_RATELIMIT_QPS=',parameters('cloudproviderConfig').cloudProviderRatelimitQPS,' CLOUDPROVIDER_RATELIMIT_BUCKET=',parameters('cloudproviderConfig').cloudProviderRatelimitBucket,' USE_MANAGED_IDENTITY_EXTENSION=',variables('useManagedIdentityExtension'),' USER_ASSIGNED_IDENTITY_ID=',variables('userAssignedClientID'),' USE_INSTANCE_METADATA=',variables('useInstanceMetadata'),' LOAD_BALANCER_SKU=',variables('loadBalancerSku'),' EXCLUDE_MASTER_FROM_STANDARD_LB=',variables('excludeMasterFromStandardLB'),' CONTAINER_RUNTIME=',parameters('containerRuntime'),' CONTAINERD_DOWNLOAD_URL_BASE=',parameters('containerdDownloadURLBase'),' POD_INFRA_CONTAINER_SPEC=',parameters('kubernetesPodInfraContainerSpec'),' KMS_PROVIDER_VAULT_NAME=',variables('clusterKeyVaultName'))]",
{{if not IsHostedMaster}}
"provisionScriptParametersMaster": "[concat('MASTER_VM_NAME=',variables('masterVMNames')[variables('masterOffset')],' ETCD_PEER_URL=',variables('masterEtcdPeerURLs')[variables('masterOffset')],' ETCD_CLIENT_URL=',variables('masterEtcdClientURLs')[variables('masterOffset')],' MASTER_NODE=true CLUSTER_AUTOSCALER_ADDON=',parameters('kubernetesClusterAutoscalerEnabled'),' ACI_CONNECTOR_ADDON=',parameters('kubernetesACIConnectorEnabled'),' APISERVER_PRIVATE_KEY=',parameters('apiServerPrivateKey'),' CA_CERTIFICATE=',parameters('caCertificate'),' CA_PRIVATE_KEY=',parameters('caPrivateKey'),' MASTER_FQDN=',variables('masterFqdnPrefix'),' KUBECONFIG_CERTIFICATE=',parameters('kubeConfigCertificate'),' KUBECONFIG_KEY=',parameters('kubeConfigPrivateKey'),' ETCD_SERVER_CERTIFICATE=',parameters('etcdServerCertificate'),' ETCD_CLIENT_CERTIFICATE=',parameters('etcdClientCertificate'),' ETCD_SERVER_PRIVATE_KEY=',parameters('etcdServerPrivateKey'),' ETCD_CLIENT_PRIVATE_KEY=',parameters('etcdClientPrivateKey'),' ETCD_PEER_CERTIFICATES=',string(variables('etcdPeerCertificates')),' ETCD_PEER_PRIVATE_KEYS=',string(variables('etcdPeerPrivateKeys')),' ENABLE_AGGREGATED_APIS=',string(parameters('enableAggregatedAPIs')),' KUBECONFIG_SERVER=',variables('kubeconfigServer'))]",
{{end}}
Expand Down
2 changes: 2 additions & 0 deletions parts/k8s/kuberneteswindowssetup.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ $global:KubeNetwork = "l2bridge"
$global:KubeDnsSearchPath = "svc.cluster.local"

$global:UseManagedIdentityExtension = "{{WrapAsVariable "useManagedIdentityExtension"}}"
$global:UserAssignedClientID = "{{WrapAsVariable "userAssignedClientID"}}"
$global:UseInstanceMetadata = "{{WrapAsVariable "useInstanceMetadata"}}"
$global:LoadBalancerSku = "{{WrapAsVariable "loadBalancerSku"}}"
$global:ExcludeMasterFromStandardLB = "{{WrapAsVariable "excludeMasterFromStandardLB"}}"
Expand Down Expand Up @@ -185,6 +186,7 @@ Write-AzureConfig()
"primaryAvailabilitySetName": "$global:PrimaryAvailabilitySetName",
"primaryScaleSetName": "$global:PrimaryScaleSetName",
"useManagedIdentityExtension": $global:UseManagedIdentityExtension,
"userAssignedIdentityID": $global:UserAssignedClientID,
"useInstanceMetadata": $global:UseInstanceMetadata,
"loadBalancerSku": "$global:LoadBalancerSku",
"excludeMasterFromStandardLB": $global:ExcludeMasterFromStandardLB
Expand Down
Loading

0 comments on commit 93a0267

Please sign in to comment.