搭建高可用K3S集群

k3s是经CNCF一致性认证的Kubernetes发行版,专为物联网及边缘计算设计。

bash

# 定义安装参数	
export INSTALL_K3S_VERSION=v1.18.9+k3s1
export INSTALL_K3S_EXEC="--docker --kube-apiserver-arg service-node-port-range=1-65000 --no-deploy traefik --write-kubeconfig  ~/.kube/config --write-kubeconfig-mode 666"
# 安装
sudo curl -sfL http://rancher-mirror.cnrancher.com/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn sh -
  • MySQL,LB,Rancher UI单独部署
  • 3个master节点,实现最基本的K3S-Server冗余
  • 2个worker节点,通过LB 接入master节点

数据库也可以做HA LB 只需要支持4层负载均衡,此处使用nginx

服务器用途配置IP
k3s-lbLB/Rancher UI/MySQL2C4G10.11.12.100
k3s-m1K3S-Server(master 节点)1C2G10.11.12.101
k3s-m2K3S-Server(master 节点)1C2G10.11.12.102
k3s-m3K3S-Server(master 节点)1C2G10.11.12.103
k3s-worker1K3S-Agent(worker 节点)2C2G10.11.12.104
k3s-worker2K3S-Agent(worker 节点)2C2G10.11.12.105
  • 操作系统:CentOS 7.6Alpine 3.12也实验通过
  • Docker Version: 19.03.9

高可用架构图

k3s-architecture-ha-server

对比一下单机版架构图

k3s-architecture-single-server

全新系统,主要是安装docker,并配置加速镜像,以及一些内核参数优化。

登录每一个服务器,修改对应的机器名

bash

hostnamectl --static set-hostname k3s-lb && hostnamectl set-hostname k3s-lb
hostnamectl --static set-hostname k3s-m1 && hostnamectl set-hostname k3s-m1
hostnamectl --static set-hostname k3s-m2 && hostnamectl set-hostname k3s-m2
hostnamectl --static set-hostname k3s-m3 && hostnamectl set-hostname k3s-m3
hostnamectl --static set-hostname k3s-worker1 && hostnamectl set-hostname k3s-worker1
hostnamectl --static set-hostname k3s-worker2 && hostnamectl set-hostname k3s-worker2

安装MySQL(已有MySQL可忽略)

bash

docker run -d  \
--name k3s-mysql  \
--restart=always  \
-v /data/k3s-cluster/mysql/conf:/etc/mysql/conf.d \
-v /data/k3s-cluster/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=root \
-p 3306:3306 \
mysql:5.7.29 \
--default-time-zone=+8:00

安装 Rancher UI

bash

docker run -d \
--restart=unless-stopped \
--name rancher-server \
-v /data/rancher/:/var/lib/rancher/ \
-p 8088:80 -p 8443:443 \
--privileged \
rancher/rancher:stable

与 2.4.x 或之前的版本相比,使用docker run命令安装 Rancher 2.5.x 时,需要添加--privileged标志变量,启用特权模式安装 Rancher。

你需要记下这个容器的运行参数,升级的时候还会用到(如果忘记,可以docker inspect rancher-server查看)。

访问地址 https://10.11.12.100:8443

安装Nginx(略)

注意:编译时需要添加stream模块

配置 nginx ,添加stream配置

text

events {
    # ....
}
http {
    # ...
}
# 新加的部分
stream {
    upstream k3s {
        server 10.11.12.101:6443;
        server 10.11.12.102:6443;
        server 10.11.12.103:6443;
    }
 
    server {
       listen 6443;
       proxy_pass k3s;
    }
}

配置 host (/etc/hosts)

bash

echo "10.11.12.100 k3s-mysql-server" >> /etc/hosts

安装K3S-Server,使用开始创建的用户运行(不要使用root用户执行)

bash

curl -sfL http://rancher-mirror.cnrancher.com/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn sh -s - server \
  --datastore-endpoint="mysql://root:root@tcp(k3s-mysql-server:3306)/database-name"

