title: kubernetes 1.18.3 集群部署 #标题tags: k8s #标签
date: 2020-06-14
categories: k8s # 分类
某个夜深人静的晚上,躺在床上的我翻来覆去无法入睡,思索再三,一个鲤鱼打挺,爬到了电脑前,写下了这篇文章。
环境准备
OS | IP | hostname |
---|---|---|
Centos 7.5 | 192.168.20.2 | master01 |
Centos 7.5 | 192.168.20.3 | node01 |
Centos 7.5 | 192.168.20.4 | node02 |
注:上述主机名即为集群中的角色,也就是说192.168.20.2为k8s中的master节点,其余为k8s中的node节点。每个主机,最少2G内存,CPU不得低于2核心。
安装前准备
接下来的操作,若无特殊说明,均需在所有节点上执行。
升级内核
此博文是安装的kubernetes 1.18.3版本,需将内核版本升至最新,否则可能会出现kubelet无法启动或pod无法解析域名等问题,请参考博文Centos 7.5内核升级进行升级。
在进行接下来的操作前,请保证你的内核版本在4.4.xxx以上。
$ uname -r
4.4.227-1.el7.elrepo.x86_64
修改hostname,并配置解析
$ hostnamectl set-hostname your-new-host-name
$ echo "127.0.0.1 $(hostname)" >> /etc/hosts
检查网络
必须保证所有节点上 Kubernetes 所使用的 IP 地址必须可以互通(无需 NAT 映射、无安全组或防火墙隔离)
是否安装k8s集群的硬性要求
必须满足以下几个硬性要求:
- 内核版本大于4.4.xxx。
- cpu核心数不低于2,内存不低于2G。
- hostname不是localhost,且不包含下划线、小数点、大写字母。
- 任意节点都有固定的内网IP地址。
- 任意节点上kubelet使用的IP地址在同一局域网内,没有网络策略隔离。
- 任意节点不会直接使用 docker run 或 docker-compose 运行容器。
安装docker 19.03
# 卸载旧版本docker
$ yum remove -y docker \
docker-client \
docker-client-latest \
docker-ce-cli \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine
# 设置 yum repository
$ yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 安装 docker
$ yum install -y docker-ce-19.03.8 docker-ce-cli-19.03.8 containerd.io
# 修改 docker 镜像下载源
$ [ -d /etc/docker ] || mkdir /etc/docker
echo "{\"registry-mirrors\": [\"https://registry.cn-hangzhou.aliyuncs.com\",\"https://4grd6p3s.mirror.aliyuncs.com\"]}" >> /etc/docker/daemon.json
# 修改docker的根目录(默认根目录为:/var/lib/docker),根据需要来确定是否要修改
# 修改根目录,只是在启动命令后增加“--graph=/data/lib/docker”
$ vim /usr/lib/systemd/system/docker.service # 跳转到14行,修改如下
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --graph=/data/lib/docker
# 启动docker
$ systemctl enable docker && systemctl start docker
# 确认 docker 版本及镜像下载地址
$ docker version
$ docker info | grep -A1 'Registry Mirrors:'
Registry Mirrors:
https://registry.cn-hangzhou.aliyuncs.com/
加载ipvs模块
# 若内核大于4.19替换nf_conntrack_ipv4为nf_conntrack:
$ 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
# 执行脚本
$ chmod 755 /etc/sysconfig/modules/ipvs.modules
/etc/sysconfig/modules/ipvs.modules
lsmod | grep -e ip_vs -e nf_conntrack_ipv4
# 安装相关管理工具
$ yum install ipset ipvsadm -y
调整系统其他配置
# 安装nfs-utils
$ yum install -y nfs-utils wget
# 关闭防火墙
$ systemctl stop firewalld
systemctl disable firewalld
# 关闭SeLinux
$ setenforce 0
sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config
# 禁用swap分区
$ swapoff -a
yes | cp /etc/fstab /etc/fstab_bak
cat /etc/fstab_bak |grep -v swap > /etc/fstab
# 调整内核参数
# 如果有配置,则修改
sed -i "s#^net.ipv4.ip_forward.*#net.ipv4.ip_forward=1#g" /etc/sysctl.conf
sed -i "s#^net.bridge.bridge-nf-call-ip6tables.*#net.bridge.bridge-nf-call-ip6tables=1#g" /etc/sysctl.conf
sed -i "s#^net.bridge.bridge-nf-call-iptables.*#net.bridge.bridge-nf-call-iptables=1#g" /etc/sysctl.conf
sed -i "s#^net.ipv6.conf.all.disable_ipv6.*#net.ipv6.conf.all.disable_ipv6=1#g" /etc/sysctl.conf
sed -i "s#^net.ipv6.conf.default.disable_ipv6.*#net.ipv6.conf.default.disable_ipv6=1#g" /etc/sysctl.conf
sed -i "s#^net.ipv6.conf.lo.disable_ipv6.*#net.ipv6.conf.lo.disable_ipv6=1#g" /etc/sysctl.conf
sed -i "s#^net.ipv6.conf.all.forwarding.*#net.ipv6.conf.all.forwarding=1#g" /etc/sysctl.conf
# 如果没有,则追加
cat >> /etc/sysctl.conf << EOF
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
net.ipv6.conf.all.forwarding = 1
EOF
# 执行命令以应用
$ sysctl -p
部署k8s
配置k8s的yum源
$ cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
卸载旧版本
$ yum remove -y kubelet kubeadm kubectl
安装kubelet、kubeadm、kubectl
$ yum install -y kubelet-1.18.3 kubectl-1.18.3 kubeadm-1.18.3
yum安装的kubeadm,初始化集群后,有个比较烦人的事情,就是多数证书的有效期为1年,最多的证书有效期是十年,一年之后,就需要更新集群证书或者升级集群,所以还需要编译一下kubedam,以便可以更改证书有效期(上述之所以还用yum装kubeadm,是因为我们需要其安装的依赖,而不是kubeadn指令)。
修改kubeadm源码并编译
修改kubeadm源码及编译等操作,只需在任意一台机器上执行即可,等编译完成后,再将编译的kubeadm指令发送至其他节点即可。
$ wget https://github.com/kubernetes/kubernetes/archive/v1.18.3.tar.gz
$ tar zxf v1.18.3.tar.gz && cd kubernetes-1.18.3/
修改CA证书时间
$ vim staging/src/k8s.io/client-go/util/cert/cert.go
# 跳转至66行,将10修改为100(是将十年的ca证书修改为100年)
65 NotBefore: now.UTC(),
66 NotAfter: now.Add(duration365d * 100).UTC(),
具体位置如下:
修改其他证书有效期
$ vim cmd/kubeadm/app/constants/constants.go
# 跳转至49行,修改如下(追加 * 100):
CertificateValidity = time.Hour * 24 * 365 * 100
具体位置如下:
编译kubeadm
可以采用容器运行一个go环境,如果你的宿主机有go环境,则用宿主机进行编译即可。
wget https://dl.google.com/go/go1.13.9.linux-amd64.tar.gz
tar zxf go1.13.9.linux-amd64.tar.gz -C /opt/
cat >> /etc/profile << EOF
export GOROOT=/opt/go
export PATH=\$PATH:\$GOROOT/bin
EOF
source /etc/profile
go version
make all WHAT=cmd/kubeadm GOFLAGS=-v
执行上述命令后,等待1~2分钟,输入如下:
将编译生成的指令copy到指定目录
# copy到本机
mv /usr/bin/kubeadm{,.old}
cp _output/local/bin/linux/amd64/kubeadm /usr/bin/
# 分发到其他节点
for i in 3 4;do rsync -az /usr/bin/kubeadm 192.168.20.${i}:/usr/bin/;done
好,接下来继续在所有节点上执行。
修改docker Cgroup Driver为systemd
如果不修改,在添加 worker 节点时可能会碰到如下错误
[WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd".
Please follow the guide at https://kubernetes.io/docs/setup/cri/
修改指令如下:
$ sed -i "s#^ExecStart=/usr/bin/dockerd.*#ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --exec-opt native.cgroupdriver=systemd --graph=/data/lib/docker#g" /usr/lib/systemd/system/docker.service
确认docker的cgroup driver
systemctl daemon-reload
systemctl restart docker
docker info | grep -i cgroup # 确认每个docker节点的cgroup driver为systemd
Cgroup Driver: systemd
启动kubelet
systemctl daemon-reload
systemctl enable kubelet
systemctl start kubelet
注:如果此时执行systemctl status kubelet
命令,会得到 kubelet 启动失败的错误提示,请忽略此错误,因为必须完成后续步骤中 kubeadm init 的操作,kubelet 才能正常启动。
错误如下:
初始化master节点
注:接下来的操作,只需要在master节点上进行配置。
配置环境变量
注:export 命令只在当前 shell 会话中有效,开启新的 shell 窗口后,如果要继续安装过程,请重新执行此处的 export 命令。
# 将192.168.20.2替换为你自己master节点的IP
$ export MASTER_IP=192.168.20.2
# 替换 apiserver.demo 为你想要的 dnsName
$ export APISERVER_NAME=apiserver.demo
# Kubernetes 容器组所在的网段,该网段安装完成后,由 kubernetes 创建,事先并不存在于我们的物理网络中
$ export POD_SUBNET=10.100.0.1/16
# 配置解析
$ echo "${MASTER_IP} ${APISERVER_NAME}" >> /etc/hosts
执行初始化master
# 由于后续可能会下载多个文件,所以创建新目录,以方便观察用到了哪些文件
$ mkdir k8s_deploy && cd k8s_deploy
# 准备kubeadm所需yaml文件
cat <<EOF > ./kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
kubernetesVersion: v1.18.3
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers
controlPlaneEndpoint: "${APISERVER_NAME}:6443"
networking:
serviceSubnet: "10.96.0.0/16"
podSubnet: "${POD_SUBNET}"
dnsDomain: "cluster.local"
EOF
# kubeadm 初始化
$ kubeadm init --config=kubeadm-config.yaml --upload-certs
配置kubectl
rm -rf /root/.kube/
mkdir /root/.kube/
cp -i /etc/kubernetes/admin.conf /root/.kube/config
安装calico网络插件
和calico网络插件功能一样的还有一个叫做flannel
网络插件,如果有兴趣,可以自行去github上查看。
好了,废话不多说,开始安装 calico 网络插件,参考:官方文档。
注:你的k8s集群节点数量是大于50个还是小于50个,所需进行的配置是不一样的,建议去官方文档看一眼。
我这里3个节点,肯定是按照小于50的配置来的咯。
补充:在我按照此文档部署集群后的某一天,我的集群重启了一次,然后calicao组件就出现了问题,故写在这里,建议在部署calica组件时,就将这个坑填上。
具体故障问题: k8s/calico组件故障排查。
# 下面下载的是kuboard官方提供的yml文件,如果失效了,请替换为官方的地址:https://docs.projectcalico.org/manifests/calico.yaml
$ wget https://kuboard.cn/install-script/calico/calico-3.13.1.yaml
$ kubectl apply -f calico-3.13.1.yaml
# 执行yaml文件后,请执行下面的操作,等待3-10分钟,直到所有的容器组处于 Running 状态
$ watch kubectl get pod -n kube-system -o wide
# 注:若网速不好,可能会导致镜像下载错误,这就不展开怎么解决了
# 提示:可以手动将yaml文件中指定的镜像下载下来,然后修改镜像下载策略为imagePullPolicy: IfNotPresent
# 然后执行指令 kubectl delete -f calico-3.13.1.yaml && kubectl apply -f calico-3.13.1.yaml 后继续观察。
必须保证所有容器处于running状态,如下:
如果初始化失败,请检查以下节点:
- 环境变量 MASTER_IP 的值应该为 master 节点的 内网IP,如果不是,请重新 export
- APISERVER_NAME 不能是 master 的 hostname
- APISERVER_NAME 必须全为小写字母、数字、小数点,不能包含减号
- POD_SUBNET 所使用的网段不能与 master节点/worker节点 所在的网段重叠。该字段的取值为一个 CIDR 值,如果对 CIDR 这个概念还不熟悉,请仍然执行 export POD_SUBNET=10.100.0.1/16 命令,不做修改
- 然后重新初始化master节点,重新初始化前,请先执行
kubeadm reset -f
操作。
初始化worker节点
获取join命令参数
# 在 master 节点上执行
$ kubeadm token create --print-join-command
# 输出如下:
W0614 03:26:48.357692 27702 configset.go:202] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
# 我们需要的就是下面kubeadm join指令,每个集群初始化出来的指令都不一样,请复制自己master输出的指令
kubeadm join apiserver.demo:6443 --token nihz20.sueqfz69toge9d15 --discovery-token-ca-cert-hash sha256:9960790c2fd65dfdc8dc8cd5bdcf89b5093539d8a108422ea9a93b7e28731c41
# 该 token 的有效时间为 2 个小时,2小时内,您可以使用此 token 初始化任意数量的 worker 节点。
初始化worker节点
所有worker节点都执行下述指令,以便加入k8s集群。
# 只在 worker 节点执行
# 替换 192.168.20.2 为 master 节点的内网 IP
$ export MASTER_IP=192.168.20.2
# 替换 apiserver.demo 为初始化 master 节点时所使用的 APISERVER_NAME
$ export APISERVER_NAME=apiserver.demo
# 配置解析
$ echo "${MASTER_IP} ${APISERVER_NAME}" >> /etc/hosts
# 替换为 master 节点上 kubeadm token create 命令的输出
$ kubeadm join apiserver.demo:6443 --token nihz20.sueqfz69toge9d15 --discovery-token-ca-cert-hash sha256:9960790c2fd65dfdc8dc8cd5bdcf89b5093539d8a108422ea9a93b7e28731c41
最终,在master上查看所有pod状态,全为running即可,如下:
查看node状态全为Ready:
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready master 36m v1.18.3
node01 Ready <none> 9m58s v1.18.3
node02 Ready <none> 8m15s v1.18.3
确认集群证书有效期
查看集群证书有效期是否为100年
$ kubeadm alpha certs check-expiration
输出如下:
worker节点不能join成功
如果遇到worker节点不能成功的join到k8s集群,那么请按照以下思路来解决问题。
在worker节点执行以下语句可验证worker节点是否能访问 apiserver
$ curl -ik https://apiserver.demo:6443
如果不能,请在 master 节点上验证
$ curl -ik https://apiserver.demo:6443
正常输出结果如下:
HTTP/1.1 403 Forbidden
Cache-Control: no-cache, private
Content-Type: application/json
X-Content-Type-Options: nosniff
Date: Sat, 13 Jun 2020 19:44:58 GMT
Content-Length: 233
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {
},
"status": "Failure",
"message": "forbidden: User \"system:anonymous\" cannot get path \"/\"",
"reason": "Forbidden",
"details": {
},
"code": 403
可能原因
如果 master 节点能够访问 apiserver、而 worker 节点不能,则请检查自己的网络设置
- /etc/hosts 是否正确设置?
- 是否有安全组或防火墙的限制?
worker 节点默认网卡
- Kubelet使用的 IP 地址 与 master 节点可互通(无需 NAT 映射),且没有防火墙、安全组隔离,如果你使用 vmware 或 virtualbox 创建虚拟机用于 K8S 学习,可以尝试 NAT 模式的网络,而不是桥接模式的网络。
移除worker节点并重试
注:正常情况下,无需移除 worker 节点,如果添加到集群出错,可以移除 worker 节点,再重新尝试添加。
在准备移除的 worker 节点上执行
# 只在 worker 节点执行
$ kubeadm reset -f
在 master 节点上执行
# 只在 master 节点执行,获取worker列表
kubectl get nodes -o wide
# 只在 master 节点执行,将demo-worker-x-x替换为你要移除的节点
kubectl delete node demo-worker-x-x
部署k8s管理工具——kuboard
兼容性如下:
Kubernetes 版本 | Kuboard 版本 | 兼容性 | 说明 |
---|---|---|---|
v1.18 | v1.0.x,v2.0.x | 😄 | 已验证 |
v1.17 | v1.0.x,v2.0.x | 😄 | 已验证 |
v1.16 | v1.0.x,v2.0.x | 😄 | 已验证 |
v1.15 | v1.0.x,v2.0.x | 😄 | 已验证 |
v1.14 | v1.0.x,v2.0.x | 😄 | 已验证 |
v1.13 | v1.0.x,v2.0.x | 😄 | 已验证 |
v1.12 | v1.0.x,v2.0.x | 😐 | Kuboard 不支持 Kubernetes v1.12 |
v1.11 | v1.0.x,v2.0.x | 😐 | Kuboard 不支持 Kubernetes v1.11 |
安装kuboard
# 安装
$ kubectl apply -f https://kuboard.cn/install-script/kuboard.yaml
$ kubectl apply -f https://addons.kuboard.cn/metrics-server/0.3.6/metrics-server.yaml
# 查看kuboard运行状态,直到状态为running
$ watch kubectl get pods -l k8s.kuboard.cn/name=kuboard -n kube-system
NAME READY STATUS RESTARTS AGE
kuboard-7bb89b4cc4-99l9n 1/1 Running 0 2m22s
获取Token
Token有两种类型,分别是管理员用户、只读用户的Token,这里将分别写下两种token的查看方式。
获取管理员用户的Token
此Token拥有 ClusterAdmin 的权限,可以执行所有操作。
# 执行命令如下
$ echo $(kubectl -n kube-system get secret $(kubectl -n kube-system get secret | grep kuboard-user | awk '{print $1}') -o go-template='{{.data.token}}' | base64 -d)
# 输出如下(复制输出内容)
eyJhbGciOiJSUzI1NiIsImtpZCI6IllWaUVoOXZtUUNlS25JaVpPZVhReGhnNzZjcExzSFVfZy1ycGJiZkp0ZEUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJrdWJvYXJkLXVzZXItdG9rZW4tajRidHgiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoia3Vib2FyZC11c2VyIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiNjMxNDM3ODQtMWM4My00NzRiLWExMGUtMDE0ZjY4MDA1NGUyIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmt1Ym9hcmQtdXNlciJ9.i6z0pUpyYdBlfwkMEH4FTjsz550J3fGn_e9uNrke_TpLasvvQlqfwQ8_kUOrjXyztW42ANcTZTVZ2z8lE7tsf53FpKwDnhZ3Swt0pcC018Cm-4q0YhkHqJlh6l4c6DiPqqPetYfvOOfXee-f9EbuQVCMVLqDfqZKwDM8Qa3gt81tk4oFwlDfahNdUmL0UQXXm_2LXQHqcXJ5slc7V1NDngou8aSxA1GgfFsQB8SxIjYlatD5mG_ZyIpX9gPZxiDWgOJDCogwIhrJGa2vDPnhZSayqJwZrIvsS2WLejeh5w7D0p6ZdNg53R_pPjOt5NLgeJZQCF3pvvo-touWNbnTPA
获取只读用户的Token
只读用户拥有的权限如下:
- view 可查看名称空间的内容
- system:node 可查看节点信息
- system:persistent-volume-provisioner 可查看存储类和存储卷声明的信息
适用场景:
只读用户不能对集群的配置执行修改操作,非常适用于将开发环境中的 Kuboard 只读权限分发给开发者,以便开发者可以便捷地诊断问题。
# 执行命令如下
$ echo $(kubectl -n kube-system get secret $(kubectl -n kube-system get secret | grep kuboard-viewer | awk '{print $1}') -o go-template='{{.data.token}}' | base64 -d)
# 复制输出的Token信息
eyJhbGciOiJSUzI1NiIsImtpZCI6IllWaUVoOXZtUUNlS25JaVpPZVhReGhnNzZjcExzSFVfZy1ycGJiZkp0ZEUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJrdWJvYXJkLXZpZXdlci10b2tlbi1tNzRkbCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJrdWJvYXJkLXZpZXdlciIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjNjMTI0NmExLTgzZTktNGZlZC1hNGQ2LTRkMjYzNzQ1YjBjZiIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTprdWJvYXJkLXZpZXdlciJ9.jpuVX2aYmpycjcXxTnMCnJre_F10OHiMZPgcOxnPJ3B_5ZeDHzj__06MCn2IF0x8yZZmJIqqr57HIWU5eGKk1jqxuC1OHCQGcG4RGL0e0hCcW-MW2nRT6YMWTiqGMGQ9Ooydt3pLaTEdJAg0ZnMXY5eoBIk9TX_UzoQASH0kkBnjqFDwaJ8-O6bybVB1cNQIlUug2mSgY2sWn-JvyA9doeq7qjS5mXrO_rGbGwUR2HL_KWNeFd9Ha_GWpnSHMdARMTCgDHiV_sznRFG72puWgg-J_2oSEC8pM8-VpBRSxzHbgEI5-ANP2fwjpcJDT8SdBHC5XntGT3ctA66de2T8vQ
访问Kuboard
Kuboard Service 使用了 NodePort 的方式暴露服务,NodePort 为 32567;可以按如下方式访问 Kuboard:
http://任意一个Worker节点的IP地址:32567/
访问登录页面:
登录后的首页如下:
不要以为就这些东西,很多地方都是可以点击进去的,如下:
加入节点至k8s集群中
上面部署的是一个master、两个node的k8s集群,那么后续根据业务需求,需要新增node节点或者说要把master做成高可用,那应该怎么弄呢?这里就来写一下,参考:
加入master节点
如果对master节点做高可用,那么至少要三个master节点,所以这里还需要新增两个master节点,并且呢,针对着三个master节点,还要做个VIP,以便将apiserver的解析记录指定为这个VIP。
实现VIP的方式有很多种:
1、自己写网卡配置文件,增加IPADDR1 选项,配置VIP,当节点宕掉后,可以将VIP配置到其他master节点,这样需要人工参与切换VIP,但不会新增其他服务,当然,这样的话,对于apiserever的请求只会落在那个VIP所在的节点,其他两个master处于空闲状态,这个没关系的,master的资源消耗本就不大。
2、使用keepalived,将三个master配置为一个虚拟组,由keepalived来控制vip绑定在哪个节点,以及VIP的自动切换,推荐此方式。
3、使用keepalived+nginx,需要新增两个nginx,轮询后端三个master节点,然后针对这两个nginx,通过keepalived来做到高可用,其中,nginx也可以换成其他负载方式,如:haporxy、lvs,不推荐此方式,需要依赖较多的组件,并且增加一层代理,转发效率将会受到影响。
我这里将采用第二种方式,将三个master节点通过keepalived,加入到一个备份组,VIP可以落在任意一个master节点上。
配置VIP
假设我这里新增两个节点:192.168.20.5、192.168.20.6 以master的角色加入到集群,并且主机名分别为 master02、master03,那么就需要将master01/2/3 作为一个热备组,以便VIP可以绑定在这三个master节点的任意一个。VIP地址为: 192.168.20.20。
安装keepalived
三个master节点都安装keepalived
$ yum -y install keepalived
配置VIP到master01节点
由于现在master01已经是集群中的master角色,所以需要将VIP先绑定在master01上,才可以正确的进行后面的工作(其余两个节点由于还未加入集群,故先不配置keepalived)。
master01节点配置如下
关于keepalived的各项配置,可以参考博文:Keepalived配置详解。
# 修改keepalived配置文件
$ cat > /etc/keepalived/keepalived.conf << EOF
global_defs {
script_user root
router_id MASTER-01
}
vrrp_script chk_apiserver {
script "/etc/keepalived/chk_apiserver.sh"
interval 2
}
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 23
priority 100
nopreempt
advert_int 1
authentication {
auth_type PASS
auth_pass 1234
}
virtual_ipaddress {
192.168.20.20/24
}
track_script {
chk_apiserver
}
}
EOF
# 定义apiserver健康检查脚本
$ cat > /etc/keepalived/chk_apiserver.sh << 'EEE'
keepalived_log=/etc/keepalived/vip.log
apiserver_port=$(ss -lnpt | grep 6443 | wc -l) # 确保此处过滤出来的是你的进程
if [[ ${apiserver_port} -eq 0 ]];then
cat >> ${keepalived_log} << EOF
apiserver stopped running at $(date '+%F %T')
Stopping keepalived ...
EOF
systemctl stop keepalived
fi
EEE
# 赋予脚本执行权限
$ chmod +x /etc/keepalived/chk_apiserver.sh
启动keepalived
$ systemctl start keepalived # 启动keepalived
$ ip a # 确保VIP已经配置上
修改apiserver的解析IP
当VIP成功配置到master01后,就可以修改k8s集群中所有节点的apiserver.demo
域名解析到这个VIP了。自行操作即可。
$ vim /etc/hosts
192.168.20.20 apiserver.demo
初始化第二、三个master节点
获得 master 节点的 join 命令
可以和第一个Master节点一起初始化第二、三个Master节点,也可以从单Master节点调整过来,只需要
- 增加Master的 LoadBalancer(已通过VIP解决)
- 将所有节点的 /etc/hosts 文件中 apiserver.demo 解析为 LoadBalancer 的地址(已修改为VIP的地址)
- 添加第二、三个Master节点
- 初始化 master 节点的 token 有效时间为 2 小时
和第一个master节点一起初始化
如果是在第一个master节点初始化后的两小时内,又要初始化第二个第三个节点,那么只需在新节点上进行如下操作即可:
按照此博文开头,进行安装docker、调整配置等操作,具体要做的如下:
- 升级内核
- 修改hostname,并配置解析
- 检查网络
- 是否安装k8s集群的硬性要求
- 安装docker 19.03
- 调整系统其他配置
- 配置k8s的yum源
- 卸载旧版本
- 安装kubelet、kubeadm、kubectl
- 修改docker Cgroup Driver为systemd
- 确认docker的cgroup driver
- 启动kubelet
- 将master01编译后的kubeadm命令分发至master02和master03
- 为了避免镜像下载时间过长,可以将
calico
相关的三个镜像,先从别的节点导入到要加入集群的节点。
当上面的工作都完成后,那么只需要进行如下操作了:
# 只在第二、三个 master 节点 master01 和 master02 执行
# 替换 x.x.x.x 为 VIP地址
export APISERVER_IP=x.x.x.x
# 替换 apiserver.demo 为 前面已经使用的 dnsName
export APISERVER_NAME=apiserver.demo
echo "${APISERVER_IP} ${APISERVER_NAME}" >> /etc/hosts
# 使用初始化第一个master节点时获得的第二、三个 master 节点的 join 命令
kubeadm join apiserver.demo:6443 --token ejwx62.vqwog6il5p83uk7y \
--discovery-token-ca-cert-hash sha256:6f7a8e40a810323672de5eee6f4d19aa2dbdb38411845a1bf5dd63485c43d303 \
--control-plane --certificate-key 70eb87e62f052d2d5de759969d5b42f372d0ad798f98df38f7fe73efdf63a13c
# 只需要将上面的kubeadm命令替换为你初始化第一个master节点时输出的指令即可。
第一个master节点初始化2小时后再初始化
上面是初始化第一个master节点的两小时内,加入master的方案,那么如果在master01初始化已经过了很久了,此时需要新加入master节点,应该怎么做呢?
下面是具体配置过程。
按照此博文开头,进行安装docker、调整配置等操作,具体要做的如下:
- 升级内核
- 修改hostname,并配置解析
- 检查网络
- 是否安装k8s集群的硬性要求
- 安装docker 19.03
- 调整系统其他配置
- 配置k8s的yum源
- 卸载旧版本
- 安装kubelet、kubeadm、kubectl
- 修改docker Cgroup Driver为systemd
- 确认docker的cgroup driver
- 启动kubelet
- 将master01编译后的kubeadm命令分发至master02和master03
- 为了避免镜像下载时间过长,可以将
calico
相关的三个镜像,先从别的节点导入到要加入集群的节点。
当上述准备工作都完成后,即可进行如下操作:
# master01 上执行,获取certificate key
$ kubeadm init phase upload-certs --upload-certs # 只在 第一个 master 节点 master01 执行
I0124 18:35:17.502961 82541 version.go:252] remote version is much newer: v1.20.2; falling back to: stable-1.18
W0124 18:35:25.635218 82541 configset.go:202] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
[upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
[upload-certs] Using certificate key: # 我们需要的就是下面的key
12fcb810e71cbd1a732aae6db92cb4a192634d9c2cf9591503bdcc9f84e34e51
# 获取join命令
$ kubeadm token create --print-join-command # 只在 第一个 master 节点 master01 执行
W0124 18:36:48.528349 84266 configset.go:202] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
kubeadm join apiserver.demo:6443 --token 1gpxxr.ja1evfq98u2sra8n --discovery-token-ca-cert-hash sha256:44d8e65585d22541d833801dc4be2b66d28e7836ddcc3a2cc1992afe355d7f46
则,第二、三个 master 节点的 join 命令如下(先将命令拼凑好,还不可以执行哦):
- 如下命令中,
--control-plane --certificate-key
为手动新增配置,--control-plane --certificate-key
前面来自于上面获得的join命令,--control-plane --certificate-key
之后的来自于上面获得的 certificate key。
$ kubeadm join apiserver.demo:6443 --token 1gpxxr.ja1evfq98u2sra8n \
--discovery-token-ca-cert-hash sha256:44d8e65585d22541d833801dc4be2b66d28e7836ddcc3a2cc1992afe355d7f46 \
--control-plane --certificate-key 12fcb810e71cbd1a732aae6db92cb4a192634d9c2cf9591503bdcc9f84e34e51
初始化第二、三个 master 节点
# 只在master02和master03 这两个未加入集群的master节点上执行
$ export APISERVER_IP=192.168.20.20 # 此IP为VIP地址
$ export APISERVER_NAME=apiserver.demo # 替换 apiserver.demo 为 前面已经使用的 dnsName
$ echo "${APISERVER_IP} ${APISERVER_NAME}" >> /etc/hosts
# 执行前面拼凑好的join命令
$ kubeadm join apiserver.demo:6443 --token 1gpxxr.ja1evfq98u2sra8n \
--discovery-token-ca-cert-hash sha256:44d8e65585d22541d833801dc4be2b66d28e7836ddcc3a2cc1992afe355d7f46 \
--control-plane --certificate-key 12fcb810e71cbd1a732aae6db92cb4a192634d9c2cf9591503bdcc9f84e34e51
# 当join成功后,执行如下命令,以便master02/03可以操作集群
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
配置master02的keepalived
cat > /etc/keepalived/keepalived.conf << EOF
global_defs {
script_user root
router_id MASTER-02
}
vrrp_script chk_apiserver {
script "/etc/keepalived/chk_apiserver.sh"
interval 2
}
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 23
priority 100
nopreempt
advert_int 1
authentication {
auth_type PASS
auth_pass 1234
}
virtual_ipaddress {
192.168.20.20/24
}
track_script {
chk_apiserver
}
}
EOF
# 定义apiserver健康检查脚本
$ cat > /etc/keepalived/chk_apiserver.sh << 'EEE'
keepalived_log=/etc/keepalived/vip.log
apiserver_port=$(ss -lnpt | grep 6443 | wc -l) # 确保此处过滤出来的是你的进程
if [[ ${apiserver_port} -eq 0 ]];then
cat >> ${keepalived_log} << EOF
apiserver stopped running at $(date '+%F %T')
Stopping keepalived ...
EOF
systemctl stop keepalived
fi
EEE
# 赋予脚本执行权限
$ chmod +x /etc/keepalived/chk_apiserver.sh
# 启动keepalived
$ systemctl restart keepalived
配置master03的keepalived
cat > /etc/keepalived/keepalived.conf << EOF
global_defs {
script_user root
router_id MASTER-03
}
vrrp_script chk_apiserver {
script "/etc/keepalived/chk_apiserver.sh"
interval 2
}
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 23
priority 100
nopreempt
advert_int 1
authentication {
auth_type PASS
auth_pass 1234
}
virtual_ipaddress {
192.168.20.20/24
}
track_script {
chk_apiserver
}
}
EOF
# 定义apiserver健康检查脚本
$ cat > /etc/keepalived/chk_apiserver.sh << 'EEE'
keepalived_log=/etc/keepalived/vip.log
apiserver_port=$(ss -lnpt | grep 6443 | wc -l) # 确保此处过滤出来的是你的进程
if [[ ${apiserver_port} -eq 0 ]];then
cat >> ${keepalived_log} << EOF
apiserver stopped running at $(date '+%F %T')
Stopping keepalived ...
EOF
systemctl stop keepalived
fi
EEE
# 赋予脚本执行权限
$ chmod +x /etc/keepalived/chk_apiserver.sh
# 启动keepalived
$ systemctl restart keepalived
加入worker节点
# 在任意master节点执行,以便获取work加入集群的指令
$ kubeadm token create --print-join-command # 我们需要的就是下面的指令
kubeadm join apiserver.demo:6443 --token uxz2wd.95nz40pjfugdaoa2 --discovery-token-ca-cert-hash sha256:44d8e65585d22541d833801dc4be2b66d28e7836ddcc3a2cc1992afe355d7f46
按照此博文开头,针对要加入集群的worker节点进行安装docker、调整配置等操作,具体要做的如下:
- 升级内核
- 修改hostname,并配置解析
- 检查网络
- 是否安装k8s集群的硬性要求
- 安装docker 19.03
- 调整系统其他配置
- 配置k8s的yum源
- 卸载旧版本
- 安装kubelet、kubeadm、kubectl
- 修改docker Cgroup Driver为systemd
- 确认docker的cgroup driver
- 启动kubelet
- 将master01编译后的kubeadm命令分发至master02和master03
- 为了避免镜像下载时间过长,可以将
calico
相关的三个镜像,先从别的节点导入到要加入集群的节点。
初始化woker节点
以下操作在要加入集群的worker节点执行即可。
$ export APISERVER_IP=192.168.20.20 # 此IP为VIP地址
$ export APISERVER_NAME=apiserver.demo # 替换 apiserver.demo 为 前面已经使用的 dnsName
$ echo "${APISERVER_IP} ${APISERVER_NAME}" >> /etc/hosts
# 加入集群
$ kubeadm join apiserver.demo:6443 --token uxz2wd.95nz40pjfugdaoa2 --discovery-token-ca-cert-hash sha256:44d8e65585d22541d833801dc4be2b66d28e7836ddcc3a2cc1992afe355d7f46
验证集群
查看node节点运行情况
$ kubectl get nodes -o wide
返回如下:
查看pod运行情况
$ kubectl get pod -n kube-system -o wide
返回如下:
验证etcd集群
$ kubectl -n kube-system exec etcd-master02 -- etcdctl --endpoints=https://192.168.20.2:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key member list -wtable
返回如下:
$ kubectl -n kube-system exec etcd-master02 -- etcdctl --endpoints=https://192.168.20.2:2379,https://192.168.20.5:2379,https://192.168.20.6:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key endpoint status
返回如下:
验证集群转发模式
查看kube-proxy日志,输出信息包含Using ipvs Proxier,则表示使用的是ipvs转发模式,效率最好。输出信息包含Using iptables Proxier.
则表示使用的iptables模式,相比较ipvs,效率较低。
# pod名称根据自己的实际名称来定
$ kubectl -n kube-system logs kube-proxy-wlmdm
iptables模式的话,返回如下: