资讯详情

【4】Kubernetes pod资源

容器与pod资源对象

为什么Kubernetes要引入pod概念不直接操作Docker容器

首先要明确一个概念,Kubernetes不仅仅是支持Docker当这个容器运行时,我的另一篇文章是什么?Kubernetes的CRI-我们知道容器运行时界面介绍的内容Kubernetes通过CRI支持去除抽象层Docker其他容器运行时,如rkt甚至支持客户自定义容器运行。

  • 第一个原因:借助CRI使抽象层Kubernetes它不依赖于底层特定容器运行时的技术,而是直接操作pod,pod内部管理多个与业务密切相关的用户业务容器,方便Kubernetes做扩展。
  • 第二个原因原因Kubernetes没有pod这个概念是直接管理容器,所以一组容器作为一个单元,假设其中一个容器死亡,该单元的状态应该如何定义?它应该被理解为整体死亡还是个人死亡?

这个问题之所以不容易回答,是因为它包含了这组业务容器的逻辑单元,没有统一的方法来代表整个容器组的状态。Kubernetes引入pod的概念,并且每个pod里都有一个Kubernetes系统自带的pause容器的原因,通过引入pause这与业务无关,功能相似Linux操作系统保护过程Kubernetes以系统标准容器为准pause容器的状态代表整个容器组的状态。

img

  • 第三个原因:pod所有业务容器共享pause容器的IP地址,以及pause容器mount的Volume,通过这种设计,业务容器可以直接通信,文件可以直接共享。

Pod资源清单

下面是Pod资源清单:

apiVersion: v1     #必选,版本号,比如v1 kind: Pod         #必选,资源类型,如 Pod metadata:         #必选,元数据   name: string     #必选,Pod名称   namespace: string  #Pod命名空间默认为"default"   labels:           #自定义标签列表     - name: string                  spec:  #必选,Pod详细定义中容器   containers:  #必选,Pod中容器列表   - name: string   #必选,容器名称     image: string  ##必选,容器镜像名称     imagePullPolicy: [ Always|Never|IfNotPresent ]  #获取镜像的策略      command: [string]   #如果不指定容器的启动命令列表,则使用包装时使用的启动命令     args: [string]      ##容器启动命令参数列表     workingDir: string  #容器工作目录     volumeMounts:       ##存储卷配置挂载在容器内     - name: string      #引用pod共享存储卷的定义名称需要使用volumes[]部分定义的卷名       mountPath: string #存储卷在容器中mount绝对路径应小于512字符       readOnly: boolean #是否为只读模式?     ports: ##需要暴露的端口库号列表     - name: string        #端口名称       containerPort: int  #容器需要监听的端口号
      hostPort: int       #容器所在主机需要监听的端口号,默认与Container相同
      protocol: string    #端口协议,支持TCP和UDP,默认TCP
    env:   #容器运行前需设置的环境变量列表
    - name: string  #环境变量名称
      value: string #环境变量的值
    resources: #资源限制和请求的设置
      limits:  #资源限制的设置
        cpu: string     #Cpu的限制,单位为core数,将用于docker run --cpu-shares参数
        memory: string  #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数
      requests: #资源请求的设置
        cpu: string    #Cpu请求,容器启动的初始可用数量
        memory: string #内存请求,容器启动的初始可用数量
    lifecycle: #生命周期钩子
        postStart: #容器启动后立即执行此钩子,如果执行失败,会根据重启策略进行重启
        preStop: #容器终止前执行此钩子,无论结果如何,容器都会终止
    livenessProbe:  #对Pod内各容器健康检查的设置,当探测无响应几次后将自动重启该容器
      exec:         #对Pod容器内检查方式设置为exec方式
        command: [string]  #exec方式需要制定的命令或脚本
      httpGet:       #对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、port
        path: string
        port: number
        host: string
        scheme: string
        HttpHeaders:
        - name: string
          value: string
      tcpSocket:     #对Pod内个容器健康检查方式设置为tcpSocket方式
         port: number
       initialDelaySeconds: 0       #容器启动完成后首次探测的时间,单位为秒
       timeoutSeconds: 0          #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒
       periodSeconds: 0           #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次
       successThreshold: 0
       failureThreshold: 0
       securityContext:
         privileged: false
  restartPolicy: [Always | Never | OnFailure]  #Pod的重启策略
  nodeName: <string> #设置NodeName表示将该Pod调度到指定到名称的node节点上
  nodeSelector: obeject #设置NodeSelector表示将该Pod调度到包含这个label的node上
  imagePullSecrets: #Pull镜像时使用的secret名称,以key:secretkey格式指定
  - name: string
  hostNetwork: false   #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络
  volumes:   #在该pod上定义共享存储卷列表
  - name: string    #共享存储卷名称 (volumes类型有很多种)
    emptyDir: { 
        }       #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值
    hostPath: string   #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录
      path: string                #Pod所在宿主机的目录,将被用于同期中mount的目录
    secret:          #类型为secret的存储卷,挂载集群与定义的secret对象到容器内部
      scretname: string  
      items:     
      - key: string
        path: string
    configMap:         #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部
      name: string
      items:
      - key: string
        path: string
