Kubernetes Pod概述

Pod简介

Pod是Kubernetes创建或部署的最小/最简单的基本单位,一个Pod代表集群上正在运行的一个进程。
一个Pod封装一个应用容器,Pod代表部署的一个单位。
Pods提供两种共享资源:网络和存储。
网络:每个Pod被分配一个独立的IP地址,Pod中的每个容器共享网络命名空间,包括IP地址和网络端口。
存储:Pod可以指定一组共享存储volumes。Pod中的所有容器都可以访问共享volumes,允许这些容器共享数据。
Pod不会自愈。如果Pod运行的Node故障,或者是调度器本身故障,这个Pod就会被删除。同样的,如果Pod所在Node缺少资源或者Pod处于维护状态,Pod也会被驱逐。Controller可以创建和管理多个Pod,提供副本管理、滚动升级和集群级别的自愈能力。例如,如果一个Node故障,Controller就能自动将该节点上的Pod调度到其他健康的Node上。

POD生命周期

Pod 的 status 定义在 PodStatus 对象中,其中有一个 phase 字段。

  • 挂起(Pending):Pod 已被 Kubernetes 系统接受,但有一个或者多个容器镜像尚未创建。等待时间包括调度 Pod 的时间和通过网络下载镜像的时间,这可能需要花点时间。
  • 运行中(Running):该 Pod 已经绑定到了一个节点上,Pod 中所有的容器都已被创建。至少有一个容器正在运行,或者正处于启动或重启状态。
  • 成功(Succeeded):Pod 中的所有容器都被成功终止,并且不会再重启。
  • 失败(Failed):Pod 中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出或者被系统终止。
  • 未知(Unknown):因为某些原因无法取得 Pod 的状态,通常是因为与 Pod 所在主机通信失败。

容器存活探针,健康检查

探针 是由 kubelet 对容器执行的定期诊断。要执行诊断,kubelet 调用由容器实现的 Handler。

  • ExecAction:在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。
  • TCPSocketAction:对指定端口上的容器的 IP 地址进行 TCP 检查。如果端口打开,则诊断被认为是成功的。
  • HTTPGetAction:对指定的端口和路径上的容器的 IP 地址执行 HTTP Get 请求。如果响应的状态码大于等于200 且小于 400,则诊断被认为是成功的。

livenessProbe:探测应用是否处于健康状态,如果不健康则删除重建改容器
readinessProbe:探测应用是否启动完成并且处于正常服务状态,如果不正常则更新容器的状态

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: nginx
  name: nginx
spec:
    containers:
    - image: nginx
      imagePullPolicy: Always
      name: http
      livenessProbe:
        httpGet:
        path: /
        port: 80
        initialDelaySeconds: 15
        timeoutSeconds: 1
      readinessProbe:
        httpGet:
        path: /ping
        port: 80
        initialDelaySeconds: 5
        timeoutSeconds: 1

诊断结果状态:

  • 成功:容器通过了诊断。
  • 失败:容器未通过诊断。
  • 未知:诊断失败,因此不会采取任何行动。

初始化容器

Init Container在所有容器运行之前执行(run-to-completion),常用来初始化配置。

apiVersion: v1
kind: Pod
metadata:
  name: init-demo
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80
    volumeMounts:
    - name: workdir
      mountPath: /usr/share/nginx/html
  # These containers are run during pod initialization
  initContainers:
  - name: install
    image: busybox
    command:
    - wget
    - "-O"
    - "/work-dir/index.html"
    - http://kubernetes.io
    volumeMounts:
    - name: workdir
      mountPath: "/work-dir"
  dnsPolicy: Default
  volumes:
  - name: workdir
    emptyDir: {}

重启策略

PodSpec 中有一个 restartPolicy 字段,可能的值为 Always、OnFailure 和 Never。默认为 Always,意味着容器在探测失败时被杀死并重新启动。

  • Always:只要退出就重启
  • OnFailure:失败退出(exit code不等于0)时重启
  • Never:只要退出就不再重启

这里的重启是指在Pod所在Node上面本地重启,并不会调度到其他Node上去。

ImagePullPolicy

支持三种ImagePullPolicy

  • Always:不管镜像是否存在都会进行一次拉取。
  • Never:不管镜像是否存在都不会进行拉取
  • IfNotPresent:只有镜像不存在时,才会进行镜像拉取。
    注意:
  • 默认为IfNotPresent,但:latest标签的镜像默认为Always。
  • 拉取镜像时docker会进行校验,如果镜像中的MD5码没有变,则不会拉取镜像数据。
  • 生产环境中应该尽量避免使用:latest标签,而开发环境中可以借助:latest标签自动拉取最新的镜像。

指定Node部署

通过nodeSelector,一个Pod可以指定它所想要运行的Node节点。
首先给Node加上标签:

$ kubectl label nodes <your-node-name> disktype=ssd

接着,指定该Pod只想运行在带有disktype=ssd标签的Node上:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:
    disktype: ssd

给容器和Pod分配内存资源

配置内存申请和限制

memory-request-limit.yaml

apiVersion: v1
kind: Pod
metadata:
  name: memory-demo
spec:
  containers:
  - name: memory-demo-ctr
    image: vish/stress
    resources:
      limits:
        memory: "200Mi"
      requests:
        memory: "100Mi"
    args:
    - -mem-total
    - 150Mi
    - -mem-alloc-size
    - 10Mi
    - -mem-alloc-sleep
    - 1s

创建一个容器的Pod,这个容器申请100M的内存,并且内存限制设置为200M,args代码段提供了容器所需的参数。-mem-total 150Mi告诉容器尝试申请150M 的内存。
在mem-example命名空间中创建pod:

# kubectl create -f memory-request-limit.yaml --namespace=mem-example

