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

  《重识云原生系列》专题索引:

  1. 第一章——不谋全局不足以谋一域
  2. 第二章计算第1节——计算虚拟化技术总述
  3. 第二章计算第2节——主流虚拟化技术之VMare ESXi
  4. 第二章计算第3节——主流虚拟化技术之Xen
  5. 第二章计算第4节——主流虚拟化技术之KVM
  6. 第二章计算第5节——商用云主机方案
  7. 第二章计算第6节——裸金属方案
  8. 第三章云存储第1节——分布式云存储总述
  9. 第三章云存储第2节——SPDK方案综述
  10. 第三章云存储第3节——Ceph统一存储方案
  11. 第三章云存储第4节——OpenStack Swift 对象存储方案
  12. 第三章云存储第5节——商用分布式云存储方案
  13. 第四章云网络第一节——云网络技术发展简述
  14. 第四章云网络4.2节——相关基础知识准备
  15. 第四章云网络4.3节——重要网络协议
  16. 第四章云网络4.3.1节——路由技术简述
  17. 第四章云网络4.3.2节——VLAN技术
  18. 第四章云网络4.3.3节——RIP协议
  19. 第四章云网络4.3.4节——OSPF协议
  20. 第四章云网络4.3.5节——EIGRP协议
  21. 第四章云网络4.3.6节——IS-IS协议
  22. 第四章云网络4.3.7节——BGP协议
  23. 第四章云网络4.3.7.2节——BGP协议概述
  24. 第四章云网络4.3.7.3节——BGP协议实现原理
  25. 第四章云网络4.3.7.4节——高级特性
  26. 第四章云网络4.3.7.5节——实操
  27. 第四章云网络4.3.7.6节——MP-BGP协议
  28. 第四章云网络4.3.8节——策略路由
  29. 第四章云网络4.3.9节——Graceful Restart(平滑重启)技术
  30. 第四章云网络4.3.10节——VXLAN技术
  31. 第四章云网络4.3.10.2节——VXLAN Overlay网络方案设计
  32. 第四章云网络4.3.10.3节——VXLAN隧道机制
  33. 第四章云网络4.3.10.4节——VXLAN报文转发过程
  34. 第四章云网络4.3.10.5节——VXlan组网架构
  35. 第四章云网络4.3.10.6节——VXLAN应用部署方案
  36. 第四章云网络4.4节——Spine-Leaf网络架构
  37. 第四章云网络4.5节——大二层网络
  38. 第四章云网络4.6节——Underlay 和 Overlay概念
  39. 第四章云网络4.7.1节——网络虚拟化与卸载加速技术的演进简述
  40. 第四章云网络4.7.2节——virtio网络半虚拟化简介
  41. 第四章云网络4.7.3节——Vhost-net方案
  42. 第四章云网络4.7.4节vhost-user方案——virtio的DPDK卸载方案
  43. 第四章云网络4.7.5节vDPA方案——virtio的半硬件虚拟化实现
  44. 第四章云网络4.7.6节——virtio-blk存储虚拟化方案
  45. 第四章云网络4.7.8节——SR-IOV方案
  46. 第四章云网络4.7.9节——NFV
  47. 第四章云网络4.8.1节——SDN总述
  48. 第四章云网络4.8.2.1节——OpenFlow概述
  49. 第四章云网络4.8.2.2节——OpenFlow协议详解
  50. 第四章云网络4.8.2.3节——OpenFlow运行机制
  51. 第四章云网络4.8.3.1节——Open vSwitch简介
  52. 第四章云网络4.8.3.2节——Open vSwitch工作原理详解
  53. 第四章云网络4.8.4节——OpenStack与SDN的集成
  54. 第四章云网络4.8.5节——OpenDayLight
  55. 第四章云网络4.8.6节——Dragonflow
  56.  第四章云网络4.9.1节——网络卸载加速技术综述

  57. 第四章云网络4.9.2节——传统网络卸载技术

  58. 第四章云网络4.9.3.1节——DPDK技术综述

  59. 第四章云网络4.9.3.2节——DPDK原理详解

  60. 第四章云网络4.9.4.1节——智能网卡SmartNIC方案综述

  61. 第四章云网络4.9.4.2节——智能网卡实现

  62. 第六章容器6.1.1节——容器综述

  63. 第六章容器6.1.2节——容器安装部署

  64. 第六章容器6.1.3节——Docker常用命令

  65. 第六章容器6.1.4节——Docker核心技术LXC

  66. 第六章容器6.1.5节——Docker核心技术Namespace

  67. 第六章容器6.1.6节—— Docker核心技术Chroot

  68. 第六章容器6.1.7.1节——Docker核心技术cgroups综述

  69. 第六章容器6.1.7.2节——cgroups原理剖析

  70. 第六章容器6.1.7.3节——cgroups数据结构剖析

  71. 第六章容器6.1.7.4节——cgroups使用

  72. 第六章容器6.1.8节——Docker核心技术UnionFS

  73. 第六章容器6.1.9节——Docker镜像技术剖析

  74. 第六章容器6.1.10节——DockerFile解析

  75. 第六章容器6.1.11节——docker-compose容器编排

  76. 第六章容器6.1.12节——Docker网络模型设计

  77. 第六章容器6.2.1节——Kubernetes概述

  78. 第六章容器6.2.2节——K8S架构剖析

  79. 第六章容器6.3.1节——K8S核心组件总述

  80. 第六章容器6.3.2节——API Server组件

  81. 第六章容器6.3.3节——Kube-Scheduler使用篇

  82. 第六章容器6.3.4节——etcd组件

  83. 第六章容器6.3.5节——Controller Manager概述

  84. 第六章容器6.3.6节——kubelet组件

  85. 第六章容器6.3.7节——命令行工具kubectl

  86. 第六章容器6.3.8节——kube-proxy

  87. 第六章容器6.4.1节——K8S资源对象总览

  88. 第六章容器6.4.2.1节——pod详解

  89. 第六章容器6.4.2.2节——Pod使用(上)

  90. 第六章容器6.4.2.3节——Pod使用(下)

  91. 第六章容器6.4.3节——ReplicationController

  92. 第六章容器6.4.4节——ReplicaSet组件

  93. 第六章容器基础6.4.5.1节——Deployment概述

  94. 第六章容器基础6.4.5.2节——Deployment配置详细说明

  95. 第六章容器基础6.4.5.3节——Deployment实现原理解析

  96. 第六章容器基础6.4.6节——Daemonset

  97. 第六章容器基础6.4.7节——Job

  98. 第六章容器基础6.4.8节——CronJob

