【k8s】实验搭建及pod控制器运用

核心原理阐述

  1. Kubernetes 架构原理 (Master-Node 模型)
  • 控制平面 (Master):集群的大脑。

  • API Server:集群网关,所有操作都必须通过它。

  • Scheduler:负责调度 Pod 到合适的 Node。

  • Controller Manager:维护集群状态(如副本数、故障恢复)。

  • etcd:分布式键值存储,保存集群所有关键数据。

  • 工作节点 (Node):干活的单元。

  • kubelet:节点代理,负责与 Master 通信并管理 Pod 生命周期。

  • 容器运行时 (Docker/containerd):真正负责运行容器。

  • kube-proxy:维护网络规则,实现 Service 的负载均衡和服务发现。

Kubernetes 资源基础

  1. 核心概念

    • Kubernetes 中所有内容抽象为资源,最小管理单元是 Pod
    • 通常通过 Pod 控制器管理 Pod,而非直接管理
    • 服务访问通过 Service 实现,数据持久化通过存储系统实现
  2. 资源管理方式

    |---------|------|-----------------|-------------------------------------|
    | 类型 | 适用场景 | 特点 | 示例命令 |
    | 命令式对象管理 | 测试 | 简单直接,无法审计跟踪 | kubectl run nginx-pod --image=nginx |
    | 命令式对象配置 | 开发 | 可审计跟踪,配置文件多时有麻烦 | kubectl create -f nginx-pod.yaml |
    | 声明式对象配置 | 开发 | 支持目录操作,意外情况调试难 | kubectl apply -f nginx-pod.yaml |

  3. Pod 核心知识

    Pod 定义

    最小可部署单元,代表集群中运行的一个进程
    包含一个或多个容器,共享 IPC、Network 和 UTC 命名空间

    每个 Pod 拥有唯一 IP 地址

1.基础环境准备(4台虚拟机)

核心目标

搭建一个高可用的 Kubernetes 生产级集群,实现容器化应用的自动化部署、扩展和管理。

整体流程

  1. 理论准备:理解 K8S 架构、组件及其协作原理。

  2. 环境规划:规划节点角色、网络、存储等资源。

  3. 基础准备:在所有节点上完成系统初始化(关闭 swap、配置网络、安装 Docker 等)。

  4. 核心安装:安装 K8S 核心组件 (`kubeadm`, `kubelet`, `kubectl`) 和容器运行时接口 (`cri-dockerd`)。

  5. 私有仓库:配置 Harbor 作为私有镜像仓库,供集群拉取镜像。

  6. 集群初始化:在 Master 节点使用 `kubeadm init` 初始化控制平面。

  7. 网络部署:安装 Flannel CNI 插件,为 Pod 提供网络通信能力。

  8. 节点扩容:将 Worker 节点加入集群,形成多节点集群。

  9. 功能验证:创建测试 Pod 验证集群基本功能是否正常。


1.1 reg节点

先开一台reg节点的虚拟机,IP为192.168.1.222

关闭selinux

部署Harbor

下载安装所需依赖包:这里已经提前下好,直接拖进来了

使用OpenSSL生成自签名证书,保障HTTPS通信

bash 复制代码
[root@reg ~]#  openssl req -newkey rsa:4096 -nodes -sha256 -keyout /data/certs/timinglee.org.key -addext "subjectAltName = DNS:reg.timinglee.org" -x509 -days 365 -out /data/certs/timinglee.org.crt

国家,省,市,...

提供私有Docker镜像仓库,仓库地址为reg.timinglee.org,供集群内其他节点拉取镜像。。

等待构建完成,通过Docker Compose启动Harbor服务。配置所有节点信任自签名证书,并登录私有仓库。

bash 复制代码
ps:第一次启动用./install.sh --with-chartmuseum

后面启动时进入harbor目录通过Docker Compose启动

cd harbor/

docker compose up -d

注意:每次关闭虚拟机后重启时,都要通过该命令重启Harbor服务

成功后就可以访问了

此时reg虚拟机就可以后台运行了,接下来我们看另外的


1.2 Kubernetes集群搭建

克隆三台主机:master100 ,node1:10,node2:20

关闭swap和本地解析

关闭Swap以确保内存管理一致性。

