9:57 AM December 10, 2022

Xây dựng một Kyubanetezu Kurasuta và triển khai ứng dụng web với Kyuba-chan

Bài viết này hướng dẫn xây dựng một K8s cluster (キューバーネテズ・クラスター), phục vụ cho mục đích học tập, nghiên cứu, triển khai các testbed trong mỗi trường lab cỡ nhỏ. Bài viết hữu ích với những người lần đầu làm quen với K8s, xây dựng một hệ thống K8s đơn giản phục vụ cho việc tìm hiểu các loại resources của Orchestrator này.

K8s (Kubernetes, K——–s, K8s), là một trình điều phối container (Containers Orchestrator) mạnh mẽ hàng đầu hiện nay, được xây dựng bởi Google. Kubernetes, tiếng Anh đọc là Kuu-ber-net-eez hoặc Kuu-ber-nets đều được, thực ra đây là một từ tiếng Hi Lạp κυβερνήτης, đọc đúng phải là kyu-ver-ni-tis, nghĩa là thuyền trưởng, mang ý nghĩa là người điều khiển con tàu chở các containers. Tham khảo thêm thì tiếng Nhật bạn có thể đọc là Kyu-ba-ne-te-zư cho nó UwU. K8s mang lại những lợi ích to lớn trong việc triển khai ứng dụng theo mô hình Microservice, lập lịch, giám sát và quản lí Container, là công cụ không thể thiếu trong DevOps. Thực ra có rất nhiều các trình quản lí container khác, có thể kể tới đó là Docker Swarm, nhưng trong đó K8s thì vẫn là vua. K8s hiện được tích hợp trong các Cloud Provider như AWS (EKS), Azure (AKS), GCP (GKE), và trong thực tế thì nhiều usecase của K8s là được sử dụng trên các Provider này. Tuy nhiên đối với người mới, để sử dụng được các dịch vụ trên lại đòi hỏi một lượng kĩ năng nhất định về từng Cloud Provider. Thế nên, việc xây dựng một K8s Cluster trên môi trường lab với quy mô nhỏ là cần thiết.

Khi bắt đầu tìm hiểu về K8s, trưởng lab của tôi đã dành cho nhóm 1 tuần chỉ để cài cái này, và kết quả là vẫn không cài được. Cơ bản vì nó còn một số cấu hình khác mà không dễ lắm để tìm một phát ăn ngay trên google. Tôi hi vọng bài viết này hữu ích với người đang bắt đầu tìm hiểu về K8s, tránh những sự cố đáng tiếc như đập bàn phím đập chuột hoặc thậm chí là đập máy tính.

1. Cài đặt thủ công

1.1. Tạo các máy ảo

Đầu tiên cần tạo ra các máy ảo để cài đặt K8s. Có thể dùng VMware Workstation tạo thủ công hoặc dùng KVM chuyên nghiệp hơn cũng được. Ta cần tạo ra một máy master và ít nhất một máy worker (mỗi máy khoảng 4vCPU 4GB RAM). Sau khi tạo xong thì có mấy việc cần setup như sau:

Xoá cái vim-tiny nếu cái máy ảo của bạn bấm i trong vim nó không vào chế độ insert luôn, khó dùng lắm

$ sudo apt-get remove vim-tiny
$ sudo apt-get remove –auto-remove vim-tiny

Thiết lập mật khẩu đơn giản, ở đây theo truyền thống tôi đặt là “1” cho nó bảo mật 🙂

$ vi /etc/pam.d/common-password
password        [success=2 default=ignore]      pam_unix.so obscure sha512 minlen=4

Đặt hostname, đặt là master cho máy master, worker1, worker2, … cho các máy worker

$ sudo vi /etc/hostname

Tiếp theo ta cần đặt ip tĩnh cho mỗi máy. Hướng dẫn dưới đây sẽ áp dụng cho máy ảo tạo bởi VMWare Workstation, với máy ảo tạo bằng các trình ảo hoá khác, ý tưởng tương tự. Để không bị ảnh hưởng khi dùng máy ở nhà cũng như ở trường, vì ở mỗi nơi máy host sẽ có ip khác nhau nên nếu để mạng bridge sẽ dễ bị lỗi, ta cài đặt các node sử dụng mạng NAT, sau đó tại Virtual Network Editor ta setup lại mạng NAT như sau:

Cấu hình mạng trong VMWare

Mạng NAT là 172.16.1.0/24, gateway là 172.16.1.2, nên đặt tránh mạng 192.168.x.x hoặc cái gì đó khó bị xung đột. Tại mỗi node, chạy câu lệnh:

$ sudo vi /etc/netplan/0 (tab một phát ^^)

Sửa file như sau:

Lưu ý, mục network.ethernets, ens33 là tên của interface mạng của máy, để xem máy đang dùng interface nào ta dùng lệnh ifconfig. IP tĩnh ta muốn set cho máy thì điền vào mục network.ethernets.ens33.addresses. Chú ý rằng địa chỉ và gateway phải phù hợp với cấu hình mạng ta thiết lập trong VMware. Lưu ý các giá trị tương ứng trong file netplan và các phần được bôi đỏ của ảnh cấu hình mạng trong VMWare .

Lưu lại cấu hình netplan, sau đó chạy lệnh:

$ sudo netplan apply

Làm tương tự với các node còn lại. Tới đây ta đã cài đặt xong cơ bản một VM, ta nên lưu lại trạng thái này bằng cách tạo một snapshot.

1.2. Cài đặt Docker và K8s

