11 Nov 2021
Preparations
hcloud
- Login to Hetzner Cloud Dashboard and create a new Project.
- In the project, generate new Hetzner Cloud API Token.
- Install
hcloudcommandline tool:brew install hcloud - Connect
hcloudto API token:hcloud context create <$CLUSTER_NAME> - Generate SSH key:
ssh-keygen -t rsa -b 4096 -N '' -C '<$CLUSTER_SSH_KEY>' -f ~/.ssh/id_rsa_cluster - Store SSH public key:
hcloud ssh-key create --name <$CLUSTER_SSH_KEY> --public-key-from-file ~/.ssh/id_rsa_cluster.pub
Network
- Create internal network:
hcloud network create --name <$CLUSTER_NETWORK> --ip-range 10.0.0.0/16 - Add subnet:
hcloud network add-subnet --network-zone eu-central --type server --ip-range 10.0.0.0/16 <$CLUSTER_NETWORK>
Firewall (Optional)
- Create firewall:
hcloud firewall create --name <$CLUSTER_FIREWALL> - Add firewall exception for SSH:
hcloud firewall add-rule --direction in --protocol tcp --port 22 <$CLUSTER_FIREWALL>
Servers
- Create servers:
hcloud server create --image ubuntu-20.04 --name <$MASTER_NODE> --type cpx11 --location nbg1 --start-after-create --ssh-key <$CLUSTER_SSH_KEY> hcloud server create --image ubuntu-20.04 --name <$WORKER_NODE_01> --type cpx31 --location nbg1 --start-after-create --ssh-key <$CLUSTER_SSH_KEY> hcloud server create --image ubuntu-20.04 --name <$WORKER_NODE_02>--type cpx31 --location fsn1 --start-after-create --ssh-key <$CLUSTER_SSH_KEY> - Attach servers to internal network:
hcloud server attach-to-network --network <$CLUSTER_NETWORK> --ip 10.0.0.10 <$MASTER_NODE> hcloud server attach-to-network --network <$CLUSTER_NETWORK> --ip 10.0.0.11 <$WORKER_NODE_01> hcloud server attach-to-network --network <$CLUSTER_NETWORK> --ip 10.0.0.12 <$WORKER_NODE_02>
Load Balancer
- Create Load Balancer:
hcloud load-balancer create --name <$CLUSTER_LB> --type lb11 --location nbg1 - Attach Load Balancer to internal network:
hcloud load-balancer attach-to-network --network <$CLUSTER_NETWORK> --ip 10.0.0.254 <$CLUSTER_LB>
Kubernetes Setup
SSH into each of the nodes to setup the Kubernetes cluster:
hcloud server ssh <$NODE_NAME>
Server Setup
- Disable Swap:
swapoff -a sed -i '/swap/d' /etc/fstab - Enable
br_netfilterkernel module:cat > /etc/modules-load.d/kubernetes.conf << EOF br_netfilter EOF modprobe br_netfilter - Enable routing:
cat > /etc/sysctl.d/kubernetes.conf << EOF net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 EOF sysctl --system - Install dependencies:
apt update apt install -y apt-transport-https ca-certificates curl - Import Kubernetes signing key:
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - - Add Kubernetes package repo:
echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" > /etc/apt/sources.list.d/kubernetes.list - Install Kubernetes packages:
apt update apt install -y containerd kubeadm kubelet kubectl apt-mark hold kubelet kubeadm kubectl - Configure
kubeletservice to enable Hetzner Cloud Provider:cat > /etc/systemd/system/kubelet.service.d/20-hcloud.conf << EOF [Service] Environment="KUBELET_EXTRA_ARGS=--cloud-provider=external" EOF systemctl daemon-reload systemctl restart kubelet
Initialize Kubernetes Cluster
- On the master node:
kubeadm init \ --pod-network-cidr=10.244.0.0/16 \ --apiserver-advertise-address=0.0.0.0 \ --apiserver-cert-extra-sans=10.0.0.10 - Copy the
kubeadm join...command from the last command’s output and change the external IP to 10.0.0.10. - Run the modified
kubeadm joincommand on all worker nodes.
Kubernetes Configruation
The cluster configuration can be done locally.
- Install
kubectl:brew install kubernetes-cli - Copy the contents of
/etc/kubernetes/admin.conffrom the master node to the local$HOME/.kube/configfile. - Check if the connection to the cluster is working:
kubectl get nodesNote: The nodes’ status will be
NotReadybecause there is no network controller installed yet.
Network Controller
Install Flannel Network Controller:
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
Note: When running
kubectl get nodenow, the status of all nodes should beReady.
Hetzner Cloud Controller
- Create Secrets:
kubectl -n kube-system create secret generic hcloud \ --from-literal=token=<$HETZNER_API_TOKEN> \ --from-literal=network=<$CLUSTER_NETWORK_ID>Note: Run
hcloud network listto get<$CLUSTER_NETWORK_ID>. - Install Hetzner Cloud Controller:
kubectl -n kube-system apply -f https://github.com/hetznercloud/hcloud-cloud-controller-manager/releases/download/v1.12.0/ccm-networks.yaml
CSI Driver
- Create Secret:
kubectl -n kube-system create secret generic hcloud-csi \ --from-literal=token=<$HETZNER_API_TOKEN> - Install CSI Driver:
kubectl apply -f https://raw.githubusercontent.com/hetznercloud/csi-driver/v1.6.0/deploy/kubernetes/hcloud-csi.yml
Ingress Controller
Install Nginx Ingress Controller:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.0.4/deploy/static/provider/cloud/deploy.yaml
Load Balancer
Connect Ingress Controller to Hetzner Load Balancer:
kubectl -n ingress-nginx annotate services ingress-nginx-controller \
load-balancer.hetzner.cloud/name="<$CLUSTER_LB>" \
load-balancer.hetzner.cloud/location="nbg1" \
load-balancer.hetzner.cloud/use-private-ip="true" \
load-balancer.hetzner.cloud/uses-proxyprotocol="true" \
load-balancer.hetzner.cloud/hostname="<$CLUSTER_LB_HOSTNAME>"
Note:
<$CLUSTER_LB_HOSTNAME>needs to be a valid DNS record that points to the Load Balancers’ public IP address.

Comments
Nothing yet. Say the first thing.
Sign in to join the conversation.