本篇知识点开始,为各位读者介绍本系列知识点最后一个大内容Kubernetes,业内简称K8s,从能力上来讲它其实是一个虚拟化编排工具,无论是容器还是虚拟机都可以编排,但由于业内使用习惯,出于成本和法律风险原因常常配合Docker使用,成本指容器比虚拟机使用更经济,更容易超卖,法律风险指基于源码二次开发容易处理不当,相比之下docker用的Apache 2.0开源协议是可操作性最高的,而反观kvm他用的是GPL协议,该协议要求软件发布时如果原GPL协议源码不可被分离,则整个项目都必须免费开源,否则许可失效原先对此作出的修改开发都被视为著作权侵权,先不说像国内容器编排常见的容器直连插件这种比较底层的更改,就成果商用这一项就毕了,因此由于常见就是配合docker所以k8s也被称为容器编排工具。
不过,各位读者可以看两篇文献 https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.20.md#deprecation 、https://kubernetes.io/blog/2022/02/17/dockershim-faq/,就可以发现,k8s在1.20开始声明不再默认支持docker,并在 1.24 删除了兼容docker的核心模块 dockershim ,不过有个叫 cri-dockerd 的社区版插件可以代替原来的官方代码让 k8s 继续兼容docker,这个插件是社区和 docker 官方合作的将原来的 dockershim 维护在外部,从而更加倾向于标准CRI接口。k8s官方自身开始支持containerd等更加符合CRI标准的运行时。就国内而言,基本还是k8s + docker的组合,即使需要安装社区插件,本质原因大家懂的都懂,1.24以后才彻底删除支持,在此之前体系已经很成熟,各大厂商基于源码开发了很多扩展的东西,真要迁移成本很大了,要各位读者自己坐在决策位置上,你也不敢那自己的前途去押宝,因此本系列知识点同样基于docker部署。其实 docker 它底层也是containerd,k8s 弃用的也只是作为中间商的 docker 应用层,商用环境稳健大于性能,因此普遍不激进的更近变动而已,使用插件维持现状
容器编排工具也不是一上来就是K8s,它也经历了一系列的演化流程。前面介绍的Docker,除了它本身,它的生态圈中还有 Compose、Swarm、Machine。在介绍私有化部署时顺带介绍了Compose,其他两个由于现在主流都是用K8s所有本系列知识点不涉及,有兴趣的可以看看其他资料。本文只串联一次容器编排工具的发展史,最开始是docker-machine主要用于准备docker host(Docker主机),简单易用但功能有限,是早期的Docker引擎管理工具,2021年开始已弃用,官方建议使用docker desktop(一个收费软件)替代。docker-compose和docker-machine是同时期的产物,通过单一命令即可创建并启动单节点上单一完整服务的容器编排工具,仅适用于单机环境,无法管理多主机集群,因其核心的、不可替代的本地编排价值,一直活跃至今。docker-swarm和前面两个是同时期产品,也就是2014年,当时并称运维三剑客,它的作用是把多个 Docker 主机"伪装"成一个巨大的虚拟 Docker 主机,采用声明式服务模型,通过YAML文件定义应用状态,服务规模可扩大可缩小,保持期望状态,支持服务发现、负载均衡、滚动更新等,Swarm 在2016-2017年间和 Kubernetes 激烈竞争,2017年,Docker 公司在自己企业版里内置了 Kubernetes,标志着"编排之争"落下帷幕。不过 Swarm 依然活着,也有市场占比,但是非常小,现在作为 Docker 内置的集群功能,适合中小规模、追求简单易用的场景。K8s全球75%企业采用,无替代方案。比Docker Swarm和Kubernetes还要早的是Apache Mesos + Marathon编排框架,它兼容Hadoop、Kafka、Spark等大数据框架,但是系统复杂,学习困难使用独立API接口,2019年被Twitter弃用
Kubernetes采用有中心节点的分布式架构,管理节点(Master)和工作节点(Worker/Node),管理节点接收并处理所有用户请求、管理集群状态和调度决策、确保应用高可用(自动处理节点故障),工作节点实际运行容器化应用、接收并执行Master节点指令、上报节点状态和资源使用情况
管理节点有四个核心组件,组件本身可运行在任意节点,但通常集中部署在一台主机上且不运行用户容器,各组件通过etcd共享数据,形成完整的管理体系
kube-apiserver:集群出入口,所有资源请求/操作都通过其提供的接口进行,类似OpenStack中的CON storm组件
kube-controller-manager:管理集群中的控制器(后台线程),相当于企业中的"总经理"管理各小组长
kube-scheduler:监控未调度的Pod请求,为Pod选择运行节点
etcd:集群默认存储系统,保存所有集群数据(API数据、调度数据等)
工作节点的核心组件有三个
kubelet:管理Pod生命周期(创建/销毁pod),负责存储卷和网络管理
kube-proxy:通过维护iptables/ipvs规则实现service访问,解决pod IP变化问题(开源版本下建议通过service而非直接访问pod IP)
container runtime:支持docker/containerd/Rkt等多种运行时,负责镜像管理和容器实际运行
除此之外,Kubernetes还有增强集群功能的附件,非必需但能丰富使用体验
CoreDNS/kube-dns:为集群提供DNS服务(关键服务)
Ingress Controller:提供集群外部访问入口(突破"铜墙铁壁")
Heapster/Metrics-server:集群资源监控(可配合Prometheus使用)
Dashboard:提供GUI管理界面
Fluentd-elasticsearch:集群日志采集存储方案
Kubernetes提供了四种方式本地化部署方式。至于公有云部署方式那就多了,像阿里云ACK、华为云CCE、腾讯云EKS这种就是买服务了运维主力不需要用户太多的操心
1、kubeadm :Kubernetes官方支持的工具,提供创建集群的"快速路径"最佳实践,只关注集群引导(bootstrapping),不关心机器配置,不包含插件安装(如仪表盘、监控方案等),可部署最小化可行性集群(包含master和worker节点),适合测试/学习环境,也可用于生产环境,初始化速度快(约1分钟),节点加入仅需十几秒。官方文档https://kubernetes.io/docs/reference/setup-tools/kubeadm/
2、minikube :官方推荐的本地单节点集群部署工具,功能有限,不适合复杂场景,仅用于测试/学习目的,不支持生产环境使用,可快速部署(单主机),且跨平台支持(Linux/Mac/Windows)
3、二进制部署方式:纯手动部署,准备工作多,但维护和故障排查简单,资源占用少(APIServer等组件占用系统资源少),适合生产环境
4、国内第三方部署工具:RKE(基于Docker的快速部署工具,通过配置文件快速完成集群部署,支持节点动态添加/删除)、KubeKey(基于Go语言开发,底层使用kubeadm并行安装,支持在线或离线高可用集群一键部署),Kubeasz(基于二进制方式+Ansible实现自动化,支持分步安装组件,提供集群管理功能(备份恢复等))
通常最基本的具备kubeadm 、二进制部署这两种方式,就可以了,其他的要是还有精力就当扩展去了解即可。本文下面使用 kubeadm 带各位读者部署一套学习以及未来测试环境用的K8s集群
本次测试集群,使用CentOS 7系统,共三台节点采用1个master节点+2个worker节点的部署方案,注意后续自己部署时,每台主机的主机名必须唯一且不同
master节点
CPU:4核(最低不能低于2核)
内存:8GB(建议不低于3-4GB)
硬盘:50GB
主机名:master01
worker节点配置:
CPU:4核
内存:8GB
硬盘:50GB
主机名:worker01和worker02
第一步:部署环境准备
首先所有主机的IP配置与实际使用的网段一致,比如使用VMware虚拟机保持NAT或者桥接的策略即可,不要在服务器上自己自定义子网,配置文件:/etc/sysconfig/network-scripts/ifcfg-ens33,
bash
BOOTPROTO="none"或BOOTPROTO="static"(禁用DHCP)
IPADDR="192.168.239.70"(设置静态IP)
PREFIX="24"(等同于255.255.255.0)
GATEWAY="192.168.239.2"(默认网关)
DNS1="114.114.114.114"(DNS服务器)
ONBOOT="yes"(开机自动启用网卡)
所有集群主机均需添加主机名与IP地址的映射关系,配置文件:/etc/hosts
bash
192.168.239.70 master01.k8s.com
192.168.239.71 worker01.k8s.com
192.168.239.72 worker02.k8s.com
所有主机关闭防火墙配置服务,执行如下命令
bash
停止服务:systemctl stop firewalld
禁用自启:systemctl disable firewalld
所有主机关闭SELinux,/etc/selinux/config
bash
# 设置为禁用
SELINUX = disabled
#或者执行非交互式命令
sed -ri 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
所有主机时间需要同步 -》https://blog.csdn.net/dudadudadd/article/details/110947177,或者最小化安装 ntpdate,同步阿里云
bash
yum install ntpdate
ntpdate time1.aliyun.com
# 后续同步使用 crontab -e
crontab -e
0 * * * * /usr/sbin/ntpdate time1.aliyun.com
# 或者你有自己的批量执行命令脚本
(crontab -l 2>/dev/null; echo "0 * * * * /usr/sbin/ntpdate time1.aliyun.com") | crontab -
# 也可以批量删除
crontab -l | grep -v "time1.aliyun.com" | crontab -
所有主机升级系统内核,K8s有很多插件,需要的内核版本比较高,并且新内核的一些软件旧内核可能没有
bash
# 首先看一下当前内核,centos 7 默认内核是3.x
uname -r
24年底所有的在线 os 7 系统可用源基本都关了,因此不能在线安装,只能手动编译内核,目前能下载到的只有清华源,所以去下载源码包编译,下载个差不多的就行本文用5.6.15
https://mirrors.tuna.tsinghua.edu.cn/kernel/v5.x/linux-5.6.15.tar.gz
# 安装编译依赖
yum groupinstall -y "Development Tools"
yum install -y ncurses-devel bison flex elfutils-libelf-devel openssl-devel \
bc rpm-build redhat-rpm-config asciidoc hmaccalc perl-ExtUtils-Embed \
pesign xmlto audit-libs-devel binutils-devel elfutils-devel \
newt-devel numactl-devel pciutils-devel python-devel zlib-devel \
gcc gcc-c++ make perl diffutils gettext
# 编译并安装
tar -zxf linux-5.6.15.tar.gz
cd linux-5.6.15
# 开始编译,会出现巨多的选项,这些是内核微调选项,按住回车别松手,一路默认直到出现 gcc 开始编译的日志
make -j$(nproc)
# 编译完成先安装内核模块
make modules_install
# 再安装内核
make install
所有主机设置GRUB引导,从而设置新安装内核为默认启动项
bash
# 查看当前有启动项
awk -F\' '$1=="menuentry " {print i++ " : " $2}' /boot/grub2/grub.cfg
# 预期安装上面的内核后,它应当在第一个,所以设置默认启动第 0 位的内核
grub2-set-default 0
# 重新生成内核引导配置文件,必须重新生成
grub2-mkconfig -o /boot/grub2/grub.cfg
重启所有节点
bash
reboot
# 重启后确定内核版本
uname -r
# 对于旧的内核,比如自带的3.x可以直接删掉了
[root@master01 ~]# rpm -qa | grep kernel
kernel-3.10.0-1160.71.1.el7.x86_64
kernel-debug-devel-3.10.0-1160.119.1.el7.x86_64
kernel-tools-3.10.0-1160.71.1.el7.x86_64
kernel-3.10.0-1160.119.1.el7.x86_64
kernel-tools-libs-3.10.0-1160.71.1.el7.x86_64
kernel-headers-3.10.0-1160.119.1.el7.x86_64
#删除后刷新启动项
grub2-mkconfig -o /boot/grub2/grub.cfg
# 如果你未来要更新这个手动编译升级的内核,先去更新你的新内核,旧内核需要手动删除如下的文件列表
rm -f /boot/vmlinuz-5.6.15
rm -f /boot/initramfs-5.6.15.img
rm -f /boot/System.map-5.6.15
rm -rf /lib/modules/5.6.15
所有节点,修改系统配置文件,让系统自身拥有转发能力和网桥过滤,就和前面知识点KVM同一个操作,只不过多了个网桥流量进入防火墙过滤。按照官方建议,新建/etc/sysctl.d/k8s.conf文件写入如下配置。和直接修改/etc/sysctl.conf的区别在于/etc/sysctl.conf是传统的配置方式,不过同配置项它的优先级最低,且不方便管理
bash
#让原本在OSI模型第二层数据链路层的网桥数据,也进入第三层网络层的防火墙
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
#启用IPv4转发
net.ipv4.ip_forward = 1
#禁用swap分区
vm.swappiness = 0
网桥过滤,需要加载一个模块,所有主机执行后加入持久化
bash
# 加载模块,这个 -- 可以不写,他是因为有些模块名称里面有 - ,所以 -- 是modprobe 命令的一个参数告诉它参数的识别方式
modprobe -- br_netfilter
# 查看结果
lsmod | grep br_netfilter
# 生成配置文件持久化
echo "br_netfilter" | tee /etc/modules-load.d/k8s.conf
随后刷新内核配置
bash
sysctl -p /etc/sysctl.d/k8s.conf
所有主机安装ipset及ipvsadm,IPSET是一个IP地址集合工具,用来优化防火墙配置时的IP列表可能很多或者很长的问题,IPVS是内核级别的服务代理功能,你可以理解为它是一个内核自带的Nginx,但它比Nginx强大很多,K8s使用它来完成内部转发这类防火墙功能,安装ipvsadm工具主要用于通过命令行查看和管理IPVS功能
bash
yum -y install ipset ipvsadm
随后开始配置IPVS,首先创建 /etc/sysconfig/modules/ipvs.modules 文件,用来系统启动时自动调用,加载IPVS需要的模块,它本质是一个脚本,所以不放在/etc/modules-load.d下面
bash
cat > /etc/sysconfig/modules/ipvs.modules << 'EOF'
#!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack
EOF
ip_vs:基础模块
ip_vs_rr:轮询算法模块
ip_vs_wrr:加权轮询算法模块
ip_vs_sh:哈希算法模块
nf_conntrack:连接跟踪模块
第一次先手动执行一次
bash
chmod 755 /etc/sysconfig/modules/ipvs.modules
bash /etc/sysconfig/modules/ipvs.modules
lsmod | grep -e ip_vs -e nf_conntrack
现在检查所有节点是否有交换分区,如果有官方建议关掉
bash
# 临时工关闭
swapoff -a
# 注释调用/etc/fstab 文件中的Swap分区即可后续也不再启用
再次重启所有节点
bash
reboot
# 验证内核版本
uname -r
# 验证模块
lsmod | grep -e ip_vs -e nf_conntrack -e br_netfilter
# 验证内核参数
sysctl -a | grep -e net.bridge.bridge-nf-call -e net.ipv4.ip_forward -e vm.swappiness
所有节点 SSH 互信 -》https://blog.csdn.net/dudadudadd/article/details/117816179
同时取消SSH显示输入yes -》 https://blog.csdn.net/dudadudadd/article/details/117899463
到此 K8s 的安装前置准备完成
第二步:所有节点部署 docker -》https://blog.csdn.net/dudadudadd/article/details/158845838 ,务必确保docker使用20.10+版本,本文使用26.1.4。由于要和 k8s 一起使用,需要在配置文件下添加一行
bash
vi /etc/docker/daemon.json
追加:
"exec-opts": ["native.cgroupdriver=systemd"]
systemctl daemon-reload
systemctl restart docker
第三步:所有节点安装 cri-dockerd 接口服务。先在master01上安装,其他节点同步文件就行
bash
# 先确定系统是那个架构,本文部署环境是 x86_64
uname -m
# 随后去下载 0.3.7 的,注意不要下错架构,x86 下载amd的就行
https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.7/cri-dockerd-0.3.7.amd64.tgz
# 它就是一条二进制命令,解压后,放入系统 bin 路径下
tar -zxf cri-dockerd-0.3.7.amd64.tgz
mv cri-dockerd/cri-dockerd /usr/local/bin/
chmod +x /usr/local/bin/cri-dockerd
cri-dockerd --version
创建 systemd 服务文件,让系统能识别到 cri-dockerd 服务,文件内容不用改直接复制即可
bash
vi /etc/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
[Service]
Type=notify
ExecStart=/usr/local/bin/cri-dockerd --pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.9 --network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir=/opt/cni/bin --container-runtime-endpoint=unix:///var/run/cri-dockerd.sock --cri-dockerd-root-directory=/var/lib/dockershim --docker-endpoint=unix:///var/run/docker.sock --cri-dockerd-root-directory=/var/lib/docker
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
StartLimitBurst=3
StartLimitInterval=60s
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
Delegate=yes
KillMode=process
[Install]
WantedBy=multi-user.target
bash
vi /etc/systemd/system/cri-dockerd.socket
[Unit]
Description=CRI Docker Socket for the API
PartOf=cri-docker.service
[Socket]
ListenStream=/var/run/cri-dockerd.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker
[Install]
WantedBy=sockets.target
启动服务。服务启动没有问题,则另外两台节点同步二进制命令和配置,启动服务即可
bash
systemctl daemon-reload
systemctl start cri-dockerd
systemctl status cri-dockerd
systemctl enable cri-dockerd.service
第四步:现在开始正式安装 k8s 。先去github上看好你自己要安装的 k8s 版本 https://github.com/kubernetes/kubernetes/releases,一定要是 1.24+ 的,本文安装1.28.0。在未来无论工作还是自己使用,尽量不要选择 1.20 - 1.24 之间的版本,要不你就去安装低版本默认支持docker,要不就安装新版配合插件
所有节点准备k8s的国内镜像yum,一般是阿里云,新建/etc/yum.repos.d/kubernetes.repo文件
bash
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
enabled=1
刷新yum,正常会出现 kubernetes 仓库
bash
yum clean all
yum makecache
yum repolist
开始安装 k8s 服务,先查询yum中是否有你需要的版本,和文本同版本就不用看了,已经确定有了
bash
yum --showduplicates list kubeadm | grep 1.28.0
随后 master01 节点上安装核心服务
bash
yum install -y kubelet-1.28.0-0 kubeadm-1.28.0-0 kubectl-1.28.0-0
另外两台节点上安装除客户端外的核心服务
bash
yum install -y kubelet-1.28.0-0 kubeadm-1.28.0-0
安装完成后,所有节点修改配置文件/etc/sysconfig/kubelet,禁用 k8s 对交换分区的检查,因为上面已经关了,没必要再让它执行。以及指定 cri-dockerd 服务数据路径和启动方式(和docker统一)
bash
KUBELET_EXTRA_ARGS="--fail-swap-on=false --container-runtime-endpoint=unix:///var/run/cri-dockerd.sock --cgroup-driver=systemd"
确保 k8s 和 docker 是开启自启的
bash
systemctl enable kubelet docker
第五步:在主节点 master01.k8s.com 上操作集群主节点的初始化
bash
kubeadm init --kubernetes-version=v1.28.0 --pod-network-cidr=10.10.0.0/16 --service-cidr=10.11.0.0/16 --ignore-preflight-errors=Swap,SystemVerification --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers --cri-socket unix:///var/run/cri-dockerd.sock --apiserver-advertise-address=192.168.10.11
init的参数都可以通过--help查帮助
--kubernetes-version 指定安装版本,如果不指定默认"stable-1"
--pod-network-cidr 设置pod网络的ip地址范围,你自己用的话,随便选一个就行,就和docker内部容器的ip一样的意思,但是切记不要和宿主机网段冲突,因为单跑docker可以自定义网络策略并且桥接继承宿主机的网卡,但是k8s不能这样用,它有一套自己独有的网络模式,而且其本身也会生成几张特有的网卡,如果占了宿主机的网络策略会造成冲突的。并且你这里设置的pod网络策略往后所有加入的worker节点都会使用该策略。注意!该配置很多地方你会看到写的都是 10.244.0.0/16 ,这是因为有一个必备 k8s 插件存在有些许狗血的默认配置,大部分人偷懒就不改了,但是工作中普遍要变
--service-cidr Service的ip和pod网络一样的情况,所以也选一个没被占用的,虽然service本质上也是一个附件类pod,但是它的不融于pod体系,反而起到代理的作用,所以需要一个独立的网段
--ignore-preflight-errors 是忽略某些警告
--image-repository设置镜像下载的远程仓库,一定要设置成阿里云,当然你要是有自己的 harbor 服务也可以用自己的
--cri-socket是设置使用那个CRI接口,因为1.24以后不默认支持docker,所以会去查询系统上有的CIR,如果不指定会识别到 cri-dockerd 和 containerd 两个
--apiserver-advertise-address设置API Server的通信地址,通常不带,默认就是主节点自身,还可以改端口号,不过一般也默认
这里要特别说明 SystemVerification 警告的忽略,不同的发行版可能会有一个模块叫做config,但这个模块不属于标准内核的范围,所以上面编译的5.6.15并没有,因此需要忽略它的警告
初始化需要一点时间,最后会输出如下的信息,表示初始化成功。最后一行的信息一定要保存下来,后面worker节点加入要用,各位读者最好和这里一样,将成功提示开始的后面所有信息单独保存一份
bash
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.239.70:6443 --token u03dy1.4zo5d3q11ifs4thq \
--discovery-token-ca-cert-hash sha256:1ce08a2e73685fa117b67a7452ff7ec196c499d463a6ea6e57d1e30747ec73f6
后续使用,要知道几个关键路径
k8s内部也有自己生成的证书,存储在/etc/kubernetes/pki目录
所有集群配置文件,存储在/etc/kubernetes目录下
静态Pod,也就是调度组件、Service暴露组件等等,在/etc/kubernetes/manifests
此时按照输出的日志已经告诉了你下一步该做什么,To start using your cluster, you need to run the following as a regular user,就是用一个普通的用户执行三条命令,在项目上使用的话就需要严格执行,个人自己的虚拟机上使用直接用root用户,把上面的环境变量加载到你的用户级别!!PATH里。总之上面三条命令的最终目的就是让一个日后负责k8s的运维人员执行k8s命令的时候有证书文件而已,因为一般不可能拿到root
bash
# 准备一个普通用户
useradd k8sadmin
passwd k8sadmin
# 在root用户身份下,该配置文件给上面的普通用户 sudo 权限
visudo
#追加一行,你自己的环境可以写所有命令都允许,且无需密码
k8sadmin ALL=(ALL) NOPASSWD: ALL
# 工作中要限制
k8sadmin ALL=(ALL) ALL
# 或者 只允许执行某些命令
k8sadmin ALL=(ALL) /usr/bin/systemctl, /bin/rm
# 切换到该用户下执行命令
su k8sadmin
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
现在,查看集群服务状态
bash
[k8sadmin@master01 opt]$ kubectl get cs
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME STATUS MESSAGE ERROR
controller-manager Healthy ok
etcd-0 Healthy ok
scheduler Healthy ok
[k8sadmin@master01 opt]$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
master01.k8s.com NotReady control-plane 43m v1.28.0
根据上面的输出,你会发现各组件都已经处于健康状态,但是看所有节点信息中,主节点一直是未准备就绪,这是因为 k8s 需要单独安装网络组件静态Pod,该组件 k8s 官方一直用的是第三方组件,本身不自带,一般是Flannel。去git上找Flannel并安装-》 https://github.com/flannel-io/flannel,看Deploying flannel manually,会告诉你如何安装

