【Kubernetes实战】四、Pod详解①——Pod的结构、定义和配置

主要详细介绍Pod资源的各种配置(即yaml文件)和原理。

1. Pod结构和定义

1) Pod结构

在这里插入图片描述
Pause容器,这是每个Pod都会有的一个根容器,它的作用有两个:

  • 可以以它为依据,评估整个Pod的健康状态(Pod的寿命与Pause相同,而与用户容器无关);
  • 可以在根容器上设置IP地址,其它容器都此IP(Pod IP),以实现Pod内部的网络通信(Pod的之间的通信采用虚拟二层网络技术来实现,当前环境用的是Flannel)。
    在这里插入图片描述
    summary:知道pod里有1根容器(Pause)+n个用户容器,可通过Pause容器判断健康状态、可以做IP共享。

2) Pod定义

Pod资源清单(yaml配置文件的编写,以下为常用的参数):

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

可以按照层级结构来学习pod.yaml的编写,如第一层:apiVersion / kind / metadata / spec …;第一层之下又有第二层、第三层…。还可以通过如下命令查看每种资源的可配置项:

kubectl explain 资源类型  # 查看某种资源可配置的一级属性

# 例如
kubectl explain pod

在这里插入图片描述

  • kubernetes中基本所有资源的一级属性都是一样的,主要包含5部分:
    • apiVersion <string>: 版本,由kubernetes内部定义,版本号必须可以用 kubectl api-versions 查询到;
      在这里插入图片描述
    • kind <string>:类型,由kubernetes内部定义,版本号必须可以用 kubectl api-resources 查询到;
      在这里插入图片描述
    • metadata <Object>: 元数据,主要是资源标识和说明,常用的有name、namespace、labels等;常用的如下:
      在这里插入图片描述
    • spec <Object>: 描述,这是配置中最重要的一部分,里面是对各种资源配置的详细描述;
    • status <Object>: 状态信息,里面的内容不需要定义,由kubernetes自动生成,可以通过此字段查看pod(等资源)的状态。例如使用如下命令查看一个pod的状态:
kubectl get pods -n test-ns
kubectl get pod nginx-deploy-8446569dd6-4f45j -o yaml -n test-ns

在这里插入图片描述

查看某种资源属性的子属性:

kubectl explain 资源类型.属性  # 查看某种资源属性的子属性

# 例如
kubectl explain pod.spec

在这里插入图片描述

  • 在上面的一级属性中,spec是重点,其子属性为:
    • containers <[]Object>:容器列表,用于定义容器的详细信息。是一个对象列表因为一个pod中可以运行多个容器;

    • nodeName <String>:指定调度节点,根据nodeName的值将pod调度到指定的Node节点上;

    • nodeSelector <map[]>:根据NodeSelector中定义的信息选择将该Pod调度到包含这些label的Node上;

    • hostNetwork <boolean>:是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络。如果使用宿主机网络,则需要保证端口不要重复,因此一般不使用宿主机IP;
      在这里插入图片描述

    • volumes <[]Object>:存储卷,用于定义Pod上面挂在的存储信息;

    • restartPolicy <string>: 重启策略,表示Pod在遇到故障的时候的处理策略(重启?删除?不管?)。

2. Pod配置

这一节主要来研究 pod.spec.containers 属性,这也是pod配置中最为关键的一项配置。
在这里插入图片描述

常用参数:

FIELDS:
    name <string> # 容器名称
    image <string> # 容器需要的镜像地址
    imagePullPolicy <string> # 镜像拉取策略(本地拉取?远程仓库拉取?...)
    command <[]string> # 容器的启动命令列表,如不指定,使用打包时使用的启动命令
    args <[]string> # 容器的启动命令需要的参数列表
    env <[]Object> # 容器环境变量的配置
    ports <[]Object> # 容器需要暴露的端口号列表
    resources <Object> # 资源限制和资源请求的设置

1) 基本配置:创建一个yaml文件test-container-base.yaml:

# test-container-base.yaml
apiVersion: v1
kind: Pod
metadata: 
    name: test-conta-base
    namespace: test-ns
    labels:
        user: Cherry
spec: 
    containers:
    - name: nginx-base
      image: nginx:1.17.1
    - name: busybox-base
      image: busybox:1.30