1 Pod使用

1.10 访问 DNS 的策略

        通过设置 dnsPolicy 参数,设置 Pod 中容器访问 DNS 的策略:

  • ClusterFirst:优先基于 cluster domain (如 default.svc.cluster.local) 后缀,通过 kube-dns 查询 (默认策略);
  • Default:优先从 Node 中配置的 DNS 查询;

1.11 使用主机的 IPC 命名空间

        通过设置 spec.hostIPC 参数为 true,使用主机的 IPC 命名空间,默认为 false。

1.12 使用主机的网络命名空间

        通过设置 spec.hostNetwork 参数为 true,使用主机的网络命名空间,默认为 false。

1.13 使用主机的 PID 空间

        通过设置 spec.hostPID 参数为 true,使用主机的 PID 命名空间,默认为 false。

apiVersion: v1 
kind: Pod 
metadata: 
  name: busybox1 
  labels: 
    name: busybox 
spec: 
  hostIPC: true 
  hostPID: true 
  hostNetwork: true 
  containers: 
    - image: busybox 
      command: 
        - sleep 
        - "3600" 
      name: busybox

1.14 设置 Pod 的 hostname

        通过 spec.hostname 参数实现,如果未设置默认使用 metadata.name 参数的值作为 Pod 的 hostname。

1.15 设置 Pod 的子域名

        通过 spec.subdomain 参数设置 Pod 的子域名,默认为空。比如,指定 hostname 为 busybox-2 和 subdomain 为 default-subdomain,完整域名为 busybox-2.default-subdomain.default.svc.cluster.local,也可以简写为 busybox-2.default-subdomain.default:

apiVersion: v1 
kind: Pod 
metadata: 
  name: busybox2 
  labels: 
    name: busybox 
spec: 
  hostname: busybox-2 
  subdomain: default-subdomain 
  containers: 
    - image: busybox 
      command: 
        - sleep 
        - "3600" 
      name: busybox

注意:

  • 默认情况下,DNS 为 Pod 生成的 A 记录格式为 pod-ip-address.my-namespace.pod.cluster.local,如 1-2-3-4.default.pod.cluster.local;
  • 上面的示例还需要在 default namespace 中创建一个名为 default-subdomain(即 subdomain)的 headless service,否则其他 Pod 无法通过完整域名访问到该 Pod(只能自己访问到自己);
kind: Service 
apiVersion: v1 
metadata: 
  name: default-subdomain 
spec: 
  clusterIP: None 
  selector: 
    name: busybox 
    ports: 
      - name: foo 
      # Actually, no port is needed. 
        port: 1234 
        targetPort: 1234

注意:

        必须为 headless service 设置至少一个服务端口(spec.ports,即便它看起来并不需要),否则 Pod 与 Pod 之间依然无法通过完整域名来访问。

