1 概述

Pod是K8S系统中可以创建和管理的最小单元,是资源对象模型中由用户创建或部署的最小资源对象模型

有许多组件围绕Pod进行扩展和支持,比如控制器对象是用来管控Pod对象的,Service或者Ingress资源对象是用来暴露Pod引用对象的,PersistentVolume资源对象是用来为Pod提供存储等。

1.1 Pod结构

Pod是多进程设计,一个Pod里面包含多个容器,而一个容器里面运行一个应用程序。

每个Pod都有一个特殊的被称为 “根容器”的Pause容器。Pause容器对应的镜像属于Kubernetes平台的一部分,为其他的业务容器作支撑。一般把业务相关联的容器放到一个pod里,从而方便相关容器之间网络互通和文件共享。

1.2 实现机制

Pod实现主要依赖于共享网络共享存储两大机制

  • 共享网络:docker创建的容器由于namespace和group而相互隔离的,在创建业务容器时会注册到 pause容器 中从而共享其 ip地址,mac地址,port 等信息,这样便处于同一个网络中实现网络的共享。
  • 共享存储:如下所示,每个容器会挂载到公共的数据卷Volume上,然后其数据都持久化存储到其中,当一个容器挂掉后,新的容器也能从Volume读取到之前的数据
apiversion: v1
  kind: Pod
  metadata:
    name: my-pod
  spec:
    containers:
    -name: write
      image: centos
      command: ["bash", "-u","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: {}

2 Pod机制

2.1 镜像拉取策略

Pod的拉取策略主要分为了以下几种

  • IfNotPresent:默认值,镜像在宿主机上不存在才拉取
  • Always:每次创建Pod都会重新拉取一次镜像
  • Never:Pod永远不会主动拉取这个镜像
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    -name: nginx
    image: nginx:1.14
    # 拉取策略
    imagePullPolicy: Always

2.2 Pod资源限制

Pod在进行调度时,可以在调度器对资源的分配进行设置。例如限制使用的资源是 2C4G,那么在调度到对应的node节点时,只会占用对应的资源,对于不满足资源的节点则会跳过。

有两种资源配置的方式:

  • request:表示调度所需最少的资源
  • limits:表示最多允许使用的资源
apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: db
    image: mysql
    env:
    - name: MYSQL__ROOT_PASSWORD
      value: "password"
        
    resources:
      # 资源限制
      requests:
        memory: "64Mi"
        cpu: "250m"
        
      limits:
        memory: "128Mi"
        cpu: "500m"

2.3 Pod重启机制

当Pod中的容器出现问题时就会触发重启机制,重启策略主要分为以下三种

  • Always:当容器终止退出后,总是重启容器,默认策略 【nginx等,需要不断提供服务】
  • OnFailure:当容器异常退出(退出状态码非0)时,才重启容器。
  • Never:当容器终止退出,从不重启容器
apiVersion: v1
kind: Pod
metadata:
  name: dns-test
spec:
  containers:
  - name: busybox
    image: busybox:1.28
    args:
    - /bin/sh
    - -c
    - sleep 33000
  # 重启策略
  restartPolicy: Never

2.4 Pod健康检查

通过容器检查来判断服务是否可用,共有两种检查方式:存活检查livenessProbe,如果检查失败,将杀死容器,根据Pod的restartPolicy来操作;就绪检查readinessProbe,如果检查失败,Kubernetes会把Pod从Service endpoints中剔除

Probe支持以下三种检查方式

  • http Get:发送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;
    # 通过exec来执行存活检查
    livenessProbe:
      exec:
        command:
        -cat
        -/tmp/healthy
      initialDelaySeconds: 5
      periodSeconds: 5

3 调度策略

创建Pod流程如下:

  • 首先创建一个pod,然后创建一个API Server 和 Etcd,把创建出来的信息存储在etcd中
  • 然后创建 Scheduler,监控API Server是否有新的Pod,如果有的话,会通过调度算法把pod调度具体node上
  • 在node节点,会通过 kubelet -- apiserver 读取etcd 拿到分配在当前node节点pod信息,然后通过docker创建容器

影响Pod调度的属性

在Pod调度时会有多个条件影响调度结果。

首先调度器会考虑Pod的资源限制,根据request找到满足条件的node节点进行调度

3.1 节点选择器NodeSelector

调度器会根据节点的标签将任务调度到符合条件的节点上,例如下面将任务调度到标签为dev的节点上

apiVersion: v1
kind: Pod
metadata:
  name: pod-example
spec:
  # 根据节点选择器标签进行调度
  nodeSelector:
    env role: dev
  containers:
  -name: nginx
    image: nginx:1.15

可以通过以下命令为节点新增标签,然后节点选择器就会进行调度了

kubectl label node node1 env_role=prod

3.2 节点亲和性NodeAffinity

节点亲和性和之前nodeSelector 基本一样的,根据节约束条件来决定Pod调度到哪些节点上

  • 硬亲和性:约束条件必须满足,不满足则不分配
  • 软亲和性:尝试满足,不保证
apiVersion: v1                                              
kind: Pod                                                    
metadata:                                                    
   name: with-node-affinity                                    
spec:                                                             
   affinity:                                                   
     nodeAffinitv:
       # 硬亲和性
       requiredDuringSchedulinglgnoredDuringExecution:
         nodeSelectorTerms:
         - matuhExpEessions:
           - key: env sle
             operator: In
             values:
               - dev
               - test
       # 软亲和性
       preferredDuringSchedulinglgnoredDuringExecution:
       - weight: 1
         preference:
           matchExpressions:
           - key: group
             operator: In
             values:
             - otherprod

支持常用操作符:in、NotIn、Exists、Gt、Lt、DoesNotExists

反亲和性:就是和亲和性刚刚相反,如 NotIn、DoesNotExists等

3.3 污点Taint

通过Taint 将节点添加污点,从而使本节点不做普通分配调度。nodeSelector 和 NodeAffinity,都是Pod的属性,而污点是节点的属性。

可以通过污点

  • 专用节点【限制ip】
  • 配置特定硬件的节点【固态硬盘】
  • 基于Taint驱逐【在node1不放,在node2放】

通过如下命令查看污点情况

kubectl describe node k8smaster | grep Taint

污点值有三个

  • NoSchedule:一定不被调度
  • PreferNoSchedule:尽量不被调度【也有被调度的几率】
  • NoExecute:不会调度,并且还会驱逐Node已有Pod

通过如下命令为节点添加污点

kubectl taint node [node] key=value:污点的三个值

举例:

kubectl taint node k8snode1 env_role=yes:NoSchedule

# 删除污点
kubectl taint node k8snode1 env_role:NoSchedule-