沪ICP备2021032517号-1

Pod

  |   0 评论   |   0 浏览

pod介绍与原理讲解

Pod是kubernetes中你可以创建和部署的最小也是最简的单位。Pod代表着集群中运行的进程。

Pod中可以共享两种资源:网络和存储。pod中的容器共享IP地址和端口号,它们之间可以通过`localhost`互相发现

在Kubernetes集群中Pod有如下两种使用方式:

  • 一个Pod中运行一个容器。“每个Pod中一个容器”的模式是最常见的用法;在这种使用方式中,你可以把Pod想象成是单个容器的封装,kuberentes管理的是Pod而不是直接管理容器。
  • 在一个Pod中同时运行多个容器。一个Pod中也可以同时封装几个需要紧密耦合互相协作的容器,它们之间共享资源。这些在同一个Pod中的容器可以互相协作成为一个service单位——一个容器共享文件,另一个“sidecar”容器来更新这些文件。Pod将这些容器的存储资源作为一个实体来管理。

Controller可以创建和管理多个Pod,提供副本管理、滚动升级和集群级别的自愈能力。例如,如果一个Node故障,Controller就能自动将该节点上的Pod调度到其他健康的Node上。

包含一个或者多个Pod的Controller示例:

通常,用户不需要手动直接创建Pod,而是应该使用controller(例如Deployments),即使是在创建单个Pod的情况下。Controller可以提供集群级别的自愈功能、复制和升级管理。


pod的创建与删除


pod生命周期管理

Pod 的 status 字段是一个 PodStatus 对象,PodStatus中有一个 phase 字段。

下面是 phase 可能的值:

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

下图是Pod的生命周期示意图,从图中可以看到Pod状态的变化。

image.png

static pods

静态pods是直接由特定节点上的kubelet进程来管理,不通过主控节点上的API服务器。静态pod不关联任何replication controller,它由kubelet进程自己来监控,当pod崩溃时重启该pod。对于静态pod没有健康检查。静态pod始终绑定在某一个kubelet,并且始终运行在同一个节点上。

cat static-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: static-web
spec:
  containers:
    - name: web
      image: nginx:alpine

initContainers

初始化容器(initContaineres),即应用容器在主容器启动之前需要运行的容器,常用于为主容器执行一些预置操作,他们具有两种典型特征

Init 容器总是运行到成功完成为止。

每个 Init 容器都必须在下一个 Init 容器启动之前成功完成。

如果 Pod 的 Init 容器失败,Kubernetes 会不断地重启该 Pod,直到 Init 容器成功为止。然而,如果 Pod 对应的 restartPolicy 为 Never,它不会重新启动。

如果Pod 指定了多个 Init 容器,那些容器会按顺序一次运行一个。 每个 Init 容器必须运行成功,下一个才能够运行。

示例1:在POD启动前修改index.html内容

[root@Master01 cka]# cat init.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-init
spec:
  containers:
  - name: apline
    image: nginx
    command: ['sh', '-c', 'cat /usr/share/nginx/html/index.html && sleep 3600']
    volumeMounts:
    - name: index-dir
      mountPath: "/usr/share/nginx/html"
  volumes:
  - name: index-dir
    emptyDir: {}
  initContainers:
  - name: init
    image: busybox
    command: ['sh', '-c', 'echo "123" > /usr/share/nginx/html/index.html']
    volumeMounts:
    - name: index-dir
      mountPath: "/usr/share/nginx/html"

示例2:

使用init container判断volume是否挂载成功,并切判断里面是否写入文件

apiVersion: v1
kind: Pod
metadata:
  name: init-pod
  namespace: andriy-dang
  labels:
    app: myapp
spec:
  volumes:
  - name: emptydir
    emptyDir: {}
  containers:
  - name: myapp-container
    image: busybox
    command: ["sh", "-c", "if [ -f /test/file ]; then sleep 10000; else exit 1;fi"]
    volumeMounts:
    - mountPath: /test
      name: emptydir
  initContainers:
  - name: init-myservice
    image: busybox
    command: ['sh', '-c', 'echo "hello" > /test/file']
    volumeMounts:
    - mountPath: /test
      name: emptydir

健康检查

该什么时候使用存活(liveness)和就绪(readiness)探针?

如果容器中的进程能够在遇到问题或不健康的情况下自行崩溃,则不一定需要存活探针; kubelet 将根据 Pod 的restartPolicy 自动执行正确的操作。

如果您希望容器在探测失败时被杀死并重新启动,那么请指定一个存活探针,并指定restartPolicy 为 Always 或 OnFailure。

如果要仅在探测成功时才开始向 Pod 发送流量,请指定就绪探针。在这种情况下,就绪探针可能与存活探针相同,但是 spec 中的就绪探针的存在意味着 Pod 将在没有接收到任何流量的情况下启动,并且只有在探针探测成功后才开始接收流量。

如果您希望容器能够自行维护,您可以指定一个就绪探针,该探针检查与存活探针不同的端点。

请注意,如果您只想在 Pod 被删除时能够排除请求,则不一定需要使用就绪探针;在删除 Pod 时,Pod 会自动将自身置于未完成状态,无论就绪探针是否存在。当等待 Pod 中的容器停止时,Pod 仍处于未完成状态。

LivenessProbe

ReadnessProbe

pod的spec常用项

restartPolicy

  • Always:重启容器;Pod phase 仍为 Running。
  • OnFailure:重启容器;Pod phase 仍为 Running。
  • Never:Pod phase 变成 Failed。

imagePullPolicy:

  • Always:每次都下载最新的镜像
  • Never:只使用本地镜像,从不下载
  • IfNotPresent:只有当本地没有的时候才下载镜像

资源限制值和请求值

resources:
  limits: 
    cpu: "500m"
	memory: "2G"
  requests: 
    cpu: "100m"
	memory: "1G"

调度

nodeName: 

nodeSelector: 

启动命令

command

command: [ "/bin/sh","-c","cat /etc/config/keys" ]

secret 环境变量

spec:
  containers:
  - image: hbr.hf.cn/test/solo:v1.2
    name: solo
    env:
    - name: JDBC_USERNAME
      valueFrom:
        secretKeyRef:
          name: mysqlsecret
          key: JDBC_USERNAME
    - name: JDBC.PASSWORD
      valueFrom:
        secretKeyRef:
          name: mysqlsecret
          key: JDBC_PASSWORD

secret voluments

spec:
  containers:
  - name: mypod
    image: redis
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: true
  volumes:
  - name: foo
    secret:
      secretName: mysecret

hostPath 挂载宿主机目录到容器

spec:
  containers:
  - name: mypod
    image: redis
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: true
  volumes:
  - name: foo
    hostPath:
      path: /data
          type: Directory

configMap 挂载配置文件到容器

kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm
apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: gcr.io/google_containers/busybox
      command: [ "/bin/sh","-c","cat /etc/config/keys" ]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        name: special-config
        items:
        - key: special.level
          path: keys
  restartPolicy: Never

special.level 将会被挂载在 config-volume 的文件 /etc/config/keys 下.