#小提示:
# 在这里,可通过一个命令来查看每种资源的可配置项
# kubectl explain 资源类型 查看某种资源可以配置的一级属性
# kubectl explain 资源类型.属性 查看属性的子属性
[root@k8s-master01 ~]# kubectl explain pod
KIND:     Pod
VERSION:  v1
FIELDS:
   apiVersion   <string>
   kind <string>
   metadata     <Object>
   spec <Object>
   status       <Object>

[root@k8s-master01 ~]# kubectl explain pod.metadata
KIND:     Pod
VERSION:  v1
RESOURCE: metadata <Object>
FIELDS:
   annotations  <map[string]string>
   clusterName  <string>
   creationTimestamp    <string>
   deletionGracePeriodSeconds   <integer>
   deletionTimestamp    <string>
   finalizers   <[]string>
   generateName <string>
   generation   <integer>
   labels       <map[string]string>
   managedFields        <[]Object>
   name <string>
   namespace    <string>
   ownerReferences      <[]Object>
   resourceVersion      <string>
   selfLink     <string>
   uid  <string>

在kubernetes中基本所有资源的一级属性都是一样的,主要包含5部分:

  • apiVersion <string> 版本,由kubernetes内部定义,版本号必须可以用 kubectl api-versions 查询到
  • kind <string> 类型,由kubernetes内部定义,版本号必须可以用 kubectl api-resources 查询到
  • metadata <Object> 元数据,主要是资源标识和说明,常用的有name、namespace、labels等
  • spec <Object> 描述,这是配置中最重要的一部分,里面是对各种资源配置的详细描述
  • status <Object> 状态信息,里面的内容不需要定义,由kubernetes自动生成

在上面的属性中,spec是接下来研究的重点,继续看下它的常见子属性:

  • containers <[]Object> 容器列表,用于定义容器的详细信息
  • nodeName <String> 根据nodeName的值将pod调度到指定的Node节点上
  • nodeSelector <map[]> 根据NodeSelector中定义的信息选择将该Pod调度到包含这些label的Node 上
  • hostNetwork <boolean> 是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络
  • volumes <[]Object> 存储卷,用于定义Pod上面挂在的存储信息
  • restartPolicy <string> 重启策略,表示Pod在遇到故障的时候的处理策略

管理pod中的容器

镜像及其获取策略

kubernetes支持用户自定义镜像文件的获取策略,例如在网络资源较为紧张时可以禁止从仓库中获取镜像文件等。容器的imagePullPolicy字段用于为其指定镜像获取策略,它的值可以包括以下几种

  • Always:镜像标签为latest或镜像不存在时总是从指定的仓库中获取镜像
  • IfNotPresent:仅当本地镜像缺失时方才从目标仓库下载镜像
  • Never:禁止从仓库下载镜像,即仅使用本地镜像

默认值说明:

如果镜像tag为具体版本号, 默认策略是:IfNotPresent

如果镜像tag为:latest(最终版本) ,默认策略是always

[root@k8s-master1 ~]# cat pod1.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-example
spec:
  containers:
  - name: nginx
    image: nginx:latest
    imagePullPolicy: Always
[root@k8s-master1 ~]# kubectl apply -f pod1.yaml 
pod/pod-example configured

