目录
3.2.3为什么要有volumeClainTemplate?
3.2.4.1安装CoreDNS,仅二进制部署环境需要安装CoreDNS
[3.2.5.2创建 statefulset](#3.2.5.2创建 statefulset)
[3.2.5.3删除 statefulset](#3.2.5.3删除 statefulset)
一、Pod控制器及其功用
Pod控制器,又称之为工作负载(workload),是用于实现管理pod的中间层,确保pod资源符合预期的状态,pod的资源出现故障时,会尝试进行重启,当根据重启策略无效,则会重新新建pod的资源。
二、pod控制器有多种类型
2.1ReplicaSet
代用户创建指定数量的pod副本,确保pod副本数量符合预期状态,并且支持滚动式自动扩容和缩容功能。
2.1.1ReplicaSet主要三个组件组成
(1)用户期望的pod副本数量
(2)标签选择器,判断哪个pod归自己管理
(3)当现存的pod数量不足,会根据pod资源模板进行新建
帮助用户管理无状态的pod资源,精确反应用户定义的目标数量,但是RelicaSet不是直接使用的控制器,而是使用Deployment。
2.2Deployment
工作在ReplicaSet之上,用于管理无状态应用,目前来说最好的控制器。支持滚动更新和回滚功能,还提供声明式配置。 例如:搭建微服务
ReplicaSet 与Deployment 这两个资源对象逐步替换之前RC的作用。
(无状态的像nginx,有状态的像mysql(它每天都要写入数据、存数据,都会有变化,所以是有状态的))
2.3DaemonSet
用于确保集群中的每一个节点只运行特定的pod副本,通常用于实现系统级后台任务。
比如ELK服务
特性:服务是无状态的
服务必须是守护进程
2.4StatefulSet
管理有状态应用
2.5Job
只要完成就立即退出,不需要重启或重建
2.6Cronjob
周期性任务控制,不需要持续后台运行
三、Pod与控制器之间的关系
controllers:在集群上管理和运行容器的 pod 对象, pod 通过 label-selector 相关联。
Pod 通过控制器实现应用的运维,如伸缩,升级等。
3.1Deployment
- 部署无状态应用
- 管理Pod和ReplicaSet
- 具有上线部署、副本设定、滚动升级、回滚等功能
- 提供声明式更新,例如只更新一个新的image
- 应用场景:web服务(例如nginx、微服务)
官网示例:
下面是一个 Deployment 示例。其中创建了一个 ReplicaSet,负责启动三个 nginx
Pod:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
部署:
cd /opt/pod-kongzhiqi
kubectl create deployment nginx-deployment --image=nginx:1.15 --port=80 --replicas=2 --dry-run=client -oyaml > nginx-deployment.yaml
快速编写yaml文件
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-deployment
name: nginx-deployment
spec:
replicas: 2
selector:
matchLabels:
app: nginx-deployment
template:
metadata:
labels:
app: nginx-deployment
spec:
containers:
- image: nginx:1.15
name: nginx
ports:
- containerPort: 80
在示例中,Deployment使用了Nginx的Docker镜像nginx:1.15
如果想要更新这个镜像到新版本,只需修改YAML文件中的image
字段,然后重新应用配置即可。Kubernetes会自动处理更新过程。
Deployment配置文件解释:
- apiVersion: apps/v1:指定了Kubernetes API的版本。
- kind: Deployment:表明这是一个Deployment资源。
- metadata:包含了Deployment的名称和标签。
- spec:定义了Deployment的规格。
- replicas:设置期望的Pod副本数量为2。
- selector:使用matchLabels来选择具有相同标签的Pod。
- template:定义了Pod模板,包括Pod的元数据和规格。
- metadata:Pod的标签与Deployment的标签匹配。
- spec:定义了Pod的容器规格,包括容器名称、镜像和端口
kubectl get pods,deploy,rs
查看pod 的yaml格式配置
kubectl edit deployment/nginx-deployment
[root@master01 pod-kongzhiqi]#pwd
/opt/pod-kongzhiqi
[root@master01 pod-kongzhiqi]#kubectl edit deployment/nginx-deployment
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"labels":{"app":"nginx-deployment"},"name":"nginx-deployment","namespace":"default"},"spec":{"replicas":2,"selector":{"matchLabels":{"app":"nginx-deployment"}},"template":{"metadata":{"labels":{"app":"nginx-deployment"}},"spec":{"containers":[{"image":"nginx:1.15","name":"nginx","ports":[{"containerPort":80}]}]}}}}
creationTimestamp: "2024-05-30T07:57:41Z"
generation: 1
labels:
app: nginx-deployment #Deployment资源的标签
name: nginx-deployment
namespace: default
resourceVersion: "70320"
selfLink: /apis/apps/v1/namespaces/default/deployments/nginx-deployment
uid: 55353951-63cf-4566-aed3-1c1f73949770
spec:
progressDeadlineSeconds: 600
replicas: 2 #期望的pod数量,默认是1
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx-deployment
strategy:
rollingUpdate:
maxSurge: 25% #升级过程中会先启动的新Pod的数量不超过期望的Pod数量的25%,也可以是一个绝对值
maxUnavailable: 25% #升级过程中在新的Pod启动好后销毁的旧Pod的数量不超过期望的Pod数量的25%,也可以是一个绝对值
type: RollingUpdate #滚动升级
template:
metadata:
creationTimestamp: null
labels: #Pod副本关联的标签
app: nginx-deployment
spec:
containers:
- image: nginx:1.15 #镜像名称
imagePullPolicy: IfNotPresent #镜像拉取策略
name: nginx
ports:
- containerPort: 80 #容器暴露的监听端口
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always #容器重启策略
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
status:
availableReplicas: 2
conditions:
- lastTransitionTime: "2024-05-30T07:58:52Z"
lastUpdateTime: "2024-05-30T07:58:52Z"
message: Deployment has minimum availability.
reason: MinimumReplicasAvailable
status: "True"
type: Available
- lastTransitionTime: "2024-05-30T07:57:41Z"
lastUpdateTime: "2024-05-30T07:58:52Z"
message: ReplicaSet "nginx-deployment-6cc9594db" has successfully progressed.
reason: NewReplicaSetAvailable
status: "True"
type: Progressing
observedGeneration: 1
readyReplicas: 2
replicas: 2
updatedReplicas: 2
查看历史版本
kubectl rollout history deployment/nginx-deployment
3.2SatefulSet
- 部署有状态应用
- 稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现
- 稳定的网络标志, 即Pod重新调度后其PodName和HostName不变,基于Headless Service(即没有Cluster IP的Service)来实现
- 有序部署,有序扩展,即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次进行(即从0到N-1,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态),基于init containers来实现
- 有序收缩,有序删除(即从N-1到0) StatefulSet 也确保 Pod 是有序删除的,即从 N-1 到 0 的顺序。
- 常见的应用场景:数据库
官方文档https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/
StatefulSet | Kuberneteshttps://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/statefulset/
https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/
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
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx # has to match .spec.template.metadata.labels
serviceName: "nginx"
replicas: 3 # by default is 1
template:
metadata:
labels:
app: nginx # has to match .spec.selector.matchLabels
spec:
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: k8s.gcr.io/nginx-slim:0.8
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "my-storage-class"
resources:
requests:
storage: 1Gi
示例定义了一个 Headless Service 和一个 StatefulSet,用于部署一个名为 nginx 的应用。这个 StatefulSet 配置了 3 个副本,每个 Pod 都有一个名为 www 的 PVC,用于存储,并且使用了 nginx-slim 镜像。这个 StatefulSet 还设置了一个 Headless Service 来提供稳定的网络标识。
3.2.1StatefulSet三个组件
从上面的应用场景可以发现,StatefulSet由以下几个部分组成:
- Headless Service(无头服务):用于为Pod资源标识符生成可解析的DNS记录。
- volumeClaimTemplates(存储卷申请模板):基于静态或动态PV供给方式为Pod资源提供专有的固定存储。
- StatefulSet:用于管控Pod资源。
3.2.2为什么要有headless
在deployment中,每一个pod是没有名称,是随机字符串,是无序的。而statefulset中是要求有序的,每一个pod的名称必须是固定的。当节点挂了,重建之后的标识符是不变的,每一个节点的节点名称是不能改变的。pod名称是作为pod识别的唯一标识符,必须保证其标识符的稳定并且唯一。
为了实现标识符的稳定,这时候就需要一个headless service 解析直达到pod,还需要给pod配置一个唯一的名称。
3.2.3为什么要有volumeClainTemplate?
大部分有状态副本集都会用到持久存储,比如分布式系统来说,由于数据是不一样的,每个节点都需要自己专用的存储节点。而在 deployment中pod模板中创建的存储卷是一个共享的存储卷,多个pod使用同一个存储卷,而statefulset定义中的每一个pod都不能使用同一个存储卷,由此基于pod模板创建pod是不适应的,这就需要引入volumeClainTemplate,当在使用statefulset创建pod时,会自动生成一个PVC,从而请求绑定一个PV,从而有自己专用的存储卷。
服务发现:就是应用服务之间相互定位的过程。
应用场景:
- 动态性强:Pod会飘到别的node节点
- 更新发布频繁:互联网思维小步快跑,先实现再优化,老板永远是先上线再慢慢优化,先把idea变成产品挣到钱然后再慢慢一点一点优化
- 支持自动伸缩:一来大促,肯定是要扩容多个副本
K8S里服务发现的方式---DNS,使K8S集群能够自动关联Service资源的"名称"和"CLUSTER-IP",从而达到服务被集群自动发现的目的。
3.2.4实现K8S里DNS功能的插件:
- skyDNS:Kubernetes 1.3之前的版本
- kubeDNS:Kubernetes 1.3至Kubernetes 1.11
- CoreDNS:Kubernetes 1.11开始至今
3.2.4.1安装CoreDNS,仅二进制部署环境需要安装CoreDNS
方法一:
下载链接:https://github.com/kubernetes/kubernetes/blob/master/cluster/addons/dns/coredns/coredns.yaml.base #官方网站
vim transforms2sed.sed
s/__DNS__SERVER__/10.0.0.2/g
s/__DNS__DOMAIN__/cluster.local/g
s/__DNS__MEMORY__LIMIT__/170Mi/g
s/__MACHINE_GENERATED_WARNING__/Warning: This is a file generated from the base underscore template file: coredns.yaml.base/g
sed -f transforms2sed.sed coredns.yaml.base > coredns.yaml
方法二:上传 coredns.yaml 文件
kubectl create -f coredns.yaml
kubectl get pods -n kube-system
查看statefulset的定义:
kubectl explain statefulset
kubectl explain statefulset.spec
FIELDS:
- podManagementPolicy <string> #Pod管理策略
- replicas <integer> #副本数量
- revisionHistoryLimit <integer> #历史版本限制
- selector <Object> -required- #选择器,必选项
- serviceName <string> -required- #服务名称,必选项
- template <Object> -required- #模板,必选项
- updateStrategy <Object> #更新策略
- volumeClaimTemplates <[]Object> #存储卷申请模板,必选项
3.2.5部署
定义一个dns-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: dns-busybox
spec:
containers:
- name: busybox
image: busybox:1.28.4
args:
- /bin/sh
- -c
- sleep 36000
restartPolicy: Never
kubectl get svc
这边只是为了检测下
进入容器测试CoreDNS解析
接着部署:
apiVersion: v1
kind: Service
metadata:
name: sts-svc
namespace: default
labels:
app: sts-svc
spec:
type: ClusterIP
clusterIP: None
ports:
- port: 80
name: http
protocol: TCP
targetPort: 80
selector:
app: myapp-sts
使用 kubectl get svc
命令查看集群中的服务。可以看到 myapp-svc
服务的状态,它是一个无头服务,没有 ClusterIP。
3.2.5.1定义资源清单
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: myapp-sts
spec:
selector:
matchLabels:
app: myapp-sts # 必须匹配 .spec.template.metadata.labels
serviceName: "sts-svc"
replicas: 3 # 默认值是 1
template:
metadata:
labels:
app: myapp-sts # 必须匹配 .spec.selector.matchLabels
spec:
containers:
- name: myapp
image: soscscs/myapp:v1
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "nfs-client-storageclass"
resources:
requests:
storage: 1Gi
3.2.5.2创建 statefulset
kubectl get pv,pvc
解析上例:由于 StatefulSet 资源依赖于一个实现存在的 Headless 类型的 Service 资源,所以需要先定义一个名为 myapp-svc 的 Headless Service 资源,用于为关联到每个 Pod 资源创建 DNS 资源记录。接着定义了一个名为 myapp 的 StatefulSet 资源,它通过 Pod 模板创建了 3 个 Pod 资源副本,并基于 volumeClaimTemplates 向前面创建的PV进行了请求大小为1Gi 的专用存储卷。
stor01节点即nfs机器操作
创建pv
mkdir -p /data/volumes/v{1,2,3,4,5}
使用 mkdir
命令在 /data/volumes/
目录下创建五个新的目录(v1 到 v5)。这些目录将用作 NFS 共享的存储卷
配置 NFS 共享:
vim /etc/exports
/data/volumes/v1 192.168.246.0/24(rw,no_root_squash)
/data/volumes/v2 192.168.246.0/24(rw,no_root_squash)
/data/volumes/v3 192.168.246.0/24(rw,no_root_squash)
/data/volumes/v4 192.168.246.0/24(rw,no_root_squash)
/data/volumes/v5 192.168.246.0/24(rw,no_root_squash)
编辑 /etc/exports
文件,添加上述创建的目录作为共享资源。每个目录都配置了 IP 地址范围 192.168.246.0/24
,表示只有该子网内的客户端可以访问这些共享。rw
表示允许读写权限,no_root_squash
允许 root 用户以 root 权限访问共享。
重启 NFS 服务:
systemctl restart rpcbind
systemctl restart nfs
重新导出共享:
exportfs -arv
查看共享列表:
showmount -e
定义PV的yaml文件
pv-demo.yaml
文件包含了五个 PersistentVolume (PV) 的定义,这些 PV 将使用 NFS 服务器 stor01
上的共享目录。每个 PV 都有一个指定的容量和访问模式。
vim pv-demo.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv001
labels:
name: pv001
spec:
nfs:
path: /data/volumes/v1
server: stor01
accessModes: ["ReadWriteMany","ReadWriteOnce"]
capacity:
storage: 1Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv002
labels:
name: pv002
spec:
nfs:
path: /data/volumes/v2
server: stor01
accessModes: ["ReadWriteOnce"]
capacity:
storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv003
labels:
name: pv003
spec:
nfs:
path: /data/volumes/v3
server: stor01
accessModes: ["ReadWriteMany","ReadWriteOnce"]
capacity:
storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv004
labels:
name: pv004
spec:
nfs:
path: /data/volumes/v4
server: stor01
accessModes: ["ReadWriteMany","ReadWriteOnce"]
capacity:
storage: 4Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv005
labels:
name: pv005
spec:
nfs:
path: /data/volumes/v5
server: stor01 #可以是nfs机器的ip地址也可以是主机名,此处主机名,验证下
accessModes: ["ReadWriteMany","ReadWriteOnce"]
capacity:
storage: 5Gi
kubectl apply -f pv-demo.yaml
kubectl get pv
使用 kubectl get pv
命令查看集群中的 PV 列表,确认这些 PV 是否已成功创建。
这些 PV 定义使得 Kubernetes 集群能够使用 NFS 共享作为持久化存储。在 StatefulSet 或其他需要持久化存储的工作负载中,可以通过 PersistentVolumeClaim (PVC) 来请求这些 PV。这样,即使 Pod 在集群中重新调度,它们也能保持对这些共享存储的访问,这对于有状态的应用(如数据库)来说非常重要。
这边就接着上一篇博客搭建好,StorageClass + NFS之后继续使用了哦,如下图
访问测试
接下来dns解析下
由于是k8s内部解析方式,所以解析不了
编写yaml文件
apiVersion: v1
kind: Pod
metadata:
name: ceshi
spec:
containers:
- name: centos
image: centos:7
command:
- /bin/sh
- -c
- sleep 36000
nodeName: node01
3.2.5.3删除 statefulset
删除 (倒叙删除)
kubectl delete -f myapp-sts.yaml
当删除的时候是从myapp-sts-2开始进行删除的,关闭是逆向关闭
我们看到把数据库删除之后,再重新建,数据还是在的,名称对应数据库了,不管ip地址变不变,数据都在的
再重新创建,此时PVC依旧存在的,再重新创建pod时,依旧会重新去绑定原来的pvc
kubectl apply -f myapp-sts.yaml
kubectl get pod
kubectl exec -it ceshi sh
k8s内部的负载均衡 ,访问的时候会根据资源占比进行调度,会调度到资源少的,请求少的pod,不会负载均衡轮询的调度
K8S的内部负载均衡是根据资源的请求量,每次登入数据库所查看的数据不同,根据内部的不同调度,可能每次调度的节点都不同
3.2.5.4滚动更新
StatefulSet 控制器将在 StatefulSet 中删除并重新创建每个 Pod。它将以与 Pod 终止相同的顺序进行(从最大的序数到最小的序数),每次更新一个 Pod。在更新其前身之前,它将等待正在更新的 Pod 状态变成正在运行并就绪。如下操作的滚动更新是按照2-0的顺序更新
vim myapp-sts.yaml
在这个配置文件里修改成v2 其他不需要需改哦
#查看滚动更新的过程 (倒叙更新)
在创建的每一个Pod中,每一个pod自己的名称都是可以被解析的
查看一下podname,还有svc的name
解析
#从上面的解析,我们可以看到在容器当中可以通过对Pod的名称进行解析到ip。
其解析的域名格式如下:
(pod_name).(service_name).(namespace_name).svc.cluster.local
3.2.6查看命令
3.2.6.1查看创建的无头服务myapp-svc
kubectl get svc #查看创建的无头服务myapp-svc
3.2.6.2查看statefulset
kubectl get sts
3.2.6.3查看pvc绑定
kubectl get pvc
3.2.6.4查看pv绑定
kubectl get pv
3.2.6.5查看Pod信息
kubectl get pods
3.2.6statefulset的特点
- statefulset用于部署有状态的应用(有实时数据需要存储的应用)
- 部署statefulset之前,需要先创建一个headless service(表示clusterip为node的特殊service类型),statefulset的配置清单模板需要去指定servicename为headless service的名称。
- statefulset创建的pod名称是固定不变的,且唯一的
- statefulset的资源配置模板可以设置pvc模板,指定storageclassname字段值,可以引用storageclass资源,调用存储卷插件,动态创建pv
- statefulset管理的pod有滚动更新和扩容和缩容功能,扩容的时候为升序执行,滚动更新和缩容的时候为降序执行。
- statefulset管理的pod可以在k8s集群的pod中,基于headless service以及coredns实现对pod名称解析出podIP
如何在 Kubernetes 中对 StatefulSet 进行扩容和缩容操作
#扩展伸缩
kubectl scale sts myapp --replicas=4 #扩容副本增加到4个
kubectl get pods -w #动态查看扩容
kubectl get pv #查看pv绑定
kubectl patch sts myapp -p '{"spec":{"replicas":2}}' #打补丁方式缩容
kubectl get pods -w #动态查看缩容
3.3DaemonSet(工作负载)控制器
DaemonSet 确保全部(或者一些)Node 上运行一个 Pod 的副本。当有 Node 加入集群时,也会为他们新增一个 Pod 。当有 Node 从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。
使用 DaemonSet 的一些典型用法:
- 运行集群存储 daemon,例如在每个 Node 上运行 glusterd、ceph。
- 在每个 Node 上运行日志收集daemon,例如fluentd、logstash。
- 在每个 Node 上运行监控daemon,例如 Prometheus Node Exporter、collectd、Datadog 代理、New Relic 代理,或 Ganglia gmond。
应用场景:Agent
DaemonSet 是 Kubernetes 中的一种工作负载控制器,它确保在集群中的所有(或指定的)节点上运行一个 Pod 的副本。这使得DaemonSet 成为运行集群级服务的理想选择,如日志收集、监控代理、存储守护进程等。
官方案例(监控)
https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/
3.3.1关键特性
- 节点覆盖:DaemonSet 确保在集群中的每个节点上都有一个 Pod 副本运行,或者根据需要在特定节点上运行。
- 自动管理:当新节点加入集群时,DaemonSet 会自动在这些节点上创建 Pod。当节点被移除时,相应的 Pod 也会被清理。
- 删除行为:删除 DaemonSet 会删除它创建的所有 Pod,这有助于维护集群的整洁。
3.3.2典型用例
- 集群存储守护进程:在每个节点上运行如 GlusterFS 的 glusterd 或 Ceph 的守护进程,以提供分布式存储服务。
- 日志收集 :部署如 Fluentd、Logstash 等日志收集代理,以便在每个节点上收集日志并将其发送到中央日志存储。
- 监控代理:在每个节点上运行监控代理,如 Prometheus 的 Node Exporter、Collectd、Datadog 代理、New Relic 代理或 Ganglia 的 gmond,以收集节点的监控数据。
3.3.3应用场景
- Agent:DaemonSet 常用于部署代理或守护进程,这些代理或守护进程作为集群的"代理",执行特定的任务,如数据收集、服务代理等。
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: nginx-daemonset
labels:
app: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14
ports:
- containerPort: 80
我们看到DaemonSet会在每个node节点都创建一个Pod
3.4Job
- Job分为普通任务(Job)和定时任务(CronJob)
- 常用于运行那些仅需要执行一次的任务
- 应用场景 :数据库迁移、批处理脚本、kube-bench扫描、离线数据处理,视频解码等业务
https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/
3.4.1应用场景
- 数据库迁移:执行数据库迁移脚本,直到迁移成功。
- 批处理脚本:运行批处理作业,如数据备份、日志清理等。
- 安全扫描:使用 kube-bench 等工具对集群进行安全扫描。
- 离线数据处理:处理不需要持续运行的大量数据,如数据分析、报告生成等。
- 视频解码:执行视频转码等耗时的一次性任务
.spec.template.spec.restartPolicy该属性拥有三个候选值:OnFailure,Never和Always。默认值为Always。它主要用于描述Pod内容器的重启策略。在Job中只能将此属性设置为OnFailure或Never,否则Job将不间断运行。
.spec.backoffLimit用于设置job失败后进行重试的次数,默认值为6。默认情况下,除非Pod失败或容器异常退出,Job任务将不间断的重试,此时Job遵循 .spec.backoffLimit上述说明。一旦.spec.backoffLimit达到,作业将被标记为失败。
- 定义了一个名为 pi 的 Job,它将运行一个 Perl 容器来计算圆周率(π)。
- .spec.template.spec 定义了 Pod 的规格,包括容器的名称、镜像和执行的命令。
- restartPolicy: Never 表示 Pod 失败后不会重启。
- backoffLimit: 4 表示 Job 在失败后最多重试 4 次。
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
spec:
containers:
- name: pi
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
backoffLimit: 4
在所有node节点下载perl镜像,因为镜像比较大,所以建议提前下载好
使用
docker pull perl
命令提前拉取 Perl 镜像,以避免在 Job 执行时下载镜像导致延迟
docker pull perl
master 节点
使用 kubectl apply -f job.yaml
命令创建 Job。这将在集群中启动一个 Pod 来执行计算圆周率的任务。
kubectl apply -f job.yaml
kubectl get pods
使用 kubectl get pods
命令查看 Pod 的状态。您可以看到 Pod pi-mql4l
已经成功完成。
结果输出到控制台
kubectl logs pi-mql4l #结果输出到控制台
清除job资源
kubectl delete -f job.yaml
使用 kubectl delete -f job.yaml
命令删除 Job 和相关的 Pod 资源
设置 Job 的重试次数 (
job-limit.yaml
)backoffLimit
vim job-limit.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: busybox
spec:
template:
spec:
containers:
- name: busybox
image: busybox
imagePullPolicy: IfNotPresent
command: ["/bin/sh", "-c", "sleep 10;date;exit 1"]
restartPolicy: Never
backoffLimit: 2
创建一个新的 Job 配置文件,名为
busybox
,它将运行一个 BusyBox 容器,执行一个失败的命令(exit 1
)。
backoffLimit: 2
表示 Job 在失败后最多重试 2 次。
kubectl apply -f job-limit.yaml
kubectl get job,pods
kubectl describe job busybox
3.5CronJob
- 周期性任务,像Linux的Crontab一样。
- 周期性任务
- 应用场景:通知,备份
CronJob 是 Kubernetes 中处理周期性任务的强大工具,它使得自动化任务的创建和管理变得简单。通过定义 Cron 表达式,您可以轻松地安排任务在特定的时间执行,从而实现自动化运维。
官方文档链接
https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs/
3.5.1应用场景
-
通知系统:定期发送系统状态通知、日志报告或其他类型的定期通知。
-
数据备份:执行数据库备份、文件备份等周期性数据保护任务。
-
定期清理:清理日志文件、临时文件或其他不再需要的数据。
-
监控和报告:定期执行监控任务并生成报告。
3.5.2部署CronJob
如何在 Kubernetes 中创建一个 CronJob,该 CronJob 每分钟执行一次打印 "Hello" 的任务。
示例:每分钟打印hello
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
imagePullPolicy: IfNotPresent
args:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure
- apiVersion: 指定 Kubernetes API 的版本。
- kind: 指定资源类型为 CronJob。
- metadata: 包含 CronJob 的名称。
- spec: 包含 CronJob 的规格。
- schedule: 使用 Cron 表达式定义任务的执行时间表。在这个例子中,"*/1 * * * *" 表示每分钟执行一次。
- jobTemplate: 定义了 Job 模板,它包含了执行任务的 Pod 规格。
- containers: 定义了容器的名称、镜像和其他参数。
- args: 执行的命令,这里使用 /bin/sh 打印当前日期和 "Hello" 消息。
- restartPolicy: 设置为 OnFailure,表示只在容器失败时重启。
kubectl apply -f cronjob.yaml
kubectl get cronjob
使用 kubectl get cronjob
命令查看 CronJob 的状态,包括调度时间、活动状态和最近一次执行的时间。
查看执行的 Pod:
使用
kubectl get pods
命令查看由 CronJob 创建的 Pod。这些 Pod 通常会在任务完成后标记为Completed
。
kubectl get pods
使用 kubectl logs
命令查看特定 Pod 的日志输出。可以进入其中一个pod,可以看到打印的日期和 "Hello" 消息。
报错解决
#如果报错:Error from server (Forbidden): Forbidden (user=system:anonymous, verb=get, resource=nodes, subresource=proxy) ( pods/log hello-1621587780-c7v54)
#解决办法:绑定一个cluster-admin的权限
kubectl create clusterrolebinding system:anonymous --clusterrole=cluster-admin --user=system:anonymous
如果在查看日志时遇到权限问题,可以通过创建一个 clusterrolebinding 来授予 system:anonymous 用户 cluster-admin 权限。这通常不推荐,因为它会降低集群的安全性。在生产环境中,应该使用更细粒度的权限控制。
通过这些步骤,可以在 Kubernetes 中设置周期性任务,例如定期备份、日志清理或发送通知。CronJob 提供了一种简单的方式来自动化这些重复性任务。
3.5.3cronjob其它可用参数的配置
cronjob其它可用参数的配置
spec:
concurrencyPolicy: Allow #要保留的失败的完成作业数(默认为1)
schedule: '*/1 * * * *' #作业时间表。在此示例中,作业将每分钟运行一次
startingDeadlineSeconds: 15 #pod必须在规定时间后的15秒内开始执行,若超过该时间未执行,则任务将不运行,且标记失败
successfulJobsHistoryLimit: 3 #要保留的成功完成的作业数(默认为3)
terminationGracePeriodSeconds: 30 #job存活时间 默认不设置为永久
jobTemplate: #作业模板。这类似于工作示例
四、温故而知新
无状态:
1)deployment 认为所有的pod都是一样的
2)不用考虑顺序的要求
3)不用考虑在哪个node节点上运行
4)可以随意扩容和缩容
有状态
1)实例之间有差别,每个实例都有自己的独特性,元数据不同,例如etcd,zookeeper
2)实例之间不对等的关系,以及依靠外部存储的应用。
常规service和无头服务区别
service:一组Pod访问策略,提供cluster-IP群集之间通讯,还提供负载均衡和服务发现。
Headless service:无头服务,不需要cluster-IP,而是直接以DNS记录的方式解析出被代理Pod的IP地址。
deployment
部署无状态应用的管理RS 和 pod 创建Pod ,主要是维护pod副本数量与期望状态相同
创建和删除pod时并行执行、升级时是先创建一部分,再删除一部分
SatefulSet部署有状态的应用,每个pod的唯一(名称)且不变的, 每个pod拥有自己专属的持久化的存储(Pvc和PV)
在k8s集群内部可以通过
(pod name).{service name). (namespace).svc.cluster.local 解析出pod的IP(基于headless service 和coreDNS)
创建和删除pod是有顺序的(串行执行的),升级时串行执行的,会删除旧的pod,再创建新pod删除和升级时逆序执行的(先从标识符最大的n-2开始,一直到最小的0)
Daemonset理论上在k8s集群的所有node节点上创建相同的pod(无论node节点什么时候加入到k8s集群),但是会受到node节点上污点影响
job部署一次性任务的pod,正常完成后容器立即退出并且不重启容器(restartpolicy不设置Always),也不会重建异常,完成后重试任务重建次数根据backofflimit 配置指定(默认为6次)
cronjob周期性的部署任务的pod,正常完成后容器会立即退出并不会重启容器(restartPolicy 不设置Always),也不会重建pod,schedule 配置周期性的事件表* * * * *(分时日月周)