乔克视界 乔克视界
首页
  • 运维
  • 开发
  • 监控
  • 安全
  • 随笔
  • Docker
  • Golang
  • Python
  • AIOps
  • DevOps
  • Kubernetes
  • Prometheus
  • ELK
  • 心情杂货
  • 读书笔记
  • 面试
  • 实用技巧
  • 博客搭建
友链
关于
收藏
  • 分类
  • 标签
  • 归档

乔克

云原生爱好者
首页
  • 运维
  • 开发
  • 监控
  • 安全
  • 随笔
  • Docker
  • Golang
  • Python
  • AIOps
  • DevOps
  • Kubernetes
  • Prometheus
  • ELK
  • 心情杂货
  • 读书笔记
  • 面试
  • 实用技巧
  • 博客搭建
友链
关于
收藏
  • 分类
  • 标签
  • 归档
  • Docker

  • Golang

  • AIOps

  • Python

  • DevOps

  • Kubernetes

    • 什么是云原生?
    • Docker容器技术
    • Kubernetes简介
    • Kubernetes核心对象
    • Kubernetes集群管理
      • 安装集群
        • 前置说明
        • 环境准备
        • 初始化集群
        • 初始化 master 节点
        • 初始化 node 节点
        • 初始化网络
        • 安装 Dashboard
      • 更新集群
        • 升级集群
        • 升级前准备
        • 升级目标
        • 备份集群
        • 升级控制节点
        • 升级节点
        • 验证集群
        • 其他
        • 升级证书
        • 添加/删除节点
        • 添加节点
        • 删除节点
      • 备份 K8s 集群
        • 备份数据库
        • 备份
        • 恢复
        • 备份集群清单
        • 安装客户端
        • 安装服务端
        • 安装 minio
        • 安装 velero 服务端
        • 执行备份操作
        • 总结
      • 最后
      • 链接
    • Kubernetes权限管理
    • Kubernetes工作负载管理
    • Kubernetes调度管理
    • Kubernetes应用质量管理
    • Kubernetes数据持久化管理
    • Kubernetes应用访问管理
    • Kubernetes应用配置管理
    • Kubernetes有状态应用管理
    • Kubernetes 网络管理
    • Helm 应用包管理
  • Prometheus

  • ELK

  • 专栏
  • Kubernetes
乔克
2025-07-19
目录

Kubernetes集群管理

Kubernetes 作为容器的编排平台,它是以集群的形式为业务提供服务。所以在日常的工作中,作为 Kubernetes 平台的维护者,会经常对集群进行管理。

这里,我将集群管理分为以下几种:

af77e0141244194f7bc84953db7081d8 MD5

# 安装集群

# 前置说明

Kubernetes 的集群安装分为:kubeadm 安装和二进制安装。在这里,只会介绍 kubeadm 的安装。

安装说明:

集群节点:2 个

IP 信息:master:192.168.205.128 node:192.168.205.128

Kubernetes 版本:v1.24.2

运行时:containerd

系统:centos 7.9

系统内核:3.10.0-1160

# 环境准备

这是安装的不是生产级别的集群,只是为了演示使用。

(1)在每个节点添加 host 信息

cat >> /etc/hosts << EOF
192.168.205.128 kk-master
192.168.205.130 kk-node01
EOF
1
2
3
4

(2)关闭防火墙和 SELinux

systemctl stop firewalld
systemctl disable firewalld

setenforce 0
cat /etc/selinux/config
SELINUX=disabled
1
2
3
4
5
6

(3)优化内核参数

cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
vm.swappiness=0
EOF
1
2
3
4
5
6

执行以下命令使其生效:

modprobe br_netfilter
sysctl -p /etc/sysctl.d/k8s.conf
1
2

(4)关闭 swap 空间

swapoff -a
1

注释/etc/fstab 文件中 swap 挂载。

cat /etc/fstab

##
## /etc/fstab
## Created by anaconda on Tue Apr 12 17:10:16 2022
##
## Accessible filesystems, by reference, are maintained under '/dev/disk'
## See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
##
/dev/mapper/centos-root /                       xfs     defaults        0 0
UUID=bc73c871-006c-4e24-a7af-6beb9aac06a7 /boot                   xfs     defaults        0 0
## /dev/mapper/centos-swap swap                    swap    defaults        0 0
1
2
3
4
5
6
7
8
9
10
11
12

(5)安装 ipvs 软件包

cat > /etc/sysconfig/modules/ipvs.modules <<EOF
##!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4
EOF
chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules && lsmod | grep -e ip_vs -e nf_conntrack_ipv4

yum install ipset ipvsadm -y
1
2
3
4
5
6
7
8
9
10
11

(6)同步服务器时间

yum install chrony -y
systemctl enable chronyd
systemctl start chronyd
chronyc sources
1
2
3
4

(7)安装 containerd

yum install -y yum-utils \
 device-mapper-persistent-data \
 lvm2
yum-config-manager \
 --add-repo \
 https://download.docker.com/linux/centos/docker-ce.repo
yum list | grep containerd
yum install containerd -y
1
2
3
4
5
6
7
8

创建 containerd 配置文件。

