当前位置: 首页 > news >正文

【Kubernetes基础--Pod深入理解2】--查阅笔记3

目录

  • Pod 生命周期和重启策略
  • Pod 的调度
    • Deployment或RC:自动调度
    • DaemonSet:在每个 Node 上都调度一个 Pod
    • Job:批处理调度
    • Cronjob:定时任务
  • Init Container(初始化容器)
  • Pod 的升级和回滚
    • Deployment 的升级
    • Deployment 的回滚
    • 暂停和恢复 Deployment 的部署操作,来完成复杂的修改
  • Pod的扩缩容
    • 手动扩缩容
    • 自动扩缩容机制
      • HPA的工作原理
      • 指标的类型
      • HPA 配置

Pod 生命周期和重启策略

Pod 的状态:

  • Pending:API Server 已创建该 Pod,但 Pod 内还有一个或多个容器的镜像没有创建,包括正在下载镜像的过程
  • Running:Pod 内所有容器均已创建,且至少有一个容器处于运行、正在启动或正在重启状态
  • Succeeded:Pod 内所有容器均成功执行后退出,且不会再重启
  • Failed:所有容器均已退出,但至少有一个容器退出为失败状态
  • Unknown:无法获取该 Pod 的状态,可能由于网络原因

Pod 的重启策略(RestartPolicy)应用于 Pod 内的所有容器,并且仅在 Pod 所处的 Node 上由 kubelet 进行判断和重启操作。当某个容器异常退出或者健康检查失败时,kubelet 将根据 RestartPolicy 的设置来进行相应的操作

Pod的重启策略包括Always、OnFailure和Never,默认值为Always。

  • Always:当容器失效时,由 kubelet 自动重启该容器
  • OnFailure:当容器终止运行且退出码不为0时,由kubelet自动重启该容器
  • Never:不论容器运行状态如何,kubelet都不会重启该容器

Pod 的重启策略与控制方式息息相关,当前可用于管理 Pod 的控制器包括 ReplicationController、Job、DaemonSet 及直接通过 kubelet 管理(静态Pod)​。每种控制器对 Pod 的重启策略要求:

  • RC 和 DaemonSet:必须设置为Always,需要保证该容器持续运行
  • Job:OnFailure 或 Never,确保容器执行完成后不再重启
  • kubelet:在 Pod 失效时自动重启它,不论将RestartPolicy设置为什么值,也不会对Pod进行健康检查

Pod 的调度

k8s 一般很少直接创建一个 Pod,多数情况下会通过 RC、Deployment、DaemonSet、Job 等控制器完成对一组 Pod 副本的创建、调度及全生命周期的自动控制任务。

Deployment或RC:自动调度

Deployment 或 RC 可以自动部署一个容器应用的多分副本,可以持续监控副本的数量。

示例:使用 Deployment 配置文件 nginx-deployment.yaml 创建一个 ReplicaSet,会创建3个 Nginx 应用的 Pod:

apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-deployment
spec:replicas: 3 # 3个副本template:metadata:labels:app: nginxspec:containers:- name: nginximage: nginx:1.7.9ports:- containerPort: 80

创建并查看:

kubectl create -f nginx-deployment.yamlkubectl get depliments # 创建好所有3个副本,并且所有副本都是最新的可用的kubectl get rs  # 已创建的ReplicaSet(RS)kubectl get pods # 已创建的Pod的信息

这3个 Nginx Pod 由系统全自动完成调度。它们各自最终运行在哪个节点上,完全由 Master 的 Scheduler 经过一系列算法计算得出,用户无法干预调度过程和结果。

除了系统自动调度算法,k8s 也提供了多种丰富的调度策略,只需在 Pod 的定义中使用 NodeSelector、NodeAffinity、PodAffinity、Pod 驱逐等更加细粒度的调度策略设置,就能完成对 Pod 的精准调度。

DaemonSet:在每个 Node 上都调度一个 Pod

