容器编排 -- Pod

基本概念

  1. 在Kubernetes中,Pod是一等公民
  2. Pod是Kubernetes的原子调度单位,Kubernetes统一按照Pod(而非容器)的资源需求进行计算
  3. 容器的本质是进程
  4. 容器的单进程模型
    • 并不是指容器里只能运行一个进程,而是指容器没有管理多个进程的能力
    • 原因
      • 容器里PID=1的进程是应用本身,其它进程都是PID=1进程的子进程
      • 用户编写的应用,并不能像正常OS里面的init进程或者systemd进程那样拥有进程管理的功能
  5. 容器间具有『超亲密关系』的典型特征
    • 互相之间会发生直接的文件交换
    • 使用localhost或者Socket文件进行本地通信
    • 会发生非常频繁的远程调用
    • 需要共享某些Linux Namespace
  6. 并不是所有有关系的容器都属于同一个Pod,如Java应用容器和MySQL更适合做成两个Pod
  7. Pod在Kubernetes中的重要意义 – 容器设计模式

实现原理

  1. Pod只是一个逻辑概念
    • Kubernetes真正处理的,还是宿主机上Linux容器的Namespace和Cgroups,并不存在所谓的Pod的边界或者隔离环境
  2. Pod里的所有容器,共享的是同一个Network Namespace,并且可以声明共享同一个Volume
  3. Pod的实现会使用一个中间容器,称为Infra容器
    • Infra容器永远都是第一个被创建的容器,其它用户定义的容器,则通过Join Network Namespace,与Infra容器关联
    • Infra容器占用极少的资源,镜像为k8s.gcr.io/pause汇编语言编写,永远处于『暂停』状态)
      • Infra容器Hold住Network Namespace后,用户容器可以加入到Infra容器的Network Namespace中
  4. Pod中的容器A和容器B
    • 可以直接使用localhost进行通信
    • 看到的网络设备与Infra容器看到的完全一样
    • 一个Pod只有一个IP地址,即该Pod的Network Namespace对应的IP地址
    • 其它网络资源,一个Pod一份,可以被Pod中的所有容器共享
    • Pod的生命周期只跟Infra容器一致,与容器A和容器B无关
  5. 对于同一个Pod里面的所有用户容器来说,他们的进出流量,可以认为都是通过Infra容器完成的
    • 网络插件:不必关心用户容器启动与否,重点关注如何配置Pod(Infra容器)的Network Namespace
  6. 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中,启动一个辅助容器,来完成一些独立于主容器(进程)之外的工作

  1. 所有Init Container都会比spec.containers定义的用户容器先启动,并且有序,直到都启动并且退出后,用户容器才会启动
  2. 跟进程页表(虚拟内存->物理内存)的原理比较类似
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的本质

  1. 虚拟机 vs 容器
    • 运行在虚拟机里的应用,都是被systemd或者supervisord管理的一组进程
    • 容器的本质是进程
  2. 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

  1. 一旦Pod对象的NodeName被赋值,Kubernetes会认为该Pod已经经过调度,调度的结果为赋值的节点名字
  2. 该字段一般由调度器负责设置

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

  1. shareProcessNamespace=true:Pod里的容器要共享PID Namespace
  2. 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

  1. Always(默认值):每次创建Pod都重新拉取一次镜像,当镜像为nginx或者nginx:latest,ImagePullPolicy会被认为Always
  2. Never/IfNotPresent:Pod不会主动拉取镜像,只有在宿主机上不存在该镜像时才拉取

Lifecycle

定义Container Lifecycle Hooks

  1. postStart
    • 容器启动后,立即执行一个指定的操作
    • postStart启动时,ENTRYPOINT可能还没结束
    • 如果postStart执行超时或者错误,Pod的Events会记录相关错误信息,Pod也处于失败的状态
  2. 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),并且已经可以对外提供服务

  1. Pending
    • Pod的YAML文件已经提交给Kubernetes,API Object已经被创建并保存在Etcd中
    • 但由于Pod里有些容器由于某种原因不能被顺利创建(如调度失败)
  2. Running
    • Pod已经调度成功,跟一个具体的节点绑定
    • Pod所包含的容器都已经创建成功,并且至少有一个正在运行中
  3. Succeeded
    • Pod里所有容器都正常运行完毕,并且已经退出
    • 在运行一次性任务时最为常见
  4. Failed
    • Pod里至少有一个容器以不正常(非0返回码)退出
    • 此时需要Debug,查看Pod的Events和日志
  5. 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

  1. 任何运行在Kubernetes集群上的应用,都必须使用ServiceAccountToken里保存的授权信息,才能合法地访问API Server
  2. 为了方便使用,Kubernetes提供默认的服务账号(Default Service Account),Pod可以直接使用,无需显式声明挂载
  3. InClusterConfig(推荐):Kubernetes客户端以容器的方式运行在集群里,然后使用Default Service Account自动授权
  4. 默认的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的状态

  1. Pod的状态为Running,而非Failed,RESTARTS为3说明了已经被Kubernetes重启了,该过程Pod保持Running状态不变
  2. Kubernetes中没有Docker的Stop语义,重启代表着重新创建容器,该功能称为Kubernetes的RestartPolicy(Pod恢复机制)
  3. 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

  1. pod.spec.restartPolicy(标准字段)
    • Always(默认值):在任何情况下,只要容器不在运行状态,就自动重启容器
    • OnFailure:只在容器异常时才自动重启容器
    • Never:从来不重启容器
  2. 基本的设计原理
    • 只要restartPolicy允许重启异常的容器(Always+OnFailure),那么这个Pod会保持Running状态(否则进入Failed状态)
    • 包含多个容器的Pod,只有里面所有的容器都进入异常状态后,Pod才会进入Failed状态(在此之前,都是Running状态)

Pod & Node

  1. Pod的恢复过程,永远发生在当前Node上,不会跑到别的Node上
  2. 一旦一个Pod与一个Node绑定,除非绑定发生变化,否则永远不会离开该Node,哪怕Node宕机,该Pod也不会主动迁移
  3. 如果想让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: {}

参考资料

  1. 深入剖析Kubernetes
0%