K8S-POD详解
Pod是最小的部署单元,也是后面经常配置的地方,本章节带你熟悉Pod中常见资源配置及参数。
也就是YAML这部分:
... template: metadata: labels: app: web spec: containers: - image: a13552821243/java-demo:latest imagePullPolicy: Always name: java
6.1 Pod介绍
-
最小部署单元
-
一组容器的集合
-
一个Pod中的容器共享网络命名空间
-
6.2 Pod存在的意义
Pod为亲密性应用而存在。
亲密性应用场景:
-
两个应用之间发生文件交互
-
两个应用需要通过127.0.0.1或者socket通信
-
两个应用需要发生频繁的调用
6.3 Pod实现机制与设计模式
Pod本身是一个逻辑概念,没有具体存在,那究竟是怎么实现的呢?
众所周知,容器之间是通过Namespace隔离的,Pod要想解决上述应用场景,那么就要让Pod里的容器之间高效共享。
具体分为两个部分:网络和存储
-
共享网络
kubernetes的解法是这样的:会在每个Pod里先启动一个infra container
小容器,然后让其他的容器连接进来这个网络命名空间,然后其他容器看到的网络试图就完全一样了,即网络设备、IP地址、Mac地址等,这就是解决网络共享问题。在Pod的IP地址就是infra container的IP地址。
-
共享存储
比如有两个容器,一个是nginx,另一个是普通的容器,普通容器要想访问nginx里的文件,就需要nginx容器将共享目录通过volume挂载出来,然后让普通容器挂载的这个volume,最后大家看到这个共享目录的内容一样。
例如:
# pod.yaml apiVersion: v1 kind: Pod metadata: name: my-pod spec: containers: - name: write image: centos command: ["bash","-c","for i in {1..100};do echo $i >> /data/hello;sleep 1;done"] volumeMounts: - name: data mountPath: /data - name: read image: centos command: ["bash","-c","tail -f /data/hello"] volumeMounts: - name: data mountPath: /data volumes: - name: data emptyDir: {}
上述示例中有两个容器,write容器负责提供数据,read消费数据,通过数据卷将写入数据的目录和读取数据的目录都放到了该卷中,这样每个容器都能看到该目录。
kubectl apply -f pod.yaml kubectl logs my-pod -c read -f
在Pod中容器分为以下几个类型:
-
Infrastructure Container:基础容器,维护整个Pod网络空间,对用户不可见
-
InitContainers:初始化容器,先于业务容器开始执行,一般用于业务容器的初始化工作
-
Containers:业务容器,具体跑应用程序的镜像
apiVersion: v1 kind: Pod metadata: name: my-pod spec: containers: - name: java image: a13552821243/java-demo imagePullPolicy: IfNotPresent
imagePullPolicy 字段有三个可选值:
-
IfNotPresent:镜像在宿主机上不存在时才拉取
-
Always:默认值,每次创建 Pod 都会重新拉取一次镜像
-
Never: Pod 永远不会主动拉取这个镜像
如果拉取公开的镜像,直接按照上述示例即可,但要拉取私有的镜像,是必须认证镜像仓库才可以,即docker login,而在K8S集群中会有多个Node,显然这种方式是很不放方便的!为了解决这个问题,K8s 实现了自动拉取镜像的功能。 以secret方式保存到K8S中,然后传给kubelet。
Pod资源配额有两种:
-
申请配额:调度时使用,参考是否有节点满足该配置
spec.containers[].resources.limits.cpu
spec.containers[].resources.limits.memory
-
限制配额:容器能使用的最大配置
spec.containers[].resources.requests.cpu
spec.containers[].resources.requests.memory
示例:
apiVersion: v1 kind: Pod metadata: name: web spec: containers: - name: java image: a13552821243/java-demo resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m"
1核=1000m
1.5核=1500m
那上面限制配置就是1核的二分之一(500m),即该容器最大使用半核CPU。
该值也可以写成浮点数,更容易理解:
半核=0.5
1核=1
apiVersion: v1 kind: Pod metadata: name: my-pod spec: containers: - name: java image: a13552821243java-demo restartPolicy: Always
restartPolicy字段有三个可选值:
-
Always:当容器终止退出后,总是重启容器,默认策略。
-
OnFailure:当容器异常退出(退出状态码非0)时,才重启容器。适于job
-
Never:当容器终止退出,从不重启容器。适于job
6.7 健康检查
默认情况下,kubelet 根据容器状态作为健康依据,但不能容器中应用程序状态,例如程序假死。这就会导致无法提供服务,丢失流量。因此引入健康检查机制确保容器健康存活。
健康检查有两种类型:
-
livenessProbe
如果检查失败,将杀死容器,根据Pod的restartPolicy来操作。
-
readinessProbe
如果检查失败,Kubernetes会把Pod从service endpoints中剔除。
这两种类型支持三种检查方法:
Probe支持以下三种检查方法:
-
httpGet
发送HTTP请求,返回200-400范围状态码为成功。
-
exec
执行Shell命令返回状态码是0为成功。
-
tcpSocket
发起TCP Socket建立成功。
apiVersion: v1 kind: Pod metadata: labels: test: liveness name: liveness-exec spec: containers: - name: liveness image: busybox args: - /bin/sh - -c - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 60 livenessProbe: exec: command: - cat - /tmp/healthy initialDelaySeconds: 5 periodSeconds: 5
上述示例:启动容器第一件事创建文件,停止30s,删除该文件,再停止60s,确保容器还在运行中。
验证现象:容器启动正常,30s后异常,会restartPolicy策略自动重建,容器继续正常,反复现象。
先看下创建一个Pod的工作流程: create pod -> apiserver -> write etcd -> scheduler -> bind pod to node -> write etcd -> kubelet( apiserver get pod) -> dcoekr api,create container -> apiserver -> update pod status to etcd -> kubectl get pods
这里给你介绍调度策略:nodeName、nodeSelector和污点
1、nodeName
nodeName用于将Pod调度到指定的Node名称上。
apiVersion: v1 kind: Pod metadata: labels: run: busybox name: busybox namespace: default spec: nodeName: k8s-node1 containers: - image: busybox name: bs command: - "ping" - "baidu.com"
kubectl label nodes k8s-node1 team=a kubectl label nodes k8s-node2 team=b
2、nodeSelector
nodeSelector用于将Pod调度到匹配Label的Node上。
先给规划node用途,然后打标签,例如将两台node划分给不同团队使用:
后在创建Pod只会被调度到含有team=a标签的节点上。
apiVersion: v1 kind: Pod metadata: name: busybox namespace: default spec: nodeSelector: team: b containers: - image: busybox name: bs command: - "ping" - "baidu.com"
**3、taint(污点)与tolerations(容忍)** 污点应用场景:节点独占,例如具有特殊硬件设备的节点,如GPU 设置污点命令:
kubectl taint node [node] key=value[effect]
其中[effect] 可取值:
-
NoSchedule :一定不能被调度。
-
PreferNoSchedule:尽量不要调度。
-
NoExecute:不仅不会调度,还会驱逐Node上已有的Pod。
示例:
先给节点设置污点,说明这个节点不是谁都可以调度过来的:
kubectl taint node k8s-node1 abc=123:NoSchedule
apiVersion: v1 kind: Pod metadata: labels: run: busybox name: busybox3 namespace: default spec: tolerations: - key: "abc" operator: "Equal" value: "123" effect: "NoSchedule" containers: - image: busybox name: bs command: - "ping" - "baidu.com"
去掉污点:
kubectl taint node [node] key:[effect]- kubectl taint node k8s-node1 abc:NoSchedule-
# 查看事件,可用于大部分资源 kubectl describe TYPE/NAME # 如果pod启动失败,先查看日志 kubectl logs TYPE/NAME [-c CONTAINER] # 进入到容器中debug kubectl exec POD [-c CONTAINER] -- COMMAND [args...]