rancher k3s 升级 备份恢复

rke

安装命令

cluster.yml 是配置文件

1
rke up -config cluster.yml

https://rancher.com/docs/rke/latest/en/example-yamls/ example

升级条件

RKE v0.2.0 及以上的版本使用cluster.rkestate文件管理集群状态。cluster.rkestate文件中含有集群的当前状态,包括 RKE 配置和证书等信息。

这个文件和cluster.yml位于同一目录下。

cluster.rkestate文件非常重要,控制集群和升级集群的时候都需要用到这个文件,请妥善保管该文件。

升级流程

RKE v1.1.0 及以上的版本提供了以下新功能:

  • 支持不宕机升级,编辑或升级集群时,不会影响集群内的应用。
  • 支持手动指定单个节点,并单独升级这个节点。
  • 支持使用包含老版本的 Kubernetes 集群快照,将集群使用的 Kubernetes 恢复到先前的版本。这个功能使升级集群的过程变得更加安全。如果某次升级的过程中,集群中有些节点无法完成更新,导致该节点内的 pods 和应用无法访问,您可以将已经完成升级的集群所使用的 Kubernetes 降级为升级前使用的版本。

使用默认配置选项,输入rke up命令更新集群时,会依次触发以下事项:

  • 逐个更新每个节点的 etcd plane。RKE 集群内的任何一个 etcd 节点在升级的过程中失效,会导致集群升级失败。
  • 逐个更新 controlplane 节点,包括 controlplane 组件和 controlplane 节点的 worker plane 组件。
  • 逐个更新每个 etcd 节点的 worker plane 组件。
  • 批量更新 worker 节点,您可以配置每批更新的节点数量。在批量更新 worker 节点的过程中,可能会有部分节点不可用,为了降低这部分节点对于升级的影响,您可以配置最大不可用节点数量。默认的最大不可用节点数量是总节点数量的 10%,最小值为 1,如果是小数则向下取整至最近的一个整数,详情请参考下文。
  • 更新每个插件

升级k8s

k8s(限于同一个rke升级k8s)

输入以下命令,快速获取支持K8s版本号

1
2
3
4
5
rke config --list-version --all
v1.15.3-rancher2-1
v1.13.10-rancher1-2
v1.14.6-rancher2-1
v1.16.0-beta.1-rancher1-1

指定k8s版本安装,修改配置文件,原来是v1.19.16-rancher1-2

1
kubernetes_version: v1.20.14-rancher1-1

升级 Kubernetes 版本,打开cluster.yml文件,找到 kubernetes_version字符串,将原有的版本号修改为新的版本号即可。重新执行安装命令。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 应用配置
rke up -config cluster.yml

# 查看结果的Server version的GitVersion
kubectl version 

# 看到已经升级到1.20.14
Server Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.14", GitCommit:"57a3aa3f13699cf3db9c52d228c18db94fa81876", GitTreeState:"clean", BuildDate:"2021-12-15T14:47:10Z", GoVersion:"go1.15.15", Compiler:"gc", Platform:"linux/amd64"}


# 查看组件是否正常
kubectl get pods -n kube-system

NAME                                       READY   STATUS      RESTARTS   AGE
calico-kube-controllers-7d5d95c8c9-mqxmg   1/1     Running     0          11m
canal-wfv8q                                2/2     Running     0          11m
coredns-55b58f978-lj6rs                    1/1     Running     0          11m
coredns-autoscaler-76f8869cc9-fc6th        1/1     Running     0          4d16h
metrics-server-55fdd84cd4-bllfw            1/1     Running     0          11m
rke-coredns-addon-deploy-job-jpl9d         0/1     Completed   0          11m
rke-ingress-controller-deploy-job-pxvwl    0/1     Completed   0          4d22h
rke-metrics-addon-deploy-job-ck9nf         0/1     Completed   0          11m
rke-network-plugin-deploy-job-r7w92        0/1     Completed   0          11m

升级 Kubernetes 版本,打开cluster.yml文件,找到 kubernetes_version字符串,将原有的版本号修改为新的版本号即可。重新执行安装命令。

如果在kubernetes_versionsystem_images中都定义了 Kubernetes 版本,system_images中定义的版本会生效,而kubernetes_version中定义的版本不会生效。如果两者都没有定义 Kubernetes 版本,RKE 会使用默认的 Kubernetes 版本。

获取镜像版本

  • 不同的版本需要到的镜像版本参考

  • 如果在kubernetes_versionsystem_images中都定义了 Kubernetes 版本,system_images中定义的版本会生效,而kubernetes_version中定义的版本不会生效。如果两者都没有定义 Kubernetes 版本,RKE 会使用默认的 Kubernetes 版本。

    1
    2
    3
    4
    5
    6
    7
    8
    # 打印镜像
    rke config --system-images --all
      
      
    INFO[0000] Generating images list for version [v1.19.16-rancher1-2]:
    rancher/mirrored-coreos-etcd:v3.4.15-rancher1
    .....
    weaveworks/weave-npc:2.7.0
    

