二進制部署CentOS8.5+Kubernetes1.33.2+Docker28.3.1高可用集群

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 Server6443
Controller Manager10257
Scheduler10259
kubelet10250、10255(只讀端口號)
etcd2379(供客戶端訪問)、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
HostnameHost IPDocker IPRole
k8s31.vm.com192.168.26.3110.26.31.1/24master&worker、etcd、docker
k8s32.vm.com192.168.26.3210.26.32.1/24master&worker、etcd、docker
k8s33.vm.com192.168.26.3310.26.33.1/24master&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.basehttps://github.com/kubernetes/kubernetes/blob/v1.33.2/cluster/addons/dns/coredns/coredns.yaml.basekubectl部署
yaml資源components.yaml(metrics server)https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.7.2/components.yamlkubectl部署
鏡像metrics-server:v0.7.2registry.aliyuncs.com/google_containers/metrics-server:v0.7.2部署pod…
鏡像coredns:v1.12.0registry.aliyuncs.com/google_containers/coredns:v1.12.0部署pod…
鏡像pause:3.10registry.aliyuncs.com/google_containers/pause:3.10部署pod…

2.3 網絡規劃

網絡名稱網段備注
Node網絡192.168.26.0/24Node IP,Node節點的IP地址,即物理機(宿主機)的網卡地址。
Service網絡168.26.0.0/16Cluster IP,也可叫Service IP,Service的IP地址。service-cluster-ip-range定義Service IP地址范圍的參數。
Pod網絡10.26.0.0/16Pod 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 小時持續不斷的練習,例如小提琴、足球、國際象棋、圍棋等領域,無一例外都遵循這個定律,而技術的成長也基本遵循這個定律。技術成長其實最關鍵的還是對技術的熱情以及持續不斷地投入,包括學習、實踐、思考和總結等。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/88381.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/88381.shtml
英文地址,請注明出處:http://en.pswp.cn/web/88381.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

127. Java 泛型 - 泛型類與子類型

文章目錄127. Java 泛型 - 泛型類與子類型1. 泛型類和接口的子類型化示例&#xff1a;ArrayList 和 List2. 自定義泛型接口的子類型化示例&#xff1a;泛型接口的子類型解釋3. 泛型類和接口的類型參數4. 總結127. Java 泛型 - 泛型類與子類型 1. 泛型類和接口的子類型化 在 J…

內網服務器怎么設置公網遠程訪問? windows桌面連接和Linux自帶SSH外網異地跨網用完整步驟教程

沒有公網IP的本地主機跨網訪問是經常需要用到的網絡場景。要設置內網服務器在公網進行異地遠程訪問&#xff0c;需依次完成確保網絡連接正常、配置防火墻、啟用遠程訪問服務、和利用類似nat123內網映射外網打通等一系列步驟&#xff0c;以保障不同內網的遠程訪問的順利進行。一…

數據提取之bs4(BeautifuSoup4)模塊與Css選擇器

BeautifuSoup4from bs4 import BeautifulSoup創建對象 <class bs4.BeautifulSoup>soup BeautifulSoup(源碼, 解析器)bs4標簽種類&#xff08;1&#xff09;tag: 標簽print(soup.title, type(soup.title))&#xff08;2&#xff09;獲取標簽里面的文本內容, 可導航的字符…

CPP中的List

一.list的介紹&#xff1a;1.list是可以在常數范圍內在任意位置進行插入和刪除的序列式容器&#xff0c;并且該容器可以前后雙向迭代。2.list的底層是雙向鏈表結構&#xff0c;帶有哨兵位的頭結點 。3. list與forward_list非常相似&#xff1a;最主要的不同在于forward_list是單…

Ntfs!LfsUpdateLfcbFromRestart函數分析之Ntfs!LfsFindOldestClientLsn

第0部分&#xff1a;//// Find the oldest client Lsn. Use the last flushed Lsn as a starting point.//Lfcb->OldestLsn Lfcb->LastFlushedLsn;LfsFindOldestClientLsn( RestartArea,Add2Ptr( RestartArea, Lfcb->ClientArrayOffset, PLFS_CLIENT_RECORD ),&…

「日拱一碼」021 機器學習——特征工程

目錄 特征選擇 過濾法&#xff08;Filter Methods&#xff09; 方差選擇法 相關系數法 卡方檢驗 包裹法&#xff08;Wrapper Methods&#xff09; 遞歸特征消除&#xff08;RFE&#xff09; 嵌入法&#xff08;Embedded Methods&#xff09; L1正則化&#xff08;Lasso…

k8s:安裝 Helm 私有倉庫ChartMuseum、helm-push插件并上傳、安裝Zookeeper

ChartMuseum 是 Kubernetes 生態中用于存儲、管理和發布 Helm Charts 的開源系統&#xff0c;主要用于擴展 Helm 包管理器的功能 核心功能 ?集中存儲?&#xff1a;提供中央化倉庫存儲Charts&#xff0c;支持版本管理和權限控制。 ? ?跨集群部署?&#xff1a;支持多集群環境…

C++編程學習(第二天)

1、求a和b兩個數之和。#include <iostream> using namespace std;int main() {int a, b, sum; //定義變量a、b、sumcout << "請輸入第一個數字a: "; //打印需要顯示的字符串cin >> a; // >&…

