- vừa được xem lúc

[K8s] Xây dựng Kubernetes cluster bằng công cụ kubeadm trên Virtual Box

0 0 26

Người đăng: Nguyen Minh Hung

Theo Viblo Asia

GitHub repo: https://github.com/holdennguyen/kubernetes-install-cluster-with-kubeadm

Vagrant Kubernetes Kubernetes containerd

🦖 Giải thích chi tiết từng bước cho người mới bắt đầu.
Tham khảo tài liệu của K8s - mục Bootstrapping clusters with kubeadm.
Hướng dẫn này sẽ dựng Kubernetes cluster trên máy tính cá nhân bằng cách sử dụng máy ảo Virtual Box. Chúng ta sẽ sử dụng phần mềm Vagrant để tự động hóa quá trình tạo máy ảo Virtual Box.

Trước khi bắt đầu

  • 🚧 Mô hình cluster: 1 máy Control Plan và 2 máy Node.
  • 🖥️ Hệ điều hành: Ubuntu 18.04 LTS (Bionic Beaver)
  • ⚙️ Tài nguyên hệ thống: 2 GB of RAM and 2 CPUs per machine.
  • 📮 Mỗi máy sẽ có hostname, MAC address, và product_uuid riêng biệt.
  • 🧱 Không thiết lập firewall. (Mặc định cho phép traffic ra vào các port)
  • 🌐 Các máy trong cluster được kết nối mạng với nhau (private network, sử dụng network interface enp0s8 của các máy ảo).

Các bước cần làm

  • ▶️ Tạo máy ảo Virtual Box bằng Vagrant
  • ▶️ Cài đặt container runtime (containerd) trên tất cả các máy ảo
  • ▶️ Cài đặt kubeadm, kubelet và kubectl trên tất cả các máy ảo
  • ▶️ Khởi động control plane và nodes
  • ▶️ Dọn dẹp môi trường

Tạo máy ảo Virtual Box bằng Vagrant

Vagrant là một công cụ để tạo và quản lý môi trường máy ảo. Nó thường được coi là một dạng Infrastructure as Code (IaC), cho phép chúng ta khởi tạo và quản lý cơ sở hạ tầng của mình bằng code thay vì chọn bằng tay trên console. Vagrant chủ yếu đóng vai trò là công cụ sử dụng cho môi trường máy ảo và thường sẽ không dùng để quản lý cơ sở hạ tầng Production.

Bắt đầu

Chúng ta sẽ tạo các máy ảo với Virtual Box bởi vì nó miễn phí và hoạt động ổn trên tất cả các hệ điều hành.

Đầu tiên, tải và cài đặt VirtualBox, Vagrant trên máy tính của bạn.

Chúng ta sẽ xây dựng các máy ảo theo khai báo trong Vagrantfile. Tạo Vagrantfile với nội dung như sau vào thư mục của bạn.

 # -*- mode: ruby -*- # vi:set ft=ruby sw=2 ts=2 sts=2: # Xác định số lượng máy control plane (MASTER_NODE) và máy node (WORKER_NODE) NUM_MASTER_NODE = 1 NUM_WORKER_NODE = 2 IP_NW = "192.168.56." MASTER_IP_START = 1 NODE_IP_START = 2 # Tất cả thiết lập Vagrant được khai báo dưới đây. Số "2" trong Vagrant.configure # là thiết lập phiên bản sử dụng # Đừng thay đổi trừ khi bạn biết mình đang làm gì Vagrant.configure("2") do |config| # Để tham khảo thêm, xem tài liệu tại # https://docs.vagrantup.com. # Tất cả môi trường mà Vagrant xây dựng đều cần một box. Bạn có thể tìm các # box tại https://vagrantcloud.com/search. # Đây là một số thông tin chi tiết về vagrant box "ubuntu/bionic64": # Hệ điều hành: Ubuntu 18.04 LTS (Bionic Beaver) # Ubuntu 18.04 LTS sẽ được cập nhật bảo mật và sửa lỗi # từ Canonical, công ty đứng sau Ubuntu, cho đến tháng 4 năm 2023 # đối với bản desktop và server, và đến tháng 4 năm 2028 đối # với bản server có Extended Security Maintenance (ESM). # Kiến trúc: x86_64 (64-bit) # Dung lượng bộ nhớ: 10 GB # RAM: 2 GB # CPUs: 2 # Giao diện đồ họa: None (headless) # Người tạo: VirtualBox config.vm.box = "ubuntu/bionic64" # Tắt tính năng tự động cập nhật của box. Nếu tắt, # boxes sẽ chỉ kiểm tra cập nhật khi người dùng chạy # `vagrant box outdated`. Không khuyến khích. config.vm.box_check_update = false # Xem thêm tài liệu của Virtual box tại # https://developer.hashicorp.com/vagrant/docs/providers/virtualbox/configuration # Khởi tạo Control Plane (1..NUM_MASTER_NODE).each do |i| config.vm.define "kubemaster" do |node| node.vm.provider "virtualbox" do |vb| vb.name = "kubemaster" vb.memory = 2048 vb.cpus = 2 end node.vm.hostname = "kubemaster" node.vm.network :private_network, ip: IP_NW + "#{MASTER_IP_START + i}" end end # Khởi tạo Nodes (1..NUM_WORKER_NODE).each do |i| config.vm.define "kubenode0#{i}" do |node| node.vm.provider "virtualbox" do |vb| vb.name = "kubenode0#{i}" vb.memory = 2048 vb.cpus = 2 end node.vm.hostname = "kubenode0#{i}" node.vm.network :private_network, ip: IP_NW + "#{NODE_IP_START + i}" end end end 

