2018-08-27 08:39:41 +02:00
# Azure
2024-10-26 17:33:43 +02:00
In this tutorial, we'll create a Kubernetes v1.31.2 cluster on Azure with Flatcar Linux.
2018-08-27 08:39:41 +02:00
We'll declare a Kubernetes cluster using the Typhoon Terraform module. Then apply the changes to create a resource group, virtual network, subnets, security groups, controller availability set, worker scale set, load balancer, and TLS assets.
Introduce the component system for managing pre-installed addons
* Previously: Typhoon provisions clusters with kube-system components
like CoreDNS, kube-proxy, and a chosen CNI provider (among flannel,
Calico, or Cilium) pre-installed. This is convenient since clusters
come with "batteries included". But it also means upgrading these
components is generally done in lock-step, by upgrading to a new
Typhoon / Kubernetes release
* It can be valuable to manage these components with a separate
plan/apply process or through automations and deploy systems. For
example, this allows managing CoreDNS separately from the cluster's
lifecycle.
* These "components" will continue to be pre-installed by default,
but a new `components` variable allows them to be disabled and
managed as "addons", components you apply after cluster creation
and manage on a rolling basis. For some of these, we may provide
Terraform modules to aide in managing these components.
```
module "cluster" {
# defaults
components = {
enable = true
coredns = {
enable = true
}
kube_proxy = {
enable = true
}
# Only the CNI set in var.networking will be installed
flannel = {
enable = true
}
calico = {
enable = true
}
cilium = {
enable = true
}
}
}
```
An earlier variable `install_container_networking = true/false` has
been removed, since it can now be achieved with this more extensible
and general components mechanism by setting the chosen networking
provider enable field to false.
2024-05-19 00:05:33 +02:00
Controller hosts are provisioned to run an `etcd-member` peer and a `kubelet` service. Worker hosts run a `kubelet` service. Controller nodes run `kube-apiserver` , `kube-scheduler` , `kube-controller-manager` , and `coredns` , while `kube-proxy` and (`flannel`, `calico` , or `cilium` ) run on every node. A generated `kubeconfig` provides `kubectl` access to the cluster.
2018-08-27 08:39:41 +02:00
## Requirements
* Azure account
* Azure DNS Zone (registered Domain Name or delegated subdomain)
2020-08-11 06:02:56 +02:00
* Terraform v0.13.0+
2018-08-27 08:39:41 +02:00
## Terraform Setup
2020-08-11 06:02:56 +02:00
Install [Terraform ](https://www.terraform.io/downloads.html ) v0.13.0+ on your system.
2018-08-27 08:39:41 +02:00
```sh
$ terraform version
2021-06-17 22:25:43 +02:00
Terraform v1.0.0
2018-08-27 08:39:41 +02:00
```
2018-10-07 19:57:16 +02:00
Read [concepts ](/architecture/concepts/ ) to learn about Terraform, modules, and organizing resources. Change to your infrastructure repository (e.g. `infra` ).
2018-08-27 08:39:41 +02:00
```
cd infra/clusters
```
## Provider
[Install ](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest ) the Azure `az` command line tool to [authenticate with Azure ](https://www.terraform.io/docs/providers/azurerm/authenticating_via_azure_cli.html ).
```
az login
```
Configure the Azure provider in a `providers.tf` file.
```tf
provider "azurerm" {
2020-08-11 06:02:56 +02:00
features {}
2018-08-27 08:39:41 +02:00
}
2020-08-11 06:02:56 +02:00
provider "ct" {}
terraform {
required_providers {
ct = {
source = "poseidon/ct"
2022-08-18 18:04:20 +02:00
version = "0.11.0"
2020-08-11 06:02:56 +02:00
}
azurerm = {
source = "hashicorp/azurerm"
2023-04-17 18:34:33 +02:00
version = "3.50.0"
2020-08-11 06:02:56 +02:00
}
}
2018-11-27 09:08:51 +01:00
}
2018-08-27 08:39:41 +02:00
```
Additional configuration options are described in the `azurerm` provider [docs ](https://www.terraform.io/docs/providers/azurerm/ ).
2020-05-10 02:37:35 +02:00
## Flatcar Linux Images
2020-04-19 00:30:28 +02:00
2020-05-10 02:37:35 +02:00
Flatcar Linux publishes images to the Azure Marketplace and requires accepting terms.
2020-04-19 00:30:28 +02:00
```
2020-05-10 02:37:35 +02:00
az vm image terms accept --publish kinvolk --offer flatcar-container-linux-free --plan stable
2022-10-13 18:47:45 +02:00
az vm image terms accept --publish kinvolk --offer flatcar-container-linux-free --plan stable-gen2
2020-04-19 00:30:28 +02:00
```
2018-08-27 08:39:41 +02:00
## Cluster
2020-10-21 07:47:19 +02:00
Define a Kubernetes cluster using the module `azure/flatcar-linux/kubernetes` .
2018-08-27 08:39:41 +02:00
```tf
2019-08-08 05:42:40 +02:00
module "ramius" {
2024-10-26 17:33:43 +02:00
source = "git::https://github.com/poseidon/typhoon//azure/flatcar-linux/kubernetes?ref=v1.31.2"
2018-08-27 08:39:41 +02:00
# Azure
cluster_name = "ramius"
2024-07-09 06:20:46 +02:00
location = "centralus"
2018-08-27 08:39:41 +02:00
dns_zone = "azure.example.com"
dns_zone_group = "example-group"
2024-08-03 00:01:48 +02:00
network_cidr = {
ipv4 = ["10.0.0.0/20"]
}
# instances
worker_count = 2
2018-08-27 08:39:41 +02:00
# configuration
ssh_authorized_key = "ssh-rsa AAAAB3Nz..."
}
```
2020-10-21 07:47:19 +02:00
Reference the [variables docs ](#variables ) or the [variables.tf ](https://github.com/poseidon/typhoon/blob/master/azure/flatcar-linux/kubernetes/variables.tf ) source.
2018-08-27 08:39:41 +02:00
## ssh-agent
2019-09-06 08:12:09 +02:00
Initial bootstrapping requires `bootstrap.service` be started on one controller node. Terraform uses `ssh-agent` to automate this step. Add your SSH private key to `ssh-agent` .
2018-08-27 08:39:41 +02:00
```sh
ssh-add ~/.ssh/id_rsa
ssh-add -L
```
## Apply
Initialize the config directory if this is the first use with Terraform.
```sh
terraform init
```
Plan the resources to be created.
```sh
$ terraform plan
Plan: 86 to add, 0 to change, 0 to destroy.
```
Apply the changes to create the cluster.
```sh
$ terraform apply
...
2019-12-06 07:56:42 +01:00
module.ramius.null_resource.bootstrap: Still creating... (6m50s elapsed)
module.ramius.null_resource.bootstrap: Still creating... (7m0s elapsed)
module.ramius.null_resource.bootstrap: Creation complete after 7m8s (ID: 3961816482286168143)
2018-08-27 08:39:41 +02:00
2019-12-11 07:56:50 +01:00
Apply complete! Resources: 69 added, 0 changed, 0 destroyed.
2018-08-27 08:39:41 +02:00
```
In 4-8 minutes, the Kubernetes cluster will be ready.
## Verify
2019-12-06 07:56:42 +01:00
[Install kubectl ](https://kubernetes.io/docs/tasks/tools/install-kubectl/ ) on your system. Obtain the generated cluster `kubeconfig` from module outputs (e.g. write to a local file).
2018-08-27 08:39:41 +02:00
```
2019-12-06 07:56:42 +01:00
resource "local_file" "kubeconfig-ramius" {
2024-09-24 16:25:58 +02:00
content = module.ramius.kubeconfig-admin
filename = "/home/user/.kube/configs/ramius-config"
file_permission = "0600"
2019-12-06 07:56:42 +01:00
}
```
List nodes in the cluster.
```
$ export KUBECONFIG=/home/user/.kube/configs/ramius-config
2018-08-27 08:39:41 +02:00
$ kubectl get nodes
2019-09-23 02:37:23 +02:00
NAME STATUS ROLES AGE VERSION
2024-10-26 17:33:43 +02:00
ramius-controller-0 Ready < none > 24m v1.31.2
ramius-worker-000001 Ready < none > 25m v1.31.2
ramius-worker-000002 Ready < none > 24m v1.31.2
2018-08-27 08:39:41 +02:00
```
List the pods.
```
$ kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-7c6fbb4f4b-b6qzx 1/1 Running 0 26m
2018-11-11 00:16:06 +01:00
kube-system coredns-7c6fbb4f4b-j2k3d 1/1 Running 0 26m
2024-08-03 00:01:48 +02:00
kube-system cilium-1m5bf 1/1 Running 0 26m
kube-system cilium-7jmr1 1/1 Running 0 26m
kube-system cilium-bknc8 1/1 Running 0 26m
2019-09-06 08:12:09 +02:00
kube-system kube-apiserver-ramius-controller-0 1/1 Running 0 26m
kube-system kube-controller-manager-ramius-controller-0 1/1 Running 0 26m
2018-08-27 08:39:41 +02:00
kube-system kube-proxy-j4vpq 1/1 Running 0 26m
kube-system kube-proxy-jxr5d 1/1 Running 0 26m
kube-system kube-proxy-lbdw5 1/1 Running 0 26m
2019-09-06 08:12:09 +02:00
kube-system kube-scheduler-ramius-controller-0 1/1 Running 0 26m
2018-08-27 08:39:41 +02:00
```
## Going Further
2018-10-07 19:57:16 +02:00
Learn about [maintenance ](/topics/maintenance/ ) and [addons ](/addons/overview/ ).
2018-08-27 08:39:41 +02:00
## Variables
2020-10-21 07:47:19 +02:00
Check the [variables.tf ](https://github.com/poseidon/typhoon/blob/master/azure/flatcar-linux/kubernetes/variables.tf ) source.
2018-08-27 08:39:41 +02:00
### Required
| Name | Description | Example |
|:-----|:------------|:--------|
| cluster_name | Unique cluster name (prepended to dns_zone) | "ramius" |
2024-07-09 06:20:46 +02:00
| location | Azure location | "centralus" |
2018-08-27 08:39:41 +02:00
| dns_zone | Azure DNS zone | "azure.example.com" |
| dns_zone_group | Resource group where the Azure DNS zone resides | "global" |
| ssh_authorized_key | SSH public key for user 'core' | "ssh-rsa AAAAB3NZ..." |
!!! tip
2024-07-09 06:20:46 +02:00
Locations are shown in [docs ](https://azure.microsoft.com/en-us/global-infrastructure/regions/ ) or with `az account list-locations --output table` .
2018-08-27 08:39:41 +02:00
#### DNS Zone
Clusters create a DNS A record `${cluster_name}.${dns_zone}` to resolve a load balancer backed by controller instances. This FQDN is used by workers and `kubectl` to access the apiserver(s). In this example, the cluster's apiserver would be accessible at `ramius.azure.example.com` .
You'll need a registered domain name or delegated subdomain on Azure DNS. You can set this up once and create many clusters with unique names.
```tf
# Azure resource group for DNS zone
resource "azurerm_resource_group" "global" {
name = "global"
location = "centralus"
}
# DNS zone for clusters
resource "azurerm_dns_zone" "clusters" {
2019-10-01 07:18:15 +02:00
resource_group_name = azurerm_resource_group.global.name
2018-08-27 08:39:41 +02:00
name = "azure.example.com"
zone_type = "Public"
}
```
2019-10-01 07:18:15 +02:00
Reference the DNS zone with `azurerm_dns_zone.clusters.name` and its resource group with `"azurerm_resource_group.global.name` .
2018-08-27 08:39:41 +02:00
!!! tip ""
If you have an existing domain name with a zone file elsewhere, just delegate a subdomain that can be managed on Azure DNS (e.g. azure.mydomain.com) and [update nameservers ](https://docs.microsoft.com/en-us/azure/dns/dns-delegate-domain-azure-dns ).
### Optional
| Name | Description | Default | Example |
|:-----|:------------|:--------|:--------|
2024-08-03 00:01:48 +02:00
| os_image | Channel for a Container Linux derivative | "flatcar-stable" | flatcar-stable, flatcar-beta, flatcar-alpha |
2018-08-27 08:39:41 +02:00
| controller_count | Number of controllers (i.e. masters) | 1 | 1 |
2019-10-01 07:18:15 +02:00
| controller_type | Machine type for controllers | "Standard_B2s" | See below |
2024-08-03 00:01:48 +02:00
| controller_disk_type | Managed disk for controllers | Premium_LRS | Standard_LRS |
| controller_disk_size | Managed disk size in GB | 30 | 50 |
| worker_count | Number of workers | 1 | 3 |
2022-10-13 18:47:45 +02:00
| worker_type | Machine type for workers | "Standard_D2as_v5" | See below |
2024-08-03 00:01:48 +02:00
| worker_disk_type | Managed disk for workers | Standard_LRS | Premium_LRS |
| worker_disk_size | Size of the disk in GB | 30 | 100 |
| worker_ephemeral_disk | Use ephemeral local disk instead of managed disk | false | true |
2020-03-08 03:40:39 +01:00
| worker_priority | Set priority to Spot to use reduced cost surplus capacity, with the tradeoff that instances can be deallocated at any time | Regular | Spot |
2020-03-29 20:46:22 +02:00
| controller_snippets | Controller Container Linux Config snippets | [] | [example ](/advanced/customization/#usage ) |
| worker_snippets | Worker Container Linux Config snippets | [] | [example ](/advanced/customization/#usage ) |
2022-02-07 16:44:09 +01:00
| networking | Choice of networking provider | "cilium" | "calico" or "cilium" or "flannel" |
2024-07-06 02:21:50 +02:00
| network_cidr | Virtual network CIDR ranges | { ipv4 = ["10.0.0.0/16"], ipv6 = [ULA, ...] } | { ipv4 = ["10.0.0.0/20"] } |
2018-08-27 08:39:41 +02:00
| pod_cidr | CIDR IPv4 range to assign to Kubernetes pods | "10.2.0.0/16" | "10.22.0.0/16" |
| service_cidr | CIDR IPv4 range to assign to Kubernetes services | "10.3.0.0/16" | "10.3.0.0/24" |
2019-10-07 03:30:07 +02:00
| worker_node_labels | List of initial worker node labels | [] | ["worker-pool=default"] |
2018-08-27 08:39:41 +02:00
Check the list of valid [machine types ](https://azure.microsoft.com/en-us/pricing/details/virtual-machines/linux/ ) and their [specs ](https://docs.microsoft.com/en-us/azure/virtual-machines/linux/sizes-general ). Use `az vm list-skus` to get the identifier.
!!! warning
2019-10-07 03:30:07 +02:00
Do not choose a `controller_type` smaller than `Standard_B2s` . Smaller instances are not sufficient for running a controller.
2018-08-27 08:39:41 +02:00
2020-03-08 03:40:39 +01:00
#### Spot Priority
2018-08-27 08:39:41 +02:00
2020-03-08 03:40:39 +01:00
Add `worker_priority=Spot` to use [Spot Priority ](https://docs.microsoft.com/en-us/azure/virtual-machines/linux/spot-vms ) workers that run on Azure's surplus capacity at lower cost, but with the tradeoff that they can be deallocated at random. Spot priority VMs are Azure's analog to AWS spot instances or GCP premptible instances.