About Me

quickbooksthai โปรแกรมบัญชี

ติดตั้ง KUBERNETES แบบออฟไลน์บน CENTOS

เนื่องจากผมเองได้มาเล่น Kubernetes และอยากลองติดตั้งแบบออฟไลน์ดู เลยจะมาเขียนไว้ก่อนเพื่อกันลืม แต่ไหน ๆ ก็เขียนละเลยเอาลง blog เลยละกัน จึงเป็นที่มาของ blog นี้ครับ
offline-install-kubernetes.jpg
ภาพประกอบจาก kubernetes.io
ก่อนที่จะเริ่มทำ ผมจะอธิบายคร่าว ๆ ก่อนว่า เราจะลง Kubernetes บน 2 โหนด คือ master และ worker (ซึ่งชื่อก็ตาม role เลยนะครับ) เป็นเครื่องออฟไลน์ และจะมีเครื่องออนไลน์ไว้ดาวน์โหลดแพคเกจต่าง ๆ ซึ่งทุกคำสั่งจะระบุบรรทัดแรกสุดว่าให้รันเครื่องไหน
Prerequisite: ขอ assume ว่าผู้อ่านบทความนี้เข้าใจสิ่งเหล่านี้มาแล้ว ดังนั้นจะไม่ขอลงลึกมาก
  • คอมมานด์ของ Docker
  • สถาปัตยกรรมของ Kubernetes
  • คอมมานด์เบื้องต้นของ kubectl
ในระบบนี้ ผมทดสอบด้วยการใช้ EC2 บน AWS โดยไม่มี Internet Gateway หรือ NAT Gateway และมีเครื่องออนไลน์อีกเครื่องต่อ Internet Gateway เพื่อเป็นเครื่องดาวน์โหลดแพคเกจต่าง ๆ และ shell เข้าไปยังเครื่อง EC2 ที่อยู่ในโหมดออฟไลน์ด้วย
จุดที่พึงระวังคือเครื่องออนไลน์และออฟไลน์ควรจะเหมือนกันให้มากที่สุด เพราะการดาวน์โหลดแพคเกจ yum จะอิงจากแพคเกจที่มีในเครื่องอยู่แล้วเป็นหลัก เช่นถ้าเครื่องออนไลน์อัพเดตเวอร์ชันใหม่กว่าออฟไลน์ เวลาดาวน์โหลดแพคเกจอาจจะมาไม่ครบทุกแพคเกจ และเวลาขนไปติดตั้งที่เครื่องออฟไลน์อาจพบปัญหาได้ เพราะเครื่องออนไลน์มีแพคเกจนั้นแล้วแต่เครื่องออฟไลน์ไม่มี
หมายเหตุ: Cloud Provider หลายเจ้ามี Managed Kubernetes Services ให้อยู่แล้ว ถ้าไม่จำเป็นก็ใช้เงินแก้ปัญหาไปดูจะเป็นทางเลือกที่ดีกว่า แต่ถ้ามีเหตุผลที่จำเป็นต้องลง Kubernetes เอง blog นี้จะช่วยท่านได้มาก

ติดตั้ง DOCKER

