Kubernetes Pod概述
Pod简介
Pod是Kubernetes创建或部署的最小/最简单的基本单位,一个Pod代表集群上正在运行的一个进程。
一个Pod封装一个应用容器,Pod代表部署的一个单位。
Pods提供两种共享资源:网络和存储。
网络:每个Pod被分配一个独立的IP地址,Pod中的每个容器共享网络命名空间,包括IP地址和网络端口。
存储:Pod可以指定一组共享存储volumes。Pod中的所有容器都可以访问共享volumes,允许这些容器共享数据。
Pod不会自愈。如果Pod运行的Node故障,或者是调度器本身故障,这个Pod就会被删除。同样的,如果Pod所在Node缺少资源或者Pod处于维护状态,Pod也会被驱逐。Controller可以创建和管理多个Pod,提供副本管理、滚动升级和集群级别的自愈能力。例如,如果一个Node故障,Controller就能自动将该节点上的Pod调度到其他健康的Node上。
POD生命周期
Pod 的 status 定义在 PodStatus 对象中,其中有一个 phase 字段。
- 挂起(Pending):Pod 已被 Kubernetes 系统接受,但有一个或者多个容器镜像尚未创建。等待时间包括调度 Pod 的时间和通过网络下载镜像的时间,这可能需要花点时间。
- 运行中(Running):该 Pod 已经绑定到了一个节点上,Pod 中所有的容器都已被创建。至少有一个容器正在运行,或者正处于启动或重启状态。
- 成功(Succeeded):Pod 中的所有容器都被成功终止,并且不会再重启。
- 失败(Failed):Pod 中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出或者被系统终止。
- 未知(Unknown):因为某些原因无法取得 Pod 的状态,通常是因为与 Pod 所在主机通信失败。
容器存活探针,健康检查
探针 是由 kubelet 对容器执行的定期诊断。要执行诊断,kubelet 调用由容器实现的 Handler。
- ExecAction:在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。
- TCPSocketAction:对指定端口上的容器的 IP 地址进行 TCP 检查。如果端口打开,则诊断被认为是成功的。
- HTTPGetAction:对指定的端口和路径上的容器的 IP 地址执行 HTTP Get 请求。如果响应的状态码大于等于200 且小于 400,则诊断被认为是成功的。
livenessProbe:探测应用是否处于健康状态,如果不健康则删除重建改容器
readinessProbe:探测应用是否启动完成并且处于正常服务状态,如果不正常则更新容器的状态
apiVersion: v1
kind: Pod
metadata:
labels:
app: nginx
name: nginx
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: http
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 15
timeoutSeconds: 1
readinessProbe:
httpGet:
path: /ping
port: 80
initialDelaySeconds: 5
timeoutSeconds: 1
诊断结果状态:
- 成功:容器通过了诊断。
- 失败:容器未通过诊断。
- 未知:诊断失败,因此不会采取任何行动。
初始化容器
Init Container在所有容器运行之前执行(run-to-completion),常用来初始化配置。
apiVersion: v1
kind: Pod
metadata:
name: init-demo
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: workdir
mountPath: /usr/share/nginx/html
# These containers are run during pod initialization
initContainers:
- name: install
image: busybox
command:
- wget
- "-O"
- "/work-dir/index.html"
- http://kubernetes.io
volumeMounts:
- name: workdir
mountPath: "/work-dir"
dnsPolicy: Default
volumes:
- name: workdir
emptyDir: {}
重启策略
PodSpec 中有一个 restartPolicy 字段,可能的值为 Always、OnFailure 和 Never。默认为 Always,意味着容器在探测失败时被杀死并重新启动。
- Always:只要退出就重启
- OnFailure:失败退出(exit code不等于0)时重启
- Never:只要退出就不再重启
这里的重启是指在Pod所在Node上面本地重启,并不会调度到其他Node上去。
ImagePullPolicy
支持三种ImagePullPolicy
- Always:不管镜像是否存在都会进行一次拉取。
- Never:不管镜像是否存在都不会进行拉取
- IfNotPresent:只有镜像不存在时,才会进行镜像拉取。
注意: - 默认为IfNotPresent,但:latest标签的镜像默认为Always。
- 拉取镜像时docker会进行校验,如果镜像中的MD5码没有变,则不会拉取镜像数据。
- 生产环境中应该尽量避免使用:latest标签,而开发环境中可以借助:latest标签自动拉取最新的镜像。
指定Node部署
通过nodeSelector,一个Pod可以指定它所想要运行的Node节点。
首先给Node加上标签:
$ kubectl label nodes <your-node-name> disktype=ssd
接着,指定该Pod只想运行在带有disktype=ssd标签的Node上:
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd
给容器和Pod分配内存资源
配置内存申请和限制
memory-request-limit.yaml
apiVersion: v1
kind: Pod
metadata:
name: memory-demo
spec:
containers:
- name: memory-demo-ctr
image: vish/stress
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"
args:
- -mem-total
- 150Mi
- -mem-alloc-size
- 10Mi
- -mem-alloc-sleep
- 1s
创建一个容器的Pod,这个容器申请100M的内存,并且内存限制设置为200M,args代码段提供了容器所需的参数。-mem-total 150Mi告诉容器尝试申请150M 的内存。
在mem-example命名空间中创建pod:
# kubectl create -f memory-request-limit.yaml --namespace=mem-example
验证Pod的容器是否正常运行:
# kubectl get pod memory-demo --namespace=mem-example
查看Pod的详细信息:
# kubectl get pod memory-demo --output=yaml --namespace=mem-example
-----------------
...
resources:
limits:
memory: 200Mi
requests:
memory: 100Mi
...
POD实际使用内存约为150M。
删除Pod:
# kubectl delete pod memory-demo --namespace=mem-example
当创建POD时内存超出限制内存,则POD会被kill掉,reason: OOMKilled。
当创建POD时内存超出节点能力范围时,Pod的状态是Pending,因为Pod不会被调度到任何节点,它会一直保持在Pending状态下,因为节点上没有足够的内存。
如果没有内存限制,则容器使用内存资源没有上限,容器可以使用当前节点上所有可用的内存资源。
给容器和Pod分配CPU资源
给容器声明CPU限制
cpu-request-limit.yaml
apiVersion: v1
kind: Pod
metadata:
name: cpu-demo
spec:
containers:
- name: cpu-demo-ctr
image: vish/stress
resources:
limits:
cpu: "1"
requests:
cpu: "0.5"
args:
- -cpus
- "2"
会创建一个只有一个容器的Pod,这个容器申请0.5个CPU,并且CPU限制设置为1. cpus "2"代码告诉容器尝试使用2个CPU资源。
在cpu-example命名空间中创建pod:
# kubectl create -f cpu-request-limit.yaml --namespace=cpu-example
验证Pod的容器是否正常运行:
# kubectl get pod cpu-demo --namespace=cpu-example
查看Pod的详细信息:
# kubectl get pod cpu-demo --output=yaml --namespace=cpu-example
--------------
resources:
limits:
cpu: "1"
requests:
cpu: 500m
当创建的pod申请的CPU资源超过集群node所提供的资源,那么pod会一直处于Pending状态,那是因为这个Pod并不会被调度到任何节点上,所以它会一直保持这种状态。
如果你指定容器的CPU限额,则容器使用CPU资源没有上限,它可以使用它运行的Node上所有的CPU资源。
通过环境变量向容器暴露 Pod 信息
使用 Pod 字段作为环境变量的值
dapi-envars-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: dapi-envars-fieldref
spec:
containers:
- name: test-container
image: k8s.gcr.io/busybox
command: [ "sh", "-c"]
args:
- while true; do
echo -en '\n';
printenv MY_NODE_NAME MY_POD_NAME MY_POD_NAMESPACE;
printenv MY_POD_IP MY_POD_SERVICE_ACCOUNT;
sleep 10;
done;
env:
- name: MY_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- 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_POD_SERVICE_ACCOUNT
valueFrom:
fieldRef:
fieldPath: spec.serviceAccountName
restartPolicy: Never
env 字段是 EnvVars 的数组。数组中的第一个元素指定 MY_NODE_NAME 环境变量从 Pod 的 spec.nodeName 字段中获取其值。字段是 Pod 的字段,不是 Pod 中的容器的字段。
创建pod:
# kubectl create -f dapi-envars-pod.yaml
查看容器日志:
# kubectl logs dapi-envars-fieldref
-------------
minikube
dapi-envars-fieldref
default
172.17.0.48
default
配置文件的 command 和 args 字段。当容器启动时,它将 5 个环境变量的值写到标准输出中。每十秒钟重复一次。
进入容器内查看环境变量:
MY_POD_SERVICE_ACCOUNT=default
...
MY_POD_NAMESPACE=default
MY_POD_IP=172.17.0.4
...
MY_NODE_NAME=minikube
...
MY_POD_NAME=dapi-envars-fieldref
使用容器字段作为环境变量的值
dapi-envars-container.yaml
apiVersion: v1
kind: Pod
metadata:
name: dapi-envars-resourcefieldref
spec:
containers:
- name: test-container
image: k8s.gcr.io/busybox:1.24
command: [ "sh", "-c"]
args:
- while true; do
echo -en '\n';
printenv MY_CPU_REQUEST MY_CPU_LIMIT;
printenv MY_MEM_REQUEST MY_MEM_LIMIT;
sleep 10;
done;
resources:
requests:
memory: "32Mi"
cpu: "125m"
limits:
memory: "64Mi"
cpu: "250m"
env:
- name: MY_CPU_REQUEST
valueFrom:
resourceFieldRef:
containerName: test-container
resource: requests.cpu
- name: MY_CPU_LIMIT
valueFrom:
resourceFieldRef:
containerName: test-container
resource: limits.cpu
- name: MY_MEM_REQUEST
valueFrom:
resourceFieldRef:
containerName: test-container
resource: requests.memory
- name: MY_MEM_LIMIT
valueFrom:
resourceFieldRef:
containerName: test-container
resource: limits.memory
restartPolicy: Never
env 字段是 EnvVars 的数组。数组中的第一个元素指定 MY_CPU_REQUEST 环境变量从名为 test-container 的容器的 requests.cpu 字段中获取其值。类似地,其他环境变量从容器字段中获取它们的值。
创建pod,查看pod日志:
# kubectl create -f dapi-envars-container.yaml
# kubectl logs dapi-envars-resourcefieldref
--------------
1
1
33554432
67108864