Trong Vagrantfile này, chúng ta đơn giản chỉ khai báo:

  • Số lượng máy ảo: NUM_MASTER_NODE, NUM_WORKER_NODE
  • Địa chỉ IP: IP_NW, MASTER_IP_START, NODE_IP_START
  • Kết nối mạng nội bộ: node.vm.network
  • hostname riêng biệt cho mỗi máy ảo: node.vm.hostname
  • Hệ điều hành: config.vm.box
  • Tài nguyên hệ thống: vb.memory, vb.cpus

Cú pháp trong VagrantfileRuby, nhưng để viết hay chỉnh sửa bạn không cần phải hiểu về ngôn ngữ lập trình Ruby. Xem thêm đây để biết thêm thông tin về cú pháp trong Vagrantfile.

Bắt đầu khởi tạo

Chạy câu lệnh:

 vagrant up

Output sẽ tương tự như sau:

 Bringing machine 'kubemaster' up with 'virtualbox' provider... Bringing machine 'kubenode01' up with 'virtualbox' provider... Bringing machine 'kubenode02' up with 'virtualbox' provider... ==> kubemaster: Importing base box 'ubuntu/bionic64'... ==> kubemaster: Matching MAC address for NAT networking... ==> kubemaster: Setting the name of the VM: kubemaster ==> kubemaster: Clearing any previously set network interfaces... ==> kubemaster: Preparing network interfaces based on configuration... kubemaster: Adapter 1: nat kubemaster: Adapter 2: hostonly ==> kubemaster: Forwarding ports... kubemaster: 22 (guest) => 2222 (host) (adapter 1) ==> kubemaster: Running 'pre-boot' VM customizations... ==> kubemaster: Booting VM... ==> kubemaster: Waiting for machine to boot. This may take a few minutes... kubemaster: SSH address: 127.0.0.1:2222 kubemaster: SSH username: vagrant kubemaster: SSH auth method: private key kubemaster: Warning: Connection reset. Retrying... kubemaster: Warning: Connection aborted. Retrying... kubemaster: kubemaster: Vagrant insecure key detected. Vagrant will automatically replace kubemaster: this with a newly generated keypair for better security. kubemaster: kubemaster: Inserting generated public key within guest... kubemaster: Removing insecure key from the guest if it's present... kubemaster: Key inserted! Disconnecting and reconnecting using new SSH key... ==> kubemaster: Machine booted and ready! ==> kubemaster: Checking for guest additions in VM... kubemaster: The guest additions on this VM do not match the installed version of kubemaster: VirtualBox! In most cases this is fine, but in rare cases it can kubemaster: prevent things such as shared folders from working properly. If you see kubemaster: shared folder errors, please make sure the guest additions within the kubemaster: virtual machine match the version of VirtualBox you have installed on kubemaster: your host and reload your VM. kubemaster: kubemaster: Guest Additions Version: 5.2.42 kubemaster: VirtualBox Version: 7.0 ==> kubemaster: Setting hostname... ==> kubemaster: Configuring and enabling network interfaces... ==> kubemaster: Mounting shared folders... kubemaster: /vagrant => C:/Users/MSI BRAVO/kubernetes-install-cluster-with-kubeadm ==> kubenode01: Importing base box 'ubuntu/bionic64'... ==> kubenode01: Matching MAC address for NAT networking... ==> kubenode01: Setting the name of the VM: kubenode01 ==> kubenode01: Fixed port collision for 22 => 2222. Now on port 2200. ==> kubenode01: Clearing any previously set network interfaces... ==> kubenode01: Preparing network interfaces based on configuration... kubenode01: Adapter 1: nat kubenode01: Adapter 2: hostonly ==> kubenode01: Forwarding ports... kubenode01: 22 (guest) => 2200 (host) (adapter 1) ==> kubenode01: Running 'pre-boot' VM customizations... ==> kubenode01: Booting VM... ==> kubenode01: Waiting for machine to boot. This may take a few minutes... kubenode01: SSH address: 127.0.0.1:2200 kubenode01: SSH username: vagrant kubenode01: SSH auth method: private key kubenode01: Warning: Connection reset. Retrying... kubenode01: Warning: Connection aborted. Retrying... kubenode01: kubenode01: Vagrant insecure key detected. Vagrant will automatically replace kubenode01: this with a newly generated keypair for better security. kubenode01: kubenode01: Inserting generated public key within guest... kubenode01: Removing insecure key from the guest if it's present... kubenode01: Key inserted! Disconnecting and reconnecting using new SSH key... ==> kubenode01: Machine booted and ready! ==> kubenode01: Checking for guest additions in VM... kubenode01: The guest additions on this VM do not match the installed version of kubenode01: VirtualBox! In most cases this is fine, but in rare cases it can kubenode01: prevent things such as shared folders from working properly. If you see kubenode01: shared folder errors, please make sure the guest additions within the kubenode01: virtual machine match the version of VirtualBox you have installed on kubenode01: your host and reload your VM. kubenode01: kubenode01: Guest Additions Version: 5.2.42 kubenode01: VirtualBox Version: 7.0 ==> kubenode01: Setting hostname... ==> kubenode01: Configuring and enabling network interfaces... ==> kubenode01: Mounting shared folders... kubenode01: /vagrant => C:/Users/MSI BRAVO/kubernetes-install-cluster-with-kubeadm ==> kubenode02: Importing base box 'ubuntu/bionic64'... ==> kubenode02: Matching MAC address for NAT networking... ==> kubenode02: Setting the name of the VM: kubenode02 ==> kubenode02: Fixed port collision for 22 => 2222. Now on port 2201. ==> kubenode02: Clearing any previously set network interfaces... ==> kubenode02: Preparing network interfaces based on configuration... kubenode02: Adapter 1: nat kubenode02: Adapter 2: hostonly ==> kubenode02: Forwarding ports... kubenode02: 22 (guest) => 2201 (host) (adapter 1) ==> kubenode02: Running 'pre-boot' VM customizations... ==> kubenode02: Booting VM... ==> kubenode02: Waiting for machine to boot. This may take a few minutes... kubenode02: SSH address: 127.0.0.1:2201 kubenode02: SSH username: vagrant kubenode02: SSH auth method: private key kubenode02: Warning: Connection reset. Retrying... kubenode02: Warning: Connection aborted. Retrying... kubenode02: kubenode02: Vagrant insecure key detected. Vagrant will automatically replace kubenode02: this with a newly generated keypair for better security. kubenode02: kubenode02: Inserting generated public key within guest... kubenode02: Removing insecure key from the guest if it's present... kubenode02: Key inserted! Disconnecting and reconnecting using new SSH key... ==> kubenode02: Machine booted and ready! ==> kubenode02: Checking for guest additions in VM... kubenode02: The guest additions on this VM do not match the installed version of kubenode02: VirtualBox! In most cases this is fine, but in rare cases it can kubenode02: prevent things such as shared folders from working properly. If you see kubenode02: shared folder errors, please make sure the guest additions within the kubenode02: virtual machine match the version of VirtualBox you have installed on kubenode02: your host and reload your VM. kubenode02: kubenode02: Guest Additions Version: 5.2.42 kubenode02: VirtualBox Version: 7.0 ==> kubenode02: Setting hostname... ==> kubenode02: Configuring and enabling network interfaces... ==> kubenode02: Mounting shared folders... kubenode02: /vagrant => C:/Users/MSI BRAVO/kubernetes-install-cluster-with-kubeadm 

Bạn có thể kiểm tra trạng thái các máy ảo đã dựng bằng lệnh sau:

 vagrant status

Thông tin về các máy ảo được tạo và quản lý bởi vagrant được trả về

 Current machine states: kubemaster running (virtualbox) kubenode01 running (virtualbox) kubenode02 running (virtualbox) This environment represents multiple VMs. The VMs are all listed above with their current state. For more information about a specific VM, run `vagrant status NAME`.

Lỗi nhức nách: vagrant up times out tại bước 'default: SSH auth method: private key'

Lỗi này xảy ra khi bật máy ảo không thành công. Mặc định, Virtual Box sử dụng TSC mode gọi là "RealTscOffset," để điều chỉnh giá trị TSC (Time Stamp Counter) trên máy ảo để đồng bộ clock freqency của CPU giữa máy host và máy ảo.

Nếu bạn đang sử dụng Windows đã bật phần mềm máy ảo Hyper-V, phải tắt Hyper-V để tránh gây ra xung đột với Virtual Box dẫn đến lỗi vagrant up time out ở trên.

Để tắt hoàn toàn Hyper-V, chạy lệnh sau trong cmd:

 bcdedit /set hypervisorlaunchtype off

sau đó tắt và bật lại máy tính.

Chú ý rằng bcdedit là viết tắt của boot configuration data edit, nói cách khác nó sẽ ảnh hưởng đến những phần mềm có thiết lập khi boot lại hệ điều hành, vì vậy bạn cần phải shutdown máy hoàn toàn (không suspend hay restart) để áp dụng thay đổi. Để PC tắt trong khoảng 10 giây trước khi bật lại. Nếu PC không cho shutdown trong Start menu, bạn có thể chạy lệnh shutdown /p trong cmd dưới quyền admin. Trên laptop, bạn có thể cần phải tháo pin.

Cài lại VagrantVirtual Box. Nếu lỗi vẫn còn, có thể bạn sẽ phải cài lại hệ điều hành Windows, nhớ đừng bật Hyper-V!

Truy cập vào máy ảo bằng Vagrant

Để ssh vào máy ảo, chỉ cần chạy lệnh:

 vagrant ssh <hostname>

Vagrant SSH with VSCode

Có thể thấy trong output khi chạy vagrant up, Vagrant có chuyển tiếp port 22 và tạo ssh keypairs cho mỗi máy ảo dù chúng ta không thiết lập trong Vagrantfile. Để xem thêm thông tin, bạn có thể đọc Vagrant Share: SSH SharingVagrantfile: config.ssh.

OK, sang bước kế tiếp nào!

Cài đặt container runtime (containerd) trên tất cả các máy ảo

Thực hiện công việc ở bước này trên tất cả các máy ảo

Ghi chú: Dockershim đã bị bỏ khỏi dự án Kubernetes ở bản 1.24. Đọc Dockershim Removal FAQ để biết thêm thông tin.

Dockershim là một thành phẩn của Kubernetes được sử dụng để giao tiếp với Docker runtime. Nó được giới thiệu như một giải pháp tạm thời cho phép Kubernetes sử dụng Docker như một container runtime trước khi Kubernetescontainer runtime interface (CRI) của riêng họ.

Bạn cần phải cài đặt một container runtime trên mỗi node trong cụm K8s (Kubernetes) để các Pods có thể chạy ở đó. Và phiên bản K8s 1.26 yêu cầu phải sử dụng một container runtime tương thích với Container Runtime Interface (CRI) của K8s. Đây là một số container runtime phổ biến với Kubernetes:

