第6章:深入理解Pod对象

时间:2021-05-04 13:54:16   收藏:0   阅读:20

Pod是最小的部署单元,也是后面经常配置的地方,本章节带你熟悉Pod中常见资源配置及参数。

也就是YAML这部分:

...
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - image: lizhenliang/java-demo:latest
        imagePullPolicy: Always
        name: java

6.1 Pod介绍

6.2 Pod存在的意义

Pod为亲密性应用而存在。

亲密性应用场景:

6.3 Pod实现机制与设计模式

Pod本身是一个逻辑概念,没有具体存在,那究竟是怎么实现的呢?

众所周知,容器之间是通过Namespace隔离的,Pod要想解决上述应用场景,那么就要让Pod里的容器之间高效共享。

具体分为两个部分:网络和存储

kubernetes的解法是这样的:会在每个Pod里先启动一个infra container小容器,然后让其他的容器连接进来这个网络命名空间,然后其他容器看到的网络视图就完全一样了,即网络设备、IP地址、Mac地址等,这就是解决网络共享问题。在Pod的IP地址就是infra container的IP地址(即pause容器)。

比如有两个容器,一个是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中容器分为以下几个类型:

6.4 镜像拉取策略

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: java
      image: lizhenliang/java-demo
      imagePullPolicy: IfNotPresent

imagePullPolicy 字段有三个可选值(镜像仓库中的镜像都打标签):

如果拉取公开的镜像,直接按照上述示例即可,但要拉取私有的镜像,是必须认证镜像仓库才可以,即docker login,而在K8S集群中会有多个Node,显然这种方式是很不放方便的!为了解决这个问题,K8s 实现了自动拉取镜像的功能。 以secret方式保存到K8S中,然后传给kubelet。

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  imagePullSecrets:
    - name: myregistrykey
  containers:
    - name: java
      image: lizhenliang/java-demo
      imagePullPolicy: IfNotPresent

上述中名为 myregistrykey 的secret是由 kubectl create secret docker-registry 命令创建:

# kubectl create secret docker-registry myregistrykey --docker-username=admin --docker-password=Harbor12345 --docker-email=admin@harbor.com --docker-server=192.168.31.70
# kubectl get secret

--docker-username: 指定docker仓库账号 --docker-password: 指定docker仓库密码 --docker-email: 指定邮件地址(选填) --docker-server: 指定docke仓库地址

6.5 资源限制

如果不限制资源默认共享宿主机的所有资源。

Pod资源配额有两种:

示例:

apiVersion: v1
kind: Pod
metadata:
  name: web
spec:
  containers:
  - name: java
    image: lizhenliang/java-demo
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

其中cpu值比较抽象,可以这么理解:

1核=1000m

1.5核=1500m

那上面限制配置就是1核的二分之一(500m),即该容器最大使用半核CPU。

该值也可以写成浮点数,更容易理解:

半核=0.5

1核=1

1.5核=1.5

6.6 重启策略

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
    - name: java
      image: lizhenliang/java-demo
    restartPolicy: Always

restartPolicy字段有三个可选值:

6.7 健康检查

默认情况下,kubelet 根据容器状态作为健康依据,但不能检查容器应用程序状态,例如程序假死。这就会导致无法提供服务,丢失流量。因此引入健康检查机制确保容器健康存活。

健康检查有两种类型:

这两种类型支持三种检查方法:

Probe支持以下三种检查方法:

示例:

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策略自动重建,容器继续正常,反复现象。

6.8 调度策略

先看下创建一个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

技术分享图片

Pod根据调度器默认算法将Pod分配到合适的节点上,一般是比较空闲的节点。但有些情况我们希望将Pod分配到指定节点,该怎么做呢?

这里给你介绍调度策略:nodeName、nodeSelector和污点(kubectl edit 或 kubectl apply -f 方式改变已经存在 pod 的调度机器,保存后,配置不生效)

1、nodeName

nodeName用于将Pod调度到指定的Node名称上。

例如:下面示例会绕过调度系统,直接分配到k8s-node1节点。

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"

2、nodeSelector

nodeSelector用于将Pod调度到匹配Label的Node上。

先给规划node用途,然后打标签,例如将两台node划分给不同团队使用:

# 创建标签
kubectl label node <node-name> <label-key>=<label-value>
# 查看标签
kubectl get node --show-labels
# 删除标签
kubectl label node <node-name> <label-key>-
# 修改标签值
kubectl label node <node-name> <label-key>=<label-value> --overwrite
?
kubectl label nodes k8s-node1 team=a
kubectl label nodes k8s-node2 team=b

然后在创建Pod只会被调度到含有team=a标签的节点上。

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  namespace: default
spec:
  nodeSelector:
    team: a
  containers:
  - image: busybox
    name: bs
    command:
    - "ping"
    - "baidu.com"

3、taint(污点)与tolerations(容忍)

污点应用场景:节点独占,例如具有特殊硬件设备的节点,如GPU

设置污点命令:

kubectl taint node [node] key=value[effect] 

其中[effect] 可取值:

示例:

先给节点设置污点,说明这个节点不是谁都可以调度过来的:

kubectl taint node k8s-node1  abc=123:NoSchedule

查看污点:

kubectl describe node k8s-node1 |grep Taints

然后在创建Pod只有声明了容忍污点(tolerations),才允许被调度到abc=123污点节点上。

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"

如果不配置容忍污点,则永远不会调度到k8s-node1。

去掉污点:

kubectl taint node [node] key:[effect]-
kubectl taint node k8s-node1 abc:NoSchedule-

6.9 故障排查

# 查看事件,可用于大部分资源
kubectl describe TYPE/NAME   
# 如果pod启动失败,先查看日志
kubectl logs TYPE/NAME [-c CONTAINER] 
# 进入到容器中debug
kubectl exec POD [-c CONTAINER] -- COMMAND [args...]

原文:https://www.cnblogs.com/LiuChang-blog/p/14729321.html

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!