1.16 设置 Pod 的 DNS 选项

        从 v1.9 开始,可以在 kubelet 和 kube-apiserver 中设置 --feature-gates=CustomPodDNS=true 开启设置每个 Pod DNS 地址的功能。

注意:该功能在 v1.10 中为 Beta 版,v1.9 中为 Alpha 版。

apiVersion: v1 
kind: Pod 
metadata: 
  namespace: default 
  name: dns-example 
spec: 
  containers: 
    - name: test 
      image: nginx 
  dnsPolicy: "None" 
  dnsConfig: 
    nameservers: 
      - 1.2.3.4 
    searches: 
      - ns1.svc.cluster.local 
      - my.dns.search.suffix 
    options: 
      - name: ndots 
        value: "2" 
      - name: edns0

        对于旧版本的集群,可以使用 ConfigMap 来自定义 Pod 的 /etc/resolv.conf,如:

kind: ConfigMap 
apiVersion: v1 
metadata: 
  name: resolvconf 
  namespace: default 
data: 
  resolv.conf: | 
    search default.svc.cluster.local svc.cluster.local cluster.local 
    nameserver 10.0.0.10 

--- 
kind: Deployment 
apiVersion: extensions/v1beta1 
metadata: 
  name: dns-test 
  namespace: default 
spec: 
  replicas: 1 
  template: 
    metadata: 
      labels: 
        name: dns-test 
    spec: 
      containers: 
        - name: dns-test 
          image: alpine 
          stdin: true 
          tty: true 
          command: ["sh"] 
          volumeMounts: 
            - name: resolv-conf 
              mountPath: /etc/resolv.conf 
              subPath: resolv.conf 
      volumes: 
        - name: resolv-conf 
          configMap: 
            name: resolvconf 
            items: 
              - key: resolv.conf 
                path: resolv.conf

1.17 资源限制

        Kubernetes 通过 cgroups 限制容器的 CPU 和内存等计算资源,包括 requests(请求,调度器保证调度到资源充足的 Node 上,如果无法满足会调度失败)和 limits(上限)等:

  • spec.containers[].resources.limits.cpu:CPU 上限,可以短暂超过,容器也不会被停止
  • spec.containers[].resources.limits.memory:内存上限,不可以超过;如果超过,容器可能会被终止或调度到其他资源充足的机器上
  • spec.containers[].resources.limits.ephemeral-storage:临时存储(容器可写层、日志以及 EmptyDir 等)的上限,超过后 Pod 会被驱逐
  • spec.containers[].resources.requests.cpu:CPU 请求数,也是调度 CPU 资源的依据,可以超过
  • spec.containers[].resources.requests.memory:内存请求数,也是调度内存资源的依据,可以超过;但如果超过,容器可能会在 Node 内存不足时清理
  • spec.containers[].resources.requests.ephemeral-storage:临时存储(容器可写层、日志以及 EmptyDir 等)的请求数,调度容器存储的依据

        比如 nginx 容器请求 30% 的 CPU 和 56MB 的内存,但限制最多只用 50% 的 CPU 和 128MB 的内存:

apiVersion: v1 
kind: Pod 
metadata: 
  labels: 
    app: nginx 
    name: nginx 
spec: 
  containers: 
    - image: nginx 
      name: nginx 
      resources: 
        requests: 
          cpu: "300m" 
          memory: "56Mi" 
          limits: 
            cpu: "1" 
            memory: "128Mi"

注意

  • CPU 的单位是 CPU 个数,可以用 millicpu (m) 表示少于 1 个 CPU 的情况,如 500m = 500millicpu = 0.5cpu,而一个 CPU 相当于:
    • AWS 上的一个 vCPU
    • GCP 上的一个 Core
    • Azure 上的一个 vCore
    • 物理机上开启超线程时的一个超线程
  • 内存的单位则包括 E, P, T, G, M, K, Ei, Pi, Ti, Gi, Mi, Ki 等。
  • 从 v1.10 开始,可以设置 kubelet ----cpu-manager-policy=static 为 Guaranteed(即 requests.cpu 与 limits.cpu 相等)Pod 绑定 CPU(通过 cpuset cgroups)。 

1.18 健康检查

1.18.1 容器探针

  • livenessProbe:存活探针,指示容器是否正在运行。如果存活探测失败,则 kubelet 会杀死容器,并且容器将受到其重启策略的影响。如果容器不提供存活探针,则默认状态为Success。
  • readinessProbe:就绪探针,指示容器是否准备好服务请求。如果就绪探测失败,端点控制器将从与 Pod 匹配的所有Service 的端点中删除该 Pod 的 IP 地址。初始延迟之前的就绪状态默认为Failure。如果容器不提供就绪探针,则默认状态为Success。

#查看livenessProbe帮助命令:

kubectl explain pods.spec.containers.livenessProbe

#查看readinessProbe帮助命令:

