【重识云原生】第六章容器6.4.2.2节——Pod使用(上)

时间:2022-09-29 13:41:46

【重识云原生】第六章容器6.4.2.2节——Pod使用(上)

1 Pod使用

1.1 Pod 定义

        通过 yaml 或 json 描述 Pod 和其内容器的运行环境以及期望状态,比如一个最简单的 nginx pod 可以定义为:

apiVersion: v1 
kind: Pod 
metadata: 
  name: nginx 
  labels: 
    app: nginx 
spec: 
  containers: 
    - name: nginx 
      image: nginx 
      ports: 
        - containerPort: 80

        在生产环境中,推荐使用 Deployment、StatefulSet、Job 或者 CronJob 等控制器来创建 Pod,而不推荐直接创建 Pod。

1.2 pod模板

        控制器(如deployment、daemonset、statefulset等)是通过创建pod模板来创建和管理pod的,PodTemplate是用于创建pod的规范,并且包含在deployment、job和daemonset中。每个控制器使用自己内部的Pod模板来创建实际的Pod。PodTemplate是运行应用程序所需的任何控制器的一部分。下面的示例是一个简单的Job的清单,包含一个podtemplate,这个是用来生成pod的模板。该Pod中的容器会打印一条消息,然后暂停。

#cat job-template.yaml 
apiVersion: batch/v1 
kind: Job 
metadata: 
    name: hello 
spec: 
  template: 
    # This is the pod template 
    spec: 
      containers: 
        - name: hello 
          image: busybox 
          command: ['sh', '-c', 'echo "Hello, Kubernetes!" && sleep 3600'] 
      restartPolicy: OnFailure 
    # The pod template ends here

        修改pod template或切换到新的pod tmplate对已经存在的pod没有影响。 POD不直接接收模板更新,而是创建一个新的POD来匹配修改后的POD模板。例如,控制器可确保正在运行的Pod与当前Pod模板匹配。如果模板已更新,则控制器必须删除现有的Pod并根据更新的模板创建新的Pod。每个控制器都实现自己的规则来处理Pod模板的更改。在节点上,kubelet不直接观察或管理有关Pod模板和更新的任何详细信息。

1.3 和pod相关的api对象

1.3.1 kubectl explain pods 

        上面命令可以看到和pod相关的api对象有哪些,也就是通过资源清单yaml部署一个pod时需要哪些字段。

1.3.2 apiVersion

        apiVersion定义了此对象表示的版本化模式。服务器应将已识别的模式转换为最新的内部值,并可能拒绝无法识别的值。更多信息参考:

community/api-conventions.md at master · kubernetes/community · GitHub

        查看k8s集群支持的apiVersion有哪些,可以使用下面的命令:

kubectl api-versions 

admissionregistration.k8s.io/v1 
admissionregistration.k8s.io/v1beta1 
apiextensions.k8s.io/v1 
apiextensions.k8s.io/v1beta1 
apiregistration.k8s.io/v1 
apiregistration.k8s.io/v1beta1 
apps/v1 authentication.k8s.io/v1 
authentication.k8s.io/v1beta1 
authorization.k8s.io/v1 
authorization.k8s.io/v1beta1 
autoscaling/v1 autoscaling/v2beta1 
autoscaling/v2beta2 batch/v1 
batch/v1beta1 
certificates.k8s.io/v1beta1 
coordination.k8s.io/v1 
coordination.k8s.io/v1beta1 
crd.projectcalico.org/v1 
discovery.k8s.io/v1beta1 
events.k8s.io/v1beta1 
extensions/v1beta1 
metrics.k8s.io/v1beta1 
networking.k8s.io/v1 
networking.k8s.io/v1beta1 
node.k8s.io/v1beta1 
policy/v1beta1 
rbac.authorization.k8s.io/v1 
rbac.authorization.k8s.io/v1beta1 
scheduling.k8s.io/v1 
scheduling.k8s.io/v1beta1 
storage.k8s.io/v1 
storage.k8s.io/v1beta1 
v1

1.3.3 kind

        Kind是表示此对象表示的REST资源的字符串值。服务器可以从客户端提交请求的端点推断出这一点,说白了就是表示我们要创建什么资源,如deployment、statefulset、pod、service、ingress。

        查看更详细信息可参考:

https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds

1.3.4 metadata

        标准对象的元数据。更多信息:

community/api-conventions.md at master · kubernetes/community · GitHub