docker

k8s支持的docker版本

https://github.com/kubernetes/kubernetes/tree/master/CHANGELOG

1
2
3
# If set to true, RKE will not fail when unsupported Docker version
# are found,默认是false
ignore_docker_version: false

升级服务

是指cluster.yml文件里面的service

可以修改服务的对象,或添加extra_args,然后运行rke up命令,升级服务。

说明: service_cluster_ip_rangecluster_cidr不可修改。

升级system_images

system_images更新替换对应的镜像组件,但要注意组件兼容。一般不随便替换

添加/删除节点

https://rancher.com/docs/rke/latest/en/managing-clusters/

1
2
3
4
5
6
7
8
# Adding/Removing Nodes
rke up -config cluster.yml

# Adding/Removing Worker Nodes
rke up --update-only -config cluster.yml

# Removing Kubernetes Components from Nodes
rke remove

The cluster’s etcd snapshots are removed, including both local snapshots and snapshots that are stored on S3.

Pods are not removed from the nodes. If the node is re-used, the pods will automatically be removed when the new Kubernetes cluster is created.

  • Clean each host from the directories left by the services:
    • /etc/kubernetes/ssl
    • /var/lib/etcd
    • /etc/cni
    • /opt/cni
    • /var/run/calico

创建快照

打开命令行工具,输入rke etcd snapshot-save命令,运行后即可保存 cluster config 文件内每个 etcd 节点的快照。RKE 会将节点快照保存在/opt/rke/etcd-snapshots路径下。运行上述命令时,RKE 会创建一个用于备份快照的容器。完成备份后,RKE 会删除该容器。

https://docs.rancher.cn/docs/rke/etcd-snapshots/one-time-snapshots/_index

1
2
3
4
5
6
# 运行以下命令,在本地创建一个一次性快照
rke etcd snapshot-save --config cluster.yml --name snapshot-name

WARN[0000] This is not an officially supported version (v1.2.16-rc1) of RKE. Please download the latest official release at https://github.com/rancher/rke/releases

INFO[0018] Finished saving/uploading snapshot [snapshot-name] on all etcd hosts

保存到/opt/rke/etcd-snapshots

1
2
3
4
5
1
2
3
4
5
root@d-ecs-38357230:~/rancher# ll /opt/rke/etcd-snapshots
total 3040
drwxr-xr-x 2 root root    4096 Jun  9 16:23 ./
drwxr-xr-x 3 root root    4096 Jun  9 11:33 ../
-rw------- 1 root root 3103107 Jun  9 16:23 snapshot-name.zip

上传到minio

1
2
3
4
5
6
7
8
9
rke etcd snapshot-save \
--config cluster.yml \
--name snapshot-name \
--s3 \
--access-key admin \
--secret-key 12345678 \
--bucket-name rancher-backup \
--s3-endpoint back.xxxx.cn \ 
--s3-endpoint-ca minio.crt   # https公钥文件路径

恢复快照

https://docs.rancher.cn/docs/rke/etcd-snapshots/restoring-from-backup/_index

您的 Kubernetes 集群发生了灾难,您可以使用rke etcd snapshot-restore来恢复您的 etcd。这个命令可以将 etcd 恢复到特定的快照,应该在遭受灾难的特定集群的 etcd 节点上运行

当您运行该命令时,将执行以下操作。

  • 同步快照或从 S3 下载快照(如有必要)。
  • 跨 etcd 节点检查快照校验和,确保它们是相同的。
  • 通过运行rke remove删除您当前的集群并清理旧数据。这将删除整个 Kubernetes 集群,而不仅仅是 etcd 集群。
  • 从选择的快照重建 etcd 集群。
  • 通过运行rke up创建一个新的集群。
  • 重新启动集群系统 pod。

警告:在运行rke etcd snapshot-restore之前,您应该备份集群中的任何重要数据,因为该命令会删除您当前的 Kubernetes 集群,并用新的集群替换。

1
2
3
4
5
6
7
8
9
10
11
12
13
# 本地
rke etcd snapshot-restore --config cluster.yml --name snapshot-name

# minio
rke etcd snapshot-restore \
--config cluster.yml \
--name snapshot-name \
--s3 \
--access-key admin \
--secret-key 12345678 \
--bucket-name rancher-backup \
--s3-endpoint back.xxxx.cn \ 
--s3-endpoint-ca minio.crt

有自定义配置例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
nodes:
  - address: xxxxx
    user: root
    role: ["controlplane", "etcd", "worker"]
    ssh_key_path: ~/.ssh/id_rsa
    port: 22
services:
  kube-api:
    # 为NodePort服务提供不同的端口范围
    service_node_port_range: 20000-32767
  scheduler:
      extra_args:
        policy-config-file: /etc/kubernetes/scheduler-policy-config.json # 例如这种配置

kubernetes_version: v1.19.16-rancher1-1
cluster_name: cluster01