kubectl explain pods.spec.containers.readinessProbe

        整个图如下:

         从上面可以看出,我们pod在从创建到结束之前,会一直处于某种状态之中。 

1.18.2 LivenessProbe探针配置

[root@master yaml]# cat liveness.yaml 
kind: Pod 
apiVersion: v1 
metadata: 
  name: liveness 
  labels: 
    test: liveness 
spec: 
  restartPolicy: OnFailure 
  containers: 
    - name: liveness 
      image: busybox 
      args: 
        - /bin/sh 
        - -c 
        - touch /tmp/test; sleep 60; rm -rf /tmp/test; sleep 300 
      livenessProbe: 
        exec: 
          command: 
            - cat 
            - /tmp/test 
        initialDelaySeconds: 10 
        periodSeconds: 5
  • initialDelaySeconds: Pod运行多长时间进行探测(单位是秒);
  • periodSeconds: 每隔多长时间进行一次探测(单位是秒);

        上述yaml文件中针对/tmp/test这个文件进行指定了健康检查策略为 livenessProbe,并且指定了重启策略为OnFailure。这样容器可以正常的运行,但是总是会重启。如图:

 1.18.3 ReadinessProbe探针配置

        配置几乎是一模一样的,只是健康检测的方式更换一下,如下:

[root@master yaml]# cat readiness.yaml 
kind: Pod 
apiVersion: v1 
metadata: 
  name: readiness 
  labels: 
    test: readiness 
spec: 
  restartPolicy: OnFailure 
  containers: 
    - name: readiness 
      image: busybox 
      args: 
        - /bin/sh 
        - -c 
        - touch /tmp/test; sleep 60; rm -rf /tmp/test; sleep 300 
      readinessProbe: 
        exec: 
          command: 
            - cat 
            - /tmp/test 
        initialDelaySeconds: 10 
        periodSeconds: 5

        那么此时运行的pod状态如图:

         查看的效果可能不是很明显,使用以下方法,便可查看具体的效果。

[root@master yaml]# cat hcscal.yaml 
kind: Deployment 
apiVersion: extensions/v1beta1 
metadata: 
  name: web 
spec: 
  replicas: 3 
  template: 
    metadata: 
      labels: 
        run: web 
    spec: 
      containers: 
        - name: web 
          image: httpd 
          ports: 
            - containerPort: 80 
          readinessProbe: 
            httpGet: 
              scheme: HTTP 
              path: /healthy 
              port: 80 
            initialDelaySeconds: 10 
            periodSeconds: 5

---

kind: Service 
apiVersion: v1 
metadata: 
  name: web-svc 
spec: 
  type: NodePort 
  selector: 
    run: web 
  ports: 
    - protocol: TCP 
      port: 90 
      targetPort: 80 
      nodePort: 30321

        创建一个deployment资源、一个Service资源并且相互之间进行关联。

        执行的结果如图:

 由此可以得出以下结论:

  • ReadinessProbe探针的使用场景livenessProbe稍有不同,有的时候应用程序可能暂时无法接受请求,比如Pod已经Running了,但是容器内应用程序尚未启动成功,在这种情况下,如果没有ReadinessProbe,则Kubernetes认为它可以处理请求了,然而此时,我们知道程序还没启动成功是不能接收用户请求的,所以不希望kubernetes把请求调度给它,则使用ReadinessProbe探针。
  • ReadinessProbe和livenessProbe可以使用相同探测方式,只是对Pod的处置方式不同,ReadinessProbe是将Pod IP:Port从对应的EndPoint列表中删除,而livenessProbe则Kill容器并根据Pod的重启策略来决定作出对应的措施。

每种探针都支持以下三种探测方式:

  • exec:通过执行命令来检查服务是否正常,针对复杂检测或无HTTP接口的服务,命令返回值为0则表示容器健康;
  • httpGet:通过发送http请求检查服务是否正常,返回200-399状态码则表明容器健康;
  • tcpSocket:通过容器的IP和Port执行TCP检查,如果能够建立TCP连接,则表明容器健康;

1.18.4 小结

  1. liveness和readiness是两种健康检查机制,如果不特意配置,K8s将两种探测采用相同的默认行为,即通过判断容器启动进程的返回值是否为零,来判断探测是否成功;
  2. 两种探测配置完全一样。不同之处在于探测失败后的行为:
    1.  liveness探测是根据Pod重启策略操作容器,大多数是重启容器;
    2.  readiness则是将容器设置为不可用,不接受service转发的请求;
  3. 两种探测方法可以独立存在,也可同时使用;比如使用liveness判断容器是否需要重启实现自愈;用readiness判断容器是否已经准备好对外提供服务。

1.18.5 健康检测的应用

        主要应用是在scale(扩容、缩容)、更新(升级)过程中使用。下面通过一个简单的小实验进行验证:

[root@master yaml]# cat app.v1.yaml 
//版本1的yaml文件创建10个副本使用busybox镜像,如下: 
apiVersion: extensions/v1beta1 
kind: Deployment 
metadata: 
  name: app 
spec: 
  replicas: 10 
  template: 
    metadata: 
      labels: 
        run: app 
    spec: 
      containers: 
        - name: app 
          image: busybox 
          args: 
            - /bin/sh 
            - -c 
            - sleep 10; touch /tmp/healthy; sleep 3000 
          readinessProbe: 
            exec: 
              command: 
                - cat 
                - /tmp/healthy 
            initialDelaySeconds: 10 
            periodSeconds: 5

        使用yaml文件生成相应的资源,并且记录历史版本信息:

[root@master yaml]# kubectl apply -f app.v1.yaml --record

        查看pod信息,如图:

[root@master yaml]# cat app.v2.yaml 
//版本2的yaml文件创建10个副本使用busybox镜像 
//并模拟(代码中有问题,并进行升级),如下: 
apiVersion: extensions/v1beta1 
kind: Deployment 
metadata: 
  name: app 
spec: 
  strategy: 
    rollingUpdate: 
      maxSurge: 2 
      maxUnavailable: 2 
  replicas: 10 
  template: 
    metadata: 
      labels: 
        run: app 
    spec: 
      containers: 
        - name: app 
          image: busybox 
          args: 
            - /bin/sh 
            - -c 
            - sleep 3000 
          readinessProbe: 
            exec: 
              command: 
                - cat 
                - /tmp/healthy 
            initialDelaySeconds: 10 
            periodSeconds: 5 
//maxSurge:此参数控制滚动更新过程中,副本总数超过预期数的值,可以是整数,也可以是百分比。默认是1 
//maxUnavailable:不可用Pod的值,默认为1,可以是整数,也可以是百分比 

[root@master yaml]# kubectl apply -f app.v2.yamll --record

        查看pod信息,如图: 

        从图中可以看出,一共有12个pod,并且有四个pod是不可用的!因为健康检查机制在检查到有问题时,就不会更新了剩余的pod了!

[root@master yaml]# cat app.v3.yaml 
//版本2的yaml文件创建10个副本使用busybox镜像 
//并且不使用健康检查机制,如下: 
apiVersion: extensions/v1beta1 
kind: Deployment 
metadata: 
  name: app 
spec: 
  replicas: 10 
  template: 
    metadata: 
      labels: 
        run: app 
    spec: 
      containers: 
        - name: app 
          image: busybox 
          args: 
            - /bin/sh 
            - -c 
            - sleep 3000 

[root@master yaml]# kubectl apply -f app.v3.yamll --record

        再次查看pod的状态信息,如图:

         如果不使用健康检查机制,就可以看出及时pod中服务存在问题,也会全部更新!

[root@master yaml]# kubectl rollout history deployment app //查看记录的历史版本 
[root@master yaml]# kubectl rollout undo deployment app --to-revision=1 //回滚到可用的版本

        再次查看pod的运行状态,如图:

         由此可以看出pod健康检查的重要性!

1.19 命名空间-namespace

        namespace叫做命名空间,可以把k8s集群划分成多个名称空间,然后对不同的名称空间的资源做隔离,可以控制各个名称空间的入栈,出栈策略,是一种在多个用户之间划分群集资源的方法。

#查看k8s集群当前有哪些名称空间:

kubectl get namespace

1.20 pod label

(1)什么是标签?

        标签其实就一对 key/value ,被关联到对象上,比如Pod,标签的使用我们倾向于能够标示对象的特殊特点,并且对用户而言是有意义的(就是一眼就看出了这个Pod是干什么的),标签可以用来划分特定组的对象(比如版本,服务类型等),标签可以在创建一个对象的时候直接给与,也可以在后期随时修改,每一个对象可以拥有多个标签,但是,key值必须是唯一的。

(2)查看所有pod资源对象的标签

kubectl get pods --show-labels

(3)查看带有指定标签的pod

kubectl get pods -L web1

(4)显示所有资源对象下web1这个标签的标签值

kubectl get pods -l web1 --show-labels

        查看拥有web1这个标签的资源对象,并且把标签显示出来。

(5)想修改资源的标签,比方说想给web加上个release标签

        给资源对象打标签要使用label命令,指定给某个类型下的某个资源打标签,资源中的key/value可以是多个,因此在web(pod名字)这个资源下再打个标签release,用如下命令:

kubectl label pods web release=new

        查看标签是否打成功:

kubectl get pods --show-labels

        显示如下,显示如下,说明标签达成功了;

NAME READY STATUS RESTARTS AGE LABELS 
web   1/1  Running   1     21h release=new,web1=tomcat