暴露端口

Docker的网络模型中,使用默认网络的容器化应用需要通过NAT将其暴露到外部网络中才能被其他节点之上的容器客户端所访问。然而kubernetes系统的网络模型中,各pod的ip地址处于同一网络平面上,无论是否为容器指定了要暴露的端口,都不会影响集群中其他节点之上的pod客户端对其进行访问,这就意味着,任何监听在非lo接口的端口都可以通过pod网络直接被请求

  • 指定暴露端口为tcp的80,并将之命名为http
[root@k8s-master1 ~]# cat pod1.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-example
spec:
  containers:
  - name: nginx
    image: nginx:latest
    imagePullPolicy: Always
    ports:
    - name: http
      containerPort: 80
      protocol: TCP
[root@k8s-master1 ~]# kubectl delete pods pod-example
pod "pod-example" deleted
[root@k8s-master1 ~]# kubectl apply -f pod1.yaml 
pod/pod-example created
[root@k8s-master1 ~]# curl 10.244.3.9 -I
HTTP/1.1 200 OK
Server: nginx/1.21.1
Date: Mon, 16 Aug 2021 16:18:22 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 06 Jul 2021 14:59:17 GMT
Connection: keep-alive
ETag: "60e46fc5-264"
Accept-Ranges: bytes

自定义运行的容器化应用

由docker镜像启动容器时运行的应用程序在相应的Dokcerfile中由ENTRYPOINT指令进行定义,传递给程序的参数则通过CMD指令指定,ENTRYPOINT指令不存在时,CMD可用于同时指定程序及其参数。

容器的command字段能够指定不同于镜像默认运行的应用程序,并且可以同时使用args字段进行参数传递,他们将覆盖镜像中的默认定义。

[root@k8s-master1 ~]# cat pod1.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-example
spec:
  containers:
  - name: nginx
    image: nginx:latest
    imagePullPolicy: Always
    ports:
    - name: http
      containerPort: 80
      protocol: TCP
    command: ["/bin/sh"]
    args: ["-c","while true;do sleep 30;done"]
[root@k8s-master1 ~]# kubectl delete pods pod-example
pod "pod-example" deleted
[root@k8s-master1 ~]# kubectl apply -f pod1.yaml 
pod/pod-example created
[root@k8s-master1 ~]# kubectl get pods pod-example -o wide
NAME          READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
pod-example   1/1     Running   0          33s   10.244.3.10   k8s-node2   <none>           <none>

创建pod-command.yaml文件,内容如下:

apiVersion: v1
kind: Pod
metadata:
  name: pod-command
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.1
  - name: busybox
    image: busybox:1.30
    command: ["/bin/sh","-c","touch /tmp/hello.txt;while true;do /bin/echo $(date +%T) >> /tmp/hello.txt; sleep 3; done;"]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q2TICaPq-1651206830823)(04.kubernetes pod资源/image-20210617224457945.png)]

command,用于在pod中的容器初始化完毕之后运行一个命令。

稍微解释下上面命令的意思:

“/bin/sh”,“-c”, 使用sh执行命令

touch /tmp/hello.txt; 创建一个/tmp/hello.txt 文件

while true;do /bin/echo $(date +%T) >> /tmp/hello.txt; sleep 3; done; 每隔3秒向文件中写入当前时间

# 创建Pod
[root@k8s-master01 pod]# kubectl create -f pod-command.yaml
pod/pod-command created

# 查看Pod状态
# 此时发现两个pod都正常运行了
[root@k8s-master01 pod]# kubectl get pods pod-command -n dev
NAME          READY   STATUS   RESTARTS   AGE
pod-command   2/2     Runing   0          2s

