Skip to content
No description, website, or topics provided.
Branch: master
Clone or download
Latest commit 0403f28 May 5, 2019

Kubernetes The Hard Way on Azure

This tutorial is designed for Microsoft Azure and Azure CLI 2.0. It is a fork of the great Kubernetes The Hard Way from Kesley Hightower that describes same steps using Google Cloud Platform.

Azure part is based on the work done by Jonathan Carter - @lostintangent in this fork and Ivan Fioravanti - @ivanfioravanti in this fork.

This tutorial walks you through setting up Kubernetes the hard way. This guide is not for people looking for a fully automated command to bring up a Kubernetes cluster. If that's you then check out Azure Kubernetes Service (AKS), or the Getting Started Guides.

Kubernetes The Hard Way is optimized for learning, which means taking the long route to ensure you understand each task required to bootstrap a Kubernetes cluster.

The results of this tutorial should not be viewed as production ready, and may receive limited support from the community, but don't let that stop you from learning!

Target Audience

The target audience for this tutorial is someone planning to support a production Kubernetes cluster and wants to understand how everything fits together.

Cluster Details

Kubernetes The Hard Way guides you through bootstrapping a highly available Kubernetes cluster with end-to-end encryption between components and RBAC authentication.


This script creates the necessary infrastructure using ARM Template. The main difference between Provisioning Compute Resources is a setup system identity for Kubernetes master nodes. System Identity will be used to integrate the Kubernetes cloud provider with the Azure Resource Manager.

    "copy": {
        "name": "controller-assignments-copy",
        "count": "[variables('controllerCount')]"
    "apiVersion": "2017-09-01",
    "type": "Microsoft.Authorization/roleAssignments",
    "name": "[guid(resourceId('Microsoft.Compute/virtualMachines/', concat('controller-',copyIndex())))]",
    "properties": {
        "roleDefinitionId": "[variables(parameters('builtInRoleType'))]",
        "principalId": "[reference(resourceId('Microsoft.Compute/virtualMachines/', concat('controller-',copyIndex())), '2017-12-01', 'Full').identity.principalId]",
        "scope": "[resourceGroup().id]"
    "dependsOn": [
        "[concat('Microsoft.Compute/virtualMachines/', concat('controller-',copyIndex()))]"

In addition, the Cloud Provider configuration for Azure appears here.

Necessary data are obtained from Azure Instance Metadata service.

response=$(curl '' -H Metadata:true -s)
tenantId=$(echo $response | python -c 'import sys, json, base64; print (base64.b64decode(json.load(sys.stdin)["access_token"].split(".")[1]))' | python -c 'import sys, json, base64; print (json.load(sys.stdin)["tid"])')
subscriptionId=$(curl -s -H Metadata:true "")
location=$(curl -s -H Metadata:true "")

Cloud Provider configuration through /etc/kubernetes/azure.json file. Cloud provider config documentation.

    "cloud": "AzurePublicCloud",
    "tenantId": "${tenantId}",
    "subscriptionId": "${subscriptionId}",
    "aadClientId": "msi",
    "aadClientSecret": "msi",
    "resourceGroup": "kubernetes",
    "location": "${location}",
    "vmType": "standard",
    "subnetName": "kubernetes-subnet",
    "securityGroupName": "kubernetes-nsg",
    "vnetName": "kubernetes-vnet",
    "primaryAvailabilitySetName": "worker-as",
    "cloudProviderBackoff": true,
    "cloudProviderBackoffRetries": 6,
    "cloudProviderBackoffExponent": 1.5,
    "cloudProviderBackoffDuration": 5,
    "cloudProviderBackoffJitter": 1,
    "cloudProviderRatelimit": true,
    "cloudProviderRateLimitQPS": 3,
    "cloudProviderRateLimitBucket": 10,
    "useManagedIdentityExtension": true,
    "userAssignedIdentityID": "",
    "useInstanceMetadata": true,
    "loadBalancerSku": "Basic",
    "excludeMasterFromStandardLB": false,
    "providerVaultName": "",
    "maximumLoadBalancerRuleCount": 250,
    "providerKeyName": "k8s",
    "providerKeyVersion": ""

Additionally, the smoke test shows service exposure via load balancer using the Azure Voting App.

You can’t perform that action at this time.