官方仓库中已经告诉你,如果你是1.17+的版本,你可以直接运行命令下载相应的镜像并安装,刚好本篇中的版本够线。但是!你要注意它下面的小字,如果初始化集群时用的Pod网络策略不是 10.244.0.0/16就要自己设置
bash
# 命令,不要看官方仓库的,因为国内访问不到官方的 helm 仓库
# 需要手动创建命名空间
kubectl create ns kube-flannel
kubectl label --overwrite ns kube-flannel pod-security.kubernetes.io/enforce=privileged pod-security.kubernetes.io/warn=privileged pod-security.kubernetes.io/audit=privileged
# 下载安装文件,版本方面用稳定版就行,本文用v0.25.6
curl -L -o kube-flannel.yml https://cdn.jsdelivr.net/gh/flannel-io/flannel@v0.25.6/Documentation/kube-flannel.yml
#随后修改下载的到文件,搜索 "Network": "10.244.0.0/16" 换成你自己的
sed -i 's|10.244.0.0/16|10.10.0.0/16|g' kube-flannel.yml
# 一下命令可以查看是否修改全了
grep -A 5 -B 5 "Network" kube-flannel.yml
# 手动拉取镜像,因为本文在同步验证文档部署时发现,依靠k8s自己拉不下来
# 具体的镜像名称,看 kube-flannel.yml 中的 image ,如果各位读者用的和本文版本一直,直接执行命令就行
docker pull docker.io/flannel/flannel:v0.25.6
docker pull docker.io/flannel/flannel-cni-plugin:v1.5.1-flannel2
# 执行安装
kubectl apply -f kube-flannel.yml
# 如果中途遇到问题,需要先删除,然后从创建nc哪一步重头开始
kubectl delete -f kube-flannel.yml
# 部署需要一点时间,你可以陆续查询关注状态
[k8sadmin@master01 opt]$ kubectl get pods -n kube-flannel
NAME READY STATUS RESTARTS AGE
kube-flannel-ds-zvggr 0/1 Init:0/2 0 21s
# 直到它变为 运行状态
[k8sadmin@master01 opt]$ kubectl get pods -n kube-flannel
NAME READY STATUS RESTARTS AGE
kube-flannel-ds-d2nwc 1/1 Running 0 55s
# 现在 再去看集群节点,主节点就时 ready 状态了
[k8sadmin@master01 opt]$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
master01.k8s.com Ready control-plane 135m v1.28.0
到此,主节点的安装部署就算完成了
第六步:所有 worker 节点,使用上面初始化时,日志给你的命令加入集群,记得带上CRI接口选择参数
bash
kubeadm join 192.168.239.70:6443 --token u03dy1.4zo5d3q11ifs4thq --discovery-token-ca-cert-hash sha256:1ce08a2e73685fa117b67a7452ff7ec196c499d463a6ea6e57d1e30747ec73f6 --cri-socket unix:///var/run/cri-dockerd.sock --ignore-preflight-errors=Swap,SystemVerification
加入后,主节点查询node列表就可以看到了,和master一样node节点在刚加入集群的时候也是notready,需要等待一会,它会从master同步flannel,不需要你手动拉取镜像
bash
[k8sadmin@master01 opt]$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
master01.k8s.com Ready control-plane 153m v1.28.0
worker01.k8s.com NotReady <none> 108s v1.28.0
worker02.k8s.com NotReady <none> 94s v1.28.0
[k8sadmin@master01 opt]$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
master01.k8s.com Ready control-plane 153m v1.28.0
worker01.k8s.com Ready <none> 108s v1.28.0
worker02.k8s.com Ready <none> 94s v1.28.0
在master节点还可以查询到k8s系统pod情况
bash
[k8sadmin@master01 opt]$ kubectl get pods -n kube-system -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
coredns-6554b8b87f-74frl 1/1 Running 0 154m 10.10.0.2 master01.k8s.com <none> <none>
coredns-6554b8b87f-974x9 1/1 Running 0 154m 10.10.0.3 master01.k8s.com <none> <none>
etcd-master01.k8s.com 1/1 Running 0 154m 192.168.239.70 master01.k8s.com <none> <none>
kube-apiserver-master01.k8s.com 1/1 Running 0 154m 192.168.239.70 master01.k8s.com <none> <none>
kube-controller-manager-master01.k8s.com 1/1 Running 0 154m 192.168.239.70 master01.k8s.com <none> <none>
kube-proxy-47l24 1/1 Running 0 2m56s 192.168.239.71 worker01.k8s.com <none> <none>
kube-proxy-4g642 1/1 Running 0 154m 192.168.239.70 master01.k8s.com <none> <none>
kube-proxy-8825q 1/1 Running 0 2m42s 192.168.239.72 worker02.k8s.com <none> <none>
kube-scheduler-master01.k8s.com 1/1 Running 0 154m 192.168.239.70 master01.k8s.com <none> <none>
到此,单主节点 k8s 集群就部署完成了,后续如果各位读者,需要使用低版本默认支持 docker 的 1.20 以下版本,在部署方式上是一样的,只需去掉 cri-dockerd 相关配置即可