# 进入pod中的busybox容器,查看文件内容
# 补充一个命令: kubectl exec pod名称 -n 命名空间 -it -c 容器名称 /bin/sh 在容器内部执行命令
# 使用这个命令就可以进入某个容器的内部,然后进行相关操作了
# 比如,可以查看txt文件的内容
[root@k8s-master01 pod]# kubectl exec pod-command -n dev -it -c busybox /bin/sh
/ # tail -f /tmp/hello.txt
14:44:19
14:44:22
14:44:25
特别说明:
    通过上面发现command已经可以完成启动命令和传递参数的功能,为什么这里还要提供一个args选项,用于传递参数呢?这其实跟docker有点关系,kubernetes中的command、args两项其实是实现覆盖Dockerfile中ENTRYPOINT的功能。
 1 如果command和args均没有写,那么用Dockerfile的配置。
 2 如果command写了,但args没有写,那么Dockerfile默认的配置会被忽略,执行输入的command
 3 如果command没写,但args写了,那么Dockerfile中配置的ENTRYPOINT的命令会被执行,使用当前args的参数
 4 如果command和args都写了,那么Dockerfile的配置被忽略,执行command并追加上args参数

pod资源限制

在kubernetes上,可由容器或Pod请求或消费的计算资源指的是cpu和内存。cpu属于可压缩型资源,即资源额度可按需收缩,而内存则是不可压缩型资源,对其执行收缩操作可能会导致某种程度的问题。

资源隔离属于容器级别,cpu和内存资源的配置需要在Pod中的容器上进行,每种资源均可由requests属性定义其请求的确保可用值,即容器运行可能用不到这些额度的资源,但用到时必须确保由如此多的资源可用,而limits属性则用于限制资源的可用的最大值。

Pod和Container的资源请求和限制: • spec.containers[].resources.limits.cpu • spec.containers[].resources.limits.memory • spec.containers[].resources.requests.cpu • spec.containers[].resources.requests.memory

  • 定义资源请求和限制
[root@k8s-master1 ~]# cat pod-stress-ng.yaml 
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"
  - name: wp
    image: wordpress
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
[root@k8s-master1 ~]# kubectl apply -f pod-stress-ng.yaml 
pod/frontend created
  • 查看pod描述
[root@k8s-master1 ~]# kubectl describe pod frontend
Name:         frontend
Namespace:    default
Priority:     0
Node:         k8s-node1/192.168.80.101
Start Time:   Wed, 18 Aug 2021 01:18:11 +0800
Labels:       <none>
Annotations:  <none>
Status:       Pending
IP:           
IPs:          <none>
Containers:
  db:
    Container ID:   
    Image:          mysql
    Image ID:       
    Port:           <none>
    Host Port:      <none>
    State:          Waiting
      Reason:       ContainerCreating
    Ready:          False
    Restart Count:  0
    Limits:
      cpu:     500m
      memory:  128Mi
    Requests:
      cpu:     250m
      memory:  64Mi
    Environment:
      MYSQL_ROOT_PASSWORD:  password
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-9dwb4 (ro)
  wp:
    Container ID:   
    Image:          wordpress
    Image ID:       
    Port:           <none>
    Host Port:      <none>
    State:          Waiting
      Reason:       ContainerCreating
    Ready:          False
    Restart Count:  0
    Limits:
      cpu:     500m
      memory:  128Mi
    Requests:
      cpu:        250m
      memory:     64Mi
    Environment:  <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-9dwb4 (ro)

注:limits是对资源的总限制、requests是最低分配的资源。requests一般要比limits要小一些。

注:250m/单核CPU的白分之25 /0.25

注:资源限制 cpu可以直接设置为数字 “1”为1核“2”为2核。

环境变量

通过环境变量配置容器化应用时,需要在容器配置段中嵌套使用env字段

创建pod-env.yaml文件,内容如下:

apiVersion: v1
kind: Pod
metadata:
  name: pod-env
  namespace: dev
spec:
  containers:
  - name: busybox
    image: busybox:1.30
    command: ["/bin/sh","-c","while true;do /bin/echo $(date +%T);sleep 60; done;"]
    env: # 设置环境变量列表
    - name: "username"
      value: "admin"
    - name: "password"
      value: "123456"

env,环境变量,用于在pod中的容器设置环境变量。

# 创建Pod
[root@k8s-master01 ~]# kubectl create -f pod-env.yaml
pod/pod-env created

# 进入容器,输出环境变量
[root@k8s-master01 ~]# kubectl exec pod-env -n dev -c busybox -it /bin/sh
/ # echo $username
admin
/ # echo $password
123456

