Published on

Cài đặt Kubernetes cluster trên Ubuntu server 22.04

Hiện tại thì mình mới sắm được 3 con Lenovo Tiny M73 (hàng cũ) để làm 1 cái HomeLab phục vụ học tập nghiên cứu về Kubernetes. Ban đầu mình tính mua Raspberry Pi 4 bản 8G nhưng giá khá chát nên thôi.

Bài viết này sẽ hướng dẫn các bước cài đặt và cấu hình 1 Kuberntes cluster trên Ubuntu server.

Cấu hình

  • 03 Lenovo Tiny M73: core-i5 4570T (2 core), 16G RAM DDR3, 128G SSD
  • Kubernetes cluster: 01 Master, 02 Worker
  • Phiên bản hệ điều hành: Ubuntu Server 22.04
NodeIPhostname
master192.168.1.10k8s-master.nvtienanh.local
worker1192.168.1.11k8s-worker1.nvtienanh.local
worker2192.168.1.12k8s-worker2.nvtienanh.local

Tiến hành

Sau khi cài hệ điều hành lên các thiết bị, chúng ta tiến hành thao tác trên các thiết bị Cập nhật phần mềm lên phiên bản mới nhất (thực hiện trên tất cả các node)

sudo apt update
sudo apt upgrade -y

Sau khi cập nhật xong, chúng ta khởi động lại các server

sudo reboot

Đặt hostname và cập nhật hosts file

Master node

sudo hostnamectl set-hostname "k8s-master.nvtienanh.local"

Worker 1

sudo hostnamectl set-hostname "k8s-worker1.nvtienanh.local"

Worker 2

sudo hostnamectl set-hostname "k8s-worker2.nvtienanh.local"

Tiếp theo chúng ta cập nhật file /etc/hosts file của tất cả các node.

sudo apt install -y nano // Cài nano editor nếu server chưa có
sudo nano /etc/hosts

Sau đó thêm vào bên dưới file nội dung dưới đây:

192.168.1.10   k8s-master.nvtienanh.local k8s-master
192.168.1.11   k8s-worker1.nvtienanh.local k8s-worker1
192.168.1.12   k8s-worker2.nvtienanh.local k8s-worker2

Disable swap và cập nhật kernel

Lưu ý:

Các lệnh dưới đây thực hiện trên tất cả các node

sudo swapoff -a

Kiểm tra lại xem swap đã disabled hay chưa bằng lệnh free -h, nếu thành công kết quả sẽ như dưới đây:

$ free -h
               total        used        free      shared  buff/cache   available
Mem:           7.7Gi       167Mi       7.1Gi       1.0Mi       437Mi   7.3Gi
Swap:             0B          0B          0B

Tiếp theo disable swap trong /etc/fstab

sudo nano /etc/fstab

Tìm dòng: /swap.img none swap sw 0 0 và cập nhật lại thành:

#/swap.img       none       swap       sw       0       0

Sau đó chạy tiếp các lệnh:

sudo mount -a
free -h

Load the following kernel modules on all the nodes:

sudo tee /etc/modules-load.d/containerd.conf <<EOF
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter

Set the following Kernel parameters for Kubernetes.

sudo tee /etc/sysctl.d/kubernetes.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF

Sau đó reload lại sysctl

sudo sysctl --system

Cài đặt containerd run time

Lưu ý:

Chạy các lệnh dưới đây trên tất cả các node

sudo apt install -y curl gnupg2 software-properties-common apt-transport-https ca-certificates
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmour -o /etc/apt/trusted.gpg.d/docker.gpg
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt update
sudo apt install -y containerd.io

Sau khi cài đặt xong, chúng ta thêm cấu hình containerd.

containerd config default | sudo tee /etc/containerd/config.toml >/dev/null 2>&1
sudo sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml
sudo systemctl restart containerd
sudo systemctl enable containerd

Cài đặt Kubernetes

Lưu ý:

Chạy các lệnh dưới đây trên tất cả các node

curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
sudo apt-add-repository "deb http://apt.kubernetes.io/ kubernetes-xenial main"
sudo apt update
sudo apt install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

Khởi tạo cluster bằng kubeadm

Lưu ý:

