概述
软件版本:rke2 version v1.22.5+rke2r1
os:ubuntu18.04
RKE2是Rancher Kubernetes新的发行版,结合和k3s和RKE1的一些特性。与RKE1相比主要特性在于安全性,符合美国联邦政府部门的安全性和合规性,完整通过CIS安全基线标准,符合FIPS-140-2 标准和定期的镜像安全扫描。
比如结合k3s的一个单体二进制文件启动,底层runtime集成containerd。
与其他Kubernetes部署工具对比
| 组件集成度 | 安全性 | 组件容器化 | 部署简易性 | |
|---|---|---|---|---|
| kubeadm | 低,需要单独部署kubelet、runtime等组件,然后在通过static-pod启动其他组件。 | 中,默认安全配置 | 除kubelet外全部容器化 | 低,组件HA需要用户自己完成。 |
| RKE-1 | 低,单独部署runtime然后在通过rke部署集群。 | 中,默认安全配置 | 全部容器化 | 高,一键部署,组件HA自动完成 |
| RKE-2 | 高,单体二进制文件集成runtime和kubelet,一键启动。 | 高,专为安全而生,符合各项安全测试规范 | 除kubelet外全部容器化 | 中,每台节点需要单独操作安装,组件HA自动完成 |
RKE2部署
部署前提:
Linux部署前提条件:
- 关闭swap。
- 关闭NetworkManager(若有),或配置NetworkManager忽略 calico/flannel 相关网络接口。
- 关闭Selinux,或参考下述链接配置Selinux规则。
- 节点主机名采用标准FQDN格式。
若需要开启NetworkManager和Selinux,策略配置NetworkManager和Selinux策略链接:
https://rancher2.docs.rancher.cn/docs/rke2/known_issues/_index#networkmanager
通过完整兼容性测试的操作系统:
Ubuntu 18.04 (amd64)
Ubuntu 20.04 (amd64)
CentOS/RHEL 7.8 (amd64)
CentOS/RHEL 8.2 (amd64)
SLES 15 SP2 (amd64) (v1.18.16+rke2r1 和更新版本)
注:使用Cilium网络插件时,因为ebpf依赖内核技术,所以需要保证以下内核版本
1 、kernel版本 >= 4.9.17
通过RKE2单机方式快速部署Kubernetes
部署Server
下载rke2二进制可执行文件,和自动配置rke2-server
curl -sfL http://rancher-mirror.rancher.cn/rke2/install.sh | INSTALL_RKE2_MIRROR=cn sh -
设置rke2-server开机自启
systemctl enable rke2-server.service
启动rke2-server
systemctl start rke2-server.service
此时,将会通过rke2自动拉起kubelet,然后以static-pod方式启动api-server、Controller-manager、etcd、scheduler
日志查看:
journalctl -u rke2-server -f
默认情况下rke2将创建以下目录:
/var/lib/rancher/rke2/:存放额外部署的集群插件(core-dns、网络插件、Ingress-Controller)、etcd数据库存放路径、其他worker连接的token。
/etc/rancher/rke2/:连接集群的kubeconfig文件,以及集群组件参数配置信息。
将常用CLI配置软链接
ln -s /var/lib/rancher/rke2/bin/kubectl /usr/bin/kubectl
ln -s /var/lib/rancher/rke2/bin/ctr /usr/bin/ctr
ln -s /var/lib/rancher/rke2/bin/crictl /usr/bin/crictl
配置kubeconfig
mkdir -p ~/.kube/
cp /etc/rancher/rke2/rke2.yaml ~/.kube/config
验证查看:
kubectl get node
NAME STATUS ROLES AGE VERSION
rke-node6 Ready control-plane,etcd,master 72m v1.22.5+rke2r1
获取worker注册到server的token文件
cat /var/lib/rancher/rke2/server/token
部署worker
下载rke2二进制可执行文件,和自动配置rke2-server
curl -sfL http://rancher-mirror.rancher.cn/rke2/install.sh | INSTALL_RKE2_MIRROR=cn INSTALL_RKE2_TYPE="agent" sh -
启动rke2-agent服务
systemctl enable rke2-agent.service
配置rke2-agent服务
mkdir -p /etc/rancher/rke2/
vim /etc/rancher/rke2/config.yaml
配置文件内容如下:
server: https://<server>:9345
token: <token from server node>
注:
rke2 server 进程通过端口 9345 监听新节点的注册。Kubernetes API 仍然监听端口 6443。
启动服务,等待服务启动注册成功。
systemctl start rke2-agent.service
日志查看
1 | journalctl -u rke2-agent -f |
查看最终部署
kubectl get node
NAME STATUS ROLES AGE VERSION
rke-node6 Ready control-plane,etcd,master 81m v1.22.5+rke2r1
rke-node7 Ready <none> 70m v1.22.5+rke2r1
测试验证
kubectl create deployment test --image=busybox:1.28 --replicas=2 -- sleep 30000
通过RKE2高可用方式部署Kubernetes
前提条件:
Apiserver统一入口(可选),为了方便外部访问集群,需要在集群实现统一入口,可以通过L4负载均衡器或vip地址或智能轮询DNS。集群内部已经通过rke2-agent实现了worker访问api-server的多入口反向代理。
奇数个(推荐三个)的 server节点,运行 etcd、Kubernetes API 和其他控制节点服务。
部署顺序
- 启动第一个 server 节点
- 加入其他 server 节点
- 加入 agent 节点
部署负载均衡器(可选)
以nginx为例,配置转发到9345和后端6443端口
创建nginx.conf文件
events {
worker_connections 1024; ## Default: 1024
}
stream {
upstream kube-apiserver {
server host1:6443 max_fails=3 fail_timeout=30s;
server host2:6443 max_fails=3 fail_timeout=30s;
server host3:6443 max_fails=3 fail_timeout=30s;
}
upstream rke2 {
server host1:9345 max_fails=3 fail_timeout=30s;
server host2:9345 max_fails=3 fail_timeout=30s;
server host3:9345 max_fails=3 fail_timeout=30s;
}
server {
listen 6443;
proxy_connect_timeout 2s;
proxy_timeout 900s;
proxy_pass kube-apiserver;
}
server {
listen 9345;
proxy_connect_timeout 2s;
proxy_timeout 900s;
proxy_pass rke2;
}
}
将对应的3个ip地址修改为实际server节点ip地址
启动nginx
docker run -itd -p 9345:9345 -p 6443:6443 -v ~/nginx.conf:/etc/nginx/nginx.conf nginx
实际生产环境部署建议部署两个nginx,中间通过keepalived维持vip实现统一入口。
部署第一个Server
下载rke2二进制可执行文件,和自动配置rke2-server
curl -sfL http://rancher-mirror.rancher.cn/rke2/install.sh | INSTALL_RKE2_MIRROR=cn sh -
设置rke2-server开机自启
systemctl enable rke2-server.service
配置config.yaml文件
mkdir /etc/rancher/rke2/ -p
touch config.yaml
输入以内容
tls-san:
- xxx.xxx.xxx.xxx
- www.xxx.com
此处填写LB的统一入口ip地址或域名,如果有多个换行分组方式隔开。
启动rke2-server
systemctl start rke2-server.service
将常用CLI配置软链接
ln -s /var/lib/rancher/rke2/bin/kubectl /usr/bin/kubectl
ln -s /var/lib/rancher/rke2/bin/ctr /usr/bin/ctr
ln -s /var/lib/rancher/rke2/bin/crictl /usr/bin/crictl
配置kubeconfig
mkdir -p ~/.kube/
cp /etc/rancher/rke2/rke2.yaml ~/.kube/config
可以将kubeconfig文件中的中的ip地址由127.0.0.1替换为实际LB的IP地址。
获取注册到server的token文件
cat /var/lib/rancher/rke2/server/token
配置其他Server
配置rke2-agent服务
mkdir -p /etc/rancher/rke2/
vim /etc/rancher/rke2/config.yaml
配置文件内容如下:
server: https://<server>:9345
token: <token from server node>
tls-san:
- xxx.xxx.xxx.xxx
- www.xxx.com
注:
- server地址可以填写第一台Server的地址,也可以填写外部统一入口的地址,最佳实践是填写统一入口地址,这样当第一个Server出现问题后,agent还可以通过统一入口地址通过其他Server获取集群信息。
- token填写第一台server的token
- tls-san跟第一台server一样,一般填写统一入口的ip地址或域名,用于TLS证书注册。
下载rke2二进制可执行文件,和自动配置rke2-server
curl -sfL http://rancher-mirror.rancher.cn/rke2/install.sh | INSTALL_RKE2_MIRROR=cn sh -
设置rke2-server开机自启
systemctl enable rke2-server.service
启动rke2-server
systemctl start rke2-server.service
等待注册和集群启动
验证:
kubectl get node
NAME STATUS ROLES AGE VERSION
rke-node4 Ready control-plane,etcd,master 140m v1.22.5+rke2r1
rke-node5 Ready control-plane,etcd,master 138m v1.22.5+rke2r1
rke-node6 Ready control-plane,etcd,master 19h v1.22.5+rke2r1
rke-node7 Ready <none> 19h v1.22.5+rke2r1
进入etcd-pod,查看etcd集群状态。
etcdctl --cert /var/lib/rancher/rke2/server/tls/etcd/server-client.crt --key /var/lib/rancher/rke2/server/tls/etcd/server-client.key --endpoints https://127.0.0.1:2379 --cacert /var/lib/rancher/rke2/server/tls/etcd/server-ca.crt member list
e19d2834bb177be1, started, rke-node4-896165c9, https://192.168.0.25:2380, https://192.168.0.25:2379, false
ec67af24a94fb07c, started, rke-node6-fed10843, https://192.168.0.32:2380, https://192.168.0.32:2379, false
f7e9f28da0a6e5e6, started, rke-node5-4a4b6af5, https://192.168.0.29:2380, https://192.168.0.29:2379, false
按单机操作加入agent节点。
通过RKE2离线部署kubernetes集群
Tarball模式
RKE2的离线部署方式与k3s比较相似,都是提前将对应的离线介质下载放置到对应的目录,启动二进制进程执行。
在RKE2对应的Release页下载对应的离线安装介质
https://github.com/rancher/rke2/releases
主要为以下离线安装介质
- rke2-images.linux-amd64.tar
- rke2.linux-amd64.tar.gz
- sha256sum-amd64.txt
根据所需要的不同网络插件,下载对应的镜像包 - rke2-images-canal.linux-amd64.tar.gz
- 离线安装脚本
将这些下载后的安装介质放置在节点的一个统一目录如/root/images
下载离线安装脚本
curl -sfL https://get.rke2.io --output install.sh
部署安装
INSTALL_RKE2_ARTIFACT_PATH=/root/images sh install.sh
执行此脚本,将自动对离线介质进行解压到对应目录。
接下来就跟在线安装一样,启动RKE2的进程,进行部署server和agent
启动rke2
设置rke2-server开机自启
systemctl enable rke2-server.service
启动rke2-server
systemctl start rke2-server.service
等待注册和集群启动
Private Registry
将镜像上传到镜像仓库
可以使用rancher的rancher-load-images.sh脚本结合rke2-images-all.linux-amd64.txt文件进行镜像上传。
下载rke2可执行文件rke2.linux-amd64.tar.gz
解压,将systemctl文件和rke2可执行文件复制到对应目录
cp lib/systemd/system/* /usr/local/lib/systemd/system/
cp bin/* /usr/local/bin/
cp share/* /usr/local/share/ -rf
配置config.yaml,指定默认拉取镜像
system-default-registry: xxx.xxx.xxx.xxx
若私有镜像仓库为http或自签名https需要在/etc/rancher/rke2 /registries.yaml进行配置
但这里我配置的insecure-registry没有生效,具体issue查看:https://github.com/rancher/rke2/issues/2317
通过RKE2部署Kubernetes高可用实现原理
RKE2部署的Kubernetes和其他Kubernetes的组件需要HA的方式是一致的.
Kubernetes 集群的高可用是针对:
- etcd
- controller-manager
- scheduler
- apiserver
etcd:通过本身的 Raft 算法 Leader 选主机制,组成ETCD集群,实现 etcd 高可用。
controller manager:leader election 选举竞争锁的机制来保证高可用。
scheduler:leader election 选举竞争锁的机制来保证高可用。
apiserver:无状态,通过前端负载均衡实现高可用。
另外一个在于在rke2集群中,containerd、kubelet组件集成到了rke2服务中,这点和k3s非常相式,同时在rke2服务中还集成了nginx服务,主要用于做为kubelet连接api-server的方向代理。
HA的主要区别在于API-server统一入口,因为RKE2会帮助其他组件自动做HA,

当有统一入口时,跟kubeadm和其他原生Kubernetes一样,所有请求都会通过统一负载均衡器连接到后端的rke2-server。

如果api-server没有统一入口,kubelet和rke2-agent去连接rke2-server时,会用一个server地址去注册即可,然后agent会获取 所有rke2 server 的地址,然后存储到 /var/lib/rancher/rke2/agent/etc/rke2-api-server-agent-load-balancer.json中,生成nginx反向代理配置
比如:
cat rke2-agent-load-balancer.json
{
"ServerURL": "https://192.168.3.10:9345",
"ServerAddresses": [
"192.168.3.11:9345",
"192.168.3.12:9345"
],
"Listener": null
当192.168.3.10 挂掉之后,会自动切换到另一个rke2 server 去连接。当192.168.3.10恢复后,回重新连接192.168.3.10。
另外在前面也提到,rke2里面也集成了containerd,那么问题来了,如果rke2-agent进程出现问题down了,是否会影响平台上业务正常运行呢?
答案是,不会影响业务正常运行,因为containerd创建容器是通过containerd-shim-runc-v2调用runc创建,当containerd出现问题时containerd-shim-runc-v2会被init进程托管,不会导致退出影响现有业务POD。但需要注意的是rke2-agent退出后kubelet也退出了,对应的业务状态探测就没有了,在默认超时5分钟后,Controller-manager会将业务pod重建。
其他使用技巧
使用RKE2部署Kubernetes使用其他网络插件
默认情况下rke2部署使用的是canal做为网络插件,还支持calico和cilium网络插件,若想使用其他网络插件只需要进行配置即可。
如cilium
cilium依赖内核bfp特性,在启用前需要先进行挂载。
检查是否有进行挂载
mount | grep /sys/fs/bpf
进行挂载
sudo mount bpffs -t bpf /sys/fs/bpf
sudo bash -c 'cat <<EOF >> /etc/fstab
none /sys/fs/bpf bpf rw,relatime 0 0
EOF'
在次检查
mount | grep /sys/fs/bpf
bpffs on /sys/fs/bpf type bpf (rw,relatime)
bpffs on /sys/fs/bpf type bpf (rw,relatime)
在start rke2-server和agent服务前先配置config.yaml
mkdir -p /etc/rancher/rke2/
vim /etc/rancher/rke2/config.yaml
添加以下参数
cni: cilium
启动rke2-server
systemctl start rke2-server.service
查看是否部署成功
kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system cilium-6rfzw 1/1 Running 0 52s
kube-system cilium-node-init-998vd 1/1 Running 0 52s
kube-system cilium-operator-85f67b5cb7-nw7n8 1/1 Running 0 52s
kube-system cilium-operator-85f67b5cb7-qc2vh 0/1 Pending 0 52s
kube-system cloud-controller-manager-rke-node4 1/1 Running 0 65s
kube-system etcd-rke-node4 1/1 Running 0 73s
组件参数配置
在/etc/rancher/rke2/config.yaml 文件中,按照对应组件,添加对应的参数,如apiserver对应为kube-apiserver-arg,组件对应参数为etcd-arg。kube-controller-manager-arg、kube-scheduler-arg、kubelet-arg、kube-proxy-arg。
1 | etcd-arg: |
配置完成后启动rke2-server。agent节点要同步时配置,否则kubelet和kube-proxy参数将不生效
检查参数是否生效
如:
ps aux|grep system-reserved
集群备份和还原
rke2备份文件保存在每个拥有etcd角色的节点的/var/lib/rancher/rke2/server/db/snapshots目录内,拥有多副本保存。
默认每隔12小时备份一次,保留5份。
注:目前版本只能通过定时备份,没有立刻备份的选型。
将
指定备份文件恢复
关闭rke2-server进程
systemctl stop rke2-server
指定文件恢复
rke2 server \
--cluster-reset \
--cluster-reset-restore-path=<PATH-TO-SNAPSHOT>
若是HA集群,还原成功后在其他server节点将执行rm -rf /var/lib/rancher/rke2/server/db然后重新启动server,加入集群。
rke2跟rke1一样也支持将备份文件在一个新集群进行还原。
常见操作
参考链接:
https://gist.github.com/superseb/3b78f47989e0dbc1295486c186e944bf
查看本机运行的容器
ctr命令
/var/lib/rancher/rke2/bin/ctr --address /run/k3s/containerd/containerd.sock --namespace k8s.io container ls
crictl命令
export CRI_CONFIG_FILE=/var/lib/rancher/rke2/agent/etc/crictl.yaml
/var/lib/rancher/rke2/bin/crictl ps
/var/lib/rancher/rke2/bin/crictl --config /var/lib/rancher/rke2/agent/etc/crictl.yaml ps
/var/lib/rancher/rke2/bin/crictl --runtime-endpoint unix:///run/k3s/containerd/containerd.sock ps -a
最终都是连接到containerd的socket文件
查看日志
journalctl -f -u rke2-server
/var/lib/rancher/rke2/agent/containerd/containerd.log
/var/lib/rancher/rke2/agent/logs/kubelet.log
etcd操作
etcdctl check perf
for etcdpod in $(kubectl -n kube-system get pod -l component=etcd --no-headers -o custom-columns=NAME:.metadata.name); do kubectl -n kube-system exec $etcdpod -- sh -c "ETCDCTL_ENDPOINTS='https://127.0.0.1:2379' ETCDCTL_CACERT='/var/lib/rancher/rke2/server/tls/etcd/server-ca.crt' ETCDCTL_CERT='/var/lib/rancher/rke2/server/tls/etcd/server-client.crt' ETCDCTL_KEY='/var/lib/rancher/rke2/server/tls/etcd/server-client.key' ETCDCTL_API=3 etcdctl check perf"; done
etcdctl endpoint status
for etcdpod in $(kubectl -n kube-system get pod -l component=etcd --no-headers -o custom-columns=NAME:.metadata.name); do kubectl -n kube-system exec $etcdpod -- sh -c "ETCDCTL_ENDPOINTS='https://127.0.0.1:2379' ETCDCTL_CACERT='/var/lib/rancher/rke2/server/tls/etcd/server-ca.crt' ETCDCTL_CERT='/var/lib/rancher/rke2/server/tls/etcd/server-client.crt' ETCDCTL_KEY='/var/lib/rancher/rke2/server/tls/etcd/server-client.key' ETCDCTL_API=3 etcdctl endpoint status"; done
etcdctl endpoint health
for etcdpod in $(kubectl -n kube-system get pod -l component=etcd --no-headers -o custom-columns=NAME:.metadata.name); do kubectl -n kube-system exec $etcdpod -- sh -c "ETCDCTL_ENDPOINTS='https://127.0.0.1:2379' ETCDCTL_CACERT='/var/lib/rancher/rke2/server/tls/etcd/server-ca.crt' ETCDCTL_CERT='/var/lib/rancher/rke2/server/tls/etcd/server-client.crt' ETCDCTL_KEY='/var/lib/rancher/rke2/server/tls/etcd/server-client.key' ETCDCTL_API=3 etcdctl endpoint health"; done
etcdctl compact
rev=$(kubectl -n kube-system exec $(kubectl -n kube-system get pod -l component=etcd --no-headers -o custom-columns=NAME:.metadata.name | head -1) -- sh -c "ETCDCTL_ENDPOINTS='https://127.0.0.1:2379' ETCDCTL_CACERT='/var/lib/rancher/rke2/server/tls/etcd/server-ca.crt' ETCDCTL_CERT='/var/lib/rancher/rke2/server/tls/etcd/server-client.crt' ETCDCTL_KEY='/var/lib/rancher/rke2/server/tls/etcd/server-client.key' ETCDCTL_API=3 etcdctl endpoint status --write-out fields | grep Revision | cut -d: -f2")
kubectl -n kube-system exec $(kubectl -n kube-system get pod -l component=etcd --no-headers -o custom-columns=NAME:.metadata.name | head -1) -- sh -c "ETCDCTL_ENDPOINTS='https://127.0.0.1:2379' ETCDCTL_CACERT='/var/lib/rancher/rke2/server/tls/etcd/server-ca.crt' ETCDCTL_CERT='/var/lib/rancher/rke2/server/tls/etcd/server-client.crt' ETCDCTL_KEY='/var/lib/rancher/rke2/server/tls/etcd/server-client.key' ETCDCTL_API=3 etcdctl compact \"$(echo $rev)\""
etcdctl defrag
kubectl -n kube-system exec $(kubectl -n kube-system get pod -l component=etcd --no-headers -o custom-columns=NAME:.metadata.name | head -1) -- sh -c "ETCDCTL_ENDPOINTS='https://127.0.0.1:2379' ETCDCTL_CACERT='/var/lib/rancher/rke2/server/tls/etcd/server-ca.crt' ETCDCTL_CERT='/var/lib/rancher/rke2/server/tls/etcd/server-client.crt' ETCDCTL_KEY='/var/lib/rancher/rke2/server/tls/etcd/server-client.key' ETCDCTL_API=3 etcdctl defrag --cluster"
对应的,直接操作etcdctl
参考:https://gist.github.com/superseb/3b78f47989e0dbc1295486c186e944bf