Bạn có thể xem hướng dẫn cài đặt cho các loại trên tại đây. Trong hướng dẫn này, chúng ta sẽ sử dụng Containerd.

Cài đặt và thiết lập các yêu cầu cần chuẩn bị trước

Tải các module của nhân Linux

 cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf overlay br_netfilter EOF sudo modprobe overlay sudo modprobe br_netfilter
  • modules-load.d trong Linux là thư mục hệ thống sử dụng để thiết lập các module của kernel được tải lên tiến trình. Nó bao gồm các tệp đuôi .conf chỉ định các module được tải khi hệ thống khởi động.

  • Module overlay được sử dụng để cung cấp overlay filesystem, là một kiểu filesystem cho phép nhiều filesystem xếp chồng lên nhau. Nó cực kỳ hữu dụng trong công nghệ containerization, nơi các container cần những filesystem cô lập của riêng nó.

  • Module br_netfilter được sử dụng để bật tính năng lọc và thao tác gói tin ở kernel-level, hữu dụng đối với việc kiểm soát lưu lượng mạng và bảo mật. Nó thường được dùng cùng với các mạng của namespace và các thiết bị mạng ảo để cung cấp việc cô lập cũng như định tuyến cho ứng dụng containerized.

Để kiểm tra module overlaybr_netfilter đã được load, chạy lệnh dưới đây:

 lsmod | grep overlay lsmod | grep br_netfilter

Chuyển tiếp IPv4 và cho phép iptables nhận diện brigded traffic

 # thiết lập các tham số sysctl, luôn tồn tại dù khởi động lại 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 # Áp dụng các tham số sysctl mà không cần khởi động lại sudo sysctl --system
  • sysctl.d là thư mục hệ thống trong Linux, sử dụng để thiết lập các tham số cho kernel trong runtime. Nó chứa các tệp có đuôi .conf quy định các giá trị của biến sysctl, đó là các tham số của kernel có thể được sử dụng để tinh chỉnh hành vi của Linux kernel.

  • Trong môi trường containerized, thông thường cần phải bật (đặt giá trị 1) net.bridge.bridge-nf-call-iptables để traffic giữa các container có thể lọc bởi iptables firewall của máy chủ. Điều này rất quan trọng vì lý do bảo mật, nó cho phép máy chủ cung cấp các lớp bảo mật mạng cho ứng dụng containerized.

Để kiểm tra net.bridge.bridge-nf-call-iptables, net.bridge.bridge-nf-call-ip6tables, net.ipv4.ip_forward đã được bật trong thiết lập sysctl hay chưa, chạy lệnh:

 sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward

Cài đặt containerd

Gói containerd.io ở định dạng DEB và RPM được phân phối bởi Docker (không phải bởi dự án containerd). So sánh với các tệp nhị phân gốc của containerd, gói containerd.io cũng bao gồm runc, nhưng lại không có CNI plugins.

Container Network Interface (CNI) là giao diện tiêu chuẩn để cấu hình mạng cho các container trên Linux. Nó cho phép một loạt các tùy chọn kết nối mạng bao gồm overlay network, load balancing và các chính sách bảo mật sử dụng với ứng dụng containerized. Trong hướng dẫn này, chúng ta sẽ sử dụng CNI plugin với Pod network add-on sẽ được cài đặt ở bước sau trong mục .

Cập nhật apt package index và cài đặt packages cho phép apt sử dụng repository qua HTTPS:

 sudo apt-get update sudo apt-get install \ ca-certificates \ curl \ gnupg \ lsb-release

Thêm GPG key chính thức của Docker:

 sudo mkdir -m 0755 -p /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

Sử dụng lệnh sau để cài đặt repository:

 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

Cập nhật lại apt package index sau khi cài đặt repo:

 sudo apt-get update

Cài đặt phiên bản mới nhất của gói containerd.io

 sudo apt-get install containerd.io

Cgroup drivers

Trong Linux, các control group được sử dụng để giới hạn tài nguyên phân bổ cho các tiến trình.

Các kubeletcontainer runtime chạy dưới nó đều cần control groups để thực hiện việc quản lý tài nguyên cho các podcontainer như yêu cầu hay giới hạn về cpu/memory. Để giao tiếp với các control group, kubeletcontainer runtime cần sử dụng cgroup driver. Một điều cực kỳ quan trọng đó là kubeletcontainer runtime cần phải sử dụng cùng một loại cgroup driver với thiết lập giống nhau.

Có hai loại cgroup drivers hỗ trợ đó là:

  • cgroupfs
  • systemd

Bởi vì các máy ảo đã dựng của chúng ta sử dụng systemd, vậy nên ta sẽ thiết lập kubeletcontainerd dùng systemd làm cgroup driver.

Tùy thuộc vào bản phân phối và phiên bản của Linux, bạn sẽ thấy loại cgroup driver khác nhau. Để xem loại cgroup driver hiện tại trên Linux, bạn có thể kiểm tra giá trị của cgroup mount point bằng cách nhập lệnh: cat /proc/mounts | grep cgroup

Thiết lập cgroup driver cho containerd

Để thiết lập cho containerd dùng cgroup driversystemd, chạy:

 sudo vi /etc/containerd/config.toml

thay thế toàn bộ nội dung trong tệp config.toml với nội dung cài đặt sau:

 [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc] [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] SystemdCgroup = true

nhớ khởi động lại containerd để áp dụng thay đổi

 sudo systemctl restart containerd

Thiết lập cgroup driver cho kubelet