1.3.5 spec

        指定容器的所需行为。更多信息:

https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

1.3.6 status

        最近观察到的pod的状态。此数据可能不是最新的。Status不需要在pod或者其他资源中定义,这个默认是存在的,更多信息:https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status

1.4 怎么创建pod?

        1.通过定义资源清单yaml文件(就是以yaml结尾的文件)创建pod,在k8s的master节点操作。

        查看定义资源清单需要哪些字段

kubectl explain pods 
kubectl explain pods.apiVersion 
kubectl explain pods.kind 
kubectl explain pods.metadata 
kubectl explain pods.spec
cat pod.yaml 

apiVersion: v1 
kind: Pod 
metadata: 
  name: web 
  namespace: default 
  labels: 
    web1: tomcat 
spec: 
  containers: 
    - name: tomcat1 
      image: tomcat:8.5-jre8-alpine 
      imagePullPolicy: IfNotPresent 

# 通过kubectl apply创建一个pod 
kubectl apply -f pod.yaml 

# 查看pod创建的情况 
kubectl get pods 

# 显示如下: 
NAME READY STATUS RESTARTS AGE 
web 0/1 ContainerCreating 0 37s 

# 查看pod的详细信息 
kubectl describe pods web 

# pod.yaml定义的所有资源都删除掉 
kubectl delete -f pod.yaml yaml 

# 查看pod调度到哪个节点 
kubectl get pods -o wide 

# 显示如下: 
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES 
web 1/1 Running 0 5m30s 10.244.1.21 node1 <none> <none> 

# 查看pod日志 
kubectl logs web 

# 查看pod里指定容器的日志 
kubectl logs -c tomcat1 web 

# 进入到刚才创建的pod,刚才创建的pod名字是web 
kubectl exec -it web -- /bin/bash 

# 假如pod里有多个容器,进入到pod里的指定容器,按如下命令: 
kubectl exec -it web -c tomcat1 -- /bin/bash 

# 可查看到刚才创建的pod 
kubectl get pods

1.5 使用 Volume

        Volume 可以为容器提供持久化存储,比如:

apiVersion: v1 
kind: Pod 
metadata: 
  name: redis 
spec: 
  containers: 
    - name: redis 
      image: redis 
      volumeMounts: 
        - name: redis-storage 
          mountPath: /data/redis 
  volumes: 
    - name: redis-storage 
      emptyDir: {}

        更多挂载存储卷的方法参考 Volume

1.6 私有镜像

        在使用私有镜像时,需要创建一个 docker registry secret,并在容器中引用。

        创建 docker registry secret:

kubectl create secret docker-registry regsecret --docker-server=<your-registry-server> --docker-username=<your-name> --docker-password=<your-pword> --docker-email=<your-email>

        比如使用 Azure Container Registry(ACR):

ACR_NAME=dregistry 
SERVICE_PRINCIPAL_NAME=acr-service-principal 

# Populate the ACR login server and resource id. 
ACR_LOGIN_SERVER=$(az acr show --name $ACR_NAME --query loginServer --output tsv) 
ACR_REGISTRY_ID=$(az acr show --name $ACR_NAME --query id --output tsv) 

# Create a contributor role assignment with a scope of the ACR resource. 
SP_PASSWD=$(az ad sp create-for-rbac --name $SERVICE_PRINCIPAL_NAME --role Reader --scopes $ACR_REGISTRY_ID --query password --output tsv) 

# Get the service principle client id. 
CLIENT_ID=$(az ad sp show --id http://$SERVICE_PRINCIPAL_NAME --query appId --output tsv) 

# Create secret 
kubectl create secret docker-registry acr-auth --docker-server $ACR_LOGIN_SERVER --docker-username $CLIENT_ID --docker-password $SP_PASSWD --docker-email local@local.domain

        在引用 docker registry secret 时,有两种可选的方法:

        第一种是直接在 Pod 描述文件中引用该 secret:

apiVersion: v1 
kind: Pod 
metadata: 
  name: private-reg 
spec: 
  containers: 
    - name: private-reg-container 
      image: dregistry.azurecr.io/acr-auth-example 
      imagePullSecrets: 
        - name: acr-auth

        第二种是把 secret 添加到 service account 中,再通过 service account 引用(一般是某个 namespace 的 default service account):

$ kubectl get secrets myregistrykey 
$ kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "myregistrykey"}]}' 