恢复过程中会重建/etc/kubernetes目录,然后scheduler-policy-config.json会丢失导致恢复失败,所以要在恢复过程中配好配置

轮换证书

  • etcd
  • kubelet (node certificate)
  • kubelet(服务证书,如果启用)
  • kube-apiserver
  • kube-proxy
  • kube-scheduler
  • kube-controller-manager

/etc/kubernetes/ssl,证书目录

1
rke cert rotate --rotate-ca

因为证书改变,相应的token也会变化,所以在完成集群证书更新后,需要对连接API SERVER的 Pod 进行重建,以获取新的token

例如:

搭建集群,添加网络后,coredns异常

1
2
3
kubectl get pods -n kube-system
NAME                                 READY   STATUS    RESTARTS   AGE
coredns-5dc887ffbb-2s8jd             0/1     Running   0          16h

coredns日志如下

1
2
3
085101-78d2af792bab/tools/cache/reflector.go:98: Failed to list *v1.Namespace: Unauthorized
pkg/mod/k8s.io/client-go@v0.0.0-20190620085101-78d2af792bab/tools/cache/reflector.go:98: Failed to list *v1.Endpoints: Unauthorized
pkg/mod/k8s.io/client-go@v0.0.0-20190620085101-78d2af792bab/tools/cache/reflector.go:98: Failed to list *v1.Service: Unauthorized

查看api server日志