mkdir -p /etc/containerd
## containerd config default > /etc/containerd/config.toml
## 替换配置文件
sed -i "s##k8s.gcr.io##registry.cn-hangzhou.aliyuncs.com/google_containers##g"  /etc/containerd/config.toml
sed -i 's##SystemdCgroup = false##SystemdCgroup = true##g' /etc/containerd/config.toml
sed -i "s##https://registry-1.docker.io##https://registry.cn-hangzhou.aliyuncs.com##g"  /etc/containerd/config.toml
1
2
3
4
5
6

启动 containerd。

systemctl daemon-reload
systemctl enable containerd
systemctl restart containerd
1
2
3

(8)安装 Kubernetes 组件

cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
 http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
1
2
3
4
5
6
7
8
9
10

安装指定版本的组件。

yum install -y kubelet-1.24.2 kubeadm-1.24.2 kubectl-1.24.2
1

设置运行时。

crictl config runtime-endpoint /run/containerd/containerd.sock
1

设置 kubelet 为自启动。

systemctl daemon-reload
systemctl enable kubelet && systemctl start kubelet
1
2

# 初始化集群

上面把基础环境准备好了,现在开始真正的进行集群初始化。

# 初始化 master 节点

然后接下来在 master 节点配置 kubeadm 初始化文件,可以通过如下命令导出默认的初始化配置:

kubeadm config print init-defaults > kubeadm.yaml
1

然后根据我们自己的需求修改配置,比如修改 imageRepository 的值,kube-proxy 的模式为 ipvs,需要注意的是由于我们使用的 containerd 作为运行时,所以在初始化节点的时候需要指定cgroupDriver为systemd。

apiVersion: kubeadm.k8s.io/v1beta3
bootstrapTokens:
- groups:
  - system:bootstrappers:kubeadm:default-node-token
  token: abcdef.0123456789abcdef
  ttl: 24h0m0s
  usages:
  - signing
  - authentication
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: 192.168.205.128
  bindPort: 6443
nodeRegistration:
  criSocket: unix:///var/run/containerd/containerd.sock
  imagePullPolicy: IfNotPresent
  name: master
  taints: null
---
apiServer:
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
etcd:
  local:
    dataDir: /var/lib/etcd
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: 1.24.2
networking:
  dnsDomain: cluster.local
  serviceSubnet: 10.96.0.0/12
scheduler: {}
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd
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

然后使用上面的配置文件进行初始化:

kubeadm init --config=kubeadm.yaml

......
Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.205.128:6443 --token abcdef.0123456789abcdef \
        --discovery-token-ca-cert-hash sha256:51b5e566d3f95aaf3170916d67958bc16cb1b44934885a857b07ee58f041334a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

如上输出表示 master 节点初始化成功。

# 初始化 node 节点

在初始化 node 节点的时候,必须把 kubernetes 需要的组件安装上。确保安装完成后,使用初始化 master 节点成功后输出的命令加入节点即可。

kubeadm join 192.168.205.128:6443 --token abcdef.0123456789abcdef \
        --discovery-token-ca-cert-hash sha256:51b5e566d3f95aaf3170916d67958bc16cb1b44934885a857b07ee58f041334a
1
2

然后可以在 master 节点使用 kubectl get node 查看节点是否加入。

kubectl get no
NAME        STATUS     ROLES           AGE     VERSION
kk-node01   NotReady   <none>          15s     v1.24.2
master      NotReady   control-plane   3m29s   v1.24.2
1
2
3
4

# 初始化网络

通过上面kubectl get node查看节点信息的时候发现节点的STATUS是NotReady,这是因为现在整个集群还没有相应的网络插件,导致整个集群并不能正常的运行,下面我们就来安装对应的网络插件。

网络插件的选择有很多种,比如 flannel,calico 等。

(1)下载 calico 的 yaml 清单

wget https://raw.githubusercontent.com/projectcalico/calico/master/manifests/calico.yaml
1

(2)安装 calico

kubectl apply -f calico.yaml
1

(3)在集群中查看安装结果

kubectl get po -n kube-system | grep calico
calico-kube-controllers-5d49fc6c56-szm6v   1/1     Running   0          3m21s
calico-node-66q62                          1/1     Running   0          3m21s
calico-node-lwrcm                          1/1     Running   0          3m21s
1
2
3
4

现在可以看到 kubernetes 所有节点的状态变成Ready了。

kubectl get no
NAME        STATUS   ROLES           AGE   VERSION
kk-node01   Ready    <none>          26m   v1.24.2
master      Ready    control-plane   29m   v1.24.2
1
2
3
4

# 安装 Dashboard

上面集群安装完成后,基本都需要使用命令行进行操作,如果为了提升集群的可视化,可以安装一些 Dashboard。

目前市面上的 Dashboard 有很多,比如 kubesphere、kuboard、kubernetes dashboard 等。这里安装的是 kubernetes dashboard,其他可视化产品可以自己去了解并使用。

(1)使用如下命令进行安装

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.5.0/aio/deploy/recommended.yaml
1

(2)查看安装情况

kubectl get po -n kubernetes-dashboard
NAME                                         READY   STATUS    RESTARTS   AGE
dashboard-metrics-scraper-7bfdf779ff-f9zwn   1/1     Running   0          41s
kubernetes-dashboard-6cdd697d84-lvzvz        1/1     Running   0          41s
1
2
3
4

(3)访问

首先将 kubernetes-dashboard 的 service 改成 NodePort,然后通过节点 IP+NodePort 端口进行访问。

修改完成过后信息如下。