ในการติดตั้งนี้ ผมจะใช้ CRI (Container Runtime Interface) ของ Kubernetes เป็น Docker ดังนั้น ขั้นแรก ต้องลง Docker CE ก่อน โดยใช้วิธีติดตั้งจาก repo โดยรันคำสั่งดังนี้ (ในกรณีที่ CRI ไม่ใช่ Docker จะต้องตั้งค่าเพิ่มเติมด้วย แต่ถ้าเป็น Docker แล้วไม่ต้องทำอะไร)
บนเครื่องออนไลน์ ให้รันคำสั่งทั้งหมดเพื่อเพิ่มดาวน์โหลดแพคเกจ .rpm และเพิ่ม repo ของ Docker
[online]
yum install --downloadonly --downloaddir=/path/to/rpm yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install --downloadonly --downloaddir=/path/to/rpm/ docker-ce docker-ce-cli containerd.io
จากนั้นขนไฟล์ทั้งหมดที่โหลดมาจากเครื่องออนไลน์ไปที่ master, worker ด้วยคำสั่ง
[online]
scp /path/to/rpm/.rpm user@master:/path/to/dest/
scp /path/to/rpm/
.rpm user@worker:/path/to/dest/
รันคำสั่งขนไฟล์ไปให้ครบทุกเครื่องออฟไลน์ จากนั้นรันคำสั่งนี้ที่เครื่องออฟไลน์ทีละเครื่องเพื่อติดตั้ง Docker
[master & worker]
yum install -y /path/to/dest/*.rpm
yum จะติดตั้ง Docker ให้ รอจนเสร็จแล้วให้สั่งรัน Docker ผ่าน systemctl ดังนี้
[master & worker]
systemctl enable docker && systemctl start docker
หลังจากนั้นให้ลองทดสอบการรัน Docker ดูว่าสามารถรันได้ตามปกติ
ส่วนรายละเอียดอื่น ๆ หรือหากมีปัญหาในการติดตั้ง Docker สามารถเข้าไปดูที่ doc ได้เลย >> https://docs.docker.com/install/linux/docker-ce/centos/
จากข้อควรระวังที่ว่าแพคเกจในเครื่องออนไลน์และออฟไลน์ ถ้าต่างกันเราอาจพบปัญหาได้นั้น ผมพบว่าปัญหาจะเกิดกับ Docker มากกว่า Kubernetes ดังนั้นถ้าใครพบปัญหาแนะนำให้เปลี่ยนการติดตั้งไปดาวน์โหลดไบนารีเพื่อมาลงเองแทน เพราะไบนารีของ Docker จะมีแพคเกจที่ครบกว่า ดูวิธีติดตั้งได้ที่นี่ > https://docs.docker.com/install/linux/docker-ce/binaries/
ข้อสังเกต: kubeadm จะเรียกหา docker.service จาก systemd หากนำ Docker มาลงแบบ manual ไม่ผ่าน package manager อย่างเช่น yum จะไม่ได้เซ็ท systemd ให้ ต้องเซ็ทเองก่อนจะรัน kubeadm แต่เนื่องจากผมขอแนะนำให้ลงผ่าน yum ดังนั้น blog นี้จะไม่ได้ให้วิธีเซ็ทไว้

ติดตั้ง KUBERNETES

ถัดไปจะเป็นการติดตั้ง Kubernetes โดยใช้ kubeadm เริ่มจากการเพิ่ม repo ของ Kubernetes เข้าไปใน yum โดยใช้คำสั่ง
[online]
cat < /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF
จากนั้นดาวน์โหลดแพคเกจบนเครื่องออนไลน์โดยใช้คำสั่งดังนี้
[online]
yum --downloadonly --downloaddir=/path/to/rpm/ kubelet kubeadm kubectl --disableexcludes=kubernetes

เมื่อโหลดเสร็จแล้วให้ขนไฟล์ทั้งหมดไปไว้ที่เครื่อง master และ worker โดยใช้คำสั่งนี้รันบนเครื่องออนไลน์
[online]
scp /path/to/rpm/.rpm user@master:/path/to/dest
scp /path/to/rpm/
.rpm user@worker:/path/to/dest

รันคำสั่งนี้เพื่อติดตั้ง rpm บนเครื่องออฟไลน์ทั้ง master และ worker โดยรันทีละเครื่อง
[master & worker]
yum install -y /path/to/dest/*.rpm
รันคำสั่งนี้บนเครื่อง master และ worker เพื่อตั้งค่า โดยรันทีละเครื่อง
[master & worker]
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
จากนั้นให้เปิดไฟล์ /etc/sysctl.d/k8s.conf (ไม่มีให้สร้างขึ้นมา) และใส่สิ่งเหล่านี้ลงไป
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
เมื่อเสร็จแล้วให้รันคำสั่ง sysctl --system เพื่อให้ระบบอ่านค่า
ถัดไปให้รันคำสั่งนี้บนเครื่อง master และ worker เพื่อสั่ง enable kubelet โดยรันทีละเครื่อง
[master & worker]
systemctl enable --now kubelet
จากนั้น รันคำสั่ง kubeadm config images list ที่ master ตัว kubeadm จะแสดงรายการอิมเมจที่ต้องใช้ทั้งหมด ให้ตามดาวน์โหลดอิมเมจทั้งหมดจากเครื่องออนไลน์โดยใช้ docker pull ขนไฟล์มา และรันคำสั่ง docker load -i ทีละอิมเมจ โดยบนเครื่องออนไลน์ให้ทำดังนี้
[online]
docker pull k8s.gcr.io/kube-apiserver:v1.15.1
docker save -o /path/to/source/apiserver.tar k8s.gcr.io/kube-apiserver:v1.15.1
ซึ่งจะต้องทำทุกอิมเมจจนครบ หลังจากนั้นรันคำสั่งนี้บนเครื่องออนไลน์เพื่อขนอิมเมจเข้าเครื่อง master, worker
[online]
scp /path/to/source/*.tar user@master:/path/to/dest
ส่วนเครื่อง master และ worker ให้รันคำสั่งดังนี้ทีละเครื่อง เพื่อโหลดอิมเมจทั้งหมดทีเดียว (เนื่องจาก docker load ไม่สามารถใส่คำสั่ง wildcard เหมือน shell command อื่น ๆ ได้ จึงต้องใช้ loop แต่ใครจะใช้ docker load พิมพ์มือทีละตัวก็ได้ไม่ว่ากัน)
REPORT THIS AD

[master & worker]
for $f in /path/to/dest/*.tar
do
docker load -i $f
done
หลังจากนั้น ที่เครื่อง master ให้สั่งดังนี้ เพื่อให้ kubeadm เริ่มสร้างคลัสเตอร์
[master]
kubeadm init --pod-network-cidr 10.244.0.0/16 --apiserver-advertise-address $(hostname -i)
เนื่องจาก kubeadm จะตรวจสอบคลัสเตอร์ก่อนรัน ถ้าไม่ผ่านการตรวจสอบอาจจะ error และระบบจะไม่ทำงานต่อ ให้ลองไปตรวจดูว่าเราติดขั้นตอนอะไรและต้องแก้ไขที่ไหนต่อ โดยรายละเอียดเกี่ยวกับ kubeadm ให้ดูที่นี่ >> https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
เมื่อ init เสร็จ kubeadm จะพ่นคอมมานด์ออกมาสองอย่าง คือคอมมานด์ไว้สำหรับรันเซ็ทอัพ kubectl เพื่อไว้ควบคุม Kubernetes หน้าตาแบบนี้
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
คอมมานด์นี้รันได้เลย ส่วนอีกคอมมานด์คือคอมมานด์สำหรับ join node เข้าคลัสเตอร์
kubeadm join 10.192.20.231:6443 --token sw4rhb.kp35r47v4t8ij9tx --discovery-token-ca-cert-hash sha256:0ce787cf9e7fe738a8423962708b4ae8f77f0d1e43b4b33a3594bd831a230640
ซึ่งจะมีโทเคน คอมมานด์นี้ให้คัดลอกเก็บไว้เพราะจะได้ใช้อีกแน่ ๆ

ติดตั้ง NETWORK POD

จากนั้น kubeadm แนะนำให้ติดตั้ง network pod ต่อ โดยเราจะเลือก pod ไหนก็ได้ตามต้องการ ซึ่ง Kubernetes มี network ให้เลือกหลายค่าย ดังนี้ https://kubernetes.io/docs/concepts/cluster-administration/addons
flannel.jpg
ภาพจาก GitHub Flannel
ผมเลือก Flannel เป็น network โดยรายละเอียดของ Flannel ไปดูได้ที่ GitHub https://github.com/coreos/flannel/blob/master/Documentation/kubernetes.md
เริ่มการติดตั้ง ที่เครื่องออนไลน์ให้รันคำสั่งนี้ เพื่อโหลดไฟล์สำหรับดีพลอย Flannel มาก่อน
เมื่อ curl ดาวน์โหลดไฟล์เสร็จแล้ว จะได้ไฟล์ที่ชื่อว่า kube-flannel.yml ให้ใช้ vi เพื่อดูว่า Flannel เรียกคอนเทนเนอร์ชื่ออะไร (สังเกตว่าจะอยู่ตรง image: ) ให้ไปตามดาวน์โหลด และขนไฟล์ yaml ของ Flannel พร้อมกับอิมเมจของคอนเทนเนอร์เข้าเครื่อง master
หลังจากนั้น ที่เครื่อง master ให้รัน kubectl apply -f kube-flannel.yml เพื่อสร้าง Flannel บนคลัสเตอร์
เมื่อติดตั้ง pod network เสร็จแล้ว ให้เช็คว่า pod network และ CoreOS รันแล้วด้วยคำสั่ง kubectl get pods --all-namespaces บนเครื่อง master เมื่อมั่นใจว่าทั้งหมดรันแล้ว ต่อไปก็จะเป็นการ join worker เข้ากับ master

สั่ง JOIN WORKER เข้ากับ MASTER

ขั้นแรกของการ join คือให้สั่ง join โดยรันบน worker ด้วยคอมมานด์ที่เก็บไว้ก่อนหน้านี้ ซึ่งจะหน้าตาประมาณนี้
[worker: run with your own copied command]
kubeadm join 10.192.20.231:6443 --token sw4rhb.kp35r47v4t8ij9tx --discovery-token-ca-cert-hash sha256:0ce787cf9e7fe738a8423962708b4ae8f77f0d1e43b4b33a3594bd831a230640
ปล. นี่คือโทเคนจริงแต่เป็นแค่เครื่องทดลองของผมเอง และตอนนี้คลัสเตอร์โดนทุบทิ้งไปหมดแล้วครับ 😛 ถ้าคลัสเตอร์คุณยังอยู่อย่าแปะ token แบบนี้นะ
เมื่อรันคำสั่งนี้แล้ว kubeadm จะทำการ join worker เข้ากับ master node เมื่อ worker บอกสถานะว่า join เรียบร้อยแล้ว ให้รันคอมมานด์นี้ที่ master
[master]
kubectl get nodes
เอาท์พุตของคำสั่งนี้จะเป็นโหนดทั้งหมดที่ join เข้าคลัสเตอร์ ในตอนนี้สถานะของ worker อาจจะเป็น NotReady อยู่ ให้รันคำสั่งนี้
[master]
kubectl label node worker node-role.kubernetes.io/compute=
คำสั่งนี้จะ label ให้ worker node ให้ Kubernetes กำหนดสถานะเป็น compute หลังจากนั้นอีกสักพักใช้คำสั่ง kubectl get nodes บน master ก็จะเห็นว่าสถานะของ worker เป็น Ready ก็คือพร้อมใช้งานแล้ว

ข้อสังเกตที่พบจากการทดลองทำเอง และวิธีแก้

  • network pod ควรดีพลอยก่อนเริ่มนำ worker เข้ามา join ถ้าไม่ทำระบบอาจไม่ join ให้
  • ถ้าดีพลอยจนหมดตามขั้นตอนแล้วมีปัญหา เช่น join โหนดไม่ได้ join แล้ว master node ไม่ ready ให้ลองรีสตาร์ทเครื่อง master ดูก่อน
  • ถ้าเปิดโหมด swap ไว้จะ error ตอนตรวจสอบ kubeadm ดังนั้นต้องปิดก่อนรัน kubeadm โดยสั่ง swapoff -a ส่วนวิธีปิดถาวรให้ดูที่นี่ > https://docs.platform9.com/kubernetes/disabling-swap-kubernetes-node/
  • เครื่อง master ต้องมีมากกว่า 2 CPU ถ้าไม่เข้าเงื่อนไขนี้ kubeadm จะไม่ให้ผ่าน หากเป็นเทสอาจติด flag เพื่อ skip ข้อนี้ไปได้ แต่ไม่ควรทำกับโปรดักชั่น
  • โดยปกติ master จะไม่มีการ schedule pod (จะรันเฉพาะ pod ที่เกี่ยวกับ system เท่านั้น) เนื่องจากเหตุผลด้านความปลอดภัย แต่หากคลัสเตอร์มีโหนดจำนวนไม่มาก ก็สามารถสั่งเปิด schedule บน master ได้เช่นกัน โดยใช้คำสั่ง kubectl taint node mymasternode node-role.kubernetes.io/master:NoSchedule-

การติดตั้ง KUBERNETES ยังไม่จบ

จนถึงขั้นตอนนี้ คุณจะได้ Kubernetes Cluster พร้อมกับ kubectl ที่ใช้ควบคุมคลัสเตอร์, ใช้เป็น proxy หรือใด ๆ ก็ตามแล้ว
แต่กว่า Kubernetes Cluster จะใช้งานได้จริงเรายังมีงานอีกจำนวนมากที่ต้องทำครับ ที่ตอนนี้นึกออกเช่น
ซึ่งทั้งหมดนี้ผมยังไม่ว่างทำต่อ ถ้าสะดวกทำเมื่อไรแล้วจะมาอัพเดตอีกทีครับ

Post a Comment

0 Comments