(6)k8s的标签选择器:

        与name和UID不同,label不提供唯一性。通常,我们会看到很多对象有着一样的label。通过标签选择器,客户端/用户能方便辨识出一组对象。

API目前支持两种标签选择器:

  • 基于等值的标签选择器
  • 基于集合的标签选择器

        一个label选择器可以由多个必须条件组成,由逗号分隔。在多个必须条件指定的情况下,所有的条件都必须满足,因而逗号起着AND逻辑运算符的作用。

        一个空的label选择器(即有0个必须条件的选择器)会选择集合中的每一个对象。

        一个null型label选择器(仅对于可选的选择器字段才可能)不会返回任何对象。

        基于等值关系的标签选择器:=,==,!=

        基于相等性或者不相等性的条件允许用label的键或者值进行过滤。匹配的对象必须满足所有指定的label约束,尽管他们可能也有额外的label。有三种运算符是允许的,“=”,“==”和“!=”。前两种代表相等性(他们是同义运算符),后一种代表非相等性。例如:

environment = production tier != frontend

        第一个选择所有键等于 environment 值为 production 的资源。后一种选择所有键为 tier 值不等于 frontend 的资源,和那些没有键为 tier 的label的资源。

        要过滤所有处于 production 但不是 frontend 的资源,可以使用逗号操作符,

environment=production,tier!=frontend

        基于集合的标签选择器:

        基于集合的label条件允许用一组值来过滤键。支持三种操作符: in , notin ,和 exists(仅针对于key符号) 。例如:

environment in (production, qa) 

tier notin (frontend, backend) 

        第一个例子,选择所有键等于 environment ,且value等于 production 或者 qa 的资源。 第二个例子,选择所有键等于tier且值是除了frontend 和 backend 之外的资源,和那些没有label的键是 tier 的资源。 类似的,逗号操作符相当于一个AND操作符。因而要使用一个 partition 键(不管值是什么),并且 environment 不是 qa 过滤资源可以用 partition,environment notin (qa) 。

        基于集合的选择器是一个相等性的宽泛的形式,因为 environment=production 相当于environment in (production) ,与 != and notin 类似。 

        基于集合的条件可以与基于相等性 的条件混合。例如, partition in (customerA,customerB),environment != qa 。 

        标签选择器根据定义的标签可以选择匹配到的资源对象。

        更多详细信息可参考:

Labels and Selectors | Kubernetes

node label

(1)查看nodes节点的标签

kubectl get nodes --show-labels

(2)给node节点打标签:

kubectl label nodes node1 node011=haha kubectl get nodes --show-labels

        可以看到node01上有node011这个标签了。

(3)节点选择器nodeSelector

#查看nodeSelector帮助命令 
kubectl explain pods.spec.nodeSelector 

# nodeSelector <map[string]string> 
# NodeSelector is a selector which must be true for the pod to fit on a node. 
# Selector which must match a node's labels for the pod to be scheduled on that node. 
# More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/

        上面有一个nodeSelector,这个是节点标签选择器,可以限制pod运行在哪个节点上

kubectl get pods -o wide

        从上面可以看到web运行在node1上,如果我们想要让它运行在master1上,就需要用到节点选择器:

nodeSelector:

  node011: haha #这个node011是我们给node1节点打的标签,在上面已经操作过

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 
  nodeSelector: 
    node011:haha 

kubectl delete -f pod.yaml 
kubectl apply -f pod.yaml 
kubectl get pods -o wide

        显示pod运行在node1上。

        如果node1和node2都有node011这个标签,那么nodeSelector则根据调度策略调度pod到相应的node节点上。

        更多详细信息可参考:

Assigning Pods to Nodes | Kubernetes

节点名称

        nodeName:指定pod节点运行在哪个具体node上,不存在调度说法。

        查看 nodeName帮助命令:

kubectl explain pods.spec.nodeName

1.21 使用 Capabilities

        默认情况下,容器都是以非特权容器的方式运行。比如,不能在容器中创建虚拟网卡、配置虚拟网络。

        Kubernetes 提供了修改 Capabilities 的机制,可以按需要给容器增加或删除。比如下面的配置给容器增加了 CAP_NET_ADMIN 并删除了 CAP_KILL。

apiVersion: v1 
kind: Pod 
metadata: 
  name: cap-pod 
spec: 
  containers: 
    - name: friendly-container 
      image: "alpine:3.4" 
      command: ["/bin/sleep", "3600"] 
      securityContext: 
        capabilities: 
          add: 
            - NET_ADMIN 
          drop: 
            - KILL

1.22 限制网络带宽

        可以通过给 Pod 增加 kubernetes.io/ingress-bandwidth 和 kubernetes.io/egress-bandwidth 这两个 annotation 来限制 Pod 的网络带宽:

apiVersion: v1 
kind: Pod 
metadata: 
  name: qos 
  annotations: 
    kubernetes.io/ingress-bandwidth: 3M 
    kubernetes.io/egress-bandwidth: 4M 
spec: 
  containers: 
    - name: iperf3 
      image: networkstatic/iperf3 
      command: 
        - iperf3 
        - -s

        仅 kubenet 支持限制带宽目前只有 kubenet 网络插件支持限制网络带宽,其他 CNI 网络插件暂不支持这个功能。

        kubenet 的网络带宽限制其实是通过 tc 来实现的:

# setup qdisc (only once) 
    tc qdisc add dev cbr0 root handle 1: htb default 30 
# download rate 
    tc class add dev cbr0 parent 1: classid 1:2 htb rate 3Mbit 
    tc filter add dev cbr0 protocol ip parent 1:0 prio 1 u32 match ip dst 10.1.0.3/32 flowid 1:2 
# upload rate 
    tc class add dev cbr0 parent 1: classid 1:3 htb rate 4Mbit 
    tc filter add dev cbr0 protocol ip parent 1:0 prio 1 u32 match ip src 10.1.0.3/32 flowid 1:3

1.23 调度到指定的 Node 上

        可以通过 nodeSelector、nodeAffinity、podAffinity 以及 Taints 和 tolerations 等来将 Pod 调度到需要的 Node 上。

        也可以通过设置 nodeName 参数,将 Pod 调度到指定 node 节点上。

        比如,使用 nodeSelector,首先给 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

        nodeAffinity、podAffinity 以及 Taints 和 tolerations 等的使用方法请参考 调度器章节

1.24 自定义 hosts

        默认情况下,容器的 /etc/hosts 是 kubelet 自动生成的,并且仅包含 localhost 和 podName 等。不建议在容器内直接修改 /etc/hosts 文件,因为在 Pod 启动或重启时会被覆盖。

        默认的 /etc/hosts 文件格式如下,其中 nginx-4217019353-fb2c5 是 podName:

$ kubectl exec nginx-4217019353-fb2c5 -- cat /etc/hosts 
# Kubernetes-managed hosts file. 
127.0.0.1 localhost 
::1 localhost ip6-localhost ip6-loopback 
fe00::0 ip6-localnet 
fe00::0 ip6-mcastprefix 
fe00::1 ip6-allnodes 
fe00::2 ip6-allrouters 
10.244.1.4 nginx-4217019353-fb2c5

        从 v1.7 开始,可以通过 pod.Spec.HostAliases 来增加 hosts 内容,如:

apiVersion: v1 
kind: Pod 
metadata: 
  name: hostaliases-pod 
spec: 
  hostAliases: 
    - ip: "127.0.0.1" 
      hostnames: 
        - "foo.local" 
        - "bar.local" 
        - ip: "10.1.2.3" 
      hostnames: 
        - "foo.remote" 
        - "bar.remote" 
  containers: 
    - name: cat-hosts 
      image: busybox 
      command: 
        - cat 
      args: 
        - "/etc/hosts"
$ kubectl logs hostaliases-pod 
# Kubernetes-managed hosts file. 
127.0.0.1 localhost 
::1 localhost ip6-localhost ip6-loopback 
fe00::0 ip6-localnet 
fe00::0 ip6-mcastprefix 
fe00::1 ip6-allnodes 
fe00::2 ip6-allrouters 
10.244.1.5 hostaliases-pod 
127.0.0.1 foo.local 
127.0.0.1 bar.local 
10.1.2.3 foo.remote 
10.1.2.3 bar.remote

1.25 HugePages

        v1.8 + 支持给容器分配 HugePages,资源格式为 hugepages-(如 hugepages-2Mi)。使用前要配置:

  • 开启 --feature-gates="HugePages=true"
  • 在所有 Node 上面预分配好 HugePage ,以便 Kubelet 统计所在 Node 的 HugePage 容量

        使用示例

apiVersion: v1 
kind: Pod 
metadata: 
  generateName: hugepages-volume- 
spec: 
  containers: 
    - image: fedora:latest 
      command: 
        - sleep 
        - inf 
      name: example 
      volumeMounts: 
        - mountPath: /hugepages 
          name: hugepage 
      resources: 
        limits: 
          hugepages-2Mi: 100Mi 
  volumes: 
    - name: hugepage 
      emptyDir: 
        medium: HugePages

注意事项:

  • HugePage 资源的请求和限制必须相同;
  • HugePage 以 Pod 级别隔离,未来可能会支持容器级的隔离;
  • 基于 HugePage 的 EmptyDir 存储卷最多只能使用请求的 HugePage 内存;
  • 使用 shmget() 的 SHM_HUGETLB 选项时,应用必须运行在匹配 proc/sys/vm/hugetlb_shm_group 的用户组(supplemental group)中;

