Native Kubernetes Cluster Installation Tool
Kubernetes clusters on the cloud, basically all cloud vendors support one-click deployment. The main focus here is on local deployment, or baremetal deployment.
The approach presented in this article is suitable for development testing, and there may still be issues with security, stability, long-term availability, and other solutions.
kubernetes is a component-based system with a lot of flexibility in the installation process, and many components have multiple implementations, each with their own characteristics, making it dizzying for beginners.
It is not easy to install and configure these components one by one and get them to work together.
The following are some of the tools that support Baremetal deployment.
- kubeadm: The community’s cluster installation tool, which is now very mature.
- Difficulty of use: easy
- k3s: lightweight kubernetes, small resource requirements, very simple to deploy, suitable for development testing or edge environments
- support airgap offline deployment
- easy to use: super easy
- alibaba/sealer: support for packaging the entire kubernetes into an image for delivery, and very easy to deploy.
- ease of use: super easy
- This project is still in development, but it seems that many toB companies are already using it for k8s application delivery.
- kubespray: suitable for self-built production-level clusters, is a large and comprehensive kubernetes installation solution, automatic installation of container runtime, k8s, network plug-ins and other components, and there are many options for each component. But it feels a bit complicated.
- difficulty of use: medium
- support airgap offline deployment, but I have tried it before is a pit, now I do not know how it is
- the underlying use of kubeadm deployment cluster
In order to learn Kubernetes, I use the following official kubeadm for deployment (do not ask why not binary deployment, ask is lazy), container runtime using containerd, network plug-ins are currently the most trendy eBPF-based Cilium.
kubernetes officially introduces two topologies for highly available clusters: “Stacked etcd topology” and “External etcd topology”, for simplicity, this article uses the first “stacked Etcd topology” to create a three-master highly available cluster.
Reference.
- Kubernetes Docs - Installing kubeadm
- Kubernetes Docs - Creating Highly Available clusters with kubeadm /high-availability/)
1. Environment preparation for the node
First prepare three Linux virtual machines, system selected on demand, and then adjust the settings of these three machines:.
- Node configuration.
- master: no less than 2c/3g, hard disk 20G
- master node performance is also affected by the number of cluster Pods, the above configuration should be able to support up to 100 Pods per Worker node. The above configuration should be able to support up to 100 Pods per worker node. * worker: depends on the demand, recommended not less than 2c/4g, hard disk not less than 20G, 40G if sufficient resources are recommended.
- master: no less than 2c/3g, hard disk 20G
- In the same network and interoperable (usually the same LAN)
- hostname and mac/ip address of each host and
/sys/class/dmi/id/product_uuid
, must be unique- Here the most problematic, usually hostname conflicts!
- Must turn off swap for kubelet to work properly!
For convenience, I directly used ryan4yin/pulumi-libvirt to automatically create five virtual machines and set the ip/hostname.
This article uses the KVM cloud image of opensuse leap 15.3 to test the installation.
1.1 iptables setup
The current container network for kubernetes uses the bridge mode by default. In this mode, you need to enable iptables
to take over the traffic on the bridge.
Configure it as follows.
1.2 Open node port
For LAN environment, it is recommended to close the firewall directly. This way all ports are available and convenient.
Usually for our cloud clusters, the firewall is also turned off, but the client ip is restricted by the “security group” provided by the cloud service
The control-plane node, i.e. master, needs to open the following ports.
Protocol | Direction | Port Range | Purpose | Used By |
---|---|---|---|---|
TCP | Inbound | 6443* | Kubernetes API server | All |
TCP | Inbound | 2379-2380 | etcd server client API | kube-apiserver, etcd |
TCP | Inbound | 10250 | kubelet API | Self, Control plane |
TCP | Inbound | 10251 | kube-scheduler | Self |
TCP | Inbound | 10252 | kube-controller-manager | Self |
The Worker node needs to develop the following ports.
Protocol | Direction | Port Range | Purpose | Used By |
---|---|---|---|---|
TCP | Inbound | 10250 | kubelet API | Self, Control plane |
TCP | Inbound | 30000-32767 | NodePort Services† | All |
In addition, when we test locally, we may prefer to use NodePort
on ports 80
, 443
, 8080
, etc. We need to modify the -service-node-port-range
parameter of kube-apiserver to customize the port range of NodePort, and the corresponding worker nodes should also open these ports.
2. Installing containerd
First, the environment configuration.
|
|
Install containerd+nerdctl:
|
|
nerdctl
is a command line tool for containerd, but its containers and images are completely isolated from Kubernetes containers and images and are not interoperable!
Currently, you can only view and pull Kubernetes containers and mirrors through crictl
, and the next section will cover the installation of crictl.
3. install kubelet/kubeadm/kubectl
|
|
Try crictl:
4. Create load balancing for the master kube-apiserver to achieve high availability
According to the official kubeadm documentation Kubeadm Docs - High Availability Considerations, the most well-known load balancing approach to achieve high availability for kube-apiserver is keepalived+haproxy, while simpler tools like kube-vip can also be considered.
For simplicity, let’s use kube-vip directly, refer to the official documentation of kube-vip: Kube-vip as a Static Pod with Kubelet.
P.S. I’ve also seen some installation tools ditch keepalived and run a nginx on each node to do load balancing, with all the master addresses written in the configuration…
First, use the following command to generate the kube-vip configuration file, using ARP as an example (we recommend switching to BGP for production environments).
|
|
All three master nodes need to run the above command (the worker does not) to create the static-pod configuration file for kube-vip. After kubeadm initialization, kubelet will automatically pull them up as static pods.
5. Creating a cluster with kubeadm
All you need to do is run this command.
|
|
kubeadm should report an error indicating that some of your dependencies do not exist, so install the dependencies first.
|
|
Re-run the previous kubeadm command again and it should execute properly, it does the following operations.
- Pull the container image of the control plane
- Generate a ca root certificate
- Generate tls certificates for etcd/apiserver etc. using the root certificate
- Generate kubeconfig configuration for each component of the control plane
- Generate static pod configuration, kubelet will automatically pull up kube-proxy and all other k8s master components based on these configurations
After running, it will give you three commands.
-
Place
kubeconfig
under$HOME/.kube/config
, whichkubectl
needs to use to connect to the kube-apiserver -
The command to add the control-plane node to the cluster:
- Because we added the static-pod configuration of kube-vip in advance, the preflight-check here will report an error, so you need to add this parameter to ignore the error -
--ignore-preflight-errors=DirAvailable--etc-kubernetes-manifests
- Because we added the static-pod configuration of kube-vip in advance, the preflight-check here will report an error, so you need to add this parameter to ignore the error -
-
The command to join a worker node to a cluster:
After running the first part of the kubeconfig
processing command, you can use kubectl to view the status of the cluster.
|
|
Now run the join cluster command printed out earlier on the other nodes and you have a highly available cluster set up.
After all the nodes have joined the cluster, you should have three control plane masters and two workers when viewed through kubectl.
|
|
Right now they are all in the NotReady state and will not be ready until we get the network plug-in installed.
Now look at the certificate issuance status of the cluster again.
|
|
You can see that several of the kubernetes.io/kubelet-serving
certificates are still pending, because we set serverTLSBootstrap: true
in the kubeadm configuration file to allow Kubelet to request CA-signed certificates from the cluster, instead of self-signing result.
The main purpose of setting this parameter is to allow components such as metrics-server to communicate with kubelet using the https protocol and to avoid adding the parameter --kubelet-insecure-tls
for metrics-server.
Currently kubeadm does not support automatic approval of certificates requested by kubelets, we need to approve them manually:
Until these certificates are approved, all functions that require calls to the kubelet api will not be available, such as
- View pod logs
- Get node metrics
- etc.
5.1 Frequently Asked Questions
5.1.1 Using domestic mirror sources
If you do not have a VPN, kubeadm’s default mirror repository cannot be pulled from within China. If you have high reliability requirements, it is better to build your own private mirror repository and push the mirrors to the private repository.
You can list all the mirror addresses you need to use with the following command.
Use a tool or script such as skopeo
to copy the above image to your private repository, or for convenience (test environment) consider looking for a synchronized image address online. Add the image address to kubeadm-config.yaml
and deploy it.
5.1.2 Resetting the cluster configuration
If anything goes wrong during the cluster creation process, you can restore the configuration by running kubeadm reset
on all nodes, and then go through the kubeadm cluster creation process again.
However, a few things should be noted.
kubeadm reset
will clear all static-pod configuration files including kube-vip configuration, so the master node needs to re-run the kube-vip command given earlier and generate the kube-vip configuration.kubeadm reset
will not reset the network interface configuration, the master node needs to manually clean up the vip added by kube-vip:ip addr del 192.168.122.200/32 dev eth0
.- If you wish to reinstall the cluster after installing the network plugin, the sequence is as follows.
- delete -f xxx.yaml
via
kubectl delete -f xxx.yaml/
helm uninstall` Delete all other application configurations except network - Delete the network plugin
- Reboot all nodes first, or manually reset the network configuration of all nodes
- Recommend reboot, because I don’t know how to reset manually… tried
systemctl restart network
and it doesn’t clean up all virtual network interfaces.
- Recommend reboot, because I don’t know how to reset manually… tried
- delete -f xxx.yaml
After doing so, re-run the cluster installation and you should be fine.
6. Verifying the high availability of the cluster
Although the network plug-in is not yet installed and all nodes of the cluster are not yet ready, we can already verify the high availability of the cluster simply by using the kubectl command.
First, we install the authentication file $HOME/.kube/config
and kunbectl that we placed on k8s-master-0 on another machine, such as my host machine.
Then run the kubectl get node
command on the host machine to verify the high availability of the cluster.
- When all three master nodes are running normally, the kubectl command also works
- pause or stop one of the masters, the kubectl command still works fine
- pause the second master again, the kubectl command should get stuck and time out, and it won’t work
- resume restore one of the two stopped masters, and the kubectl command will work again
This completes kubeadm’s work, and the next step is to install the network plugin and the cluster will be available.
7. Installing Network Plugins
There are many kinds of network plugins available in the community, the more well-known ones with good performance are Calico and Cilium, where Cilium focuses on high performance and observability based on eBPF.
Here are the installation methods of these two plug-ins respectively. (Note that only one of the network plug-ins can be installed, not repeated.)
You need to install helm locally in advance, I use the host here, so you only need to install it on the host:
7.1 Installing Cilium
Official documentation: https://docs.cilium.io/en/v1.10/gettingstarted/k8s-install-kubeadm/
cilium provides a high-performance and highly observable k8s clustering network via eBPF. cilium also provides a more efficient implementation than kube-proxy and can completely replace kube-proxy.
Let’s start with kube-proxy mode and familiarize ourselves with cilium.
You can check the progress of cilium installation via kubectl get pod -A
, when all pods are ready, the cluster is ready~.
cilium also provides a dedicated client.
Then use the cilium client to check the status of the web plugin:
|
|
cilium also provides commands to automatically create pods for connectivity testing of clustered networks:
|
|
As you can observe by kubectl get po -A
, this test command automatically creates a cilium-test
namespace and creates several pods for detailed testing at startup.
The whole test process will last about 5 minutes or so, and the pods will not be automatically deleted after the test is completed, but will be deleted manually using the following command.
|
|
7.2 Installing Calico
Official documentation: https://docs.projectcalico.org/getting-started/kubernetes/self-managed-onprem/onpremises
It’s only two or three lines of command. The installation is really easy, so I don’t bother to introduce it, just read the official documentation.
But there are actually quite a lot of details about calico, so we recommend reading through its official documentation to understand the architecture of calico.
8. check cluster status
The official dashboard doesn’t work very well, so we recommend installing a local k9s directly, which is particularly cool.
|
|
Then it’s time to have fun.
9. Install metrics-server
Possible issues with this step: Enabling signed kubelet serving certificates
If you need to use HPA and simple cluster monitoring, then metrics-server must be installed, so let’s install it now.
First, running kubectl’s monitoring command should report an error.
You shouldn’t see any monitoring metrics in k9s either.
Now install it via helm.
metrics-server will only deploy one instance by default, if you want high availability, please refer to the official configuration: metrics-server - high-availability manifests
Once the metrics-server is up and running, you can use the kubectl top
command.
10. Add regular backup capability to etcd
See backup and restore for etcd
11. Installing Volume Provisioner
As we learn to use stateful applications such as Prometheus/MinIO/Tekton, they will by default declare the required data volumes via PVC.
To support this capability, we need to deploy a Volume Provisioner in the cluster.
For on-cloud environments, it is OK to directly access the Volume Provisioner provided by the cloud provider, which is convenient, hassle-free, and reliable enough.
For bare-metal environments, the more famous one should be rook-ceph, but this thing is complicated to deploy and difficult to maintain, not suitable for testing and learning, and not suitable for production environments.
For development, test environments, or personal clusters, it is recommended to use.
- local data volume, suitable for data can be lost, and does not require distributed scenarios, such as development and testing environments
- NFS data volumes, suitable for scenarios where data can be lost, performance requirements are not high, and distributed is required. For example, development test environments, or applications that do not have much pressure online
- https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner
- https://github.com/kubernetes-csi/csi-driver-nfs
- The reliability of NFS data depends on external NFS servers, and enterprises often use NAS such as Synology as NFS servers.
- If the external NFS server goes down, the application will crash.
- Direct use of object storage on the cloud is suitable for scenarios where you want to have no data loss and low performance requirements.
- Use https://github.com/rclone/rclone mount mode directly to save data, or sync folder data directly to the cloud (there may be some data loss).