$ kubectl get serviceaccounts default -o yaml 
apiVersion: v1 
kind: ServiceAccount 
metadata: 
  creationTimestamp: 2015-08-07T22:02:39Z 
  name: default 
  namespace: default 
  selfLink: /api/v1/namespaces/default/serviceaccounts/default 
  uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6 
secrets: 
  - name: default-token-uudge 
imagePullSecrets: 
  - name: myregistrykey

1.7 重启策略(restartPolicy):Pod在遇到故障之后重启的动作

        支持三种 RestartPolicy:

  • Always:当容器失效时,由Kubelet自动重启该容器。RestartPolicy的默认值。
  • OnFailure:当容器终止运行且退出码不为0时由Kubelet重启。
  • Never:无论何种情况下,Kubelet都不会重启该容器。

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

kubect1 edit deployment nginx -deployment restartPolicy: Always

示例

vim pod3.yaml 
apiVersion: v1 
kind: Pod 
metadata: 
  name: foo 
spec: 
  containers: 
    name: busybox 
    image: busybox 
    args: /bin/sh c sleep 30; exit 3
kubectl apply -f pod3.yaml

        查看Pod状态, 等容器启动后30秒后执行exit退出进程进入error状态, 就会重启次数加1

kubectl get pods
kubectl delete -f pod3.yaml 
vim pod3.yaml 
apiVersion: v1 
kind: Pod 
metadata: 
  name: foo 
spec: 
  containers: 
    name: busybox 
    image: busybox 
    args: /bin/sh c sleep 30; exit 3 
  restartPolicy: Never #restartPolicy与containers要对齐

1.8 环境变量

        环境变量为容器提供了一些重要的资源,包括容器和 Pod 的基本信息以及集群中服务的信息等:

(1) hostname

        HOSTNAME 环境变量保存了该 Pod 的 hostname。

(2)容器和 Pod 的基本信息

        Pod 的名字、命名空间、IP 以及容器的计算资源限制等可以以 Downward API 的方式获取并存储到环境变量中。

apiVersion: v1 
kind: Pod 
metadata: 
  name: test 
spec: 
  containers: 
    - name: test-container 
      image: gcr.io/google_containers/busybox 
      command: ["sh", "-c"] 
      args: - env 
      resources: 
        requests: 
          memory: "32Mi" 
          cpu: "125m" 
          limits: 
            memory: "64Mi" 
            cpu: "250m" 
        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 
          - 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

(3) 集群中服务的信息

        容器的环境变量中还可以引用容器运行前创建的所有服务的信息,比如默认的 kubernetes 服务对应以下环境变量:

KUBERNETES_PORT_443_TCP_ADDR=10.0.0.1 
KUBERNETES_SERVICE_HOST=10.0.0.1 
KUBERNETES_SERVICE_PORT=443 
KUBERNETES_SERVICE_PORT_HTTPS=443 
KUBERNETES_PORT=tcp://10.0.0.1:443 
KUBERNETES_PORT_443_TCP=tcp://10.0.0.1:443 
KUBERNETES_PORT_443_TCP_PROTO=tcp 
KUBERNETES_PORT_443_TCP_PORT=443

        由于环境变量存在创建顺序的局限性(环境变量中不包含后来创建的服务),推荐使用 DNS 来解析服务。

1.9 镜像拉取策略

支持三种 ImagePullPolicy:

  • Always:不管本地镜像是否存在都会去仓库进行一次镜像拉取。校验如果镜像有变化则会覆盖本地镜像,否则不会覆盖。
  • Never:只是用本地镜像,不会去仓库拉取镜像,如果本地镜像不存在则Pod运行失败。
  • IfNotPresent:只有本地镜像不存在时,才会去仓库拉取镜像。ImagePullPolicy的默认值。

注意:

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

参考链接

pod详解 - 快乐嘉年华 - 博客园

Kubernetes中pod详解_人间不值得-的博客-CSDN博客

Pod详解_我的紫霞辣辣的博客-CSDN博客_pod方法

k8s之pod与Pod控制器 - woaiyitiaochai - 博客园

kubernetes 实践四:Pod详解 - xingyys - 博客园

Pod · Kubernetes指南

K8S实战基础知识之POD - 知乎

K8S Pod详解_ldd儆儆的博客-CSDN博客_k8s pod

k8s之pod详解_爱show的小卤蛋的博客-CSDN博客_k8s pod