1. Labels和Selectors
1.1 标签(Labels)
配置文件配置:可以在 metadata.labels 中进行配置,示例如下:
metadata: # Pod 相关的元数据,用于描述 Pod 的数据
name: nginx-demo # Pod 的名称
labels: # 定义 Pod 的标签
type: app # 自定义label标签,名字为 type,值为 app
version: 1.0.0 # 自定义label标签,描述 Pod 版本号
namespace: 'default' # 命名空间的配置
kubectl 使用:
查看标签:
# 语法:kubectl get <资源类型> --show-labels
kubectl get po --show-labels
kubectl get nodes --show-labels
临时创建label:
# 语法:kubectl label po <资源名称> <标签名>=<值>
# 根据资源名称创建label
kubectl label po nginx-demo author=wuye
# 根据标签 author值为wuyea 筛选pod并批量创建label; -l 是label的选择器
kubectl label pods -l author=wuye date=0516
修改已经存在的标签:
# 语法:kubectl label po <资源名称> <标签名>=<值> --overwrite
kubectl label po nginx-demo author=wuyea --overwrite
1.2 选择器(Selectors)
配置文件:在各对象的配置 spec.selector 或其他可以写 selector 的属性中编写。
kubectl 使用:
# 匹配单个值,查找 author=wuyea 的 pod; -A 查询所有命令空间
kubectl get po -A -l author=wuyea
# 匹配多个值中的任意一个
kubectl get po -A -l 'version in (1.0.0, 1.1.0, 1.2.0)'
# 查找 version!=1 and author=wuyea 的 pod 信息
kubectl get po -l version!=1.1.0,author=wuyea
# 不等值 + 语句
kubectl get po -A -l 'version!=1.1.0,author in (wuyea, wuye)'
2. Deployment
Deployment是对无状态应用的部署及管理(如nginx)。
2.0 Deployment 配置文件详解:
### 注释内容可以删除掉,暂时忽略
apiVersion: apps/v1 # deployment api 版本
kind: Deployment # 资源类型为 deployment
metadata: # 元数据
#annotations:
# deployment.kubernetes.io/revision: "2"
#creationTimestamp: "2025-05-16T07:19:52Z"
#generation: 2
labels: # 标签
app: nginx-deploy # 具体的 key:value
name: nginx-deploy # deployment 的名字
namespace: default # 命名空间
#resourceVersion: "3624773"
#uid: a18ff5d6-3380-4e9f-8046-783307413c50
spec:
#progressDeadlineSeconds: 600
replicas: 1 # 期望副本数
revisionHistoryLimit: 10 # 进行滚动更新后,保留的历史版本数
selector: # 选择器,用于找到匹配的 RS
matchLabels: # 按照标签匹配
app: nginx-deploy
strategy: # 更新策略
rollingUpdate: # 滚动更新配置
maxSurge: 25% # 进行滚动更新时,更新的个数最多可以超过期望副本数的个数/比例(比如期望更新10个,在资源足够时最多更新12个)
maxUnavailable: 25% # 进行滚动更新时,最大不可用更新比例;表示在所有副本数中,最多可以有多少个不更新成功
type: RollingUpdate # 更新类型,采用滚动更新
template: # pod 模板
metadata: # pod 的元信息
#creationTimestamp: null
labels: # pod 标签
app: nginx-deploy
spec: # pod 期望信息
containers: # pod 的容器
- image: nginx:latest # 镜像
imagePullPolicy: IfNotPresent # 拉取策略
name: nginx # 容器名称
#resources: {}
#terminationMessagePath: /dev/termination-log
#terminationMessagePolicy: File
#dnsPolicy: ClusterFirst
restartPolicy: Always # 重启策略
#schedulerName: default-scheduler
#securityContext: {}
terminationGracePeriodSeconds: 30 # 删除操作最多宽限多长时间
2.1 创建Deployment
如何得到上面的配置文件?可以部署一个nginx示例,然后查看系统的配置即可,命令如下:
# 创建 deployment
kubectl create deploy nginx-deploy --image=nginx:latest
# 可以使用下面命令查看资源名称,通过名称也可以看出三者的关系:deployment包含replicaset,replicaset控制pod副本数
kubectl get deploy,rs,po
# 使用 -o yaml 查看默认的 deployment 配置
kubectl get deploy nginx-deploy -o yaml > nginx-deploy.yaml # 删除文件中的status块,即可得到上面的yaml文件
# 根据yaml文件创建deployment
kubectl create -f nginx-deploy.yaml
# 更新替换
kubectl replace -f deploy-nginx.yaml
# 查看标签
kubectl get deploy,rs,po --show-labels
2.2 滚动更新
只有修改了 deployment 配置文件中的 template 中的属性后,才会触发更新操作
# 修改 nginx 版本号
kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
# 或者通过 kubectl edit deployment/nginx-deployment 进行修改
# 查看滚动更新的过程
kubectl rollout status deploy <deployment_name>
# 查看部署描述,最后展示发生的事件列表也可以看到滚动更新过程
kubectl describe deploy <deployment_name>
# 获取部署信息,UP-TO-DATE 表示已经有多少副本达到了配置中要求的数目
kubectl get deployments
# 通过 kubectl get rs 可以看到增加了一个新的 rs
# 通过 kubectl get pods 可以看到所有 pod 关联的 rs 变成了新的
多个滚动更新并行:假设当前有 5 个 nginx:1.7.9 版本,你想将版本更新为 1.9.1,当更新成功第三个以后,你马上又将期望更新的版本改为 1.9.2,那么此时会立马删除之前的三个,并且立马开启更新 1.9.2 的任务
2.3 更新回滚
默认情况下,kubernetes会在系统中保存前两次的Deployment的rollout历史记录,以便你可以随时会退(你可以修改revision history limit来更改保存的revision数)。
案例:这里假设我更新nginx镜像版本为1.9.1,但是不小心输错为 1.91,此时就需要回滚。
kubectl set image deployment/nginx-deploy nginx=nginx:1.91 # 修改deploy的镜像版本
kubectl rollout history deployment nginx-deploy # 查看历史版本
kubectl rollout history deploy/nginx-deploy --revision=2 # 查看某个版本的信息,这里查看第2个版本
kubectl rollout undo deployment/nginx-deploy --to-revision=2 # 回滚到某个版本
2.4 扩容缩容
通过 kube scale 命令可以进行自动扩容/缩容,以及通过 kube edit 编辑 replcas 也可以实现扩容/缩容
扩容与缩容只是直接创建副本数,没有更新 pod template 因此不会创建新的 rs。
# 把 nginx-deploy 的副本数扩缩容到6个
kubectl scale deploy nginx-deploy --replicas=6
2.5 暂停恢复
由于每次对 pod template 中的信息发生修改后,都会触发更新 deployment 操作,那么此时如果频繁修改信息,就会产生多次更新,而实际上只需要执行最后一次更新即可,当出现此类情况时我们就可以暂停 deployment 的 rollout
通过 kubectl rollout pause deployment <name> 就可以实现暂停,直到你下次恢复后才会继续进行滚动更新。
kubectl rollout pause deploy nginx-deploy # 暂停更新
kubectl rollout resume deploy nginx-deploy # 恢复更新
3. StatefulSet
StatefulSet是对有状态应用的部署及管理(如MySQL)。
官方链接:https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/statefulset/
3.0 StatefulSet 配置文件详解
--- # 两个 --- 之间代表插入一块yaml内容
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet # StatefulSet 类型的资源
metadata:
name: web # StatefulSet 对象的名字
spec:
serviceName: "nginx" # 使用哪个service来管理dns
replicas: 2 # 副本数2个
selector:
matchLabels:
app: nginx # 必须匹配 .spec.template.metadata.labels
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
imagePullPolicy: IfNotPresent # 镜像拉取策略:只有当本地不存在时才会拉取
ports: # 容器内要暴漏的端口号
- containerPort: 80 # 具体暴漏的端口号
name: web # 该端口配置的名字
volumeMounts: # 加载数据卷
- name: www # 指定加载哪个数据卷
mountPath: /usr/share/nginx/html # 加载到容器中的哪个目录
volumeClaimTemplates: # 数据卷模板
- metadata: # 数据卷的描述
name: www # 数据卷的名称
annotations: # 数据卷的注解
volume.alpha.kubernetes.io/storage-class: anything
spec: # 数据卷的规约
accessModes: [ "ReadWriteOnce" ] # 访问模式
resources:
requests:
storage: 1Gi # 需要 1G 的存储资源
3.1 创建StatefulSet
# 创建StatefulSet
kubectl create -f web.yaml
# 查看 StatefulSet 状态
kubectl get sts # StatefulSet可以简写为sts
# 查看 service 状态
kubectl get svc
# 查看 挂载 状态
kubectl get pvc
# 查看 挂载 详情
kubectl describe pvc www-web-0
# 检查服务是否可用需要在另一个容器中,因为主机无法访问
kubectl run -it --image busybox dns-test --restart=Never --rm /bin/sh
# 进入容器内后执行命令:ping web-0.nginx
3.2 扩容缩容
# 扩缩容方法一:修改replicas数量即可实现扩缩容,简单直接。
kubectl scale statefulset web --replicas=5
# 方法二:通过patch打补丁的方式实现
kubectl patch statefulset web -p '{"spec":{"replicas":3}}'
3.3 镜像更新
# 镜像更新(目前还不支持直接更新 image,需要 patch 来间接实现)
kubectl patch sts web --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"nginx:1.9.1"}]'
更新方式有两种,分别是 RollingUpdate 和 OnDelete 。
RollingUpdate
StatefulSet 也可以采用滚动更新策略,同样是修改 pod template 属性后会触发更新,但是由于 pod 是有序的,在 StatefulSet 中更新时是基于 pod 的顺序倒序更新的。
基于 RollingUpdate 的特性,我们可以实现灰度发布(金丝雀发布)。
灰度发布:
灰度发布的目标:将项目上线后产生问题的影响尽量降到最低。
灰度发布的原理:利用滚动更新中的 partition 属性,可以实现简易的灰度发布的效果。
例如我们有 5 个 pod,如果当前 partition 设置为 3,那么此时滚动更新时,只会更新那些 序号 >= 3 的 pod。
利用该机制,我们可以通过控制 partition 的值,来决定只更新其中一部分 pod,确认没有问题后再主键增大更新的 pod 数量,最终实现全部 pod 更新。
OnDelete
只有在 pod 被删除时会进行更新操作。
3.4 删除
# 删除 StatefulSet 和 Headless Service
# 级联删除:删除 statefulset 时会同时删除 pods
kubectl delete statefulset web
# 非级联删除:删除 statefulset 时不会删除 pods,删除 sts 后,pods 就没人管了,此时再删除 pod 不会重建的
kubectl deelte sts web --cascade=false
# 删除 service
kubectl delete service nginx
4. DaemonSet
为每一个匹配的Node都部署一个守护进程。
官方链接:https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/daemonset/
4.1 DaemonSet 配置文件详解
apiVersion: apps/v1
kind: DaemonSet # 创建 DaemonSet 资源
metadata:
name: fluentd-elasticsearch # 名字
spec:
selector:
matchLabels:
name: fluentd-elasticsearch
template:
metadata:
labels:
name: fluentd-elasticsearch
spec:
nodeSelector: # 节点选择器,指定守护进程只能运行在label匹配的节点上
type: compute
containers:
- name: fluentd-elasticsearch
image: quay.io/fluentd_elasticsearch/fluentd:v5.0.1
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts: # 加载数据卷,避免数据丢失
- name: varlog # 数据卷名字
mountPath: /var/log # 将数据卷挂载到容器内的哪个目录
# it may be desirable to set a high priority class to ensure that a DaemonSet Pod
# preempts running Pods
# priorityClassName: important
terminationGracePeriodSeconds: 30
volumes: # 定义数据卷
- name: varlog # 定义的数据卷的名称
hostPath: # 数据卷类型,主机路径的模式,也就是与node共享目录
path: /var/log # node 中的共享目录
4.2 DaemonSet 常用命令
# 创建 DaemonSet
kubectl create -f fluentd-ds.yaml
# 查看 DaemonSet
kubectl get ds
# 查看节点标签
kubectl get nodes --show-labels
# 给c1节点增加标签 type=compute
kubectl label no c1 type=compute
5. HPA 自动扩/缩容
通过观察 pod 的 cpu、内存使用率或自定义 metrics 指标进行自动的扩容或缩容 pod 的数量。
通常用于 Deployment、StatefulSet,不适用于无法扩/缩容的对象,如 DaemonSet。
控制管理器每隔30s(可以通过–horizontal-pod-autoscaler-sync-period修改)查询metrics的资源使用情况。
5.1 开启指标服务
如果没有指标服务,当使用 kubectl top pods 命令时会提示 Metrics API not available。
使用 kubectl top pods 命令能看到pod的资源使用情况,所以需要安装指标服务。
下载 metrics-server 组件配置文件
wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml -O metrics-server-components.yaml修改镜像地址为国内的地址
# 检查:(自行修改,这是我当时的镜像代理) [root@head ~]# grep -n "image" metrics-server-components.yaml 142: image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/registry.k8s.io/metrics-server/metrics-server:v0.8.0 143: imagePullPolicy: IfNotPresent修改
metrics-server-components.yaml文件中容器的 tls 配置,不验证 tls,在 containers 的 args 参数中增加--kubelet-insecure-tls参数。spec: selector: matchLabels: k8s-app: metrics-server strategy: rollingUpdate: maxUnavailable: 0 template: metadata: labels: k8s-app: metrics-server spec: containers: - args: - --cert-dir=/tmp - --secure-port=10250 - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname - --kubelet-use-node-status-port - --metric-resolution=15s - --kubelet-insecure-tls # 增加了这一行 image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/registry.k8s.io/metrics-server/metrics-server:v0.8.0 # 修改成了代理镜像地址安装组件
kubectl apply -f metrics-server-components.yaml查看 pod 状态
kubectl get pods --all-namespaces | grep metrics # 如果pod没有运行,使用该命令查看原因 kubectl describe po metrics-server-98ddd7b5d-9wggn -n kube-system
5.2 cpu,内存指标监控
前提条件
要想实现 cpu 或内存的监控,首先有个前提条件是该对象必须配置了
resources.requests.cpu或resources.requests.memory才可以,可以配置当 cpu/memory 达到上述配置的百分比后进行扩容或缩容。示例:
spec: ...... template: metadata: creationTimestamp: null labels: app: nginx-deploy spec: containers: - image: nginx:latest imagePullPolicy: IfNotPresent name: nginx resources: # 必须配置资源请求 limits: cpu: 200m memory: 128Mi requests: # hpa看的是requests,不是limits! cpu: 100m memory: 128Mi创建一个 HPA
先准备一个好一个有做资源限制的 deployment,然后执行命令
kubectl autoscale deploy <deploy-name> --cpu-percent=20 --min=2 --max=5创建HPA。通过kubectl get hpa可以获取 HPA 信息。测试
找到对应服务的 service,编写循环测试脚本提升内存与 cpu 负载
while true; do wget -q -O- http://ip:port > /dev/null ; done可以通过多台机器执行上述命令,增加负载,当超过负载后可以查看 pods 的扩容情况
kubectl get pods。查看 pods 资源使用情况
kubectl top pods扩容测试完成后,再关闭循环执行的指令,让 cpu 占用率降下来,然后过 5 分钟后查看自动缩容情况。
5.3 自定义指标监控
- 控制管理器开启–horizontal-pod-autoscaler-use-rest-clients
- 控制管理器的–apiserver指向API Server Aggregator
- 在API Server Aggregator中注册自定义的metrics API
end 补充
StatefulSet与Deployment的对比
| 特性 | StatefulSet | Deployment |
|---|---|---|
| 数据持久化 | 为每个Pod提供独立的持久化存储卷 | 没有持久化存储,Pod删除时数据丢失 |
| 网络标识 | 每个Pod有稳定的网络标识(如DNS) | 没有固定的网络标识 |
| Pod管理 | 有序启动、终止,Pod编号固定 | 无序启动、终止 |
| 扩展方式 | 可以水平扩展,但需要更复杂的数据同步 | 简单的水平扩展 |
| 适用场景 | 有状态应用,如数据库、缓存系统等 | 无状态应用,如Web服务器、API等 |
总结
- 无状态应用:适用于无需持久化状态的应用,它们能在Kubernetes中实现灵活的扩展与调度,适用于处理单次请求的服务。
- 有状态应用:需要管理应用数据状态,并依赖持久化存储的应用,这类应用的实例通常需要特定的配置、顺序启动和稳定的存储和网络标识。Kubernetes通过StatefulSet来提供这些功能,确保数据一致性和可靠性。