这种方式,推荐将这些配置单独存储在配置文件中,这种方式将在后面介绍。

apiVersion: v1
kind: Pod
metadata:
  name: pod-example
spec:
  containers:
  - name: nginx
    image: nginx:latest
    imagePullPolicy: Always
    ports:
    - name: http
      containerPort: 80
      protocol: TCP
    command: ["/bin/sh"]
    args: ["-c","while true;do sleep 30;done"]
    env:
    - name: REDIS_HOST
      value: 地址:6379
    - name: LOG_LEVEL
      value: info

共享节点的网络名称空间

同一个pod对象的各容器均运行于一个独立的、隔离的Network名称空间中,共享同一个网络协议栈及相关的网络设备。也有一些特殊的pod对象需要运行于所在节点的名称空间中,执行系统级的管理任务,例如查看和操作节点的网络资源甚至是网络设备等。

apiVersion: v1
kind: Pod
metadata:
  name: pod-example
spec:
  containers:
  ......
  hostNetwork: True

pod的安全上下文

参考博客:https://blog.csdn.net/qq_34556414/article/details/118529692

标签与标签选择器

管理资源标签

标签是kubernetes极具特色的功能之一,它能够附加于kubernetes的任何资源对象之上。简单来说,标签就是键值类型的数据,他们可用于资源创建时直接指定,也可随时按需添加于活动对象中。

创建资源时,可以直接在其metadata中嵌套使用labels字段以定义要附加的标签项。

[root@k8s-master1 ~]# cat pod1.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-example
  labels:
    env: qa
    tier: frontend
spec:
  containers:
  - name: nginx
    image: nginx:latest
    imagePullPolicy: Always
    ports:
    - name: http
      containerPort: 80
      protocol: TCP
    command: ["/bin/sh"]
    args: ["-c","while true;do sleep 30;done"]
[root@k8s-master1 ~]# kubectl apply -f pod1.yaml 
pod/pod-example configured
[root@k8s-master1 ~]# kubectl get pods pod-example --show-labels
NAME          READY   STATUS    RESTARTS      AGE   LABELS
pod-example   1/1     Running   1 (21h ago)   21h   env=qa,tier=frontend
  • 指定显示特定标签
[root@k8s-master1 ~]# kubectl get pods pod-example -L env,tier
NAME          READY   STATUS    RESTARTS      AGE   ENV   TIER
pod-example   1/1     Running   1 (21h ago)   22h   qa    frontend
  • 管理活动对象的标签
[root@k8s-master1 ~]# kubectl label pods/pod-example env2=production
pod/pod-example labeled
[root@k8s-master1 ~]# kubectl get pods pod-example -L env,tier,env2
NAME          READY   STATUS    RESTARTS      AGE   ENV   TIER       ENV2
pod-example   1/1     Running   1 (21h ago)   22h   qa    frontend   production
  • 覆盖已经存在的标签
[root@k8s-master1 ~]# kubectl label pods/pod-example env=qa
error: 'env' already has a value (qa), and --overwrite is false
[root@k8s-master1 ~]# kubectl label pods/pod-example env=qq --overwrite
pod/pod-example labeled
[root@k8s-master1 ~]# kubectl get pods pod-example -L env,tier,env2
NAME          READY   STATUS    RESTARTS      AGE   ENV   TIER       ENV2
pod-example   1/1     Running   1 (21h ago)   22h   qq    frontend   production

标签选择器

标签选择器用于表达标签的查询条件或选择标准,kubernetes api支持两个选择器,基于等值关系以及基于集合关系的标签选择器

  • 选择出env不等于qq的pod
[root@k8s-master1 ~]# kubectl get pods -l "env!=qq" --show-labels
NAME                     READY   STATUS    RESTARTS      AGE   LABELS
nginx-6799fc88d8-46gmb   1/1     Running   4 (22h ago)   9d    app=nginx,pod-template-hash=6799fc88d8
nginx-6799fc88d8-kn2dq   1/1     Running   4 (22h ago)   9d    app=nginx,pod-template-hash=6799fc88d8
nginx-6799fc88d8-qthk8   1/1     Running   4 (22h ago)   9d    app=nginx,pod-template-hash=6799fc88d8
  • 多个标签选择器
