pod创建

命令创建

kubectl run nginx --image=swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:latest
pod/nginx created

YAML创建

cat pod.yml
apiVersion: v1                
kind: Pod                      
metadata:                       
  name: pod-stress               
spec:
  containers:           
  - name: c1             
    image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/polinux/stress:latest
    command: ["stress"]
    args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]

# polinux/stress这个镜像用于压力测试,在启动容器时传命令与参数就是相当于分配容器运行时需要的压力
kubectl apply -f pod.yml

镜像拉取策略

由imagePullPolicy参数控制

  • Always : 不管本地有没有镜像,都要从仓库中下载镜像
  • Never : 从来不从仓库下载镜像, 只用本地镜像,本地没有就算了
  • IfNotPresent: 如果本地存在就直接使用, 不存在才从仓库下载

默认的策略是:

  • 当镜像标签版本是latest,默认策略就是Always
  • 如果指定特定版本默认拉取策略就是IfNotPresent。

pod资源限制

spec:
  containers:
  - name: c1
    image: polinux/stress
    imagePullPolicy: IfNotPresent
    resources:
      limits:
        memory: "200Mi"
        cpu: "500m"
      requests:
        memory: "100Mi"
        cpu: "250m"

如果内存不够,这个pod状态变为OOMKilled,因为它是内存不足所以显示Container被杀死

pod重启策略

Always:表示容器挂了总是重启,这是默认策略 
OnFailures:表容器状态为错误时才重启,也就是容器正常终止时才重启 
Never:表示容器挂了不予重启 

对于Always这种策略,容器只要挂了,就会立即重启,这样是很耗费资源的。所以Always重启策略是这么做的:第一次容器挂了立即重启,如果再挂了就要延时10s重启,第三次挂了就等20s重启...... 依次类推

pod调度

pod调度流程

img

1. 通过kubectl命令应用资源清单文件(yaml格式)向api server 发起一个create pod 请求
2. api server接收到pod创建请求后,生成一个包含创建信息资源清单文件
3. apiserver 将资源清单文件中信息写入etcd数据库
4. Scheduler启动后会一直watch API Server,获取 podSpec.NodeName为空的Pod,即判断pod.spec.Node == null? 若为null,表示这个Pod请求是新的,需要创建,因此先进行调度计算(共计2步:1、过滤不满足条件的,2、选择优先级高的),找到合适的node,然后将信息在etcd数据库中更新分配结果:pod.spec.Node = nodeA (设置一个具体的节点)
5. kubelet 通过watch etcd数据库(即不停地看etcd中的记录),发现有新的Node出现,如果这条记录中的Node与所在节点编号相同,即这个Pod由scheduler分配给自己,则调用node中的Container Runtime,进而创建container,并将创建后的结果返回到给api server用于更新etcd数据库中数据状态。

调度约束

我们为了实现容器主机资源平衡使用, 可以使用约束把pod调度到指定的node节点

  • nodeName 用于将pod调度到指定的node名称上
  • nodeSelector 用于将pod调度到匹配Label的node上

nodeName

nodeName: master01      # 通过nodeName调度到master01 节点

nodeSelector

spec:
  nodeSelector:                         # nodeSelector节点选择器
    bussiness: game                     # 指定调度到标签为bussiness=game的节点
  containers:
  - name: nginx
    image: nginx:1.15-alpine

node 节点亲和性

Node 节点亲和性针对的是 pod 和 node 的关系,Pod 调度到 node 节点的时候匹配的条件

requiredDuringSchedulingIgnoredDuringExecution 硬亲和性

spec:
  containers:
    - name: myapp
      image: nginx
  affinity:    #用于控制Pod调度的亲和性和反亲和性规则。
    nodeAffinity:   #控制Pod如何调度到节点上。
      requiredDuringSchedulingIgnoredDuringExecution:   # 表示在调度时必须满足的条件,在Pod执行期间可以忽略。
        nodeSelectorTerms:   #包含一个或多个匹配表达式,用于描述节点必须满足的条件。
          - matchExpressions:   #包含一组键、操作符和值的列表,用于描述节点的标签。
              - key: zone   #节点标签的键。
                operator: In   #操作符,可以是 In, NotIn, Exists, DoesNotExist, Gt, Lt
                values:      ##一个或多个字符串值。
                  - foo 
                  - bar

我们检查当前节点中有任意一个节点拥有 zone 标签的值是 foo 或者 bar,就可以把 pod 调度到这个 node 节点的 foo 或者 bar 标签上的节点上

preferredDuringSchedulingIgnoredDuringExecution 软亲和性

软亲和性是可以运行这个 pod 的,尽管没有运行这个 pod 的节点定义的标签

spec:
  containers:
    - name: myapp
      image: ikubernetes/myapp:v1
  affinity:    ##用于控制Pod调度的亲和性和反亲和性规则。
    nodeAffinity:   ##控制Pod如何调度到节点上
      preferredDuringSchedulingIgnoredDuringExecution:   ##表示在调度时偏好但不强制的条件,在Pod执行期间可以忽略。
        - preference:    ##包含一个或多个匹配表达式,用于描述节点应该满足的条件
            matchExpressions:   ##包含一组键、操作符和值的列表,用于描述节点的标签
              - key: zone1   #节点标签的键
                operator: In    #操作符,可以是 In, NotIn, Exists, DoesNotExist, Gt, Lt
                values:
                  - foo1
                  - bar1
          weight: 60    #用于描述偏好的权重,范围从 1 到 100。权重越高,调度器越倾向于将Pod调度到匹配的节点上。

