参考官网链接:https://docs.rancher.cn/docs/k3s/upgrades/_index/

注:如果要对 server/master 节点升级,绝对不要在流量高峰场景下进行

如果不希望清理所有容器及网络组件,不要轻易使用 k3s-killall.sh 脚本

官方文档描述升级过程为高可用模式,但最好还是在流量低峰期进行升级

否则可能会导致部署单元多个 Pod 都部署在同一节点,然后进行了 Pod 转移,如下

Kubernetes 在 1.22 版本新增了安全 sysctl 参数 net.ipv4.ip_unprivileged_port_start,且需要将内核版本升级至 4.4 以上:https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/#enabling-unsafe-sysctls

我的 sysctl 配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 将桥接的 IPv4 流量传递到 iptables 的链,禁用 swap
cat > /etc/sysctl.d/k3s.conf << EOF
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
# 表示开启 TCP 连接中 TIME-WAIT sockets 的快速回收,默认为 0,表示关闭
net.ipv4.tcp_tw_recycle = 0
# 关闭 swap 虚拟内存
vm.swappiness = 0
# 表示内核允许分配所有的物理内存,而不管当前的内存状态如何
vm.overcommit_memory = 1
# 内存不足时,启动 OOM killer
vm.panic_on_oom = 0
# 允许非特权用户使用端口从 0 开始,k8s 1.22 以上版本支持此参数,且内核支持版本需要大于 4.4
net.ipv4.ip_unprivileged_port_start=0
# 禁用 IPv6
net.ipv6.conf.all.disable_ipv6=1
net.ipv6.conf.default.disable_ipv6=1
net.ipv6.conf.lo.disable_ipv6=1
EOF

Linux 内核升级,参考站内:linux 内核升级过程篇

K3s 进行基础升级

Server 节点

修改 /etc/profile

1
2
3
4
5
6
7
8
9
10
11
12
# k3s
export K3S_CLUSTER_INIT=true
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
# 修改版本号
#export INSTALL_K3S_VERSION=v1.21.7+k3s1
export INSTALL_K3S_VERSION=v1.24.3+k3s1
export INSTALL_K3S_EXEC="server \
# 此参数是在 v1.24.1+k3s 之后新增的,参考 issue: https://github.com/k3s-io/k3s/issues/5637
--egress-selector-mode=disabled \
--tls-san rancher.k3s.cn \
--kubelet-arg max-pods=300 \
--kube-apiserver-arg service-node-port-range=30000-40000"

执行升级:

1
2
source /etc/profile
curl -sfL https://rancher-mirror.oss-cn-beijing.aliyuncs.com/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn sh -

Agent 节点

修改 /etc/profile

1
2
3
4
5
6
7
8
#k3s
export K3S_TOKEN="K10ed88cf924226d11ff411a8d5797fcad4dce224a4888442bcac7aad85f24abbf6::server:95845805df4dfe5d6acaee084f650f5f"
export K3S_URL="https://rancher.k3s.cn:6443"
# 修改版本号
#export INSTALL_K3S_VERSION=v1.21.7+k3s1
export INSTALL_K3S_VERSION=v1.24.3+k3s1
export INSTALL_K3S_EXEC="agent \
--kubelet-arg max-pods=300"

执行升级:

1
2
source /etc/profile
curl -sfL https://rancher-mirror.oss-cn-beijing.aliyuncs.com/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn sh -

K3s 进行自动升级 - system-upgrade-controller

如果 K3s 集群由 Rancher 管理,切记不要安装 system-upgrade-controller,而是使用 Rancher UI 来管理升级。

  • 如果 K3s 集群是导入到 Rancher 的,Rancher 将管理 system-upgrade-controller 部署和计划。不需要安装 system-upgrade-controller
  • 如果 K3s 集群是由 Rancher 预配的,Rancher 将使用系统 Agent 来管理版本升级。不需要安装 system-upgrade-controller
  • 如果 K3s 集群不是由 Rancher 管理的,可以使用 system-upgrade-controller

参考:https://docs.rancher.cn/docs/k3s/upgrades/automated/_index

适用于自建 K3s 集群,使用 Rancher 的 system-upgrade-controller 来管理手动/自动升级。

总共需要完成两步配置:

  1. 安装 system-upgrade-controller,会在集群内创建名为 plans.upgrade.cattle.io 的 CRD
  2. 配置更新计划。这里可以使用自动发现 release 模式,保证实时更新到最新版本,同时也可以创建升级到指定版本的一次性更新计划

安装 system-upgrade-controller

联网执行一句话:

1
kubectl apply -f https://github.com/rancher/system-upgrade-controller/releases/latest/download/system-upgrade-controller.yaml