DaemonSet 是 k8s 1.2版本新增的一个资源对象,用于管理在集群中每个 Node 上只运行一份 Pod 的副本实例。

应用场景:

  • 每个 Node 上都运行一个 GlusterFS 存储或者 Ceph 存储的 Daemon 进程
  • 每个 Node 上都运行一个日志采集程序,如 Fluentd 或 Logstach
  • 每个 Node 上都运行一个性能监控程序,采集该 Node 的运行性能数据,例如 Prometheus Node Exporter、collectd、New Relic agent 或者 Ganglia gmond 等

示例:定义为在每个 Node 上都启动一个 fluentd 容器,配置文件 fluentd-ds.yaml,其中挂载了物理机的两个目录 “/var/log” 和“/var/lib/docker/containers”​:

apiVersion: apps/v1
kind: DaemonSet
metadata:name: fluentd-cloud-loggingnamespace: kube-systemlabels:k8s-app: fluentd-cloud-logging
spec:template:metadata:namespace: kube-systemlabels:k8s-app: fluentd-cloud-loggingspec:containers:- name: fluentd-cloud-loggingimage: fluentd-elasticsearch:1.17resources:limits:cpu: 100mmemory: 200Mienv:- name: FLUENTD_ARGSvalue: -qvolumeMounts:- name: varlogmountPath: /var/logreadOnly: false- name: containersmountPath: /var/lib/docker/containersreadOnly: falsevolumes:- name: containershostPath:path: /var/lib/docker/containers- name: varloghostPath:path: /var/logupdateStrategy:   # 1.6版本 滚动升级 默认设置;另外一个值是OnDelete,即只有手工删除了DaemonSet创建的Pod副本,新的Pod副本才会被创建出来type: RollongUpdate

创建并查看:

kubectl create -f fluentd-ds.yamlkubectl get daemonset --namespace=kube-system
kubectl get pods --namespace=kube-system

Job:批处理调度

k8s 从1.2版本开始支持批处理类型的应用,我们可以通过 k8s Job 资源对象来定义并启动一个批处理任务。批处理任务通常并行(或者串行)启动多个计算进程去处理一批工作项(work item)​,处理完成后,整个批处理任务结束。按照批处理任务实现方式的不同,有以下几种模式:

  • Job Template Expansion 模式:一个 Job 对象对应一个待处理的 Work item,有几个 Work item 就产生几个独立的 Job,通常适合 Work item 数量少、每个 Work item 要处理的数据量比较大的场景,比如有一个100GB 的文件作为一个 Work item,总共有10个文件需要处理
  • Queue with Pod Per Work Item 模式:采用一个任务队列存放 Work item,一个 Job 对象作为消费者去完成这些 Work item,在这种模式下,Job 会启动 N 个 Pod,每个 Pod 都对应一个Work item
  • Queue with Variable Pod Count 模式:也是采用一个任务队列存放 Work item,一个 Job 对象作为消费者去完成这些 Work item,但与上面的模式不同,Job 启动的 Pod 数量是可变的
  • Single Job with Static Work Assignment 模式:一个Job产生多个Pod,采用程序静态方式分配任务项,而不是采用队列模式进行动态分配

Job 的类型:

  1. Non-parallel Jobs
    通常一个 Job 只启动一个 Pod,除非 Pod 异常,才会重启该 Pod,一旦此 Pod 正常结束,Job将结束

  2. Parallel Jobs with a fixed completion count
    并行 Job 会启动多个 Pod,此时需要设定 Job 的.spec.completions 参数为一个正数,当正常结束的 Pod 数量达至此参数设定的值后,Job结束。此外,Job 的.spec.parallelism 参数用来控制并行度,即同时启动几个 Job 来处理 Work Item

  3. Parallel Jobs with a work queue
    任务队列方式的并行 Job 需要一个独立的 Queue,Work item 都在一个 Queue 中存放,不能设置 Job 的.spec.completions 参数,此时 Job有以下特性:

    • 每个 Pod 都能独立判断和决定是否还有任务项需要处理
    • 如果某个 Pod 正常结束,则 Job 不会再启动新的 Pod
    • 如果一个 Pod 成功结束,则此时应该不存在其他 Pod 还在工作的情况,它们应该都处于即将结束、退出的状态
    • 如果所有 Pod 都结束了,且至少有一个 Pod 成功结束,则整个 Job 成功结束