Trong phiên bản 1.22, nếu người dùng không cài đặt trường cgroupDriver trong KubeletConfiguration, kubeadm sẽ mặc định nó là systemd. Chúng ta không cần làm gì để thiết lập cgroup driver cho kubelet trong hướng dẫn này vì sẽ dùng kubeadm để khởi tạo cụm K8s trong các bước tiếp theo. Bạn có thể xem tại đây để biết thêm thông tin về cách thiết lập.

Cài đặt kubeadm, kubelet và kubectl trên tất cả các máy ảo

Thực hiện công việc ở bước này trên tất cả các máy ảo

Kubeadm là một command-line tool dùng để khởi tạo một Kubernetes cluster. Nó là một bản phân phối chính thức của Kubernetes và được thiết kế để đơn giản hóa quá trình thiết lập Kubernetes cluster. Kubeadm tự động hóa nhiều tác vụ liên quan đến thiết lập cluster chẳng hạn như cấu hình control plane components, tạo TLS certificates, và thiết lập Kubernetes networking.

Một trong những nội dung chính được đề cập trong kỳ thi Certified Kubernetes Administrator (CKA) là thiết lập cluster, bao gồm việc sử dụng các công cụ như kubeadm để khởi tạo một Kubernetes cluster mới.

Tắt swap space:

Bạn phải tắt tính năng swap để kubelet hoạt động bình thường. Xem thêm thảo luận về điều này trong issue: https://github.com/kubernetes/kubernetes/issues/53533

Kubelet, là node agent chính chạy trên worker node, giả sử mỗi node có một lượng bộ nhớ khả dụng cố định. Nếu node bắt đầu tiến hành swap, kubelet có thể bị delay hoặc các vấn đề khác ảnh hưởng đến tính stabilityreliability của Kubernetes cluster. Chính vì vậy, Kubernetes khuyên swap nên được disabled trên mỗi node trong cluster.

Để tắt swap trên máy Linux, sử dụng:

 # Đầu tiên là tắt swap sudo swapoff -a # Sau đó tắt swap mỗi khi khởi động trong /etc/fstab sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab

Cài đặt kubeadm, kubelet và kubectl :

  • kubelet: component chạy trên tất cả các máy trong cluster và thực hiện những việc như khởi động các podcontainer.

  • kubectl: command line tool dùng để nói chuyện với cluster.

  • kubeadm: công cụ cài đặt các component còn lại của kubernetes cluster.

kubeadm sẽ không cài đặt kubelet hay kubectl cho bạn, vì vậy hãy đảm bảo chúng sử dụng các phiên bản phù hợp với các component khác trong Kubernetes control planekubeadm cài cho bạn.

Cảnh báo: Hướng dẫn này sẽ loại bỏ các Kubernetes packages ra khỏi mọi tiến trình system upgrade. Do kubeadmKubernetes cần được đặc biệt chú ý mỗi khi upgrade.

Để biết thêm thông tin về việc các phiên bản lệch nhau được hỗ trợ hãy xem:

Cập nhật apt package index và cài các package cần thiết để sử dụng trong Kubernetes apt repository:
 sudo apt-get update sudo apt-get install -y apt-transport-https ca-certificates curl
Tải Google Cloud public signing key:
 sudo mkdir -m 0755 -p /etc/apt/keyrings sudo curl -fsSLo /etc/apt/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
Thêm Kubernetes apt repository:
 echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
Cập nhật lại apt package index, cài đặt phiên bản mới nhất của kubelet, kubeadmkubectl, ghim phiên bản hiện tại tránh việc tự động cập nhật:
 sudo apt-get update sudo apt-get install -y kubelet kubeadm kubectl sudo apt-mark hold kubelet kubeadm kubectl

kubelet sẽ tự động khởi động lại mỗi giây vì ở trạng thái crashloop, đợi kubeadm đưa ra yêu cầu cần thực hiện.

Ghi chú: 🔐 Client certificates được tạo bởi kubeadm sẽ bị hết hạn sau 1 year. Đọc thêm ở đây để biết thêm về cách tùy chỉnh và làm mới certificates.

Khởi động control plane và nodes

Khởi tạo control plane

control plane là nơi chạy các component bao gồm etcd (cơ sở dữ liệu của cluster) và API Server (nơi các câu lệnh kubectl giao tiếp).

Để tiến hành khởi tạo, chạy câu lệnh sau ở máy ảo mà chúng ta đặt tên là kubemaster:

 sudo kubeadm init --apiserver-advertise-address=192.168.56.2 --pod-network-cidr=10.244.0.0/16
  • --apiserver-advertise-address=192.168.56.2: Địa chỉ IP mà máy chủ API sẽ lắng nghe các câu lệnh. Trong hướng dẫn này sẽ là địa chỉa IP của máy ảo kubemaster.
  • --pod-network-cidr=10.244.0.0/16: control plane sẽ tự động phân bổ địa chỉ IP trong CIDR chỉ định cho các pod trên mọi node trong cụm cluster. Bạn sẽ cần phải chọn CIDR sao cho không trùng với bất kỳ dải mạng hiện có để tránh xung đột địa chỉ IP.

kubeadm init đầu tiên sẽ chạy một loại các bước kiểm tra để đảm bảo máy đã sẵn sàng chạy Kubernetes. Những bước kiểm tra này sẽ đưa ra các cảnh báo và thoát lệnh khi có lỗi. Kế tiếp kubeadm init tải xuống và cài đặt các thành phần của control plane. Việc này có thể sẽ mất vài phút, sau khi kết thúc bạn sẽ thấy thông báo:

 Your Kubernetes control-plane has initialized successfully! To start using your cluster, you need to run the following as a regular user: mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config You should now deploy a Pod network to the cluster. Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at: /docs/concepts/cluster-administration/addons/ You can now join any number of machines by running the following on each node as root: kubeadm join <control-plane-host>:<control-plane-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>