验证Pod的容器是否正常运行:

# kubectl get pod memory-demo --namespace=mem-example

查看Pod的详细信息:

# kubectl get pod memory-demo --output=yaml --namespace=mem-example
-----------------
...
resources:
  limits:
    memory: 200Mi
  requests:
    memory: 100Mi
...

POD实际使用内存约为150M。
删除Pod:

# kubectl delete pod memory-demo --namespace=mem-example

当创建POD时内存超出限制内存,则POD会被kill掉,reason: OOMKilled。
当创建POD时内存超出节点能力范围时,Pod的状态是Pending,因为Pod不会被调度到任何节点,它会一直保持在Pending状态下,因为节点上没有足够的内存。
如果没有内存限制,则容器使用内存资源没有上限,容器可以使用当前节点上所有可用的内存资源。

给容器和Pod分配CPU资源

给容器声明CPU限制

cpu-request-limit.yaml

apiVersion: v1
kind: Pod
metadata:
  name: cpu-demo
spec:
  containers:
  - name: cpu-demo-ctr
    image: vish/stress
    resources:
      limits:
        cpu: "1"
      requests:
        cpu: "0.5"
    args:
    - -cpus
    - "2"

会创建一个只有一个容器的Pod,这个容器申请0.5个CPU,并且CPU限制设置为1. cpus "2"代码告诉容器尝试使用2个CPU资源。
在cpu-example命名空间中创建pod:

# kubectl create -f cpu-request-limit.yaml --namespace=cpu-example

验证Pod的容器是否正常运行:

# kubectl get pod cpu-demo --namespace=cpu-example

查看Pod的详细信息:

# kubectl get pod cpu-demo --output=yaml --namespace=cpu-example
--------------
resources:
  limits:
    cpu: "1"
  requests:
    cpu: 500m

当创建的pod申请的CPU资源超过集群node所提供的资源,那么pod会一直处于Pending状态,那是因为这个Pod并不会被调度到任何节点上,所以它会一直保持这种状态。
如果你指定容器的CPU限额,则容器使用CPU资源没有上限,它可以使用它运行的Node上所有的CPU资源。

通过环境变量向容器暴露 Pod 信息

使用 Pod 字段作为环境变量的值

dapi-envars-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: dapi-envars-fieldref
spec:
  containers:
    - name: test-container
      image: k8s.gcr.io/busybox
      command: [ "sh", "-c"]
      args:
      - while true; do
          echo -en '\n';
          printenv MY_NODE_NAME MY_POD_NAME MY_POD_NAMESPACE;
          printenv MY_POD_IP MY_POD_SERVICE_ACCOUNT;
          sleep 10;
        done;
      env:
        - name: MY_NODE_NAME
          valueFrom:
            fieldRef:
              fieldPath: spec.nodeName
        - name: MY_POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: MY_POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: MY_POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        - name: MY_POD_SERVICE_ACCOUNT
          valueFrom:
            fieldRef:
              fieldPath: spec.serviceAccountName
  restartPolicy: Never

env 字段是 EnvVars 的数组。数组中的第一个元素指定 MY_NODE_NAME 环境变量从 Pod 的 spec.nodeName 字段中获取其值。字段是 Pod 的字段,不是 Pod 中的容器的字段。
创建pod:

# kubectl create -f dapi-envars-pod.yaml

查看容器日志:

# kubectl logs dapi-envars-fieldref
-------------
minikube
dapi-envars-fieldref
default
172.17.0.48
default

配置文件的 command 和 args 字段。当容器启动时,它将 5 个环境变量的值写到标准输出中。每十秒钟重复一次。
进入容器内查看环境变量:

MY_POD_SERVICE_ACCOUNT=default
...
MY_POD_NAMESPACE=default
MY_POD_IP=172.17.0.4
...
MY_NODE_NAME=minikube
...
MY_POD_NAME=dapi-envars-fieldref

使用容器字段作为环境变量的值

dapi-envars-container.yaml

apiVersion: v1
kind: Pod
metadata:
  name: dapi-envars-resourcefieldref
spec:
  containers:
    - name: test-container
      image: k8s.gcr.io/busybox:1.24
      command: [ "sh", "-c"]
      args:
      - while true; do
          echo -en '\n';
          printenv MY_CPU_REQUEST MY_CPU_LIMIT;
          printenv MY_MEM_REQUEST MY_MEM_LIMIT;
          sleep 10;
        done;
      resources:
        requests:
          memory: "32Mi"
          cpu: "125m"
        limits:
          memory: "64Mi"
          cpu: "250m"
      env:
        - name: MY_CPU_REQUEST
          valueFrom:
            resourceFieldRef:
              containerName: test-container
              resource: requests.cpu
        - name: MY_CPU_LIMIT
          valueFrom:
            resourceFieldRef:
              containerName: test-container
              resource: limits.cpu
        - name: MY_MEM_REQUEST
          valueFrom:
            resourceFieldRef:
              containerName: test-container
              resource: requests.memory
        - name: MY_MEM_LIMIT
          valueFrom:
            resourceFieldRef:
              containerName: test-container
              resource: limits.memory
  restartPolicy: Never

env 字段是 EnvVars 的数组。数组中的第一个元素指定 MY_CPU_REQUEST 环境变量从名为 test-container 的容器的 requests.cpu 字段中获取其值。类似地,其他环境变量从容器字段中获取它们的值。
创建pod,查看pod日志:

# kubectl create -f dapi-envars-container.yaml
# kubectl logs dapi-envars-resourcefieldref
--------------
1
1
33554432
67108864
posted @ 2019-11-12 10:20  我是一条最咸的咸鱼  阅读(540)  评论(0编辑  收藏  举报
返回顶部