diff --git a/contrib/azurerm/.gitignore b/contrib/azurerm/.gitignore new file mode 100644 index 000000000..3a04fb276 --- /dev/null +++ b/contrib/azurerm/.gitignore @@ -0,0 +1,2 @@ +.generated +/inventory \ No newline at end of file diff --git a/contrib/azurerm/README.md b/contrib/azurerm/README.md new file mode 100644 index 000000000..d8cd28e7f --- /dev/null +++ b/contrib/azurerm/README.md @@ -0,0 +1,64 @@ +# Kubernetes on Azure with Azure Resource Group Templates + +Provision the base infrastructure for a Kubernetes cluster by using [Azure Resource Group Templates](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-authoring-templates) + +## Status + +This will provision the base infrastructure (vnet, vms, nics, ips, ...) needed for Kubernetes in Azure into the specified +Resource Group. It will not install Kubernetes itself, this has to be done in a later step by yourself (using kargo of course). + +## Requirements + +- [Install azure-cli](https://docs.microsoft.com/en-us/azure/xplat-cli-install) +- [Login with azure-cli](https://docs.microsoft.com/en-us/azure/xplat-cli-connect) +- Dedicated Resource Group created in the Azure Portal or through azure-cli + +## Configuration through group_vars/all + +You have to modify at least one variable in group_vars/all, which is the **cluster_name** variable. It must be globally +unique due to some restrictions in Azure. Most other variables should be self explanatory if you have some basic Kubernetes +experience. + +## Bastion host + +You can enable the use of a Bastion Host by changing **use_bastion** in group_vars/all to **true**. The generated +templates will then include an additional bastion VM which can then be used to connect to the masters and nodes. The option +also removes all public IPs from all other VMs. + +## Generating and applying + +To generate and apply the templates, call: + +```shell +$ ./apply-rg.sh +``` + +If you change something in the configuration (e.g. number of nodes) later, you can call this again and Azure will +take care about creating/modifying whatever is needed. + +## Clearing a resource group + +If you need to delete all resources from a resource group, simply call: + +```shell +$ ./clear-rg.sh +``` + +**WARNING** this really deletes everything from your resource group, including everything that was later created by you! + + +## Generating an inventory for kargo + +After you have applied the templates, you can generate an inventory with this call: + +```shell +$ ./generate-inventory.sh +``` + +It will create the file ./inventory which can then be used with kargo, e.g.: + +```shell +$ cd kargo-root-dir +$ ansible-playbook -i contrib/azurerm/inventory -u devops --become -e "@inventory/group_vars/all.yml" cluster.yml +``` + diff --git a/contrib/azurerm/apply-rg.sh b/contrib/azurerm/apply-rg.sh new file mode 100755 index 000000000..392353d87 --- /dev/null +++ b/contrib/azurerm/apply-rg.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +set -e + +AZURE_RESOURCE_GROUP="$1" + +if [ "$AZURE_RESOURCE_GROUP" == "" ]; then + echo "AZURE_RESOURCE_GROUP is missing" + exit 1 +fi + +ansible-playbook generate-templates.yml + +azure group deployment create -f ./.generated/network.json -g $AZURE_RESOURCE_GROUP +azure group deployment create -f ./.generated/storage.json -g $AZURE_RESOURCE_GROUP +azure group deployment create -f ./.generated/availability-sets.json -g $AZURE_RESOURCE_GROUP +azure group deployment create -f ./.generated/bastion.json -g $AZURE_RESOURCE_GROUP +azure group deployment create -f ./.generated/masters.json -g $AZURE_RESOURCE_GROUP +azure group deployment create -f ./.generated/minions.json -g $AZURE_RESOURCE_GROUP \ No newline at end of file diff --git a/contrib/azurerm/clear-rg.sh b/contrib/azurerm/clear-rg.sh new file mode 100755 index 000000000..d83253660 --- /dev/null +++ b/contrib/azurerm/clear-rg.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +set -e + +AZURE_RESOURCE_GROUP="$1" + +if [ "$AZURE_RESOURCE_GROUP" == "" ]; then + echo "AZURE_RESOURCE_GROUP is missing" + exit 1 +fi + +ansible-playbook generate-templates.yml + +azure group deployment create -g "$AZURE_RESOURCE_GROUP" -f ./.generated/clear-rg.json -m Complete \ No newline at end of file diff --git a/contrib/azurerm/generate-inventory.sh b/contrib/azurerm/generate-inventory.sh new file mode 100755 index 000000000..f6eaa5d28 --- /dev/null +++ b/contrib/azurerm/generate-inventory.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +set -e + +AZURE_RESOURCE_GROUP="$1" + +if [ "$AZURE_RESOURCE_GROUP" == "" ]; then + echo "AZURE_RESOURCE_GROUP is missing" + exit 1 +fi + +ansible-playbook generate-inventory.yml -e azure_resource_group="$AZURE_RESOURCE_GROUP" diff --git a/contrib/azurerm/generate-inventory.yml b/contrib/azurerm/generate-inventory.yml new file mode 100644 index 000000000..2f5373d89 --- /dev/null +++ b/contrib/azurerm/generate-inventory.yml @@ -0,0 +1,5 @@ +--- +- hosts: localhost + gather_facts: False + roles: + - generate-inventory diff --git a/contrib/azurerm/generate-templates.yml b/contrib/azurerm/generate-templates.yml new file mode 100644 index 000000000..3d4b1ca01 --- /dev/null +++ b/contrib/azurerm/generate-templates.yml @@ -0,0 +1,5 @@ +--- +- hosts: localhost + gather_facts: False + roles: + - generate-templates diff --git a/contrib/azurerm/group_vars/all b/contrib/azurerm/group_vars/all new file mode 100644 index 000000000..d7c49742a --- /dev/null +++ b/contrib/azurerm/group_vars/all @@ -0,0 +1,26 @@ + +# Due to some Azure limitations, this name must be globally unique +cluster_name: example + +# Set this to true if you do not want to have public IPs for your masters and minions. This will provision a bastion +# node that can be used to access the masters and minions +use_bastion: false + +number_of_k8s_masters: 3 +number_of_k8s_nodes: 3 + +masters_vm_size: Standard_A2 +masters_os_disk_size: 1000 + +minions_vm_size: Standard_A2 +minions_os_disk_size: 1000 + +admin_username: devops +admin_password: changeme +ssh_public_key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLRzcxbsFDdEibiyXCSdIFh7bKbXso1NqlKjEyPTptf3aBXHEhVil0lJRjGpTlpfTy7PHvXFbXIOCdv9tOmeH1uxWDDeZawgPFV6VSZ1QneCL+8bxzhjiCn8133wBSPZkN8rbFKd9eEUUBfx8ipCblYblF9FcidylwtMt5TeEmXk8yRVkPiCuEYuDplhc2H0f4PsK3pFb5aDVdaDT3VeIypnOQZZoUxHWqm6ThyHrzLJd3SrZf+RROFWW1uInIDf/SZlXojczUYoffxgT1lERfOJCHJXsqbZWugbxQBwqsVsX59+KPxFFo6nV88h3UQr63wbFx52/MXkX4WrCkAHzN ablock-vwfs@dell-lappy" + +# Azure CIDRs +azure_vnet_cidr: 10.0.0.0/8 +azure_admin_cidr: 10.241.2.0/24 +azure_masters_cidr: 10.0.4.0/24 +azure_minions_cidr: 10.240.0.0/16 diff --git a/contrib/azurerm/roles/generate-inventory/tasks/main.yml b/contrib/azurerm/roles/generate-inventory/tasks/main.yml new file mode 100644 index 000000000..92c6f7be9 --- /dev/null +++ b/contrib/azurerm/roles/generate-inventory/tasks/main.yml @@ -0,0 +1,11 @@ +--- + +- name: Query Azure VMs + command: azure vm list-ip-address --json {{ azure_resource_group }} + register: vm_list_cmd + +- set_fact: + vm_list: "{{ vm_list_cmd.stdout }}" + +- name: Generate inventory + template: src=inventory.j2 dest="{{playbook_dir}}/inventory" \ No newline at end of file diff --git a/contrib/azurerm/roles/generate-inventory/templates/inventory.j2 b/contrib/azurerm/roles/generate-inventory/templates/inventory.j2 new file mode 100644 index 000000000..cd93a2bb6 --- /dev/null +++ b/contrib/azurerm/roles/generate-inventory/templates/inventory.j2 @@ -0,0 +1,33 @@ + +{% for vm in vm_list %} +{% if not use_bastion or vm.name == 'bastion' %} +{{ vm.name }} ansible_ssh_host={{ vm.networkProfile.networkInterfaces[0].expanded.ipConfigurations[0].publicIPAddress.expanded.ipAddress }} ip={{ vm.networkProfile.networkInterfaces[0].expanded.ipConfigurations[0].privateIPAddress }} +{% else %} +{{ vm.name }} ansible_ssh_host={{ vm.networkProfile.networkInterfaces[0].expanded.ipConfigurations[0].privateIPAddress }} +{% endif %} +{% endfor %} + +[kube-master] +{% for vm in vm_list %} +{% if 'kube-master' in vm.tags.roles %} +{{ vm.name }} +{% endif %} +{% endfor %} + +[etcd] +{% for vm in vm_list %} +{% if 'etcd' in vm.tags.roles %} +{{ vm.name }} +{% endif %} +{% endfor %} + +[kube-node] +{% for vm in vm_list %} +{% if 'kube-node' in vm.tags.roles %} +{{ vm.name }} +{% endif %} +{% endfor %} + +[k8s-cluster:children] +kube-node +kube-master diff --git a/contrib/azurerm/roles/generate-templates/defaults/main.yml b/contrib/azurerm/roles/generate-templates/defaults/main.yml new file mode 100644 index 000000000..5ea0ff548 --- /dev/null +++ b/contrib/azurerm/roles/generate-templates/defaults/main.yml @@ -0,0 +1,37 @@ +apiVersion: "2015-06-15" + +virtualNetworkName: "KubVNET" + +subnetAdminName: "ad-subnet" +subnetMastersName: "master-subnet" +subnetMinionsName: "minion-subnet" + +routeTableName: "routetable" +securityGroupName: "secgroup" + +nameSuffix: "{{cluster_name}}" + +availabilitySetMasters: "master-avs" +availabilitySetMinions: "minion-avs" + +faultDomainCount: 3 +updateDomainCount: 10 + +bastionVmSize: Standard_A0 +bastionVMName: bastion +bastionIPAddressName: bastion-pubip + +disablePasswordAuthentication: true + +sshKeyPath: "/home/{{admin_username}}/.ssh/authorized_keys" + +imageReference: + publisher: "OpenLogic" + offer: "CentOS" + sku: "7.2" + version: "latest" +imageReferenceJson: "{{imageReference|to_json}}" + +storageAccountName: "sa{{nameSuffix | replace('-', '')}}" +storageAccountType: "Standard_LRS" + diff --git a/contrib/azurerm/roles/generate-templates/tasks/main.yml b/contrib/azurerm/roles/generate-templates/tasks/main.yml new file mode 100644 index 000000000..8b0789987 --- /dev/null +++ b/contrib/azurerm/roles/generate-templates/tasks/main.yml @@ -0,0 +1,14 @@ +- set_fact: + base_dir: "{{playbook_dir}}/.generated/" + +- file: path={{base_dir}} state=directory recurse=true + +- template: src={{item}} dest="{{base_dir}}/{{item}}" + with_items: + - network.json + - storage.json + - availability-sets.json + - bastion.json + - masters.json + - minions.json + - clear-rg.json diff --git a/contrib/azurerm/roles/generate-templates/templates/availability-sets.json b/contrib/azurerm/roles/generate-templates/templates/availability-sets.json new file mode 100644 index 000000000..4f458cd66 --- /dev/null +++ b/contrib/azurerm/roles/generate-templates/templates/availability-sets.json @@ -0,0 +1,30 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + }, + "variables": { + }, + "resources": [ + { + "type": "Microsoft.Compute/availabilitySets", + "name": "{{availabilitySetMasters}}", + "apiVersion": "{{apiVersion}}", + "location": "[resourceGroup().location]", + "properties": { + "PlatformFaultDomainCount": "{{faultDomainCount}}", + "PlatformUpdateDomainCount": "{{updateDomainCount}}" + } + }, + { + "type": "Microsoft.Compute/availabilitySets", + "name": "{{availabilitySetMinions}}", + "apiVersion": "{{apiVersion}}", + "location": "[resourceGroup().location]", + "properties": { + "PlatformFaultDomainCount": "{{faultDomainCount}}", + "PlatformUpdateDomainCount": "{{updateDomainCount}}" + } + } + ] +} \ No newline at end of file diff --git a/contrib/azurerm/roles/generate-templates/templates/bastion.json b/contrib/azurerm/roles/generate-templates/templates/bastion.json new file mode 100644 index 000000000..d765c9d36 --- /dev/null +++ b/contrib/azurerm/roles/generate-templates/templates/bastion.json @@ -0,0 +1,99 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + }, + "variables": { + "vnetID": "[resourceId('Microsoft.Network/virtualNetworks', '{{virtualNetworkName}}')]", + "subnetAdminRef": "[concat(variables('vnetID'),'/subnets/', '{{subnetAdminName}}')]" + }, + "resources": [ + {% if use_bastion %} + { + "apiVersion": "{{apiVersion}}", + "type": "Microsoft.Network/publicIPAddresses", + "name": "{{bastionIPAddressName}}", + "location": "[resourceGroup().location]", + "properties": { + "publicIPAllocationMethod": "Static" + } + }, + { + "apiVersion": "{{apiVersion}}", + "type": "Microsoft.Network/networkInterfaces", + "name": "{{bastionVMName}}-nic", + "location": "[resourceGroup().location]", + "dependsOn": [ + "[concat('Microsoft.Network/publicIPAddresses/', '{{bastionIPAddressName}}')]" + ], + "properties": { + "ipConfigurations": [ + { + "name": "BastionIpConfig", + "properties": { + "privateIPAllocationMethod": "Dynamic", + "publicIPAddress": { + "id": "[resourceId('Microsoft.Network/publicIPAddresses', '{{bastionIPAddressName}}')]" + }, + "subnet": { + "id": "[variables('subnetAdminRef')]" + } + } + } + ] + } + }, + { + "apiVersion": "{{apiVersion}}", + "type": "Microsoft.Compute/virtualMachines", + "name": "{{bastionVMName}}", + "location": "[resourceGroup().location]", + "dependsOn": [ + "[concat('Microsoft.Network/networkInterfaces/', '{{bastionVMName}}-nic')]" + ], + "tags": { + "roles": "bastion" + }, + "properties": { + "hardwareProfile": { + "vmSize": "{{bastionVmSize}}" + }, + "osProfile": { + "computerName": "{{bastionVMName}}", + "adminUsername": "{{admin_username}}", + "adminPassword": "{{admin_password}}", + "linuxConfiguration": { + "disablePasswordAuthentication": "true", + "ssh": { + "publicKeys": [ + { + "path": "{{sshKeyPath}}", + "keyData": "{{ssh_public_key}}" + } + ] + } + } + }, + "storageProfile": { + "imageReference": {{imageReferenceJson}}, + "osDisk": { + "name": "osdisk", + "vhd": { + "uri": "[concat('http://', '{{storageAccountName}}', '.blob.core.windows.net/vhds/', '{{bastionVMName}}', '-osdisk.vhd')]" + }, + "caching": "ReadWrite", + "createOption": "FromImage" + } + }, + "networkProfile": { + "networkInterfaces": [ + { + "id": "[resourceId('Microsoft.Network/networkInterfaces', '{{bastionVMName}}-nic')]" + } + ] + } + } + } + {% endif %} + ] +} \ No newline at end of file diff --git a/contrib/azurerm/roles/generate-templates/templates/clear-rg.json b/contrib/azurerm/roles/generate-templates/templates/clear-rg.json new file mode 100644 index 000000000..5facf5e67 --- /dev/null +++ b/contrib/azurerm/roles/generate-templates/templates/clear-rg.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": {}, + "variables": {}, + "resources": [], + "outputs": {} +} \ No newline at end of file diff --git a/contrib/azurerm/roles/generate-templates/templates/masters.json b/contrib/azurerm/roles/generate-templates/templates/masters.json new file mode 100644 index 000000000..c85addac8 --- /dev/null +++ b/contrib/azurerm/roles/generate-templates/templates/masters.json @@ -0,0 +1,196 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + }, + "variables": { + "lbDomainName": "{{nameSuffix}}-api", + "lbPublicIPAddressName": "kubernetes-api-pubip", + "lbPublicIPAddressType": "Static", + "lbPublicIPAddressID": "[resourceId('Microsoft.Network/publicIPAddresses',variables('lbPublicIPAddressName'))]", + "lbName": "kubernetes-api", + "lbID": "[resourceId('Microsoft.Network/loadBalancers',variables('lbName'))]", + + "vnetID": "[resourceId('Microsoft.Network/virtualNetworks', '{{virtualNetworkName}}')]", + "kubeMastersSubnetRef": "[concat(variables('vnetID'),'/subnets/', '{{subnetMastersName}}')]" + }, + "resources": [ + { + "apiVersion": "{{apiVersion}}", + "type": "Microsoft.Network/publicIPAddresses", + "name": "[variables('lbPublicIPAddressName')]", + "location": "[resourceGroup().location]", + "properties": { + "publicIPAllocationMethod": "[variables('lbPublicIPAddressType')]", + "dnsSettings": { + "domainNameLabel": "[variables('lbDomainName')]" + } + } + }, + { + "apiVersion": "{{apiVersion}}", + "name": "[variables('lbName')]", + "type": "Microsoft.Network/loadBalancers", + "location": "[resourceGroup().location]", + "dependsOn": [ + "[concat('Microsoft.Network/publicIPAddresses/', variables('lbPublicIPAddressName'))]" + ], + "properties": { + "frontendIPConfigurations": [ + { + "name": "kube-api-frontend", + "properties": { + "publicIPAddress": { + "id": "[variables('lbPublicIPAddressID')]" + } + } + } + ], + "backendAddressPools": [ + { + "name": "kube-api-backend" + } + ], + "loadBalancingRules": [ + { + "name": "kube-api", + "properties": { + "frontendIPConfiguration": { + "id": "[concat(variables('lbID'), '/frontendIPConfigurations/kube-api-frontend')]" + }, + "backendAddressPool": { + "id": "[concat(variables('lbID'), '/backendAddressPools/kube-api-backend')]" + }, + "protocol": "tcp", + "frontendPort": 443, + "backendPort": 443, + "enableFloatingIP": false, + "idleTimeoutInMinutes": 5, + "probe": { + "id": "[concat(variables('lbID'), '/probes/kube-api')]" + } + } + } + ], + "probes": [ + { + "name": "kube-api", + "properties": { + "protocol": "tcp", + "port": 443, + "intervalInSeconds": 5, + "numberOfProbes": 2 + } + } + ] + } + }, + {% for i in range(number_of_k8s_masters) %} + {% if not use_bastion %} + { + "apiVersion": "{{apiVersion}}", + "type": "Microsoft.Network/publicIPAddresses", + "name": "master-{{i}}-pubip", + "location": "[resourceGroup().location]", + "properties": { + "publicIPAllocationMethod": "Static" + } + }, + {% endif %} + { + "apiVersion": "{{apiVersion}}", + "type": "Microsoft.Network/networkInterfaces", + "name": "master-{{i}}-nic", + "location": "[resourceGroup().location]", + "dependsOn": [ + {% if not use_bastion %} + "[concat('Microsoft.Network/publicIPAddresses/', 'master-{{i}}-pubip')]", + {% endif %} + "[concat('Microsoft.Network/loadBalancers/', variables('lbName'))]" + ], + "properties": { + "ipConfigurations": [ + { + "name": "MastersIpConfig", + "properties": { + "privateIPAllocationMethod": "Dynamic", + {% if not use_bastion %} + "publicIPAddress": { + "id": "[resourceId('Microsoft.Network/publicIPAddresses', 'master-{{i}}-pubip')]" + }, + {% endif %} + "subnet": { + "id": "[variables('kubeMastersSubnetRef')]" + }, + "loadBalancerBackendAddressPools": [ + { + "id": "[concat(variables('lbID'), '/backendAddressPools/kube-api-backend')]" + } + ] + } + } + ], + "networkSecurityGroup": { + "id": "[resourceId('Microsoft.Network/networkSecurityGroups', '{{securityGroupName}}')]" + }, + "enableIPForwarding": true + } + }, + { + "type": "Microsoft.Compute/virtualMachines", + "name": "master-{{i}}", + "location": "[resourceGroup().location]", + "dependsOn": [ + "[concat('Microsoft.Network/networkInterfaces/', 'master-{{i}}-nic')]" + ], + "tags": { + "roles": "kube-master,etcd" + }, + "apiVersion": "{{apiVersion}}", + "properties": { + "availabilitySet": { + "id": "[resourceId('Microsoft.Compute/availabilitySets', '{{availabilitySetMasters}}')]" + }, + "hardwareProfile": { + "vmSize": "{{masters_vm_size}}" + }, + "osProfile": { + "computerName": "master-{{i}}", + "adminUsername": "{{admin_username}}", + "adminPassword": "{{admin_password}}", + "linuxConfiguration": { + "disablePasswordAuthentication": "{{disablePasswordAuthentication}}", + "ssh": { + "publicKeys": [ + { + "path": "{{sshKeyPath}}", + "keyData": "{{ssh_public_key}}" + } + ] + } + } + }, + "storageProfile": { + "imageReference": {{imageReferenceJson}}, + "osDisk": { + "name": "ma{{nameSuffix}}{{i}}", + "vhd": { + "uri": "[concat('http://','{{storageAccountName}}','.blob.core.windows.net/vhds/master-{{i}}.vhd')]" + }, + "caching": "ReadWrite", + "createOption": "FromImage", + "diskSizeGB": "{{masters_os_disk_size}}" + } + }, + "networkProfile": { + "networkInterfaces": [ + { + "id": "[resourceId('Microsoft.Network/networkInterfaces', 'master-{{i}}-nic')]" + } + ] + } + } + } {% if not loop.last %},{% endif %} + {% endfor %} + ] +} \ No newline at end of file diff --git a/contrib/azurerm/roles/generate-templates/templates/minions.json b/contrib/azurerm/roles/generate-templates/templates/minions.json new file mode 100644 index 000000000..d25769374 --- /dev/null +++ b/contrib/azurerm/roles/generate-templates/templates/minions.json @@ -0,0 +1,113 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + }, + "variables": { + "vnetID": "[resourceId('Microsoft.Network/virtualNetworks', '{{virtualNetworkName}}')]", + "kubeMinionsSubnetRef": "[concat(variables('vnetID'),'/subnets/', '{{subnetMinionsName}}')]" + }, + "resources": [ + {% for i in range(number_of_k8s_nodes) %} + {% if not use_bastion %} + { + "apiVersion": "{{apiVersion}}", + "type": "Microsoft.Network/publicIPAddresses", + "name": "minion-{{i}}-pubip", + "location": "[resourceGroup().location]", + "properties": { + "publicIPAllocationMethod": "Static" + } + }, + {% endif %} + { + "apiVersion": "{{apiVersion}}", + "type": "Microsoft.Network/networkInterfaces", + "name": "minion-{{i}}-nic", + "location": "[resourceGroup().location]", + "dependsOn": [ + {% if not use_bastion %} + "[concat('Microsoft.Network/publicIPAddresses/', 'minion-{{i}}-pubip')]" + {% endif %} + ], + "properties": { + "ipConfigurations": [ + { + "name": "MinionsIpConfig", + "properties": { + "privateIPAllocationMethod": "Dynamic", + {% if not use_bastion %} + "publicIPAddress": { + "id": "[resourceId('Microsoft.Network/publicIPAddresses', 'minion-{{i}}-pubip')]" + }, + {% endif %} + "subnet": { + "id": "[variables('kubeMinionsSubnetRef')]" + } + } + } + ], + "networkSecurityGroup": { + "id": "[resourceId('Microsoft.Network/networkSecurityGroups', '{{securityGroupName}}')]" + }, + "enableIPForwarding": true + } + }, + { + "type": "Microsoft.Compute/virtualMachines", + "name": "minion-{{i}}", + "location": "[resourceGroup().location]", + "dependsOn": [ + "[concat('Microsoft.Network/networkInterfaces/', 'minion-{{i}}-nic')]" + ], + "tags": { + "roles": "kube-node" + }, + "apiVersion": "{{apiVersion}}", + "properties": { + "availabilitySet": { + "id": "[resourceId('Microsoft.Compute/availabilitySets', '{{availabilitySetMinions}}')]" + }, + "hardwareProfile": { + "vmSize": "{{minions_vm_size}}" + }, + "osProfile": { + "computerName": "minion-{{i}}", + "adminUsername": "{{admin_username}}", + "adminPassword": "{{admin_password}}", + "linuxConfiguration": { + "disablePasswordAuthentication": "{{disablePasswordAuthentication}}", + "ssh": { + "publicKeys": [ + { + "path": "{{sshKeyPath}}", + "keyData": "{{ssh_public_key}}" + } + ] + } + } + }, + "storageProfile": { + "imageReference": {{imageReferenceJson}}, + "osDisk": { + "name": "mi{{nameSuffix}}{{i}}", + "vhd": { + "uri": "[concat('http://','{{storageAccountName}}','.blob.core.windows.net/vhds/minion-{{i}}.vhd')]" + }, + "caching": "ReadWrite", + "createOption": "FromImage", + "diskSizeGB": "{{minions_os_disk_size}}" + } + }, + "networkProfile": { + "networkInterfaces": [ + { + "id": "[resourceId('Microsoft.Network/networkInterfaces', 'minion-{{i}}-nic')]" + } + ] + } + } + } {% if not loop.last %},{% endif %} + {% endfor %} + ] +} \ No newline at end of file diff --git a/contrib/azurerm/roles/generate-templates/templates/network.json b/contrib/azurerm/roles/generate-templates/templates/network.json new file mode 100644 index 000000000..728adf138 --- /dev/null +++ b/contrib/azurerm/roles/generate-templates/templates/network.json @@ -0,0 +1,109 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + }, + "variables": { + }, + "resources": [ + { + "apiVersion": "{{apiVersion}}", + "type": "Microsoft.Network/routeTables", + "name": "{{routeTableName}}", + "location": "[resourceGroup().location]", + "properties": { + "routes": [ + ] + } + }, + { + "type": "Microsoft.Network/virtualNetworks", + "name": "{{virtualNetworkName}}", + "location": "[resourceGroup().location]", + "apiVersion": "{{apiVersion}}", + "dependsOn": [ + "[concat('Microsoft.Network/routeTables/', '{{routeTableName}}')]" + ], + "properties": { + "addressSpace": { + "addressPrefixes": [ + "{{azure_vnet_cidr}}" + ] + }, + "subnets": [ + { + "name": "{{subnetMastersName}}", + "properties": { + "addressPrefix": "{{azure_masters_cidr}}", + "routeTable": { + "id": "[resourceId('Microsoft.Network/routeTables', '{{routeTableName}}')]" + } + } + }, + { + "name": "{{subnetMinionsName}}", + "properties": { + "addressPrefix": "{{azure_minions_cidr}}", + "routeTable": { + "id": "[resourceId('Microsoft.Network/routeTables', '{{routeTableName}}')]" + } + } + } + {% if use_bastion %} + ,{ + "name": "{{subnetAdminName}}", + "properties": { + "addressPrefix": "{{azure_admin_cidr}}", + "routeTable": { + "id": "[resourceId('Microsoft.Network/routeTables', '{{routeTableName}}')]" + } + } + } + {% endif %} + ] + } + }, + { + "apiVersion": "{{apiVersion}}", + "type": "Microsoft.Network/networkSecurityGroups", + "name": "{{securityGroupName}}", + "location": "[resourceGroup().location]", + "properties": { + "securityRules": [ + {% if not use_bastion %} + { + "name": "ssh", + "properties": { + "description": "Allow SSH", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "22", + "sourceAddressPrefix": "Internet", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 100, + "direction": "Inbound" + } + }, + {% endif %} + { + "name": "kube-api", + "properties": { + "description": "Allow secure kube-api", + "protocol": "Tcp", + "sourcePortRange": "*", + "destinationPortRange": "443", + "sourceAddressPrefix": "Internet", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 101, + "direction": "Inbound" + } + } + ] + }, + "resources": [], + "dependsOn": [] + } + ] +} \ No newline at end of file diff --git a/contrib/azurerm/roles/generate-templates/templates/storage.json b/contrib/azurerm/roles/generate-templates/templates/storage.json new file mode 100644 index 000000000..2632aba2c --- /dev/null +++ b/contrib/azurerm/roles/generate-templates/templates/storage.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + }, + "variables": { + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts", + "name": "{{storageAccountName}}", + "location": "[resourceGroup().location]", + "apiVersion": "{{apiVersion}}", + "properties": { + "accountType": "{{storageAccountType}}" + } + } + ] +} \ No newline at end of file