上面定义了一个比较简单Pod的配置,里面有两个容器:

  • nginx:用1.17.1版本的nginx镜像创建(nginx是一个轻量级web容器);
  • busybox:用1.30版本的busybox镜像创建(busybox是一个小巧的linux命令集合)。

然后运行如下命令:

kubectl apply -f test-container-base.yaml

在这里插入图片描述
查看一下pod中的详情信息:

kubectl describe pod test-conta-base -n test-ns

在这里插入图片描述
因此只有一个容器成功启动,另一个有问题(后续讲解问题——启动命令部分)。

2) 镜像拉取策略

imagePullPolicy用于设置镜像拉取策略,kubernetes支持配置三种拉取策略:

kubectl explain pod.spec.containers

在这里插入图片描述

  • Always:总是从远程仓库拉取镜像(一直远程下载);
  • IfNotPresent:本地有则使用本地镜像,本地没有则从远程仓库拉取镜像(本地有就本地,本地没有就远程下载)。
  • Never:只使用本地镜像,从不去远程仓库拉取,本地没有就报错(一直使用本地)。

imagePullPolicy的默认值取决于镜像的tag,如果镜像tag为具体版本号,默认策略是:IfNotPresent;如果镜像tag为:latest(最新版本) ,默认策略是always。在实际使用中一般不会使用镜像的最新版本,为了稳定会为其指定版本号,因此常用的imagePullPolicy默认值就是IfNotPresent。

创建如下yaml文件:

# test-image-pullpolicy.yaml
apiVersion: v1
kind: Pod
metadata:
    name: test-image-pullpolicy  # 此name不准使用大写
    namespace: test-ns
spec:
    containers:
    - name: nginx
      image: nginx:1.17.2
      imagePullPolicy: Never
    - name: busybox
      image: busybox:1.30

查看一下本地已经拉取的镜像:

docker images

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以看到,三个节点上均没有上述yaml文件指定的nginx:1.17.2镜像,同时镜像拉去策略为Nerver(只使用本地镜像,从不去远程仓库拉取),那这样的话运行结果是什么?

运行如下命令创建Pod:

kubectl apply -f test-image-pullpolicy.yaml

在这里插入图片描述
发现pod没有启动成功,查看出了什么错误:

kubectl describe pod test-image-pullpolicy -n test-ns

在这里插入图片描述
可以看到镜像不存在。初始将这个pod调度到了node2上,查看node2上的docker images:没有nginx:1.17.2
在这里插入图片描述
若想使其运行成功,则只需修改镜像拉去策略为IfNotPresent:

vim test-image-pullpolicy.yaml
# 修改如下部分:
      imagePullPolicy: IfNotPresent

发现修改文件之后不能直接使用kubectl apply -f命令,因为仅当框框中的spec的值发生改变时才会更新,此处修改imagePullPolicy相当于没有改变。因此需要先删除pod,再重新apply。
在这里插入图片描述

kubectl delete -f test-image-pullpolicy.yaml
kubectl apply -f test-image-pullpolicy.yaml

在这里插入图片描述
虽然还没有运行成功(先不管,此处只关注镜像的拉取),查看一下pod中的状况:
在这里插入图片描述
此时可以看到,这个pod被调度到了node2上,且nginx:1.17.2已经被成功拉取,查看一下node2节点上的docker镜像:
在这里插入图片描述

3) 启动命令

在前面的案例中,一直有一个问题没有解决,就是的busybox容器一直没有成功运行(1/2:只运行了nginx容器,busybox容器没有成功运行)
在这里插入图片描述

那么到底是什么原因导致这个容器的故障呢?原来busybox并不是一个程序,而是类似于一个工具类的集合,即busybox里面并没有一个进程在运行,而都是一些小的命令,kubernetes集群启动管理后,它会自动关闭(因为容器中没有一个进程在占据着他,因此一启动就结束了)。解决方法就是让其一直在运行(例如在busybox中运行一个死循环),这就用到了command配置

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

# test-pod-command.yaml
apiVersion: v1
kind: Pod
metadata:
    name: test-pod-command
    namespace: test-ns
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;"]

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秒向文件中写入当前时间。

在这里插入图片描述
显示nginx与busybox容器都运行成功了。查看/tmp/hello.txt是否有内容,即上述command指令是否正常执行:首先要进入容器:

# kubectl exec pod名称 -n 命名空间 -it -c 容器名称 /bin/sh # 在容器内部执行命令
kubectl exec test-pod-command -n test-ns -it -c busybox /bin/sh
# exec:执行,在docker中有同样的命令
# -n:指定命名空间
# -it:以交互式方式执行
# -c:指定容器,当这个颇多、中只有一个容器时可以不写

