ติดตั้ง Kubernetes บน Ubuntu 22
ก่อนจะทำการ install kubernetes เราต้องตรวจสอบ spec ของ server ก่อนว่าเพียงพอต่อการใช้งานหรือไม่ โดยที่ spec ขั้นต่ำที่สามารถติดต้ัง kubernetes ได้คือ
- ต้องมี 2 CPUs
- มี RAM อย่างน้อย 2GB
- ต้องมี Disk ว่างอย่างน้อยๆ 2 GB (ไม่รวมกับพื้นที่ ที่ application และ database ต้องใช้งาน)
หลังจากนั้นให้เชื่อม nodes ต่างๆเข้าหากันให้เรียบร้อย(ทุกๆ node ต้องอยู่ใน network เดียวกัน) หลังจากนั้นก็เช้าสู่ขั้นตอนการติดต้ัง ซึ่งมีขั้นตอนต่างๆ ดังนี้
- Disable swap
- ตั้ง hostname
- Mapping IP Address กับ Hostname ในทุกๆ Nodes
- ตั้งค่า IPV4 Bridge ในทุกๆ Nodes
- ติดต้ัง Container runtime(Containerd)
- ติดตั้ง Kubernetes components ในทุกๆ Nodes
- สร้าง Kubernetes Cluster
- ติดตั้ง Kubernetes network(Calico)
- นำ Worker Node join เข้ามาใน cluster
1. Disable Swap
Swap Space คือ การย้ายข้อมูลที่อยู่ใน Memory(RAM) ไปเก็บไว้ใน disk เพื่อประหยัดพื้นที่ใน RAM ดังนั้นเมื่อ enable swap ขึ้นมาระบบจะ stable มากขึ้นเพราะจะใช้พื้นที่ใน memory(RAM) น้อยลง แต่ปัญหาก็คือความไม่แน่นอนของการอ่านเขียนข้อมูล เพราะถ้าเราไปอ่านข้อมูลใน Swap Space ก็จะช้ากว่าการอ่านเขียนข้อมูลใน RAM ดังนั้นในขั้นตอนแรกของการติดตั้ง เราต้องไป disable swap เพื่อให้ kubernetes สามารถจัดการกับ performance ได้ง่ายขึ้น
Kubernetes schedule จะใช้ปริมาณของ memory ในการตัดสินใจตว่าจะ deploy pod ลงไปใน node ไหน
การ disable swap เราจะใช้คำสั่ง
$ swapoff -a
คำสั่ง swapoff จะเป็นการ disable ชั่วคราวเท่านั้นถ้า restart server ใหม่ swap จะถูก enable ขึ้นมาใช้งานใหม่ เราจึงต้องไปแก้ไฟล์ fstab โดยการ comment บรรทัดที่มี swap ออก
$ sudo sed -i '/ swap / s/^/#/' /etc/fstab
2. ตั้ง Hostname
ในขั้นตอนนี้เราจะตั้งชื่อ hostname ให้อ่านง่าย อาจดูว่าเป็นขั้นตอนที่ดูไม่ค่อยจำเป็นเท่าไหร่ เพราะเราสามารถตั้ง hostname เป็นอะไรก็ได้ kubernetes ไม่ได้สนใจ แต่หลังจากนี้ถ้าเกิดปัญหาขึ่้นมาตอน Operation การตั้งชื่อให้อ่านง่ายจะช่วยเรามากๆ ดังนั้นเราจะไม่ตั้งชื่อเป็น ubuntu-01, ubuntu-02 แบบนี้ เพราะสุดท้ายคุณเองนั่นแหละจะลืมเองว่าตัวไหนเป็น control plane หรือตัวไหนเป็น worker
เราจะใช้คำสั่งนี้ในการตั้ง hostname
$ sudo hostnamectl set-hostname "control-plane"
และเราจะใช้คำสั่ง exec bash เพื่อให้ดการเปลี่ยนชื่อ hostname นี้มีผลทันที
$ exec bash
เราจะตั้งชื่อเครื่องตามนนี้
- เครื่องที่ทำหน้าที่เป็น control plane หรือ master ให้ใช้ชื่อว่า control-plane
- เครื่องที่ทำหน้าที่เป็น worker ให้ตั้งชื่อเรียงลำดับไปเรื่อยๆ แบบนี้
- worker-node1
- worker-node2
- worker-node3
ข้อแนะนำ ใน 1 cluster ควรจะมี worker nodes อย่างน้อย 3 ตัว
3. Mapping IP Address กับ Hostname ในทุกๆ Nodes
เราต้องแก้ไขไฟล์ /etc/hosts เพื่อ map ip address กับ hostname ที่เราได้ตั้งไว้เวลาอ้างถึง hostname จะได้วิ่งไปยัง IP Address ของเครื่องนั้นเลย วิธีการคือ เปิดไฟล์ /etc/hosts แล้วเพิ่มข้อความนี้เข้าไป
10.0.0.2 control-plane
10.0.0.3 worker-node1
10.0.0.4 worker-node2
10.0.0.5 worker-node3
IP Address ของเราจะไม่เหมือนกันขึ้นอยู่กับ network ที่เรากำหนดไว้
4. ตั้งค่า IPV4 Bridge ในทุกๆ Nodes
ในกรณีที่เราใช้ containerd เป็น container runtime เราต้อง set ให้ network เป็น bridge เราจึงต้อง run script นี้
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# sysctl params required by setup, params persist across reboots
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
# Apply sysctl params without reboot
sudo sysctl --system
5. ติดตั้ง Container Runtime(Containerd)
Kubernetes นั้นไม่สามารถทำงานกับ container ได้เราจึงต้องติดตั้ง container runtime เพื่อสร้าง container ขึ้นมาทำงาน ซึ่ง container runtime ที่ได้รับความนิยมมากที่สุดตอนนี้คือ containerd โดยจะมีขั้นตอนติดตั้ง containerd ดังนี้
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install -y containerd.io
หลังจากที่เรา install containerd เสร็จเรียบร้อยให้สร้าง default configuration ของ containerd ด้วยคำสั่ง
sudo mkdir -p /etc/containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml
หลังจากนั้นให้แก้ config.toml ที่ได้มา โดยดารเปิดไฟล์ /etc/containerd/config.toml แล้วให้ค้นหา section ที่มีชื่อว่า [plugins.“io.containerd.grpc.v1.cri”.containerd.runtimes.runc] เปลี่ยน SystemdCgroup จาก false ไปเป็น true
หรือ run คำสั่งนี้เพื่อเปลี่ยน SystemdCgroup
sudo sed -i 's/ SystemdCgroup = false/ SystemdCgroup = true/' /etc/containerd/config.toml
ที่เราต้องแก้ไฟล์ config.toml เพราะ kubelet ต้องการไปอยู่ใน cgroup ของ systemd
สุดท้ายให้ restart containerd service ใหม่อีกรอบ
$ sudo systemctl restart containerd
สิ่งที่ต้องระวัง
ถ้าเราใช้ containerd ห้ามติดตั้่ง docker ลงไปด้วย เพราะ kubeadm จะทำการค้นหา container runtime ซึ่ง kubeadm จะเลือกใช้งาน docker ก่อน containerd
ส่วนใหญ่บน server เรานิยมใช้ containerd มากกว่า docker เพราะตอนที่เราติดตั้ง kubernetes จะไม่มี docker shim ติดตั้งมาด้วย ดังนั้นถ้าเราอยากใช้งาน docker เราต้องไปติดตั้ง docker shim เอง
6. ติดตั้ง Kubernetes Components ในทุกๆ Nodes
ขั้นตอนนี้สำคัญมากๆ เพราะต้องการเครื่องมือที่จะต้องใช้ในการติดตั้ง kubernetes ซึ่งเครื่องมือที่เราต้องใช้ประกอบไปด้วย
- kubeadm เป็นคำสั่งที่ใช้ในการสร้าง kubernetes cluster และนำ worker node เข้ามา join ใน cluster
- kubelet เป็น agent ที่จะ run อยู่ในทุกๆ Node มีไว้คุยกับ Control plane
- kubectl เป็น command line ที่เราต้องใช้จัดการ kubernetes cluster
$ sudo apt-get install kubelet kubeadm kubectl
$ sudo apt-mark hold kubelet kubeadm kubectl containerd
หลังจากนั้นให้ตรวจสอบว่าในแต่ละเครื่อง kubelet และ containerd ทำงานปกติหรือไม่ด้วยคำสั่ง
$ sudo systemctl enable kubelet.service
$ sudo systemctl enable containerd.service
7. สร้าง Kubernetes Cluster
ในขั้นตอนนี้ให้เข้าไปที่เตรื่อง control-plane แล้ว run คำสั่ง kubeadm init เพื่อสร้าง kubernetes cluster
$ sudo kubeadm init
ถ้าต้องการระบุ IP address ของ Pods ให้ใช้ –pod-network-cidr ต่อท้าย
sudo kubeadm init --pod-network-cidr=10.0.0.0/16
อย่าให้ IP address ของ Pods ไป overlap หรือซ้ำกับ IP address ของ physical network
ในการจัดการกับ Kubernetes Cluster โดยใช้ kubectl เราต้องกำหนด configuration ของ user ที่ต้องการใช้งาน kubernetes cluster เราจึงต้องย้าย admin.conf ที่ generate ออกมาจาก kubeadm init ไปวางไว้ใน folder /.kube/config
# สร้าง folder .kube ใน home directory ของ user ปัจจุบัน
mkdir -p $HOME/.kube
# copy admin.conf ไปวางไว้ใน folder ที่เราได้สร้างขึ้น
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
# ปรับสิทธิให้ kubectl สามารถเข้ามาอ่านได้
sudo chown $(id -u):$(id -g) $HOME/.kube/config
8. ติดตั้ง Kubernetes Network(Calico)
หลังจากที่เราได้ init cluster ขึ้นมาแล้ว หลังจากนี้ให้เข้าไปติดตั้ง kubernetes network ซึ่ง Kubernetes network นั้นมีให้เลือกหลายตัวมากๆ ซึ่ง kubernetes ที่ได้รับความนิยมมากๆคือ Calico ซึ่งขั้นตอนการติดตั้ง Calico จะมีดังนี้
- Download calico.yml
$ wget https://raw.githubusercontent.com/projectcalico/calico/master/manifests/calico.yaml
หลังจากนั้นติดตั้ง Calico ด้วย kubectl apply
$ kubectl apply -f calico.yaml
สามารถเลือก kubernetes network ตัวอื่นได้ตามความต้องการ โดยสามารถดูรายละเอียดต่อได้ที่นี่
9. นำ Worker Node join เข้ามาใน cluster
ตอนที่เรา run คำสั่ง kubeadm init ในขั้นตอนที่ 7 จะมี command สำหรับ join เข้ามาใน cluster ที่สร้าง ให้นำคำสั่งนั้นไป run ในเครื่อง worker ทุกตัว
|
|
เราต้องมี token และ ค่า hash ของ CA certificate เราถึงจะสามารถ join เข้าไปใน cluster ได้ แต่ถ้าเรา copy คำสั่ง kubeadm join ไว้ไม่ทันให้กลับไปที่เครื่อง control-plane แล้ว run คำสั่ง
$ kubeadm token list
และหาค่า hash ของ CA Certificate ด้วยคำสั่ง
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
นำ token และ hash ของ CA Certificate ไปแทนที่ในคำสั่งนี้
|
|
หรือถ้าต้องการสร้าง token ตัวใหม่ขึ้นมาเราสามารถใช้ –print-join-command ต่อท้ายเข้าไปได้เลย
$ kubeadm token create --print-join-command
หลังจากนั้น copy คำสั่งที่ได้ไป run ใน worker node
สุดท้ายให้ทำการตรวจสอบสถานะของ Nodes ต่างๆ โดยที่ run คำสั่งนี้ใน control-plane
kubectl get nodes
ถ้าได้ผลลัพธ์ออกมามีทั้ง Control Plane และ Worker Nodes ครบตามจำนวนที่เราต้องการก็ถือว่าการติดตั้ง kubernetes ของเราเสร็จสมบูรณ์เรียบร้อย