Pod 节点亲和性

pod 自身的亲和性调度有两种表示形式:

​ podaffinity:pod 和 pod 更倾向腻在一起,把相近的 pod 结合到相近的位置,如同一区域,同一机架,这样的话 pod 和 pod 之间更好通信,比方说有两个机房,这两个机房部署的集群有 1000 台主机,那么我们希望把 nginx 和 tomcat 都部署同一个地方的 node 节点上,可以提高通信效率;

​ podunaffinity:pod 和 pod 更倾向不腻在一起,如果部署两套程序,那么这两套程序更倾向于反亲和性,这样相互之间不会有影响。

第一个 pod 随机选则一个节点,做为评判后续的 pod 能否到达这个 pod 所在的节点上的运行方式,这就称为 pod 亲和性;我们怎么判定哪些节点是相同位置的,哪些节点是不同位置的;我们在定义 pod 亲和性时需要有一个前提,哪些 pod 在同一个位置,哪些 pod 不在同一个位置,这个位置是怎么定义的,标准是什么?以节点名称为标准,这个节点名称相同的表示是同一个位置, 节点名称不相同的表示不是一个位置。

亲和性

定义两个 pod,第一个 pod 做为基准,第二个 pod 跟着它走:

apiVersion: v1
kind: Pod
metadata:
  name: pod-first
  labels:
    app2: myapp2
    tier: frontend
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-second
  labels:
    app: backend
    tier: db
spec:
  containers:
  - name: busybox
    image: busybox:latest
    imagePullPolicy: IfNotPresent
    command: ["sh","-c","sleep 3600"]
  affinity:    
    podAffinity:     #这部分定义了Pod之间的亲和性策略。
       requiredDuringSchedulingIgnoredDuringExecution:   #硬亲和性
       - labelSelector:    #选择具有特定标签的Pod。
            matchExpressions:
            - {key: app2, operator: In, values: ["myapp2"]}
         topologyKey: kubernetes.io/hostname    #指定节点属性键,这里是节点名称。

上面表示创建的 pod 必须与拥有 app=myapp 标签的 pod 在一个节点上

第一个 pod 调度到哪,第二个 pod 也调度到哪,这就是 pod 节点亲和性

反亲和性

定义两个 pod,第一个 pod 做为基准,第二个 pod 跟它调度节点相反

apiVersion: v1
kind: Pod
metadata:
  name: pod-first
  labels:
    app1: myapp1
    tier: frontend
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-second
  labels:
    app: backend
    tier: db
spec:
  containers:
  - name: busybox
    image: busybox:latest
    imagePullPolicy: IfNotPresent
    command: ["sh","-c","sleep 3600"]
  affinity:   
    podAntiAffinity:      #这部分定义了Pod之间的亲和性策略。
       requiredDuringSchedulingIgnoredDuringExecution:    #硬亲和性
       - labelSelector:   #选择具有特定标签的Pod。
           matchExpressions:
           - {key: app1, operator: In, values: ["myapp1"]}
         topologyKey: kubernetes.io/hostname    #指定节点属性键,这里是节点名称。

topologykey的作用

topologyKey作用:

​ 节点标签:节点必须具有这个标签键,并且具有具体的值。

​ 反亲和性:带有相同应用标签的 Pod 不会被调度到具有相同标签的节点上。

​ 亲和性:如果使用的是亲和性配置,则带有相同应用标签的 Pod 将被尽可能调度到具有相同标签的节点上。

污点、容忍度

给了节点选则的主动权,我们给节点打一个污点,不容忍的 pod 就运行不上来,污点就是定义在节点上的键值属性数据,可以定决定拒绝那些 pod;

taints 是键值数据,用在节点上,定义污点;

tolerations 是键值数据,用在 pod 上,定义容忍度,能容忍哪些污点

pod 亲和性是 pod 属性;但是污点是节点的属性,污点定义在 nodeSelector 上

污点等级

effect 用来定义对 pod 对象的排斥等级(效果): NoSchedule: 仅影响 pod 调度过程,当 pod 能容忍这个节点污点,就可以调度到当前节点,后来这个节点的污点改了,加了一个新的污点,使得之前调度的 pod 不能容忍了,那这个 pod 会怎么处理,对现存的 pod 对象不产生影响 NoExecute: 既影响调度过程,又影响现存的 pod 对象,如果现存的 pod 不能容忍节点后来加的污点,这个 pod 就会被驱逐 PreferNoSchedule: 最好不,也可以,是 NoSchedule 的柔性版本

容忍度匹配