更新配置存储在 ConfigMap,默认配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: v1
data:
SYSTEM_UPGRADE_CONTROLLER_DEBUG: "false"
SYSTEM_UPGRADE_CONTROLLER_THREADS: "2"
SYSTEM_UPGRADE_JOB_ACTIVE_DEADLINE_SECONDS: "900"
SYSTEM_UPGRADE_JOB_BACKOFF_LIMIT: "99"
SYSTEM_UPGRADE_JOB_IMAGE_PULL_POLICY: Always
SYSTEM_UPGRADE_JOB_KUBECTL_IMAGE: rancher/kubectl:v1.25.4
SYSTEM_UPGRADE_JOB_PRIVILEGED: "true"
SYSTEM_UPGRADE_JOB_TTL_SECONDS_AFTER_FINISH: "900"
SYSTEM_UPGRADE_PLAN_POLLING_INTERVAL: 15m
kind: ConfigMap
metadata:
name: default-controller-env
namespace: system-upgrade

创建更新计划

按照官方文档说法,推荐使用两份计划,分别对应 server (master) 和 agent (worker) 节点的升级。

按照版本升级配置示例:

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# Server plan
apiVersion: upgrade.cattle.io/v1
kind: Plan
metadata:
name: server-plan
namespace: system-upgrade
spec:
concurrency: 1 # 指定同时升级的节点个数
cordon: true # 升级禁止调度
nodeSelector:
matchExpressions:
- key: node-role.kubernetes.io/master # 指定 master 节点
operator: In
values:
- "true"
serviceAccountName: system-upgrade
upgrade:
image: rancher/k3s-upgrade
version: v1.25.16+k3s4 # 指定版本,也可替换为下面地址,自动升级到最新的 stable 版本
# channel: https://update.k3s.io/v1-release/channels/stable
# https://update.k3s.io/v1-release/channels:该地址可查看所有可更新的版本
---
# Agent plan
# 同名字段意义同上
apiVersion: upgrade.cattle.io/v1
kind: Plan
metadata:
name: agent-plan
namespace: system-upgrade
spec:
concurrency: 1
cordon: true
nodeSelector:
matchExpressions:
- key: node-role.kubernetes.io/master
operator: DoesNotExist
prepare:
args:
- prepare
- server-plan # 这里配置意思是等待 server-plan 计划结束后再执行升级
image: rancher/k3s-upgrade
serviceAccountName: system-upgrade
upgrade:
image: rancher/k3s-upgrade
version: v1.25.16+k3s4

查看升级进度:

1
2
kubectl -n system-upgrade get plans -o yaml
kubectl -n system-upgrade get jobs -o yaml

使用 Rancher 管理 K3s 版本

  • 进入 Rancher 首页
  • 点击 Manage
  • 选择对应集群,并点击 Edit Config,随后会跳至此页面
  • 该计划会先更新 master,再更新 node
  • 修改完配置后点击 Save,然后集群会默认安装 system-upgrade-controller,每更新一个节点时会将其置为 Cordoned 状态【并打上污点 node.kubernetes.io/unschedulable=:NoSchedule / node.kubernetes.io/unreachable=:NoSchedule / node.kubernetes.io/unreachable=:NoExecute】,同时集群节点的更新状态会以如下方式展示
  • 更新过程中不会影响正在运行的服务,但保险起见,尽量选择一个非流量高峰期
  • 不需要关心节点在更新前是否配置了污点
  • 更新过程中会在每个节点部署以 apply-k3s-worker-plan-on- 开头的 Pod,此类 Pod 会保持一段时间的 Ready 状态,不需要过多关心
  • 完成更新的节点会被打上以 plan.upgrade.cattle.io/k3s-{master/worker}-plan= 开头的 Label

问题

参考:https://github.com/k3s-io/k3s/issues/6869

helm-install-traefik-h5gjd with errors in log

1
Error: UPGRADE FAILED: rendered manifests contain a resource that already exists. Unable to continue with update: IngressRoute "traefik-dashboard" in namespace "kube-system" exists and cannot be imported into the current release: invalid ownership metadata; annotation validation error: missing key "meta.helm.sh/release-name": must be set to "traefik"; annotation validation error: missing key "meta.helm.sh/release-namespace": must be set to "kube-system"

解决办法:annotations 补充缺失的 missing key

1
2
3
4
5
6
7
8
9
# kubectl edit ingressroutes.traefik.containo.us -n kube-system traefik-dashboard

metadata:
annotations:
......
meta.helm.sh/release-name: traefik
meta.helm.sh/release-namespace: kube-system

# ingressroute.traefik.containo.us/traefik-dashboard edited