Kubernetes install cluster

1 – Provision Virtual Box’s VM with 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 VirtualBoxVagrant 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. Dùng Git clone repo này hoặc đơn giản copy Vagrantfile này vào thư mục của bạn. (Tham khảo: kodekloudhub).

# -*- 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_NODENUM_WORKER_NODE
  • Địa chỉ IP: IP_NWMASTER_IP_STARTNODE_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.memoryvb.cpus

Cú pháp trong Vagrantfile là Ruby, 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:

vagrant up
#Output
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 Vagrant và Virtual 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!


1.2. 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>

Có thể thấy trong output khi chạy vagrant upVagrant 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 Sharing và Vagrantfile: config.ssh.

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

2 -Installing a container runtime (containerd) on all virtual machines

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 Kubernetes có container 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.


2.1 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 overlay và br_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-iptablesnet.bridge.bridge-nf-call-ip6tablesnet.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 networkload 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 Khởi tạo control plane và nodes.

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

2.2. 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 kubelet và container 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 pod và container như yêu cầu hay giới hạn về cpu/memory. Để giao tiếp với các control groupkubelet và container runtime cần sử dụng cgroup driverMột điều cực kỳ quan trọng đó là kubelet và container 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 kubelet và containerd 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 driver là systemd, 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:


2.3. 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 KubeletConfigurationkubeadm 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.

3. Installing kubeadm, kubelet, and kubectl on all virtual machines

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 clusterKubeadm 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.

3.1 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: kubernetes/kubernetes#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 swapkubelet có thể bị delay hoặc các vấn đề khác ảnh hưởng đến tính stability và reliability 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

3.2 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 pod và container.
  • 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 plane mà kubeadm 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 kubeadm và Kubernetes 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:

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, kubeadm và kubectl, 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.

4. Bootstrapping control plane and nodes

4.1 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/16control 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 clusterBạ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:mastersCN = kubernetes-adminsystem: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.

4.2 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:kubenode01kubenode02 với sudo permission:

export KUBECONFIG=/etc/kubernetes/admin.conf

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

Output sẽ 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.

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

Ở control-plane kubemaster và worker nodes kubenode01kubenode02 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

4.4 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

Active Internet connections (only servers)
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 kubemasterkubenode01kubenode02 đã được thêm vào Kubernetes cluster nhưng đang có STATUS là NotReady.

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-ons là Kubernetes-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 runtimepod 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 CalicoFlannel, 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

4.5.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 set và coredns 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)

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.

Viết một bình luận