关闭当前三个节点的所有swap,并且重启之后也不能有

修改/etc/hosts,确保节点间可通过主机名通信。

所有节点安装Docker,

前面我们在reg节点上已经配置好docker了,现在把安装包拷贝到其他三个节点上。

Master编辑配置文件

拷到其他两个node节点

配置仓库的加速器

并配置镜像加速器指向私有Harbor仓库。重启Docker服务并登录Harbor。

bash 复制代码
[root@docker1 ~]# cat /etc/docker/daemon.json

{

      "registry-mirrors": [

        "https://reg.timinglee.org",

      ]

}
bash 复制代码
[root@master docker]# for i in 10 20; do scp daemon.json root@192.168.1.$i:/etc/docker/; done                          
daemon.json                                                                          100%   57    85.4KB/s   00:00
daemon.json                                                                          100%  57   117.3KB/s   00:00
[root@master docker]# for i in 100 10 20; do ssh root@192.168.1.$i systemctl enable --now docker; done

Docker info

三个主机都检查一下复制的文件成功没,一般这个时候就可以登陆了,但是

登陆报错,发现少了一个目录

cd /etc/docker/certs.d/

记得检查是否复制成功

再次登陆,成功

登陆其他主机(所有主机都必须登陆,否则下不来东西)


1.3 安装k8s

1.3.1 修改cri-dockerd启动文件添加

将需要安装的包下载下来,这里是有文件包直接拖进来了,没有的话可以去官网上搜索包下载'

对于其他的节点前面下载了docker包,现在可以先把包删除,再从master把新包拷过去

node2同理

配置kubelet使用cri-dockerd作为容器运行时。启动kubelet服务。

1.3.2 安装K8s部署工具

在【master】配置环境变量,设置kubectl命令补齐功能、

bash 复制代码
dnf install bash-completion -y
echo "source <(kubectl completion bash)" >> ~/.bashrc
source  ~/.bashrc

1.4 拉取k8s镜像

导入镜像

$0所有

root@master docker-images# docker images | awk '/google/{print 1":"2}' |awk -F / '{system("docker tag "0" reg.timinglee.org/k8s/"3)}'

bash 复制代码
[root@master docker-images] docker images | awk '/reg/{print $0}'
我们要的是这些

[root@master docker-images] docker images | awk '/reg/{print $1":"$2}'
就可以开始推了
如果拉取失败仓库拒绝可能是没开启重启一下reg的harbor
进入到harbor的目录下面
docker compose down 再docker compose up -d

root@master docker-images# docker images | awk '/timinglee/{system("docker push " 1":"2)}'

【三个节点】

打开服务

bash 复制代码
指定容器网络
kubeadm init --pod-network-cidr=10.244.0.0/16 \
--image-repository reg.timinglee.org/k8s \
--kubernetes-version v1.30.0 \
--cri-socket=unix:///var/run/cri-dockerd.sock


先导入配置
[root@master docker-images] echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
[root@master docker-images] source ~/.bash_profile
[root@master docker-images]  kubectl get nodes
NAME                   STATUS     ROLES           AGE   VERSION
master.timinglee.org   NotReady   control-plane   2m    v1.30.0

notready未运行成功

其他节点

现在节点加不进去,因为还没有网络插件flannel

1.5 拉取Flannel镜像

先导入镜像:有俩个镜像显示

从Docker Hub拉取Flannel镜像,推送到私有Harbor。

分为三步 tag-新建项目-push

#先创建项目再拉取push,否则会拉取失败

cs 复制代码
两个镜像就要操作两次
 docker tag flannel/flannel:v0.25.5 reg.timinglee.org/flannel/flannel:v0.25.5
#push 仓库网站/项目目录/镜像名 如果有了该目录,就不需要新建
docker push reg.timinglee.org/flannel/flannel:v0.25.5

bash 复制代码
打标签
docker tag flannel/flannel-cni-plugin:v1.5.1-flannel1 reg.timinglee.org/flannel/fl                                 annel-cni-plugin:v1.5.1-flannel1
上传
docker push reg.timinglee.org/flannel/flannel-cni-plugin:v1.5.1-flannel1

修改kube-flannel.yml中的镜像地址为私有仓库路径。

修改文件kube-flannel.yml

