一文弄懂Kubernetes集群管理

树叶云

一文弄懂Kubernetes集群管理

作者:乔克 2022-08-09 09:10:43

云计算

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

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

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

安装集群

前置说明

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.128kk-master
192.168.205.130kk-node01
EOF

(2)关闭防火墙和SELinux。

$systemctlstopfirewalld
$systemctldisablefirewalld
$setenforce0
$cat/etc/selinux/config
SELINUX=disabled

(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

执行以下命令使其生效:

$modprobebr_netfilter
$sysctl-p/etc/sysctl.d/k8s.conf

(4)关闭swap空间。

$swapoff-a

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

$cat/etc/fstab
#
#/etc/fstab
#CreatedbyanacondaonTueApr1217:10:162022
#
#Accessiblefilesystems, byreference, aremaintainedunder'/dev/disk'
#Seemanpagesfstab(5), findfs(8), mount(8) and/orblkid(8) formoreinfo
#
/dev/mapper/centos-root/xfsdefaults00
UUID=bc73c871-006c-4e24-a7af-6beb9aac06a7/bootxfsdefaults00
#/dev/mapper/centos-swapswapswapdefaults00

(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
$chmod755/etc/sysconfig/modules/ipvs.modules&&bash/etc/sysconfig/modules/ipvs.modules&&lsmod|grep-eip_vs-enf_conntrack_ipv4
$yuminstallipsetipvsadm-y

(6)同步服务器时间。

$yuminstallchrony-y
$systemctlenablechronyd
$systemctlstartchronyd
$chronycsources

(7)安装containerd。

$yuminstall-yyum-utils\
device-mapper-persistent-data\
lvm2
$yum-config-manager\
--add-repo\
https://download.docker.com/linux/centos/docker-ce.repo
$yumlist|grepcontainerd
$yuminstallcontainerd-y

创建containerd配置文件。

$mkdir-p/etc/containerd
#containerdconfigdefault>/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

启动containerd。

$systemctldaemon-reload
$systemctlenablecontainerd
$systemctlrestartcontainerd

(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

安装指定版本的组件。

$yuminstall-ykubelet-1.24.2kubeadm-1.24.2kubectl-1.24.2

设置运行时。

$crictlconfigruntime-endpoint/run/containerd/containerd.sock

设置kubelet为自启动。

$systemctldaemon-reload
$systemctlenablekubelet&&systemctlstartkubelet

初始化集群

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

初始化master节点

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

$kubeadmconfigprintinit-defaults>kubeadm.yaml

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

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

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

$kubeadminit--config=kubeadm.yaml
......
YourKubernetescontrol-planehasinitializedsuccessfully!
Tostartusingyourcluster, youneedtorunthefollowingasaregularuser:
mkdir-p$HOME/.kube
sudocp-i/etc/kubernetes/admin.conf$HOME/.kube/config
sudochown$(id-u):$(id-g) $HOME/.kube/config
Alternatively, ifyouaretherootuser, youcanrun:
exportKUBECONFIG=/etc/kubernetes/admin.conf
Youshouldnowdeployapodnetworktothecluster.
Run"kubectl apply -f [podnetwork].yaml"withoneoftheoptionslistedat:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Thenyoucanjoinanynumberofworkernodesbyrunningthefollowingoneachasroot:
kubeadmjoin192.168.205.128:6443--tokenabcdef.0123456789abcdef\
--discovery-token-ca-cert-hashsha256:51b5e566d3f95aaf3170916d67958bc16cb1b44934885a857b07ee58f041334a

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

初始化node节点

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

$kubeadmjoin192.168.205.128:6443--tokenabcdef.0123456789abcdef\
--discovery-token-ca-cert-hashsha256:51b5e566d3f95aaf3170916d67958bc16cb1b44934885a857b07ee58f041334a

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

$kubectlgetno
NAMESTATUSROLESAGEVERSION
kk-node01NotReady<none>15sv1.24.2
masterNotReadycontrol-plane3m29sv1.24.2

初始化网络

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

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

(1)下载calico的yaml清单。

$wgethttps://raw.githubusercontent.com/projectcalico/calico/master/manifests/calico.yaml

(2)安装calico。

$kubectlapply-fcalico.yaml

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

$kubectlgetpo-nkube-system|grepcalico
calico-kube-controllers-5d49fc6c56-szm6v1/1Running03m21s
calico-node-66q621/1Running03m21s
calico-node-lwrcm1/1Running03m21s

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

$kubectlgetno
NAMESTATUSROLESAGEVERSION
kk-node01Ready<none>26mv1.24.2
masterReadycontrol-plane29mv1.24.2

安装Dashboard

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

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

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

$kubectlapply-fhttps://raw.githubusercontent.com/kubernetes/dashboard/v2.5.0/aio/deploy/recommended.yaml

(2)查看安装情况。

$kubectlgetpo-nkubernetes-dashboard
NAMEREADYSTATUSRESTARTSAGE
dashboard-metrics-scraper-7bfdf779ff-f9zwn1/1Running041s
kubernetes-dashboard-6cdd697d84-lvzvz1/1Running041s

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

修改完成过后信息如下。

$kubectlgetsvc-nkubernetes-dashboard
NAMETYPECLUSTER-IPEXTERNAL-IPPORT(S) AGE
dashboard-metrics-scraperClusterIP10.109.224.102<none>8000/TCP113s
kubernetes-dashboardNodePort10.101.69.180<none>443:30497/TCP113s

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

这里访问要使用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~]#catadmin-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"

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

(2)获取token。

#获取token的值
$kubectl-nkube-systemgetsecretdashboard-admin-ojsonpath={.data.token}|base64-d

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

更新集群

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

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

升级集群

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

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

升级前准备

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

升级目标

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

$kubectlgetnodes
NAMESTATUSROLESAGEVERSION
kk-masterReadycontrol-plane7m20sv1.24.0
kk-node01Ready<none>6m40sv1.24.0

备份集群

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

(1)下载脚本。

$mkdir-p/data
$cd/data
$gitclonehttps://github.com/solomonxu/k8s-backup-restore.git

(2)执行备份。

$cd/data/k8s-backup-restore
$ ./bin/k8s_backup.sh

如果要恢复怎么办?只需要执行如下步骤。

(1)创建恢复目录。

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

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

$cpdevops_deployments_gitlab.yaml ../../restore/

(3)执行恢复命令。

$cd/data/k8s-backup-restore
$ ./bin/k8s_restore.sh

升级控制节点

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

$yumlist--showduplicateskubeadm--disableexcludes=kubernetes

(2)升级kubeadm到指定版本。

$yuminstall-ykubeadm-1.24.2-0--disableexcludes=kubernetes

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

$ 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"}

(3)排空节点。

$kubectlcordonkk-master
$kubectldrainkk-master

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

$kubeadmupgradeplan
[upgrade/config] Makingsuretheconfigurationiscorrect:
[upgrade/config] Readingconfigurationfromthecluster...
[upgrade/config] FYI: Youcanlookatthisconfigfilewith'kubectl -n kube-system get cm kubeadm-config -o yaml'
[preflight] Runningpre-flightchecks.
[upgrade] Runningclusterhealthchecks
[upgrade] Fetchingavailableversionstoupgradeto
[upgrade/versions] Clusterversion: v1.24.0
[upgrade/versions] kubeadmversion: v1.24.2
[upgrade/versions] Targetversion: v1.24.2
[upgrade/versions] Latestversioninthev1.24series: v1.24.2
Componentsthatmustbeupgradedmanuallyafteryouhaveupgradedthecontrolplanewith'kubeadm upgrade apply':
COMPONENTCURRENTTARGET
kubelet2xv1.24.0v1.24.2
Upgradetothelatestversioninthev1.24series:
COMPONENTCURRENTTARGET
kube-apiserverv1.24.0v1.24.2
kube-controller-managerv1.24.0v1.24.2
kube-schedulerv1.24.0v1.24.2
kube-proxyv1.24.0v1.24.2
CoreDNSv1.8.6v1.8.6
etcd3.5.3-03.5.3-0
Youcannowapplytheupgradebyexecutingthefollowingcommand:
kubeadmupgradeapplyv1.24.2
_____________________________________________________________________
Thetablebelowshowsthecurrentstateofcomponentconfigsasunderstoodbythisversionofkubeadm.
Configsthathavea"yes"markinthe"MANUAL UPGRADE REQUIRED"columnrequiremanualconfigupgradeor
resettingtokubeadmdefaultsbeforeasuccessfulupgradecanbeperformed. Theversiontomanually
upgradetoisdenotedinthe"PREFERRED VERSION"column.
APIGROUPCURRENTVERSIONPREFERREDVERSIONMANUALUPGRADEREQUIRED
kubeproxy.config.k8s.iov1alpha1v1alpha1no
kubelet.config.k8s.iov1beta1v1beta1no
_____________________________________________________________________

(5)升级集群。

$kubeadmupgradeapplyv1.24.2--configkubeadm.yaml

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

......
[upgrade/successful] SUCCESS!Yourclusterwasupgradedto"v1.24.2". Enjoy!
......

(6)取消节点调度保护。

$kubectluncordonkk-master

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

$kubeadmupgradenode

(8)升级kubectl和kubelet。

$yuminstall-ykubelet-1.24.2-0kubectl-1.24.2-0--disableexcludes=kubernetes

(9)重启kubelet。

$systemctldaemon-reload
$systemctlrestartkubelet

升级节点

(1)升级kubeadm。

$yuminstall-ykubeadm-1.24.2-0--disableexcludes=kubernetes

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

$kubectlcordonkk-node01
$kubectldrainkk-node01

(3)升级节点。

$kubeadmupgradenode

(4)升级kubelet。

$yuminstall-ykubelet-1.24.2-0--disableexcludes=kubernetes

(5)重启节点。

$systemctldaemon-reload
$systemctlrestartkubelet

(6)恢复节点可调度。

$kubectluncordonkk-node01

验证集群

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

$kubectlgetno
NAMESTATUSROLESAGEVERSION
kk-masterReadycontrol-plane33mv1.24.2
kk-node01Ready<none>32mv1.24.2

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

$kubectlgetpo-A
NAMESPACENAMEREADYSTATUSRESTARTSAGE
kube-systemcalico-kube-controllers-5d49fc6c56-pq57d1/1Running031m
kube-systemcalico-node-rjdqh1/1Running031m
kube-systemcalico-node-s84751/1Running031m
kube-systemcoredns-7f74c56694-qpvmv1/1Running035m
kube-systemcoredns-7f74c56694-ww8kb1/1Running035m
kube-systemetcd-kk-master1/1Running035m
kube-systemkube-apiserver-kk-master1/1Running011m
kube-systemkube-controller-manager-kk-master1/1Running010m
kube-systemkube-proxy-5pf651/1Running010m
kube-systemkube-proxy-mcxlq1/1Running010m
kube-systemkube-scheduler-kk-master1/1Running010m

其他

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

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

  • kubeadm-backup-etcd-
  • kubeadm-backup-manifests-

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

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

升级证书

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

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

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

$kubeadmcertscheck-expiration
[check-expiration] Readingconfigurationfromthecluster...
[check-expiration] FYI: Youcanlookatthisconfigfilewith'kubectl -n kube-system get cm kubeadm-config -o yaml'
CERTIFICATEEXPIRESRESIDUALTIMECERTIFICATEAUTHORITYEXTERNALLYMANAGED
admin.confJul04, 202308:43UTC364dcano
apiserverJul04, 202308:39UTC364dcano
apiserver-etcd-clientJul04, 202308:39UTC364detcd-cano
apiserver-kubelet-clientJul04, 202308:39UTC364dcano
controller-manager.confJul04, 202308:40UTC364dcano
etcd-healthcheck-clientJul04, 202308:16UTC364detcd-cano
etcd-peerJul04, 202308:16UTC364detcd-cano
etcd-serverJul04, 202308:16UTC364detcd-cano
front-proxy-clientJul04, 202308:39UTC364dfront-proxy-cano
scheduler.confJul04, 202308:40UTC364dcano
CERTIFICATEAUTHORITYEXPIRESRESIDUALTIMEEXTERNALLYMANAGED
caJul01, 203208:16UTC9yno
etcd-caJul01, 203208:16UTC9yno
front-proxy-caJul01, 203208:16UTC9yno

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

(2)备份证书。

$mkdir/etc/kubernetes.bak.20220704
$cp-r/etc/kubernetes/* /etc/kubernetes.bak.20220704

(3)备份etcd数据库。

#备份数据目录
$cp-r/var/lib/etcd/var/lib/etcd.bak
#快照备份
$exportETCDCTL_API=3
$etcdctl--endpointslocalhost:2379snapshotsavesnapshot.db\
--cacert=/etc/kubernetes/pki/etcd/ca.crt\
--cert=/etc/kubernetes/pki/etcd/server.crt\
--key=/etc/kubernetes/pki/etcd/server.key
#快照恢复命令
$etcdctlsnapshotrestoresnapshot.db--namem3--data-dir=/home/etcd_data

(4)更新证书。

$kubeadmalphacertsrenewall--config=kubeadm.yaml

(5)更新kubeconfig。

$kubeadminitphasekubeconfigall--configkubeadm.yaml

(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

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

$cd/etc/kubernetes/manifests
$mv*.yaml ../
$mv ../*.yaml .

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

(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.128kk-master
192.168.205.130kk-node01
192.168.205.133kk-node02
EOF

(2)查看集群token。

$kubeadmtokenlist

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

$kubeadmtokencreate

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

$kubeadmjoin192.168.205.128:6443--tokenq0mjah.4k3oavynezdj8jf9\
--discovery-token-ca-cert-hashsha256:3d5c2e7d2532a4f085159d89de3ea2ea515e0784787b9c1adf0d3826c283733c\
--node-namekk-node02

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

$kubectlgetno
NAMESTATUSROLESAGEVERSION
kk-masterReadycontrol-plane111mv1.24.2
kk-node01Ready<none>111mv1.24.2
kk-node02Ready<none>54sv1.24.2

删除节点

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

(1)设置节点不可调度。

$kubectlcordonkk-node02

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

$kubectldrainkk-node02--ignore-daemonsets=true--delete-emptydir-data=true

(3)然后进行节点删除。

$ kubectl delete nodes kk-node02

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

备份集群

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

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

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

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

备份数据库

备份

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

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

$wgethttps://github.com/etcd-io/etcd/releases/download/v3.5.3/etcd-v3.5.3-linux-amd64.tar.gz
$tarxfetcd-v3.5.3-linux-amd64.tar.gz
$mvetcd-v3.5.3-linux-amd64/etcdctl/usr/local/bin/

(2)检验命令。

$etcdctlversion
etcdctlversion: 3.5.3
APIversion: 3.5

(3)进行备份操作。

$exportETCDCTL_API=3
$etcdctl--endpointslocalhost:2379snapshotsavesnapshot.db\
--cacert=/etc/kubernetes/pki/etcd/ca.crt\
--cert=/etc/kubernetes/pki/etcd/server.crt\
--key=/etc/kubernetes/pki/etcd/server.key

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

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

$exportETCDCTL_API=3
$etcdctl--endpointslocalhost:2379snapshotsavesnapshot.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"}
Snapshotsavedatsnapshot.db
$ll
total3472
-rw-------. 1rootroot3551264Jul420:00snapshot.db

但是,我们不可能每次都手动来进行备份,所以最好是通过定时任务来执行。为了更好的备份,这里编写了一个简单的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
exportETCDCTL_API=2;$ETCDCTL_PATHbackup--data-dir$ETCD_DATA_DIR--backup-dir$BACKUP_DIR
sleep3
{
exportETCDCTL_API=3;$ETCDCTL_PATH--endpoints="$ENDPOINTS"snapshotsave$BACKUP_DIR/snapshot.db\
--cacert="$ETCDCTL_CA_FILE"\
--cert="$ETCDCTL_CERT"\
--key="$ETCDCTL_KEY"
} >/dev/null
sleep3
cd$BACKUP_DIR/../;ls-lt|awk'{if(NR>(5+1)){print "rm -rf "$9}}'|sh

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

$crontab-l
*/30****/opt/etcd_back/etcd_backup.sh

恢复

(1)停止kube-apiserver和etcd。

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

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

(2)移除etcd数据目录。

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

(3)执行恢复。

ETCDCTL_API=3etcdctlsnapshotrestoresnapshot.db--namekk-master--initial-cluster"kk-master=https://192.168.205.128:2380"--initial-cluster-tokenetcd-cluster--initial-advertise-peer-urlshttps://192.168.205.128:2380   --data-dir=/var/lib/etcd

(4)重启Kubernetes组件。

mv ../*.yaml .

(5)验证集群状态。

$kubectlgetnodes
NAMESTATUSROLESAGEVERSION
kk-masterReadycontrol-plane7h48mv1.24.2
kk-node01Ready<none>7h48mv1.24.2
$kubectlgetpo-A
NAMESPACENAMEREADYSTATUSRESTARTSAGE
defaultnginx1-585f98d7bf-45fnk1/1Running03h58m
kube-systemcalico-kube-controllers-5d49fc6c56-pq57d1/1Running3 (<invalid>ago) 7h45m
kube-systemcalico-node-rjdqh1/1Running07h45m
kube-systemcalico-node-s84751/1Running07h45m
kube-systemcoredns-7f74c56694-qpvmv1/1Running07h48m
kube-systemcoredns-7f74c56694-ww8kb1/1Running07h48m
kube-systemetcd-kk-master1/1Running07h48m
kube-systemkube-apiserver-kk-master1/1Running2 (2m1sago) 7h24m
kube-systemkube-controller-manager-kk-master1/1Running07h24m
kube-systemkube-proxy-5pf651/1Running07h24m
kube-systemkube-proxy-mcxlq1/1Running07h23m
kube-systemkube-scheduler-kk-master1/1Running07h24m

备份集群清单

在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 客户端进行操作,安装过程可以参考文档,操作是很简单的。

安装客户端

到https://github.com/vmware-tanzu/velero/releases下载对应的版本并安装。

$wgethttps://github.com/vmware-tanzu/velero/releases/download/v1.9.0/velero-v1.9.0-linux-amd64.tar.gz
$tarxfvelero-v1.9.0-linux-amd64.tar.gz
$mvvelero-v1.9.0-linux-amd64/velero/usr/local/bin/
$veleroversion
Client:
Version: v1.9.0
Gitcommit: 6021f148c4d7721285e815a3e1af761262bff029
<errorgettingserverversion: namespaces"velero"notfound>

安装服务端

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

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

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

安装minio

(1)添加helm源。

$helmrepoaddminiohttps://helm.min.io/

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

$helminstallminio\
--namespacevelero--create-namespace\
--setaccessKey=minio,secretKey=minio123\
--setmode=standalone\
--setservice.type=NodePort\
--setpersistence.enabled=false\
minio/minio

(2)使用UI访问查看。

$kubectlgetsvc-nvelero
NAMETYPECLUSTER-IPEXTERNAL-IPPORT(S) AGE
minioNodePort10.110.75.97<none>9000:32000/TCP92s

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

安装velero服务端

(1)在minio上创建buckrt。

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

[default]
aws_access_key_id=minio
aws_secret_access_key=minio123

(3)安装velero。

$veleroinstall\
--provideraws\
--bucketvelero\
--imagevelero/velero:v1.6.3\
--pluginsvelero/velero-plugin-for-aws:v1.2.1\
--namespacevelero\
--secret-file ./credentials-velero\
--use-volume-snapshots=false\
--use-restic\
--backup-location-configregion=minio,s3ForcePathStyle="true",s3Url=http://minio.velero.svc:9000

(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)在default的namespace下创建一个nginx Pod。

$kubectlcreatedeploymentnginx--imagenginx

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

$velerobackupcreatedefault-backup-20220705--include-namespacesdefault--default-volumes-to-restic

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

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

$kubectldeletedeploymentnginx

(5)执行恢复操作。

$velerorestorecreate--from-backupdefault-backup-20220705

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

$kubectlgetpo
NAMEREADYSTATUSRESTARTSAGE
nginx-8f458dc5b-z6fnh1/1Running038s

总结

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

最后

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

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

文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/248938.html<

(0)
运维的头像运维
上一篇2025-04-27 19:50
下一篇 2025-04-27 19:51

相关推荐

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注