INSTALL_K3S_VERSION=v1.19.9+k3s1 从 Github 下载 K3s 的版本。如果没有指定,将尝试从"stable"频道下载。 INSTALL_K3S_EXEC='args'为 k3s 提供其他参数。

bash

# 定义安装参数	
export INSTALL_K3S_VERSION=v1.19.9+k3s1
export INSTALL_K3S_EXEC="--datastore-endpoint mysql://root:root@tcp(k3s-mysql-server:3306)/k3s \
--docker \
--kube-apiserver-arg service-node-port-range=1-65000 \
--kube-proxy-arg proxy-mode=ipvs \
--no-deploy traefik \
--write-kubeconfig  ~/.kube/config \
--write-kubeconfig-mode 644 \
--node-taint k3s-controlplane=true:NoExecute"

参数说明:

text

--datastore-endpoint value	# 指定 etcd、Mysql、Postgres 或 Sqlite(默认)数据源名称
--docker	# 用docker代替containerd
--kube-proxy-arg value	# 自定义 kube-proxy 进程的参数
--kube-apiserver-arg value	# 自定义kube-apiserver进程的参数
--no-deploy value	# 不需要部署的组件 (有效选项: coredns, servicelb, traefik, local-storage, metrics-server)
--write-kubeconfig value	# 将管理客户端的kubeconfig写入这个文件
--write-kubeconfig-mode	# 用这种模式编写kubeconfig,例如:644
--node-taint value	# 用一组污点注册kubelet

安装

bash

curl -sfL http://rancher-mirror.cnrancher.com/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn sh -

执行命令后,使用kubectl get nodes查看状态,如果成功能看到3个节点 如需重新安装可以卸载脚本 /usr/local/bin/k3s-uninstall.sh

默认情况下,k3s 启动 master 节点也同时具有 worker 角色,是可调度的,因此可以在它们上启动工作

1、通过 --node-taint

bash

curl -sfL http://rancher-mirror.cnrancher.com/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn INSTALL_K3S_EXEC="--node-taint k3s-controlplane=true:NoExecute" sh -

–node-taint key1=value1:NoExecute NoSchedule: 不调度 PreferNoSchedule: 尽量不调度 NoExecute: 不调度并且立即驱逐节点上现存pod

2、通过 --disable-agent

bash

curl -sfL http://rancher-mirror.cnrancher.com/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn INSTALL_K3S_EXEC="--disable-agent" sh -

去除taint

bash

kubectl describe node k3s-m1 | grep Taint
kubectl taint nodes k3s-m1 k3s-controlplane:NoExecute-

更多参数参考:K3s Server 配置参考的K3s Server CLI 帮助

先登录任意一个master节点,查看node-token

bash

cat /var/lib/rancher/k3s/server/node-token

在worker节点上执行,使用开始创建的用户(不要使用root用户执行)

bash

export K3S_TOKEN={node-token的内容}
# export K3S_TOKEN=K106f30302c8e0e3e07a4476d8add6712043c154b668e1f4f8c128c2687c5b994a6::server:5b5e57722986d80b8d2db3b75064709a
export INSTALL_K3S_VERSION=v1.19.9+k3s1
# LB的地址
export K3S_URL=https://10.11.12.100:6443
export INSTALL_K3S_EXEC="--docker \
--kube-proxy-arg proxy-mode=ipvs"

参数说明:

text

--docker	# 用docker代替containerd
--kube-proxy-arg value	# 自定义 kube-proxy 进程的参数

更多参数参考:K3s Agent配置参考的K3s Agent CLI 帮助

安装

bash

curl -sfL http://rancher-mirror.cnrancher.com/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn sh -

执行命令后,在master节点使用kubectl get nodes查看状态,如果成功能看到新的节点

如需重新安装可以卸载脚本 /usr/local/bin/k3s-agent-uninstall.sh