毫米波雷達守護銀發安全:七彩喜跌倒檢測儀重構居家養老防線

在老齡化加速與獨居老人數量攀升的背景下&#xff0c;跌倒已成為威脅老年人生命安全的“隱形殺手”。七彩喜跌倒檢測儀以毫米波雷達技術為核心&#xff0c;通過“非接觸式監測智能預警”重塑居家安全防護體系&#xff0c;為銀發群體構建起全天候、無感化的數字守護網。技術突破…

面試復盤:節流中第二次觸發的事件?答錯補課

面試復盤&#xff1a;節流中第二次觸發的事件&#xff1f;答錯補課 背景描述 今天面試時被問到一個看似基礎但暗藏玄機的問題&#xff1a;“節流&#xff08;Throttle&#xff09;函數中&#xff0c;第二次觸發的那一幀事件是否會被丟掉&#xff1f;” 我基于對經典節流實現的…

Spark偽分布式集群搭建(Ubuntu系統)

環境準備 系統要求&#xff1a;Ubuntu 20.04/22.04 LTS 軟件版本&#xff1a; Hadoop 3.3.5 JDK 8 Spark-3.5.6-bin-hadoop3 硬件要求&#xff1a;至少4GB內存&#xff0c;20GB磁盤空間 以下是基于Ubuntu系統的Spark偽分布式集群搭建全流程。以Spark 3.5.6 Hadoop 3.3.…

【快手】數據挖掘面試題0001:查找連續三天登錄的用戶

文章大綱一、測試數據構建二、自連接方案三、窗口函數方案一張用戶表&#xff0c;uer_id&#xff0c;signin_date&#xff0c;大概是這么幾項&#xff0c;查找連續三天登錄的用戶。 比如說&#xff0c;1,2兩天登錄不是連續三天&#xff0c;456登錄為連續三天登錄&#xff0c;56…

簡說scp命令

簡單介紹 scp的全稱是&#xff1a;Secure Copy Protocol&#xff08;安全復制協議&#xff09;&#xff0c;是Linux中用于在網絡中安全傳輸文件的命令行工具。它基于SSH協議&#xff0c;用于在本地服務器和遠程服務器之間&#xff0c;或者兩臺遠程服務器之間復制文件或目錄。 s…

自動化測試解決方案Parasoft SOAtest無腳本UI測試實踐指南

傳統UI自動化測試常面臨技術門檻高、維護成本大、穩定性差等挑戰。尤其在頁面頻繁變更時&#xff0c;測試腳本的更新和維護會顯著降低測試效率。 自動化測試解決方案Parasoft SOAtest通過可視化操作和智能元素定位技術&#xff0c;無需編寫代碼&#xff0c;讓測試人員能夠像真…

vscode配置頭文件和編譯器

在 VS Code 中配置編譯器和頭文件路徑需要修改兩個核心文件&#xff1a;c_cpp_properties.json&#xff08;用于智能提示&#xff09;和 tasks.json&#xff08;用于構建&#xff09;。以下是詳細步驟&#xff1a; —### 1. 配置智能提示和頭文件路徑 (c_cpp_properties.json)作…

HTML+JS+CSS制作一個數獨游戲

閑來無事&#xff0c;用HTMLJSCSS制作了一個數獨游戲消遣。其實主要是自己做題的時候用筆畫刪除數字太容易出錯&#xff0c;所以想搞一個程序稍微輔助一下。通過制作這個程序&#xff0c;反而提高了手工做題的水平&#xff0c;至少學會了記錄步數以便于回退。 20250710功能更新…

嵌入式硬件中電容的基本原理與實現詳解02

我們今天重點討論點知識點如下: 1.各種種類的電容優缺點對比講解 2.電容的標稱值介紹 3.電容的單位介紹 4.常見的電壓信號有哪些? 5. 電容的耐壓值講解 6.電容的容值有哪些? 7.12pF、15pF 電容常用在什么場合? 8. 振蕩電路中使用的電容常常需要使用什么材質的電容? 9.100n…

Python訓練打卡DAY46

DAY46&#xff1a;通道注意力&#xff08;SE注意力&#xff09; 恩師浙大疏錦行 知識點&#xff1a; 不同CNN層的特征圖&#xff1a;不同通道的特征圖什么是注意力&#xff1a;注意力家族&#xff0c;類似于動物園&#xff0c;都是不同的模塊&#xff0c;好不好試了才知道。通…

fastadmin_php專項

1.時間的判斷,還有就是在php這邊如何去拿前端html元素上面的值input($row.borrowtime);// 創建兩個 DateTime 對象$row_expecttime new \DateTime(input($row.borrowtime));$par_expecttime new \DateTime( $params[expecttime]); // // 計算兩個日期之間的差異 // …

如何在MySQL中選擇使用InnoDB還是MyISAM引擎?

在 MySQL 中選擇 InnoDB 還是 MyISAM 存儲引擎時&#xff0c;需根據應用場景的需求權衡功能、性能和數據完整性。以下是具體的選擇指南&#xff1a; 1. 優先考慮事務和外鍵需求必須使用 InnoDB&#xff1a; 若應用需要 事務支持&#xff08;如金融轉賬、訂單處理&#xff09;或…