文章目录
- Kubernetes 部署方式
- 常见的K8S安装部署方式
- Kubeadm与二进制部署的区别
- Kubernetes部署安装
- 环境配置
- Kubernetes集群初始化配置(实验环境)
- 一、操作系统初始化配置
- 二、部署Docker引擎
- etcd 集群搭建
- 配置 etcd 集群
- Kubernetes Master 组件部署
- 准备工作
- 创建目录
- 复制证书
- 解压 Kubernetes 二进制文件
- 创建 Bootstrap Token
- 启动 Master 组件
- 生成 Kubeconfig 文件
- 验证集群状态
- Kubernetes Worker Node 部署
- 在所有 Node 节点上执行的操作
- 在 Master 节点(master01)上执行的操作
- 在 node01 节点上操作
- 启动 kubelet 服务
- 在 master01 节点上操作,通过 CSR 请求
- 在 node01 节点上操作
- 加载 ip_vs 模块
- 启动proxy服务
- 部署 CNI 网络组件
- 在 node01 节点上操作
- 上传 cni-plugins-linux-amd64-v1.3.0.tgz 和 flannel镜像文件 到 /opt 目录中
- 在 master01 节点上操作
- 上传 kube-flannel.yml 文件到 /opt/k8s 目录中,部署 CNI 网络
- 部署 Calico(在 master01 节点操作)
- 部署 Calico
- 查看node状态
- 修改calico的网络模式
- node02 节点部署
- 在 node01 节点上操作
- 在 node02 节点上操作
- 在 master01 节点上操作
- 通过 CSR 请求
- 在 node02 节点上操作
- 加载 ipvs 模块
- 使用proxy.sh脚本启动proxy服务
- 查看群集中的节点状态
- 部署 CoreDNS
- CoreDNS
- 部署CoreDNS
- 在所有 node 节点上操作
- 在 master01 节点上操作
- DNS 解析测试
- 故障排除
Kubernetes 部署方式
常见的K8S安装部署方式
- Minikube
- 用途:用于本地快速运行一个单节点微型K8S,适合学习、预览K8S特性。
- 部署地址:https://kubernetes.io/docs/setup/minikube
- Kubeadm
- 用途:提供
kubeadm init
和kubeadm join
命令,用于快速部署K8S集群,相对简单。 - 文档地址:https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm/
- 用途:提供
- 二进制安装部署
- 用途:生产首选,从官方下载发行版的二进制包,手动部署每个组件和自签TLS证书,组成K8S集群。
- 下载地址:https://github.com/kubernetes/kubernetes/releases
- 备注:虽然手动部署较麻烦,但期间可以学习很多工作原理,也利于后期维护。
总结:
- Minikube:适合本地学习和预览K8S特性。
- Kubeadm:部署简单,适合快速搭建K8S集群,但管理难度较大,故障恢复速度较慢。
- 二进制部署:部署复杂,但管理方便,集群伸展性能好,稳定性高,适合生产环境。
Kubeadm与二进制部署的区别
- 二进制部署
- 部署难度:难
- 管理方便性:方便
- 集群伸展性能:好
- 稳定性:集群规模到达一定规模(几百个节点、上万个Pod)时,二进制部署的稳定性高于kubeadm。
- 故障恢复:宿主机起来后,进程也会自动起来,恢复速度快。
- Kubeadm部署
- 部署难度:简单
- 管理方便性:难
- 部署方式:以容器管理容器的方式部署组件及服务。
- 故障恢复:恢复速度比二进制慢,因为需要先启动宿主机,再启动进程,最后启动容器,集群才能恢复。
Kubernetes部署安装
环境配置
节点名称 | IP地址 | 托管服务/组件 |
---|---|---|
k8s集群master01 | 20.0.0.10 | kube-apiserver, kube-controller-manager, kube-scheduler, etcd |
k8s集群master02 | 20.0.0.66 | (备用master) |
k8s集群node01 | 20.0.0.58 | kubelet, kube-proxy, docker, etcd |
k8s集群node02 | 20.0.0.59 | kubelet, kube-proxy, docker, etcd |
etcd集群节点1 | 20.0.0.10 | etcd |
etcd集群节点2 | 20.0.0.58 | etcd |
etcd集群节点3 | 20.0.0.59 | etcd |
Kubernetes集群初始化配置(实验环境)
一、操作系统初始化配置
-
关闭防火墙
- 停止并禁用
firewalld
服务。 - 清除所有iptables规则。
systemctl stop firewalld systemctl disable firewalld iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
- 停止并禁用
-
关闭SELinux
- 临时关闭SELinux。
- 永久修改
/etc/selinux/config
文件,将SELinux设置为disabled
。
setenforce 0 sed -i 's/enforcing/disabled/' /etc/selinux/config
-
关闭Swap
- 临时关闭Swap。
- 永久禁用Swap,修改
/etc/fstab
文件,注释掉Swap相关行。
swapoff -a sed -ri 's/.*swap.*/#&/' /etc/fstab
-
设置主机名
- 根据规划,使用
hostnamectl
命令设置各节点的主机名。
hostnamectl set-hostname [主机名]
- 根据规划,使用
-
添加Hosts
- 在
master
节点上,编辑/etc/hosts
文件,添加集群内其他节点的IP和主机名映射。
cat >> /etc/hosts << EOF 20.0.0.10 master01 20.0.0.58 node01 20.0.0.59 node02 EOF
- 在
-
调整内核参数
- 创建
/etc/sysctl.d/k8s.conf
文件,添加必要的内核参数配置。 - 应用配置。
cat > /etc/sysctl.d/k8s.conf << EOF net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv6.conf.all.disable_ipv6=1 net.ipv4.ip_forward=1 EOF sysctl --system
- 创建
-
时间同步
- 安装
ntpdate
工具。 - 使用
ntpdate
同步时间。
yum install ntpdate -y ntpdate time.windows.com
- 安装
二、部署Docker引擎
-
安装依赖
- 在所有
node
节点上,安装yum-utils
、device-mapper-persistent-data
和lvm2
。
yum install -y yum-utils device-mapper-persistent-data lvm2
- 在所有
-
添加Docker仓库
- 使用
yum-config-manager
添加Docker的官方仓库。
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
- 使用
-
安装Docker
- 安装Docker CE、Docker CE CLI和
containerd.io
。
yum install -y docker-ce docker-ce-cli containerd.io
- 安装Docker CE、Docker CE CLI和
-
配置Docker
- 创建
/etc/docker
目录。 - 在
/etc/docker/daemon.json
文件中添加Docker的配置,包括镜像加速器、Cgroup Driver等。
mkdir /etc/docker cat > /etc/docker/daemon.json <<EOF {"registry-mirrors": ["https://6ijb8ubo.mirror.aliyuncs.com", "https://docker.m.daocloud.io", "https://docker.1panel.live"],"exec-opts": ["native.cgroupdriver=systemd"],"log-driver": "json-file","log-opts": {"max-size": "1g", "max-file": "3"} } EOF
- 创建
-
启动并启用Docker服务
- 启动Docker服务。
- 设置Docker服务开机自启。
systemctl start docker.service systemctl enable docker.service
-
验证Docker配置
- 使用
docker info
命令检查Cgroup Driver是否配置正确。
docker info | grep "Cgroup Driver" Cgroup Driver: systemd
- 使用
------------------------------ 部署 etcd 集群 ------------------------------
etcd是一个分布式键值存储系统,用于在分布式系统中保存配置信息、元数据以及关键的共享状态。它是一个开源项目,最初由CoreOS开发并维护,现在由CNCF托管。etcd的设计目标是提供可靠的分布式存储,以支持分布式系统的一致性和高可用性。
关键特性:
- 分布式存储:etcd的数据存储是分布式的,可以跨多个节点进行分布,确保高可用性和可扩展性。
- 强致性:etcd提供强一致性的保证,确保在集群中的所有节点都能看到相同的数据视图。
- 轻量级:etcd采用轻量级的Raft一致性算法,以确保集群中的节点之间达成一致,同时保持相对较低的性能开销。
- API支持:etcd提供简单而强大的HTTP+JSON API,使得开发人员可以轻松地与其进行交互,并集成到各种应用和工具中。
- Watch机制:etcd支持Watch机制,允许客户端监视特定键的变化,并在数据发生变更时得到通知。
- 安全性:etcd支持SSL/TLS加密,以保障数据在传输过程中的安全性,并提供基于角色的访问控制。
应用场景:
- 配置管理: etcd常用于存储应用程序和系统的配置信息,允许动态地更新配置而无需重启应用。
- 服务发现: etcd可以用作服务发现的后端存储,帮助服务在动态环境中找到彼此。
- 分布式锁: 通过etcd的分布式锁机制,可以实现分布式系统中的协同工作和资源同步。
- 集群协调: etcd在构建分布式系统中,作为集群协调的关键组件,确保系统的一致性和稳定性。
总体而言,etcd在云原生应用和分布式系统中发挥着重要作用,提供了可靠的分布式存储和协调服务,为应用程序提供一致性、可靠性和高可用性的基础设施支持。
etcd 目前默认使用2379端口提供HTTP API服务, 2380端口和peer通信(这两个端口已经被IANA(互联网数字分配机构)官方预留给etcd)。 即etcd默认使用2379端口对外为客户端提供通讯,使用端口2380来进行服务器间内部通讯。
etcd 在生产环境中一般推荐集群方式部署。由于etcd 的leader选举机制,要求至少为3台或以上的奇数台。
---------- 准备签发证书环境 ----------
CFSSL 是 CloudFlare 公司开源的一款 PKI/TLS 工具。 CFSSL 包含一个命令行工具和一个用于签名、验证和捆绑 TLS 证书的 HTTP API 服务。使用Go语言编写。
CFSSL 使用配置文件生成证书,因此自签之前,需要生成它识别的 json 格式的配置文件,CFSSL 提供了方便的命令行生成配置文件。
CFSSL 用来为 etcd 提供 TLS 证书,它支持签三种类型的证书:
- client 证书,服务端连接客户端时携带的证书,用于客户端验证服务端身份,如 kube-apiserver 访问 etcd;
- server 证书,客户端连接服务端时携带的证书,用于服务端验证客户端身份,如 etcd 对外提供服务;
- peer 证书,相互之间连接时使用的证书,如 etcd 节点之间进行验证和通信。
这里全部都使用同一套证书认证。
etcd 集群搭建
- 安装 cfssl 工具
- 下载并安装
cfssl
、cfssljson
和cfssl-certinfo
工具。
链接可能失效,此处自己上传的文件进行实验wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -O /usr/local/bin/cfssl wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -O /usr/local/bin/cfssljson wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 -O /usr/local/bin/cfssl-certinfo chmod +x /usr/local/bin/cfssl*
- 下载并安装
- 生成 etcd 证书
- 创建目录并上传脚本。
mkdir /opt/k8s cd /opt/k8s/ chmod +x etcd-cert.sh etcd.sh vim /opt/k8s/etcd-cert.sh # 修改 etcd 中集群的 IP 地址 mkdir /opt/k8s/etcd-cert mv etcd-cert.sh etcd-cert/ cd /opt/k8s/etcd-cert/ ./etcd-cert.sh # 生成 CA 证书、etcd 服务器证书及私钥 ls#看到以下内容 ca-config.json ca-csr.json ca.pem server.csr server-key.pem ca.csr ca-key.pem etcd-cert.sh server-csr.json server.pem
- 下载并解压 etcd
cd /opt/k8s/ wget https://github.com/etcd-io/etcd/releases/download/v3.4.26/etcd-v3.4.26-linux-amd64.tar.gz tar zxvf etcd-v3.4.26-linux-amd64.tar.gz
配置 etcd 集群
- 创建必要目录
mkdir -p /opt/etcd/{cfg,bin,ssl} cd /opt/k8s/etcd-v3.4.26-linux-amd64/ mv etcd etcdctl /opt/etcd/bin/ cp /opt/k8s/etcd-cert/*.pem /opt/etcd/ssl/
- 启动 etcd 服务
- 在
master01
节点上启动 etcd 并等待其他节点加入。
进入卡住状态等待其他节点加入,这里需要三台etcd服务同时启动,如果只启动其中一台后,服务会卡在那里,直到集群中所有etcd节点都已启动,可忽略这个情况cd /opt/k8s/ ./etcd.sh etcd01 20.0.0.10 etcd02=https://20.0.0.58:2380,etcd03=https://20.0.0.59:2380
- 可另外打开一个窗口查看etcd进程是否正常
ps -ef | grep etcd
- 在
- 拷贝配置文件到集群节点中
- 把etcd相关证书文件、命令文件和服务管理文件全部拷贝到另外两个etcd集群节点
scp -r /opt/etcd/ root@20.0.0.58:/opt/ scp -r /opt/etcd/ root@20.0.0.59:/opt/ scp /usr/lib/systemd/system/etcd.service root@20.0.0.58:/usr/lib/systemd/system/ scp /usr/lib/systemd/system/etcd.service root@20.0.0.59:/usr/lib/systemd/system/
- 配置其他节点
- 在
node01
和node02
节点上修改/opt/etcd/cfg/etcd
配置文件。
vim /opt/etcd/cfg/etcd #[Member] ETCD_NAME="etcd02" #修改 ETCD_DATA_DIR="/var/lib/etcd" ETCD_LISTEN_PEER_URLS="https://20.0.0.58:2380" #修改 ETCD_LISTEN_CLIENT_URLS="https://20.0.0.58:2379" #修改#[Clustering] ETCD_INITIAL_ADVERTISE_PEER_URLS="https://20.0.0.58:2380" #修改 ETCD_ADVERTISE_CLIENT_URLS="https://20.0.0.58:2379" #修改 ETCD_INITIAL_CLUSTER="etcd01=https://20.0.0.10:2380,etcd02=https://20.0.0.58:2380,etcd03=https://20.0.0.59:2380" ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" ETCD_INITIAL_CLUSTER_STATE="new"
- 在
- 启动 etcd 服务并检查状态
systemctl start etcd systemctl enable etcd systemctl status etcd
- 检查 etcd 集群状态
ETCDCTL_API=3 /opt/etcd/bin/etcdctl --endpoints="https://20.0.0.10:2379,https://20.0.0.58:2379,https://20.0.0.59:2379" --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/server.pem --key=/opt/etcd/ssl/server-key.pem endpoint health --write-out=table
- 查看当前的 leader
ETCDCTL_API=3 /opt/etcd/bin/etcdctl --endpoints="https://20.0.0.10:2379,https://20.0.0.58:2379,https://20.0.0.59:2379" --cacert=/opt/etcd/ssl/ca.pem --cert=/opt/etcd/ssl/server.pem --key=/opt/etcd/ssl/server-key.pem endpoint status --write-out=table
- –cacert :使用此CA证书验证启用https的服务器的证书
- –key :使用此TLS密钥文件标识HTTPS客户端
- –cert :使用此TLS证书文件标识HTTPS客户端
- –endpoints:集群中以逗号分隔的机器地址列表
- cluster-health:检查etcd集群的运行状况
Kubernetes Master 组件部署
准备工作
- 上传文件到 /opt/k8s 目录
- 上传
master.zip
和k8s-cert.sh
到/opt/k8s
。 - 上传
kubernetes-server-linux-amd64.tar.gz
到/opt/k8s
。
- 上传
注:此处用的是自己的master.zip压缩包里有事先准备好的脚本文件资源等并不适用所有情况,适度参考。
2. 解压和权限设置
- 解压
master.zip
并赋予脚本执行权限。cd /opt/k8s/ unzip master.zip chmod +x *.sh
创建目录
- 创建 Kubernetes 工作目录
mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}
- 创建证书目录
mkdir /opt/k8s/k8s-cert mv /opt/k8s/k8s-cert.sh /opt/k8s/k8s-cert cd /opt/k8s/k8s-cert/ ./k8s-cert.sh#生成ca证书、相关组件的证书和私钥
- 查看生成的证书
大致得到如下结果ls *pem
admin-key.pem apiserver-key.pem ca-key.pem kube-proxy-key.pem
admin.pem apiserver.pem ca.pem kube-proxy.pem
复制证书
- 将 CA 证书和 API Server 相关证书及私钥复制到
ssl
目录。cp ca*pem apiserver*pem /opt/kubernetes/ssl/
#上传 kubernetes-server-linux-amd64.tar.gz 到 /opt/k8s/ 目录中,解压 kubernetes 压缩包
#下载地址:https://github.com/kubernetes/kubernetes/blob/release-1.20/CHANGELOG/CHANGELOG-1.20.md
#注:打开链接你会发现里面有很多包,下载一个server包就够了,包含了Master和Worker Node二进制文件。
解压 Kubernetes 二进制文件
-
解压 Kubernetes 服务器包
cd /opt/k8s/ tar zxvf kubernetes-server-linux-amd64.tar.gz
-
复制master组件的关键命令文件到 kubernetes工作目录的
bin
子目录中cd /opt/k8s/kubernetes/server/bin cp kube-apiserver kubectl kube-controller-manager kube-scheduler /opt/kubernetes/bin/ ln -s /opt/kubernetes/bin/* /usr/local/bin/
创建 Bootstrap Token
- 创建并运行 token.sh 脚本
cd /opt/k8s/ vim token.sh #!/bin/bash #获取随机数前16个字节内容,以十六进制格式输出,并删除其中空格 BOOTSTRAP_TOKEN=$(head -c 16 /dev/urandom | od -An -t x | tr -d ' ') cat > /opt/kubernetes/cfg/token.csv <<EOF ${BOOTSTRAP_TOKEN},kubelet-bootstrap,10001,"system:kubelet-bootstrap" EOF
chmod +x token.sh ./token.sh cat /opt/kubernetes/cfg/token.csv
启动 Master 组件
- 启动 API Server
- 需要先准备好
apiserver.sh
脚本,传入参数如 etcd 集群地址。
cd /opt/k8s/ ./apiserver.sh 20.0.0.10 https://20.0.0.10:2379,https://20.0.0.58:2379,https://20.0.0.59:2379 # 检查 API Server 是否启动成功 ps aux | grep kube-apiserver netstat -natp | grep 6443
- 需要先准备好
- 启动 Scheduler
cd /opt/k8s/ ./scheduler.sh ps aux | grep kube-scheduler
注意脚本中的IP地址是否正确
- 启动 Controller Manager
./controller-manager.sh
注意脚本中的IP地址是否正确
生成 Kubeconfig 文件
- 生成
kubectl
连接集群的kubeconfig
文件,并运行admin.sh
脚本。./admin.sh
注意脚本中的IP地址是否正确
验证集群状态
- 查看集群组件状态
kubectl get cs
输出大致如下:
NAME STATUS MESSAGE ERROR
controller-manager Healthy ok
scheduler Healthy ok
etcd-2 Healthy {"health":"true"}
etcd-1 Healthy {"health":"true"}
etcd-0 Healthy {"health":"true"}
-
查看版本信息
kubectl version
-
查看当前 leader
kubectl -n kube-system get leases kube-scheduler kubectl -n kube-system get leases kube-controller-manager
Kubernetes Worker Node 部署
在所有 Node 节点上执行的操作
-
创建 Kubernetes 工作目录
- 创建必要的目录结构用于存放 Kubernetes 组件的二进制文件、配置文件、证书和日志。
mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs}
- 创建必要的目录结构用于存放 Kubernetes 组件的二进制文件、配置文件、证书和日志。
-
上传并解压 node.zip
- 将包含
kubelet.sh
和proxy.sh
脚本的node.zip
文件上传到/opt
目录。 - 解压
node.zip
并赋予脚本执行权限。cd /opt/ unzip node.zip chmod +x kubelet.sh proxy.sh
- 将包含
在 Master 节点(master01)上执行的操作
-
拷贝 kubelet 和 kube-proxy 到 Node 节点
- 将
kubelet
和kube-proxy
二进制文件从 Master 节点的/opt/k8s/kubernetes/server/bin
目录拷贝到各个 Node 节点的/opt/kubernetes/bin/
目录。cd /opt/k8s/kubernetes/server/bin scp kubelet kube-proxy root@20.0.0.58:/opt/kubernetes/bin/ scp kubelet kube-proxy root@20.0.0.59:/opt/kubernetes/bin/
- 将
-
生成 kubeconfig 文件
- 创建
/opt/k8s/kubeconfig
目录,上传kubeconfig.sh
脚本并赋予执行权限。 - 执行
kubeconfig.sh
脚本生成bootstrap.kubeconfig
和kube-proxy.kubeconfig
文件。这些文件包含连接到 API Server 所需的证书和配置信息。mkdir /opt/k8s/kubeconfigcd /opt/k8s/kubeconfig chmod +x kubeconfig.sh ./kubeconfig.sh 20.0.0.10 /opt/k8s/k8s-cert/
- 创建
-
拷贝 kubeconfig 文件到 Node 节点
- 将生成的
bootstrap.kubeconfig
和kube-proxy.kubeconfig
文件拷贝到各个 Node 节点的/opt/kubernetes/cfg/
目录。scp bootstrap.kubeconfig kube-proxy.kubeconfig root@20.0.0.58:/opt/kubernetes/cfg/ scp bootstrap.kubeconfig kube-proxy.kubeconfig root@20.0.0.59:/opt/kubernetes/cfg/
- 将生成的
-
RBAC 授权和自动批准 CSR 请求
- 创建 RBAC 绑定,使用户
kubelet-bootstrap
能够发起 CSR 请求并自动批准这些请求。kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap kubectl create clusterrolebinding node-autoapprove-bootstrap --clusterrole=system:certificates.k8s.io:certificatesigningrequests:nodeclient --user=kubelet-bootstrap kubectl create clusterrolebinding node-autoapprove-certificate-rotation --clusterrole=system:certificates.k8s.io:certificatesigningrequests:selfnodeclient --user=kubelet-bootstrap
- 创建 RBAC 绑定,使用户
kubelet 采用 TLS Bootstrapping 机制,自动完成到 kube-apiserver 的注册,在 node 节点量较大或者后期自动扩容时非常有用。
Master apiserver 启用 TLS 认证后,node 节点 kubelet 组件想要加入集群,必须使用CA签发的有效证书才能与 apiserver 通信,当 node 节点很多时,签署证书是一件很繁琐的事情。因此 Kubernetes 引入了 TLS bootstraping 机制来自动颁发客户端证书,kubelet 会以一个低权限用户自动向 apiserver 申请证书,kubelet 的证书由 apiserver 动态签署。
kubelet 首次启动通过加载 bootstrap.kubeconfig 中的用户 Token 和 apiserver CA 证书发起首次 CSR 请求,这个 Token 被预先内置在 apiserver 节点的 token.csv 中,其身份为 kubelet-bootstrap 用户和 system:kubelet-bootstrap 用户组;想要首次 CSR 请求能成功(即不会被 apiserver 401 拒绝),则需要先创建一个 ClusterRoleBinding,将 kubelet-bootstrap 用户和 system:node-bootstrapper 内置 ClusterRole 绑定(通过 kubectl get clusterroles 可查询),使其能够发起 CSR 认证请求。
TLS bootstrapping 时的证书实际是由 kube-controller-manager 组件来签署的,也就是说证书有效期是 kube-controller-manager 组件控制的;kube-controller-manager 组件提供了一个 --experimental-cluster-signing-duration 参数来设置签署的证书有效时间;默认为 8760h0m0s,将其改为 87600h0m0s,即 10 年后再进行 TLS bootstrapping 签署证书即可。
也就是说 kubelet 首次访问 API Server 时,是使用 token 做认证,通过后,Controller Manager 会为 kubelet 生成一个证书,以后的访问都是用证书做认证了。
在 node01 节点上操作
启动 kubelet 服务
cd /opt/
./kubelet.sh 20.0.0.58
ps aux | grep kubelet
在 master01 节点上操作,通过 CSR 请求
- 检查到 node01 节点的 kubelet 发起的 CSR 请求,Pending 表示等待集群给该节点签发证书
kubectl get csr
#输出大致如下
NAME AGE SIGNERNAME REQUESTOR CONDITION
node-csr-duiobEzQ0R93HsULoS9NT9JaQylMmid_nBF3Ei3NtFE 12s kubernetes.io/kube-apiserver-client-kubelet kubelet-bootstrap Pending
- 通过 CSR 请求
kubectl certificate approve node-csr-duiobEzQ0R93HsULoS9NT9JaQylMmid_nBF3Ei3NtFE
- Approved,Issued 表示已授权 CSR 请求并签发证书
kubectl get csr
NAME AGE SIGNERNAME REQUESTOR CONDITION
node-csr-duiobEzQ0R93HsULoS9NT9JaQylMmid_nBF3Ei3NtFE 2m5s kubernetes.io/kube-apiserver-client-kubelet kubelet-bootstrap Approved,Issued
- 查看节点,由于网络插件还没有部署,节点会没有准备就绪 NotReady
kubectl get node
NAME STATUS ROLES AGE VERSION
20.0.0.58 NotReady <none> 108s v1.20.15
在 node01 节点上操作
加载 ip_vs 模块
for i in $(ls /usr/lib/modules/$(uname -r)/kernel/net/netfilter/ipvs|grep -o "^[^.]*");do echo $i; /sbin/modinfo -F filename $i >/dev/null 2>&1 && /sbin/modprobe $i;done
启动proxy服务
cd /opt/
./proxy.sh 20.0.0.58
ps aux | grep kube-proxy
部署 CNI 网络组件
在 node01 节点上操作
上传 cni-plugins-linux-amd64-v1.3.0.tgz 和 flannel镜像文件 到 /opt 目录中
cd /opt/
docker load -i flannel.tar
docker load -i flannel-cni-plugin.tar
mkdir -p /opt/cni/bin
tar zxvf cni-plugins-linux-amd64-v1.3.0.tgz -C /opt/cni/bin
在 master01 节点上操作
上传 kube-flannel.yml 文件到 /opt/k8s 目录中,部署 CNI 网络
cd /opt/k8s
kubectl apply -f kube-flannel.yml
kubectl get pods -n kube-flannel
NAME READY STATUS RESTARTS AGE
kube-flannel-ds-hjtc7 1/1 Running 0 7s
kubectl get nodes
NAME STATUS ROLES AGE VERSION
20.0.0.58 Ready <none> 81m v1.20.15
ip -d a show flannel.1 #在node上查看flannel.1的端口
route -n #通过路由信息,看到发送到对端网段的数据包都会经过 flannel.1发出,网关ip也是对端vtep设备的ip地址
ip neigh show dev flannel.1 #由于flannel.1 通过路由信息已经知道对端vtep的ip地址,通过查询本地arp缓存表,得到目的vtep的mac地址
bridge fdb show flannel.1 #flannel.1可以通过查询本机的FDB表获取目的节点主机的ip
部署 Calico(在 master01 节点操作)
curl:https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml
部署 Calico
上传 calico.yaml 文件到 /opt/k8s 目录中
vim
冒号模式下/CALICO_IPV4POOL_CIDR
找
cd /opt/k8s
vim calico.yaml#修改里面定义 Pod 的网络(CALICO_IPV4POOL_CIDR),需与前面 kube-controller-manager 配置文件指定的 cluster-cidr 网段一样- name: CALICO_IPV4POOL_CIDRvalue: "10.244.0.0/16" #Calico 默认使用的网段为 192.168.0.0/16
kubectl apply -f calico.yaml
kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-659bd7879c-4h8vk 1/1 Running 0 58s
calico-node-nsm6b 1/1 Running 0 58s
calico-node-tdt8v 1/1 Running 0 58s
查看node状态
等 Calico Pod 都 Running,节点也会准备就绪
kubectl get nodes
修改calico的网络模式
将IPIP变为BGP
kubectl edit ds calico-node -n kube-system
......- name: CALICO_IPV4POOL_IPIPvalue: "Never" #设置为Never时为BGP模式,设置为Always时为IPIP模式,设置为Cross-SubNet时为混合模式- name: IP_AUTODETECTION_METHOD #添加下面两行value: "interface=ens33" #指定calico使用的网卡kubectl edit ippool ipipMode: Never #把ipipMode从Always修改成为Never
使用BGP模式时,查看IP会发现tunl0没有IP地址了;查看route会发现不再使用tunl0了,而是直接通过物理网卡转发。
ip addr
ip route
node02 节点部署
在 node01 节点上操作
cd /opt/
scp kubelet.sh proxy.sh root@20.0.0.59:/opt/
scp -r /opt/cni root@20.0.0.59:/opt/
在 node02 节点上操作
启动kubelet服务
cd /opt/
chmod +x kubelet.sh
./kubelet.sh 20.0.0.59
在 master01 节点上操作
kubectl get csr
NAME AGE SIGNERNAME REQUESTOR CONDITION
node-csr-BbqEh6LvhD4R6YdDUeEPthkb6T_CJDcpVsmdvnh81y0 10s kubernetes.io/kube-apiserver-client-kubelet kubelet-bootstrap Pending
node-csr-duiobEzQ0R93HsULoS9NT9JaQylMmid_nBF3Ei3NtFE 85m kubernetes.io/kube-apiserver-client-kubelet kubelet-bootstrap Approved,Issued
通过 CSR 请求
kubectl certificate approve node-csr-BbqEh6LvhD4R6YdDUeEPthkb6T_CJDcpVsmdvnh81y0
kubectl get csr
NAME AGE SIGNERNAME REQUESTOR CONDITION
node-csr-BbqEh6LvhD4R6YdDUeEPthkb6T_CJDcpVsmdvnh81y0 23s kubernetes.io/kube-apiserver-client-kubelet kubelet-bootstrap Approved,Issued
node-csr-duiobEzQ0R93HsULoS9NT9JaQylMmid_nBF3Ei3NtFE 85m kubernetes.io/kube-apiserver-client-kubelet kubelet-bootstrap Approved,Issued
在 node02 节点上操作
加载 ipvs 模块
for i in $(ls /usr/lib/modules/$(uname -r)/kernel/net/netfilter/ipvs|grep -o "^[^.]*");do echo $i; /sbin/modinfo -F filename $i >/dev/null 2>&1 && /sbin/modprobe $i;done
使用proxy.sh脚本启动proxy服务
cd /opt/
chmod +x proxy.sh
./proxy.sh 20.0.0.59
查看群集中的节点状态
kubectl get nodes
部署 CoreDNS
CoreDNS
- CoreDNS 是 Kubernetes 的默认 DNS 实现。
- 为 Kubernetes 集群内的 Pod 提供 DNS 服务。
- 通过创建 service 资源名称与 ClusterIP 的对应关系解析,避免将 service 的 ClusterIP 地址硬编码到应用程序代码中。
部署CoreDNS
在所有 node 节点上操作
- 上传
coredns.tar
到/opt
目录中。 - 使用 Docker 加载 CoreDNS 镜像:
cd /opt docker load -i coredns.tar
在 master01 节点上操作
- 上传
coredns.yaml
文件到/opt/k8s
目录中。 - 使用 kubectl 部署 CoreDNS:
cd /opt/k8s kubectl apply -f coredns.yaml
- 检查 CoreDNS Pod 的状态:
示例输出:kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE coredns-5ffbfd976d-j6shb 1/1 Running 0 32s
DNS 解析测试
- 使用 busybox 镜像运行一个临时 Pod 进行 DNS 解析测试:
kubectl run -it --rm dns-test --image=busybox:1.28.4 sh
- 在 busybox Pod 中执行
nslookup
命令:/ # nslookup kubernetes.default.svc.cluster.local. Server: 10.0.0.2 Address: 10.0.0.2:53Name: kubernetes.default.svc.cluster.local Address: 10.0.0.1
故障排除
-
如果 DNS 解析测试失败,可以尝试给
kubectl
绑定默认cluster-admin
管理员集群角色,授权集群操作权限:kubectl create clusterrolebinding cluster-system-anonymous --clusterrole=cluster-admin --user=system:anonymous
-
确保所有 node 节点上已经加载了 CoreDNS 的 Docker 镜像。
-
部署 CoreDNS 的配置文件
coredns.yaml
需要正确配置,确保 CoreDNS 能够正确解析 Kubernetes 集群内的服务。 -
在进行 DNS 解析测试时,确保 CoreDNS Pod 已经处于 Running 状态。