kubectl get svc -n kubernetes-dashboard
NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)         AGE
dashboard-metrics-scraper   ClusterIP   10.109.224.102   <none>        8000/TCP        113s
kubernetes-dashboard        NodePort    10.101.69.180    <none>        443:30497/TCP   113s
1
2
3
4

在浏览器输入https://192.168.205.128:30497进行访问,如下:

c081257c2192d5f32a2202ad0b90db43 MD5

这里访问要使用token或者kubeconfig,这里使用 token 进行访问。

(1)生成 token,这里直接生成 admin 级别的 token。

apiVersion: v1
kind: ServiceAccount
metadata:
  name: dashboard-admin
  namespace: kube-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: dashboard-admin
  namespace: kube-system
[root@kk-master ~]## cat admin-token.yaml
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: dashboard-admin
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
roleRef:
  kind: ClusterRole
  name: admin
  apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
  name: dashboard-admin
  namespace: kube-system
---
apiVersion: v1
kind: Secret
type: kubernetes.io/service-account-token
metadata:
  name: dashboard-admin
  namespace: kube-system
  annotations:
    kubernetes.io/service-account.name: "dashboard-admin"
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

说明:从 kubernetes 1.24 版本开始,移除了创建 serviceaccount 自动创建 secret token 的功能,所以需要自己创建 secret token 和 serviceaccount 进行关联。

(2)获取 token

## 获取token的值
kubectl -n kube-system get secret dashboard-admin -o jsonpath={.data.token}|base64 -d
1
2

然后就可以登录查看集群信息了。

27d1471bd680ac22062869a2886d74b5 MD5

# 更新集群

集群的更新操作有很多,比如创建或删除应用、添加或者删除节点等,这里主要介绍几种常用的操作:

  • 升级集群
  • 更新集群证书
  • 添加或删除集群

# 升级集群

Kubernetes 社区新版本的推出速度很快的,至少保持一年 3 个版本的迭代。在实际生产中,我们可能不会频繁的升级集群,因为这样的动作太大,可能导致其他生产问题。

但是,有时候会因为某些原因(比如软件版本兼容性、集群 BUG 等)不得不做升级集群的操作,所以,有必要掌握集群的升级方法以备不时之需。

# 升级前准备

  • 升级前,需要认真阅读每个版本的CHANGELOG (opens new window)。
  • 务必备份所有重要组件,例如存储在数据库中应用层面的状态。 kubeadm upgrade 不会影响你的工作负载,只会涉及 Kubernetes 内部的组件,但备份终究是好的。
  • 可以小版本升级,也可以跨一个大版本升级,不建议跨两个大版本升级

# 升级目标

现在集群的版本是 1.24.0,预计升级的目标版本是 1.24.2。

kubectl get nodes
NAME        STATUS   ROLES           AGE     VERSION
kk-master   Ready    control-plane   7m20s   v1.24.0
kk-node01   Ready    <none>          6m40s   v1.24.0
1
2
3
4

# 备份集群

kubeadm upgrade 不会影响你的工作负载,只会涉及 Kubernetes 内部的组件,但备份终究是好的。这里主要是对集群的所有资源进行备份,我使用的是一个开源的脚本,项目地址是:https://github.com/solomonxu/k8s-backup-restore (opens new window)

(1)下载脚本

mkdir -p /data
cd /data
git clone https://github.com/solomonxu/k8s-backup-restore.git
1
2
3

(2)执行备份

cd /data/k8s-backup-restore
./bin/k8s_backup.sh
1
2

如果要恢复怎么办?只需要执行如下步骤。
(1)创建恢复目录

mkdir -p /data/k8s-backup-restore/data/restore
1

(2)将需要恢复的 YAML 清单复制到该目录下

cp devops_deployments_gitlab.yaml ../../restore/
1

(3)执行恢复命令

cd /data/k8s-backup-restore
./bin/k8s_restore.sh
1
2

# 升级控制节点

(1)确定要升级的版本包是否存在

yum list --showduplicates kubeadm --disableexcludes=kubernetes
1

(2)升级 kubeadm 到指定版本

yum install -y kubeadm-1.24.2-0 --disableexcludes=kubernetes
1

执行以下命令查看是否升级成功。

kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"24", GitVersion:"v1.24.2", GitCommit:"f66044f4361b9f1f96f0053dd46cb7dce5e990a8", GitTreeState:"clean", BuildDate:"2022-06-15T14:20:54Z", GoVersion:"go1.18.3", Compiler:"gc", Platform:"linux/amd64"}
1
2

(3)排空节点

kubectl cordon kk-master
kubectl drain kk-master
1
2

(4)运行升级计划,查看是否可以升级

kubeadm upgrade plan
[upgrade/config] Making sure the configuration is correct:
[upgrade/config] Reading configuration from the cluster...
[upgrade/config] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[preflight] Running pre-flight checks.
[upgrade] Running cluster health checks
[upgrade] Fetching available versions to upgrade to
[upgrade/versions] Cluster version: v1.24.0
[upgrade/versions] kubeadm version: v1.24.2
[upgrade/versions] Target version: v1.24.2
[upgrade/versions] Latest version in the v1.24 series: v1.24.2

Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
COMPONENT   CURRENT       TARGET
kubelet     2 x v1.24.0   v1.24.2

Upgrade to the latest version in the v1.24 series:

COMPONENT                 CURRENT   TARGET
kube-apiserver            v1.24.0   v1.24.2
kube-controller-manager   v1.24.0   v1.24.2
kube-scheduler            v1.24.0   v1.24.2
kube-proxy                v1.24.0   v1.24.2
CoreDNS                   v1.8.6    v1.8.6
etcd                      3.5.3-0   3.5.3-0

You can now apply the upgrade by executing the following command:

        kubeadm upgrade apply v1.24.2

_____________________________________________________________________


The table below shows the current state of component configs as understood by this version of kubeadm.
Configs that have a "yes" mark in the "MANUAL UPGRADE REQUIRED" column require manual config upgrade or
resetting to kubeadm defaults before a successful upgrade can be performed. The version to manually
upgrade to is denoted in the "PREFERRED VERSION" column.

API GROUP                 CURRENT VERSION   PREFERRED VERSION   MANUAL UPGRADE REQUIRED
kubeproxy.config.k8s.io   v1alpha1          v1alpha1            no
kubelet.config.k8s.io     v1beta1           v1beta1             no
_____________________________________________________________________
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

(5)升级集群

kubeadm upgrade apply v1.24.2 --config kubeadm.yaml
1

看到如下输出表示升级成功。

......
[upgrade/successful] SUCCESS! Your cluster was upgraded to "v1.24.2". Enjoy!
......
1
2
3

(6)取消节点调度保护

kubectl uncordon kk-master
1

(7)由于这里 Master 即是控制平面,也是节点,所以需要对其在进行一次升级

kubeadm upgrade node
1

(8)升级 kubectl 和 kubelet

yum install -y kubelet-1.24.2-0 kubectl-1.24.2-0 --disableexcludes=kubernetes
1

(9)重启 kubelet

systemctl daemon-reload
systemctl restart kubelet
1
2

# 升级节点

(1)升级 kubeadm

yum install -y kubeadm-1.24.2-0 --disableexcludes=kubernetes
1

(2)设置节点不可调度且排空节点

kubectl cordon kk-node01
kubectl drain kk-node01
1
2

(3)升级节点

kubeadm upgrade node
1

(4)升级 kubelet

yum install -y kubelet-1.24.2-0 --disableexcludes=kubernetes
1

(5)重启节点

systemctl daemon-reload
systemctl restart kubelet
1
2

(6)恢复节点可调度

kubectl uncordon kk-node01
1

# 验证集群

(1)查看集群状态信息是否正常

kubectl get no
NAME        STATUS   ROLES           AGE   VERSION
kk-master   Ready    control-plane   33m   v1.24.2
kk-node01   Ready    <none>          32m   v1.24.2
1
2
3
4

(2)查看集群 Pod 是否正常

kubectl get po -A
NAMESPACE     NAME                                       READY   STATUS    RESTARTS   AGE
kube-system   calico-kube-controllers-5d49fc6c56-pq57d   1/1     Running   0          31m
kube-system   calico-node-rjdqh                          1/1     Running   0          31m
kube-system   calico-node-s8475                          1/1     Running   0          31m
kube-system   coredns-7f74c56694-qpvmv                   1/1     Running   0          35m
kube-system   coredns-7f74c56694-ww8kb                   1/1     Running   0          35m
kube-system   etcd-kk-master                             1/1     Running   0          35m
kube-system   kube-apiserver-kk-master                   1/1     Running   0          11m
kube-system   kube-controller-manager-kk-master          1/1     Running   0          10m
kube-system   kube-proxy-5pf65                           1/1     Running   0          10m
kube-system   kube-proxy-mcxlq                           1/1     Running   0          10m
kube-system   kube-scheduler-kk-master                   1/1     Running   0          10m
1
2
3
4
5
6
7
8
9
10
11
12
13

# 其他

在升级过程中如果升级失败并且没有回滚,可以继续执行kubeadm upgrade。如果要从故障状态恢复,可以执行kubeadm upgrade --force。

在升级期间,会在/etc/kubernetes/tmp目录下生成备份文件:

  • kubeadm-backup-etcd-<datetime>
  • kubeadm-backup-manifests-<datetime>

kubeadm-backup-etcd 中包含本地 etcd 的数据备份,如果升级失败并且无法修复,可以将其数据复制到 etcd 数据目录进行手动修复。

kubeadm-backup-manifests 中保存的是节点静态 pod 的 YAML 清单,如果升级失败并且无法修复,可以将其复制到/etc/kubernetes/manifests下进行手动修复。

# 升级证书

升级集群可能不会经常发送,但是升级证书应该是一个常态化操作。

使用 kubeadm 安装的证书默认有效期是一年,也就是说在证书过期之前必须对证书进行升级,不然就会导致整个集群异常。

可以使用如下命令查看集群的证书情况。

kubeadm certs check-expiration
[check-expiration] Reading configuration from the cluster...
[check-expiration] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'

CERTIFICATE                EXPIRES                  RESIDUAL TIME   CERTIFICATE AUTHORITY   EXTERNALLY MANAGED
admin.conf                 Jul 04, 2023 08:43 UTC   364d            ca                      no
apiserver                  Jul 04, 2023 08:39 UTC   364d            ca                      no
apiserver-etcd-client      Jul 04, 2023 08:39 UTC   364d            etcd-ca                 no
apiserver-kubelet-client   Jul 04, 2023 08:39 UTC   364d            ca                      no
controller-manager.conf    Jul 04, 2023 08:40 UTC   364d            ca                      no
etcd-healthcheck-client    Jul 04, 2023 08:16 UTC   364d            etcd-ca                 no
etcd-peer                  Jul 04, 2023 08:16 UTC   364d            etcd-ca                 no
etcd-server                Jul 04, 2023 08:16 UTC   364d            etcd-ca                 no
front-proxy-client         Jul 04, 2023 08:39 UTC   364d            front-proxy-ca          no
scheduler.conf             Jul 04, 2023 08:40 UTC   364d            ca                      no