[root@k8s-master1 ~]# kubectl get pods -l "env=qq,tier=frontend" --show-labels
NAME          READY   STATUS    RESTARTS      AGE   LABELS
pod-example   1/1     Running   1 (22h ago)   22h   env2=production,env=qq,tier=frontend
  • 显示值为production或dev中的一个的所有pod
[root@k8s-master1 ~]# kubectl get pods -l "env in (qq,qa)" --show-labels
NAME          READY   STATUS    RESTARTS      AGE   LABELS
pod-example   1/1     Running   1 (22h ago)   22h   env2=production,env=qq,tier=frontend
  • 显示所有存在env标签的pod
[root@k8s-master1 ~]# kubectl get pods -l "env " --show-labels
NAME          READY   STATUS    RESTARTS      AGE   LABELS
pod-example   1/1     Running   1 (22h ago)   22h   env2=production,env=qq,tier=frontend
  • 显示所有不存在env标签,但有app的标签的pod
[root@k8s-master1 ~]# kubectl get pods -l '!env,app' --show-labels
NAME                     READY   STATUS    RESTARTS      AGE   LABELS
nginx-6799fc88d8-46gmb   1/1     Running   4 (22h ago)   9d    app=nginx,pod-template-hash=6799fc88d8
nginx-6799fc88d8-kn2dq   1/1     Running   4 (22h ago)   9d    app=nginx,pod-template-hash=6799fc88d8
nginx-6799fc88d8-qthk8   1/1     Running   4 (22h ago)   9d    app=nginx,pod-template-hash=6799fc88d8

pod节点选择器

pod节点选择器是标签及标签选择器的一种应用,它能够让pod对象基于集群中工作节点的标签来挑选倾向运行的目标节点。

  • 给node对象添加标签
[root@k8s-master1 ~]# kubectl get nodes --show-labels
NAME          STATUS   ROLES                  AGE   VERSION   LABELS
k8s-master1   Ready    control-plane,master   9d    v1.22.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master1,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=,node.kubernetes.io/exclude-from-external-load-balancers=
k8s-node1     Ready    <none>                 9d    v1.22.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node1,kubernetes.io/os=linux
k8s-node2     Ready    <none>                 9d    v1.22.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node2,kubernetes.io/os=linux

[root@k8s-master1 ~]# kubectl label nodes k8s-node1 disktype=ssd
node/k8s-node1 labeled

[root@k8s-master1 ~]# kubectl get nodes --show-labels
NAME          STATUS   ROLES                  AGE   VERSION   LABELS
k8s-master1   Ready    control-plane,master   9d    v1.22.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master1,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=,node.kubernetes.io/exclude-from-external-load-balancers=
k8s-node1     Ready    <none>                 9d    v1.22.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=ssd,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node1,kubernetes.io/os=linux
k8s-node2     Ready    <none>                 9d    v1.22.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node2,kubernetes.io/os=linux
  • 指定pod资源调度至这些具有ssd设备的节点上,只需要为其使用spec.nodeSelector标签选择器即可
[root@k8s-master1 ~]# cat pod1.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-example
  labels:
    env: qa
    tier: frontend
spec:
  containers:
  - name: nginx
    image: nginx:latest
    imagePullPolicy: Always
    ports:
    - name: http
      containerPort: 80
      protocol: TCP
    command: ["/bin/sh"]
    args: ["-c","while true;do sleep 30;done"]
  nodeSelector: 
    disktype: ssd

[root@k8s-master1 ~]# kubectl delete pod pod-example
pod "pod-example" deleted
[root@k8s-master1 ~]# kubectl apply -f pod1.yaml 
pod/pod-example created
    
[root@k8s-master1 ~]# kubectl get pods pod-example -o wide
NAME          READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
pod-example   1/1     Running   0          33s   10.244.1.12   k8s-node1   <none>           <none>

pod对象的生命周期

我们一般将pod对象从创建至终的这段时间范围称为pod的生命周期,它主要包含下面的过程:

  • pod创建过程
  • 运行初始化容器(init container)过程
  • 运行主容器(main container)
    • 容器启动后钩子(post start)、容器终止前钩子(pre stop)
    • 容器的存活性探测(liveness probe)、就绪性探测(readiness probe)
  • pod终止过程