Chỉ chạy lênh dưới đây trên master node

sudo kubeadm init \
  --pod-network-cidr=10.10.0.0/16 \
  --control-plane-endpoint=k8s-master.nvtienanh.local

Trong đó 10.10.0.0/16 là CIDR của pod network, bạn có thể thay theo nhu cầu.

Nếu chạy thành công, kết quả trả về sẽ như sau

anh@k8s-master:~$ sudo kubeadm init \
  --pod-network-cidr=10.10.0.0/16 \
  --control-plane-endpoint=k8s-master.nvtienanh.local
[init] Using Kubernetes version: v1.26.1
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [k8s-master.nvtienanh.local kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 192.168.1.10]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "etcd/ca" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [k8s-master.nvtienanh.local localhost] and IPs [192.168.1.10 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [k8s-master.nvtienanh.local localhost] and IPs [192.168.1.10 127.0.0.1 ::1]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[apiclient] All control plane components are healthy after 7.503422 seconds
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config" in namespace kube-system with the configuration for the kubelets in the cluster
[upload-certs] Skipping phase. Please see --upload-certs
[mark-control-plane] Marking the node k8s-master.nvtienanh.local as control-plane by adding the labels: [node-role.kubernetes.io/control-plane node.kubernetes.io/exclude-from-external-load-balancers]
[mark-control-plane] Marking the node k8s-master.nvtienanh.local as control-plane by adding the taints [node-role.kubernetes.io/control-plane:NoSchedule]
[bootstrap-token] Using token: daii9y.g4dq24u6irkz4pt0
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap,RBAC Roles
[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to get nodes
[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] Configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] Configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regularuser:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listedat:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following asroot:

  kubeadm join k8s-master.nvtienanh.local:6443 --token daii9y.g4dq24u6irkz4pt0 \
        --discovery-token-ca-cert-hash sha256:58b9cc96ed57a5797fddea653756dbda830efbff55b720a10cffb3948d489148 \
        --control-plane

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join k8s-master.nvtienanh.local:6443 --token daii9y.g4dq24u6irkz4pt0 \
        --discovery-token-ca-cert-hash sha256:58b9cc96ed57a5797fddea653756dbda830efbff55b720a10cffb3948d489148

Tiếp theo, thực thi các lệnh dưới đây trên master node

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

Chúng ta thử chạy lệnh để kiếm tra trạng thái của cluster

kubectl cluster-info
kubectl get nodes

Kết quả trả về:

anh@k8s-master:~$ kubectl cluster-info
Kubernetes control plane is running at https://k8s-master.nvtienanh.local:6443
CoreDNS is running at https://k8s-master.nvtienanh.local:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
anh@k8s-master:~$ kubectl get nodes
NAME                         STATUS     ROLES           AGE   VERSION
k8s-master.nvtienanh.local   NotReady   control-plane   55m   v1.26.1

Chúng ta thấy là control plane đang chạy và hiện tại chỉ có mỗi master node, chúng ta sẽ tiến hành thêm worker node vào cluster này.

Thêm worker node vào cluster

Lưu ý: Các lệnh dưới đây chỉ chạy trên các worker node

Chúng ta xem lại output của lệnh sudo kubeadm init ở trên và copy lại command bên dưới phần:

Then you can join any number of worker nodes by running the following on each as root:
kubeadm join k8s-master.nvtienanh.local:6443 --token daii9y.g4dq24u6irkz4pt0 \
        --discovery-token-ca-cert-hash sha256:58b9cc96ed57a5797fddea653756dbda830efbff55b720a10cffb3948d489148

Sau kết quả trả về trên terminal sẽ có dạng như sau

anh@k8s-worker1:~$ sudo kubeadm join k8s-master.nvtienanh.local:6443 --token daii9y.g4dq24u6irkz4pt0 \
        --discovery-token-ca-cert-hash sha256:58b9cc96ed57a5797fddea653756dbda830efbff55b720a10cffb3948d489148
[sudo] password for anh:
[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

Khi chạy kubectl get nodes để kiếm tra các node (chạy trên terminal của master node), kết quả trả về:

anh@k8s-master:~$ kubectl get nodes
NAME                          STATUS     ROLES           AGE   VERSION
k8s-master.nvtienanh.local    NotReady   control-plane   58m   v1.26.1
k8s-worker1.nvtienanh.local   NotReady   <none>          87s   v1.26.1
k8s-worker2.nvtienanh.local   NotReady   <none>          44s   v1.26.1

cho thấy là các node đã được thêm thành công vào cluster.

Cài đặt Calico Pod Network cho Kubernetes cluster

Lưu ý: Các lệnh dưới đây chỉ chạy trên master node

Đầu tiên chúng ta tải về file manifest dưới dạng file yaml, đây là file cài đặt Calico trên Kubernetes cluster có số node nhỏ hơn 50

curl https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml -O

Mở file vừa tải về và tìm để phần CALICO_IPV4POOL_CIDR

---
# The default IPv4 pool to create on startup if none exists. Pod IPs will be
# chosen from this range. Changing this value after installation will have
# no effect. This should fall within `--cluster-cidr`.
# - name: CALICO_IPV4POOL_CIDR
#   value: "192.168.0.0/16"
# Disable file logging so `kubectl logs` works.
- name: CALICO_DISABLE_FILE_LOGGING
  value: 'true'

Chúng ta sửa lại dải IP cho đúng với CIDR của pod network trong lệnh sudo kubeadm init. Trong ví dụ của mình là 10.10.0.0/16 nên file sau khi sửa lại có dạng như sau

---
# The default IPv4 pool to create on startup if none exists. Pod IPs will be
# chosen from this range. Changing this value after installation will have
# no effect. This should fall within `--cluster-cidr`.
- name: CALICO_IPV4POOL_CIDR
  value: '10.10.0.0/16'
# Disable file logging so `kubectl logs` works.
- name: CALICO_DISABLE_FILE_LOGGING
  value: 'true'

Sau đó chúng ta cài Calico lên Kubernetes cluster:

kubectl apply -f calico.yaml

Kết quả trả về

anh@k8s-master:~$ kubectl apply -f calico.yaml
poddisruptionbudget.policy/calico-kube-controllers created
serviceaccount/calico-kube-controllers created
serviceaccount/calico-node created
configmap/calico-config created
customresourcedefinition.apiextensions.k8s.io/bgpconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/bgppeers.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/blockaffinities.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/caliconodestatuses.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/clusterinformations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/felixconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworksets.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/hostendpoints.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamblocks.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamconfigs.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamhandles.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ippools.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipreservations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/kubecontrollersconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networksets.crd.projectcalico.org created
clusterrole.rbac.authorization.k8s.io/calico-kube-controllers created
clusterrole.rbac.authorization.k8s.io/calico-node created
clusterrolebinding.rbac.authorization.k8s.io/calico-kube-controllers created
clusterrolebinding.rbac.authorization.k8s.io/calico-node created
daemonset.apps/calico-node created
deployment.apps/calico-kube-controllers created

Chúng ta sẽ kiểm tra xem calico đã được deploy thành công chưa bằng cách kiểm tra các pod trên namespace kube-system

anh@k8s-master:~$ kubectl get pods -n kube-system
NAME                                                 READY   STATUS    RESTARTS   AGE
calico-kube-controllers-57b57c56f-ptddp              1/1     Running   0          2m44s
calico-node-5fqml                                    1/1     Running   0          2m44s
calico-node-llfjq                                    1/1     Running   0          2m44s
calico-node-vw78h                                    1/1     Running   0          2m44s
coredns-787d4945fb-n7s9t                             1/1     Running   0          62m
coredns-787d4945fb-rs9mj

Nếu status là Running có nghĩa đã deploy thành công, bây giờ nếu kiểm tra trạng thái của các node thì status sẽ là Ready

anh@k8s-master:~$ kubectl get nodes
NAME                          STATUS   ROLES           AGE     VERSION
k8s-master.nvtienanh.local    Ready    control-plane   62m     v1.26.1
k8s-worker1.nvtienanh.local   Ready    <none>          5m53s   v1.26.1
k8s-worker2.nvtienanh.local   Ready    <none>          5m10s   v1.26.1

Video hướng dẫn

Như vậy mọi thứ đã xong, hy vọng bài viết này sẽ hữu ích với bạn.