RKE2的简单使用

概述

软件版本: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

1
curl -sfL http://rancher-mirror.rancher.cn/rke2/install.sh | INSTALL_RKE2_MIRROR=cn sh -

设置rke2-server开机自启

1
systemctl enable rke2-server.service

启动rke2-server

1
systemctl start rke2-server.service

此时,将会通过rke2自动拉起kubelet,然后以static-pod方式启动api-server、Controller-manager、etcd、scheduler

日志查看:

1
journalctl -u rke2-server -f

默认情况下rke2将创建以下目录:

/var/lib/rancher/rke2/:存放额外部署的集群插件(core-dns、网络插件、Ingress-Controller)、etcd数据库存放路径、其他worker连接的token。
/etc/rancher/rke2/:连接集群的kubeconfig文件,以及集群组件参数配置信息。

将常用CLI配置软链接

1
2
3
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

1
2
mkdir -p ~/.kube/
cp /etc/rancher/rke2/rke2.yaml ~/.kube/config

验证查看:

1
2
3
kubectl get node
NAME STATUS ROLES AGE VERSION
rke-node6 Ready control-plane,etcd,master 72m v1.22.5+rke2r1

获取worker注册到server的token文件

1
cat /var/lib/rancher/rke2/server/token

部署worker
下载rke2二进制可执行文件,和自动配置rke2-server

1
curl -sfL http://rancher-mirror.rancher.cn/rke2/install.sh | INSTALL_RKE2_MIRROR=cn INSTALL_RKE2_TYPE="agent" sh -

启动rke2-agent服务

1
systemctl enable rke2-agent.service

配置rke2-agent服务

1
2
mkdir -p /etc/rancher/rke2/
vim /etc/rancher/rke2/config.yaml

配置文件内容如下:

1
2
server: https://<server>:9345
token: <token from server node>

注:
rke2 server 进程通过端口 9345 监听新节点的注册。Kubernetes API 仍然监听端口 6443。

启动服务,等待服务启动注册成功。

1
systemctl start rke2-agent.service

日志查看

1
journalctl -u rke2-agent -f

查看最终部署

1
2
3
4
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

测试验证

1
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文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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

1
docker run -itd -p 9345:9345 -p 6443:6443 -v ~/nginx.conf:/etc/nginx/nginx.conf nginx

实际生产环境部署建议部署两个nginx,中间通过keepalived维持vip实现统一入口。

部署第一个Server
下载rke2二进制可执行文件,和自动配置rke2-server

1
curl -sfL http://rancher-mirror.rancher.cn/rke2/install.sh | INSTALL_RKE2_MIRROR=cn sh -

设置rke2-server开机自启

1
systemctl enable rke2-server.service

配置config.yaml文件

1
mkdir /etc/rancher/rke2/ -p

1
touch config.yaml

输入以内容

1
2
3
tls-san:
- xxx.xxx.xxx.xxx
- www.xxx.com

此处填写LB的统一入口ip地址或域名,如果有多个换行分组方式隔开。

启动rke2-server

1
systemctl start rke2-server.service

将常用CLI配置软链接

1
2
3
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

1
2
mkdir -p ~/.kube/
cp /etc/rancher/rke2/rke2.yaml ~/.kube/config

可以将kubeconfig文件中的中的ip地址由127.0.0.1替换为实际LB的IP地址。

获取注册到server的token文件

1
cat /var/lib/rancher/rke2/server/token

配置其他Server
配置rke2-agent服务

1
2
mkdir -p /etc/rancher/rke2/
vim /etc/rancher/rke2/config.yaml

配置文件内容如下:

1
2
3
4
5
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

1
curl -sfL http://rancher-mirror.rancher.cn/rke2/install.sh | INSTALL_RKE2_MIRROR=cn sh -

设置rke2-server开机自启

1
systemctl enable rke2-server.service

启动rke2-server

1
systemctl start rke2-server.service

等待注册和集群启动

验证:

1
2
3
4
5
6
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集群状态。

1
2
3
4
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

下载离线安装脚本

1
curl -sfL https://get.rke2.io --output install.sh

部署安装

1
INSTALL_RKE2_ARTIFACT_PATH=/root/images sh install.sh

执行此脚本,将自动对离线介质进行解压到对应目录。
接下来就跟在线安装一样,启动RKE2的进程,进行部署server和agent
启动rke2

设置rke2-server开机自启

1
systemctl enable rke2-server.service

启动rke2-server

1
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可执行文件复制到对应目录

1
cp lib/systemd/system/* /usr/local/lib/systemd/system/

1
cp bin/* /usr/local/bin/
1
cp share/* /usr/local/share/ -rf

配置config.yaml,指定默认拉取镜像

1
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反向代理配置
比如:

1
2
3
4
5
6
7
8
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特性,在启用前需要先进行挂载。
检查是否有进行挂载

1
mount | grep /sys/fs/bpf

进行挂载

1
2
3
4
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'

在次检查

1
2
3
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

1
2
mkdir -p /etc/rancher/rke2/
vim /etc/rancher/rke2/config.yaml

添加以下参数

1
cni: cilium

启动rke2-server

1
systemctl start rke2-server.service

查看是否部署成功

1
2
3
4
5
6
7
8
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
2
3
4
5
6
7
etcd-arg:
- "quota-backend-bytes=858993459"
- "max-request-bytes=33554432"
kube-apiserver-arg:
- "watch-cache=true"
kubelet-arg:
- "system-reserved=cpu=1,memory=2048Mi"

配置完成后启动rke2-server。agent节点要同步时配置,否则kubelet和kube-proxy参数将不生效

检查参数是否生效
如:

1
ps aux|grep system-reserved

集群备份和还原

rke2备份文件保存在每个拥有etcd角色的节点的/var/lib/rancher/rke2/server/db/snapshots目录内,拥有多副本保存。
默认每隔12小时备份一次,保留5份。

注:目前版本只能通过定时备份,没有立刻备份的选型。

指定备份文件恢复

关闭rke2-server进程

1
systemctl stop rke2-server

指定文件恢复

1
2
3
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命令

1
/var/lib/rancher/rke2/bin/ctr --address /run/k3s/containerd/containerd.sock --namespace k8s.io container ls

crictl命令

1
2
export CRI_CONFIG_FILE=/var/lib/rancher/rke2/agent/etc/crictl.yaml
/var/lib/rancher/rke2/bin/crictl ps

1
/var/lib/rancher/rke2/bin/crictl --config /var/lib/rancher/rke2/agent/etc/crictl.yaml ps
1
/var/lib/rancher/rke2/bin/crictl --runtime-endpoint unix:///run/k3s/containerd/containerd.sock ps -a

最终都是连接到containerd的socket文件

查看日志

1
2
3
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

1
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

1
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

1
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

1
2
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

1
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