pod的相位

在整个生命周期中,Pod会出现5种),分别如下:

  • 挂起(Pending):apiserver已经创建了pod资源对象,但它尚的过程中
  • 运行中(Running):pod已经被调度至某节点,并且所有容器都已经被kubelet创建完成
  • 成功(Succeeded):pod中的所有容器都已经成功终止并且不会被重启
  • 失败(Failed):所有容器都已经终止,但至少有一个容器终止失败,即容器返回了非0值的退出状态
  • 未知(Unknown):apiserver无法正常获取到pod对象的状态信息,通常由网络通信失败所导致

pod的创建过程

  1. 用户通过kubectl或其他api客户端提交pod spec给api server
  2. api server尝试着将pod对象的相关信息存入etcd中,待写入操作执行完成,api server即会返回确认信息至客户端
  3. api server开始反应etcd中的状态变化
  4. 所有的kubernetes组件均使用watch机制来跟踪检查api server上的相关的变动
  5. kube-scheduler(调度器)通过其watcher觉察到api server创建了新的pod对象但尚未绑定至任何工作节点
  6. kube-scheduler为pod对象挑选一个工作节点并将结果信息更新至api server
  7. 调度结果信息由api server更新至etcd存储系统中,而却api server也开始反映此pod对象的调度结果
  8. pod被调度到的目标工作节点上的kubelet尝试在当前节点上调用docker启动容器,并将容器的结果状态回送至api server
  9. api server将pod状态信息存入etcd中
  10. 在etcd确认写入操作成功完成之后,api server将确认信息发送至相关的kubelet事件将通过它被接收

pod的终止过程

  1. 用户发送删除pod对象的命令
  2. api服务器中的pod对象会随着事件的推移而更新,在宽限期内(默认为30秒),pod被视为“dead”
  3. 将pod标记为terminating状态
  4. (与第三步同时运行)kubelet在监控到pod对象转为“Terminating”状态的同时启动Pod关闭过程
  5. (与第三步同时运行)端点控制器监控到pod对象的关闭行为时将其从所有匹配到此端点的service资源的端点列表中移除
  6. 如果当前Pod对象定义了preStop钩子处理器,则在其标记为“terminating”后即会以同步的方式启动执行;如若宽限期结束后,preStop仍未执行结束,则第2步会被重新执行并额外获取一个时长为2秒的小宽限期。
  7. Pod对象中的容器进程收到TERM信号。
  8. 宽限期结束后,若存在任何一个仍在运行的进程,那么Pod对象即会收到SIGKILL信号
  9. Kubelet请求API Server将此Pod资源的宽限期设置为0从而完成删除操作,它变得对用户不再可见。

钩子函数

钩子函数能够感知自身生命周期中的事件,并在相应的时刻到来时运行用户指定的程序代码。

kubernetes在主容器的启动之后和停止之前提供了两个钩子函数:

  • post start:容器创建之后执行,如果失败了会重启容器
  • pre stop :容器终止之前执行,执行完成之后容器将成功终止,在其完成之前会阻塞删除容器的操作

钩子处理器支持使用下面三种方式定义动作:

  • Exec命令:在容器内执行一次命令

    ……
      lifecycle:
        postStart: 
          exec:
            command:
            - cat
            - /tmp/healthy
    ……
    
  • TCPSocket:在当前容器尝试访问指定的socket

    ……      
      lifecycle:
        postStart:
          tcpSocket:
            port: 8080
    ……
    
  • HTTPGet:在当前容器中向某url发起http请求

    ……
      lifecycle:
        postStart:
          httpGet:
            path: / #URI地址
            port: 80 #端口号
            host: 192.168.5.3 #主机地址
            scheme: HTTP #支持的协议,http或者https
    ……
    

接下来,以exec方式为例,演示下钩子函数的使用,创建pod-hook-exec.yaml文件,内容如下:

apiVersion: v1
kind: Pod
metadata:
  name: pod-hook-exec
  namespace: dev
spec:
  containers:
  - name: main-container
    image: nginx:1.17.1
  

标签: 连接器eins探针deins探针连接器d

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台