cs 复制代码
把前缀去掉即可
[root@master ~]# kubectl apply -f kube-flannel.yml
[root@master ~]# kubectl get nodes

应用Flannel配置,等待Pod就绪。

要等插件运行起来后才能看到

1.6 其他主机加入集群

使用kubeadm join命令将node10和node20加入集群。检查节点状态和网络连通性。

火墙是不是没关

记得检查火墙

bash 复制代码
 kubeadm join 192.168.1.100:6443 --token w6p5gc.a5halrlwz735s7rb --discovery-token-ca-cert-hash sha256:9166dd9826643972c931f34a0ace7e663cd69efa8f32c6e931b3f89ed3b90224 --cri-socket=unix:///var/run/cri-dockerd.sock

加载的比较慢可能是火墙

cpp 复制代码
出现问题重新加载
[root@node2 ~]# kubeadm reset --cri-socket=unix:///var/run/cri-dockerd.sock
再执行刚才的命令
kubeadm join 192.168.1.100:6443 --token w6p5gc.a5halrlwz735s7rb --discovery-token-ca-cert-hash sha256:9166dd9826643972c931f34a0ace7e663cd69efa8f32c6e931b3f89ed3b90224 --cri-socket=unix:///var/run/cri-dockerd.sock

到此为止安装完成

1.7 测试

登不上去,没认证

有点慢

先登录再认证

可以看到两个节点各自运行了一个nginx


容器编排原理

Pod:K8S 最小调度单元,包含一个或多个共享网络/存储的容器。

Controller:通过定义期望状态(如 replicas: 3)来管理 Pod 的生命周期,确保实际状态始终向期望状态收敛(声明式管理)。

Service:为一组 Pod 提供稳定的访问入口和负载均衡。

CNI (Container Network Interface):Flannel 等插件负责为每个 Pod 分配 IP 并实现跨节点网络通信。

2. 基础Pod与控制器实验

2.1 Pod镜像准备

bash 复制代码
 docker tag busyboxplus:latest reg.timinglee.org/library/busyboxplus:latest

 docker push reg.timinglee.org/library/busyboxplus
bash 复制代码
docker tag timinglee/myapp:v1 reg.timinglee.org/library/myapp:v1
#记得push要新建项目
 docker push reg.timinglee.org/library/myapp:v1

导入nginx镜像

bash 复制代码
#创建一个webcluster控制器,控制器中pod数量为2
把nginx上传到harbor仓库
docker tag nginx:latest  reg.timinglee.org/library/nginx:latest
新建项目后再push
docker push reg.timinglee.org/library/nginx:latest

直接创建自主式Pod,生命周期与Pod绑定。创建Deployment管理Pod副本,支持滚动更新和回滚。通过kubectl edit实时修改配置如镜像版本。

bash 复制代码
[root@k8s-master ~] kubectl create deployment webcluseter --image nginx --replicas 2
#查看控制器
[root@k8s-master ~] kubectl get  deployments.apps
这是在 Kubernetes 环境中创建一个名为 webcluseter 的 Deployment 资源,指定使用 nginx 镜像,期望副本数(--replicas)为 2 ,输出 deployment.apps/webcluseter created 表示 Deployment 创建成功 

一个Pod内运行多个容器,共享网络和存储空间。注意端口冲突问题需配置不同端口或协议。在Pod主容器启动前运行Init容器执行初始化任务。

Pod运行后修改不了配置文件了

控制器可以直接进到文件里面修改

#编辑控制器配置

root@k8s-master \~# kubectl edit deployments.apps web

只是进去看了一下,什么都没改,所以显示no changes made

bash 复制代码
#删除资源
[root@k8s-master ~] kubectl delete deployments.apps web
deployment.apps "web" deleted
[root@k8s-master ~] kubectl get deployments.apps
No resources found in default namespace.
一个pod运行两个容器个
test里面有两个基于nginx的容器test1和test2

会自动生成配置文件

STATUS会刷新,一会运行一会error,因为我们配置了两个test1,test2,两个共享网路资源端口冲突

修改

现在两个都运行

Kubectl describe pod查看状态

进入容器内部输入指令

可以访问本地

每次小实验结束后都把该pod删除,以免影响后续实验

