当前位置: 首页 > news >正文

二进制部署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.lryc.cn/news/584467.html

相关文章:

  • pdf_copy.ahk
  • 醋酸镨:闪亮的稀土宝藏,掀开科技应用新篇章
  • 软考(软件设计师)计算机网络-物理层,数据链路层
  • Android 如何阻止应用自升级
  • 如何使用python实现多个word文档格式进行修改
  • Android 15 Settings 搜索框:引入关键字过滤功能
  • uni-app X APP在线升级 解决【uni-upgrade-center-app】未配置uni-upgrade-center 问题
  • 20250710解决KickPi的K7的SDK编译异常:rk3576-android14.0-25250704.tar.gz【降低BUILD_JOBS】
  • 独立服务器选择Rocky Linux还是CentOS
  • 征程 6M 部署 Omnidet 感知模型
  • 微信小程序101~110
  • Kettle导入Excel文件进数据库时,数值发生错误的一种原因
  • 【大模型推理论文阅读】Enhancing Latent Computation in Transformerswith Latent Tokens
  • 【React】MQTT + useEventBus 实现MQTT长连接以及消息分发
  • Xavier上安装RTSP服务端教程
  • React封装过哪些组件-下拉选择器和弹窗表单
  • 虚拟项目[3D物体测量]
  • SpringBoot整合腾讯云新一代行为验证码
  • 【Note】Linux Kernel 实时技术深入:详解 PREEMPT_RT 与 Xenomai
  • 【TCP/IP】12. 文件传输协议
  • 堆的应用(讲解超详细)
  • 【AI大模型】LLM模型架构深度解析:BERT vs. GPT vs. T5
  • 基础 IO
  • 常见射频电路板工艺流程
  • 如何在VMware里的飞牛OS访问主机里面图片文件夹
  • C语言易错点整理(一)
  • 苍穹外卖—day1
  • Redis中BigKey的隐患
  • CMake指令:add_custom_command和add_custom_target详解
  • SYM32第二十天 ESP8266-01S和电脑实现串口通信(3)