Lưu lại câu lệnh kubeadm join... khi init thành công để thêm các node vào cluster.

Để kubectl có thể dùng với non-root user, chạy những lệnh sau, chúng cũng được nhắc trong output khi kubeadm init thành công:

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

Mặt khác, nếu bạn là root user, có thể dùng lệnh sau:

 export KUBECONFIG=/etc/kubernetes/admin.conf

Cảnh báo: Kubeadm cấp certificate trong admin.conf để có Subject: O = system:masters, CN = kubernetes-admin. system:masters là một nhóm người dùng siêu cấp, bỏ qua lớp ủy quyền (như RBAC). Tuyệt đối không chia sẻ tệp admin.conf với bất kỳ ai, thay vào đó hãy cấp cho người dùng các quyền tùy chỉnh bằng cách tạo cho họ một tệp kubeconfig với lệnh kubeadm kubeconfig. Để biết thêm chi tiết hãy đọc Generating kubeconfig files for additional users.

Thêm các node vào cluster

Chạy câu lệnh trong phần output của kubeadm init trên tất cả các worker node - máy ảo:kubenode01, kubenode02 với sudo permission:

 sudo kubeadm join --token <token> <control-plane-host>:<control-plane-port> --discovery-token-ca-cert-hash sha256:<hash>

Nếu bạn không lưu lại lệnh kubeadm join, quay lại máy control-plane: kubemaster.

Lấy <token> bằng lệnh

 kubeadm token list

Output sẽ tương tự như sau:

 TOKEN TTL EXPIRES USAGES DESCRIPTION EXTRA GROUPS 8ewj1p.9r9hcjoqgajrj4gi 23h 2018-06-12T02:51:28Z authentication, The default bootstrap system: signing token generated by bootstrappers: 'kubeadm init'. kubeadm: default-node-token

Mặc định, <tokens> sẽ hết hạn sau 24 giờ. Nếu bạn thêm worker node khi <token> đã hết hạn, bạn có thể tạo <token> mới bằng cách chạy lệnh sau trên control-plane node:

 kubeadm token create

Output sẽ cho <token> mới tương tự như sau:

 5didvk.d09sbcov8ph2amjw

Lấy <hash> bằng lệnh

 openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | \ openssl dgst -sha256 -hex | sed 's/^.* //'

Output sẽ tương tự:

 8cb2de97839780a412b93877f8507ad6c94f73add17d5d7058e91741c9d5ec78

Lấy <control-plane-host>:<control-plane-port> bằng lệnh

 cat /$HOME/.kube/config | grep server

Sẽ được output tương tự:

 server: https://192.168.56.2:6443

<control-plane-host>:<control-plane-port> sẽ là 192.168.56.2:6443

Thêm worker node vào Kubernetes cluster thành công

Bạn sẽ nhận được thông báo thành công như sau trên các máy worker node:

 [preflight] Running pre-flight checks ... (log output of join workflow) ... Node join complete: * Certificate signing request sent to control-plane and response received. * Kubelet informed of new secure connection details. Run 'kubectl get nodes' on control-plane to see this machine join.

Sau vài giây, bạn sẽ thấy thông tin node này trong phần output của lệnh kubectl get nodes khi chạy trên control plane node.

Kiểm tra các component của Kubernetes cluster

Ở control-plane kubemaster và worker nodes kubenode01, kubenode02 chạy lệnh:

 sudo netstat -lntp

Tất cả các components với LISTEN ports tương ứng sẽ được hiển thị như dưới đây:

kubemaster

 Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 127.0.0.1:10248 0.0.0.0:* LISTEN 8013/kubelet tcp 0 0 127.0.0.1:10249 0.0.0.0:* LISTEN 8182/kube-proxy tcp 0 0 192.168.56.2:2379 0.0.0.0:* LISTEN 7811/etcd tcp 0 0 127.0.0.1:2379 0.0.0.0:* LISTEN 7811/etcd tcp 0 0 192.168.56.2:2380 0.0.0.0:* LISTEN 7811/etcd tcp 0 0 127.0.0.1:2381 0.0.0.0:* LISTEN 7811/etcd tcp 0 0 127.0.0.1:10257 0.0.0.0:* LISTEN 7791/kube-controlle tcp 0 0 127.0.0.1:10259 0.0.0.0:* LISTEN 7907/kube-scheduler tcp 0 0 127.0.0.1:34677 0.0.0.0:* LISTEN 2826/containerd tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN 817/systemd-resolve tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1380/sshd tcp6 0 0 :::10250 :::* LISTEN 8013/kubelet tcp6 0 0 :::6443 :::* LISTEN 7884/kube-apiserver tcp6 0 0 :::10256 :::* LISTEN 8182/kube-proxy tcp6 0 0 :::22 :::* LISTEN 1380/sshd

kube-apiserver hiển thị chỉ LISTEN tới IPv6 :::6443 nhưng thực chất API server đang lắng nghe qua địa chỉ IPv6 cho phép truy cập qua địa chỉ IPv4, còn gọi là IPv4-mapped IPv6 address. Đây là lý do tại sao có thể chạy lệnh kubeadm join trên worker nodes thành công với --apiserver-advertise-address tới địa chỉ IPv4. Ví dụ, địa chỉ IPv4 192.168.5.2 có thể biểu diễn bằng địa chỉ IPv6 ::ffff:192.168.5.2.

