本文主要用来学习Pod,参考文章Overview,Static Pod.
Pod为K8S中最小的执行单位以及部署单位,代表运行在cluster上的processes。Pod中封装了container,存储,网络IP以及container如何运行的资源和信息。
Docker是Pod中最常用的container runtime,也支持其他container runtime.
Pod中的containers共享其中的storage和network。
- 每个Pod有一个unique IP, Pod中的container共享network namespace,包括IP和Port。Pod中的container之间使用localhost进行交互,与外部交互注意分配不同Port。
- Pod中的container之间可以共享存储空间。
注意:若Pod设置hostPort时,同一个host上只能启动一个Pod副本。若设置hostNetwork为true表示使用主机网络,不再使用Docker网桥,同一个host上只能启动一个Pod副本。
- Pod Phase
Pod phase包含下面5个状态:
-Container State
Container包括下面3个state:
-
Waiting
默认的state,处于pull image或apply secret阶段就处于该状态; -
Running
表示container正在正常运行; -
Terminated
表示container执行完毕,停止执行。当container执行成功或执行失败时进入该状态;
-Image Pull Policy
Image Pull Policy有3种:Always, Never,IfNotPresent,默认为Always。Always表示每次都尝试重新拉取镜像;IfNotPresent表示本地不存在镜像时才拉取镜像;Never表示仅使用本地镜像
-Restart Policy
Restart Policy有3种:Always, OnFailure, and Never,该policy应用于Pod中的所有container,默认为Always。在5分钟内按照指数后退规则的时间间隔重启并在启动成功10分钟后重设。
RC和DaemonSet中必须设置为Always,保证容器持续运行;Job可设置为OnFailure或Never确保容器执行完成后不再启动。
-Pod Probe
Probe可以使用命令行或http get来检测container的状态,返回Success, Failure, Unknown。命令行返回0表示健康,http方式返回状态码[200,400)表示健康。
有3种类型的Probe:
- livenessProbe 用来判断container是不是处于running,若失败,删除container。若不提供,默认为Success
- readinessProbe 判断container是否可用于service requests,若失败,将Pod's IP address从所有service的endpoint中删除。初始的默认为Failure,若不提供,默认为Success
- startupProbe 判断container中的app是否已经启动,当提供该probe,在其成功之前,其他probe被disabled,若失败,删除container。若不提供,默认为Success
下面是使用livenessProbe的示例:
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-http
spec:
containers:
- args:
- /server
image: k8s.gcr.io/liveness
livenessProbe:
httpGet:
# when "host" is not defined, "PodIP" will be used
# host: my-host
# when "scheme" is not defined, "HTTP" scheme will be used. Only "HTTP" and "HTTPS" are allowed
# scheme: HTTPS
path: /healthz
port: 8080
httpHeaders:
- name: X-Custom-Header
value: Awesome
initialDelaySeconds: 15
timeoutSeconds: 1
name: liveness
-Init Containers
Pod中的init containers在app containers之前执行,可以是一些工具以及启动脚本。
Init containers可以包含多个,特点是:1. init containers必须能够complete;2. init containers依次执行,前面的执行成功才会执行后面的container; 3.不支持readiness probes;
下面是使用init container的示例,2个init container分别等待service启动。
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox:1.28
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: init-myservice
image: busybox:1.28
command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
- name: init-mydb
image: busybox:1.28
command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
当Pod重启时,所有的init containers都会重新执行。Init container的修改只能修改其image field,而且修改完后,Pod会重新启动。同时,由于init containers会被重启,重试和重新执行,所以init container的code必须是可重入的。
-Pod Preset
PodPresets是一种Object,在Pod创建时插入一些info,这些info可能是secrets, volumes, volume mounts, and environment variables。
使用label selectors来确定Pod Preset会被哪些Pod使用。
使用机制如下:1.获取所有可用的PodPreset;2.检查Pod的label来获取被使用的PodPreset;3.将PodPreset的资源merge到Pod中;4.若合并失败,Pod创建时将不合并这些PodPreset,但会抛出event来说明;5.若合并成功,Pod中添加annotation来表示使用了哪些PodPreset。
一个Pod可用同时使用多个PodPreset,同时一个PodPreset也可用被多个Pod使用。PodPreset被修改后,所有使用它的Pod自动更新。
当不想在Pod中使用PodPreset时,在Pod Spec中添加podpreset.admission.kubernetes.io/exclude: "true"
。
使用PodPreset需要下面的设置:
- 开启该API TYPE
settings.k8s.io/v1alpha1/podpreset
,需要在api server的--runtime-config
中添加settings.k8s.io/v1alpha1=true
; - 开启
PodPrese
,在API server的--enable-admission-plugins
中添加PodPreset
; - 在namespace中创建PodPreset;
下面是PodPreset的示例:
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将会被所有具有label role:frontend的Pod使用。
-Static Pod
Static Pod被kubelet daemon在指定node上直接管理,API Server并不管理Static Pod。kubelet自动在API Server上为static pod创建mirror pod,因此,API Server感知static pod的存在但不管理。
有2种方式来创建static pod:主机文件方式,网络文件方式。
主机文件方式:
- 在Node的Path中创建pod的yaml文件,如:
/etc/kubelet.d/static-web.yaml
mkdir /etc/kubelet.d/
cat <<EOF >/etc/kubelet.d/static-web.yaml
apiVersion: v1
kind: Pod
metadata:
name: static-web
labels:
role: myrole
spec:
containers:
- name: web
image: nginx
ports:
- name: web
containerPort: 80
protocol: TCP
EOF
- 设置kubelet的
--pod-manifest-path=/etc/kubelet.d/
并重启kubelet
systemctl restart kubelet
网络文件方式:
同样在web server上创建pod的yaml文件,然后如下设置kubelet的参数并重启kubelet。
--manifest-url=<manifest-url>
当使用kubectl delete静态pod时,kubelet并不会删除static pod,使其为Pending状态。
kubelet会周期性的扫描指定的目录来动态增加和删除static pod。
-Downward API
有些集群中,每个Node需要将自己的ID和进程绑定的IP地址等信息事先写入到配置文件中,进程在启动时读取这些配置文件并将信息发布到类似服务注册中心的地方,以实现集群Node的自动发现功能。此时,可以使用Downward API来实现,创建init container通过环境变量或文件获得Pod自身的名称、IP地址等信息并将信息写入主程序的配置文件中,最后启动主程序。
Downward API使得Pod容器内可以获得Pod的信息,可以通过环境变量和volume挂载的方式实现。
环境变量方式:
spec:
containers:
-name: test-container
image: busybox
command: ["/bin/bash", "-c", "env"]
- name: MY_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: MY_POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: MY_POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: MY_CPU_REQUEST
valueFrom:
resourceFieldRef:
containerName: test-container
resource: requests.cpu
volume挂载方式:
spec:
containers:
volumeMounts:
- name: podinfo
mountPath: /etc
readOnly: false
volumes:
- name: podinfo
downwardAPI:
items:
- path: "lables"
fieldRef:
fieldPath: metadata.labels
K8s对长时间运行的容器的要求:其主程序需要一直在前台运行。若主程序运行在后台,创建Pod后会认为Pod执行完毕,从而立即销毁该Pod。
Replication Controller的标签选择器只能选择一个标签,而ReplicaSet拥有集合式的标签选择器。