美文网首页
Kubernetes——Pod简介

Kubernetes——Pod简介

作者: 懒无趣 | 来源:发表于2020-12-29 22:20 被阅读0次

    Pod

    凡是调度、网络、存储,以及安全相关的属性,基本上是 Pod 级别的。

    凡是 Pod 中的容器要共享宿主机的 Namespace,也一定是 Pod 级别的定义

    原理

    Pod 里的所有容器,共享的是同一个 Network Namespace,并且可以声明共享同一个 Volume。其实全部容器跑在一个容器里面名为Infra(k8s.gcr.io/pause)因此

    • 它们可以直接使用 localhost 进行通信;
    • 它们看到的网络设备跟 Infra 容器看到的完全一样;
    • 一个 Pod 只有一个 IP 地址,也就是这个 Pod 的 Network Namespace 对应的 IP 地址;
    • 当然,其他的所有网络资源,都是一个 Pod 一份,并且被该 Pod 中的所有容器共享;
    • Pod 的生命周期只跟 Infra 容器一致,而与容器 A 和 B 无关。

    Network NameSpace

    Mount NameSpace

    一个pod里面的容器共享mount namespace,所以不同容器挂载的volume是可以共享的,那么就有一种设计模式叫sidecar,比如:

    我现在有一个应用,需要不断地把日志文件输出到容器的 /var/log 目录中。这时,我就可以把一个 Pod 里的 Volume 挂载到应用容器的 /var/log 目录上。然后,我在这个 Pod 里同时运行一个 sidecar 容器,它也声明挂载同一个 Volume 到自己的 /var/log 目录上。这样,接下来 sidecar 容器就只需要做一件事儿,那就是不断地从自己的 /var/log 目录里读取日志文件,转发到 MongoDB 或者 Elasticsearch 中存储起来。这样,一个最基本的日志收集工作就完成了。
    

    NodeSelector

    是一个供用户将 Pod 与 Node 进行绑定的字段,用法如下所示:

    
    apiVersion: v1
    kind: Pod
    ...
    spec:
     nodeSelector:
       disktype: ssd
    

    NodeName

    一旦 Pod 的这个字段被赋值,Kubernetes 项目就会被认为这个 Pod 已经经过了调度,调度的结果就是赋值的节点名字。所以,这个字段一般由调度器负责设置,但用户也可以设置它来“骗过”调度器,当然这个做法一般是在测试或者调试的时候才会用到。

    HostAliases

    定义了 Pod 的 hosts 文件(比如 /etc/hosts)里的内容,用法如下:

    
    apiVersion: v1
    kind: Pod
    ...
    spec:
      hostAliases:
      - ip: "10.1.2.3"
        hostnames:
        - "foo.remote"
        - "bar.remote"
    ...
    

    Containers

    ImagePullPolicy

    • 它定义了镜像拉取的策略,ImagePullPolicy 的值默认是 Always,即每次创建 Pod 都重新拉取一次镜像。另外,当容器的镜像是类似于 nginx 或者 nginx:latest 这样的名字时,ImagePullPolicy 也会被认为 Always。

    • 而如果它的值被定义为 Never 或者 IfNotPresent,则意味着 Pod 永远不会主动拉取这个镜像,或者只在宿主机上不存在这个镜像时才拉取。

    Lifecycle

    一些hooks

    
    apiVersion: v1
    kind: Pod
    metadata:
      name: lifecycle-demo
    spec:
      containers:
      - name: lifecycle-demo-container
        image: nginx
        lifecycle:
          postStart:
            exec:
              command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
          preStop:
            exec:
              command: ["/usr/sbin/nginx","-s","quit"]
    

    Pod 对象在 Kubernetes 中的生命周期。

    Pod 生命周期的变化,主要体现在 Pod API 对象的 Status 部分,这是它除了 Metadata 和 Spec 之外的第三个重要字段。其中,pod.status.phase,就是 Pod 的当前状态,它有如下几种可能的情况:

    1. Pending。这个状态意味着,Pod 的 YAML 文件已经提交给了 Kubernetes,API 对象已经被创建并保存在 Etcd 当中。但是,这个 Pod 里有些容器因为某种原因而不能被顺利创建。比如,调度不成功。
    2. Running。这个状态下,Pod 已经调度成功,跟一个具体的节点绑定。它包含的容器都已经创建成功,并且至少有一个正在运行中。
    3. Succeeded。这个状态意味着,Pod 里的所有容器都正常运行完毕,并且已经退出了。这种情况在运行一次性任务时最为常见。
    4. Failed。这个状态下,Pod 里至少有一个容器以不正常的状态(非 0 的返回码)退出。这个状态的出现,意味着你得想办法 Debug 这个容器的应用,比如查看 Pod 的 Events 和日志。
    5. Unknown。这是一个异常状态,意味着 Pod 的状态不能持续地被 kubelet 汇报给 kube-apiserver,这很有可能是主从节点(Master 和 Kubelet)间的通信出现了问题。

    livenessProbe

    livenessProbe:
    exec:
    command: ["mysqladmin", "ping"]
    initialDelaySeconds: 30
    periodSeconds: 10
    timeoutSeconds: 5
    

    执行命令失败则pod会进入failed(命令执行返回结果不是0[exit_code])

    readinessProbe

    readinessProbe:
    exec:
    # Check we can execute queries over TCP (skip-networking is off).
    command: ["mysql", "-h", "127.0.0.1", "-e", "SELECT 1"]
    initialDelaySeconds: 5
    periodSeconds: 2
    

    执行命令失败后通过Service访问不了而不会Failed

    nodeAffinity 节点亲和性

    官方例子

    下面例子是一种required的亲和,该pv所部署到pod都必须满足 kubernetes.io/hostname = node-1。还有很多表达式,具体参考官网文档。

    
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: example-pv
    spec:
      capacity:
        storage: 5Gi
      volumeMode: Filesystem
      accessModes:
      - ReadWriteOnce
      persistentVolumeReclaimPolicy: Delete
      storageClassName: local-storage
      local:
        path: /mnt/disks/vol1
      nodeAffinity:
        required:
          nodeSelectorTerms:
          - matchExpressions:
            - key: kubernetes.io/hostname
              operator: In
              values:
              - node-1
    

    Projected Volume

    在 Kubernetes 中,有几种特殊的 Volume,它们存在的意义不是为了存放容器里的数据,也不是用来进行容器和宿主机之间的数据交换。这些特殊 Volume 的作用,是为容器提供预先定义好的数据。所以,从容器的角度来看,这些 Volume 里的信息就是仿佛是被 Kubernetes“投射”(Project)进入容器当中的。这正是 Projected Volume 的含义。

    Secret

    它的作用,是帮你把 Pod 想要访问的加密数据,存放到 Etcd 中。然后,你就可以通过在 Pod 的容器里挂载 Volume 的方式,访问到这些 Secret 里保存的信息了。

    
    apiVersion: v1
    kind: Pod
    metadata:
      name: test-projected-volume 
    spec:
      containers:
      - name: test-secret-volume
        image: busybox
        args:
        - sleep
        - "86400"
        volumeMounts:
        - name: mysql-cred
          mountPath: "/projected-volume"
          readOnly: true
      volumes:
      - name: mysql-cred
        projected:
          sources:
          - secret:
              name: user
          - secret:
              name: pass
    
    
    $ cat ./username.txt
    admin
    $ cat ./password.txt
    c1oudc0w!
    
    $ kubectl create secret generic user --from-file=./username.txt
    $ kubectl create secret generic pass --from-file=./password.txt
    
    
    $ kubectl get secrets
    NAME           TYPE                                DATA      AGE
    user          Opaque                                1         51s
    pass          Opaque                                1         51s
    
    
    $ kubectl exec -it test-projected-volume -- /bin/sh
    $ ls /projected-volume/
    user
    pass
    $ cat /projected-volume/user
    root
    $ cat /projected-volume/pass
    1f2d1e2e67df
    

    ConfigMap

    与 Secret 类似的是 ConfigMap,它与 Secret 的区别在于,ConfigMap 保存的是不需要加密的、应用所需的配置信息。而 ConfigMap 的用法几乎与 Secret 完全相同:你可以使用 kubectl create configmap 从文件或者目录创建 ConfigMap,也可以直接编写 ConfigMap 对象的 YAML 文件。

    
    # .properties文件的内容
    $ cat example/ui.properties
    color.good=purple
    color.bad=yellow
    allow.textmode=true
    how.nice.to.look=fairlyNice
    
    # 从.properties文件创建ConfigMap
    $ kubectl create configmap ui-config --from-file=example/ui.properties
    
    # 查看这个ConfigMap里保存的信息(data)
    $ kubectl get configmaps ui-config -o yaml
    apiVersion: v1
    data:
      ui.properties: |
        color.good=purple
        color.bad=yellow
        allow.textmode=true
        how.nice.to.look=fairlyNice
    kind: ConfigMap
    metadata:
      name: ui-config
      ...
    

    Downward API

    让 Pod 里的容器能够直接获取到这个 Pod API 对象本身的信息。

    
    apiVersion: v1
    kind: Pod
    metadata:
      name: test-downwardapi-volume
      labels:
        zone: us-est-coast
        cluster: test-cluster1
        rack: rack-22
    spec:
      containers:
        - name: client-container
          image: k8s.gcr.io/busybox
          command: ["sh", "-c"]
          args:
          - while true; do
              if [[ -e /etc/podinfo/labels ]]; then
                echo -en '\n\n'; cat /etc/podinfo/labels; fi;
              sleep 5;
            done;
          volumeMounts:
            - name: podinfo
              mountPath: /etc/podinfo
              readOnly: false
      volumes:
        - name: podinfo
          projected:
            sources:
            - downwardAPI:
                items:
                  - path: "labels"
                    fieldRef:
                      fieldPath: metadata.labels
    
    
    1. 使用fieldRef可以声明使用:
    spec.nodeName - 宿主机名字
    status.hostIP - 宿主机IP
    metadata.name - Pod的名字
    metadata.namespace - Pod的Namespace
    status.podIP - Pod的IP
    spec.serviceAccountName - Pod的Service Account的名字
    metadata.uid - Pod的UID
    metadata.labels['<KEY>'] - 指定<KEY>的Label值
    metadata.annotations['<KEY>'] - 指定<KEY>的Annotation值
    metadata.labels - Pod的所有Label
    metadata.annotations - Pod的所有Annotation
    
    2. 使用resourceFieldRef可以声明使用:
    容器的CPU limit
    容器的CPU request
    容器的memory limit
    容器的memory request
    

    Service Account

    • 我现在有了一个 Pod,我能不能在这个 Pod 里安装一个 Kubernetes 的 Client,这样就可以从容器里直接访问并且操作这个 Kubernetes 的 API 了呢?
    • Service Account 对象的作用,就是 Kubernetes 系统内置的一种“服务账户”,它是 Kubernetes 进行权限分配的对象。比如,Service Account A,可以只被允许对 Kubernetes API 进行 GET 操作,而 Service Account B,则可以有 Kubernetes API 的所有操作权限。
    • 像这样的 Service Account 的授权信息和文件,实际上保存在它所绑定的一个特殊的 Secret 对象里的。这个特殊的 Secret 对象,就叫作 ServiceAccountToken。任何运行在 Kubernetes 集群上的应用,都必须使用这个 ServiceAccountToken 里保存的授权信息,也就是 Token,才可以合法地访问 API Server。

    相关文章

      网友评论

          本文标题:Kubernetes——Pod简介

          本文链接:https://www.haomeiwen.com/subject/efoqoktx.html