以下是博主编写整理的 k8s 集群部署的相关的操作和在部署中出现的常见问题,写的不好欢迎大家多多在评论区提意见,共同学习,好了言归正传,今天咋们就开始学习 k8s 集群的部署!
一、环境规划
主要从四方面来介绍:
1、部署类型:使用一主俩从的部署类型(因为在学习过程中,这种方式更加简单、资源消耗更少)
2、部署方式:采用 Kubernetes 官方提供的 kubeadm 快速部署的方式
3、部署版本:这里采用的是 1.23.14 版本的 Kubernetes 、20.10.16 版本的 Docker 以及 3.25 版本 Calico
4、主机划分:申请三台服务器,依次设计好 IP 地址以及主机名,内核必须为 4.0 以上,详细的升级方法可参考博主的 Linux 内核升级教程这篇文章
角色 | IP地址 | 实验环境 |
---|---|---|
k8s-master | 192.168.246.156 | CentOS 8-Stream |
k8s-node1 | 192.168.246.253 | CentOS 8-Stream |
k8s-node2 | 192.168.246.254 | CentOS 8-Stream |
二、构建流程
构建 Kubernetes 集群大致分为以下个步骤:
1、准备环境:准备至少三台服务器可用,一台作为主节点,两台作为工作节点。在每台服务器上安装 Docker 和 Kubernetes 工具;
2、配置主节点:在主节点上运行 kubeadm init 命令进行初始化 ,按照提示执行相应的操作,保证 kubectl 命令可用;
3、添加工作节点:在每个工作节点上运行 kubeadm join 命令,将工作节点加入到主节点所在的集群中;
4、配置网络插件:安装一个网络插件,以便工作节点之间可以通信,容器可以互相访问,这里使用的是 Calico 插件;
5、验证集群:在主节点上运行命令 kubectl get nodes,确保所有节点都处于 “Ready” 状态。这表明集群已经成功搭建并且所有节点正常工作;
6、服务部署:这里通过部署 Nginx 服务来测试 Kubernetes 集群。
三、环境准备
3.1、永久关闭防火墙、selinux 和禁用 swap 分区
需要在 master、node1 和 node2 三台服务器上分别执行这些操作,保证实验环境的一致性。
在实际生产环境中是不建议关闭防火墙、selinux 和禁用 swap 分区的,因为这会降低系统的安全性,有极大的安全风险,所以会针对特定的应用场景,调整防火墙规则、swap 分区大小和 selinux 策略以满足业务需求。而在我们学习过程中,建议是将这些全部关闭,因为打开防火墙和 selinux 会导致 Kubernetes 集群中多节点通信异常、容器无法访问某些资源等等,而禁用 swap 分区可以保证所有节点的资源使用方式相同。
#永久关闭防火墙
systemctl stop firewalld && systemctl disable firewalld
#永久关闭selinux
sed -i 's/enforcing/disabled/g' /etc/selinux/config
#关闭swap分区,重启生效
sed -ri 's/.*swap.*/#&/' /etc/fstab
#根据如下命令检查所修改的内容是否已更改,如未关闭,按上述命令重新执行
systemctl status firewalld | grep active
cat /etc/selinux/config | grep ^SELINUX
cat /etc/fstab | grep swap
3.2、修改主机名、添加hosts文件、将桥接的IPv4流量传递到iptables的链
修改主机名、添加hosts文件以保证 Kubernetes 集群各个节点可以通过主机名来相互通信以及服务发现;
将桥接的 IPv4 流量传递到 iptables 的链以实现容器之间的网络隔离和路由功能。
同理也需要在 master、node1 和 node2 三台服务器上执行,保证实验环境的一致性。
#修改主机名
hostnamectl set-hostname k8s-master
#使用cat命令将ip地址和主机名映射添加到hosts文件中
cat >> /etc/hosts << EOF
192.168.246.156 k8s-master
192.168.246.253 k8s-node1
192.168.246.254 k8s-node2
EOF
# 将桥接的IPv4流量传递到iptables的链
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system # 生效
至此,三台服务器的基础环境已搭建完成,以防有些配置文件及操作没有生效,这里建议重启服务器,可使用 reboot 命令来重启。
这里建议开启 ssh 免密登录,这样方便后续服务器之间文件的传输和一键脚本的部署,具体操作如下:
#在每台服务器上生成RSA密钥对
ssh-keygen -P '' -f ~/.ssh/id_rsa
#将公钥传输给要远程的服务器(在每台服务器上,将生成的公钥复制到其他两台服务器上)
ssh-copy-id -i ~/.ssh/id_rsa.pub root@k8s-node1
......
#验证登录
ssh root@k8s-node1
.....
3.3、安装 Docker 环境
Kubernetes 集群部署需要 Docker 或其他容器环境来实现容器化应用程序的隔离、部署、管理和扩展,而 Docker 提供了标准化的容器镜像格式和强大的资源隔离功能,这就使得 Kubernetes 可以更高效地管理和操作容器化应用程序,因此这里需要在 master、node1 和 node2 三台服务器上分别安装 Docker 基础环境。
基于不同版本的 Kubernetes 对应不同版本的 Docker ,这里可通过 GitHub 来选择合适的版本以防出现不兼容的情况。
详细的安装参考文档可参考:阿里云的官方docker-ce镜像文档
#安装必要的一些系统工具并添加Docker软件源信息
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
sudo sed -i 's+download.docker.com+mirrors.aliyun.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo
#更新本地yum软件仓库的缓存信息,保证yum install或yum update等命令时能够更快地获取到软件包的信息
sudo yum makecache
#安装20.10.16版本的Docker及其相应依赖包
sudo yum install -y docker-ce-20.10.16-3.el8 docker-ce-cli-20.10.16-3.el8 docker-ce-rootless-extras-20.10.16-3.el8 containerd.io docker-compose-plugin
#启动Docker并将其设置成开机自启
systemctl start docker && systemctl enable docker
安装完可使用 docker version 或者 docker --version 命令来查看已安装的 Docker 版本信息
更改 Docker 的驱动为 systemd 驱动,因为在该版本 Kubernetes 集群部署过程中是不支持 cgroupfs 驱动的。
#查看 Docker 当前的驱动
docker info | grep Driver
#将 Docker 的驱动改为 systemd
cat > /etc/docker/daemon.json<<EOF
{"exec-opts": ["native.cgroupdriver=systemd"]}
EOF
#重新加载并重启 Docker
systemctl daemon-reload && systemctl restart docker
3.4、添加 Kubernetes 的 yum 源
由于 Kubernetes 的源仓库在国外,避免下载过慢导致失败,这里将其改为阿里云的 yum 源,分别在 master、node1 和 node2 三台服务器上执行。
cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
拓展:这里简单介绍一下如何创建 k8s 的 yum 源文件:
1、定义源标识[kubernetes]和源描述name;
2、指定源的路径 baseurl 并确定是否开启源(enabled=1表示开启,0表示禁用);
3、定义是否进行软件包完整性和安全性检查(0表示不检查,1表示检查);
4、指定 gpgkey 文件路径,至此一个本地的yum源文件编写成功。
3.5、安装 kubeadm、kubelet、kubectl 等组件
在 master、node1 和 node2 三台服务器上分别安装 kubeadm、kubelet 和 kubectl 组件,指定版本是1.23.14
- Kubeadm 是一个提供了 kubeadm init 和 kubeadm join 的工具, 作为创建 Kubernetes 集群的 “快捷途径” 的最佳实践;
- Kubelet 是 Kubernetes 集群中的一种重要的核心组件,运行在每一个节点上,负责管理和执行在节点上运行的容器;
- Kubectl 是一个用于与运行在 Kubernetes 集群上的容器化应用进行交互和管理的命令行工具。
- 详细的组件工具介绍可参考 kubernetes 的官方文档
#可根据如下命令来选择你想下载的k8s版本,这里选择的是1.23.14版本的k8s
yum list --showduplicates kubeadm --disableexcludes=kubernetes
#安装1.23.14版本的k8s及其相应依赖包
yum install -y kubelet-1.23.14 kubeadm-1.23.14 kubectl-1.23.14
#将其设置为开机自启
systemctl enable kubelet
可根据 kubectl version 、kubeadm version 、kubelet --version 命令来查看对应的版本
3.6、Master 主节点初始化
kubeadm init \
--apiserver-advertise-address=192.168.246.156 \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.23.14 \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.224.0.0/16
参数详解:
【–apiserver-advertise-address】 表示的是当前服务器的 IP 地址,也就是部署 master 主节点的 IP 地址
【–image-repository】表示的是用于拉取镜像的容器仓库,这里用的是阿里云的镜像仓库
【–kubernetes-version】表示的是当前所用 k8s 的版本
【–service-cidr】表示的是集群内部服务的虚拟 IP 地址以及地址段
【–pod-network-cidr】表示的是 Pod 网络可使用的 IP 地址段
显示 successfully 表示初始化成功,但要想使相关的组件可以正常使用,你需要按提示将目录、权限设置成功,具体操作如下:
#配置kubectl使之可以正常使用
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
3.7、添加 Node 节点到集群
根据 Master 主节点初始化成功提示的信息获取 token 值和 hash 值,使用 kubeadm join 命令将 Node 节点加入到集群中。
–token 是用于身份验证的加密令牌,默认保持24h,24小时后失效
–discovery-token-ca-cert-hash 指定一个 CA 证书的哈希值,用于验证新节点的身份
#在 Node1 和 Node2 节点上分别执行该命令
kubeadm join 192.168.246.156:6443 --token rjdydr.uu4afmz86mmgkglf --discovery-token-ca-cert-hash sha256:da61eb878295e283571e268f9c81e68876cc1eadf26cb541dc7b089c350935fb
提示 “This node has joined the cluster”表示 Node 已加入到主节点的集群中,可在主节点上运行命令 kubectl get nodes 来查看。
拓展:如 token 值过期,需要手动获取 hash 值和新的 token 值才能将 node 节点添加到集群中。操作如下:
#当前的token值,如果为空表示前集群中没有有效的token值
kubeadm token list
#重新申请token值
kubeadm token create
kubeadm token list
#根据实际情况来删除当前有效的token值
kubeadm token delete xpcpuh.mxbspj51yyskofu1
–discovery-token-ca-cert-hash 值被保存到 Kubernetes 集群的根证书文件中, 默认情况下,根证书位于 /etc/kubernetes/pki/ca.crt下,可通过如下命令获取,但需要在得到的hash值前面拼接上 sha256:才算完整。
#使用OpenSSL工具计算证书文件的SHA256哈希值
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | \
openssl rsa -pubin -outform der 2>/dev/null | \
openssl dgst -sha256 -hex | sed 's/^.* //'
3.8、部署网络 CNI 插件
由于在搭建 k8s 集群过程中,我们需要保证 Pod 可以在不同节点之间通信,因此需要在 master 主节点部署 CNI 网络插件来提供相应的网络功能,保障 Pod 通信正常。同时 CNI 网络插件也为每个 Pod 分配唯一的 IP 地址,可根据需要动态分配 IP 地址,处理 Pod 间 IP 地址冲突和重叠问题。
#下载对应版本的calico插件
curl https://docs.tigera.io/archive/v3.25/manifests/calico.yaml -O
#修改配置文件中的IP地址以及删除镜像前缀,避免下载过慢导致失败
sed -i -e 's/#\s*- name/- name/g' -e 's|#\s*value:\s*"192.168.0.0\/16"| value: "10.234.0.0/16"|g' calico.yaml
sed -i 's#docker.io/##g' calico.yaml
#构建资源应用将其应用到集群中
kubectl apply -f calico.yaml
具体选择哪个版本的 Calico 网络插件,可根据 Calico官网 进行查询,获取和 k8s 相对应的版本,这里选择的是 Calico 3.25 版本。
执行完成后可根据 kubectl get po -n kube-system 命令来检查 CNI 网络插件是否部署成功,如显示 Running 状态,则部署成功。
可在主节点上运行命令 kubectl get nodes 查看,确保所有节点都处于 “Ready” 状态。
四、服务部署
简单部署一个 Nginx 服务用于测试 Kubernetes 集群,通过访问 (IP:暴露的端口) 得到 Nginx 的页面则说明服务部署成功。
# 创建部署
kubectl create deployment nginx --image=nginx
# 暴露端口
kubectl expose deployment nginx --port=80 --type=NodePort
# 查看 pod 以及服务信息
kubectl get pod,svc
至此,Kubernetes 集群部署完成。
五、拓展知识
5.1、kubectl 命令自动补全
在实际环境中,手动输入可能会出现拼写错误或者忘记某些关键字从而导致命令执行失败或者不如预期,因此,为了提高工作效率和减少错误,使用 kubectl 命令自动补全可以大大减少输入错误和排错时间。
yum install bash-completion
#全局生效
kubectl completion bash | sudo tee /etc/bash_completion.d/kubectl > /dev/null
source /usr/share/bash-completion/bash_completion
#当前用户生效
echo 'source <(kubectl completion bash)' >>~/.bashrc
#验证,输入kubectl,按俩次Tab按键
kubectl
5.2、在任意节点使用 kubectl 命令
在实际环境中,我们不能仅仅在 master 节点上使用 kubectl 命令,这会使整个集群缺乏灵活性、故障排查困难、不便于管理等等,因此需要在任意一个 node 节点上使用该命令。
#将master节点中/etc/kubernetes/admin.conf文件拷贝到需要运行的服务器的/etc/kubernetes目录下
scp root@k8s-master:/etc/kubernetes/admin.conf /etc/kubernetes
#在对应的服务器上配置环境变量
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bashrc
source ~/.bashrc
#验证
kubectl get po,svc
5.3、将 Node 节点移出集群
#获取当前的节点列表
kubectl get nodes
#标记要移除的节点为不可调度状态(Cordoned)才可被移除,也就意味着阻止新的Pod被调度到该节点上
kubectl cordon k8s-node2
#将该节点上的所有运行中的Pod进行迁移和重新调度,确保它们运行在其他节点上。使用--ignore-daemonsets参数可以忽略DaemonSet中的Pod,这样它们将保持在该节点上
kubectl drain k8s-node2 --ignore-daemonsets
#确认所有Pod都已成功迁移后,从集群中删除该节点
kubectl delete node k8s-node2
#验证当前节点列表
kubectl get no
六、部署过程中常见问题汇总
详细的问题解答可参考博主编写的常见问题汇总这篇文章,感谢大家的支持!