Kubernetes 集群部署202507
本實驗主要軟件環境及資源如下:
- 二進制部署CentOS8.5+Kubernetes1.33.2+Docker28.3.1高可用集群
一、系統要求
?Kubermetes 系統由一組可執行程序組成,用戶可以通過Kubernetes在GitHub 的項目網站下載編譯好的二進制文件或鏡像文件,或者下載源碼并自行將其編譯為二進制文件。安裝 Kubernetes對系統軟件和硬件的要求如表 所示。
軟硬件 | 最低配置 | 推薦配置 |
---|---|---|
主機資源 | 若在集群中有1~5個Node,則要求如下: - Master:至少2 core CPU和 2GB 內存。 - Node:至少1core CPU 和內存。 在增加集群規模時,應相應地增加主機配置。在大規模集群的硬件配置方面可以參考 Kuberetes 官網給出的建議 | Master:4 core CPU和 16GB 內存。 Node:根據要運行的容器數量進行配置 |
Linux | 各種 Linux 發行版,包括RedHatLinux、CentOS、Fedora、Ubuntu.Debian 等,Kermel版本要求在 v3.10 及以上 | CentOS 7.9 |
etcd | 版本為 v3 及以上 可以參考 etcd 官網的說明下載和安裝 etcd | etcd v3 |
容器運行時 | Kubemmetes支持的容器運行時包括contaimerd、CRI-O等。 | contaimerd v1.7 |
? Kubernetes需要容器運行時的支持。目前Kubernetes 官方支持的容器運行時包括containerd、CRI-O等,推薦采用 containerd v1.7 版本。
? 對于宿主機操作系統,以CentOs7為例,使用Systemd 系統完成Kubermetes服務配置。對于其他 Linux發行版本的服務配置,可以參考相關系統管理手冊。為了便于管理常常將 Kubernetes 服務程序配置為 Linux開機自啟動。
? 需要注意的是,CentOS7默認啟動了防火墻服務(firewalld.service),而Kubernetes的 Master 與各個 Node 之間會有大量的網絡通信,安全的做法是在防火墻上配置各組件相互通信的端口號,需要配置的端口號如表所示。
組件 | 默認端口號 |
---|---|
API Server | 6443 |
Controller Manager | 10257 |
Scheduler | 10259 |
kubelet | 10250、10255(只讀端口號) |
etcd | 2379(供客戶端訪問)、2380(供etcd集群內節點之間訪問) |
集群的DNS服務 | 53(UDP)、53(TCP) |
? 對于其他組件,可能還需要開通某些端口號。例如,對于CNI網絡插件calico,需要開通 179 端口號;對于鏡像庫,需要開通鏡像庫的端口號等,這需要根據系統的要求在防火墻服務上逐個配置網絡策略。
? 在安全的網絡環境下,可以關閉防火墻服務:
# systemctl disable firewalld
# systemctl stop firewalld
? 另外,建議在主機上禁用 SELinux(可以修改操作系統的/etc/sysconfig/selinux文件將SELINUX =enforcing
修改為SELINUX=disabled
),這樣容器就可以讀取主機的文件系統了。隨著Kubernetes對SELinux支持的增強,可以逐步啟用SELinux,并通過Kubernetes 設置容器的安全機制。
二、準備工作
2.1 主機列表
1.2.1 虛擬機安裝及主機設置
- 主機名與hosts本地解析
## 查看系統版本及內核版本
[root@k8s31 ~]# cat /etc/redhat-release
CentOS Linux release 8.5.2111
[root@k8s31 ~]# uname -r
4.18.0-348.7.1.el8_5.x86_64
Hostname | Host IP | Docker IP | Role |
---|---|---|---|
k8s31.vm.com | 192.168.26.31 | 10.26.31.1/24 | master&worker、etcd、docker |
k8s32.vm.com | 192.168.26.32 | 10.26.32.1/24 | master&worker、etcd、docker |
k8s33.vm.com | 192.168.26.33 | 10.26.33.1/24 | master&worker、etcd、docker |
~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.26.31 k8s31.vm.com k8s31
192.168.26.32 k8s32.vm.com k8s32
192.168.26.33 k8s33.vm.com k8s33
- 關閉防火墻【基礎安裝】
~]# systemctl disable --now firewalldRemoved symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.~]# firewall-cmd --statenot running
- 關閉SELINUX【基礎安裝】
~]# sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config~]# reboot~]# sestatusSELinux status: disabled
修改SELinux配置需要重啟操作系統。
- 關閉交換分區【基礎安裝】
~]# sed -ri 's/.*swap.*/#&/' /etc/fstab~]# swapoff -a && sysctl -w vm.swappiness=0~]# cat /etc/fstab...#UUID=3452c4c0-d890-4d66-bf19-3b09b0ba2afa none swap defaults 0 0...~]# free -mtotal used free shared buff/cache available
Mem: 3709 270 3072 16 366 3207
Swap: 0 0 0
- 配置ulimit
~]# ulimit -SHn 65535~]# cat << EOF >> /etc/security/limits.conf
* soft nofile 655360
* hard nofile 131072
* soft nproc 655350
* hard nproc 655350
* soft memlock unlimited
* hard memlock unlimited
EOF
1.2.2 ipvs管理工具安裝及模塊加載【基礎安裝】
~]# yum install ipvsadm ipset sysstat conntrack libseccomp -y...
~]# cat >> /etc/modules-load.d/ipvs.conf <<EOF
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
ip_tables
ip_set
xt_set
ipt_set
ipt_rpfilter
ipt_REJECT
ipip
EOF~]# systemctl restart systemd-modules-load.service~]# lsmod | grep -e ip_vs -e nf_conntrack
ip_vs_sh 16384 0
ip_vs_wrr 16384 0
ip_vs_rr 16384 0
ip_vs 172032 6 ip_vs_rr,ip_vs_sh,ip_vs_wrr
nf_conntrack 172032 4 xt_conntrack,nf_nat,ipt_MASQUERADE,ip_vs
nf_defrag_ipv6 20480 2 nf_conntrack,ip_vs
nf_defrag_ipv4 16384 1 nf_conntrack
libcrc32c 16384 5 nf_conntrack,nf_nat,nf_tables,xfs,ip_vs
1.2.3 加載containerd相關內核模塊【基礎安裝】
臨時加載模塊~]# modprobe overlay~]# modprobe br_netfilter永久性加載模塊~]# cat > /etc/modules-load.d/containerd.conf << EOF
overlay
br_netfilter
EOF設置為開機啟動~]# systemctl restart systemd-modules-load.service ##systemctl enable --now systemd-modules-load.service
1.2.4 開啟內核路由轉發及網橋過濾【基礎安裝】
~]# cat <<EOF > /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
fs.may_detach_mounts = 1
vm.overcommit_memory=1
vm.panic_on_oom=0
fs.inotify.max_user_watches=89100
fs.file-max=52706963
fs.nr_open=52706963
net.netfilter.nf_conntrack_max=2310720net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_intvl =15
net.ipv4.tcp_max_tw_buckets = 36000
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_max_orphans = 327680
net.ipv4.tcp_orphan_retries = 3
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.ip_conntrack_max = 131072
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.tcp_timestamps = 0
net.core.somaxconn = 16384
EOF
~]# sysctl --system
## 所有節點配置完內核后,重啟服務器,保證重啟后內核依舊加載
~]# reboot -h now## 重啟后查看ipvs模塊加載情況:
~]# lsmod | grep --color=auto -e ip_vs -e nf_conntrack
ip_vs_sh 16384 0
ip_vs_wrr 16384 0
ip_vs_rr 16384 0
ip_vs 172032 6 ip_vs_rr,ip_vs_sh,ip_vs_wrr
nf_conntrack 172032 4 xt_conntrack,nf_nat,ipt_MASQUERADE,ip_vs
nf_defrag_ipv6 20480 2 nf_conntrack,ip_vs
nf_defrag_ipv4 16384 1 nf_conntrack
libcrc32c 16384 5 nf_conntrack,nf_nat,nf_tables,xfs,ip_vs## 重啟后查看containerd相關模塊加載情況:
~]# lsmod | egrep 'br_netfilter | overlay'
br_netfilter 24576 0
1.2.5 主機時間同步
略
1.2.6 創建軟件部署目錄
- /opt/app 存放部署資源文件
- /opt/cfg 存放配置文件
- /opt/cert 存放證書
- /opt/bin 鏈接/opt/app下的源文件,去除文件名中的版本號,方便升級時只需要更改鏈接即可。
~]# mkdir -p /opt/{app,cfg,cert,bin}
- 將下載的軟件及資源上傳到主機k8s31(192.168.26.31):/opt/app
2.2 軟件列表
2.2.1 二進制軟件
Linux ISO鏡像:CentOS-8.3.2011-x86_64-minimal.iso (https://vault.centos.org/8.3.2011/isos/x86_64/CentOS-8.3.2011-x86_64-minimal.iso)
華為開源鏡像:https://mirrors.huaweicloud.com/home
清華開源鏡像:https://mirrors.tuna.tsinghua.edu.cn/
阿里開源鏡像:https://mirrors.aliyun.com
下載:https://mirrors.aliyun.com/centos-vault/8.3.2011/isos/x86_64/CentOS-8.3.2011-x86_64-minimal.iso
docker 28.3.1 (2025-07-02 23:03:23 78.1 MiB)
https://download.docker.com/linux/static/stable/x86_64/
下載:https://download.docker.com/linux/static/stable/x86_64/docker-rootless-extras-28.3.1.tgz
cri-dockerd 0.3.18
https://github.com/Mirantis/cri-dockerd
下載:https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.18/cri-dockerd-0.3.18.amd64.tgz
kubernetes v1.33.2
https://github.com/kubernetes/kubernetes/releases
下載:https://dl.k8s.io/v1.33.2/kubernetes-server-linux-amd64.tar.gz
etcd v3.6.0
https://github.com/etcd-io/etcd/
下載:https://github.com/etcd-io/etcd/releases/download/v3.6.0/etcd-v3.6.0-linux-amd64.tar.gz
2.2.2 資源清單與鏡像
類型 | 名稱 | 下載鏈接 | 說明 |
---|---|---|---|
yaml資源 | coredns.yaml.base | https://github.com/kubernetes/kubernetes/blob/v1.33.2/cluster/addons/dns/coredns/coredns.yaml.base | kubectl部署 |
yaml資源 | components.yaml(metrics server) | https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.7.2/components.yaml | kubectl部署 |
鏡像 | metrics-server:v0.7.2 | registry.aliyuncs.com/google_containers/metrics-server:v0.7.2 | 部署pod… |
鏡像 | coredns:v1.12.0 | registry.aliyuncs.com/google_containers/coredns:v1.12.0 | 部署pod… |
鏡像 | pause:3.10 | registry.aliyuncs.com/google_containers/pause:3.10 | 部署pod… |
2.3 網絡規劃
網絡名稱 | 網段 | 備注 |
---|---|---|
Node網絡 | 192.168.26.0/24 | Node IP,Node節點的IP地址,即物理機(宿主機)的網卡地址。 |
Service網絡 | 168.26.0.0/16 | Cluster IP,也可叫Service IP,Service的IP地址。service-cluster-ip-range定義Service IP地址范圍的參數。 |
Pod網絡 | 10.26.0.0/16 | Pod IP,Pod的IP地址,容器(docker0)網橋分配的地址。cluster-cidr定義Pod網絡CIDR地址范圍的參數。 |
配置:
apiserver:--service-cluster-ip-range 168.26.0.0/16 ##Service網絡 168.26.0.0/16controller:--cluster-cidr 10.26.0.0/16 ##Pod網絡 10.26.0.0/16--service-cluster-ip-range 168.26.0.0/16 ##service網絡 168.26.0.0/16kubelet:--cluster-dns 168.26.0.100 ## 解析Service,168.26.0.100proxy:--cluster-cidr 10.26.0.0/16 ##Pod網絡 10.26.0.0/16
2.4 集群總體架構
三、容器運行時
3.1 安裝docker
3.1.1 解壓、分發、創建軟連接
## k8s31:
~]# cd /opt/app/
app]# tar zxvf docker-28.3.1.tgz
app]# ls docker
containerd containerd-shim-runc-v2 ctr docker dockerd docker-init docker-proxy runc
app]# mv docker /opt/bin/docker-28.3.1
app]# ls /opt/bin/docker-28.3.1
containerd containerd-shim-runc-v2 ctr docker dockerd docker-init docker-proxy runc
## 復制到k8s32、k8s33
app]# scp -r /opt/bin/docker-28.3.1/ root@k8s32:/opt/bin/.
app]# scp -r /opt/bin/docker-28.3.1/ root@k8s33:/opt/bin/.
## 在k8s31、k8s32、k8s33創建軟連接:
ln -s /opt/bin/docker-28.3.1/containerd /usr/bin/containerd
ln -s /opt/bin/docker-28.3.1/containerd-shim-runc-v2 /usr/bin/containerd-shim-runc-v2
ln -s /opt/bin/docker-28.3.1/ctr /usr/bin/ctr
ln -s /opt/bin/docker-28.3.1/docker /usr/bin/docker
ln -s /opt/bin/docker-28.3.1/dockerd /usr/bin/dockerd
ln -s /opt/bin/docker-28.3.1/docker-init /usr/bin/docker-init
ln -s /opt/bin/docker-28.3.1/docker-proxy /usr/bin/docker-proxy
ln -s /opt/bin/docker-28.3.1/runc /usr/bin/runc
## 如果軟連接存在,則刪除
rm -rf /usr/bin/containerd
rm -rf /usr/bin/containerd-shim-runc-v2
rm -rf /usr/bin/ctr
rm -rf /usr/bin/docker
rm -rf /usr/bin/dockerd
rm -rf /usr/bin/docker-init
rm -rf /usr/bin/docker-proxy
rm -rf /usr/bin/runc
~]# docker -v
Docker version 27.5.1, build 9f9e405
3.1.2 創建目錄、配置文件
- 在3臺主機上:使用calico網絡,去掉bip配置
## k8s31:
~]# mkdir -p /data/docker /etc/docker
~]# cat /etc/docker/daemon.json
{"data-root": "/data/docker","storage-driver": "overlay2","insecure-registries": ["harbor.oss.com:32402"],"registry-mirrors": ["https://5gce61mx.mirror.aliyuncs.com"],// "bip": "10.26.31.1/24","exec-opts": ["native.cgroupdriver=systemd"],"live-restore": true
}## k8s32:
~]# mkdir -p /data/docker /etc/docker
~]# cat /etc/docker/daemon.json
{"data-root": "/data/docker","storage-driver": "overlay2","insecure-registries": ["harbor.oss.com:32402"],"registry-mirrors": ["https://5gce61mx.mirror.aliyuncs.com"],// "bip": "10.26.32.1/24","exec-opts": ["native.cgroupdriver=systemd"],"live-restore": true
}## k8s33:
~]# mkdir -p /data/docker /etc/docker
~]# cat /etc/docker/daemon.json
{"data-root": "/data/docker","storage-driver": "overlay2","insecure-registries": ["harbor.oss.com:32402"],"registry-mirrors": ["https://5gce61mx.mirror.aliyuncs.com"],// "bip": "10.26.33.1/24","exec-opts": ["native.cgroupdriver=systemd"],"live-restore": true
}
3.1.3 創建啟動文件
]# cat /usr/lib/systemd/system/docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
3.1.4 啟動、檢查
~]# systemctl daemon-reload
~]# systemctl start docker; systemctl enable docker
~]# systemctl status docker
Client:Version: 28.3.1Context: defaultDebug Mode: falseServer:Containers: 2Running: 0Paused: 0Stopped: 2Images: 6Server Version: 28.3.1Storage Driver: overlay2Backing Filesystem: xfsSupports d_type: trueUsing metacopy: falseNative Overlay Diff: trueuserxattr: falseLogging Driver: json-fileCgroup Driver: systemdCgroup Version: 1Plugins:Volume: localNetwork: bridge host ipvlan macvlan null overlayLog: awslogs fluentd gcplogs gelf journald json-file local splunk syslogCDI spec directories:/etc/cdi/var/run/cdiSwarm: inactiveRuntimes: io.containerd.runc.v2 runcDefault Runtime: runcInit Binary: docker-initcontainerd version: 05044ec0a9a75232cad458027ca83437aae3f4darunc version: v1.2.6-0-ge89a299init version: de40ad0Security Options:seccompProfile: builtinKernel Version: 4.18.0-348.7.1.el8_5.x86_64Operating System: CentOS Linux 8OSType: linuxArchitecture: x86_64CPUs: 2Total Memory: 3.623GiBName: k8s31.vm.comID: 9006d33f-8784-4665-8414-5b936192182aDocker Root Dir: /data/dockerDebug Mode: falseExperimental: falseInsecure Registries:harbor.oss.com:32402::1/128127.0.0.0/8Registry Mirrors:https://5gce61mx.mirror.aliyuncs.com/Live Restore Enabled: trueProduct License: Community Engine
app]# docker version
Client:Version: 28.3.1API version: 1.51Go version: go1.24.4Git commit: 38b7060Built: Wed Jul 2 20:55:19 2025OS/Arch: linux/amd64Context: defaultServer: Docker Engine - CommunityEngine:Version: 28.3.1API version: 1.51 (minimum version 1.24)Go version: go1.24.4Git commit: 5beb93dBuilt: Wed Jul 2 20:56:35 2025OS/Arch: linux/amd64Experimental: falsecontainerd:Version: v1.7.27GitCommit: 05044ec0a9a75232cad458027ca83437aae3f4darunc:Version: 1.2.6GitCommit: v1.2.6-0-ge89a299docker-init:Version: 0.19.0GitCommit: de40ad0
app]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope hostvalid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000link/ether 00:0c:29:4e:b1:79 brd ff:ff:ff:ff:ff:ffinet 192.168.26.31/24 brd 192.168.26.255 scope global noprefixroute ens160valid_lft forever preferred_lft foreverinet6 fe80::20c:29ff:fe4e:b179/64 scope linkvalid_lft forever preferred_lft forever
3: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000link/ipip 0.0.0.0 brd 0.0.0.0
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group defaultlink/ether 02:42:44:b4:a6:2a brd ff:ff:ff:ff:ff:ffinet 10.26.31.1/24 brd 10.26.31.255 scope global docker0valid_lft forever preferred_lft forever
3.1.5 測試
拉取centos鏡像,啟動容器,查看容器IP
~]# docker pull centos:8
...
~]# docker images
...
~]# docker run -i -t --name node31 centos:8 /bin/bash
[root@8f14e1f187d8 /]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope hostvalid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000link/ipip 0.0.0.0 brd 0.0.0.0
3: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group defaultlink/ether 22:fb:86:5a:54:8e brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 10.26.31.2/24 brd 10.26.31.255 scope global eth0valid_lft forever preferred_lft forever
[root@8f14e1f187d8 /]# exit
3.2 安裝cri-dockerd
為什么要安裝cri-dockerd插件?
-
K8s在剛開源時沒有自己的容器引擎,而當時docker非常火爆是容器的代表,所以就在kubelet的代碼里集成了對接docker的代碼(docker shim),所以1.24版本之前是默認使用docker,不需要安裝cri-dockerd。
-
K8s1.24版本移除 docker-shim的代碼,而Docker Engine默認又不支持CRI標準,因此二者默認無法再直接集成。為此,Mirantis和Docker為了Docker Engine提供一個能夠支持到CRI規范的橋梁,就聯合創建了cri-dockerd,從而能夠讓Docker作為K8s容器引擎。
-
截至2025年6月,k8s已經更新至v1.32.5版。從v1.24起,Docker不能直接作為k8s的容器運行時,因為在k8s v1.24版本移除了docker shim的組件,這是由k8s團隊直接維護而非Docker團隊維護的組件,這意味著Docker和k8s的關系不再像原來那般親密,開發者需要使用其它符合CRI(容器運行時接口)的容器運行時工具(如containerd、CRI-O等),當然這并不意味著新版本的k8s徹底拋棄Docker(由于Docker龐大的生態和廣泛的群眾基礎,顯然這并不容易辦到),在原本安裝了Docker的基礎上,可以通過補充安裝cri-dockerd,以滿足容器運行時接口的條件,從某種程度上說,cri-dockerd就是翻版的dockershim。
3.2.1 解壓、分發、創建軟鏈接
k8s31 app]# tar -zxvf cri-dockerd-0.3.18.amd64.tgz
k8s31 app]# mv cri-dockerd /opt/bin/cri-dockerd-0.3.18
k8s31 app]# ll /opt/bin/cri-dockerd-0.3.18
總用量 49740
-rwxr-xr-x 1 1001 118 50929816 6月 10 05:48 cri-dockerd
## 復制:
k8s31 app]# scp -r /opt/bin/cri-dockerd-0.3.18 root@k8s32:/opt/bin/.
k8s31 app]# scp -r /opt/bin/cri-dockerd-0.3.18 root@k8s33:/opt/bin/.
## 創建軟鏈接:同上
ln -s /opt/bin/cri-dockerd-0.3.18/cri-dockerd /usr/local/bin/cri-dockerd
~]# cri-dockerd --version
cri-dockerd 0.3.18 (5709af9)
3.2.2 修改配置文件、啟動
]# cat /usr/lib/systemd/system/cri-dockerd.service
[Unit]
Description=CRI Interface for Docker Application Container Engine
Documentation=https://docs.mirantis.com
After=network-online.target firewalld.service docker.service
Wants=network-online.target
# Requires=cri-docker.socket ## 如果啟動報錯,則注釋掉這一行[Service]
Type=notify
ExecStart=/usr/local/bin/cri-dockerd --network-plugin=cni --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.10
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always# Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229.
# Both the old, and new location are accepted by systemd 229 and up, so using the old location
# to make them work for either version of systemd.
StartLimitBurst=3# Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230.
# Both the old, and new name are accepted by systemd 230 and up, so using the old name to make
# this option work for either version of systemd.
StartLimitInterval=60s# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity# Comment TasksMax if your systemd version does not support it.
# Only systemd 226 and above support this option.
TasksMax=infinity
Delegate=yes
KillMode=process[Install]
WantedBy=multi-user.target
]# systemctl daemon-reload
]# systemctl enable cri-dockerd && systemctl start cri-dockerd]# systemctl status cri-dockerd
● cri-dockerd.service - CRI Interface for Docker Application Container EngineLoaded: loaded (/usr/lib/systemd/system/cri-dockerd.service; enabled; vendor preset: disabled)Active: active (running) since Tue 2025-07-08 02:03:30 EDT; 15s agoDocs: https://docs.mirantis.comMain PID: 2370 (cri-dockerd)Tasks: 7Memory: 9.3MCGroup: /system.slice/cri-dockerd.service└─2370 /usr/local/bin/cri-dockerd --network-plugin=cni --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3>...
四、通過二進制文件安裝Kubernetes集群
? 通過 kubeadm 可以快速安裝 Kubernetes 集群,但如果需要調整 Kubernetes 各組件服務的參數,以及安全設置、高可用模式等,就需要通過二進制文件安裝 Kubemmetes 集群了。
? 基于 Kubernetes v1.33.2 版本,通過二進制文件對如何配置、部署啟用安全機制且有3個節點的高可用Kubernetes集群。可以適當簡化測試環境,將某些組件部署為單節點模式。
4.1 Master的高可用部署架構
? 在Kubermetes系統中,Master通過不間斷地與各個Node通信來維護整個集群的健康工作狀態,集群中各資源對象的狀態則被保存在etcd中。如果Master不能正常工作,則各個Node會處于不可管理狀態,用戶無法管理在各個Node上運行的Pod。
? 所以,在正式環境下應確保 Master 高可用,并啟用安全訪問機制,其中要至少注意以下幾方面:
-
Master的 kube-apiserver、kube-controller-manager和kube-scheduler服務以多實例方式部署,至少有3個節點,節點需要為奇數數量,通常建議為5個或7個。
-
Master啟用了基于CA認證的HTTPS安全機制。
-
etcd至少以有3個節點的集群模式部署。
-
etcd集群啟用了基于CA認證的HTTPS安全機制。
-
Master啟用了RBAC授權模式。
? 在 Master 的3個節點之前,應通過一個負載均衡器提供對客戶端的唯一訪問人口地址。對于負載均衡器,可以選擇使用硬件負載均衡器或者軟件負載均衡器進行搭建。如果選擇使用軟件負載均衡器,則可選擇的開源方案較多,本方案以HAProxy搭配keepalived為例進行說明。主流硬件負載均衡器有 F5、A10等,需要額外采購,其負載均衡配置規則與軟件負載均衡器的配置規則類似,不再贅述。
本方案中3臺主機的IP地址分別為192.168.26.31、192.168.26.32、192.168.26.33,負載均衡器使用的虛擬IP(VirtualIP,VIP)地址為 192.168.26.100。
下面對 etcd、負載均衡器、Master、Node 等組件進行高可用部署、關鍵配置、CA 證書配置等。
4.2 創建CA根證書
? 為了啟用etcd和Kubernetes服務基于CA認證的安全機制,首先需要配置CA證書。如果可以通過某個可信任的CA中心獲取證書,則可以使用其頒發的CA證書來完成系統配置。如果沒有可信任的 CA中心,則也可以通過自行制作CA證書來完成系統配置。
? etcd和Kubernetes在制作CA證書時,均需要基于CA根證書。以Kubermetes和etcd使用同一套CA根證書為例,對如何制作CA證書進行說明。可以使用OpenSSL、easyrsa、CFSSL等工具來制作CA證書,以 OpenSSL為例進行說明。
? 創建 CA 根證書的命令如下,其中包括私鑰文件 ca.key 和證書文件 ca.crt:
cert]# openssl genrsa -out ca.key 2048cert]# openssl req -x509 -new -nodes -key ca.key -subj "/CN=192.168.26.31" -days 36500 -out ca.crt
? 主要參數如下:
-
-subi:“/CN”的值為CA機構名稱,格式可以是域名或者 IP 地址。
-
-days:設置證書的有效期。
將生成的 ca.key 和 ca.crt文件保存在/opt/cert/pki 目錄下。
4.3 部署安全的 etcd 高可用集群
1. 下載 etcd 二進制文件,解壓,鏈接,配置 systemd 服務
將 etcd 二進制文件解壓縮后可以得到 etcd 和 etcdctl 文件,首先將它們鏈接到/usr/bin目錄下:
## k8s31:
~]# cd /opt/app/
app]# tar zxvf etcd-v3.6.0-linux-amd64.tar.gz
app]# ls etcd-v3.6.0-linux-amd64
Documentation etcd etcdctl etcdutl README-etcdctl.md README-etcdutl.md README.md READMEv2-etcdctl.md
app]# mv etcd-v3.6.0-linux-amd64 /opt/bin/etcd-v3.6.0
app]# ls /opt/bin/etcd-v3.6.0
Documentation etcd etcdctl etcdutl README-etcdctl.md README-etcdutl.md README.md READMEv2-etcdctl.md
## 復制:
k8s31 app]# scp -r /opt/bin/etcd-v3.6.0 root@k8s32:/opt/bin/.
k8s31 app]# scp -r /opt/bin/etcd-v3.6.0 root@k8s33:/opt/bin/.
## 創建軟鏈接:同上
ln -s /opt/bin/etcd-v3.6.0/etcd /usr/bin/etcd
ln -s /opt/bin/etcd-v3.6.0/etcdctl /usr/bin/etcdctl
app]# etcd --version
etcd Version: 3.6.0
Git SHA: f5d605a
Go Version: go1.23.9
Go OS/Arch: linux/amd64
然后將其部署為一個 systemd 服務,創建 systemd 服務的配置文件/usr/ib/systemdsystemVetcd.service:
## /usr/lib/systemd/system/etcd.service
[Unit]
Description=etcd key-value store
Documentation=https://github.com/etcd-io/etcd
After=network.target[Service]
EnvironmentFile=/opt/cfg/etcd.conf
ExecStart=/usr/bin/etcd
Restart=always[Install]
WantedBy=multi-user.target
其中,EnvironmentFile指定配置文件的全路徑,例如/opt/cfg/etcd.conf,以環境變量的格式配置其中的參數。
接下來配置 etcd需要的 CA 證書。對于配置文件/opt/cfg/etcd.conf中的完整配置參數將在創建完 CA 證書后統一配置。
2. 創建 etcd 的 CA 證書
首先創建一個x509 v3配置文件etcd_ssl.cnf,其中的subjectAltName參數(alt_names)包括所有etcd主機的 IP地址。
# /opt/cert/etcd_ssl.cnf
[ req ]
req_extensions = v3_req
distinguished_name = req_distinguished_name[ req_distinguished_name ][ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names[ alt_names ]
IP.1 = 192.168.26.31
IP.2 = 192.168.26.32
IP.3 = 192.168.26.33
然后通過openssl命令創建etcd的服務端CA證書,包括 etcd server.key 和etcd server.crt 文件,將其保存到/opt/cert目錄下:
openssl genrsa -out etcd_server.key 2048openssl req -new -key etcd_server.key -config etcd_ssl.cnf -subj "/CN=etcd-server" -out etcd_server.csropenssl x509 -req -in etcd_server.csr -CA /opt/cert/ca.crt -CAkey /opt/cert/ca.key -CAcreateserial -days 36500 -extensions v3_req -extfile etcd_ssl.cnf -out etcd_server.crt
最后創建客戶端使用的CA證書,包括etcd_client.key和 etcd_client.crt文件,也將其保存到/opt/cert目錄下,后續供 kube-apiserver 連接 etcd 時使用:
openssl genrsa -out etcd_client.key 2048openssl req -new -key etcd_client.key -config etcd_ssl.cnf -subj "/CN=etcd-client" -out etcd_client.csropenssl x509 -req -in etcd_client.csr -CA /opt/cert/ca.crt -CAkey /opt/cert/ca.key -CAcreateserial -days 36500 -extensions v3_req -extfile etcd_ssl.cnf -out etcd_client.crt
cert]# ls -l
總用量 40
-rw-r--r-- 1 root root 1127 6月 1 06:08 ca.crt
-rw------- 1 root root 1675 6月 1 06:07 ca.key
-rw-r--r-- 1 root root 41 6月 1 06:33 ca.srl
-rw-r--r-- 1 root root 1086 6月 1 06:33 etcd_client.crt
-rw-r--r-- 1 root root 989 6月 1 06:32 etcd_client.csr
-rw------- 1 root root 1675 6月 1 06:32 etcd_client.key
-rw-r--r-- 1 root root 1086 6月 1 06:31 etcd_server.crt
-rw-r--r-- 1 root root 989 6月 1 06:28 etcd_server.csr
-rw------- 1 root root 1679 6月 1 06:27 etcd_server.key
-rw-r--r-- 1 root root 311 6月 1 06:26 etcd_ssl.cnf
## 復制:
k8s31 app]# scp -r /opt/cert/* root@k8s32:/opt/cert/.
k8s31 app]# scp -r /opt/cert/* root@k8s33:/opt/cert/.
3. 對 etcd 參數的配置說明
接下來配置3個etcd節點。etcd節點的配置方式包括啟動參數、環境變量、配置文件等,通過環境變量方式將其配置到/opt/cfg/etcd.conf文件中,供systemd服務讀取。
3個etcd節點將被部署在192.168.26.31、192.168.26.32和192.168.26.33這3臺主機上,配置文件/opt/cfg/etcd.conf的內容:
]# mkdir -p /opt/etcd/data
## /opt/cfg/etcd.conf - node 1
ETCD_NAME=etcd1
ETCD_DATA_DIR=/opt/etcd/dataETCD_CERT_FILE=/opt/cert/etcd_server.crt
ETCD_KEY_FILE=/opt/cert/etcd_server.key
ETCD_TRUSTED_CA_FILE=/opt/cert/ca.crt
ETCD_CLIENT_CERT_AUTH=true
ETCD_LISTEN_CLIENT_URLS=https://192.168.26.31:2379
ETCD_ADVERTISE_CLIENT_URLS=https://192.168.26.31:2379ETCD_PEER_CERT_FILE=/opt/cert/etcd_server.crt
ETCD_PEER_KEY_FILE=/opt/cert/etcd_server.key
ETCD_PEER_TRUSTED_CA_FILE=/opt/cert/ca.crt
ETCD_LISTEN_PEER_URLS=https://192.168.26.31:2380
ETCD_INITIAL_ADVERTISE_PEER_URLS=https://192.168.26.31:2380ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster
ETCD_INITIAL_CLUSTER="etcd1=https://192.168.26.31:2380,etcd2=https://192.168.26.32:2380,etcd3=https://192.168.26.33:2380"
ETCD_INITIAL_CLUSTER_STATE=new
## /opt/cfg/etcd.conf - node 2
ETCD_NAME=etcd2
ETCD_DATA_DIR=/opt/etcd/dataETCD_CERT_FILE=/opt/cert/etcd_server.crt
ETCD_KEY_FILE=/opt/cert/etcd_server.key
ETCD_TRUSTED_CA_FILE=/opt/cert/ca.crt
ETCD_CLIENT_CERT_AUTH=true
ETCD_LISTEN_CLIENT_URLS=https://192.168.26.32:2379
ETCD_ADVERTISE_CLIENT_URLS=https://192.168.26.32:2379ETCD_PEER_CERT_FILE=/opt/cert/etcd_server.crt
ETCD_PEER_KEY_FILE=/opt/cert/etcd_server.key
ETCD_PEER_TRUSTED_CA_FILE=/opt/cert/ca.crt
ETCD_LISTEN_PEER_URLS=https://192.168.26.32:2380
ETCD_INITIAL_ADVERTISE_PEER_URLS=https://192.168.26.32:2380ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster
ETCD_INITIAL_CLUSTER="etcd1=https://192.168.26.31:2380,etcd2=https://192.168.26.32:2380,etcd3=https://192.168.26.33:2380"
ETCD_INITIAL_CLUSTER_STATE=new
## /opt/cfg/etcd.conf - node 3
ETCD_NAME=etcd3
ETCD_DATA_DIR=/opt/etcd/dataETCD_CERT_FILE=/opt/cert/etcd_server.crt
ETCD_KEY_FILE=/opt/cert/etcd_server.key
ETCD_TRUSTED_CA_FILE=/opt/cert/ca.crt
ETCD_CLIENT_CERT_AUTH=true
ETCD_LISTEN_CLIENT_URLS=https://192.168.26.33:2379
ETCD_ADVERTISE_CLIENT_URLS=https://192.168.26.33:2379ETCD_PEER_CERT_FILE=/opt/cert/etcd_server.crt
ETCD_PEER_KEY_FILE=/opt/cert/etcd_server.key
ETCD_PEER_TRUSTED_CA_FILE=/opt/cert/ca.crt
ETCD_LISTEN_PEER_URLS=https://192.168.26.33:2380
ETCD_INITIAL_ADVERTISE_PEER_URLS=https://192.168.26.33:2380ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster
ETCD_INITIAL_CLUSTER="etcd1=https://192.168.26.31:2380,etcd2=https://192.168.26.32:2380,etcd3=https://192.168.26.33:2380"
ETCD_INITIAL_CLUSTER_STATE=new
主要配置參數包括為客戶端和集群其他節點配置的各監聽URL地址(均為HTTPS URL地址 ),并配置相應的 CA 證書參數。etcd 服務的相關配置參數如下:
- ETCD_NAME:etcd節點名稱,每個節點都應不同,例如etcd1、etcd2、etcd3。
- ETCD_DATA_DIR:etcd的數據存儲目錄,例如/opt/etcd/data。
- ETCD_LISTEN_CLIENT_URLS和ETCD_ADVERTISE_CLIENT_URLS:為客戶端提供的服務監聽URL地址,例如 https://192.168.26.31:2379。
- ETCD_LISTEN_PEER_URLS和ETCD_INITIAL_ADVERTISE_PEER_URLS:為本集群其他節點提供的服務監聽UR地址,例如 https://192.168.26.31:2380。
- ETCD_INITIAL_CLUSTER_TOKEN:集群名稱,例如etcd-cluster。
- ETCD_INITIAL_CLUSTER:集群各節點的 endpoint列表,例如 etcd1=https://192168.26.31:2380,etcd2=https://192.168.26.32:2380,etcd3=https://192.168.26.33:2380.
- ETCD_INITIAL_CLUSTER_STATE:初始集群狀態,在新建集群時將其設置為“new”,在集群已存在時將其設置為“existing”。
CA 證書的相關配置參數如下:
- ETCD_CERT_FILE:etcd 服務端 CA證書-crt 文件的全路徑,例如/opt/cert/etcd_server.crt.
- ETCD_KEY_FILE:etcd 服務端 CA證書-key 文件的全路徑,例如/opt/cert/etcd_server.key.
- ETCD_TRUSTED_CA_FILE:CA根證書文件的全路徑,例如/opt/cert/ca.crt.
- ETCD_CLIENT_CERT_AUTH:是否啟用客戶端證書認證。
- ETCD_PEER_CERT_FILE:集群各節點相互認證使用的CA證書-crt文件的全路徑例如/opt/cert/etcd_server.crt.
- ETCD_PEER_KEY_FILE:集群各節點相互認證使用的CA證書-key文件的全路徑例如/opt/cert/etcd_server.key。
- ETCD_PEER_TRUSTED_CA_FILE:CA 根證書文件的全路徑,例如/opt/cert/ca.crt。
4. 啟動 etcd 集群
基于 systemd的配置,在3臺主機上首先分別啟動 etcd 服務,并設置為開機自啟動:
## 啟動etcd服務,并設置為開機自啟動
]# systemctl restart etcd && systemctl enable etcd
]# systemctl status etcd
然后用 etcdctl客戶端命令行工具攜帶客戶端 CA證書,通過 etcdctl endpoint health 命令訪問 etcd 集群,驗證集群狀態是否正常。
## 通過etcdctl endpoint health命令訪問etcd集群,驗證集群狀態是否正常
]# etcdctl --cacert=/opt/cert/ca.crt --cert=/opt/cert/etcd_client.crt --key=/opt/cert/etcd_client.key --endpoints=https://192.168.26.31:2379,https://192.168.26.32:2379,https://192.168.26.33:2379 endpoint health
https://192.168.26.33:2379 is healthy: successfully committed proposal: took = 7.782435ms
https://192.168.26.31:2379 is healthy: successfully committed proposal: took = 7.786204ms
https://192.168.26.32:2379 is healthy: successfully committed proposal: took = 11.706174ms
結果顯示各節點狀態均為“healthy”,說明集群正常運行。至此,一個啟用了 HTTPS的有3個節點的 etcd集群就部署成功。
4.4 部署安全的 Kubernetes Master 高可用集群
1. 下載 Kubernetes 服務的二進制文件
? https://github.com/kubernetes/kubernetes
首先,從Kubernetes 的官方 GitHub 代碼庫頁面下載各組件的二進制文件,在 Releases頁面找到需要下載的版本號,單擊CHANGELOG鏈接,跳轉到已編譯好的Server端二進制(Server Binaries)文件的下載頁面下載該文件。
在Server Binaries 壓縮包中包含Kubernetes的所有服務端程序的二進制文件和容器鏡像文件,并根據不同的系統架構分別提供二進制文件,例如amd64表示x86架構,arm64表示arm架構,等等,根據目標環境的要求選擇正確的文件進行下載。
在Kubernetes的Master上需要部署的服務包括etcd、kube-apiserver、kube-controller-manager和kube-scheduler。
在Node上需要部署的服務包括容器運行時(如containerd)、kubelet 和 kube-proxy。
將Kubernetes的二進制可執行文件鏈接或復制到/usr/bin目錄下,然后在/usr/lib/systemd/system目錄下為各服務創建systemd服務的配置文件,完成Kubernetes服務的安裝。
## k8s31:
~]# cd /opt/app/
app]# tar zxvf kubernetes-server-linux-amd64.tar.gz
...
app]# rm -rf kubernetes/server//bin/*_tag
app]# rm -rf kubernetes/server//bin/*.tar
app]# rm -rf kubernetes/server//bin/{apiextensions-apiserver,kubectl-convert,kube-log-runner,mounter,kube-aggregator}
app]# ll kubernetes/server//bin/
總用量 532572
-rwxr-xr-x 1 root root 74543288 6月 17 14:57 kubeadm
-rwxr-xr-x 1 root root 97968312 6月 17 14:57 kube-apiserver
-rwxr-xr-x 1 root root 90767544 6月 17 14:57 kube-controller-manager
-rwxr-xr-x 1 root root 60129464 6月 17 14:57 kubectl
-rwxr-xr-x 1 root root 81703204 6月 17 14:57 kubelet
app]# mkdir /opt/bin/kubernetes-1.33.2
app]# mv kubernetes/server/bin /opt/bin/kubernetes-1.33.2
app]# rm -rf kubernetes
## 復制:
k8s31 app]# scp -r /opt/bin/kubernetes-1.33.2 root@k8s32:/opt/bin/.
k8s31 app]# scp -r /opt/bin/kubernetes-1.33.2 root@k8s33:/opt/bin/.
## 創建軟鏈接:同上
ln -s /opt/bin/kubernetes-1.33.2/kube-apiserver /usr/bin/kube-apiserver
ln -s /opt/bin/kubernetes-1.33.2/kube-controller-manager /usr/bin/kube-controller-manager
ln -s /opt/bin/kubernetes-1.33.2/kubectl /usr/bin/kubectl
ln -s /opt/bin/kubernetes-1.33.2/kubelet /usr/bin/kubelet
ln -s /opt/bin/kubernetes-1.33.2/kube-proxy /usr/bin/kube-proxy
ln -s /opt/bin/kubernetes-1.33.2/kube-scheduler /usr/bin/kube-scheduler
app]# kubectl version
Client Version: v1.33.2
Kustomize Version: v5.6.0
The connection to the server localhost:8080 was refused - did you specify the right host or port?
2. 部署 kube-apiserver服務
(1) 設置kube-apiserver 服務需要的 CA 相關證書。首先準備一個 x509 v3 版本的證書配置文件(master_ssl.cnf):
# CA證書配置
# vi /opt/cert/master_ssl.cnf
[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[req_distinguished_name][ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names[alt_names]
DNS.1 = kubernetes
DNS.2 = kubernetes.default
DNS.3 = kubernetes.default.svc
DNS.4 = kubernetes.default.svc.cluster.local
DNS.5 = k8s-1
DNS.6 = k8s-2
DNS.7 = k8s-3
IP.1 = 168.26.0.1
IP.2 = 192.168.26.31
IP.3 = 192.168.26.32
IP.4 = 192.168.26.33
IP.5 = 192.168.26.100
在該文件的subjectAltName字段([alt names])設置Master服務的全部域名和 IP 地址。
- DNS主機名,例如k8s-1、k8s-2、k8s-3等。
- Master Service的虛擬服務名稱,例如 kubernetes.default等。
- IP 地址,包括各 kube-apiserver所在主機的 IP 地址和負載均衡器的 IP地址,例如192.168.26.31、192.168.26.32、192.168.26.33和192.168.26.100。
- Master Service虛擬服務的 ClusterIP 地址,例如 168.26.0.1。
然后通過 openssl 命令創建 kube-apiserver 的服務端 CA 證書,包括 apiserver.key 和apiserver.crt 文件,將其保存到/opt/cert目錄下:
# 創建服務端CA證書openssl genrsa -out apiserver.key 2048openssl req -new -key apiserver.key -config master_ssl.cnf -subj "/CN=apiserver" -out apiserver.csropenssl x509 -req -in apiserver.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 36500 -extensions v3_req -extfile master_ssl.cnf -out apiserver.crt
## 復制
scp -r /opt/cert/apiserver* root@k8s32:/opt/cert/.
scp -r /opt/cert/apiserver* root@k8s33:/opt/cert/.
(2) 為kube-apiserver服務創建systemd服務的配置文件/usr/lib/systemd/system/kube-apiserver.service,在該文件中,EnvironmentFile參數指定將/opt/cfg/apiserver文件作為環境文件,其中通過變量KUBE_API_ARGS設置kube-apiserver的啟動參數:
## Kubernetes各服務的配置
## vi /usr/lib/systemd/system/kube-apiserver.service
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes[Service]
EnvironmentFile=/opt/cfg/apiserver
ExecStart=/usr/bin/kube-apiserver $KUBE_API_ARGS
Restart=always[Install]
WantedBy=multi-user.target
(3) 在環境文件/opt/cfg/apiserver中,配置變量KUBE_API_ARGS 的值為kube-apiserver的全部啟動參數:
## vi /opt/cfg/apiserver
KUBE_API_ARGS="--secure-port=6443 \
--tls-cert-file=/opt/cert/apiserver.crt \
--tls-private-key-file=/opt/cert/apiserver.key \
--kubelet-client-certificate=/opt/cert/apiserver.crt \
--kubelet-client-key=/opt/cert/apiserver.key \
--client-ca-file=/opt/cert/ca.crt \
--apiserver-count=3 --endpoint-reconciler-type=master-count \
--etcd-servers=https://192.168.26.31:2379,https://192.168.26.32:2379,https://192.168.26.33:2379 \
--etcd-cafile=/opt/cert/ca.crt \
--etcd-certfile=/opt/cert/etcd_client.crt \
--etcd-keyfile=/opt/cert/etcd_client.key \
--service-cluster-ip-range=168.26.0.0/16 \
--service-node-port-range=30000-32767 \
--service-account-issuer=https://kubernetes.default.svc.cluster.local \
--service-account-signing-key-file=/opt/cert/apiserver.key \
--service-account-key-file=/opt/cert/apiserver.key \
--allow-privileged=true"
- –secure-port:HTTPS端口號,默認值為6443。
- –tls-cert-fle:服務端CA證書文件的全路徑,例如/opt/cert/apiserver.crt。
- –tls-private-key-fle:服務端CA私鑰文件的全路徑,例如/opt/cert/apiserver. key。
- –client-ca-file:CA根證書的全路徑,例如/opt/cert/ca.crt。
- –apiserver-count:API Server 實例的數量,例如3,需要同時設置參數–endpoint-reconciler-type=master-count。
- –etcd-servers:連接 etcd 的 URL列表,這里使用 HTTPS,例如 https://192.168.26.31:2379、https://192.168.26.32:2379和https://192.168.26.33:2379。
- –etcd-cafile:etcd 使用的 CA根證書文件的全路徑,例如/opt/cert/ca.crt。
- –etcd-certfile:etcd客戶端CA證書文件的全路徑,例如/opt/cert/etcd_client.crt。
- –etcd-keyfile:etcd 客戶端私鑰文件的全路徑,例如/opt/cert/etcd_ client.key。
- –service-cluster-ip-range:Service虛擬IP地址的范圍,以CIDR格式表示(168.26.0.0/16),在該范圍內不可出現物理機的IP地址。
- –service-node-port-range:Service可使用的物理機端口號范圍,默認值為 30000~32767。
- –allow-privileged:是否允許容器以特權模式運行,默認值為true。
(4) 在配置文件準備完畢后,在3臺主機上分別啟動 kube-apiserver 服務,并設置為開機自啟動:
systemctl start kube-apiserver && systemctl enable kube-apiserver
systemctl status kube-apiserver
3. 創建客戶端 CA 證書
kube-controller-manager、kube-scheduler、kubelet 和 kube-proxy 服務作為客戶端連接kube-apiserver 服務,需要為它們創建客戶端 CA證書,使其能夠正確訪問 kube-apiserver。對這幾個服務統一創建一個證書。
?通過 openssl 命令創建 CA 證書和私鑰文件
## 創建客戶端CA證書
openssl genrsa -out client.key 2048openssl req -new -key client.key -subj "/CN=admin" -out client.csropenssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 36500
其中,-subj 參數中“/CN”的名稱可以被設置為“admin”,用于標識連接 kube-apiserver的客戶端用戶的名稱。
將生成的 client.key和 client.crt文件保存在/opt/cert目錄下。
## 復制
scp -r /opt/cert/client* root@k8s32:/opt/cert/.
scp -r /opt/cert/client* root@k8s33:/opt/cert/.
4. 創建客戶端連接 kube-apiserver 服務所需的 kubeconfig 配置文件
為 kube-controller-manager、kube-scheduler、kubelet 和 kube-proxy 服務統一創建一個 kubeconfg 文件作為連接 kube-apiserver 服務的配置文件,后續也作為 kubectl 連接kube-apiserver 服務的配置文件。
?在 kubeconfig文件中主要設置訪問 kube-apiserver的URL地址及所需 CA 證書等相關參數:
## vi /opt/cfg/kubeconfig
apiVersion: v1
kind: Config
clusters:
- name: defaultcluster:server: https://192.168.26.100:9443certificate-authority: /opt/cert/ca.crt
users:
- name: adminuser:client-certificate: /opt/cert/client.crtclient-key: /opt/cert/client.key
contexts:
- context:cluster: defaultuser: adminname: default
current-context: default
- server URL地址:配置為負載均衡器(HAProxy)使用的虛擬IP地址(192.168.26.100)和HAProxy監聽的端口號(9443)。
- client-certificate:配置為客戶端證書文件(client.crt)的全路徑。
- client-key:配置為客戶端私鑰文件(client.key)的全路徑。
- certificate-authority:配置為CA根證書(ca.crt)的全路徑。
- users中的user name和context中的user:連接API Server 的用戶名,設置為與客戶端證書中的“/CN”名稱保持一致(“admin”)。
將 kubeconfig 文件保存到/opt/cfg目錄下。
5. 部署 kube-controller-manager 服務
(1) 為 kube-controller-manager 服務創建 systemd 服務的配置文件/usr/lib/systemd/system/kube-controller-manager.service,其中 EnvironmentFile參數指定使用/etc/kubernetes/controller-manager 文件作為環境文件,在該環境文件中通過變量KUBE_CONTROLLER_MANAGER_ARGS 設置 kube-controller-manager的啟動參數:
## vi /usr/lib/systemd/system/kube-controller-manager.service
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes[Service]
EnvironmentFile=/opt/cfg/controller-manager
ExecStart=/usr/bin/kube-controller-manager $KUBE_CONTROLLER_MANAGER_ARGS
Restart=always[Install]
WantedBy=multi-user.target
(2) 在環境文件/opt/cfg/controller-manager中,配置變量 KUBE_CONTROLLER_MANAGER_ARGS的值為 kube-controller-manager的全部啟動參數:
## vi /opt/cfg/controller-manager
KUBE_CONTROLLER_MANAGER_ARGS="--kubeconfig=/opt/cfg/kubeconfig \
--leader-elect=true \
--service-cluster-ip-range=168.26.0.0/16 \
--service-account-private-key-file=/opt/cert/apiserver.key \
--root-ca-file=/opt/cert/ca.crt"
- –kubeconfig:與APIServer連接的相關配置。
- –leader-elect:啟用選舉機制,在有3個節點的環境下應被設置為“true“。
- –service-account-private-key-file:為ServiceAccount自動頒發token使用的私鑰文件的全路徑/opt/cert/apiserver.key。
- –root-ca-file:CA根證書的全路徑/opt/cert/ca.crt。
- –service-cluster-ip-range:Service的虛擬IP地址范圍,以CIDR格式表示(169.169.0.0/16),與kube-apiserver服務中的配置保持一致。
(3) 在配置文件準備完畢后,在3臺主機上分別啟動 kube-controller-manager 服務,并設置為開機自啟動:
systemctl daemon-reload
systemctl start kube-controller-manager && systemctl enable kube-controller-manager
systemctl status kube-controller-manager
6. 部署 kube-scheduler 服務
(1)為kube-scheduler服務創建systemd服務的配置文件/usr/lib/systemd/system/kube-scheduler.service,其中 EnvironmentFile 參數指定使用/opt/cfg/scheduler文件作為環境文件,在該環境文件中通過變量KUBE_SCHEDULER_ARGS設置 kube-scheduler 的啟動參數:
## vi /usr/lib/systemd/system/kube-scheduler.service
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes[Service]
EnvironmentFile=/opt/cfg/scheduler
ExecStart=/usr/bin/kube-scheduler $KUBE_SCHEDULER_ARGS
Restart=always[Install]
WantedBy=multi-user.target
(2) 在環境文件/opt/cfg/scheduler中,配置變量KUBE_SCHEDULER_ARGS 的值為 kube-scheduler的全部啟動參數:
## vi /opt/cfg/scheduler
KUBE_SCHEDULER_ARGS="--kubeconfig=/opt/cfg/kubeconfig \
--leader-elect=true"
- –kubeconfig:與APIServer連接的相關配置。
- –leader-elect:啟用選舉機制,在有3個節點的環境下應被設置為“true”。
(3) 在配置文件準備完畢后,在3臺主機上分別啟動 kube-scheduler 服務,并設置為開機自啟動:
systemctl start kube-scheduler && systemctl enable kube-scheduler
systemctl status kube-scheduler
通過 systemctl status 驗證服務的啟動狀態,若狀態為“running”并且沒有報錯日志,則表示啟動成功。
7. 使用 HAProxy 和 keepalived 部署高可用負載均衡器
接下來,在3個kube-apiserver服務的前端部署HAProxy和keepalived,將VIP地址192.168.26.100作為Master的唯一入口地址,供客戶端訪問。
?將 HAProxy和keepalived均部署為至少有兩個實例的高可用架構,以免發生單點故障。下面在192.168.26.31和192.168.26.32兩臺服務器上進行部署。
HAProxy負責將客戶端的請求轉發到后端的3個kube-apiserver 實例上,keepalived 負責保證虛擬 IP地址192.168.26.100的高可用。
HAProxy和 keepalived 的部署架構如圖 所示:
接下來在k8s31(192.168.26.31)和k8s32(192.168.26.31)部署 HAProxy 和 keepalived 實例。
1) 部署兩個 HAProxy 實例
準備 HAProxy 的配置文件 haproxy.cfg:
## vi /opt/cfg/haproxy.cfg
globallog 127.0.0.1 local2chroot /var/lib/haproxypidfile /var/run/haproxy.pidmaxconn 4096user haproxygroup haproxydaemonstats socket /var/lib/haproxy/statsdefaultsmode httplog globaloption httplogoption dontlognulloption http-server-closeoption forwardfor except 127.0.0.0/8option redispatchretries 3timeout http-request 10stimeout queue 1mtimeout connect 10stimeout client 1mtimeout server 1mtimeout http-keep-alive 10stimeout check 10smaxconn 3000frontend kube-apiservermode tcpbind *:9443option tcplogdefault_backend kube-apiserverlisten statsmode httpbind *:8888stats auth admin:passwordstats refresh 5sstats realm HAProxy\ Statisticsstats uri /statslog 127.0.0.1 local3 errbackend kube-apiservermode tcpbalance roundrobinserver k8s-master1 192.168.26.31:6443 checkserver k8s-master2 192.168.26.32:6443 checkserver k8s-master3 192.168.26.33:6443 check
- frontend:HAProxy的監聽協議和端口號,使用TCP,端口號為9443
- backend:后端的3個kube-apiserver的地址(192.168.26.31:6443、192.168.26.32:6443和192.168.26.33:6443),以IP:Port 形式表示;mode 字段用于設置協議,此處的值為“tcp”;balance 字段用于設置負載均衡策略,例如roundrobin為輪詢模式。
- listen stats:狀態監控的服務配置,其中,bind用于設置監聽端口號為8888;stats auth用于設置訪問賬號和密碼(這里設置為admin:password);stats uri用于設置訪問的URL路徑,例如/stats。
通過 Docker 容器運行HAProxy且鏡像使用haproxytech/haproxy-debian:
?在兩臺服務器192.168.26.31和192.168.26.32上啟動HAProxy,將配置文件 haproxy.cfg掛載到容器的/usr/local/etc/haproxy 目錄下,啟動命令如下:
## 拉取鏡像haproxytech/haproxy-debian:latest
~]# docker pull haproxytech/haproxy-debian:latest
## 啟動haproxy
~]# docker run -d --name k8s-haproxy \--net=host \--restart=always \-v /opt/cfg/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro \haproxytech/haproxy-debian:latest
~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0c8f267ad2cd haproxytech/haproxy-debian:latest "/docker-entrypoint.…" 16 seconds ago Up 15 seconds k8s-haproxy
在一切正常的情況下,通過瀏覽器訪問 http://192.168.26.31:8888/stats 這一地址即可訪問 HAProxy 的管理頁面,輸入用戶名和密碼(admin:password)登錄后査看到的主頁界面如圖所示:
這里主要關注最后一個表格,其內容為haproxy.cfg配置文件中backend 配置的3個kube-apiserver地址,它們的狀態均為“UP",表示與3個kube-apiserver 服務成功建立連接,說明 HAProxy 工作正常。
2) 部署兩個 keepalived 實例
keepalived用于維護虛擬IP地址的高可用,同樣在k8s31和k8s32兩臺服務器上部署。其中主要需要配置keepalived對HAProxy運行狀態的監控,當某個HAProxy實例不可用時,自動將虛擬 IP地址切換到另一臺主機上。
?在第1臺服務器k8s31:192.168.26.31上創建配置文件 keepalived.conf:
## /opt/cfg/keepalived.conf
! Configuration File for keepalivedglobal_defs {router_id LVS_1
}vrrp_script checkhaproxy
{script "/opt/bin/check-haproxy.sh"interval 2weight -30
}vrrp_instance VI_1 {state MASTERinterface ens160virtual_router_id 51priority 100advert_int 1virtual_ipaddress {192.168.26.100/24 dev ens160}authentication {auth_type PASSauth_pass password}track_script {checkhaproxy}
}
在 vrrp_instance 字段設置主要參數。
- vrrp_instance VI_1:設置 keepalived 虛擬路由器組(VRRP)的名稱。
- state:設置為“MASTER”,將其他keepalived均設置為“BACKUP”。
- interface:待設置虛擬IP地址的網卡名稱。
- virtual_router_id:例如51。
- priority:優先級,例如100。
- virtual_ipaddress:虛擬IP地址,例如192.168.26.100/24。
- authentication:訪問 keepalived 服務的鑒權信息。
- track_script:HAProxy的健康檢查腳本。
keepalived需要持續監控 HAProxy的運行狀態,在某個 HAProxy 實例運行不正常時,自動切換到運行正常的 HAProxy 實例上。需要創建一個 HAProxy 健康檢查腳本,定期運行該腳本進行監控,例如新建腳本 check-haproxy.sh并將其保存到/usr/bin 目錄下。
## /opt/bin/check-haproxy.sh
#!/bin/bashcount=`netstat -apn | grep 9443 | wc -l`if [ $count -gt 0 ]; thenexit 0
elseexit 1
fi
~]# chmod +x /opt/bin/check-haproxy.sh
~]# ls -l /opt/bin/check-haproxy.sh
-rwxr-xr-x 1 root root 111 7月 8 02:58 /opt/bin/check-haproxy.sh
若檢查成功,則返回0;若檢查失敗,則返回非0值。keepalived根據上面的配置每隔2s檢査一次HAProxy的運行狀態。如果檢査到第1臺主機192.168.26.31上的HAProxy為非正常運行狀態,keepalived就會將虛擬IP地址切換到正常運行HAProxy的第2臺主機 192.168.26.32上,保證虛擬 IP地址 92.168.26.100的高可用。
?在第2臺主機k8s:192.168.26.32上創建配置文件keepalived.conf:
## /opt/cfg/keepalived.conf
! Configuration File for keepalivedglobal_defs {router_id LVS_2
}vrrp_script checkhaproxy
{script "/opt/bin/check-haproxy.sh"interval 2weight -30
}vrrp_instance VI_1 {state BACKUPinterface ens160virtual_router_id 51priority 100advert_int 1virtual_ipaddress {192.168.26.100/24 dev ens160}authentication {auth_type PASSauth_pass password}track_script {checkhaproxy}
}
這里與第1個keepalived 配置的主要差異如下:
- vrp_instance中的state被設置為“BACKUP”,這是因為在整個keepalived集群中只能有一個被設置為“MASTER"。如果keepalived集群不止有2個實例,那么除了MASTER,其他都應被設置為“BACKUP”。
- vrp_instance的值“VI_1”需要與 MASTER 的配置相同,表示它們屬于同一個虛擬路由器組,當 MASTER不可用時,同組的其他 BACKUP實例會自動選舉出一個新的MASTER。
HAProxy健康檢査腳本 check-haproxy.sh與第1個keepalived 的相同。
通過 Docker 容器運行 keepalived 且鏡像使用 osixia/keepalived:
在兩臺主機k8s31和k8s32上啟動keepalived,將配置文件keepalived.conf掛載到容器的/container/service/keepalived/assets目錄下,啟動命令如下:
~]# docker pull osixia/keepalived:latest
## 啟動keepalived
~]# docker run -d --name k8s-keepalived \--restart=always \--net=host \--cap-add=NET_ADMIN --cap-add=NET_BROADCAST --cap-add=NET_RAW \-v /opt/cfg/keepalived.conf:/container/service/keepalived/assets/keepalived.conf \-v /opt/bin/check-haproxy.sh:/usr/bin/check-haproxy.sh \osixia/keepalived:latest --copy-service
~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f41b9f3f9a4c osixia/keepalived:latest "/container/tool/run…" 9 seconds ago Up 9 seconds k8s-keepalived
0c8f267ad2cd haproxytech/haproxy-debian:latest "/docker-entrypoint.…" 9 minutes ago Up 9 minutes k8s-haproxy
在運行正常的情況下,keepalived會在第1臺主機k8s31的網卡ens160 上設置VIP地址192.168.26.100。同樣,在第1臺主機 k8s31上運行的HAProxy將在該IP地址上監聽9443端口號,對需要訪問Kubermetes Master的客戶端提供負載均衡器的人口地址,即:
192.168.26.100:9443
通過ip addr命令査看主機192.168.26.31的IP地址,可以看到在ens160網卡上新增了VIP地址192.168.26.100:
通過cul命令即可驗證通過HAProxy的192.168.26.100:9443 地址是否可以訪問 kube-apiserver 服務:
## 通過haproxy訪問kube-apiserver
# curl -v -k https://192.168.26.100:9443
* Rebuilt URL to: https://192.168.26.100:9443/
* Trying 192.168.26.100...
* TCP_NODELAY set
* Connected to 192.168.26.100 (192.168.26.100) port 9443 (#0)
...
* TLSv1.3 (IN), TLS app data, [no content] (0):
{"kind": "Status","apiVersion": "v1","metadata": {},"status": "Failure","message": "Unauthorized","reason": "Unauthorized","code": 401
* Closing connection 0
* TLSv1.3 (OUT), TLS alert, [no content] (0):
* TLSv1.3 (OUT), TLS alert, close notify (256):
}
可以看到"code": 401,表示 TCP/IP連接創建成功,說明通過虛擬IP地址192.168.26.100 成功訪問到了后端的 kube-apiserver服務。
~]# kubectl --kubeconfig=/opt/cfg/kubeconfig get cs
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME STATUS MESSAGE ERROR
etcd-0 Healthy ok
controller-manager Healthy ok
scheduler Healthy ok
至此,Master 上所需的3個服務就全部啟動完成。接下來部署各個Node的服務。
4.5 部署各個 Node 的服務
在 Node 上需要部署容器運行時(如 containerd)、kubelet和 kube-proxy 等系統組件。容器運行時可以根據需要選擇合適的軟件,例如開源的containerd、cri-o等,相關安裝部署過程參考其說明文檔。
將 192.168.26.31、192.168.26.32和 192.168.26.33 三臺主機部署為 Node,部署一個包含3個Node 的Kubernetes 集群。
1. 部署kubelet服務(容器為docker)
- 創建目錄
~]# mkdir /data/kubernetes/kubelet -p
- 啟動文件/usr/lib/systemd/system/kubelet.service。默認使用docker作為Runtime。
cat > /usr/lib/systemd/system/kubelet.service << EOF
[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/kubernetes/kubernetes
After=cri-dockerd.service
Requires=cri-dockerd.service[Service]
WorkingDirectory=/data/kubernetes/kubelet
ExecStart=/usr/bin/kubelet \\--bootstrap-kubeconfig=/opt/cert/bootstrap-kubelet.kubeconfig \\--cert-dir=/opt/cert \\--kubeconfig=/opt/cfg/kubeconfig \\--config=/opt/cfg/kubelet.json \\--container-runtime-endpoint=unix:///var/run/cri-dockerd.sock \\--pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.10 \\--root-dir=/data/kubernetes/kubelet \\--v=2
Restart=on-failure
RestartSec=5[Install]
WantedBy=multi-user.target
EOF
/opt/cert/kubelet.kubeconfig為自動創建的文件,如果已存在就刪除
- 所有k8s節點創建kubelet的配置文件/opt/cfg/kubelet.json
cat > /opt/cfg/kubelet.json << EOF
{"kind": "KubeletConfiguration","apiVersion": "kubelet.config.k8s.io/v1beta1","authentication": {"x509": {"clientCAFile": "/opt/cert/ca.crt"},"webhook": {"enabled": true,"cacheTTL": "2m0s"},"anonymous": {"enabled": false}},"authorization": {"mode": "Webhook","webhook": {"cacheAuthorizedTTL": "5m0s","cacheUnauthorizedTTL": "30s"}},"address": "192.168.26.31","port": 10250,"readOnlyPort": 10255,"cgroupDriver": "systemd", "hairpinMode": "promiscuous-bridge","serializeImagePulls": false,"clusterDomain": "cluster.local.","clusterDNS": ["168.26.0.100"]
}
EOF
注意修改:“address”: “192.168.26.31”;
“address”: “192.168.26.32”;
“address”: “192.168.26.33”
- 啟動
~]# systemctl daemon-reload
~]# systemctl enable --now kubelet
~]# systemctl status kubelet
● kubelet.service - Kubernetes KubeletLoaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; vendor preset: disabled)Active: active (running) since Tue 2025-07-08 03:09:04 EDT; 15s agoDocs: https://github.com/kubernetes/kubernetesMain PID: 3071 (kubelet)Tasks: 11 (limit: 23520)Memory: 25.3MCGroup: /system.slice/kubelet.service└─3071 /usr/bin/kubelet --bootstrap-kubeconfig=/opt/cert/bootstrap-kubelet.kubeconfig --cert-dir=/opt/cert --kubeconfig=/opt/cfg/k>
......
## 啟動不正常時,查看出錯信息:journalctl -fu kubelet
~]# kubectl get nodes -o wide --kubeconfig=/opt/cfg/kubeconfig
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k8s31.vm.com NotReady <none> 3m28s v1.33.2 192.168.26.31 <none> CentOS Linux 8 4.18.0-348.7.1.el8_5.x86_64 docker://28.3.1
k8s32.vm.com NotReady <none> 3m28s v1.33.2 192.168.26.32 <none> CentOS Linux 8 4.18.0-348.7.1.el8_5.x86_64 docker://28.3.1
k8s33.vm.com NotReady <none> 3m28s v1.33.2 192.168.26.33 <none> CentOS Linux 8 4.18.0-348.7.1.el8_5.x86_64 docker://28.3.1
如果node仍然是NotReady
,則需要安裝cni-plugin-flannel。(參見后面的Calico CNI插件部署)
~]# kubectl --kubeconfig=/opt/cfg/kubeconfig get nodes
NAME STATUS ROLES AGE VERSION
k8s31.vm.com NotReady <none> 4m29s v1.33.2
k8s32.vm.com NotReady <none> 4m29s v1.33.2
k8s33.vm.com NotReady <none> 4m29s v1.33.2
2. 部署 kubelet 服務(容器為containerd)【本次未使用】
(1) 為kubelet服務創建systemd服務的配置文件/usr/lib/systemd/system/kubelet.service:
## /usr/lib/systemd/system/kubelet.service
[Unit]
Description=Kubernetes Kubelet Server
Documentation=https://github.com/kubernetes/kubernetes
After=docker.target[Service]
EnvironmentFile=/opt/cfg/kubelet
ExecStart=/usr/bin/kubelet $KUBELET_ARGS
Restart=always[Install]
WantedBy=multi-user.target
(2) 配置文件/etc/kubernetes/kubelet的內容為通過環境變量 KUBELET_ARGS 設置的kubelet的全部啟動參數:
## /opt/cfg/kubelet
KUBELET_ARGS="--kubeconfig=/opt/cfg/kubeconfig \
--config=/opt/cfg/kubelet.config \
--hostname-override=192.168.26.31"
- –kubeconfig:設置與API Server連接的相關配置,可以與 kube-controller-manager使用的 kubeconfg 文件相同。需要將相關客戶端證書文件從 Master 復制到 Node的/opt/cfg目錄下,例如 ca.crt、client.key、client.crt 文件。
- –config:kubelet配置文件,例如kubelet.config,在Kubernetes v1.10版本中開始引人,用于逐步替換命令行參數,以簡化Node 的配置管理。
- –hostmame-override:設置本 Node 在集群中的名稱,默認值為主機名,應將各個Node 都設置為本機 IP 地址或域名。
? 配置文件 kubelet.config:
## /opt/cfg/kubelet.config
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
address: 0.0.0.0
port: 10250
cgroupDriver: systemd
clusterDNS: ["168.26.0.100"]
clusterDomain: cluster.local
authentication:anonymous:enabled: true
- address:服務監聽的IP 地址。
- port:服務監聽的端口號,默認值為 10250。
- cgroupDriver:設置為cgroupDriver驅動,可選項包括systemd 和 cgroupfs。
- clusterDNS:集群DNS服務的IP地址,例如168.26.0.100。
- clusterDomain:服務的 DNS 域名后綴,例如 cluster.local。
- authentication:設置是否允許匿名訪問或者是否使用 Webhook 進行鑒權。
(3) 在配置文件準備完畢后,在各個Node 上啟動 kubelet服務,并設置為開機自啟動命令如下:
~]# systemctl start kubelet && systemctl enable kubelet
~]# systemctl status kubelet
3. 部署 kube-proxy 服務
(1) 為 kube-proxy服務創建systemd服務的配置文件/usr/lib/systemd/system/kube-proxy.service:
## /usr/lib/systemd/system/kube-proxy.service
[Unit]
Description=Kubernetes Kube-Proxy Server
Documentation=https://github.com/kubernetes/kubernetes
After=network.target[Service]
EnvironmentFile=/opt/cfg/proxy
ExecStart=/usr/bin/kube-proxy $KUBE_PROXY_ARGS
Restart=always[Install]
WantedBy=multi-user.target
(2) 配置文件/opt/cfg/proxy 的內容為通過環境變量 KUBE_PROXY_ARGS 設置的 kube-proxy 的全部啟動參數:
## /opt/cfg/proxy
KUBE_PROXY_ARGS="--kubeconfig=/opt/cfg/kubeconfig \
--hostname-override=192.168.26.31 \
--proxy-mode=iptables"
- –kubeconfig:設置與API Server連接的客戶端身份,可以與kubelet 使用相同的kubeconfig 文件。
- –hostname-override:設置本Node在集群中的名稱,默認值為主機名。
- –proxy-mode:代理模式,可選項包括iptables、ipvs、kernelspace(Windows Node使用)。
(3) 在配置文件準備完畢后,在各個Node 上啟動 kube-proxy 服務,并設置為開機自啟動,命令如下:
~]# systemctl start kube-proxy && systemctl enable kube-proxy
~]# systemctl status kube-proxy
4. 在 Master 上通過 kubectl驗證各個 Node 的信息
在各個Node的kubelet和kube-proxy服務均正常啟動之后,會先將Node自動注冊到Master上,然后就可以到Master上通過kubectl查詢已注冊的 Node 的信息,命令如下:
]# kubectl --kubeconfig=/opt/cfg/kubeconfig get nodes
NAME STATUS ROLES AGE VERSION
k8s31.vm.com NotReady <none> 8m56s v1.33.2
k8s32.vm.com NotReady <none> 8m56s v1.33.2
k8s33.vm.com NotReady <none> 8m56s v1.33.2
可以看到各個Node的狀態均為“NotReady”,這是因為還沒有部署CNI網絡插件,無法設置容器網絡。
5. 安裝Calico CNI網絡插件
按需選擇適合的CNI網絡插件進行部署。選擇Calico CNI網絡插件,則運行以下命令即可一鍵完成部署:
- 下載 calico 的 yaml 文件(https://docs.projectcalico.org/manifests/calico.yaml)
https://github.com/projectcalico/calico/blob/release-v3.30/manifests/calico.yaml
- 配置 cidr 網段,找到
CALICO_IPV4POOL_CIDR
字段,關閉前面的注釋,把ip網段修改成和controller-manager
的--cluster-cidr
參數一致
- name: CALICO_IPV4POOL_CIDRvalue: "10.26.0.0/16"
- 拉取鏡像
app]# grep image calico.yamlimage: docker.io/calico/cni:v3.30.0imagePullPolicy: IfNotPresentimage: docker.io/calico/cni:v3.30.0imagePullPolicy: IfNotPresentimage: docker.io/calico/node:v3.30.0imagePullPolicy: IfNotPresentimage: docker.io/calico/node:v3.30.0imagePullPolicy: IfNotPresentimage: docker.io/calico/kube-controllers:v3.30.0imagePullPolicy: IfNotPresent
app]# docker pull docker.io/calico/cni:v3.30.0
app]# docker pull docker.io/calico/node:v3.30.0
app]# docker pull docker.io/calico/kube-controllers:v3.30.0
- 創建 calico 組件
app]# kubectl apply -f /opt/app/calico.yaml --kubeconfig=/opt/cfg/kubeconfig
...
在 CNI網絡插件成功運行之后,各個Node的狀態均會更新為“Ready”:
app]# watch kubectl get pod -A --kubeconfig=/opt/cfg/kubeconfig
...
app]# kubectl --kubeconfig=/opt/cfg/kubeconfig get pod -A -owide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-system calico-kube-controllers-7bfdc5b57c-gkftm 1/1 Running 0 38s 10.26.179.193 k8s31.vm.com <none> <none>
kube-system calico-node-cmc58 1/1 Running 0 38s 192.168.26.31 k8s31.vm.com <none> <none>
kube-system calico-node-k9tf8 1/1 Running 0 38s 192.168.26.33 k8s33.vm.com <none> <none>
kube-system calico-node-wwd97 1/1 Running 0 38s 192.168.26.32 k8s32.vm.com <none> <none>
]# kubectl --kubeconfig=/opt/cfg/kubeconfig get nodes
NAME STATUS ROLES AGE VERSION
k8s31.vm.com Ready <none> 15m v1.33.2
k8s32.vm.com Ready <none> 15m v1.33.2
k8s33.vm.com Ready <none> 15m v1.33.2
6. kubectl配置
- 創建admin.kubeconfig。
-server=https://192.168.26.100:9443
。在一個節點執行一次即可。(此處可不用創建,使用**/opt/cfg/kubeconfig**即可)
kubectl config set-cluster kubernetes \--certificate-authority=/opt/cert/ca.crt \--embed-certs=true \--server=https://192.168.26.100:9443 \--kubeconfig=/opt/cert/admin.kubeconfigkubectl config set-credentials kubernetes-admin \--client-certificate=/opt/cert/client.crt \--client-key=/opt/cert/client.key \--embed-certs=true \--kubeconfig=/opt/cert/admin.kubeconfigkubectl config set-context kubernetes-admin@kubernetes \--cluster=kubernetes \--user=kubernetes-admin \--kubeconfig=/opt/cert/admin.kubeconfigkubectl config use-context kubernetes-admin@kubernetes --kubeconfig=/opt/cert/admin.kubeconfig
]# mkdir ~/.kube
### ]# cp /opt/cert/admin.kubeconfig ~/.kube/config
]# cp /opt/cfg/kubeconfig ~/.kube/config
]# scp -r ~/.kube root@k8s32:~/.
]# scp -r ~/.kube root@k8s33:~/.
- 配置kubectl子命令補全
~]# echo 'source <(kubectl completion bash)' >> ~/.bashrc~]# yum -y install bash-completion
~]# source /usr/share/bash-completion/bash_completion
~]# source <(kubectl completion bash)~]# kubectl get componentstatuses
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME STATUS MESSAGE ERROR
controller-manager Healthy ok
scheduler Healthy ok
etcd-0 Healthy ok
~]# kubectl get nodes -owide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k8s31.vm.com Ready <none> 19m v1.33.2 192.168.26.31 <none> CentOS Linux 8 4.18.0-348.7.1.el8_5.x86_64 docker://28.3.1
k8s32.vm.com Ready <none> 19m v1.33.2 192.168.26.32 <none> CentOS Linux 8 4.18.0-348.7.1.el8_5.x86_64 docker://28.3.1
k8s33.vm.com Ready <none> 19m v1.33.2 192.168.26.33 <none> CentOS Linux 8 4.18.0-348.7.1.el8_5.x86_64 docker://28.3.1
為了使 Kubernetes 集群內的微服務能夠通過服務名進行網絡訪問,還需要部署kube-dns服務,建議使用CoreDNS來部署DNS服務。
?至此,一個有3個Master 的高可用 Kubernetes 集群就部署完成,接下來就可以創建 Pod、Deployment、Service 等資源對象來部署和管理容器應用及微服務。
五、 DNS服務搭建和配置
5.1 CoreDNS 總體架構
5.2 部署CoreDNS服務
修改每個Node上kubelet的 DNS 啟動參數,在其中加上以下兩個參數。
- –cluster-dns=168.26.0.100:是DNS服務的ClusterIP 地址。
- –cluster-domain=cluster.local:是在DNS 服務中設置的域名。
然后重啟 kubelet 服務。
部署 CoreDNS 服務時需要創建3個資源對象:ConfigMap、Deployment和 Service。在啟用了 RBAC 的 Kubernetes 集群中,還可以通過設置 ServiceAccount、ClusterRole、ClusterRoleBinding 來對 CoreDNS 容器進行權限設置。
- ConfigMap “coredns”主要用于設置CoreDNS的主配置文件Corefile的內容,其中可以定義各種域名的解析方式和使用的插件。
- Deployment “coredns”主要用于設置CoreDNS容器應用的內容,其中replicas副本的數量通常應該根據Kubernetes 集群的規模和服務數量確定,如果單個 CoreDNS進程不足以支撐整個集群的DNS查詢,則可以通過水平擴展提高查詢能力。由于DNS服務是Kubermetes 集群的關鍵核心服務,所以建議為其 Deployment設置自動擴縮容控制器,自動管理其副本數量。另外,對資源限制部分(CPU限制和內存限制)的設置也應根據實際環境進行調整。
- Service “kube-dns”是DNS服務的配置清單,這個服務需要設置固定的ClusterIP地址,也需要將所有Node上的 kubelet啟動參數–cluster-dns都設置為這個ClusterIP地址。
app]# cp coredns.yaml.base coredns.yaml
app]# grep image coredns.yamlimage: registry.k8s.io/coredns/coredns:v1.12.0imagePullPolicy: IfNotPresent
app]# docker pull registry.k8s.io/coredns/coredns:v1.12.0 ## 不能拉取時,使用aliyun鏡像
app]# docker pull registry.aliyuncs.com/google_containers/coredns:v1.12.0
app]# docker images|grep coredns
registry.k8s.io/coredns/coredns v1.12.0 1cf5f116067c 7 months ago 70.1MB## 修改以下內容:__DNS__DOMAIN__ 改為: cluster.local__DNS__MEMORY__LIMIT__ 改為: 170Mi__DNS__SERVER__ 改為: 168.26.0.100
## 修改內容位置
...
data:Corefile: |cluster.local {errorshealth {lameduck 5s}readykubernetes cluster.local 168.26.0.0/16 {fallthrough in-addr.arpa ip6.arpa}
...resources:limits:memory: 170Mirequests:cpu: 100mmemory: 70Mi
...
spec:selector:k8s-app: kube-dnsclusterIP: 168.26.0.100
...
通過 kubectl create命令完成 CoreDNS 服務的創建:
app]# kubectl create -f /opt/app/coredns.yaml
查看 Deployment、Pod和Service,確保容器成功啟動:
app]# kubectl get deployments --namespace=kube-system
NAME READY UP-TO-DATE AVAILABLE AGE
calico-kube-controllers 1/1 1 1 13m
coredns 1/1 1 1 8s
app]# kubectl get pods --namespace=kube-system
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-7bfdc5b57c-gkftm 1/1 Running 0 13m
calico-node-cmc58 1/1 Running 0 13m
calico-node-k9tf8 1/1 Running 0 13m
calico-node-wwd97 1/1 Running 0 13m
coredns-76b7578cff-4jxb6 1/1 Running 0 34s
app]# kubectl get services --namespace=kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 168.26.0.100 <none> 53/UDP,53/TCP,9153/TCP 53
5.3 服務名的 DNS 解析
使用一個帶有 nslookup 工具的 Pod 來驗證 DNS 服務能否正常工作,
## busybox.yaml
## app to test service name dns resolution
---
apiVersion: v1
kind: Pod
metadata:name: busyboxnamespace: default
spec:containers:- name: busyboximage: busybox:1.28imagePullPolicy: IfNotPresentcommand:- sleep- "3600"
通過kubectl create -f busybox.yaml命令即可完成創建。在該容器成功啟動后,通過 kubectl exec --nslookup 命令進行測試:
app]# kubectl create -f busybox.yaml
...
app]# kubectl exec -it busybox -- /bin/sh
/ # cat /etc/resolv.conf
nameserver 168.26.0.100
search default.svc.cluster.local. svc.cluster.local. cluster.local. vm.com
options ndots:5
/ ### 服務名DNS解析驗證【參考“集群驗證與總結”,創建svc】
如果某個 Service 屬于不同的命名空間,那么在進行 Service 查找時,需要補充命名空間的名稱,將其組合成完整的域名。下面以查找kube-dns 服務為例,將其所在命名空間“kube-system”補充在服務名之后,用“.”連接為“kube-dns.kube-system”即可查詢成功:
使用busybox:latest鏡像時解析需要全域名,使用busybox:1.28鏡像可以使用短域名。
]# kubectl exec busybox -- nslookup kube-dns.kube-system
Server: 168.26.0.100
Address 1: 168.26.0.100 kube-dns.kube-system.svc.cluster.localName: kube-dns.kube-system
Address 1: 168.26.0.100 kube-dns.kube-system.svc.cluster.local
如果僅使用kube-dns 進行查找,則會失敗:
]# kubectl exec busybox -- nslookup kube-dns
Server: 168.26.0.100
Address 1: 168.26.0.100 kube-dns.kube-system.svc.cluster.localnslookup: can't resolve 'kube-dns'
command terminated with exit code 1
六、Metrics Server
Metrics Server 的主要用途是配合Horizontal Pod Autoscaler與Vertical Pod Autoscaler來實現Kubernetes自動伸縮的功能,Metrics Server 具有如下幾個特點:
- 部署簡單,通過一個 YAML 文件可以在絕大多數系統上一鍵部署。
- 每隔15s搜集一次性能指標數據,可以實現Pod的快速自動伸縮控制。
- 輕量級,資源占用量很低,在每個 Node上只需要1m的CPU和 2MiB的內存。
- 可以支持多達 5000個Node的集群。
安裝部署很簡單,首先從官網下載 Metrics Server 的 YAML 配置文件:
wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
或者在瀏覽器直接輸入網址即可下載。
按需修改文件中的配置,其中增加啟動參數–kubelet-insecure-tls,表示在訪問 kubelet的 HTTPS 協議端口號時不驗證 TLS 證書。
...spec:containers:- args:- --cert-dir=/tmp- --secure-port=10250- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname- --kubelet-use-node-status-port- --metric-resolution=15s- --kubelet-insecure-tlsimage: registry.k8s.io/metrics-server/metrics-server:v0.7.2imagePullPolicy: IfNotPresent
...
然后,基于 YAML文件創建 Metrics Server,并等待 Pod 成功啟動。
# kubectl --namespace=kube-system create -f components.yaml
...
# kubectl --namespace=kube-system get pods -l k8s-app=metrics-server
NAME READY STATUS RESTARTS AGE
metrics-server-8467fcc7b7-nqrt4 1/1 Running 0 2m5s
查看 Metrics Server Pod 日志,確定運行正常。
# kubectl --namespace=kube-system logs metrics-server-
...
接下來,可以通過 kubectl top nodes 和 kubectl top pods 命令監控 Node 和 Pod 的 CPU、內存資源的使用情況:
app]# kubectl top nodes
NAME CPU(cores) CPU(%) MEMORY(bytes) MEMORY(%)
k8s31.vm.com 149m 7% 2265Mi 62%
k8s32.vm.com 101m 5% 1661Mi 46%
k8s33.vm.com 102m 5% 1595Mi 44%
app]# kubectl top pod -A
NAMESPACE NAME CPU(cores) MEMORY(bytes)
default busybox 0m 0Mi
default nginx-web-74lzn 0m 3Mi
default nginx-web-cwg8g 0m 3Mi
kube-system calico-kube-controllers-7bfdc5b57c-gkftm 5m 23Mi
kube-system calico-node-cmc58 38m 198Mi
kube-system calico-node-k9tf8 34m 200Mi
kube-system calico-node-wwd97 32m 199Mi
kube-system coredns-76b7578cff-l56sj 2m 16Mi
kube-system metrics-server-8467fcc7b7-nqrt4 5m 78Mi
? 啟動一個性能測試 Pod模擬大量使用系統資源,再次監控 Node 和 Pod 的性能指標數據,可以直觀地看到資源的使用情況:
# kubectl run testperf --image containerstack/alpine-stress -- stress --cpu 3 -- io 4 --vm 2 --vm-bytes 256M --timeout 3000s# kubectl get po# kubectl top nodes# kubectl top pods
? 上述測試表示,運行3個進程計算 sqrt(),運行4個進程執行 IO 寫磁盤操作,運行 2個進程執行分配內存的操作,每個進程分配 256MB內存,這個壓力測試過程持續 3000s。
? 幾個常用命令:
- kubectl top node ,可以直接指定 Node 或者 Pod 的名稱。
- kubectl top pod --sort-by=memory,實現排序功能,可以按照 CPU或者內存排序輸出。
- kubectl top pod --selector application=demo-app,通過 selector 標簽選擇器,選擇某些 Pod 進行查看。
? 也可以用 API方式訪問:
# kubectl get --raw /apis/metrics.k8s.io/v1beta1/nodes
七、使用 Dashboard 監控集群資源狀態和性能
? Kubermetes 的 Web UI網頁管理工具是 kubernetes-dashboard,可提供部署應用、資源對象管理、容器日志查詢、系統監控等常用的集群管理功能。為了在頁面上顯示系統資源的使用情況,需要部署 Metrics Server。可以使用 GitHub 倉庫提供的 YAML 文件快速部署kubernetes-dashboard。YAML文件下載:
## https://github.com/kubernetes/dashboard
# wget https://raw.githubusercontent.com/kubernetes/dashboard/refs/tags/v2.7.0/aio/deploy/recommended.yaml
? 或者使用瀏覽器打開https://github.com/kubernetes/dashboard/blob/v2.7.0/aio/deploy/recommended.yaml,然后復制內容。
? 為了方便訪問服務頁面,需要修改kubernetes-dashboard的Service 定義,可以改為NodePort 端口類型:
kind: Service
apiVersion: v1
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboardnamespace: kubernetes-dashboard
spec:type: NodePort # 設置NodePort 端口類型ports:- port: 443targetPort: 8443selector:k8s-app: kubernetes-dashboard
? 通過 kubectl apply 命令部署 Dashboard:
]# kubectl apply -f recommended.yaml
...
]# kubectl -n kubernetes-dashboard get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
dashboard-metrics-scraper ClusterIP 168.26.24.159 <none> 8000/TCP 7s
kubernetes-dashboard NodePort 168.26.220.179 <none> 443:32584/TCP 7s
? 服務啟動成功之后,就可以通過https://192.168.26.33:32584/訪間 Dashboard 的 Web 頁面了。
? 有多種方法訪問 kubernetes-dashboard,例如設置Service的NodePort 或者 kubectl forward 端口的方式。
? 首次訪問 Kubernetes Dashboard 頁面時需要登錄,如圖 所示。
?通過下面的命令,創建一個 Dashboard 登錄用的管理員賬號,授權集群管理角色,然后得到它的 Token,錄人上面的界面中即可登錄:
# cat dashboard-user.yaml
apiVersion: v1
kind: ServiceAccount
metadata:name: admin-usernamespace: kubernetes-dashboard---apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:name: admin-user
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: cluster-admin
subjects:- kind: ServiceAccountname: admin-usernamespace: kubernetes-dashboard
# kubectl apply -f dashboard-user.yaml
...
# kubectl -n kubernetes-dashboard create token admin-user
...
? 將 kubectl create token命令的輸出結果復制到登錄頁面,即可登錄 Dashboard 查看Kubernetes 集群的各種信息。其中在 Settings 菜單里可以設置語言、默認展示的命名空間等配置。首頁默認顯示命名空間 default中的工作負載信息,可以通過上方的下拉列表選擇不同的命名空間進行查看,也可以查看所有命名空間的Workload 信息,如圖所示。
在首頁上會顯示各種類型工作負載的數量統計,以及各種資源對象的列表,例如Daemonset、Deployment、Pod、Statefulset、Service 等。通過單擊左側的菜單項,可以過濾 Workloads、Service、Config and Storage、Cluster、CRD 等各類資源對象的列表和詳細信息。例如查看 Service 列表頁面,如圖所示。
八、集群驗證與總結
8.1 部署pod驗證
]# vi busybox.yaml
apiVersion: v1
kind: Pod
metadata:name: busyboxnamespace: default
spec:containers:- name: busyboximage: docker.io/library/busybox:1.28imagePullPolicy: IfNotPresentcommand:- sleep- "3600"
]# kubectl apply -f busybox.yaml
pod/busybox created
]# kubectl get pod
NAME READY STATUS RESTARTS AGE
busybox 1/1 Running 0 2s
8.2 部署service驗證
cat > nginx.yaml << "EOF"
---
apiVersion: v1
kind: ReplicationController
metadata:name: nginx-web
spec:replicas: 2selector:name: nginxtemplate:metadata:labels:name: nginxspec:containers:- name: nginximage: nginx:1.19.6imagePullPolicy: IfNotPresentports:- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:name: nginx-service-nodeport
spec:ports:- port: 80targetPort: 80nodePort: 30001protocol: TCPtype: NodePortselector:name: nginx
EOF
]# kubectl apply -f nginx.yaml
replicationcontroller/nginx-web created
service/nginx-service-nodeport created
]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox 1/1 Running 0 52m 10.26.25.193 k8s32.vm.com <none> <none>
nginx-web-74lzn 1/1 Running 0 8s 10.26.139.67 k8s33.vm.com <none> <none>
nginx-web-cwg8g 1/1 Running 0 8s 10.26.25.194 k8s32.vm.com <none> <none>
## 要拉取鏡像,需要等一會
]# kubectl get all
NAME READY STATUS RESTARTS AGE
pod/busybox 1/1 Running 0 53m
pod/nginx-web-74lzn 1/1 Running 0 33s
pod/nginx-web-cwg8g 1/1 Running 0 33sNAME DESIRED CURRENT READY AGE
replicationcontroller/nginx-web 2 2 2 33sNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 168.26.0.1 <none> 443/TCP 119m
service/nginx-service-nodeport NodePort 168.26.216.107 <none> 80:30001/TCP 33s
]# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 168.26.0.1 <none> 443/TCP 4d8h
nginx-service-nodeport NodePort 168.26.79.197 <none> 80:30001/TCP 79s
瀏覽器訪問:http://192.168.26.33:30001/
8.3 創建3個副本在不同的節點上
cat > nginx-deployment.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-deploymentlabels:app: nginx
spec:replicas: 3selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: nginximagePullPolicy: IfNotPresentports:- containerPort: 80EOF
]# kubectl apply -f nginx-deployment.yaml
deployment.apps/nginx-deployment created
]# kubectl get pod -owide |grep nginx-deployment
nginx-deployment-64598b8f46-fkwc9 1/1 Running 0 9s 10.26.179.194 k8s31.vm.com <none> <none>
nginx-deployment-64598b8f46-lbq6b 1/1 Running 0 9s 10.26.25.195 k8s32.vm.com <none> <none>
nginx-deployment-64598b8f46-qxwkb 1/1 Running 0 9s 10.26.139.68 k8s33.vm.com <none> <none>
]# kubectl delete -f nginx-deployment.yaml
8.4 用pod解析默認命名空間中的svc
使用busybox:latest鏡像時解析需要全域名,使用busybox:1.28鏡像可以使用短域名。
]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 168.26.0.1 <none> 443/TCP 168m
nginx-service-nodeport NodePort 168.26.216.107 <none> 80:30001/TCP 50m]# kubectl exec busybox -n default -- nslookup kubernetes.default.svc.cluster.local
Server: 168.26.0.100
Address: 168.26.0.100:53Name: kubernetes.default.svc.cluster.local
Address: 168.26.0.1]# kubectl exec busybox -n default -- nslookup nginx-service-nodeport.default.svc.cluster.local
Server: 168.26.0.100
Address: 168.26.0.100:53Name: nginx-service-nodeport.default.svc.cluster.local
Address: 168.26.216.107
## 使用busybox:1.28鏡像可以使用短域名
]# kubectl exec busybox -n default -- nslookup nginx-service-nodeport
Server: 168.26.0.100
Address 1: 168.26.0.100 kube-dns.kube-system.svc.cluster.localName: nginx-service-nodeport
Address 1: 168.26.216.107 nginx-service-nodeport.default.svc.cluster.local
可以看到,通過 DNS服務器168.26.0.100成功解析了nginx-service-nodeport
服務的 IP 地址168.26.216.107
。
8.5 測試跨命名空間是否可以解析
使用busybox:latest鏡像時解析需要全域名,使用busybox:1.28鏡像可以使用短域名。
]# kubectl get svc -A
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes ClusterIP 168.26.0.1 <none> 443/TCP 4h25m
default nginx-service-nodeport NodePort 168.26.216.107 <none> 80:30001/TCP 147m
kube-system kube-dns ClusterIP 168.26.0.100 <none> 53/UDP,53/TCP,9153/TCP 6m29s
kube-system metrics-server ClusterIP 168.26.107.166 <none> 443/TCP 132m
kubernetes-dashboard dashboard-metrics-scraper ClusterIP 168.26.24.159 <none> 8000/TCP 121m
kubernetes-dashboard kubernetes-dashboard NodePort 168.26.220.179 <none> 443:32584/TCP 121m
]# kubectl exec busybox -n default -- nslookup kube-dns.kube-system.svc.cluster.local
Server: 168.26.0.100
Address: 168.26.0.100:53Name: kube-dns.kube-system.svc.cluster.local
Address: 168.26.0.100## 使用busybox:1.28鏡像可以使用短域名
]# kubectl exec busybox -n default -- nslookup kube-dns.kube-system
Server: 168.26.0.100
Address 1: 168.26.0.100 kube-dns.kube-system.svc.cluster.localName: kube-dns.kube-system
Address 1: 168.26.0.100 kube-dns.kube-system.svc.cluster.local
8.6 每個節點都必須要能訪問Kubernetes的kubernetes svc 443和kube-dns的svc 53
]# kubectl get svc -A
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes ClusterIP 168.26.0.1 <none> 443/TCP 122m
default nginx-service-nodeport NodePort 168.26.216.107 <none> 80:30001/TCP 3m48s
kube-system kube-dns ClusterIP 168.26.0.100 <none> 53/UDP,53/TCP,9153/TCP 36m~]# telnet 168.26.0.1 443
Trying 168.26.0.1...
Connected to 168.26.0.1.
Escape character is '^]'.
Connection closed by foreign host.~]# telnet 168.26.0.100 53
Trying 168.26.0.100...
Connected to 168.26.0.100.
Escape character is '^]'.
Connection closed by foreign host.
8.7 Pod和其它主機及Pod之間能通
~]# kubectl get po -owide -A
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
default busybox 1/1 Running 0 59m 10.26.25.193 k8s32.vm.com <none> <none>
default nginx-web-74lzn 1/1 Running 0 6m42s 10.26.139.67 k8s33.vm.com <none> <none>
default nginx-web-cwg8g 1/1 Running 0 6m42s 10.26.25.194 k8s32.vm.com <none> <none>
kube-system calico-kube-controllers-7bfdc5b57c-gkftm 1/1 Running 1 (51m ago) 73m 10.26.179.193 k8s31.vm.com <none> <none>
kube-system calico-node-cmc58 1/1 Running 0 73m 192.168.26.31 k8s31.vm.com <none> <none>
kube-system calico-node-k9tf8 1/1 Running 0 73m 192.168.26.33 k8s33.vm.com <none> <none>
kube-system calico-node-wwd97 1/1 Running 0 73m 192.168.26.32 k8s32.vm.com <none> <none>
kube-system coredns-76b7578cff-l56sj 1/1 Running 0 38m 10.26.139.66 k8s33.vm.com <none> <none>
進入busybox ping其他節點上的pod。可以連通證明這個pod是可以跨命名空間和跨主機通信的。
]# kubectl exec -ti busybox -- sh
## 主機k8s31上的pod ping主機k8s33(POD - 跨主機)
/ # ping 192.168.26.33 -c 3
PING 192.168.26.33 (192.168.26.33): 56 data bytes
64 bytes from 192.168.26.33: seq=0 ttl=63 time=1.583 ms
64 bytes from 192.168.26.33: seq=1 ttl=63 time=0.260 ms
64 bytes from 192.168.26.33: seq=2 ttl=63 time=0.372 ms--- 192.168.26.33 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.260/0.738/1.583 ms## 主機k8s31上的pod ping主機k8s33節點上的pod(跨主機跨命名空間)
/ # ping 10.26.139.67 -c 3
/ # ping 10.26.139.67 -c 3
PING 10.26.139.67 (10.26.139.67): 56 data bytes
64 bytes from 10.26.139.67: seq=0 ttl=62 time=0.712 ms
64 bytes from 10.26.139.67: seq=1 ttl=62 time=0.442 ms
64 bytes from 10.26.139.67: seq=2 ttl=62 time=0.368 ms--- 10.26.139.67 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.368/0.507/0.712 ms## 從主機k8s31節點ping k8s32上的pod(跨主機 - POD)
k8s31 app]# ping 10.26.25.194 -c 3
PING 10.26.25.194 (10.26.25.194) 56(84) bytes of data.
64 bytes from 10.26.25.194: icmp_seq=1 ttl=63 time=0.875 ms
64 bytes from 10.26.25.194: icmp_seq=2 ttl=63 time=0.344 ms
64 bytes from 10.26.25.194: icmp_seq=3 ttl=63 time=0.287 ms--- 10.26.25.194 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2080ms
rtt min/avg/max/mdev = 0.287/0.502/0.875/0.264 ms
至此,成功完成以二進制方式部署Kubernetes1.332 + docker28.3.1高可用集群。
8.8 總結
本次實驗驗證CentOS8.5+Kubernetes1.32.5+Docker28.3.1高可用集群二進制部署
- 使用新的軟件版本進行組合時,往往會出現一些新的問題,需要花費大量時間進行測試驗證。在沿用以往方案及經驗進行試驗時,一旦遇到新問題,最快的解決方案就是用較舊的版本進行替換及驗證,而不是用SE或AI。
- 總之,關于如何在專業領域內提升,有個著名的“10000 小時定律”,簡單來說要成為某個領域頂尖的專業人才,需要10000 小時持續不斷的練習,例如小提琴、足球、國際象棋、圍棋等領域,無一例外都遵循這個定律,而技術的成長也基本遵循這個定律。技術成長其實最關鍵的還是對技術的熱情以及持續不斷地投入,包括學習、實踐、思考和總結等。