上一篇【第23篇】DaemonSet——每个节点都要有的“守护者“
下一篇【第25篇】HPA——K8s的"自动弹性伸缩"魔法
摘要
Deployment、StatefulSet、DaemonSet——它们管的都是"活着就别停"的长期运行服务。但你有没有碰到过这种需求:跑一次数据库迁移,跑完就退出;每天凌晨2点备份一次数据;并行处理100万个计算任务,全部完成就收工。这些"跑完就停"的任务如果丢给Deployment——Pod退出后Deployment会使命般地把它重启,陷入"完成→重启→完成→重启"的死循环。
K8s给了两件武器:Job管一次性任务(跑完就停,可以重试但不能无限重启),CronJob管定时任务(按Cron表达式定期触发Job)。这篇文章从最简单的Job讲起,拆解三种并发模式、失败重试策略、超时控制,最后写一个生产级CronJob——定时备份etcd数据,让你睡觉时数据自动备份好。
一、Job——“跑完就退休”
1.1 Job和Deployment的本质区别
【Job vs Deployment——生命目标完全不同】 Deployment Pod 的一生: Job Pod 的一生: ┌─────────────────────┐ ┌─────────────────────┐ │ "活下去!不许死!" │ │ "完成使命!然后退休!" │ │ │ │ │ │ Running → 挂了? │ │ Pending → Running │ │ │ │ │ │ │ │ ▼ │ │ ▼ │ │ 自动重启! │ │ Completed │ │ 永远保持Running状态 │ │ (成功退出) │ │ │ │ │ │ 适合:Web服务、API │ │ 适合:备份、迁移、 │ │ │ │ 批处理、计算 │ └─────────────────────┘ └─────────────────────┘| 维度 | Deployment | Job |
|---|---|---|
| Pod退出码0 | 重启!(restartPolicy: Always) | 完成!成功退出 |
| Pod退出码非0 | 重启 | 重试(backoffLimit控制次数) |
| 任务跑完 | N/A(永远在跑) | Pod状态变成Completed |
| 删除策略 | 手动删除 | 自动清理(ttlSecondsAfterFinished) |
| 多Pod关系 | 都是对等的 | 可以并行、可以有顺序 |
1.2 最简单的Job——“跑个echo就完事”
apiVersion:batch/v1kind:Jobmetadata:name:hello-jobspec:template:spec:containers:-name:helloimage:busyboxcommand:["sh","-c","echo 'Hello K8s Job!'; sleep 3; echo 'Done!'"]restartPolicy:Never# ← 关键!Never 或 OnFailure,不能是 Alwayskubectl apply-fhello-job.yaml# 观察Job生命周期kubectl getjobs-w# NAME COMPLETIONS DURATION AGE# hello-job 0/1 0s 0s# hello-job 1/1 8s 8s ← 完成了!kubectl get pods# NAME READY STATUS RESTARTS AGE# hello-job-xxxxx 0/1 Completed 0 15s ← 状态是Completed不是Running# 看日志——任务输出kubectl logs hello-job-xxxxx# Hello K8s Job!# Done!要点:Job Pod的
restartPolicy只能是Never或OnFailure——不能是Always。因为Job的哲学是"完成任务就退休",Pod成功退出(exit code 0)就应该保持Completed状态,而不是被重启。如果你设了Always,K8s会直接拒绝——这是Job和Deployment最根本的区别。
二、Job的三种完成模式——“单人任务"到"千人团队”
2.1 非并行Job——“一个人干完活”
默认模式——启动一个Pod,完成一次就收工。
apiVersion:batch/v1kind:Jobmetadata:name:single-taskspec:completions:1# 需要成功完成1次(默认值)parallelism:1# 同时运行1个Pod(默认值)template:spec:containers:-name:workerimage:busyboxcommand:["sh","-c","echo 'Processing...'; sleep 10; echo 'Done!'"]restartPolicy:Never【非并行Job——串行执行】 启动 ─┬─ Pod-1 运行 ─┬─ Pod-1 成功退出 ─┬─ Job完成 │ │ │ ─────┴──────────────┴──────────────────┘ 只有一个工人,干完活下班2.2 固定完成次数并行Job——“一组人一起干”
apiVersion:batch/v1kind:Jobmetadata:name:parallel-taskspec:completions:5# 需要成功完成5次parallelism:2# 同时最多跑2个Podtemplate:spec:containers:-name:workerimage:busyboxcommand:["sh","-c","echo 'Task $JOB_COMPLETION_INDEX'; sleep 5"]restartPolicy:Never【固定完成次数并行Job】 时间轴 → ──────────────────────────────────────────────────── Pod-1 ─┬─ Task 0 ─┬─ 完成 ✓ │ │ Pod-2 ─│─ Task 1 ─│─ 完成 ✓ │ │ Pod-3 ─│──────────│── Task 2 ─┬─ 完成 ✓ │ │ │ Pod-4 ─│──────────│── Task 3 ─│─ 完成 ✓ │ │ │ Pod-5 ─│──────────│──────────│── Task 4 ─┬─ 完成 ✓ │ │ │ │ ───────┴──────────┴──────────┴──────────┴─────────── parallelism=2:同一时间最多2个Pod在跑 completions=5:总共要跑5个"成功的"Pod2.3 工作队列并行Job——“抢着干,干完为止”
apiVersion:batch/v1kind:Jobmetadata:name:work-queuespec:completions:50# 需要完成50个任务parallelism:10# 10个Pod同时抢任务completionMode:Indexed# K8s 1.21+ 每个Pod有唯一索引template:spec:containers:-name:workerimage:my-worker:latestenv:-name:JOB_COMPLETION_INDEX# 自动注入的索引号valueFrom:fieldRef:fieldPath:metadata.annotations['batch.kubernetes.io/job-completion-index']command:["python","/app/worker.py","--task-id=$(JOB_COMPLETION_INDEX)"]restartPolicy:Never【工作队列并行Job】 ┌─────────────────────────────────────────────┐ │ Redis / RabbitMQ 任务队列 │ │ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ... │ │ │Q1 │ │Q2 │ │Q3 │ │Q4 │ │Q5 │ │Q6 │ │ │ └───┘ └───┘ └───┘ └───┘ └───┘ └───┘ │ └────┬──────┬──────┬──────┬──────┬──────┬──────┘ │ │ │ │ │ │ ▼ ▼ ▼ ▼ ▼ ▼ ┌────────┐┌────────┐┌────────┐ ... (10个Pod同时抢任务) │ Pod-1 ││ Pod-2 ││ Pod-3 │ │ 拿Q1 ││ 拿Q2 ││ 拿Q3 │ │ 处理完 ││ 处理完 ││ 处理完 │ │ 再拿Q7 ││ 再拿Q8 ││ 拿不到 │→ 退出(成功) └────────┘└────────┘└────────┘ 50个任务由10个Pod瓜分,谁先干完谁多干 最后没新任务了,Pod优雅退出三种模式对比
| 模式 | completions | parallelism | 适用场景 |
|---|---|---|---|
| 非并行 | 1(默认) | 1(默认) | 单个一次性任务(如数据库迁移) |
| 固定完成次数 | N(具体数值) | ≤N | 独立可并行的小任务(如图片处理) |
| 工作队列 | 1(设置不正确时Pod判断) | ≥1 | 从消息队列消费任务的场景 |
要点:不要混淆
completions和parallelism。parallelism是"你派多少人去干活",completions是"总共要成功完成多少次"。比如completions: 10, parallelism: 3——你派了3个人,干完一份活就去领下一份,一共要干完10份才下班。
三、Job的"保险机制"——失败处理、超时和清理
3.1 backoffLimit——“再给你几次机会”
Pod执行失败了怎么办?backoffLimit控制重试次数:
apiVersion:batch/v1kind:Jobmetadata:name:retry-jobspec:backoffLimit:3# 最多重试3次(默认6次)template:spec:containers:-name:flaky-taskimage:busyboxcommand:["sh","-c","echo 'Attempting...'; exit 1"]# 故意失败restartPolicy:Neverkubectl apply-fretry-job.yaml# 观察重试过程kubectl get pods-w# retry-job-xxxxx Pending 0 0s ← 第1次# retry-job-xxxxx Error 0 3s ← 失败了(exit code 1)# retry-job-yyyyy Pending 0 0s ← 重试第1次# retry-job-yyyyy Error 0 3s ← 又失败# retry-job-zzzzz Pending 0 0s ← 重试第2次# retry-job-zzzzz Error 0 3s ← 还是失败# retry-job-aaaaa Pending 0 0s ← 重试第3次# retry-job-aaaaa Error 0 3s ← 最后一次也失败...# (没有新Pod了——backoffLimit=3,已经重试3次)kubectl describe job retry-job# Conditions:# Type Status Reason# Failed True BackoffLimitExceeded ← Job标记为失败【backoffLimit 重试策略】 第1次尝试 → 失败(exit code≠0) │ ▼ (等待10秒) 第2次尝试 → 失败 │ ▼ (等待20秒) ← 退避间隔递增 第3次尝试 → 失败 │ ▼ (等待40秒) 第4次尝试(backoffLimit=3,最后一次) │ ├── 成功 → Job完成! └── 失败 → Job标记Failed,不再重试要点:backoffLimit是指"最多失败几次就放弃",不是"最多重试几次"。
backoffLimit: 3意思是如果第1、2、3次都失败了,第4次(最后一次尝试)还失败就放弃。每次失败之间K8s会自动增加等待时间(指数退避:10s→20s→40s→…)。如果你的任务是"必须成功型"——把backoffLimit设大一点,或者干脆不设(默认6次)。
3.2 activeDeadlineSeconds——“超时就别干了”
apiVersion:batch/v1kind:Jobmetadata:name:timeout-jobspec:activeDeadlineSeconds:60# Job整个生命周期最多60秒backoffLimit:3template:spec:containers:-name:slow-taskimage:busyboxcommand:["sh","-c","echo 'Working...'; sleep 120; echo 'Done!'"]# 60秒一到,整个Job被终止!restartPolicy:Neverkubectl apply-ftimeout-job.yaml kubectl describe job timeout-job# Conditions:# Type Status Reason# Failed True DeadlineExceeded ← 超时了!kubectl get pods# NAME STATUS# timeout-job-xxxxx Terminated (DeadlineExceeded)3.3 ttlSecondsAfterFinished——“自动清理退休老员工”
apiVersion:batch/v1kind:Jobmetadata:name:auto-cleanup-jobspec:ttlSecondsAfterFinished:60# 完成后60秒自动删除Pod和Job记录template:spec:containers:-name:taskimage:busyboxcommand:["sh","-c","echo 'Done!'"]restartPolicy:Neverkubectl apply-fauto-cleanup-job.yaml# 60秒后Job自动消失kubectl getjobs-w# NAME COMPLETIONS DURATION AGE# auto-cleanup-job 1/1 3s 5s# (60秒后...)# auto-cleanup-job 1/1 3s 65s# (自动删除!Job和Pod都消失了)| 参数 | 作用 | 默认值 |
|---|---|---|
backoffLimit | 最多失败几次放弃 | 6 |
activeDeadlineSeconds | Job总生命时长上限 | 无限制 |
ttlSecondsAfterFinished | 完成后多久自动删除 | 不自动删除(需手动清理) |
completions | 需要成功完成多少次 | 1 |
parallelism | 最多同时运行几个Pod | 1 |
要点:
ttlSecondsAfterFinished是1.12版本加入的救命功能——没有它的话,Job完成后Pod一直留在那里(状态是Completed),时间长了集群里几百个Completed Pod,看着就烦。设个ttlSecondsAfterFinished: 3600(1小时),完成任务审计窗口过了自动清理。注意TTL Controller在1.21才GA,旧版本可能需要手动开Feature Gate。
四、CronJob——“让Job定时自动跑”
4.1 Cron表达式——“Crontab的五芒星”
【Cron 表达式解析】 ┌────────── 分钟 (0-59) │ ┌──────── 小时 (0-23) │ │ ┌────── 日 (1-31) │ │ │ ┌──── 月 (1-12) │ │ │ │ ┌── 星期 (0-6, 0=周日) │ │ │ │ │ * * * * * │ │ │ │ │ │ │ │ │ └─── 星期天=0或7 │ │ │ └────── 12=12月 │ │ └───────── 15=15号 │ └─────────── 2=凌晨2点 └───────────── 0=0分(整点) 例子: 0 2 * * * → 每天凌晨2点 */5 * * * * → 每5分钟 0 9 * * 1-5 → 工作日早上9点 0 0 1 * * → 每月1号零点 30 3 15 6 * → 6月15日凌晨3:304.2 一个简单的CronJob
apiVersion:batch/v1kind:CronJobmetadata:name:daily-reportspec:schedule:"0 8 * * *"# 每天早上8点执行concurrencyPolicy:Forbid# 防止并发执行startingDeadlineSeconds:300# 如果到了预定时间调度器没响应,300秒内还可以启动successfulJobsHistoryLimit:3# 保留最近3个成功的Job记录failedJobsHistoryLimit:1# 保留最近1个失败的Job记录jobTemplate:spec:template:spec:containers:-name:report-generatorimage:my-report:latestcommand:["python","generate_report.py"]env:-name:DATEvalueFrom:fieldRef:fieldPath:metadata.creationTimestamprestartPolicy:Never【CronJob 生命周期】 CronJob Controller 每10秒检查一次 │ ├── 当前时间:08:00:00 │ 匹配 schedule: "0 8 * * *" → 创建Job │ │ │ ▼ │ ┌──────────────┐ │ │ Job: report- │ │ │ 1627459200 │ ← 后缀是Unix时间戳 │ │ (Pod 执行) │ │ └──────────────┘ │ ├── 第二天 08:00:00 │ 又创建一个新Job │ └── 第三天 08:00:00...4.3 concurrencyPolicy——“上一个还没跑完怎么办?”
【三种并发策略】 Allow(允许并发): ───────────────────────────────────────────── Job-1: ████████████░░░░░░░░░░░░░░░░░░░░░░░░░░ (跑了12秒还没完) Job-2: ░░░░░░░░████████░░░░░░░░░░░░░░░░░░░░░░ ← 照常启动!两个同时跑 Forbid(禁止并发): ───────────────────────────────────────────── Job-1: ████████████████████████████████████████ (一直在跑) Job-2: ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ← 被跳过!不执行 Replace(替换旧任务): ───────────────────────────────────────────── Job-1: ██████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ (跑了10秒还没完) 就被杀死 ──► × Job-2: ░░░░░░░░░░██████████░░░░░░░░░░░░░░░░░░░░ ← 旧任务被杀,新任务启动spec:schedule:"*/5 * * * *"concurrencyPolicy:Forbid# 推荐:大多数场景应该禁止并发# concurrencyPolicy: Allow # 只有任务明确支持并发时才用# concurrencyPolicy: Replace # 谨慎使用!会杀掉正在跑的任务要点:默认的
concurrencyPolicy是Allow——这意味着如果你的任务跑了6分钟,Cron每分钟触发一次,就会出现多个Job同时跑的情况。数据库备份同时跑两个——灾难!生产环境的CronJob一律设concurrencyPolicy: Forbid,除非你明确知道任务支持并发。
五、实战:定时备份etcd的CronJob
5.1 etcd备份的重要性
etcd是K8s的大脑——存着所有集群状态。etcd挂了,集群就"失忆"了:
【etcd重要性】 ┌─────────────────────────────────────────────┐ │ etcd(集群数据库) │ │ ┌─────────────────────────────────────┐ │ │ │ • 所有资源对象(Pod/Service/...) │ │ │ │ • 所有ConfigMap和Secret │ │ │ │ • 集群状态和配置 │ │ │ │ │ │ │ │ 丢了 = 集群"失忆" = 灾难! │ │ │ └─────────────────────────────────────┘ │ └─────────────────────────────────────────────┘5.2 完整备份CronJob
# 1. ServiceAccount——备份任务需要读etcd证书apiVersion:v1kind:ServiceAccountmetadata:name:etcd-backupnamespace:kube-system---# 2. Secret——存云存储凭证apiVersion:v1kind:Secretmetadata:name:backup-storage-credsnamespace:kube-systemtype:OpaquestringData:s3-access-key:"YOUR_ACCESS_KEY"s3-secret-key:"YOUR_SECRET_KEY"s3-bucket:"k8s-etcd-backups"s3-endpoint:"https://s3.amazonaws.com"---# 3. ConfigMap——备份脚本apiVersion:v1kind:ConfigMapmetadata:name:etcd-backup-scriptnamespace:kube-systemdata:backup.sh:|#!/bin/bash set -eBACKUP_DIR="/backups" TIMESTAMP=$(date +%Y%m%d_%H%M%S) BACKUP_FILE="${BACKUP_DIR}/etcd-snapshot-${TIMESTAMP}.db" echo "========================================="echo "ETCD Backup Started:$(date)" echo "========================================="# 1. 创建etcd快照echo "[1/4]Creating etcd snapshot..." ETCDCTL_API=3 etcdctl snapshot save ${BACKUP_FILE}\--endpoints=https://127.0.0.1:2379 \--cacert=/etc/kubernetes/pki/etcd/ca.crt \--cert=/etc/kubernetes/pki/etcd/server.crt \--key=/etc/kubernetes/pki/etcd/server.key# 2. 验证快照echo "[2/4]Verifying snapshot..." ETCDCTL_API=3 etcdctl snapshot status ${BACKUP_FILE}# 3. 压缩快照echo "[3/4]Compressing snapshot..." gzip ${BACKUP_FILE}COMPRESSED_FILE="${BACKUP_FILE}.gz"# 4. 上传到S3(或者你的对象存储)echo "[4/4]Uploading to S3..."# 安装aws cliif[-n "${S3_ACCESS_KEY}"]; then aws configure set aws_access_key_id ${S3_ACCESS_KEY}aws configure set aws_secret_access_key ${S3_SECRET_KEY}aws configure set region ${S3_REGION:-us-east-1}aws s3 cp ${COMPRESSED_FILE}\ s3://${S3_BUCKET}/etcd-backups/${CLUSTER_NAME}/$(date +%Y/%m/%d)/etcd-snapshot-${TIMESTAMP}.db.gz \--endpoint-url ${S3_ENDPOINT}echo "Upload successful!" elseecho "WARNING:S3 credentials not configured. Backup stored locally only." fi# 5. 清理本地旧备份(保留最近7天)echo "Cleaning up old local backups..." find ${BACKUP_DIR}-name "etcd-snapshot-*.db.gz"-mtime +7-delete echo "========================================="echo "ETCD Backup Completed:$(date)"echo "Backup file:${COMPRESSED_FILE}"echo "Size:$(du-h ${COMPRESSED_FILE}|cut-f1)" echo "========================================="---# 4. CronJob——主角apiVersion:batch/v1kind:CronJobmetadata:name:etcd-backupnamespace:kube-systemspec:schedule:"0 2 * * *"# 每天凌晨2点concurrencyPolicy:Forbid# 禁止并发successfulJobsHistoryLimit:7# 保留最近7天日志failedJobsHistoryLimit:3startingDeadlineSeconds:600# 10分钟内还可以启动jobTemplate:spec:ttlSecondsAfterFinished:86400# 24小时后自动清理backoffLimit:2# 只重试2次activeDeadlineSeconds:600# 10分钟内必须完成template:spec:serviceAccountName:etcd-backupnodeSelector:node-role.kubernetes.io/control-plane:""# 只在Master上跑tolerations:-key:node-role.kubernetes.io/control-planeoperator:Existseffect:NoSchedulecontainers:-name:backupimage:bitnami/etcd:3.5# 带etcdctl的镜像command:["/bin/bash","/scripts/backup.sh"]env:-name:CLUSTER_NAMEvalue:"prod-cluster"-name:S3_REGIONvalue:"us-east-1"-name:S3_ACCESS_KEYvalueFrom:secretKeyRef:name:backup-storage-credskey:s3-access-key-name:S3_SECRET_KEYvalueFrom:secretKeyRef:name:backup-storage-credskey:s3-secret-key-name:S3_BUCKETvalueFrom:secretKeyRef:name:backup-storage-credskey:s3-bucket-name:S3_ENDPOINTvalueFrom:secretKeyRef:name:backup-storage-credskey:s3-endpointvolumeMounts:-name:backup-datamountPath:/backups-name:etcd-certsmountPath:/etc/kubernetes/pki/etcdreadOnly:true-name:backup-scriptmountPath:/scriptsreadOnly:trueresources:requests:memory:"128Mi"cpu:"100m"limits:memory:"256Mi"cpu:"500m"restartPolicy:Nevervolumes:-name:backup-datahostPath:path:/var/backups/etcdtype:DirectoryOrCreate-name:etcd-certshostPath:path:/etc/kubernetes/pki/etcd# 访问Master上的etcd证书type:Directory-name:backup-scriptconfigMap:name:etcd-backup-scriptdefaultMode:0755# 可执行# 部署kubectl apply-fetcd-backup-cronjob.yaml# 手动触发一次测试kubectl create job--from=cronjob/etcd-backup etcd-backup-test-nkube-system# 查看测试结果kubectl logs-nkube-system job/etcd-backup-test# 查看CronJob状态kubectl get cronjob etcd-backup-nkube-system# NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE# etcd-backup 0 2 * * * False 0 <none> 5m# 暂停CronJob(不删配置,只是停掉)kubectl patch cronjob etcd-backup-nkube-system-p'{"spec":{"suspend":true}}'# 恢复kubectl patch cronjob etcd-backup-nkube-system-p'{"spec":{"suspend":false}}'# 查看历史Jobkubectl getjobs-nkube-system-l"app.kubernetes.io/managed-by=cronjob"5.3 恢复测试——备份了还得能恢复
# 从S3下载备份aws s3cps3://k8s-etcd-backups/prod-cluster/2026/07/28/etcd-snapshot-20260728_020001.db.gz.# 解压gunzip etcd-snapshot-20260728_020001.db.gz# 验证快照ETCDCTL_API=3etcdctl snapshot status etcd-snapshot-20260728_020001.db# ⚠️ 恢复操作——危险!只在测试环境做!# ETCDCTL_API=3 etcdctl snapshot restore etcd-snapshot-20260728_020001.db \# --data-dir=/var/lib/etcd-restore \# --name=master-node \# --initial-cluster=master-node=https://127.0.0.1:2380 \# --initial-advertise-peer-urls=https://127.0.0.1:2380要点:备份不验证等于没备份!定期做恢复演练——在测试集群里把etcd数据还原出来,确认快照有效。否则生产环境真出事了,你发现备份文件是坏的——那感觉比没备份还糟糕。
六、Job和CronJob常用命令
# Job命令kubectl getjobskubectl getjobs-w# 实时观察kubectl describe job<job-name>kubectl logs job/<job-name># 查看Job日志(所有Pod)kubectl logs job/<job-name>-c<container># 指定容器# 手动触发CronJobkubectl create job<test-name>--from=cronjob/<cronjob-name># 删除Job(会删除关联的Pod)kubectl delete job<job-name># CronJob命令kubectl get cronjob kubectl get cronjob-wkubectl describe cronjob<cronjob-name># 暂停/恢复CronJobkubectl patch cronjob<name>-p'{"spec":{"suspend":true}}'kubectl patch cronjob<name>-p'{"spec":{"suspend":false}}'# 查看CronJob的历史Jobskubectl getjobs--selector=app.kubernetes.io/managed-by=cronjob# 立即触发(不等到schedule时间)kubectl create job manual-etcd-backup--from=cronjob/etcd-backup# 删除CronJob(会删除所有关联的Job和Pod)kubectl delete cronjob<cronjob-name>本篇小结
Job和CronJob填补了K8s任务调度的最后一块拼图:
- Job = 一次性任务:Pod成功退出(exit 0)→ Completed,不会像Deployment一样无限重启
- 三种并发模式:非并行(单兵作战)、固定完成次数(N个工人干完N份活)、工作队列(抢任务模式)
- 失败处理:backoffLimit控制重试次数,activeDeadlineSeconds设超时上限,指数退避防雪崩
- 自动清理:ttlSecondsAfterFinished让完成的Job自动消失,不用手动删几百个Completed Pod
- CronJob = 定时Job:Cron表达式精确控制执行时间,concurrencyPolicy: Forbid防并发,suspend临时暂停
- 实战etcd备份:生产级的备份方案——定时快照→压缩→上传S3→审计日志→过期清理
Job和CronJob虽然简单,但它们是运维自动化的基石。一个凌晨2点自动跑的etcd备份CronJob,比"运维老王每天手动敲命令"可靠一万倍。
下一篇咱们聊HPA——K8s的自动弹性伸缩魔法。流量来了自动扩容,流量走了自动缩容,CPU/内存/自定义指标都能做触发条件——Pod再也不怕"撑死"或"闲死"了。
上一篇【第23篇】DaemonSet——每个节点都要有的“守护者“
下一篇【第25篇】HPA——K8s的"自动弹性伸缩"魔法