在这里插入图片描述

  • 【说明】:

通过上面发现command已经可以完成启动命令和传递参数的功能,为什么这里还要提供一个args选项,用于传递参数呢?这其实跟docker有点关系,kubernetes中的command、args两项其实是实现覆盖Dockerfile中ENTRYPOINT的功能

  1. 如果command和args均没有写,那么用Dockerfile的配置;
  2. 如果command写了,但args没有写,那么Dockerfile默认的配置会被忽略,执行输入的command;
  3. 如果command没写,但args写了,那么Dockerfile中配置的ENTRYPOINT的命令会被执行,使用当前args的参数(相当于使用Dockerfile命令,但为其配置新的参数);
  4. 如果command和args都写了,那么Dockerfile的配置被忽略,执行command并追加上args参数。

4) 环境变量

env参数:环境变量,用于在pod中的容器设置环境变量。数组类型,一个环境变量就是一个键值对。
在这里插入图片描述

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

apiVersion: v1
kind: Pod
metadata:
    name: test-pod-env
    namespace: test-ns
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"

首先创建pod:

kubectl apply -f test-pod-env.yaml -n test-ns

然后进入容器,查看环境变量:

kubectl exec test-pod-env -n test-ns -it /bin/sh

在这里插入图片描述
这种方式不是很推荐,推荐将这些配置单独存储在配置文件中(在后面介绍)。

5) 端口设置

端口的设置对应pod.spec.containers.ports=容器需要暴露的端口号列表,查看ports的子选项:
在这里插入图片描述
hostIP、hostPort解释:
在这里插入图片描述

编写一个测试案例test-pod-ports.yaml:

apiVersion: v1
kind: Pod
metadata:
    name: test-pod-ports
    namespace: test-ns
spec:
    containers:
    - name: nginx
      image: nginx:1.17.1
      ports: # 设置容器暴露的端口列表
      - name: nginx-port
        containerPort: 80
        protocol: TCP

在这里插入图片描述
在这里插入图片描述
访问容器中的程序需要使用的是 podIP:containerPort

6) 资源配额

容器中的程序要运行,肯定是要占用一定资源的,比如cpu和内存等,如果不对某个容器的资源做限制,那么它就可能吃掉大量资源,导致其它容器无法运行(一个节点上的资源总额是一定的,例如内存,若A容器忽然“发疯”,开始大量消耗内存,如果未对其进行限制,则势必会导致BCDE…等其他容器无法正常运行)。针对这种情况,kubernetes提供了对内存和cpu的资源进行配额的机制,这种机制主要通过resources选项实现,他有两个子选项:可以通过下面两个选项设置资源的上下限。

  • limits:用于限制运行时容器的最大占用资源,当容器占用资源超过limits时会被终止,并进行重启
  • requests :用于设置容器需要的最小资源,如果环境资源不够,容器将无法启动

编写一个测试案例(针对CPU和内存),创建test-pod-resources.yaml

apiVersion: v1
kind: Pod
metadata:
    name: test-pod-resources
    namespace: test-ns
spec:
    containers:
    - name: nginx
      image: nginx:1.17.1
      resources: # 资源配额
        limits: # 限制资源(上限)
          cpu: "2" # CPU限制,单位是core数
          memory: "10Gi" # 内存限制
        requests: # 请求资源(下限)
          cpu: "1" # CPU限制,单位是core数
          memory: "10Mi" # 内存限制
  • cpu:core数,可以为整数或小数;
  • memory: 内存大小,可以使用Gi、Mi、G、M等形式。

在这里插入图片描述
运行成功了,即当前的环境满足配置文件中的条件了。若将pod的资源下限改为10Gi还能运行成功吗:

        requests: # 请求资源(下限)
          cpu: "1" # CPU限制,单位是core数
          memory: "10Gi" # 内存限制

首先删除原pod:

kubectl delete -f test-pod-resources.yaml

然后修改test-pod-resources.yaml中的上述配置信息,重新创建pod:
在这里插入图片描述
可以看到,新创建的pod没有运行成功,处于Pending状态。查看详细信息:
在这里插入图片描述
显示三个节点上没有可以满足内存需求的,因此没有调度部署成功。

参考:B站大学

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值