2.2 创建自助式pod(生产不推荐

优点是灵活性高,可以精确控制 Pod 的各种配置参数,通过手动创建 Pod 可以深入了解 Pod 的结构和配置方式。在调试问题时,可以更直接地观察和调整 Pod 的设置。

缺点是手动创建和维护pod在数量较多时非常繁琐,容易出错,且缺乏高级功能,如自动部署、滚动更新、服务发现等。这可能导致应用的部署和管理效率低下。

cs 复制代码
#查看所有pods
[root@k8s-master ~]# kubectl get pods
No resources found in default namespace.

#建立一个名为timinglee的pod
[root@k8s-master ~]# kubectl run timinglee --image nginx
pod/timinglee created


[root@k8s-master ~]# kubectl get pods
NAME        READY   STATUS    RESTARTS   AGE
timinglee   1/1     Running   0          6s

#显示pod的较为详细的信息
[root@k8s-master ~]# kubectl get pods -o wide

配置存活探针检测容器是否健康,失败时重启容器。配置就绪探针检测容器是否准备好接收流量,失败则从Service负载均衡中移除。

3. 运用控制器管理pod

在 Kubernetes (k8s) 中,控制器(Controller)是实现 Pod 自动化管理的核心组件,它们通过监控集群状态并调整实际状态以匹配期望状态,确保 Pod 按照预设规则稳定运行。

以下是控制器的核心作用和常见使用场景:

3.1、控制器的核心作用

维持期望状态

控制器通过 watch 机制监控 Pod 和其他资源的状态,当实际状态与用户定义的期望状态(如副本数、运行节点等)不一致时,会自动触发调整(如创建 / 删除 Pod、重启故障实例等)。

简化 Pod 管理

直接管理 Pod 存在局限性(如 Pod 故障后不会自动重建),而控制器通过抽象层(如 Deployment、StatefulSet)简化了复杂操作(如滚动更新、扩缩容)。

实现高级功能

支持自愈、弹性伸缩、滚动更新、有状态服务管理等 Kubernetes 核心特性。

3.2、常见控制器及使用场景

以下是 Kubernetes 主要控制器的对比与适用场景的表格整理:

控制器类型 核心用途 关键特性 适用场景 替代/关联组件
ReplicationController 确保指定数量的 Pod 副本运行(已废弃) 最早的副本管理控制器,支持基本扩缩容和自愈,功能有限 历史遗留场景,不再推荐使用 被 ReplicaSet 完全替代
ReplicaSet 确保任意时刻有指定数量的 Pod 副本运行 通过标签选择器关联 Pod,自动创建/删除以维持副本数 作为 Deployment 的底层组件,不建议直接使用 被 Deployment 间接管理
Deployment 提供 Pod 和 ReplicaSet 的声明式更新能力 支持滚动更新、版本回滚、扩缩容,自动管理 ReplicaSet Web 服务、API 服务等无状态应用 基于 ReplicaSet 实现
DaemonSet 确保每个指定节点上运行一个 Pod 副本 新节点加入时自动部署,支持节点亲和性筛选 日志收集(Fluentd)、监控代理(Node Exporter)
StatefulSet 管理有状态应用的稳定运行 固定 Pod 名称/网络标识(DNS)、有序部署/更新/删除、存储与 Pod 解绑(PVC) 数据库(MySQL)、分布式系统(ZooKeeper) 需配合 Headless Service 使用
Job 执行一次性批处理任务 任务完成后 Pod 自动终止,支持并行执行和重试 数据备份、离线计算、一次性脚本执行
CronJob 基于时间调度周期性任务 类似 Linux crontab,支持 cron 表达式定义调度规则 定时日志清理、周期性数据同步 基于 Job 实现
HPA 根据资源使用率自动调整 Pod 副本数 支持 CPU/内存或自定义指标(如 QPS),动态扩缩容 流量波动大的应用(如电商促销) 需与 Deployment/StatefulSet 配合

关键说明

  • 废弃组件:ReplicationController 已完全被 ReplicaSet 替代。
  • 间接使用:ReplicaSet 通常由 Deployment 管理,无需手动操作。
  • 有状态与无状态:StatefulSet 适用于需稳定标识和存储的场景,Deployment 适用于无状态服务。
  • 自动化扩展:HPA 需配置指标源(如 Metrics Server)才能生效。
ReplicaSet(副本集)

作用

确保指定数量的 Pod 副本始终运行。

特点

通过 selector 关联 Pod,自动调整 Pod 数量。

虽然 ReplicaSets 可以独立使用,但今天它主要被Deployments 用作协调 Pod 创建、删除和更新的机制

cpp 复制代码
#生成yml文件.名字自取不固定
[root@k8s-master ~]# kubectl create deployment replicaset --image reg.timinglee.org/library/myapp:v1 --replicas 2 --dry-run=client -o yaml > replicaset.yml
#生成一个 Deployment 的 YAML 配置文件,文件名为 replicaset.yml。
#这个配置会创建一个名为 "replicaset" 的 Deployment,使用指定的镜像并保持 2 个副本。

[root@k8s-master ~]# vim replicaset.yml
apiVersion: apps/v1
kind: ReplicaSet        #控制器类型
metadata:
  labels:               #给控制器标签,让微服务可以发现它
    app: replicaset
  name: replicaset		#指定pod名称,一定小写,如果出现大写报错
spec:
  replicas: 2			#指定维护pod数量为2
  selector:				#指定检测匹配方式
    matchLabels:		#指定匹配方式为匹配标签
      app: replicaset		#指定容器匹配的标签为app=replicaset	,让控制器可以检测到它

  template:				#模板,当副本数量不足时,会根据下面的模板创建pod副本
    metadata:
      labels:
        app: replicas
    spec:
      containers:
      - image: reg.timinglee.org/library/myapp:v1
        name: myapp

[root@k8s-master ~]# kubectl apply -f replicaset.yml
replicaset.apps/replicaset created
cpp 复制代码
[root@k8s-master ~]# kubectl get pods  --show-labels
NAME               READY   STATUS    RESTARTS   AGE   LABELS
replicaset-l4xnr   1/1     Running   0          96s   app=myapp
replicaset-t2s5p   1/1     Running   0          96s   app=myapp


#replicaset是通过标签匹配pod
[root@k8s-master ~]# kubectl label pod replicaset-l4xnr app=timinglee --overwrite
pod/replicaset-l4xnr labeled
[root@k8s-master ~]# kubectl get pods  --show-labels
NAME               READY   STATUS    RESTARTS   AGE     LABELS
replicaset-gd5fh   1/1     Running   0          2s      app=myapp		#新开启的pod
replicaset-l4xnr   1/1     Running   0          3m19s   app=timinglee
replicaset-t2s5p   1/1     Running   0          3m19s   app=myapp

#恢复标签后
[root@k8s2 pod]# kubectl label pod replicaset-example-q2sq9 app- 
[root@k8s2 pod]# kubectl get pod --show-labels
NAME                       READY   STATUS    RESTARTS   AGE     LABELS
replicaset-example-q2sq9   1/1     Running   0          3m14s   app=nginx
replicaset-example-th24v   1/1     Running   0          3m14s   app=nginx
replicaset-example-w7zpw   1/1     Running   0          3m14s   app=nginx

#replicaset自动控制副本数量,pod可以自愈
[root@k8s-master ~]# kubectl delete pods replicaset-t2s5p
pod "replicaset-t2s5p" deleted
#即如果我们删除pods,它还会自动创建一个新的
[root@k8s-master ~]# kubectl get pods --show-labels
NAME               READY   STATUS    RESTARTS   AGE     LABELS
replicaset-l4xnr   1/1     Running   0          5m43s   app=myapp
replicaset-nxmr9   1/1     Running   0          15s     app=myapp

#如果想删除,直接删除控制器,指明控制器类型和名字
[root@k8s-master ~]kubectl delete replicaset replicaset
回收资源
[root@k8s2 pod]# kubectl delete -f replicaset.yml

deployment控制器
  • Deployment控制器并不直接管理pod,而是通过管理ReplicaSet来间接管理Pod

  • Deployment管理ReplicaSet,ReplicaSet管理Pod

cs 复制代码
#生成yaml文件
[root@k8s-master ~]# kubectl create deployment dep --image myapp:v1  --dry-run=client -o yaml > dep.yml

[root@k8s-master ~]# vim dep.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment
spec:
  replicas: 4
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - image: myapp:v1
        name: myapp
#建立pod
root@k8s-master ~]# kubectl apply -f dep.yml
deployment.apps/deployment created