Cronjob:定时任务

k8s 1.5版本开始增加了一种新类型的 Job,即类似 Linux Cron 的定时任务 Cron Job。确保版本是1.8以上。

# 定时表达式
Minutes Hours DayofMonth Month DayofWeek Year

其中每个域都可出现的字符:

  • Minutes:可出现“,”​“-”​“*”​“/”这4个字符,有效范围为0~59的整数
  • Hours:可出现“,”​“-”​“*”​“/”这4个字符,有效范围为0~23的整数
  • DayofMonth:可出现“,”​“-”​“*”​“/”​“?”​“L”​“W”​“C”这8个字符,有效范围为0~31的整数
  • Month:可出现“,”​“-”​“*”​“/”这4个字符,有效范围为1~12的整数或JAN~DEC
  • DayofWeek:可出现“,”​“-”​“*”​“/”​“?”​“L”​“C”​“#”这8个字符,有效范围为1~7的整数或SUN~SAT。1表示星期天,2表示星期一,以此类推。

表达式中的特殊字符“*”与“/”的含义:

  • :表示匹配该域的任意值,假如在 Minutes 域使用 “”​,则表示每分钟都会触发事件
  • /:表示从起始时间开始触发,然后每隔固定时间触发一次,例如在 Minutes 域设置为 5/20,则意味着第1次触发在第 5min 时,接下来每20min 触发一次,将在第 25min、第 45min 等时刻分别触发。

示例:cron.yaml 配置文件,定义了一个名为 hello 的Cron Job,任务每隔1min执行一次,运行的镜像是 busybox,执行的命令是 Shell 脚本,脚本执行时会在控制台输出当前时间和字符串 “ Hello from the Kubernetes cluster”​。

apiVersion: batch/v1
kind: CronJob
metadata:name: hello
spec:schedule: "*/1 * * * *"jobTemplate:spec:template:spec:containers:- name: helloimage: busyboxargs:- /bin/sh- -c- date; echo Hello from the Kubernetes clusterrestartPolicy: OnFailure
kubectl create -f cron.yaml  # cronjob "hello" created
kubectl delete cronjob hello  # cronjob "hello" deletedkubectl get cronjob hello
# 直观地了解Cron Job定期触发任务执行的历史和现状:
kubectl get jobs --watch
# 查询某个Pod          
kubectl get pods --show-all | grep hello-1498761060 
# 查询 Pod 日志
kubectl logs hello-1498761060-shpwx

Init Container(初始化容器)

很多应用场景中,应用在启动之前都需要进行初始化操作,比如:

  • 等待其他关联组件正确运行(例如数据库或某个后台服务)
  • 基于环境变量或配置模板生成配置文件
  • 从远程数据库获取本地所需配置,或者将自身注册到某个中央数据库中
  • 下载相关依赖包,或者对系统进行一些预配置操作

init container 与应用容器在本质上是一样的,但它们是仅运行一次就结束的任务,并且必须在成功执行完成后,系统才能继续执行下一个容器。根据 Pod 的重启策略(RestartPolicy)​,当 init container 执行失败,而且设置了 RestartPolicy=Never 时,Pod 将会启动失败;而设置 RestartPolicy=Always 时,Pod 将会被系统自动重启

示例:以 Nginx 应用为例,在启动 Nginx 之前,通过初始化容器 busybox 为 Nginx 创建一个 index.html 主页文件。这里为 init container 和Nginx 设置了一个共享的 Volume,以供 Nginx 访问 init container 设置的 index.html 文件:

# nginx-init-containers.yamlapiVersion: v1
kind: Pod
metadata:name: nginxannotation:
spec:
initContainers:
- name: installimage: busyboxcommand:- wget- "-O"- "/work-dir/index.html"- http:k8s.iovolumeMounts:- name: workdirmountPath: "/work-dir"
containers:
- name: nginximage: nginxports:- containerPort: 80volumeMounts:- name: workdirmountPath: /usr/share/nginx/html
dnsPolicy: Default
volumes:
- name: workdiremptyDir: {}

Pod 的升级和回滚

当集群中的某个服务需要升级时,我们需要停止目前与该服务相关的所有 Pod,然后下载新版本镜像并创建新的 Pod。
如果集群规模比较大,而且先全部停止然后逐步升级的方式会导致较长时间的服务不可用。k8s 提供了滚动升级功能来解决上述问题。

Deployment 的升级

示例:

# nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-deployment
spec:replicas: 3template:metadata:labels:app: nginxspec:containers:- name: nginximage: nginx:1.7.9ports:- containerPort: 80

现在 Pod 镜像需要被更新为 Nginx:1.9.1,我们可以通过 kubectl set image 命令为 Deployment 设置新的镜像名称:

kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
# deployment "nginx-deployment" image updated

另一种更新的方法是使用 kubectl edit命令 修改 Deployment 的配置,将 spec.template.spec.containers[0].image 从 Nginx:1.7.9 更改为Nginx:1.9.1:

kubectl edit deployment/nginx-deployment
# deployment "nginx-deployment" edited

一旦镜像名(或Pod定义)发生了修改,则将触发系统完成 Deployment 所有运行 Pod 的滚动升级操作。可以使用 kubectl rollout status 命令查看 Deployment 的更新过程:

kubectl rollout status deployment/nginx-deployment
# Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
# Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
# Waiting for rollout to finish: 1 old replicas are pending termination...
# Waiting for rollout to finish: 1 old replicas are pending termination...
# Waiting for rollout to finish: 2 of 3 updated replicas are available...
# deployment "nginx-deployment" successfully rolled outkubectl get podskubectl describe pod/nginx-deployment-xxx

Deployment 的回滚

有时可能因为新版本不稳定,我们需要将 Deployment 回滚到旧版本。默认情况下,所有 Deployment 的发布历史记录都被保留在系统中,便于随时进行回滚。

用 kubectl rollout history 命令检查这个 Deployment 部署的历史记录,如果需要查看特定版本的详细信息,则可以加上–revision=参数:

kubectl rollout history deployment/nginx-deployment
#  deployments "nginx-deployment"
# REVISION        CHANGE-CAUSE
# 1               kubectl create --filename=nginx-deployment.yaml --record=true
# 2               kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
# 3               kubectl set image deployment/nginx-deployment nginx=nginx:1.91kubectl rollout history deployment/nginx-deployment --revision=3
deployments "nginx-deployment" with revision #3
Pod Template:Labels:       app=nginxpod-template-hash=3660254150Annotations:  kubernetes.io/change-cause=kubectl set image deployment/nginx-deployment nginx=nginx:1.91Containers:nginx:Image:      nginx:1.91Port:       80/TCPEnvironment:        <none>Mounts:     <none>Volumes:      <none>

撤销本次发布并回滚到上一个部署版本;也可以使用 --to-revision 参数指定回滚到的部署版本号:

kubectl rollout undo deployment/nginx-deployment
# deployment "nginx-deployment" rolled back
kubectl rollout undo deployment/nginx-deployment --to-revision=2
# deployment "nginx-deployment" rolled back

暂停和恢复 Deployment 的部署操作,来完成复杂的修改

对于一次复杂的 Deployment 配置修改,为了避免频繁触发 Deployment 的更新操作,可以先暂停 Deployment 的更新操作,然后进行配置修改,再恢复 Deployment,一次性触发完整的更新操作,就可以避免不必要的 Deployment 更新操作了。