1
2
Unable to authenticate the request due to an error: [invalid bearer token, square/go-jose: error in cryptographic primitive

处理方式:

删除coredns-token和pods后恢复

1
2
kubectl delete secret  -n kube-system coredns-token-6n887
kubectl delete pods coredns-5dc887ffbb-zgff5

原理:

一般发生在你自定义ca,或者升级集群的时候。secret保留的 仍然是依据旧的ca 生成的token,这时需要手动删除token 和pods,让集群根据新的ca重新生成新的token,新的pod 也能使用新的token去访问。

定时备份

参考

修改配置文件cluster.yml

创建定时快照时,可配置的参数如下表所示。

参数 说明 S3 相关
interval_hours 创建快照的间隔时间。如果您使用 RKE v0.2.0 定义了creation参数,interval_hours会覆盖这个参数。如果不输入这个值,默认间隔是 5 分钟。支持输入正整数表示小时,如 1 表示间隔时间为 1 小时,每小时会创建一个快照。(默认: 12)  
retention 快照的存活时间,当快照存活的时间超过这个限制后,会自动删除快照。如果在etcd.retentionetcd.backup_config.retention都配置了限制,RKE 会以etcd.backup_config.retention为准。(默认: 6)  
bucket_name S3 的 桶名称(bucket name) *
folder 指定 S3 存储节点快照的文件夹(可选), RKE v0.3.0 及以上版本可用 *
access_key S3 的 accessKey *
secret_key S3 的 secretKey *
region S3 的 桶所在的区域(可选) *
endpoint 指定 S3 端点 URL 地址,默认值为 s3.amazonaws.com *
custom_ca 自定义证书认证,用于连接 S3 端点。使用私有存储时必填,RKE v0.2.5 及以上版本可用。 *
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
services:
  etcd:
    backup_config:
      interval_hours: 1 # 创建快照的间隔时间,单位是小时,12表示每12个小时创建一个快照
      retention: 6 # 快照的存活时间,单位是小时
      s3backupconfig:
        access_key: admin
        secret_key: 12345678
        bucket_name: rke-backup
        endpoint: xxxx.xxxx.cn
        custom_ca: |-
          -----BEGIN CERTIFICATE-----
          MIIDLTCCAhWgAwIBAgIUYXfMpXhM9X79Jd6EsWOdxsZDIa4wDQYJKoZIhvcNAQEL
          BQAwGDEWMBQGA1UEAwwNYmFjay51bmlpbi5jbjAgFw0yMjA2MDkwODQzMjRaGA8y
          MTIyMDUxNjA4NDMyNFowGDEWMBQGA1UEAwwNYmFjay51bmlpbi5jbjCCASIwDQYJ
          KoZIhvcNAQEBBQADggEPADCCAQoCggEBANVaRDjfB7H8jv7SOVYwygwuCk+l+2qC
          xJkwzBsCv9t67/mX5ecBs0aaeIh2IJRqo2SR55vzQkuk22QI7MaRU2qTGx8/4Hko
          7bqc6MJQU68BtSmiRQ8TENj5wjQEKFXHPwd68O0Uww0r/+e9WabPPxlSQDUV7xFt
          eNnjMu4xsP5hvDRrjZH3GybUon48Y48nIooMeJnRZ89HDaoOY8a+nD7W05yxv3RS
          0EgDr70YUHLpcL/n5pIu5bo2XalEU9B1jBlr972ck7f6vSO/13SRwPQK3miPLWMJ
          NfvAgvPuKt/zr0PXdaNoa5CMRjaM5G2l8pEiq5a83RgYfCZBV5y4yscCAwEAAaNt
          MGswHQYDVR0OBBYEFLv/JQ6P4dmLG8C2PspC+Y6PoU3vMB8GA1UdIwQYMBaAFLv/
          JQ6P4dmLG8C2PspC+Y6PoU3vMA8GA1UdEwEB/wQFMAMBAf8wGAYDVR0RBBEwD4IN
          YmFjay51bmlpbi5jbjANBgkqhkiG9w0BAQsFAAOCAQEA0jkQ3o2WU6TOGP1XQDHZ
          Mt8kGyOyHvN206I0OJxmYGaSXbHPmu9I2PwZ3IY+yQ5XEtyypWO7qDtuzC+laIH4
          iB1TJw90y0dtlvQPxp9XFkZwHnVyR6V9BpL/1UMDOTJOsagnSobui5Iw02i0dBFH
          sO8qm2yGV5376NQHQQ9uYFChlsYCdTEqxR7EEhQTQ9RDDT2x+8amOXKQzQzOnbBe
          UX1A2sVSt1sF1MVhR+ATblTOZG65R+WWYZCEqgVoIqqb6qYwbzYaUQ/c87cPMRcG
          ruWGRk9j5YrmlbzxQir/ofwecWxBDVyq8rks2BUVFp1r9a9WTqA44dmui9GfG9D4
          uA==
          -----END CERTIFICATE-----

一次性快照

一次性快照参考rke官方文档

备份

1
2
3
4
root@d-ecs-38357230:~/rancher# rke etcd snapshot-save --config cluster.yml --name snapshot-name
WARN[0000] This is not an officially supported version (v1.2.16-rc1) of RKE. Please download the latest official release at https://github.com/rancher/rke/releases

INFO[0018] Finished saving/uploading snapshot [snapshot-name] on all etcd hosts

保存到/opt/rke/etcd-snapshots

1
2
3
4
5
1
2
3
4
5
root@d-ecs-38357230:~/rancher# ll /opt/rke/etcd-snapshots
total 3040
drwxr-xr-x 2 root root    4096 Jun  9 16:23 ./
drwxr-xr-x 3 root root    4096 Jun  9 11:33 ../
-rw------- 1 root root 3103107 Jun  9 16:23 snapshot-name.zip

上传到minio

1
2
3
4
5
6
7
8
9
rke etcd snapshot-save \
--config cluster.yml \
--name snapshot-name \
--s3 \
--access-key admin \
--secret-key 12345678 \
--bucket-name rancher-backup \
--s3-endpoint xxxx.xxxx.cn \ 
--s3-endpoint-ca minio.crt   # https公钥文件路径

恢复

1
2
3
4
5
6
7
8
9
10
11
12
13
# 本地
rke etcd snapshot-restore --config cluster.yml --name snapshot-name

# minio
rke etcd snapshot-restore \
--config cluster.yml \
--name snapshot-name \
--s3 \
--access-key admin \
--secret-key 12345678 \
--bucket-name rancher-backup \
--s3-endpoint xxxx.xxxx.cn \ 
--s3-endpoint-ca minio.crt

有自定义配置例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
nodes:
  - address: xxxxx
    user: root
    role: ["controlplane", "etcd", "worker"]
    ssh_key_path: ~/.ssh/id_rsa
    port: 22
services:
  kube-api:
    # 为NodePort服务提供不同的端口范围
    service_node_port_range: 20000-32767
  scheduler:
      extra_args:
        policy-config-file: /etc/kubernetes/scheduler-policy-config.json # 例如这种配置

kubernetes_version: v1.19.16-rancher1-1
cluster_name: cluster01

恢复过程中会重建/etc/kubernetes目录,然后scheduler-policy-config.json会丢失导致恢复失败,所以要在恢复过程中配好配置

k3s

指定配置文件启动

大于v1.19.1+k3s1支持

默认情况下,位于/etc/rancher/k3s/config.yaml的 YAML 文件中的值将在安装时使用

1
2
3
4
5
6
write-kubeconfig-mode: "0644"
tls-san:
  - "foo.local"
node-label:
  - "foo=bar"
  - "something=amazing"

对应cli参数

1
2
3
4
5
k3s server \
  --write-kubeconfig-mode "0644"    \
  --tls-san "foo.local"             \
  --node-label "foo=bar"            \
  --node-label "something=amazing"

可以同时使用配置文件和 CLI 参数,CLI 参数将优先,对于可重复的参数,如--node-label,CLI 参数将覆盖列表中的所有值。

配置文件的位置可以通过 cli 参数--config FILE,-c FILE或者环境变量$K3S_CONFIG_FILE来改变。

升级

首先确认当前版本 v1.19.5+k3s2

1
2
3
kubectl version

Server Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.5+k3s2", GitCommit:"746cf4031370f443bf1230272bc79f2f72de2869", GitTreeState:"clean", BuildDate:"2020-12-18T01:41:55Z", GoVersion:"go1.15.5", Compiler:"gc", Platform:"linux/amd64"}

针对版本,阅读k3s升级介绍

手动升级

停止服务

为了在升级期间实现高可用性,K3s 容器在 K3s 服务停止时继续运行。

要停止所有 K3s 容器并重置 containerd 状态,k3s-killall.sh可以使用该脚本。

killall 脚本清理容器、K3s 目录和网络组件,同时还删除 iptables 链以及所有相关规则。集群数据不会被删除。

要从服务器节点运行 killall 脚本,请运行

1
/usr/local/bin/k3s-killall.sh

安装

升级时,先逐个升级 server 节点,然后再升级其他 agent 节点。

  • 发布中下载所需版本的 K3s 二进制文件,和对应镜像
  • 将下载的二进制文件复制到/usr/local/bin/k3s(或您想要的位置)
  • 重启k3s服务和代理
1
2
3
4
5
# server
systemctl restart k3s

# agent
systemctl restart k3s-agent

更新Traefik1.7to2.x

原理介绍

里面涉及到Traefik的迁移,1.20+的版本会有开始使用Traefik2,然后和Traefik1差别好大,强行升级会报错Failed to list *v1beta1.Ingress: the server could not find the requested resource (get ingresses.extensions)不要看Traefik官方的迁移文档,参考这个K3s:将 Traefik 入口控制器升级到版本 2

traefik的启动其实依赖于/var/lib/rancher/k3s/server/manifests里面的yaml

1
2
3
4
5
6
7
total 28
-rw------- 1 root root 1774 Jun 14 18:49 ccm.yaml
-rw------- 1 root root 4632 Jun 14 18:49 coredns.yaml
-rw------- 1 root root 3635 Jun 14 18:49 local-storage.yaml
drwx------ 2 root root 4096 Jun 14 11:23 metrics-server
-rw------- 1 root root 1039 Jun 14 18:49 rolebindings.yaml
-rw------- 1 root root 1155 Jun 14 18:49 traefik.yaml

里面相当于helm安装 /var/lib/rancher/k3s/server/static/charts里面的charts

解决方法

更新完k3s后,会更新charts里面的内容,但是没有更新manifests里面的yaml,可以通过doker ps/docker images定位到更新完,Traefik还在应用旧镜像。所以要找到k3s对应版本的traefik.yaml,做相应的替换。

最后

1
2
3
4
5
# 重启
systemctl restart k3s

# 或者直接apply
kubectl apply -f /var/lib/rancher/k3s/server/manifests/traefik.yaml

备份

参考

存放数据的目录由k3s server --data-dir ${data-dir} 确定

${data-dir} 默认 /var/lib/rancher/k3s or ${HOME}/.rancher/k3s(如果不是root用户)

快照目录默认为 ${data-dir}/server/db/snapshots

完整快照目录默认

1
/var/lib/rancher/k3s/server/db/snapshots

k3s 默认每12hour备份一次,保留5个备份分别用--etcd-snapshot-schedule-cron--etcd-snapshot-retention定义,都是k3s server 的子命令

参数 描述
--etcd-disable-snapshots 禁用自动 etcd 快照
--etcd-snapshot-schedule-cron 以 Cron 表达式的形式配置触发定时快照的时间点,例如:每 5 小时触发一次0 */5 * * *,默认值为每 12 小时触发一次:0 */12 * * *
--etcd-snapshot-retention 保留的快照数量,默认值为 5。
--etcd-snapshot-dir 保存数据库快照的目录路径。(默认位置:${data-dir}/db/snapshots)
--cluster-reset 忘记所有的对等体,成为新集群的唯一成员,也可以通过环境变量[$K3S_CLUSTER_RESET]进行设置。
--cluster-reset-restore-path 要恢复的快照文件的路径
1
2
3
4
5
6
7
8
ll /var/lib/rancher/k3s/server/db/snapshots
total 104460
-rw------- 1 root root 21389344 Jun  8 12:00 etcd-snapshot-1654660800
-rw------- 1 root root 21389344 Jun  9 00:00 etcd-snapshot-1654704000
-rw------- 1 root root 21389344 Jun  9 12:00 etcd-snapshot-1654747200
-rw------- 1 root root 21389344 Jun 10 00:00 etcd-snapshot-1654790400
-rw------- 1 root root 21389344 Jun 10 12:00 etcd-snapshot-1654833600

恢复

当 K3s 从备份中恢复时,旧的数据目录将被移动到 ${data-dir}/server/db/etcd-old/。然后 K3s 会尝试通过创建一个新的数据目录来恢复快照,然后从一个带有一个 etcd 成员的新 K3s 集群启动 etcd。

1
2
3
systemctl stop k3s

k3s server --cluster-reset --cluster-reset-restore-path /var/lib/rancher/k3s/server/db/snapshots/etcd-snapshot-1654833600

成功结果

1
2
3
4
5
INFO[2022-06-10T15:24:05.311564146+08:00] Logging containerd to /var/lib/rancher/k3s/agent/containerd/containerd.log
INFO[2022-06-10T15:24:05.311691243+08:00] Running containerd -c /var/lib/rancher/k3s/agent/etc/containerd/config.toml -a /run/k3s/containerd/containerd.sock --state /run/k3s/containerd --root /var/lib/rancher/k3s/agent/containerd
{"level":"warn","ts":"2022-06-10T15:24:05.311+0800","caller":"grpclog/grpclog.go:60","msg":"grpc: addrConn.createTransport failed to connect to {/run/k3s/containerd/containerd.sock  <nil> 0 <nil>}. Err :connection error: desc = \"transport: Error while dialing dial unix /run/k3s/containerd/containerd.sock: connect: no such file or directory\". Reconnecting..."}
INFO[2022-06-10T15:24:05.886266149+08:00] Etcd is running, restart without --cluster-reset flag now. Backup and delete ${datadir}/server/db on each peer etcd server and rejoin the nodes

启动k3s

1
systemctl start k3s

旧数据

1
2
3
4
5
6
7
[root@1xxx db]# ll
total 12
drwx------ 3 root root 4096 Jun 10 15:29 etcd
drwx------ 3 root root 4096 Jun  1 15:34 etcd-old-1654845840
drwx------ 2 root root 4096 Jun 10 12:00 snapshots
[root@1xxx db]# pwd
/var/lib/rancher/k3s/server/db

rancher使用rke添加集群

设置备份etcd

高级选项可以设置备份,默认会设置备份

image-20220609155115716

修改集群配置

image-20220613112015220

集群升级

image-20220613162748231

备份配置

image-20220613163104077

还原

选择集群

image-20220609155740195

选择工具-> 备份,可以手动备份新的,或者根据时间选择还原 image-20220609155842826

kubeadm创建的k8s

备份

安装etcd-client

1
2
3
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
  --cacert=<trusted-ca-file> --cert=<cert-file> --key=<key-file> \
  snapshot save <backup-file-location>

获得 trusted-ca-filecert-filekey-file。通过etcd pod describe获得

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
kubectl describe pod/etcd-master -n kube-system

Containers:
  etcd:
    Container ID:  docker://027f21079b676178393c73ff4d8adddb788dc78fc361a7d9482281bc8e3f3dae
    Image:         k8s.gcr.io/etcd:3.5.1-0
    Image ID:      docker-pullable://k8s.gcr.io/etcd@sha256:64b9ea357325d5db9f8a723dcf503b5a449177b17ac87d69481e126bb724c263
    Port:          <none>
    Host Port:     <none>
    Command:
      etcd
      --advertise-client-urls=https://10.211.55.32:2379
      --cert-file=/etc/kubernetes/pki/etcd/server.crt
      --client-cert-auth=true
      --data-dir=/var/lib/etcd
      --initial-advertise-peer-urls=https://10.211.55.32:2380
      --initial-cluster=master=https://10.211.55.32:2380
      --key-file=/etc/kubernetes/pki/etcd/server.key
      --listen-client-urls=https://127.0.0.1:2379,https://10.211.55.32:2379
      --listen-metrics-urls=http://127.0.0.1:2381
      --listen-peer-urls=https://10.211.55.32:2380
      --name=master
      --peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt
      --peer-client-cert-auth=true
      --peer-key-file=/etc/kubernetes/pki/etcd/peer.key
      --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
      --snapshot-count=10000
      --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
    State:          Running
      Started:      Fri, 10 Jun 2022 08:11:49 +0000
    Last State:     Terminated
      Reason:       Error
      Exit Code:    255
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
# 备份参数
ETCDCTL_API=3 etcdctl   snapshot save  -h


NAME:
	snapshot save - Stores an etcd node backend snapshot to a given file

USAGE:
	etcdctl snapshot save <filename> [flags]

OPTIONS:
  -h, --help[=false]	help for save

GLOBAL OPTIONS:
      --cacert=""				verify certificates of TLS-enabled secure servers using this CA bundle
      --cert=""					identify secure client using this TLS certificate file
      --command-timeout=5s			timeout for short running command (excluding dial timeout)
      --debug[=false]				enable client-side debug logging
      --dial-timeout=2s				dial timeout for client connections
      --endpoints=[127.0.0.1:2379]		gRPC endpoints
      --hex[=false]				print byte strings as hex encoded strings
      --insecure-skip-tls-verify[=false]	skip server certificate verification
      --insecure-transport[=true]		disable transport security for client connections
      --key=""					identify secure client using this TLS key file
      --user=""					username[:password] for authentication (prompt if password is not supplied)
  -w, --write-out="simple"			set the output format (fields, json, protobuf, simple, table)

最终

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 创建快照
mkdir -p backup_etcd

ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key \
  snapshot save backup_etcd/snap-$(date +%Y%m%d%H%M).db
  
# 验证 
ETCDCTL_API=3 etcdctl --write-out=table snapshot status backup_etcd/snap-202206100917.db

+----------+----------+------------+------------+
|   HASH   | REVISION | TOTAL KEYS | TOTAL SIZE |
+----------+----------+------------+------------+
| a669ed44 |   156435 |       1457 |      11 MB |
+----------+----------+------------+------------+



  • 最好不好直接复制${data-dir}/member/snap/db文件,还原时验证快照完整性,用命令会计算hash供恢复时候校验用。

  • 不要轻易使用status check,会破坏数据库完整性

    不然恢复时候报错

    1
    Error:  expected sha256 [192 34 116 2 72 172 108 91 102 14 204 205 193 70 163 254 156 27 205 148 190 171 99 63 234 149 201 220 37 154 105 68], got [178 153 122 181 91 182 33110 230 141 239 175 40 71 74 48 165 184 179 124 41 121 133 130 18 145 113 190 86 163 186 184]
    

以上可以在恢复时候添加–skip-hash-check=true 参数

恢复

  • 优先停掉所有api-server
  • 恢复etcd
  • 重启api-server

其实迁移重启所有的 组件 (e.g. kube-scheduler, kube-controller-manager, kubelet) ,以确保它们不依赖于一些陈旧的数据

停止前

image-20220610180406356

1
2
3
4
5
6
7
8
# 防止kubelet重启静态pod, 相当于停掉etcd kube-apiserver kube-controller-manager kube-scheduler
mv /etc/kubernetes/manifests  /etc/kubernetes/manifests.bak


mv /var/lib/etcd /var/lib/etcd.bak

# 使用查看是否停止
docker ps|grep k8s_

停止后

image-20220610221709512

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
# 恢复参数
ETCDCTL_API=3 etcdctl snapshot restore  -h


NAME:
	snapshot restore - Restores an etcd member snapshot to an etcd directory

USAGE:
	etcdctl snapshot restore <filename> [options] [flags]

OPTIONS:
      --data-dir=""						Path to the data directory
  -h, --help[=false]						help for restore
      --initial-advertise-peer-urls="http://localhost:2380"	List of this member's peer URLs to advertise to the rest of the cluster
      --initial-cluster="default=http://localhost:2380"		Initial cluster configuration for restore bootstrap
      --initial-cluster-token="etcd-cluster"			Initial cluster token for the etcd cluster during restore bootstrap
      --name="default"						Human-readable name for this member
      --skip-hash-check[=false]					Ignore snapshot integrity hash value (required if copied from data directory)

GLOBAL OPTIONS:
      --cacert=""				verify certificates of TLS-enabled secure servers using this CA bundle
      --cert=""					identify secure client using this TLS certificate file
      --command-timeout=5s			timeout for short running command (excluding dial timeout)
      --debug[=false]				enable client-side debug logging
      --dial-timeout=2s				dial timeout for client connections
      --endpoints=[127.0.0.1:2379]		gRPC endpoints
      --hex[=false]				print byte strings as hex encoded strings
      --insecure-skip-tls-verify[=false]	skip server certificate verification
      --insecure-transport[=true]		disable transport security for client connections
      --key=""					identify secure client using this TLS key file
      --user=""					username[:password] for authentication (prompt if password is not supplied)
  -w, --write-out="simple"			set the output format (fields, json, protobuf, simple, table)

恢复步骤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 恢复  --data-dir默认空必须指定
ETCDCTL_API=3 etcdctl --endpoints="https://127.0.0.1:2379"  --cert="/etc/kubernetes/pki/etcd/server.crt"  --key="/etc/kubernetes/pki/etcd/server.key"  --cacert="/etc/kubernetes/pki/etcd/ca.crt"   snapshot restore backup_etcd/snap-202206100917.db --skip-hash-check=true --data-dir=/var/lib/etcd


# 还原
mv /etc/kubernetes/manifests.bak /etc/kubernetes/manifests

# 查看 其他没有重启的组件calico-* coredns* kube-proxy 最好重启一下
kubectl get pods -n kube-system
NAME                                       READY   STATUS    RESTARTS   AGE
calico-kube-controllers-56fcbf9d6b-5qf99   1/1     Running   0          10m
calico-node-57dwd                          1/1     Running   0          10m
coredns-64897985d-fmp86                    1/1     Running   0          4m24s
coredns-64897985d-x7zd7                    1/1     Running   0          4m
etcd-master                                1/1     Running   0          80d
kube-apiserver-master                      1/1     Running   0          80d
kube-controller-manager-master             1/1     Running   0          80d
kube-proxy-flf9j                           1/1     Running   0          3m33s
kube-scheduler-master                      1/1     Running   0          80d

升级

https://kubernetes.io/zh-cn/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/ ,里面有旧版本的升级

升级工作的基本流程如下:

  • 升级主控制平面节点

  • 升级其他控制平面节点

  • 升级工作节点

确定升级版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 当前版本
kubeadm version

kubeadm version: &version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.5", GitCommit:"c285e781331a3785a7f436042c65c5641ce8a9e9", GitTreeState:"clean", BuildDate:"2022-03-16T15:57:37Z", GoVersion:"go1.17.8", Compiler:"gc", Platform:"linux/amd64"}

# 可升级版本
apt update
apt-cache madison kubeadm

   kubeadm |  1.24.1-00 | https://apt.kubernetes.io kubernetes-xenial/main amd64 Packages
   kubeadm |  1.24.0-00 | https://apt.kubernetes.io kubernetes-xenial/main amd64 Packages
   kubeadm |  1.23.7-00 | https://apt.kubernetes.io kubernetes-xenial/main amd64 Packages
   kubeadm |  1.23.6-00 | https://apt.kubernetes.io kubernetes-xenial/main amd64 Packages
   kubeadm |  1.23.5-00 | https://apt.kubernetes.io kubernetes-xenial/main amd64 Packages
   kubeadm |  1.23.4-00 | https://apt.kubernetes.io kubernetes-xenial/main amd64 Packages

update control plane node

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
# 用最新的补丁版本号替换 1.24.x-00 中的 x
apt-mark unhold kubeadm && \
apt-get update && apt-get install -y kubeadm=1.24.x-00 && \
apt-mark hold kubeadm

# 验证下载操作正常,并且 kubeadm 版本正确
kubeadm version

# 验证升级计划 检查你的集群是否可被升级,并取回你要升级的目标版本。 命令也会显示一个包含组件配置版本状态的表格。
kubeadm upgrade plan

[upgrade] Fetching available versions to upgrade to
[upgrade/versions] Cluster version: v1.23.5
[upgrade/versions] kubeadm version: v1.24.0
[upgrade/versions] Target version: v1.24.1
[upgrade/versions] Latest version in the v1.23 series: v1.23.7

# 将 x 替换为你为此次升级所选择的补丁版本号
kubeadm upgrade apply v1.24.x

[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

[upgrade/successful] SUCCESS! Your cluster was upgraded to "v1.24.0". Enjoy!

[upgrade/kubelet] Now that your control plane is upgraded, please proceed with upgrading your kubelets if you haven't already done so.

其它控制面节点

1
kubeadm upgrade node

不需要执行 kubeadm upgrade plan 和更新 CNI 驱动插件的操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 将节点标记为不可调度并腾空节点为节点作升级准备
kubectl drain <node-to-drain> --ignore-daemonsets


# 升级 kubelet 和 kubectl
apt-mark unhold kubelet kubectl && \
apt-get update && apt-get install -y kubelet=1.24.x-00 kubectl=1.24.x-00 && \
apt-mark hold kubelet kubectl

# 重启 kubelet
systemctl daemon-reload
systemctl restart kubelet

# 将节点标记为可调度
kubectl uncordon <node-to-drain>

# 验证集群的状态
kubectl get nodes

update worker node

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 将 1.24.x-00 中的 x 替换为最新的补丁版本号
apt-mark unhold kubeadm && \
apt-get update && apt-get install -y kubeadm=1.24.x-00 && \
apt-mark hold kubeadm

# 对于工作节点,下面的命令会升级本地的 kubelet 配置
kubeadm upgrade node

# 为不可调度并驱逐所有负载
kubectl drain <node-to-drain> --ignore-daemonsets


# 将 1.24.x-00 中的 x 替换为最新的补丁版本
apt-mark unhold kubelet kubectl && \
apt-get update && apt-get install -y kubelet=1.24.x-00 kubectl=1.24.x-00 && \
apt-mark hold kubelet kubectl

# 重启 kubelet
sudo systemctl daemon-reload
sudo systemctl restart kubelet

# 将节点标记为可调度,让节点重新上线
kubectl uncordon <node-to-drain>

工作原理

kubeadm upgrade apply 做了以下工作:

  • 检查你的集群是否处于可升级状态:
    • API 服务器是可访问的
    • 所有节点处于 Ready 状态
    • 控制面是健康的
  • 强制执行版本偏差策略。
  • 确保控制面的镜像是可用的或可拉取到服务器上。
  • 如果组件配置要求版本升级,则生成替代配置与/或使用用户提供的覆盖版本配置。
  • 升级控制面组件或回滚(如果其中任何一个组件无法启动)。
  • 应用新的 CoreDNSkube-proxy 清单,并强制创建所有必需的 RBAC 规则。
  • 如果旧文件在 180 天后过期,将创建 API 服务器的新证书和密钥文件并备份旧文件。

kubeadm upgrade node 在其他控制平节点上执行以下操作:

  • 从集群中获取 kubeadm ClusterConfiguration
  • (可选操作)备份 kube-apiserver 证书。
  • 升级控制平面组件的静态 Pod 清单。
  • 为本节点升级 kubelet 配置

kubeadm upgrade node 在工作节点上完成以下工作:

  • 从集群取回 kubeadm ClusterConfiguration
  • 为本节点升级 kubelet 配置。

参考