#查看pod信息
[root@k8s-master ~]# kubectl get pods --show-labels
版本更新

版本回滚

滚动更新策略

暂停及恢复

deamonset控制器

作用:确保集群中所有(或指定)节点运行相同的 Pod 副本新节点 加入时自动部署

适用场景:日志收集(如 Fluentd)、监控代理(如 Prometheus Node Exporter)、网络插件(如 Calico)等节点级服务。

示例:在所有节点部署pod副本

cs 复制代码
进入之前的yml文件目录
创建yml文件
[root@master 2.pod]# vi daemonset-example.yml
[root@master 2.pod]# kubectl apply  -f daemonset-example.yml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  labels:
    run: daemonset-example
  name: daemonset-example
spec:
  selector:
    matchLabels:
      app: daemonset-example
  template:
    metadata:
      labels:
        app: daemonset-example
    spec:
      containers:
      - image: myapp:v1
        name: myapp
格式非常严格!一个空格也不能少!

DaemonSet 的设计逻辑是 "在集群中每个符合条件的节点上运行且仅运行一个 Pod 副本"

我们前面集群创建了三个节点,3 个节点对应 3 个 Pod,确保每个节点(无论当前是否就绪)都有一个关联的 Pod,节点就绪后会自动启动 Pod。所以这里有三个