Cài đặt Docker và K8s theo link hướng dẫn https://phoenixnap.com/kb/install-kubernetes-on-ubuntu. Chú ý làm tới phần Install Kubernetes thì sẽ bị lỗi tại Step 1 và Step 2, ta sẽ không làm như 2 bước này trong hướng dẫn mà thay bằng các thủ tục sau. Chạy các câu lệnh:

$ sudo apt-get install -y apt-transport-https ca-certificates curl
$ sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
$ echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
$ sudo apt-get update

Tới đây thì quay lại làm tiếp Step 3 trở đi. Chú ý một số phần sẽ chỉ được thực hiện trên node master.

Tại phần Deploy Kubernetes, Step 3 câu init số 10 thay bằng câu sau:

$ sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --control-plane-endpoint=[master-hostname] --upload-certs

Có thể dùng Flannel thay cho Calico bằng cách thay toàn bộ Step 4 bằng:

$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

Khi dùng lệnh kubectl get nodes mà các node hiện status là NotReady, sử dụng 2 câu lệnh sau:

# swapoff -a
# strace -eopenat kubectl version

Các cài đặt Kyuba-chan mới nhất hiện giờ đều chọn Container Runtime là Containerd thay cho Docker. Vì vậy sau khi các K8s Pod được deploy, ta không thể dùng lệnh docker hay ctr để hiển thị các image và container đang chạy. Ta cần thay thế việc sử dụng lệnh docker bằng lệnh crictl.

Mở file /etc/crictl.yaml và thêm cấu hình:

runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 2
debug: false
pull-image-on-create: true

Vì không còn sử dụng Docker, khi khai báo tên các container image trong các file .yaml, ta cần thêm tên kho lưu trữ phía trước tên image, ví dụ, docker.io/httpd:latest thay vì httpd:latest như trước kia.

Việc cố gắng chuyển từ Containerd sang Docker là không cần thiết và có thể gây lỗi ức chế không cần thiết. Tôi không khuyến khích bạn làm cách này vì bản thân đã từng thử tới 4h sáng vẫn không xong. Một số tài liệu bạn có thể tham khảo:

Cài đặt Golang (dùng để build cri-dockerd sock) tại: Download and install – The Go Programming Language

Document về Container Runtime của K8s: Container Runtimes | Kubernetes

Document về thay đổi Container Runtime từ Docker sang Containerd: Changing the Container Runtime on a Node from Docker Engine to containerd | Kubernetes

Cài đặt cri-dockerdGitHub – Mirantis/cri-dockerd: dockerd as a compliant Container Runtime Interface for Kubernetes.

Nhắc lại lần nữa, không khuyến khích làm điều thừa thãi này.

1.3. Fix lỗi domain

Theo mặc định, một Kubernetes Cluster tốt, chuẩn sách giáo khoa sẽ thực hiện được lệnh sau từ bất kì máy nào:

$ ping kubernetes

Nếu không ping được với nghĩa rằng không có output từ câu lệnh trên, có nghĩa là Cluster chưa được setup DNS đúng. Để kiểm tra xem DNS đã được setup đúng chưa, mở file /etc/resolv.conf

nameserver 127.0.0.53
options edns0 trust-ad
search default.svc.cluster.local svc.cluster.local cluster.local

Nếu không có dòng search … như kia có nghĩa là DNS chưa được setup đúng cách. Công việc fix không đơn giản chỉ là thêm dòng đó vào file này, nó tốn của tôi rất nhiều nước mắt và tủi hờn, để cho tới ngày hôm nay, 22:32 12/6/2023, tôi mới tìm được cách trị nó.

File trên có nghĩa rằng, khi thực hiện request tới một domain nào đó, máy local sẽ tìm kiếm domain đó kèm theo các prefix liệt kê ở dòng search phía trên. Tuy nhiên file /etc/resolv.conf chỉ là một file được render ra từ một nguồn khác, sau khi thêm search vào file này, một thời gian sau máy sẽ tự reset lại. File cần edit ở đây là /etc/systemd/resolved.conf. Mở file này ra và sửa dòng Domains= như sau:

Domains=default.svc.cluster.local svc.cluster.local cluster.local

Lưu lại file và chạy lệnh:

# systemctl restart systemd-resolved

Thêm địa chỉ 169.254.25.10 (lấy được từ trường DNS trong file /etc/systemd/resolved.conf). Sau đó apply lại file netplan này.

Ơn trời, cuối cùng cũng fix được ạ.

3. Sử dụng Kubespray

Ngoài cách cài đặt thủ công như trên, ta có thể setup nhanh một cụm Kubernetes đạt chuẩn môi trường Production với công cụ Kubespray. Kuberspray được open trên Github, và được sử dụng tại Viettel Cloud 🙂

https://github.com/kubernetes-sigs/kubespray

Sau khi cài xong thì vẫn bị lỗi DNS ở trên. Mình không rõ các bạn thế nào nhưng mình và một Senpai khác cài đều bị như thế. Cơ mà Senpai kia có vẻ không quan tâm vụ này lắm, chứ mình thì khó chịu vl, tý thì khóc.

4. Triển khai ứng dụng Web đơn giản với Kyuba-chan

Ứng dụng trong ví dụ này là một ứng dụng Web sử dụng PHP được triển khai dưới dạng Micro Service với ba thành phần: PHP, Httpd, MySQL. Chi tiết code triển khai và các bước triển khai được tôi ghi trong file README.md của github repo https://github.com/bonavadeur/kyubachan-reibun.git, do Markdown file viết dễ và đẹp hơn trên Blog này.

Chú ý, hướng dẫn này chủ yếu nêu ý tưởng, không đi vào hướng dẫn chi tiết Step-by-Step. Có những lỗi phát sinh thì phải tự biết mà khắc phục :).

Cảm ơn bạn đã đọc bài viết này.