diff --git a/content/posts/2019-12-03-kubernetes-setup.md b/content/posts/2019-12-03-kubernetes-setup.md new file mode 100644 index 0000000..4564ead --- /dev/null +++ b/content/posts/2019-12-03-kubernetes-setup.md @@ -0,0 +1,340 @@ +--- +title: Single node Kubernetes setup with kubeadm and cert-manager +date: 2019-12-03 +author: James McDonald +type: post +draft: true +categories: + - Tech +--- + +This is an update of my [previous post](/posts/2019-04-04-kubernetes-setup/) +about how to set up a single node Kubernetes cluster. As noted below, this +is an evolving technology and the details of setting it up change over time. + +This follows +https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/ for the +initial cluster setup. You should look there for more detail. I strongly +recommend that you read about the various projects and verify that this +information is still valid. Things change pretty quickly. I've deliberately not +included a lot of detail in the post beyond what I did and the commands to use. + +# Requirements + +You can work around these, but it's recommended to have at least: + +* 4GB RAM +* 2 cores + +# Decisions + +Kubernetes is an open ended platform which lets you make a lot of decisions +yourself. Unfortunately it also requires you to make them (see projects like +k3s to avoid some of that). I decided to use: + +* Debian stable (buster), because why would you ever not use Debian? +* Docker as the container runtime. Next time I'll try something else (CRI-O), + but Docker is familiar so it's easy to diagnose any issues. +* Weave Net for networking. I had some trouble with Flannel, and Weave also + supports NetworkPolicy if you want to tinker with that. +* No Helm. Helm is great, but it hides away details and I'm interested in + details. +* nginx for ingress. There are a bunch of possibilities, but nginx is the + common choice and integrates nicely with lots of other things. +* Let's Encrypt certificates validated by Cloudflare DNS. I use Cloudflare + already, so this was an easy choice. DNS validation allows for wildcards and + for internal hosts. +* Single node. There are a lot of cool things about Kubernetes that you don't + get with a single node, but what I'm setting up here is for home. You can + easily add more nodes by following the instructions `kubeadm` gives you when + it runs. + +# Enable net.bridge.bridge-nf-call-iptables + +This is required by Weave and other networking options. You can read +more at +https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/#pod-network + +This was actually already set on my machine, but it doesn't hurt to be explicit. + +``` +cat > /etc/sysctl.d/20-bridge-nf.conf < /etc/docker/daemon.json < /etc/apt/sources.list.d/docker.list +apt-get update +apt-get install -y --no-install-recommends docker-ce +``` + +The `--no-install-recommends` will avoid pulling in stuff you don't need, +including the aufs DKMS package. + +# Switch to legacy iptables + +Debian 10 (buster) and newer Ubuntu come with a new iptables that uses +netfilter. This is not currently supported by kubeadm, so you have to switch to +the legacy iptables. + +``` +sudo update-alternatives --set iptables /usr/sbin/iptables-legacy +sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy +sudo update-alternatives --set arptables /usr/sbin/arptables-legacy +sudo update-alternatives --set ebtables /usr/sbin/ebtables-legacy +``` + +If you don't do this you will get the same firewall rule added every few +seconds until the network becomes unusably slow. Note that there is an +`iptables` 1.8.3 package in buster-backports which may fix this problem. +Personally I'm using legacy for the moment. + +# Install Kubernetes components +``` +curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - +cat </etc/apt/sources.list.d/kubernetes.list +deb https://apt.kubernetes.io/ kubernetes-xenial main +EOF +apt-get update +apt-get install -y kubelet kubeadm kubectl +``` + +The `xenial` in the APT source is correct. That's the repo they seem to +update, and these are Go binaries anyway so they're self-contained. + +# Run `kubeadm` to set up the cluster + +``` +kubeadm init +``` + +That's it. Neat, huh? + +There is still a bunch of work to do to make the cluster actually useful. You +can do most of the rest of this as a non-root user. Follow the instructions +`kubeadm` gave you to copy the credential **as your regular user**. + +``` +mkdir -p $HOME/.kube +sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config +sudo chown $(id -u):$(id -g) $HOME/.kube/config +``` + +And as a handy extra tip, you'll want completion: + +``` +source <(kubectl completion bash) +``` + +# Install Flannel for pod networking +``` +kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/a70459be0084506e4ec919aa1c114638878db11b/Documentation/kube-flannel.yml +kubectl get pods --all-namespaces +``` + +You should see coredns pods come to life if all is well. + +# Untaint the master so you can run pods +``` +kubectl taint nodes --all node-role.kubernetes.io/master- +``` + +At this point you can run pods and expose them with services. If that's all you +need, you're done! Next I set up an nginx-ingress and cert-manager to allow for +hostname-based HTTPS ingress with Let's Encrypt certificates. + +# Set up nginx-ingress + +I set up the nginx-ingress with host networking so I could expose my cluster's +services via ports 80 and 443 on the host. You can also expose it via a NodePort or +LoadBalancer, but this worked well for my simple setup. + +``` +kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml +cat > nginx-host-networking.yaml < external-dns.yaml < clusterissuer-cf.yaml < wildcard-cert.yaml < nginx-ingress.yaml <