CERTIFICATE AUTHORITY   EXPIRES                  RESIDUAL TIME   EXTERNALLY MANAGED
ca                      Jul 01, 2032 08:16 UTC   9y              no
etcd-ca                 Jul 01, 2032 08:16 UTC   9y              no
front-proxy-ca          Jul 01, 2032 08:16 UTC   9y              no
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

(1)使用kubeadm certs check-expiration检查证书是否过期

(2)备份证书

mkdir /etc/kubernetes.bak.20220704
cp -r /etc/kubernetes/* /etc/kubernetes.bak.20220704
1
2

(3)备份 etcd 数据库

## 备份数据目录
cp -r /var/lib/etcd /var/lib/etcd.bak
## 快照备份
export ETCDCTL_API=3
etcdctl --endpoints localhost:2379 snapshot save snapshot.db \
          --cacert=/etc/kubernetes/pki/etcd/ca.crt  \
          --cert=/etc/kubernetes/pki/etcd/server.crt \
          --key=/etc/kubernetes/pki/etcd/server.key
## 快照恢复命令
etcdctl snapshot restore snapshot.db --name m3 --data-dir=/home/etcd_data
1
2
3
4
5
6
7
8
9
10

(4)更新证书

kubeadm alpha certs renew all --config=kubeadm.yaml
1

(5)更新 kubeconfig

kubeadm init phase kubeconfig all --config kubeadm.yaml
1

(6)覆盖控制节点的 kubeconfig

mv $HOME/.kube/config $HOME/.kube/config.old
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
## chown $(id -u):$(id -g) $HOME/.kube/config
1
2
3

(7)完成后重启 kubernetes 控制面的组件

cd /etc/kubernetes/manifests
mv *.yaml ../
mv ../*.yaml .
1
2
3

containerd 运行时没有重启容器的命令,所以这里采用是直接移出再拷贝进来的操作。如果底层安装有 docker,可以使用 docker 命令进行重启。

(8)检查证书是否更新

echo | openssl s_client -showcerts -connect 127.0.0.1:6443 -servername api 2>/dev/null | openssl x509 -noout -enddate

kubeadm certs check-expiration
[check-expiration] Reading configuration from the cluster...
[check-expiration] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'

CERTIFICATE                EXPIRES                  RESIDUAL TIME   CERTIFICATE AUTHORITY   EXTERNALLY MANAGED
admin.conf                 Jul 04, 2023 09:21 UTC   364d            ca                      no
apiserver                  Jul 04, 2023 09:21 UTC   364d            ca                      no
apiserver-etcd-client      Jul 04, 2023 09:21 UTC   364d            etcd-ca                 no
apiserver-kubelet-client   Jul 04, 2023 09:21 UTC   364d            ca                      no
controller-manager.conf    Jul 04, 2023 09:21 UTC   364d            ca                      no
etcd-healthcheck-client    Jul 04, 2023 09:21 UTC   364d            etcd-ca                 no
etcd-peer                  Jul 04, 2023 09:21 UTC   364d            etcd-ca                 no
etcd-server                Jul 04, 2023 09:21 UTC   364d            etcd-ca                 no
front-proxy-client         Jul 04, 2023 09:21 UTC   364d            front-proxy-ca          no
scheduler.conf             Jul 04, 2023 09:21 UTC   364d            ca                      no

CERTIFICATE AUTHORITY   EXPIRES                  RESIDUAL TIME   EXTERNALLY MANAGED
ca                      Jul 01, 2032 08:16 UTC   9y              no
etcd-ca                 Jul 01, 2032 08:16 UTC   9y              no
front-proxy-ca          Jul 01, 2032 08:16 UTC   9y              no
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

(7)其他

默认情况下,kubeadm 使用 /etc/kubernetes/kubelet.conf中指定的 /var/lib/kubelet/pki/kubelet-client-current.pem 符号链接 来配置 kubelet 自动轮换客户端证书。如果此轮换过程失败,你可能会在 kube-apiserver 日志中看到 诸如x509: certificate has expired or is not yet valid之类的错误。

要解决此问题,你必须执行以下步骤:

  1. 从故障节点备份和删除 /etc/kubernetes/kubelet.conf 和 /var/lib/kubelet/pki/kubelet-client。
  2. 在集群中具有 /etc/kubernetes/pki/ca.key 的、正常工作的控制平面节点上 执行 kubeadm alpha kubeconfig user --org system:nodes --client-name system:node:$NODE > kubelet.conf。 $NODE 必须设置为集群中现有故障节点的名称。 手动修改生成的 kubelet.conf 以调整集群名称和服务器端点, 或传递 kubeconfig user --config(此命令接受 InitConfiguration)。 如果你的集群没有 ca.key,你必须在外部对 kubelet.conf 中的嵌入式证书进行签名。
  3. 将得到的 kubelet.conf 文件复制到故障节点上,作为 /etc/kubernetes/kubelet.conf。
  4. 在故障节点上重启 kubelet(systemctl restart kubelet),等待 /var/lib/kubelet/pki/kubelet-client-current.pem 重新创建。
  5. 在故障节点上运行 kubeadm init phase kubelet-finalize all。 这将使新的 kubelet.conf 文件使用 /var/lib/kubelet/pki/kubelet-client-current.pem 并将重新启动 kubelet。
  6. 确保节点状况变为 Ready。

PS:除了使用上面方式升级集群证书之外,还可以通过升级集群版本的方式升级证书。

# 添加/删除节点

当集群节点不足以支撑业务的时候,我们也许会对集群进行扩容,也就是添加节点以满足日常需求。当集群节点比较空闲的时候,也会对集群进行缩容,也就是删除节点以节约开支。

所以添加/删除节点在日常的工作中是比较常见的操作,而且整体操作也比较简单。

# 添加节点

添加节点的操作和初始化 node 节点一样,严格按照环境准备和初始化Node节点操作即可。

有几点需要注意:

(1)所有主机 hosts 添加新的主机

cat >> /etc/hosts << EOF
192.168.205.128 kk-master
192.168.205.130 kk-node01
192.168.205.133 kk-node02
EOF
1
2
3
4
5

(2)查看集群 token

kubeadm token list
1

(3)如果 token 不存在就自己创建

kubeadm token create
1

(4)获取 ca 证书 sha256 编码 hash 值

kubeadm join 192.168.205.128:6443 --token q0mjah.4k3oavynezdj8jf9 \
     --discovery-token-ca-cert-hash sha256:3d5c2e7d2532a4f085159d89de3ea2ea515e0784787b9c1adf0d3826c283733c \
     --node-name kk-node02
1
2
3

(5)然后可以看到集群添加成功

kubectl get no
NAME        STATUS   ROLES           AGE    VERSION
kk-master   Ready    control-plane   111m   v1.24.2
kk-node01   Ready    <none>          111m   v1.24.2
kk-node02   Ready    <none>          54s    v1.24.2
1
2
3
4
5

# 删除节点

删除节点的操作也非常简单,总结如下:

(1)设置节点不可调度

kubectl cordon kk-node02
1

(2)驱逐待删除节点上面的 Pod

 kubectl drain kk-node02 --ignore-daemonsets=true --delete-emptydir-data=true
1

(3)然后进行节点删除

kubectl delete nodes kk-node02
1

现在,节点已经从整个集群移除。

# 备份 K8s 集群

对任何系统来说,备份都必不可少,比如备份数据库,备份文件系统,备份配置文件等。

对于 Kubernetes 来说,备份也尤为重要。Kubernetes 中的所有对象都是存储在 Etcd 中,我们可以直接对数据库进行备份。当然,Kubernetes 中所有对象的配置文件也是可见的,我们也可以直接对这些配置文件进行备份。

在真正使用中,一般会做两手方案,即备份数据库和备份配置清单。如果其中一种方案无法进行恢复,还可以通过另一种来兜底。

这里同时会介绍备份 Etcd 数据库和备份集群配置清单,以方便各位在实际中酌情处理。

# 备份数据库

# 备份

备份数据库比较简单,可以直接用 etcdctl 进行备份,在上面升级证书章节有简单提到。

(1)安装 etcdctl 命令,在https://github.com/etcd-io/etcd/releases (opens new window)上下载对应的 etcd 安装包

wget https://github.com/etcd-io/etcd/releases/download/v3.5.3/etcd-v3.5.3-linux-amd64.tar.gz
tar xf etcd-v3.5.3-linux-amd64.tar.gz
mv etcd-v3.5.3-linux-amd64/etcdctl /usr/local/bin/
1
2
3

(2)检验命令

etcdctl version
etcdctl version: 3.5.3
API version: 3.5
1
2
3

(3)进行备份操作

export ETCDCTL_API=3
etcdctl --endpoints localhost:2379 snapshot save snapshot.db \
          --cacert=/etc/kubernetes/pki/etcd/ca.crt  \
          --cert=/etc/kubernetes/pki/etcd/server.crt \
          --key=/etc/kubernetes/pki/etcd/server.key
1
2
3
4
5

备份 Ectd 需要指定证书,如果执行节点没有,可以从主节点拷贝过来。

执行完成过后,可以在当前目录查看到备份结果。

export ETCDCTL_API=3
etcdctl --endpoints localhost:2379 snapshot save snapshot.db \
>           --cacert=/etc/kubernetes/pki/etcd/ca.crt  \
>           --cert=/etc/kubernetes/pki/etcd/server.crt \
>           --key=/etc/kubernetes/pki/etcd/server.key
{"level":"info","ts":"2022-07-04T20:00:17.509+0800","caller":"snapshot/v3_snapshot.go:65","msg":"created temporary db file","path":"snapshot.db.part"}
{"level":"info","ts":"2022-07-04T20:00:17.520+0800","logger":"client","caller":"v3/maintenance.go:211","msg":"opened snapshot stream; downloading"}
{"level":"info","ts":"2022-07-04T20:00:17.520+0800","caller":"snapshot/v3_snapshot.go:73","msg":"fetching snapshot","endpoint":"localhost:2379"}
{"level":"info","ts":"2022-07-04T20:00:17.544+0800","logger":"client","caller":"v3/maintenance.go:219","msg":"completed snapshot read; closing"}
{"level":"info","ts":"2022-07-04T20:00:17.556+0800","caller":"snapshot/v3_snapshot.go:88","msg":"fetched snapshot","endpoint":"localhost:2379","size":"3.6 MB","took":"now"}
{"level":"info","ts":"2022-07-04T20:00:17.556+0800","caller":"snapshot/v3_snapshot.go:97","msg":"saved","path":"snapshot.db"}
Snapshot saved at snapshot.db
ll
total 3472
-rw-------. 1 root root 3551264 Jul  4 20:00 snapshot.db
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

但是,我们不可能每次都手动来进行备份,所以最好是通过定时任务来执行。为了更好的备份,这里编写了一个简单的 shell 脚本,然后再加到定时任务中。

##! /bin/bash


ETCDCTL_PATH='/usr/local/bin/etcdctl'
ENDPOINTS='192.168.205.128:2379'
ETCD_DATA_DIR="/var/lib/etcd"
BACKUP_DIR="/var/backups/kube_etcd/etcd-$(date +%Y-%m-%d_%H:%M:%S)"

ETCDCTL_CERT="/etc/kubernetes/pki/etcd/server.crt"
ETCDCTL_KEY="/etc/kubernetes/pki/etcd/server.key"
ETCDCTL_CA_FILE="/etc/kubernetes/pki/etcd/ca.crt"


[ ! -d $BACKUP_DIR ] && mkdir -p $BACKUP_DIR


export ETCDCTL_API=2;$ETCDCTL_PATH backup --data-dir $ETCD_DATA_DIR --backup-dir $BACKUP_DIR

sleep 3

{
export ETCDCTL_API=3;$ETCDCTL_PATH --endpoints="$ENDPOINTS" snapshot save $BACKUP_DIR/snapshot.db \
                                   --cacert="$ETCDCTL_CA_FILE" \
                                   --cert="$ETCDCTL_CERT" \
                                   --key="$ETCDCTL_KEY"
} > /dev/null

sleep 3

cd $BACKUP_DIR/../;ls -lt |awk '{if(NR>(5+1)){print "rm -rf "$9}}'|sh
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

然后加入 Linux 定时任务,如下:

crontab -l
*/30 * * * * /opt/etcd_back/etcd_backup.sh
1
2