以 Nginx 为例:

kubectl get deployments
# kubectl rollout pause命令暂停Deployment的更新操作
kubectl rollout pause deployment/nginx-deployment
# 修改镜像 deployment "nginx-deployment" image updated
kubectl set image deploy/nginx-deployment nginx=nginx:1.9.1
# 查看 Deployment 的历史记录,发现并没有触发新的 Deployment 部署操作
kubectl rollout history deploy/nginx-deployment
# deployments "nginx-deployment"
# REVISION        CHANGE-CAUSE
# 1               kubectl create --filename=nginx-deployment.yaml --record=true      # 再次更新容器的资源限制:deployment "nginx-deployment" resource requirements updated
kubectl set resourcesdeployment nginx-deployment -c=nginx --limits=cpu=200m,memory=512Mi
# 恢复这个Deployment的部署操作:deployment "nginx-deployment" resumed       
kubectl rollout resume deploy nginx-deployment
# 新的ReplicaSet被创建出来了:    
kubectl get rs
# NAME                          DESIRED   CURRENT   READY     AGE
# nginx-deployment-3133440882   3         3         3         6s
# nginx-deployment-4234284026   0         0         0         49s     # 查看Deployment的事件信息,可以看到Deployment完成了更新:
kubectl describe deployment/nginx-deployment

注意,在恢复暂停的Deployment之前,无法回滚该Deployment。

Pod的扩缩容

利用 Deployment/RC 的 Scale 机制来完成服务的扩缩容。

k8s 对 Pod 的扩缩容操作提供了手动和自动两种模式,手动模式通过执行 kubectl scale 命令或通过 RESTfulAPI 对一个 Deployment/RC 进行 Pod 副本数量的设置,即可一键完成。自动模式则需要用户根据某个性能指标或者自定义业务指标,并指定Pod副本数量的范围,系统将自动在这个范围内根据性能指标的变化进行调整。

手动扩缩容

还是以上面的 Nginx 为例,通过 kubectl scale 命令可以将 Pod 副本数量从初始的3个更新为5个:

kubectl scale deployment nginx-deployment --replicas 5
# deployment "nginx-deployment" scaled
kubectl get pods

将 --replicas 设置为比当前 Pod 副本数量更小的数字,系统将会“杀掉”一些运行中的 Pod,以实现应用集群缩容:

kubectl scale deployment nginx-deployment --replicas=1
# deployment "nginx-deployment" scaled
kubectl get pods

自动扩缩容机制

k8s 1.1版本开始,Horizontal Pod Autoscaler(HPA)的控制器,用于实现基于 CPU 使用率进行自动 Pod 扩缩容的功能。HPA 控制器基于 Master 的 kube-controller-manager 服务启动参数 --horizontal-pod-autoscaler-sync-period 定义的探测周期(默认值为15s)​,周期性地监测目标 Pod 的资源性能指标,并与 HPA 资源对象中的扩缩容条件进行对比,在满足条件时对 Pod 副本数量进行调整。

HPA的工作原理

k8s 中的某个 Metrics Server(Heapster 或自定义 Metrics Server)持续采集所有 Pod 副本的指标数据。HPA 控制器通过 Metrics Server 的API(Heapster 的 API 或聚合 API)获取这些数据,基于用户定义的扩缩容规则进行计算,得到目标 Pod 副本数量。当目标 Pod 副本数量与当前副本数量不同时,HPA控制器就向 Pod 的副本控制器(Deployment、RC或ReplicaSet)发起 scale 操作,调整 Pod 的副本数量,完成扩缩容操作。

指标的类型