正常状态下三个都是running

root@master 2.pod# kubectl describe pod daemonset-example-c2njr查看状态,未运行原因

由于我为节省运行内存只开了三台机子(master,node1,reg),也就是master只有一个子节点,另一个节点本身未就绪,无法运行 Pod,所以有一个节点是就绪状态pending

cs 复制代码
# 查看所有 DaemonSet 管控的 Pod
kubectl get pods -l app=daemonset-example  

# 删除 DaemonSet(会自动删除所有关联 Pod)
kubectl delete -f daemonset-example.yml  
或者kubectl delete daemonset daemonset-example

# 扩容/缩容(虽然 DaemonSet 通常按节点数自动管理,但可强制更新)
kubectl rollout restart daemonset daemonset-example  

通过标签筛选 Pod:
因为 Pod 有 app: daemonset-example 标签,也能精准筛选:
kubectl get pods -l app=daemonset-example  

Job 与 CronJob(一次性/定时任务)

Job

执行一次性任务,任务完成后 Pod 自动终止。适合批量处理短暂的一次性任务(要指定任务数量)

CronJob

基于时间调度的 Job,如定时备份、日志清理。

job:指定任务

cs 复制代码
[root@k8s-master ~]# kubectl create job job-example --image myapp:v1  --dry-run=client -o yaml > job-example.yml
[root@k8s2 pod]# vim job-exampleb.yml
apiVersion: batch/v1
kind: job
metadata:
  name:job-example
spec:
  completions: 6		#一共完成任务数为6		
  parallelism: 2		#每次并行完成2个
  backoffLimit: 4       #运行失败后尝试4重新运行
  template:
    spec:
      containers:
      - name: pai
        image: perl:5.34.0
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]	计算Π的后2000位
      restartPolicy: Never						#关闭后不自动重启
  backoffLimit: 4								#运行失败后尝试4重新运行

[root@k8s2 pod]# kubectl apply -f job.yml

每次要用到什么镜像时,如果镜像没有导入,我们都要导入该镜像上传到harbor仓库,否则拉取不到镜像,配置无法生效

push 仓库网站/项目目录/镜像名

上传成功后再apply配置文件

cpp 复制代码
查看有没有建立成功
kubectl get pods -o wide
刚开始是两个两个开始建立
创建需要时间
直到完成六个的创建

cronjob:指定时间

比如:每天凌晨 2 点执行备份 "0 2 * * *"

cpp 复制代码
[root@k8s2 pod]# vim cronjob.yml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "* * * * *"     #位置要在job前面,*表示默认值1,每分钟新建一个
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox
            imagePullPolicy: IfNotPresent  #镜像拉取策略
            command:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure          #拉取失败不计入次数

[root@k8s2 pod]# kubectl apply -f cronjob.yml

两个必须写一个

否则默认值是always,一直会反复重新运行

测试

复制代码