kubenode*

 Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 127.0.0.1:10248 0.0.0.0:* LISTEN 8987/kubelet tcp 0 0 127.0.0.1:10249 0.0.0.0:* LISTEN 9208/kube-proxy tcp 0 0 127.0.0.1:39989 0.0.0.0:* LISTEN 2785/containerd tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN 782/systemd-resolve tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1431/sshd tcp6 0 0 :::10250 :::* LISTEN 8987/kubelet tcp6 0 0 :::10256 :::* LISTEN 9208/kube-proxy tcp6 0 0 :::22 :::* LISTEN 1431/sshd

Cài đặt Pod network add-on

Chạy lệnh kubectl get nodes trên control plane để kiểm tra các node đã thêm vào cluster

 NAME STATUS ROLES AGE VERSION kubemaster NotReady control-plane 3h1m v1.26.2 kubenode01 NotReady <none> 3h v1.26.2 kubenode02 NotReady <none> 179m v1.26.2

Có thể thấy, các máy ảo kubemaster, kubenode01, kubenode02 đã được thêm vào Kubernetes cluster nhưng đang có STATUSNotReady.

Chạy lệnh kubectl get pods -A trên control plane để xem tất cả pod trong kube-system namespace

 NAMESPACE NAME READY STATUS RESTARTS AGE kube-system coredns-787d4945fb-5cwlq 0/1 Pending 0 3h8m kube-system coredns-787d4945fb-q2s4p 0/1 Pending 0 3h8m kube-system etcd-controlplane 1/1 Running 0 3h8m kube-system kube-apiserver-controlplane 1/1 Running 0 3h8m kube-system kube-controller-manager-controlplane 1/1 Running 0 3h8m kube-system kube-proxy-7twwr 1/1 Running 0 3h7m kube-system kube-proxy-8mxt7 1/1 Running 0 3h8m kube-system kube-proxy-v9rc6 1/1 Running 0 3h8m kube-system kube-scheduler-controlplane 1/1 Running 0 3h9m

Bạn phải triển khai Container Network Interface (CNI) hỗ trợ Pod network add-on để các Pod có thể giao tiếp với nhau. Cluster DNS (CoreDNS) sẽ không được khởi động cho đến khi hoàn thất thiết lập pod network.

Pod network add-onsKubernetes-specific CNI plugins cung cấp kết nối mạng giữa các pod trong một Kubernetes cluster. Nó tạo một mạng overlay ảo phủ toàn bộ cluster và gắn cho mỗi pod một địa chỉ IP riêng.

Trong khi CNI plugins có thể được sử dụng với mọi container runtime, pod network add-ons dành riêng cho Kubernetes và cung cấp chức năng mạng cần thiết cho mô hình mạng Kubernetes. Một số ví dụ về pod network add-ons có kể đến Calico, Flannel, and Weave Net. (Xem thêm các pod network add-ons khác tại đây)

Trong hướng dẫn này, chúng ta sẽ sử dụng Weave Net add-ons. Nó dễ dàng cài đặt, sử dụng và phù hợp với việc triển khai ở quy mô nhỏ.

Để cài đặt nó cho Kubernetes cluster, chạy lệnh dưới đây trên control plane kubemaster:

 kubectl apply -f https://github.com/weaveworks/weave/releases/download/v2.8.1/weave-daemonset-k8s.yaml

Output sẽ như sau

 serviceaccount/weave-net created clusterrole.rbac.authorization.k8s.io/weave-net created clusterrolebinding.rbac.authorization.k8s.io/weave-net created role.rbac.authorization.k8s.io/weave-net created rolebinding.rbac.authorization.k8s.io/weave-net created daemonset.apps/weave-net created

Cần đảm bảo rằng dải mạng của Pod không bị trùng lặp với mạng trên các máy trong cluster. Nếu bạn khai báo --pod-network-cidr khi chạy kubeadm init, phải thêm tham số IPALLOC_RANGE vào tệp YAML của Weave network plugin. Chạy lệnh sau trên control plane kubemaster:

 kubectl edit ds weave-net -n kube-system

Lệnh này sẽ cho phép bạn chỉnh sửa tệp YAML của weave-net daemon set. Tìm đến phần spec của container có tham số name: weave để thêm biến môi trường IPALLOC_RANGE và truyền tham số --pod-network-cidr khi chạy kubeadm init. (Tệp được mở trong trình chỉnh sửa vi)

 spec: ... template: ... spec: ... containers: ... env: - name: IPALLOC_RANGE value: 10.244.0.0/16 name: weave

Lưu tệp và đợi một vài phút để weave-net daemon set khởi động lại các pod.

Thiết lập thành công

Chạy lại lệnh kubectl get pods -A trên control plane để kiểm tra, bạn sẽ thấy 3 pods của weave-net daemon setcoredns pods hiển thị đang chạy. (STATUS: Running)

 NAMESPACE NAME READY STATUS RESTARTS AGE kube-system coredns-787d4945fb-48tbh 1/1 Running 0 6m57s kube-system coredns-787d4945fb-nrsp7 1/1 Running 0 6m57s kube-system etcd-kubemaster 1/1 Running 0 7m10s kube-system kube-apiserver-kubemaster 1/1 Running 0 7m12s kube-system kube-controller-manager-kubemaster 1/1 Running 0 7m10s kube-system kube-proxy-8sxss 1/1 Running 0 4m19s kube-system kube-proxy-j7z6x 1/1 Running 0 6m58s kube-system kube-proxy-nj8j2 1/1 Running 0 4m14s kube-system kube-scheduler-kubemaster 1/1 Running 0 7m10s kube-system weave-net-7mldz 2/2 Running 0 2m kube-system weave-net-dk5dl 2/2 Running 0 70s kube-system weave-net-znhnm 2/2 Running 0 2m