# 恢复

(1)停止 kube-apiserver 和 etcd

我这里直接将所有静态 Pod 的 YAML 文件移除。

cd /etc/kubernetes/manifests
mv *.yaml ../
1
2

(2)移除 etcd 数据目录

mv /var/lib/etcd{,.bak.20220705}
1

(3)执行恢复

ETCDCTL_API=3 etcdctl snapshot restore snapshot.db   --name kk-master   --initial-cluster "kk-master=https://192.168.205.128:2380"    --initial-cluster-token etcd-cluster   --initial-advertise-peer-urls https://192.168.205.128:2380   --data-dir=/var/lib/etcd
1

(4)重启 Kubernetes 组件

 mv ../*.yaml .
1

(5)验证集群状态

kubectl get nodes
NAME        STATUS   ROLES           AGE     VERSION
kk-master   Ready    control-plane   7h48m   v1.24.2
kk-node01   Ready    <none>          7h48m   v1.24.2
kubectl get po -A
NAMESPACE     NAME                                       READY   STATUS    RESTARTS            AGE
default       nginx1-585f98d7bf-45fnk                    1/1     Running   0                   3h58m
kube-system   calico-kube-controllers-5d49fc6c56-pq57d   1/1     Running   3 (<invalid> ago)   7h45m
kube-system   calico-node-rjdqh                          1/1     Running   0                   7h45m
kube-system   calico-node-s8475                          1/1     Running   0                   7h45m
kube-system   coredns-7f74c56694-qpvmv                   1/1     Running   0                   7h48m
kube-system   coredns-7f74c56694-ww8kb                   1/1     Running   0                   7h48m
kube-system   etcd-kk-master                             1/1     Running   0                   7h48m
kube-system   kube-apiserver-kk-master                   1/1     Running   2 (2m1s ago)        7h24m
kube-system   kube-controller-manager-kk-master          1/1     Running   0                   7h24m
kube-system   kube-proxy-5pf65                           1/1     Running   0                   7h24m
kube-system   kube-proxy-mcxlq                           1/1     Running   0                   7h23m
kube-system   kube-scheduler-kk-master                   1/1     Running   0                   7h24m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 备份集群清单

在 Kubernetes 的实际使用中,需要备份的集群清单主要有以下几种:

  • Deployment 类
  • StatfulSet 类
  • DaemonSet 类
  • Service 类
  • ConfigMap 类
  • Secret 类
  • CronJob 类
  • ......

备份整个清单可以用于快速恢复集群。而且由于备份 etcd 是备份的某一时刻的完整数据,无法选择备份哪些内容,并且其备份的数据除了 etcd 本身,其他程序不可读。

备份集群的方式有很多 ,简单点的可以按照“备份集群”的步骤使用脚本进行备份,由于上面已经介绍了这种方法,这章节将采用另外的工具——velero 进行备份。

velero 是开源方案,项目地址:https://velero.io/

velero 的作用:

  • 灾备能力:提供备份恢复 k8s 集群的能力
  • 迁移能力:提供拷贝集群资源到其他集群的能力

和 etcd 备份的区别:

  • etcd 的备份必须拥有 etcd 运维权限,有些用户无法操作 etcd,如多租户场景。
  • etcd 更适合单集群内数据备份,不太适合集群迁移
  • etcd 是当前状态备份,velero 可以做到只备份集群内的一部分资源

velero 会在你的 k8s 集群上运行一个 server pod,然后配合 velero 客户端进行操作,安装过程可以参考文档 (opens new window),操作是很简单的。

# 安装客户端

到https://github.com/vmware-tanzu/velero/releases (opens new window)下载对应的版本并安装

wget https://github.com/vmware-tanzu/velero/releases/download/v1.9.0/velero-v1.9.0-linux-amd64.tar.gz
tar xf velero-v1.9.0-linux-amd64.tar.gz
mv velero-v1.9.0-linux-amd64/velero /usr/local/bin/
velero version
Client:
        Version: v1.9.0
        Git commit: 6021f148c4d7721285e815a3e1af761262bff029
<error getting server version: namespaces "velero" not found>
1
2
3
4
5
6
7
8

# 安装服务端

安装服务端的方式有两种:

  • 使用 velero 客户端安装
  • 使用 helm chart 安装

这里使用 velero 客户端进行安装。velero 的后端可以选择很多对象存储,比如阿里云 OSS,mino 等。由于阿里云 OSS 需要单独购买,所以这里采用 minio 作为后端存储。

# 安装 minio

(1)添加 helm 源

helm repo add minio https://helm.min.io/
1

(2)部署 minio。由于这里只是做测试,所以没有做数据持久化等处理。

helm install minio \
  --namespace velero --create-namespace \
  --set accessKey=minio,secretKey=minio123 \
  --set mode=standalone \
  --set service.type=NodePort \
  --set persistence.enabled=false \
  minio/minio
1
2
3
4
5
6
7

(2)使用 UI 访问查看

kubectl get svc -n velero
NAME    TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
minio   NodePort   10.110.75.97   <none>        9000:32000/TCP   92s
1
2
3

2097fc122006f810ea9be858f352a8e7 MD5

登录用户名密码为:minio:minio123

# 安装 velero 服务端

(1)在 minio 上创建 buckrt

ada90197baa11a93e207610b474c4018 MD5

(2)在 velero 安装目录中创建 credentials-velero,写入以下内容

[default]
aws_access_key_id=minio
aws_secret_access_key=minio123
1
2
3

(3)安装 velero

velero install    \
     --provider aws   \
     --bucket velero   \
     --image velero/velero:v1.6.3  \
  --plugins velero/velero-plugin-for-aws:v1.2.1  \
  --namespace velero  \
  --secret-file ./credentials-velero  \
  --use-volume-snapshots=false \
     --use-restic \
  --backup-location-config region=minio,s3ForcePathStyle="true",s3Url=http://minio.velero.svc:9000
1
2
3
4
5
6
7
8
9
10

(4)检查所有组件是否正常启动

kubectl get po -n velero
NAME                     READY   STATUS    RESTARTS   AGE
minio-6c9f559d5b-cpc2d   1/1     Running   0          3m3s
restic-pq5bm             1/1     Running   0          3m28s
velero-887577984-2tmm4   1/1     Running   0          3m28s
1
2
3
4
5

# 执行备份操作

(1)在 default 的 namespace 下创建一个 nginx Pod

kubectl create deployment nginx --image nginx
1

(2)执行备份操作,备份 default 下面的资源

velero backup create default-backup-20220705 --include-namespaces default --default-volumes-to-restic
1

(3)在 minio 上可以查看到备份的目录已经存在

815abb30a143e3340993ba534ff63958 MD5

(4)现在删除 default 命名空间下的 nginx Pod

kubectl delete deployment nginx
1

(5)执行恢复操作

velero restore create --from-backup default-backup-20220705
1

(6)可以看到 default 命名空间下的 nginx Pod 已经恢复

kubectl get po
NAME                    READY   STATUS    RESTARTS   AGE
nginx-8f458dc5b-z6fnh   1/1     Running   0          38s
1
2
3

# 总结

Kubernetes 是应用的底座,如果底座出问题了,就谈不上应用的稳定性。在实际的工作中,对基础平台的备份尤为重要,可以在遇到不可描述的事情时有兜底的方案,所以,建议对 Kubernetes 做好备份操作,最好是定时备份。

# 最后

上面就是常用的集群相关操作,熟练的掌握它们,并应用于实际,可以为你节约不少的时间成本。

当然除了这些常规操作,还有迁移集群、导入集群等,我认为其本质上还是备份还原的问题,只是会多考虑一点数据完整性和业务连续性,这跟具体的企业情况相关,所以在这里也不在赘述,如有兴趣可以私下交流。

# 链接

  • https://github.com/kubernetes/kubernetes/tree/master/CHANGELOG (opens new window)
上次更新: 2025/07/19, 21:23:02
Kubernetes核心对象
Kubernetes权限管理

← Kubernetes核心对象 Kubernetes权限管理→

最近更新
01
elastic 账户认证 401 问题
07-20
02
使用 helm 安装 es 和 kibana
07-20
03
elastic stack 搭建
07-20
更多文章>
Theme by Vdoing | Copyright © 2019-2025 乔克 | MIT License | 渝ICP备20002153号 |
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式