K3s worker 节点的角色默认为none,添加标签

bash

kubectl label node ${node} node-role.kubernetes.io/worker=worker
kubectl label node k3s-worker1 node-role.kubernetes.io/worker=worker

删除Label

bash

kubectl describe node k3s-worker1 |grep Labels
kubectl label nodes k3s-worker1 k3s-worker1-

image-20210430173315962

为什么会出现passwd不一致呢?正常来说如果用k3s-agent-uninstall.sh来清理安装过的 agent node,并不会删除password文件(/etc/rancher/node/password),那么问题很可能是VM重建或者手动操作删除的这个文件。因为agent上删除了password,agent再次注册时会重新生成password,就导致了新的password和server上原先存储的不一致。

解决办法可以有三种:

  • 手动在agent上创建password,内容和server中存储保持一致
  • 修改了server中的原始内容,让password和agent上新生成的保持一致
  • 可以试试agent注册时使用--with-node-id,这样server中认为这完全是新node,不会用原始信息比对

k3s安装时已自动安装kubectl命令行工具

因为使用的是 k3s 集群需要指定kubeconfig的位置或者将文件复制到~/.kube/config

bash

export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
cp /etc/rancher/k3s/k3s.yaml ~/.kube/config

Helm 是 kubernetes 非常好用的软件管理工具

本次安装 helm3

bash

curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh

下载地址

从官网下载最新版本的二进制安装包到本地(推荐用迅雷下载后上传服务器)

bash

curl -O https://get.helm.sh/helm-v3.3.4-linux-amd64.tar.gz
tar -zxf helm-v3.3.4-linux-amd64.tar.gz
cd linux-amd64/
cp helm /usr/local/bin/

验证

bash

helm version

测试一下,创建一个Chart

bash

helm create hello-helm
tree hello-helm

image-20201023112644862

为了测试方便,我们把 Service 的类型改成 NodePort。安装一下这个 Chart 。在 Helm 2 中,如果没有指定 release 的名称,则会自动随机生成一个名称。但是在 Helm 3 中,则必须主动指定名称,或者增加--generate-name的参数。

bash

helm install ./hello-helm --generate-name

image-20201023113509255

image-20201023113552479

等到 Pod 创建完成后,我们可以根据创建的 Service 的 NodePort 来访问该服务了,然后在浏览器中 打开 http://10.11.12.101:49641

为了方便使用,可用rancher管理面板来简化集群管理工作

打开Rancher UI (https://10.11.12.100:8443),选择导入集群,我们会得到导入K3S集群所需的命令,请保存好第三条命令以备后用。 为什么不是第二条?因为目前访问HTTPS API使用的是自签证书,直接用第二条会产生证书不信任的报错。复制生成的命令,在其中一台master 节点上执行即可。

在证书有效期小于90天时,K3S会自动进行续期。

Certificates rotate automatically if they are <90 days from expiration when k3s is started. This has been the case since v0.10: #805

As long as you are patching and restarting your k3s infrastructure at least every couple months, you shouldn’t run into expired certificates.

节点(K3S-Server,K3S-Agent)支持手动升级和自动升级,更换版本号,使用相同的参数再次执行安装脚本即可

参考 https://rancher.com/docs/k3s/latest/en/upgrades/

Rancher UI升级(就是那个rancher/rancher的容器),重新拉取新版本镜像版本即可,最好先备份

bash

# 停止容器
docker stop rancher-server
# 备份数据
docker create --volumes-from rancher-server --name rancher-data rancher/rancher:stable
docker run --volumes-from rancher-data -v $PWD:/backup busybox tar zcvf /backup/rancher-data-backup-<RANCHER_VERSION>-<DATE>.tar.gz /var/lib/rancher
# 重新拉取镜像
docker pull rancher/rancher:stable
# 然后使用之前相同参数,重新 docker run

参考 https://rancher.com/docs/rancher/v2.x/en/upgrades/upgrades/single-node/