1.26 优先级

        从 v1.8 开始,可以为 Pod 设置一个优先级,保证高优先级的 Pod 优先调度。

        优先级调度功能目前为 Beta 版,在 v1.11 版本中默认开启。对 v1.8-1.10 版本中使用前需要开启:

  • --feature-gates=PodPriority=true
  • --runtime-config=scheduling.k8s.io/v1alpha1=true --admission-control=Controller-Foo,Controller-Bar,...,Priority

        为 Pod 设置优先级前,先创建一个 PriorityClass,并设置优先级(数值越大优先级越高):

apiVersion: scheduling.k8s.io/v1alpha1 
kind: PriorityClass 
metadata: 
  name: high-priority 
value: 1000000 
globalDefault: false 
description: "This priority class should be used for XYZ service pods only."

        Kubernetes 自动创建了 system-cluster-critical 和 system-node-critical 等两个 PriorityClass,用于 Kubernetes 核心组件。

        为 Pod 指定优先级:

apiVersion: v1 
kind: Pod 
metadata: 
  name: nginx 
  labels: 
    env: test 
spec: 
  containers: 
    - name: nginx 
      image: nginx 
      imagePullPolicy: IfNotPresent 
  priorityClassName: high-priority

        当调度队列有多个 Pod 需要调度时,优先调度高优先级的 Pod。而当高优先级的 Pod 无法调度时,Kubernetes 会尝试先删除低优先级的 Pod 再将其调度到对应 Node 上(Preemption)。

注意:受限于 Kubernetes 的调度策略,抢占并不总是成功。

1.27 PodDisruptionBudget

PodDisruptionBudget (PDB) 用来保证一组 Pod 同时运行的数量,这些 Pod 需要使用 Deployment、ReplicationController、ReplicaSet 或者 StatefulSet 管理。

apiVersion: policy/v1beta1 
kind: PodDisruptionBudget 
metadata: 
  name: zk-pdb 
spec: 
  maxUnavailable: 1 
  selector: 
    matchLabels: 
      app: zookeeper

1.28 Sysctls

        Sysctls 允许容器设置内核参数,分为安全 Sysctls 和非安全 Sysctls:

  • 安全 Sysctls:即设置后不影响其他 Pod 的内核选项,只作用在容器 namespace 中,默认开启。包括以下几种
    • kernel.shm_rmid_forced
    • net.ipv4.ip_local_port_range
    • net.ipv4.tcp_syncookies
  • 非安全 Sysctls:即设置好有可能影响其他 Pod 和 Node 上其他服务的内核选项,默认禁止。如果使用,需要管理员在配置 kubelet 时开启,如 kubelet --experimental-allowed-unsafe-sysctls 'kernel.msg*,net.ipv4.route.min_pmtu'

v1.6-v1.10 示例:

apiVersion: v1 
kind: Pod 
metadata: 
  name: sysctl-example 
  annotations: 
    security.alpha.kubernetes.io/sysctls: kernel.shm_rmid_forced=1 
    security.alpha.kubernetes.io/unsafe-sysctls: net.ipv4.route.min_pmtu=1000,kernel.msgmax=1 2 3 
spec: 
  ...

        从 v1.11 开始,Sysctls 升级为 Beta 版本,不再区分安全和非安全 sysctl,统一通过 podSpec.securityContext.sysctls 设置,如:

apiVersion: v1 
kind: Pod 
metadata: 
  name: sysctl-example 
spec: 
  securityContext: 
    sysctls: 
      - name: kernel.shm_rmid_forced 
        value: "0" 
      - name: net.ipv4.route.min_pmtu 
        value: "552" 
      - name: kernel.msgmax 
        value: "65536" 
...

1.29 Pod 时区

        很多容器都是配置了 UTC 时区,与国内集群的 Node 所在时区有可能不一致,可以通过 HostPath 存储插件给容器配置与 Node 一样的时区:

apiVersion: v1 
kind: Pod 
metadata: 
  name: sh 
  namespace: default 
spec: 
  containers: 
    - image: alpine 
      stdin: true 
      tty: true 
      volumeMounts: 
        - mountPath: /etc/localtime 
          name: time 
          readOnly: true 
  volumes: 
    - hostPath: 
        path: /etc/localtime 
        type: "" 
      name: time

 参考链接

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

  • What is Pod?
  • Kubernetes Pod Lifecycle
  • DNS Pods and Services
  • Container capabilities
  • Configure Liveness and Readiness Probes
  • Init Containers
  • Linux Capabilities
  • Manage HugePages
  • Document supported docker image (Dockerfile) features

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

江中散人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值