[K8s] Xây dựng Kubernetes cluster bằng công cụ kubeadm trên Virtual Box
GitHub repo: https://github.com/holdennguyen/kubernetes-install-cluster-with-kubeadm
🦖 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 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
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ủaboot 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ảishutdown
máy hoàn toàn (khôngsuspend
hayrestart
) để áp dụng thay đổi. Để PC tắt trong khoảng10 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ệnhshutdown /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
!
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 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 Sharing và Vagrantfile: 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ự ánKubernetes
ở bản1.24
. Đọc Dockershim Removal FAQ để biết thêm thông tin.
Dockershim
là một thành phẩn củaKubernetes
được sử dụng để giao tiếp vớiDocker runtime
. Nó được giới thiệu như một giải pháp tạm thời cho phépKubernetes
sử dụngDocker
như mộtcontainer runtime
trước khiKubernetes
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.
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-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áccontainer
trênLinux
. Nó cho phép một loạt các tùy chọn kết nối mạng bao gồmoverlay 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ụngCNI plugin
vớiPod 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
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 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 group
, kubelet
và container runtime
cần sử dụng cgroup driver
. Mộ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ạicgroup driver
hiện tại trên Linux, bạn có thể kiểm tra giá trị củacgroup 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
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ậpcluster
, bao gồm việc sử dụng các công cụ như kubeadm để khởi tạo mộtKubernetes 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 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
Cài đặt kubeadm, kubelet và kubectl :
-
kubelet
: component chạy trên tất cả các máy trongcluster
và thực hiện những việc như khởi động cácpod
vàcontainer
. -
kubectl
: command line tool dùng để nói chuyện vớicluster
. -
kubeadm
: công cụ cài đặt các component còn lại củakubernetes 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. Dokubeadm
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:
- Kubernetes version and version-skew policy
- Kubeadm-specific version skew policy
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
, 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ởikubeadm
sẽ bị hết hạn sau1 year
. Đọc thêm ở đây để biết thêm về cách tùy chỉnh và làm mớicertificates
.
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 ảokubemaster
.--pod-network-cidr=10.244.0.0/16
:control plane
sẽ tự động phân bổ địa chỉ IP trongCIDR
chỉ định cho cácpod
trên mọinode
trong cụmcluster
. Bạn sẽ cần phải chọnCIDR
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 trongadmin.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ệpadmin.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ệpkubeconfig
với lệnhkubeadm 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ớiIPv6 :::6443
nhưng thực chấtAPI 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ệnhkubeadm join
trênworker nodes
thành công với--apiserver-advertise-address
tới địa chỉIPv4
. Ví dụ, địa chỉ IPv4192.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ó 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 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 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)
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ácworker node
hiển thị<none>
, điều đó có nghĩa là cácnode
này đang không chạy cáccontrol plane component
hayKubernetes services
chỉ địnhrole
. Thông thườngworker nodes
sẽ không chạy cáccontrol plane component
, vì thế điều này hoàn toàn bình thường trong mộtKubernetes 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 Vagrant
và Virtual 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úcvagrant 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.
All rights reserved