Chạy kubectl get nodes để kiểm tra trạng thái các node trong cluster, chúng sẽ đều ở trạng thái sẵn sàng. (STATUS: Ready)

 NAME STATUS ROLES AGE VERSION kubemaster Ready control-plane 9m54s v1.26.2 kubenode01 Ready <none> 6m59s v1.26.2 kubenode02 Ready <none> 6m54s v1.26.2

Nếu bạn thắc mắc tại sao ROLES của các worker node hiển thị <none>, điều đó có nghĩa là các node này đang không chạy các control plane component hay Kubernetes services chỉ định role. Thông thường worker nodes sẽ không chạy các control plane component, vì thế điều này hoàn toàn bình thường trong một Kubernetes cluster.

Networking là một phần trung tâm của Kubernetes, xem thêm Kubernetes networking model để biết thêm thông tin.

Nếu muốn tùy chỉnh cluster với kubeadm, bạn có thể đọc Create cluster kubeadm.

Clean up

Sẽ có lúc bạn gặp những lỗi không biết cách giải quyết hoặc đơn giản chỉ muốn bắt đầu lại từ đầu, phần này sẽ dành cho bạn!

Giữ lại các máy ảo, chỉ dọn dẹp Kubernetes cluster

Loại bỏ node

Chạy lệnh này để bỏ tất cả các pod đang chạy trên node theo đúng quy trình:

 kubectl drain <node name> --delete-emptydir-data --force --ignore-daemonsets

Reset các trạng thái được cài đặt bởi kubeadm

 kubeadm reset

Quá trình reset này sẽ không bao gồm việc reset hay dọn dẹp iptables rules hay IPVS tables. Nếu bạn muốn reset iptables, phải thực hiện thủ công như sau:

 iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X

Nếu muốn reset IPVS tables, bạn phải chạy lệnh dưới đây:

 ipvsadm -C

Bây giờ tiến hành loại bỏ node khỏi cluster:

 kubectl delete node <node name>

Nếu muốn thiết lập lại, run kubeadm init (thiết lập thành control-plane) hoặc kubeadm join (thiết lập thành worker node) với các đối số phù hợp.

Dọn dẹp control plane

Tiến hành quá trình đảo ngược lại tất cả các thay đổi kubeadm init đã thực hiện trên máy với lệnh:

 sudo kubeadm reset --kubeconfig="$HOME/.kube/config"

--kubeconfig=string: Xóa kubeconfig file được dùng để giao tiếp với cluster. Nếu không khai báo, một số thư mục sẽ được tìm để xóa kubeconfig file. (Nếu bạn thiết lập cho non-root user sau khi chạy kubeadm init, đừng quên xóa tệp thiết lập $HOME/.kube/config)

Tương tự như đã đề cập ở phần loại bỏ node, quá trình reset này sẽ không reset hay dọn dẹp iptables rules hay IPVS tables. Nếu muốn reset, bạn phải làm thủ công như khi loại bỏ node.

Xóa bỏ tất cả các máy ảo

Bởi vì sử dụng Vagrant để tự động hóa quá trình tạo các máy ảo, bạn có thể xóa bỏ tất cả chỉ với một câu lệnh. Chạy lệnh này ở thư mục đang sử dụng trên máy tính (Nơi cài đặt VagrantVirtual Box):

 vagrant destroy

Nếu bạn chỉ muốn tắt các máy ảo, thay vào đó hãy chạy lệnh vagrant halt. Khi đó, lúc vagrant up lại, tất cả công việc đã thực hiện trên máy ảo sẽ vẫn còn đó thay vì mất hết. Tìm hiểu thêm về lệnh này tại đây.

Bình luận

Bài viết tương tự

- vừa được xem lúc

Đề thi interview DevOps ở Châu Âu

Well. Chào mọi người, mình là Rice - một DevOps Engineers ở đâu đó tại Châu Âu.

0 0 88

- vừa được xem lúc

In calculus, love also means zero.

Mình nhớ hồi năm 2 đại học, thầy giáo môn calculus, trong một giây phút ngẫu hứng, đã đưa ra cái definition này. Lúc đấy mình cũng không nghĩ gì nhiều.

0 0 65

- vừa được xem lúc

Chuyện thay đổi

Thay đổi là một thứ gì đó luôn luôn đáng sợ. Cách đây vài tháng mình có duyên đi làm cho một banking solution tên là X.

0 0 47

- vừa được xem lúc

Pet vs Cattle - Thú cưng và gia súc

Khái niệm. Pets vs Cattle là một khái niệm cơ bản của DevOps. Bài viết này sẽ nói về sự phát triển của các mô hình dịch vụ từ cốt lõi Pets and Cattle. 1.

0 0 34

- vừa được xem lúc

Git workflow được Google và Facebook sử dụng có gì hay ho

Với developer thì Git hẳn là công cụ rất quen thuộc và không thể thiếu rồi. Thế nhưng có mấy ai thực sự hiểu được Git.

0 0 85

- vừa được xem lúc

Kubernetes - Học cách sử dụng Kubernetes Namespace cơ bản

Namespace trong Kubernetes là gì. Tại sao nên sử dụng namespace.

0 0 113