Master 的 kube-controller-manager 服务持续监测目标 Pod 的某种性能指标,以计算是否需要调整副本数量。目前 k8s 支持的指标类型:

  • Pod 资源使用率:Pod 级别的性能指标,通常是一个比率值,例如 CPU 使用率
  • Pod 自定义指标:Pod 级别的性能指标,通常是一个数值,例如接收的请求数量
  • Object 自定义指标或外部自定义指标:通常是一个数值,需要容器应用以某种方式提供,例如通过 HTTPURL“/metrics” 提供,或者使用外部服务提供的指标采集 URL

HPA 配置

HPA 资源对象处于 k8s 的 API 组 “autoscaling” 中,目前包括 v1 和 v2 两个版本。其中 autoscaling/v1 仅支持基于 CPU 使用率的自动扩缩容,autoscaling/v2 则用于支持基于任意指标的自动扩缩容配置,包括基于资源使用率、Pod 指标、其他指标等类型的指标数据,当前版本为 autoscaling/v2beta2。

  1. 基于 autoscaling/v1 版本的 HPA 配置,仅可以设置 CPU 使用率:
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:name: php-apache
spec:scaleTargetRef:apiVersion: apps/v1kind: Deploymentname: php-apacheminReplicas: 1maxReplicas: 10targetCPUUtilizationPercentage: 50

主要参数:

  • scaleTargetRef :目标作用对象,可以是Deployment 、 ReplicationController或ReplicaSet
  • targetCPUUtilizationPercentage:期望每个Pod的CPU使用率都为50%,该使用率基于Pod设置的CPU Request值进行计算,例如该值为200m,那么系统将维持Pod的实际CPU使用值为100m
  • minReplicas和maxReplicas:Pod副本数量的最小值和最大值,系统将在这个范围内进行自动扩缩容操作,并维持每个Pod的CPU使用率为50%
  1. 基于 autoscaling/v2beta2 的 HorizontalPodAutoscaler 配置:
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:name: php-apache
spec:scaleTargetRef:apiVersion: apps/v1kind: Deploymentname: php-apacheminReplicas: 1maxReplicas: 10metrics:- type: Resourceresource:name: cputarget:type: UtilizationaverageUtilization: 50

主要参数:

  • scaleTargetRef :目标作用对象,可以是 Deployment 、 ReplicationController 或 ReplicaSet
  • minReplicas和maxReplicas:Pod 副本数量的最小值和最大值,系统将在这个范围内进行自动扩缩容操作,并维持每个Pod的CPU使用率为50%
  • metrics:目标指标值。在 metrics 中通过参数type定义指标的类型;通过参数 target 定义相应的指标目标值,系统将在指标数据达到目标值时触发扩缩容操作

相关文章:

  • JavaScript事件循环
  • Qt实现文件传输客户端(图文详解+代码详细注释)
  • WPF 图标原地旋转
  • 4.16学习总结 IO流综合练习
  • 新闻业务--草稿箱
  • 坚持每日Codeforces三题挑战:Day 3 - 题目详解(2024-04-16,难度:900, 1200, 1200)
  • 库洛游戏一面+二面
  • C#中同步任务和异步任务
  • 【计算机网络】3数据链路层①
  • Mathematica 中,将含有小数的表达式转换为整数或分数形式
  • springboot异步线程事务丢失
  • MAC-​​基于 Spring 框架的高并发批量任务处理方案​
  • 【AI】SpringAI 第二弹:接入 DeepSeek 官方服务
  • Spring Boot系列之使用Arthas Tunnel Server 进行远程调试实践
  • CTF--好像需要管理员
  • gemini讲USRP
  • 【Java】时间区间内按天、周、月份索引后缀计算方法
  • 通过金融科技(Fintech)掌控财务:智能理财管理指南
  • Design Compiler:转换时间过渡调整
  • 加油站小程序实战教程11会员注册
  • 互动交流平台/兰州seo关键词优化
  • 做网站的技术要求/网站seo优化步骤
  • 家政服家政服务网站模板/南昌seo排名
  • 衡水网站建设哪家好/营销策略是什么
  • 麻江网站建设/如何建网站不花钱
  • 任经理 徐州网站建设/深圳网络营销网站设计