基本概念
在Kubernetes中,Pod是一等公民
Pod是Kubernetes的原子调度单位 ,Kubernetes统一按照Pod(而非容器)的资源需求进行计算
容器的本质是进程
容器的单进程模型
并不是指容器里只能运行一个进程,而是指容器没有管理多个进程的能力
原因
容器里PID=1的进程是应用本身,其它进程都是PID=1进程的子进程
用户编写的应用,并不能像正常OS里面的init 进程或者systemd 进程那样拥有进程管理 的功能
容器间具有『超亲密关系 』的典型特征
互相之间会发生直接的文件交换
使用localhost 或者Socket 文件进行本地通信
会发生非常频繁的远程调用
需要共享 某些Linux Namespace
并不是所有有关系的容器都属于同一个Pod,如Java应用容器和MySQL更适合做成两个Pod
Pod在Kubernetes中的重要意义 – 容器设计模式
实现原理
Pod只是一个逻辑概念
Kubernetes真正处理的,还是宿主机上Linux容器的Namespace和Cgroups ,并不存在所谓的Pod的边界或者隔离环境
Pod里的所有容器,共享的是同一个Network Namespace,并且可以声明共享同一个Volume
Pod的实现会使用一个中间容器 ,称为Infra容器
Infra容器永远都是第一个被创建 的容器,其它用户定义的容器,则通过Join Network Namespace ,与Infra容器关联
Infra容器占用极少的资源 ,镜像为k8s.gcr.io/pause
(汇编 语言编写,永远处于『暂停 』状态)
Infra容器Hold 住Network Namespace后,用户容器可以加入到Infra容器的Network Namespace中
Pod中的容器A和容器B
可以直接使用localhost 进行通信
看到的网络设备 与Infra容器看到的完全一样
一个Pod只有一个IP地址 ,即该Pod的Network Namespace对应的IP地址
其它网络资源,一个Pod一份,可以被Pod中的所有容器共享
Pod的生命周期只跟Infra容器一致 ,与容器A和容器B无关
对于同一个Pod里面的所有用户容器来说,他们的进出流量 ,可以认为都是通过Infra 容器完成的
网络插件:不必关心用户容器启动与否,重点关注如何配置Pod(Infra容器)的Network Namespace
Volume:只要把所有Volume的定义都设计在Pod层级 即可
一个Volume对应的宿主机目录对于Pod来说就只有一个
Pod里的容器只需要声明挂载该Volume,就可以共享 该Volume对应的宿主机目录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 apiVersion: v1 kind: Pod metadata: name: two-containers spec: restartPolicy: Never volumes: - name: shared-data hostPath: path: /data containers: - name: nginx-container image: nginx volumeMounts: - name: shared-data mountPath: /usr/share/nginx/html - name: debian-container image: debian volumeMounts: - name: shared-data mountPath: /pod-data command: - /bin/sh args: - '-c' - echo Hello from the debian container > /pod-data/index.html
Sidecar
Sidecar是容器设计模式里最常用 的模式 Sidecar:在一个Pod中,启动一个辅助容器 ,来完成一些独立于主容器(进程) 之外的工作
所有Init Container 都会比spec.containers定义的用户容器先启动 ,并且有序 ,直到都启动并且退出 后,用户容器才会启动
跟进程页表 (虚拟内存->物理内存)的原理比较类似
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 apiVersion: v1 kind: Pod metadata: name: javaweb-2 spec: initContainers: - image: 'geektime/sample:v2' name: war command: - cp - /sample.war - /app volumeMounts: - mountPath: /app name: app-volume containers: - image: 'geektime/tomcat:7.0' name: tomcat command: - sh - '-c' - /root/apache-tomcat-7.0.42-v2/bin/start.sh volumeMounts: - mountPath: /root/apache-tomcat-7.0.42-v2/webapps name: app-volume ports: - containerPort: 8080 hostPort: 8001 volumes: - name: app-volume emptyDir: {}
Pod的本质
虚拟机 vs 容器
运行在虚拟机里的应用,都是被systemd或者supervisord管理的一组进程
容器的本质是进程
Pod的本质 – 机器
Pod相当于虚拟机,容器相当于在虚拟机里运行的程序
因此,凡事调度 、网络 、存储 、安全 、容器的Linux Namespace 相关的属性,都是Pod级别 的
Pod对象 基本概念 NodeSelector Pod永远只能运行在携带disktype: ssd
标签(Label)的节点上,否则调度失败
1 2 3 4 5 6 apiVersion: v1 kind: Pod ... spec: nodeSelector: disktype: ssd
NodeName
一旦Pod对象的NodeName被赋值,Kubernetes会认为该Pod已经经过调度 ,调度的结果为赋值的节点名字
该字段一般由调度器 负责设置
HostAliases 定义Pod的hosts文件
1 2 3 4 5 6 7 8 9 10 apiVersion: v1 kind: Pod ... spec: hostAliases: - ip: "10.1.2.3" hostnames: - "foo.remote" - "bar.remote" ...
1 2 3 4 5 6 7 cat /etc/hosts # Kubernetes-managed hosts file. 127.0.0.1 localhost ... 10.244.135.10 hostaliases-pod 10.1.2.3 foo.remote 10.1.2.3 bar.remote
Linux Namespace PID Namespace
shareProcessNamespace=true
:Pod里的容器要共享PID Namespace
tty+stdin
等同于docker run -it
tty:Linux给用户提供的常驻小程序,用于接收用户的标准输入,返回操作系统的标准输出
stdin:在tty中输入信息
nginx.yaml 1 2 3 4 5 6 7 8 9 10 11 12 13 apiVersion: v1 kind: Pod metadata: name: nginx spec: shareProcessNamespace: true containers: - name: nginx image: nginx - name: shell image: busybox stdin: true tty: true
1 2 3 4 5 6 # kubectl apply -f nginx.yaml pod/nginx created # kubectl get pods NAME READY STATUS RESTARTS AGE nginx 2/2 Running 0 39s
连接到shell容器的tty上,可以看到nginx容器的进程、Infra容器的/pause进程
1 2 3 4 5 6 7 8 9 10 11 12 # kubectl attach -it nginx -c shell / # ps ax PID USER TIME COMMAND 1 root 0:00 /pause 9 root 0:00 nginx: master process nginx -g daemon off; 39 101 0:00 nginx: worker process 40 101 0:00 nginx: worker process 41 root 0:00 sh 47 root 0:00 ps ax # kubectl delete -f nginx.yaml pod "nginx" deleted
共享宿主机的Namespace Pod里的所有容器共享宿主机的Network、IPC、和PID Namespace
host.yaml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 apiVersion: v1 kind: Pod metadata: name: nginx spec: hostNetwork: true hostIPC: true hostPID: true containers: - name: nginx image: nginx - name: shell image: busybox stdin: true tty: true
1 2 3 4 5 6 7 8 9 10 11 12 13 # kubectl apply -f host.yaml pod/nginx created # kubectl get pods NAME READY STATUS RESTARTS AGE nginx 2/2 Running 0 10s # kubectl attach -it nginx -c shell / # hostname worker # kubectl delete -f host.yaml pod "nginx" deleted
Containers
Kubernetes对Container的定义,与Docker相比并没有太大区别 常用:image、command、workingDir、ports、volumeMounts
ImagePullPolicy
Always (默认值):每次创建Pod 都重新拉取一次镜像,当镜像为nginx 或者nginx:latest ,ImagePullPolicy会被认为Always
Never/IfNotPresent :Pod不会主动拉取镜像,只有在宿主机上不存在该镜像时才拉取
Lifecycle
定义Container Lifecycle Hooks
postStart
容器启动后,立即执行 一个指定的操作
postStart启动时,ENTRYPOINT可能还没结束
如果postStart执行超时 或者错误 ,Pod的Events 会记录相关错误信息,Pod也处于失败 的状态
preStop – 同步
时机:容器被杀死之前(如收到SIGKILL 信号)
优雅退出 :preStop的执行是同步 的,阻塞当前容器的杀死流程,直到Hook执行完成后,才允许容器被杀死
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 apiVersion: v1 kind: Pod metadata: name: lifecycle-demo spec: containers: - name: lifecycle-demo-container image: nginx lifecycle: postStart: exec: command: - /bin/sh - '-c' - echo Hello from the postStart handler > /usr/share/message preStop: exec: command: - /usr/sbin/nginx - '-s' - quit
Pod的生命周期
pod.status.phase Pod对象的Status字段,可以细分出一组Conditions(PodScheduled、Ready、Initialized、Unschedulable) Conditions主要用于描述造成当前Status的具体原因 ,如Status=Pending,Condition=Unschedulable Ready:Pod已经正常启动(Running),并且已经可以对外提供服务
Pending
Pod的YAML文件已经提交 给Kubernetes,API Object已经被创建并保存在Etcd中
但由于Pod里有些容器由于某种原因不能被顺利创建 (如调度失败)
Running
Pod已经调度成功 ,跟一个具体的节点绑定
Pod所包含的容器都已经创建成功,并且至少有一个正在运行中
Succeeded
Pod里所有容器都正常运行完毕 ,并且已经退出
在运行一次性 任务时最为常见
Failed
Pod里至少有一个容器以不正常(非0返回码 )退出
此时需要Debug,查看Pod的Events 和日志
Unknown
异常状态,Pod的状态不能持续地被kubelet汇报 给kube-apiserver
最有可能的原因:主从节点间的通信出现了问题
使用进阶 Projected Volume
作用:为容器提供预先定义好的数据 ,在容器看来,这些Volume里的信息就是被Kubernetes投射 (Project)进容器的
Secret
将Pod要访问的加密数据 存放到Etcd 中,然后通过在Pod的容器里挂载Volume 的方式来访问Secret里保存的信息 典型使用场景:存放数据库 的Credential 信息
secret.yaml secret.yaml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 apiVersion: v1 kind: Pod metadata: name: test-projected-volume spec: containers: - name: test-secret-volume image: busybox args: - sleep - '86400' volumeMounts: - name: mysql-cred mountPath: /projected-volume readOnly: true volumes: - name: mysql-cred projected: sources: - secret: name: user - secret: name: pass
创建Secret 命令行 1 2 3 4 5 # cat username.txt admin # cat password.txt c1oudc0w!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # kubectl get secrets NAME TYPE DATA AGE default-token-6nzkh kubernetes.io/service-account-token 3 4d19h # kubectl create secret generic user --from-file=./username.txt secret/user created # kubectl create secret generic pass --from-file=./password.txt secret/pass created # kubectl get secrets NAME TYPE DATA AGE default-token-6nzkh kubernetes.io/service-account-token 3 4d19h pass Opaque 1 5s user Opaque 1 10s
YAML 通过YAML文件创建的Secret对象只有一个,但在data字段可以用KV格式 保存两份Secret数据(Base64编码,编码 != 加密 )
1 2 3 4 5 # echo -n 'admin' | base64 YWRtaW4= # echo -n '1f2d1e2e67df' | base64 MWYyZDFlMmU2N2Rm
mysecret.yaml 1 2 3 4 5 6 7 8 apiVersion: v1 kind: Secret metadata: name: mysecret type: Opaque data: user: YWRtaW4= pass: MWYyZDFlMmU2N2Rm
1 2 3 4 5 6 7 8 9 # kubectl apply -f mysecret.yaml secret/mysecret created # kubectl get secrets NAME TYPE DATA AGE default-token-6nzkh kubernetes.io/service-account-token 3 4d19h mysecret Opaque 2 5s pass Opaque 1 60s user Opaque 1 65s
创建Pod 通过挂载 方式进入容器的Secret,一旦对应的Etcd 里的数据被更新,这些Volume 里的文件内容,同样会被更新 – kubelet 维护
1 2 3 4 5 6 7 8 9 10 11 12 13 14 # kubectl create -f secret.yaml pod/test-projected-volume created # kubectl get pods NAME READY STATUS RESTARTS AGE test-projected-volume 1/1 Running 0 8s # kubectl exec -it test-projected-volume -- /bin/sh / # ls /projected-volume/ password.txt username.txt / # cat /projected-volume/username.txt admin / # cat /projected-volume/password.txt c1oudc0w!
ConfigMap
与Secret类似,保存的是不需要加密 的、应用所需 的配置信息,用法与Secret完全相同
ui.properties ui.properties 1 2 3 4 color.good =purple color.bad =yellow allow.textmode =true how.nice.to.look =fairlyNice
创建ConfigMap 1 2 # kubectl create configmap ui-config --from-file=ui.properties configmap/ui-config created
查看ConfigMap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # kubectl get configmaps ui-config -o yaml apiVersion: v1 data: ui.properties: | color.good=purple color.bad=yellow allow.textmode=true how.nice.to.look=fairlyNice kind: ConfigMap metadata: creationTimestamp: "2021-06-14T09:34:18Z" name: ui-config namespace: default resourceVersion: "155630" uid: 83119647-5db5-4611-b7f7-71a414ab10fe
Downward API
让Pod里的容器 能够直接获取到这个Pod API对象本身的信息 Downward API能获取到的信息,一定是Pod里的容器进程启动之前 就能确定下来的信息
Pod的Labels字段的值,被Kubernetes自动挂载成为容器里**/etc/podinfo/labels
**文件
downward_api.yaml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 apiVersion: v1 kind: Pod metadata: name: test-downwardapi-volume labels: zone: us-est-coast cluster: test-cluster1 rack: rack-22 spec: containers: - name: client-container image: k8s.gcr.io/busybox command: - sh - '-c' args: - >- while true; do if [[ -e /etc/podinfo/labels ]]; then echo -en '\n\n'; cat /etc/podinfo/labels; fi; sleep 5; done; volumeMounts: - name: podinfo mountPath: /etc/podinfo readOnly: false volumes: - name: podinfo projected: sources: - downwardAPI: items: - path: labels fieldRef: fieldPath: metadata.labels
1 2 3 4 5 6 7 # kubectl apply -f downward_api.yaml pod/test-downwardapi-volume created # kubectl logs test-downwardapi-volume cluster="test-cluster1" rack="rack-22" zone="us-est-coast"
支持的字段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 1. 使用 fieldRef 可以声明使用: spec.nodeName - 宿主机名字 status.hostIP - 宿主机 IP metadata.name - Pod 的名字 metadata.namespace - Pod 的 Namespace status.podIP - Pod 的 IP spec.serviceAccountName - Pod 的 Service Account 的名字 metadata.uid - Pod 的 UID metadata.labels['<KEY>'] - 指定 <KEY> 的 Label 值 metadata.annotations['<KEY>'] - 指定 <KEY> 的 Annotation 值 metadata.labels - Pod 的所有 Label metadata.annotations - Pod 的所有 Annotation 2. 使用 resourceFieldRef 可以声明使用: 容器的 CPU limit 容器的 CPU request 容器的 memory limit 容器的 memory request
ServiceAccountToken
作用:Kubernetes内置的一种服务账号 ,Service Account是Kubernetes进行权限分配 的对象 样例:Service Account A只允许对Kubernetes API进行GET操作,Service Account B有Kubernetes API所有操作的权限 Service Account的授权信息和文件 ,实际上保存在它所绑定的特殊的Secret对象 里,称为ServiceAccountToken ServiceAccountToken是一种特殊的Secret
任何运行在Kubernetes集群上的应用,都必须使用ServiceAccountToken里保存的授权信息,才能合法地访问API Server
为了方便使用,Kubernetes提供默认的服务账号(Default Service Account ),Pod可以直接使用 ,无需显式声明挂载
InClusterConfig (推荐):Kubernetes客户端以容器 的方式运行在集群里,然后使用Default Service Account自动授权
默认的ServiceAccountToken存在潜在风险,可以设置默认不为Pod里的容器自动挂载这个Volume
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 # kubectl get pods NAME READY STATUS RESTARTS AGE nginx-deployment-75f76dcfd9-29d8t 1/1 Running 0 8s nginx-deployment-75f76dcfd9-6xv8q 1/1 Running 0 8s nginx-deployment-75f76dcfd9-cn4j9 1/1 Running 0 8s nginx-deployment-75f76dcfd9-xnv5m 1/1 Running 0 8s # kubectl describe pod nginx-deployment-75f76dcfd9-29d8t ... Containers: nginx: ... Mounts: /usr/share/nginx/html from nginx-vol (rw) /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-gnrc9 (ro) ... Volumes: ... kube-api-access-gnrc9: Type: Projected (a volume that contains injected data from multiple sources) TokenExpirationSeconds: 3607 ConfigMapName: kube-root-ca.crt ConfigMapOptional: <nil> DownwardAPI: true ... # kubectl exec -it nginx-deployment-75f76dcfd9-29d8t -- /bin/sh # ls /var/run/secrets/kubernetes.io/serviceaccount ca.crt namespace token # cat ls /var/run/secrets/kubernetes.io/serviceaccount/token cat: ls: No such file or directory eyJhbGciOiJSUzI1NiIsImtpZCI6Ik1LUW9LbmI5dGh2djdfS29JNElKLXl0MzZHbTR5azRTOHdxZ3dxZk5qV3cifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNjU1MjA2ODQ2LCJpYXQiOjE2MjM2NzA4NDYsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0IiwicG9kIjp7Im5hbWUiOiJuZ2lueC1kZXBsb3ltZW50LTc1Zjc2ZGNmZDktMjlkOHQiLCJ1aWQiOiIzMmM3ZjViYS0zY2JkLTQyOTktYTdiOC01ZTUwNGNmMzI1YTcifSwic2VydmljZWFjY291bnQiOnsibmFtZSI6ImRlZmF1bHQiLCJ1aWQiOiIwMWUxZDljMy1hMjkzLTQzOWItODkwMC05YzFjNjZlOWUzM2IifSwid2FybmFmdGVyIjoxNjIzNjc0NDUzfSwibmJmIjoxNjIzNjcwODQ2LCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDpkZWZhdWx0In0.Bjt3hILB6kxh5mF7TA8QN1TVMbg4PQqEmtOio3osBzVnP97Xrquf-LohVVK2vPa9RrnECiv-hKOvu-U5uFihj2_-7xBRIAOGDsdEOnVaDbmE3iB75zsNOHG5i9dbHMYyuA6eOCdkJLA9mewDNDJQHwTfrKQRevFNIVzRYfHozlRmAyeuz8iA9SOwPfsRl19rb18qb4RA4_-chEk4aGHJxbC8HMMjB-rVQRtvhoxe95r0bQP9XE9BTjlstXk-wFTGPivDcXaTrE3UPRzSD_mLOB9qRV3JtsnfMqQ7YFMDHH2pAq_hFERPx6sz8XS3D4R5gJWxql42YeLX3YTbonay3Q
Liveness
在Kubernetes中,可以为Pod里的容器定义一个健康检查的Probe ,kubelet会根据该Probe的返回值决定容器的状态
liveness.yaml liveness.yaml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 apiVersion: v1 kind: Pod metadata: labels: test: liveness name: test-liveness-exec spec: containers: - name: liveness image: busybox args: - /bin/sh - '-c' - touch /tmp/healthy; sleep 30 ; rm -rf /tmp/healthy; sleep 600 livenessProbe: exec: command: - cat - /tmp/healthy initialDelaySeconds: 5 periodSeconds: 5
创建Pod 1 2 3 4 5 6 # kubectl apply -f liveness.yaml pod/test-liveness-exec created # kubectl get pods NAME READY STATUS RESTARTS AGE test-liveness-exec 1/1 Running 0 12s
查看Pod的Events 容器刚启动的时候,报告容器为**Unhealthy
**(由于Liveness probe failed)
1 2 3 4 5 6 7 8 9 10 11 12 13 # kubectl describe pod test-liveness-exec ... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 2m default-scheduler Successfully assigned default/test-liveness-exec to worker Normal Pulled 114s kubelet Successfully pulled image "busybox" in 5.71826124s Normal Killing 70s kubelet Container liveness failed liveness probe, will be restarted Normal Pulling 40s (x2 over 119s) kubelet Pulling image "busybox" Normal Pulled 37s kubelet Successfully pulled image "busybox" in 3.755658619s Normal Created 36s (x2 over 113s) kubelet Created container liveness Normal Started 36s (x2 over 113s) kubelet Started container liveness Warning Unhealthy 0s (x5 over 80s) kubelet Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
查看Pod的状态
Pod的状态为Running ,而非Failed,RESTARTS为3说明了已经被Kubernetes重启 了,该过程Pod保持Running状态不变
Kubernetes中没有Docker的Stop语义 ,重启代表着重新创建容器 ,该功能称为Kubernetes的RestartPolicy (Pod恢复 机制)
Pod的READY 字段:表示Pod里正常容器 的个数1 2 3 # kubectl get pod test-liveness-exec NAME READY STATUS RESTARTS AGE test-liveness-exec 1/1 Running 3 4m23s
RestartPolicy
pod.spec.restartPolicy (标准字段)
Always (默认值):在任何情况下,只要容器不在运行状态 ,就自动重启容器
OnFailure :只在容器异常 时才自动重启容器
Never :从来不重启容器
基本的设计原理
只要restartPolicy允许重启异常的容器 (Always+OnFailure),那么这个Pod会保持Running状态 (否则进入Failed状态)
包含多个容器 的Pod,只有里面所有的容器都进入异常状态 后,Pod才会进入Failed状态 (在此之前,都是Running状态)
Pod & Node
Pod的恢复过程,永远发生在当前Node上 ,不会跑到别的Node上
一旦一个Pod与一个Node绑定 ,除非绑定发生变化,否则永远不会离开该Node,哪怕Node宕机 ,该Pod也不会主动迁移
如果想让Pod出现在其它Node上,必须使用Deployment来管理Pod (哪怕只需要一个Pod副本)
Liveness Probe
除了可以在容器中执行命令外,livenessProbe还可以定义为发起HTTP 或者TCP 请求的方式(Web服务类)
1 2 3 4 5 6 7 8 9 10 ... livenessProbe: httpGet: path: /healthz port: 8080 httpHeaders: - name: X-Custom-Header value: Awesome initialDelaySeconds: 3 periodSeconds: 3
1 2 3 4 5 6 ... livenessProbe: tcpSocket: port: 8080 initialDelaySeconds: 15 periodSeconds: 20
readinessProbe vs livenessProbe
readinessProbe检查结果的成功与否,决定该Pod是不是能被通过Service的方式访问到 ,并不影响Pod的生命周期
PodPreset
PodPreset定义的内容,只会在Pod API对象被创建之前 追加在这个对象本身,不会影响任何Pod控制器的定义 例如:Deployment对象本身永远不会被PodPreset改变,被修改的只是这个Deployment创建出来的所有Pod 如果定义了同时作用于同一个Pod对象的多个PodPreset,Kubernetes会尝试合并修改,冲突字段不会被修改
pod.yaml pod.yaml 1 2 3 4 5 6 7 8 9 10 11 12 13 apiVersion: v1 kind: Pod metadata: name: website labels: app: website role: frontend spec: containers: - name: website image: nginx ports: - containerPort: 80
preset.yaml 追加的定义只会作用在带有role: frontend
标签的Pod对象
preset.yaml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 apiVersion: settings.k8s.io/v1alpha1 kind: PodPreset metadata: name: allow-database spec: selector: matchLabels: role: frontend env: - name: DB_PORT value: '6379' volumeMounts: - mountPath: /cache name: cache-volume volumes: - name: cache-volume emptyDir: {}
创建PodPreset和Pod 自动添加annotation,表示该Pod对象被PodPreset改动过
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 # kubectl apply -f preset.yaml # kubectl apply -f pod.yaml # kubectl get pod website -o yaml apiVersion: v1 kind: Pod metadata: name: website labels: app: website role: frontend annotations: podpreset.admission.kubernetes.io/podpreset-allow-database: resource version spec: containers: - name: website image: nginx volumeMounts: - mountPath: /cache name: cache-volume ports: - containerPort: 80 env: - name: DB_PORT value: '6379' volumes: - name: cache-volume emptyDir: {}
参考资料
深入剖析Kubernetes