Kubernetes requires a set of machines to host the Kubernetes control plane and the worker nodes where containers are ultimately run. In this lab you will provision the compute resources required for running a secure and highly available Kubernetes cluster across a single [compute zone](https://cloud.google.com/compute/docs/regions-zones/regions-zones).
> Ensure a default compute zone and region have been set as described in the [Prerequisites](01-prerequisites.md#set-a-default-compute-region-and-zone) lab.
> If you are using Azure, ensure that the azure cli has been set up and configured as described in the [Prerequisites](01-prerequisites.md#az-setup) lab.
The Kubernetes [networking model](https://kubernetes.io/docs/concepts/cluster-administration/networking/#kubernetes-model) assumes a flat network in which containers and nodes can communicate with each other. In cases where this is not desired [network policies](https://kubernetes.io/docs/concepts/services-networking/network-policies/) can limit how groups of containers are allowed to communicate with each other and external network endpoints.
> Setting up network policies is out of scope for this tutorial.
> An [external load balancer](https://cloud.google.com/compute/docs/load-balancing/network/) will be used to expose the Kubernetes API Servers to remote clients.
List the firewall rules in the `kubernetes-the-hard-way` VPC network:
Create a [Network Security Group](https://learn.microsoft.com/en-us/azure/virtual-network/network-security-groups-overview) to allow https, ssh, and ICMP inbound traffic.
The compute instances in this lab will be provisioned using [Ubuntu Server](https://www.ubuntu.com/server) 20.04, which has good support for the [containerd container runtime](https://github.com/containerd/containerd). Each compute instance will be provisioned with a fixed private IP address to simplify the Kubernetes bootstrapping process.
To start, we will create an ssh keypair which will be used to authenticate with the VMs. This keypair will be stored in `$HOME/.ssh/k8sthehardway[.pub]` and also uploaded to azure with the name `k8sthehardway`
```
mkdir -p $HOME/.ssh
ssh-keygen -f $HOME/.ssh/k8sthehardway
az sshkey create --name k8sthehardway --public-key "@$HOME/.ssh/k8sthehardway.pub"
> The azure VMs will have the username `azureuser`. The only method of authentication available will be public key, with the key in question stored at $HOME/.ssh/k8sthehardway
> :warning:WARNING:warning:: These VMs are accessible on the internet. Adding proper security beyond public key authentication is beyond the scope of this tutorial, so be very sure clean them up when you are done
Each worker instance requires a pod subnet allocation from the Kubernetes cluster CIDR range. The pod subnet allocation will be used to configure container networking in a later exercise. The `pod-cidr` instance metadata will be used to expose pod subnet allocations to compute instances at runtime.
> The Kubernetes cluster CIDR range is defined by the Controller Manager's `--cluster-cidr` flag. In this tutorial the cluster CIDR range will be set to `10.200.0.0/16`, which supports 254 subnets.
Create three compute instances which will host the Kubernetes worker nodes:
> The azure VMs will have the username `azureuser`. The only method of authentication available will be public key, with the key in question stored at $HOME/.ssh/k8sthehardway
> :warning:WARNING:warning:: These VMs are accessible on the internet. Adding proper security beyond public key authentication is beyond the scope of this tutorial, so be very sure clean them up when you are done
SSH will be used to configure the controller and worker instances. When connecting to compute instances for the first time SSH keys will be generated for you and stored in the project or instance metadata as described in the [connecting to instances](https://cloud.google.com/compute/docs/instances/connecting-to-instance) documentation.
The VMs have been provisioned with the `k8sthehardway` keypair to allow the `azureuser` to log in. You can ssh into them via either the `az ssh` command or via normal ssh. The advantage of going through the azure cli is you don't need to remember the ip address or location of the keypair to connect, and the command is not as verbose. The advantage of plain ssh is this is more familiar to most users.
### az ssh
Run the following command to connect to `controller-0` (replace `controller-0` with the desired VM to connect to others). Note that the first time you use `az ssh` you will be prompted to install the `ssh` extension to the azure CLI.
```
az ssh vm --name controller-0 --local-user azureuser
```
### ssh
Run the following command to connect to the `controller-0` VM instance via plain ssh
```
ssh -i $HOME/.ssh/k8sthehardway azureuser@$(az vm show -d --name controller-0 --query "publicIps" -o tsv)