k8s-运维
K8S运维
记录以下管理k8s集群会用到或者我觉得可能会用到的东西.
证书管理
CA
: 根证书颁发机构
通过kubeadm
管理,目录路径: /etc/kubernetes/pki
1 |
|
apiserver.crt 和 apiserver.key: 这是 Kubernetes API 服务器的 TLS 证书和私钥。它们用于保护 API 服务器的通信。
apiserver-etcd-client.crt 和 apiserver-etcd-client.key: 这些是 API 服务器用来安全连接到 etcd 集群的客户端证书和私钥。
apiserver-kubelet-client.crt 和 apiserver-kubelet-client.key: 这些是 API 服务器用于与集群中每个 kubelet 安全通信的客户端证书和私钥。
ca.crt 和 ca.key: 这是您集群的根证书颁发机构 (CA) 的证书和私钥。几乎所有的组件证书都由这个 CA 签发。
etcd/ca.crt 和 etcd/ca.key: 这是用于 etcd 集群的专用 CA 的证书和私钥。etcd 是 Kubernetes 数据的存储后端。
etcd/healthcheck-client.crt 和 etcd/healthcheck-client.key: 在 etcd 集群中执行健康检查的客户端证书和私钥。
etcd/peer.crt 和 etcd/peer.key: etcd 节点之间通信的对等证书和私钥。
etcd/server.crt 和 etcd/server.key: etcd 服务器用于与其他组件(如 apiserver)通信的 TLS 证书和私钥。
front-proxy-ca.crt 和 front-proxy-ca.key: 是前端代理颁发机构的证书和私钥,用于代理客户端与 API 服务器之间的通信。
front-proxy-client.crt 和 front-proxy-client.key: 这是用于 Kubernetes API 服务器前端的代理客户端的证书和私钥。
sa.key 和 sa.pub: 这些是用于签名和验证服务账户令牌的私钥和公钥
生成
1 |
|
查看过期时间
1 |
|
更新
1 |
|
证书更新后要重启对应组件才能生效,在生产环境中就涉及不停机更新,pod驱逐等操作,最好在测试环境演练好并做好备份再在生产环境操作.
删除/备份
操作/etc/kubernetes/pki
目录
节点分配
节点亲和性
调度器(scheduler)上一个比较复杂,但更为强大的功能
必须规则(required)
也称为硬性规则,规则
必须
被满足,pod才能被调度.定义字段:requiredDuringSchedulingIgnoredDuringExecution
首选规则(preferred)
也称为软性规则,调度器会
尽量
满足这些规则.定义字段:preferredDuringSchedulingIgnoredDuringExecution
操作符
- In/NotIn: 确保节点标签
包含/不包含
在给定的值的列表中 - Exists/NotExists: 节点标签
存在/不存在
给定的key
,不管value是什么 - Gt/Lt: 用于基于数值的标签,保证节点标签拥有
大于/小于
特定数值的key
- In/NotIn: 确保节点标签
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
containers:
- name: nginx-container
image: nginx
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution: # 硬性
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
preferredDuringSchedulingIgnoredDuringExecution: # 软性
- weight: 1 # 软性可以有多个规则,根据权重决定优先级
preference:
matchExpressions:
- key: team
operator: In
values:
- researchNodeSelector
标签选择器,比较简单,就是通过
标签
,让pod运行在特定的节点上1
2
3
4
5
6
7
8
9
10apiVersion: v1
kind: Pod
metadata:
name: simple-pod
spec:
containers:
- name: simple-container
image: nginx
nodeSelector: # 通过标签选择节点
disktype: ssd
探针
- 启动(startup): 用于确定容器内的应用是否已经启动完整,直到启动探针检测成功,才会应用后两个探针.
- 存活(liveness): 检查容器是否在运行,检测失败,kubelet就会杀死容器根据重启策略重新启动.
- 就绪(readiness): 检测容器内应用是否已经准备好接受流量,如果检测失败,就会从它关联的所有service中除名.(不负载流量给它)
三种探针都有三种探测方式: http get / tcp socket / exec
1 |
|
pod资源限制
主要通过limits
和requests
来限制容器可以调用的资源
1 |
|
动态扩容
k8s的动态扩容有三种形式
水平扩容(HPA)
依赖
metrics-server
收集的资源使用数据来决定是否和何时进行扩容.水平扩容主要是针对pod副本的数量
进行扩容.比如cpu使用率超过80%,就加一个副本.1
2
3
4
5
6
7
8
9
10
11
12
13apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: example-hpa
namespace: default
spec:
scaleTargetRef: # 监控的target
apiVersion: apps/v1
kind: Deployment
name: example-deployment
minReplicas: 1 # cpu利用率低于50%,则会减少pod数量,最少1个
maxReplicas: 10 # 扩容最多10个
targetCPUUtilizationPercentage: 50 # 如果cpu利用率超过50%则会扩容垂直扩容(VPA)
与HPA类似,也是依赖metrics-server,但是垂直扩容针对的是
pod的使用资源
扩容.比如cpu使用率超过80%,就给这个pod加更多的cpu资源.垂直扩容比较适合一些不方便直接加副本的应用,主要是一些有状态应用
.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: example-vpa
namespace: default
spec:
targetRef: # 监控的target
apiVersion: "apps/v1"
kind: Deployment
name: example-deployment
updatePolicy:
updateMode: "Auto"
resourcePolicy:
containerPolicies: # vpa的资源调整是在容器级别上操作的,但是vpa的操作和决策(启动,更新,重启,扩缩容等)都是pod级别上的
- containerName: example-container
minAllowed: # 限制容器可以使用资源的最少值
cpu: 100m
memory: 100Mi
maxAllowed: # 限制容器可以使用资源的最大值
cpu: 1
memory: 1Gi
controlledResources: ["cpu", "memory"]关于VPA的minAllowed/maxAllowed和pod定义的limits/requests:
VPA不会更改limits,minAllowed/maxAllowed更多的是对VPA行为的指导,VPA会在minAllowed/maxAllowed的约束范围内给
requests
提出建议.如果VPA给出的requests低于pod定义的requests或高于limits,且VPA策略允许它这样做,那么VPA就会重启pod并应用它的建议.集群扩容(Cluster AutoScaler)
通过
k8s.gcr.io/cluster-autoscaler:v1.20.0
这个镜像,通过K8S-API
获取所需的信息,例如当前集群的资源使用情况和pod的调度需求(特别是因为资源不足而处于pending状态的pod),然后调用对应公有云平台的API(AWS,GCP等)或私有环境(openstack,vmware vsphere等)的API,实现节点的自动扩缩容.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
46
47
48
49
50
51
52
53
54
55
56
57apiVersion: apps/v1
kind: Deployment
metadata:
name: cluster-autoscaler
namespace: kube-system
labels:
app: cluster-autoscaler
spec:
replicas: 1
selector:
matchLabels:
app: cluster-autoscaler
template:
metadata:
labels:
app: cluster-autoscaler
spec:
containers:
- image: k8s.gcr.io/cluster-autoscaler:v1.20.0
name: cluster-autoscaler
resources:
limits:
cpu: 100m
memory: 300Mi
requests:
cpu: 100m
memory: 300Mi
command:
- ./cluster-autoscaler
- --v=4
- --stderrthreshold=info
- --cloud-provider=your-cloud-provider # aws/gcp/azure/external(自托管的集群)
- --nodes=min:max:NodeGroup1 # 每个--nodes标志对应一个节点组(node group).节点组是相同类型和配置的节点的集合.每个节点组都有最少和最大节点数以及节点组名
- --nodes=min:max:NodeGroup2 # 为了更好地控制和优化资源利用,可以针对不同的工作负载创建不同的节点组(比如一些资源占用较高的应用就分配到拥有大量cpu,内存资源的节点组种)
# 节点组的定义根据不同的平台来,比如aws就是auto scaling group,gcp就是instance group
- --namespace=kube-system
env:
- name: AWS_REGION
value: your-region # 对于 AWS,你需要设置区域
- name: ACCESS_KEY
valueFrom:
secretKeyRef:
key: accessKey
name: cloud-provider-credentials
- name: SECRET_KEY
valueFrom:
secretKeyRef:
key: secretKey
name: cloud-provider-credentials
volumeMounts:
- name: ssl-certs
mountPath: /etc/ssl/certs/ca-certificates.crt # 确保适应你的云提供商和操作系统
readOnly: true
volumes:
- name: ssl-certs
hostPath:
path: /etc/ssl/certs/ca-certificates.crt # 确保适应你的云提供商和操作系统
NetworkPolicy
有状态白名单,没有放行的流量就是拒绝所有,ACK必考,面试也被问过,需要CNI支持,比如calico,至少要记住关键的flag.
1 |
|
创建SA供别人访问
创建SA/role/rolebinding以及token
1 |
|
获取SA的访问令牌
1 |
|
用户配置
1 |
|
kubeconfig
就是~/.kube/config
文件,里面有两个重要参数:
client-certificate-data: 这个字段包含了编码后的客户端证书,它是由 Kubernetes 集群的 Certificate Authority (CA) 签发的,用于与 API 服务器通信时的客户端身份验证。这个证书表明客户端(用户或服务账户)的身份,并且在 TLS 握手过程中提供。(公钥)
client-key-data: 这个字段包含了编码后的客户端私钥。这个私钥用来与 client-certificate-data 字段中的公钥证书配对,确保通信的安全。私钥不应该共享或泄漏给其他人,因为它能证明客户端的身份。(私钥)
这两个字段用来设置特定用户与k8s API 服务器通信时使用的证书
定义集群信息
1 |
|
定义用户信息
1 |
|
用户使用证书登录,这里只说个大概流程:
创建证书签名请求(Certificate Signing Request, CSR):首先,需要在用户的机器上生成一个私钥(
client.key
),然后使用这个私钥创建一个 CSR。CSR 里包含了用户的信息,如常用名称(Common Name,即用户名),以及可能的组织单位(Organization Unit)等。提交CSR到Kubernetes集群:然后,将CSR提交给Kubernetes集群。在Kubernetes中,可以通过
kubectl
命令行工具或者API请求来完成这一步骤。由CA签署证书:集群的管理员需要批准CSR,由 Kubernetes 的 CA 处理请求并签发证书。
生成客户端证书(
client.crt
):经 CA 签名后的客户端证书会被传回给申请者。这份证书包含了用户的公钥以及CA的签名。在kubeconfig文件中引用证书和私钥:将签发的客户端证书及其对应的私钥的路径指定在 kubeconfig 文件的相应用户项中。
上下文
上下文是将用户和集群绑定在一起的设置.可以定义多个上下文,每个上下文都关联一个集群和一个用户,并可以指定一个默认的namespace
1 |
|
切换上下文
1 |
|
常用集群管理操作
怎么写yaml
1 |
|
RBAC
SA/role/RoleBinding都是
命名空间级别
的资源,所以操作它们时都要指定命名空间ClusterRole和ClusterRoleBingding是
集群级别
的资源,操作它们时不需要指定命名空间可以用RoleBinding绑定SA和ClusterRole,最终权限会限制在命名空间内
1 |
|
根据label查看资源
1 |
|
扩容deployment
1 |
|
pod的调度
调度主要通过label和taint来控制
1 |
|
关于taint的effect:
- NoSchedule: 如果一个pod没有明确通过
容忍声明
来容忍此污点,它将不会被调度到有此污点的node上- PreferNoSchedule: NoSchedule的软化版,k8s会尽量避免将pod调度到存在该污点的node上,不过如果没得选,也会调度过去
- NoExecute: 如果现有的pod没有容忍这个污点,则会被逐出node,新的pod没有容忍这个污点,则不会调度到该node上.主要用于需要驱逐节点pod的场景,比如节点维护,集群升级或策略改变.
1 |
|
SideCar
主要是某些日志收集的场景用得多,两个容器共享存储卷
1 |
|
PV和PVC
1 |
|
下面可以看出pv和pvc的关系.pv绑定具体的物理存储设备(本地,NFS,ceph等),PVC实际上是用户的存储请求,用户发起一个PVC,声明想请求多少容量的存储,k8s会根据请求绑定合适pv使用.
1 |
|
集群升级
升级kubeadm管理的集群: 官方文档
以1.28->1.29为例
在control plane上操作
1 |
|
kubeadm upgrade
这个命令会分析当前集群版本以及目标升级的版本(这里是1.29.0),验证升级计划.升级的同时也会对kubeadm管理的证书执行续约.
通过plan的输出,kubeadm主要负责升级:
- kube-apiserver
- kube-controller-manager
- kube-scheduler
- kube-proxy
- CoreDNS
- etcd (很多环境下,etcd是分开部署的,所以升级时可能需要跳过它)
1 |
|
看到以下输出说明升级成功
1 |
|
如果有多个控制平面节点,其他控制平面节点的升级命令有点不一样
1 |
|
然后升级kubelet,kubelet负责管控节点上pod的生命周期,所以需要先把节点上pod驱逐
出去,要一个一个节点
地操作(包括控制节点和工作节点)
1 |
|
某些情况下会驱逐失败:
- 没有使用controller控制的pod
- 使用了本地存储的pod(hostpath)
- 可以通过
--delete-emptydir-data --force
强制删除数据(注意安全)此时需要自行判断手动操作.
kubelet重启的影响: (chatgpt生成)
重启 kubelet 通常不会导致节点上运行的 Pod 被杀死或重新启动。不过,重启 kubelet 会暂时影响 Kubernetes 集群中控制平面与该节点的通信,包括调度器和控制器管理器。在 kubelet 重启并恢复正常运行之前,节点会被标记为 NotReady 状态。
以下是重启 kubelet 时可能发生的情况:
节点状态变化:当 kubelet 服务停止时,节点状态可能会在 Kubernetes API 中标记为
NotReady
。一旦 kubelet 重启并与 API 服务器重新建立连接,它会更新节点的状态,如果一切正常,节点状态将改回Ready
。Pod 状态信息丢失:由于重启 kubelet 期间本地的 pod 状态信息会丢失,因此当 kubelet 重启后,它需要重新同步现有 Pod 的状态信息。它将会查询容器运行时来确认现有 Pod 的运行情况,并将其反馈给 API 服务器。
工作负载调度:在 kubelet 不可用的期间,新的 Pods 将不会被调度到该节点上因为其标记为
NotReady
。如果 kubelet 的断开时间较长,集群可能开始 Pod 重新调度的过程,将 Pod 迁移到其他健康的节点上。服务中断最小化:通常情况下,重启 kubelet 对于正在节点上运行的 Pod 来说是无干扰的,因为容器是由 Docker 引擎或其他容器运行时独立管理的,并不直接依赖于 kubelet 的运行状态。
DaemonSet Pod:对于 DaemonSet 管理的 Pod,由于它们保证了在每一个节点上有一个运行的 Pod 副本,kubelet 的重启不会影响其状态,因为它们不会因为节点的
NotReady
状态而被驱逐。
ETCD备份恢复
etcd
是一个高可用的键值存储系统,用于配置共享和服务发现。在 Kubernetes 中,
etcd
存储了所有的 Kubernetes 对象的状态,比如 pods、services、configmaps、secrets 等。控制平面的组件,如 kube-apiserver、调度器和控制器管理器,都会使用 etcd 来存储和检索其所需要的状态信息。
1 |
|
生产中,etcd一般都是独立部署集群,有可能以systemd方式运行.备份方式一样,还原时有些不一样.
1 |
|