在 pod 对象定义容忍度的时候支持两种操作: 
1.等值密钥:key 和 value 上完全匹配
2.存在性判断:key 和 effect 必须同时匹配,value 可以是空 
在 pod 上定义的容忍度可能不止一个,在节点上定义的污点可能多个,需要琢个检查容忍度和污点能否匹配,
每一个污点都能被容忍,才能完成调度,如果不能容忍怎么办,那就需要看 pod 的容\忍度了
kubectl describe nodes  master01
Taints:             node-role.kubernetes.io/master:NoSchedule
上面可以看到 master 这个节点的污点是 Noschedule 
所以我们创建的 pod 都不会调度到 master01 上,因为我们创建的 pod 没有容忍度

案例

apiVersion: v1
kind: Pod
metadata:
  name: myapp-deploy
  namespace: default
  labels:
    app: myapp
    release: canary
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    ports:
    - name: http
      containerPort: 80
  tolerations:   # Pod 可以容忍的污点列表,允许 Pod 被调度到具有相应污点的节点上。
  - key: "node-type"    #污点的键名。这里为 node-type
    operator: "Equal"   #用于匹配值的操作符。Equal 表示等同于
    value: "production"   #与键关联的值。这里为 production
    effect: "NoSchedule"   #污点的效果,通常有 NoSchedule, PreferNoSchedule, 和 NoExecute。NoExecute 表示如果 Pod 不能容忍此污点,它将被驱逐。

Pod生命周期

img

健康检查

健康检查方式

Liveness Probe(存活状态探测): 指示容器是否正在运行。如果存活态探测失败,则 kubelet 会杀死容器, 并且容器将根据其重启策略决定未来。如果容器不提供存活探针, 则默认状态为 Success。

readiness Probe(就绪型探测): 指示容器是否准备好为请求提供服务。如果就绪态探测失败, 端点控制器将从与 Pod 匹配的所有服务的端点列表中删除该 Pod 的 IP 地址。 初始延迟之前的就绪态的状态值默认为 Failure。 如果容器不提供就绪态探针,则默认状态为 Success。注:检查后不健康,将容器设置为Notready;如果使用service来访问,流量不会转发给此种状态的pod

startup Probe: 指示容器中的应用是否已经启动。如果提供了启动探针,则所有其他探针都会被 禁用,直到此探针成功为止。如果启动探测失败,kubelet 将杀死容器,而容器依其 重启策略进行重启。 如果容器没有提供启动探测,则默认状态为 Success。

探测方式

Exec:执行命令
HTTPGet: http请求某一个URL路径
TCP:tcp连接某一个端口
gRPC: 使用 gRPC 执行一个远程过程调用。 目标应该实现 gRPC健康检查。 如果响应的状态是 “SERVING”,则认为诊断成功。 gRPC 探针是一个 alpha 特性,只有在你启用了 “GRPCContainerProbe” 特性门控时才能使用。

readiness+liveness综合案例

vim pod-readiness-liveiness.yml
apiVersion: v1
kind: Pod
metadata:
  name: readiness-liveness-httpget
  namespace: default
spec:
  containers:
  - name: readiness-liveness
    image: nginx:1.15-alpine
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80
    livenessProbe:
      httpGet:
        port: http
        path: /index.html
      initialDelaySeconds: 1
      periodSeconds: 3
    readinessProbe:
      httpGet:
        port: http
        path: /index.html
      initialDelaySeconds: 5   # pod启动延迟5秒后探测
      periodSeconds: 5       # 每5秒探测1次

post-start

容器启动前执行的命令

apiVersion: v1
kind: Pod
metadata:
  name: poststart
  namespace: default
spec:
  containers:
  - name: poststart
    image: nginx:1.15-alpine
    imagePullPolicy: IfNotPresent
    lifecycle:                                       # 生命周期事件
      postStart:
        exec:
          command: ["mkdir","-p","/usr/share/nginx/html/haha"]

pre-stop

容器终止前执行的命令

apiVersion: v1
kind: Pod
metadata:
  name: prestop
  namespace: default
spec:
  containers:
  - name: prestop
    image: nginx:1.15-alpine
    imagePullPolicy: IfNotPresent
    lifecycle:                                       # 生命周期事件
      preStop:                                       # preStop
        exec:
          command: ["/bin/sh","-c","sleep 60000000"]     # 容器终止前sleep 60000000秒

pod状态

状态 描述
Pending(悬决) Pod 已被 Kubernetes 系统接受,但有一个或者多个容器尚未创建亦未运行。此阶段包括等待 Pod 被调度的时间和通过网络下载镜像的时间。
Running(运行中) pod已经绑定到一个节点,并且已经创建了所有容器。至少有一个容器正在运行中,或正在启动或重新启动。
completed(完成) Pod中的所有容器都已成功终止,不会重新启动。
Failed(失败) Pod的所有容器均已终止,且至少有一个容器已在故障中终止。也就是说,容器要么以非零状态退出,要么被系统终止。
Unknown(未知) 由于某种原因apiserver无法获得Pod的状态,通常是由于Master与Pod所在主机kubelet通信时出错。
CrashLoopBackOff 多见于CMD语句错误或者找不到container入口语句导致了快速退出,可以用kubectl logs 查看日志进行排错

results matching ""

    No results matching ""