• 【重识云原生】第六章容器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。

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: busybox1
    5. labels:
    6. name: busybox
    7. spec:
    8. hostIPC: true
    9. hostPID: true
    10. hostNetwork: true
    11. containers:
    12. - image: busybox
    13. command:
    14. - sleep
    15. - "3600"
    16. 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:

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: busybox2
    5. labels:
    6. name: busybox
    7. spec:
    8. hostname: busybox-2
    9. subdomain: default-subdomain
    10. containers:
    11. - image: busybox
    12. command:
    13. - sleep
    14. - "3600"
    15. 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(只能自己访问到自己);
    1. kind: Service
    2. apiVersion: v1
    3. metadata:
    4. name: default-subdomain
    5. spec:
    6. clusterIP: None
    7. selector:
    8. name: busybox
    9. ports:
    10. - name: foo
    11. # Actually, no port is needed.
    12. port: 1234
    13. 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 版。

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. namespace: default
    5. name: dns-example
    6. spec:
    7. containers:
    8. - name: test
    9. image: nginx
    10. dnsPolicy: "None"
    11. dnsConfig:
    12. nameservers:
    13. - 1.2.3.4
    14. searches:
    15. - ns1.svc.cluster.local
    16. - my.dns.search.suffix
    17. options:
    18. - name: ndots
    19. value: "2"
    20. - name: edns0

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

    1. kind: ConfigMap
    2. apiVersion: v1
    3. metadata:
    4. name: resolvconf
    5. namespace: default
    6. data:
    7. resolv.conf: |
    8. search default.svc.cluster.local svc.cluster.local cluster.local
    9. nameserver 10.0.0.10
    10. ---
    11. kind: Deployment
    12. apiVersion: extensions/v1beta1
    13. metadata:
    14. name: dns-test
    15. namespace: default
    16. spec:
    17. replicas: 1
    18. template:
    19. metadata:
    20. labels:
    21. name: dns-test
    22. spec:
    23. containers:
    24. - name: dns-test
    25. image: alpine
    26. stdin: true
    27. tty: true
    28. command: ["sh"]
    29. volumeMounts:
    30. - name: resolv-conf
    31. mountPath: /etc/resolv.conf
    32. subPath: resolv.conf
    33. volumes:
    34. - name: resolv-conf
    35. configMap:
    36. name: resolvconf
    37. items:
    38. - key: resolv.conf
    39. 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 的内存:

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. labels:
    5. app: nginx
    6. name: nginx
    7. spec:
    8. containers:
    9. - image: nginx
    10. name: nginx
    11. resources:
    12. requests:
    13. cpu: "300m"
    14. memory: "56Mi"
    15. limits:
    16. cpu: "1"
    17. 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探针配置

    1. [root@master yaml]# cat liveness.yaml
    2. kind: Pod
    3. apiVersion: v1
    4. metadata:
    5. name: liveness
    6. labels:
    7. test: liveness
    8. spec:
    9. restartPolicy: OnFailure
    10. containers:
    11. - name: liveness
    12. image: busybox
    13. args:
    14. - /bin/sh
    15. - -c
    16. - touch /tmp/test; sleep 60; rm -rf /tmp/test; sleep 300
    17. livenessProbe:
    18. exec:
    19. command:
    20. - cat
    21. - /tmp/test
    22. initialDelaySeconds: 10
    23. periodSeconds: 5
    • initialDelaySeconds: Pod运行多长时间进行探测(单位是秒);
    • periodSeconds: 每隔多长时间进行一次探测(单位是秒);

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

     1.18.3 ReadinessProbe探针配置

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

    1. [root@master yaml]# cat readiness.yaml
    2. kind: Pod
    3. apiVersion: v1
    4. metadata:
    5. name: readiness
    6. labels:
    7. test: readiness
    8. spec:
    9. restartPolicy: OnFailure
    10. containers:
    11. - name: readiness
    12. image: busybox
    13. args:
    14. - /bin/sh
    15. - -c
    16. - touch /tmp/test; sleep 60; rm -rf /tmp/test; sleep 300
    17. readinessProbe:
    18. exec:
    19. command:
    20. - cat
    21. - /tmp/test
    22. initialDelaySeconds: 10
    23. periodSeconds: 5

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

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

    1. [root@master yaml]# cat hcscal.yaml
    2. kind: Deployment
    3. apiVersion: extensions/v1beta1
    4. metadata:
    5. name: web
    6. spec:
    7. replicas: 3
    8. template:
    9. metadata:
    10. labels:
    11. run: web
    12. spec:
    13. containers:
    14. - name: web
    15. image: httpd
    16. ports:
    17. - containerPort: 80
    18. readinessProbe:
    19. httpGet:
    20. scheme: HTTP
    21. path: /healthy
    22. port: 80
    23. initialDelaySeconds: 10
    24. periodSeconds: 5
    25. ---
    26. kind: Service
    27. apiVersion: v1
    28. metadata:
    29. name: web-svc
    30. spec:
    31. type: NodePort
    32. selector:
    33. run: web
    34. ports:
    35. - protocol: TCP
    36. port: 90
    37. targetPort: 80
    38. 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(扩容、缩容)、更新(升级)过程中使用。下面通过一个简单的小实验进行验证:

    1. [root@master yaml]# cat app.v1.yaml
    2. //版本1的yaml文件创建10个副本使用busybox镜像,如下:
    3. apiVersion: extensions/v1beta1
    4. kind: Deployment
    5. metadata:
    6. name: app
    7. spec:
    8. replicas: 10
    9. template:
    10. metadata:
    11. labels:
    12. run: app
    13. spec:
    14. containers:
    15. - name: app
    16. image: busybox
    17. args:
    18. - /bin/sh
    19. - -c
    20. - sleep 10; touch /tmp/healthy; sleep 3000
    21. readinessProbe:
    22. exec:
    23. command:
    24. - cat
    25. - /tmp/healthy
    26. initialDelaySeconds: 10
    27. periodSeconds: 5

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

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

            查看pod信息,如图:

    1. [root@master yaml]# cat app.v2.yaml
    2. //版本2的yaml文件创建10个副本使用busybox镜像
    3. //并模拟(代码中有问题,并进行升级),如下:
    4. apiVersion: extensions/v1beta1
    5. kind: Deployment
    6. metadata:
    7. name: app
    8. spec:
    9. strategy:
    10. rollingUpdate:
    11. maxSurge: 2
    12. maxUnavailable: 2
    13. replicas: 10
    14. template:
    15. metadata:
    16. labels:
    17. run: app
    18. spec:
    19. containers:
    20. - name: app
    21. image: busybox
    22. args:
    23. - /bin/sh
    24. - -c
    25. - sleep 3000
    26. readinessProbe:
    27. exec:
    28. command:
    29. - cat
    30. - /tmp/healthy
    31. initialDelaySeconds: 10
    32. periodSeconds: 5
    33. //maxSurge:此参数控制滚动更新过程中,副本总数超过预期数的值,可以是整数,也可以是百分比。默认是1
    34. //maxUnavailable:不可用Pod的值,默认为1,可以是整数,也可以是百分比
    35. [root@master yaml]# kubectl apply -f app.v2.yamll --record

            查看pod信息,如图: 

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

    1. [root@master yaml]# cat app.v3.yaml
    2. //版本2的yaml文件创建10个副本使用busybox镜像
    3. //并且不使用健康检查机制,如下:
    4. apiVersion: extensions/v1beta1
    5. kind: Deployment
    6. metadata:
    7. name: app
    8. spec:
    9. replicas: 10
    10. template:
    11. metadata:
    12. labels:
    13. run: app
    14. spec:
    15. containers:
    16. - name: app
    17. image: busybox
    18. args:
    19. - /bin/sh
    20. - -c
    21. - sleep 3000
    22. [root@master yaml]# kubectl apply -f app.v3.yamll --record

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

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

    1. [root@master yaml]# kubectl rollout history deployment app //查看记录的历史版本
    2. [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

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

    1. NAME READY STATUS RESTARTS AGE LABELS
    2. 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符号) 。例如:

    1. environment in (production, qa) 
    2. 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

    1. #查看nodeSelector帮助命令
    2. kubectl explain pods.spec.nodeSelector
    3. # nodeSelector
    4. # NodeSelector is a selector which must be true for the pod to fit on a node.
    5. # Selector which must match a node's labels for the pod to be scheduled on that node.
    6. # More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/

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

    kubectl get pods -o wide

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

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

    cat pod.yaml 看到完整的文件如下:

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: web
    5. namespace: default
    6. labels:
    7. web1: tomcat
    8. spec:
    9. containers:
    10. - name: tomcat1
    11. image: tomcat:8.5-jre8-alpine
    12. nodeSelector:
    13. node011:haha
    14. kubectl delete -f pod.yaml
    15. kubectl apply -f pod.yaml
    16. 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。

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: cap-pod
    5. spec:
    6. containers:
    7. - name: friendly-container
    8. image: "alpine:3.4"
    9. command: ["/bin/sleep", "3600"]
    10. securityContext:
    11. capabilities:
    12. add:
    13. - NET_ADMIN
    14. drop:
    15. - KILL

    1.22 限制网络带宽

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

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: qos
    5. annotations:
    6. kubernetes.io/ingress-bandwidth: 3M
    7. kubernetes.io/egress-bandwidth: 4M
    8. spec:
    9. containers:
    10. - name: iperf3
    11. image: networkstatic/iperf3
    12. command:
    13. - iperf3
    14. - -s

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

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

    1. # setup qdisc (only once)
    2. tc qdisc add dev cbr0 root handle 1: htb default 30
    3. # download rate
    4. tc class add dev cbr0 parent 1: classid 1:2 htb rate 3Mbit
    5. tc filter add dev cbr0 protocol ip parent 1:0 prio 1 u32 match ip dst 10.1.0.3/32 flowid 1:2
    6. # upload rate
    7. tc class add dev cbr0 parent 1: classid 1:3 htb rate 4Mbit
    8. 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  disktype=ssd

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

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: nginx
    5. labels:
    6. env: test
    7. spec:
    8. containers:
    9. - name: nginx
    10. image: nginx
    11. imagePullPolicy: IfNotPresent
    12. nodeSelector:
    13. disktype: ssd

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

    1.24 自定义 hosts

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

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

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

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

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: hostaliases-pod
    5. spec:
    6. hostAliases:
    7. - ip: "127.0.0.1"
    8. hostnames:
    9. - "foo.local"
    10. - "bar.local"
    11. - ip: "10.1.2.3"
    12. hostnames:
    13. - "foo.remote"
    14. - "bar.remote"
    15. containers:
    16. - name: cat-hosts
    17. image: busybox
    18. command:
    19. - cat
    20. args:
    21. - "/etc/hosts"
    1. $ kubectl logs hostaliases-pod
    2. # Kubernetes-managed hosts file.
    3. 127.0.0.1 localhost
    4. ::1 localhost ip6-localhost ip6-loopback
    5. fe00::0 ip6-localnet
    6. fe00::0 ip6-mcastprefix
    7. fe00::1 ip6-allnodes
    8. fe00::2 ip6-allrouters
    9. 10.244.1.5 hostaliases-pod
    10. 127.0.0.1 foo.local
    11. 127.0.0.1 bar.local
    12. 10.1.2.3 foo.remote
    13. 10.1.2.3 bar.remote

    1.25 HugePages

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

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

            使用示例

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. generateName: hugepages-volume-
    5. spec:
    6. containers:
    7. - image: fedora:latest
    8. command:
    9. - sleep
    10. - inf
    11. name: example
    12. volumeMounts:
    13. - mountPath: /hugepages
    14. name: hugepage
    15. resources:
    16. limits:
    17. hugepages-2Mi: 100Mi
    18. volumes:
    19. - name: hugepage
    20. emptyDir:
    21. 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,并设置优先级(数值越大优先级越高):

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

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

            为 Pod 指定优先级:

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: nginx
    5. labels:
    6. env: test
    7. spec:
    8. containers:
    9. - name: nginx
    10. image: nginx
    11. imagePullPolicy: IfNotPresent
    12. priorityClassName: high-priority

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

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

    1.27 PodDisruptionBudget

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

    1. apiVersion: policy/v1beta1
    2. kind: PodDisruptionBudget
    3. metadata:
    4. name: zk-pdb
    5. spec:
    6. maxUnavailable: 1
    7. selector:
    8. matchLabels:
    9. 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 示例:

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

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

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: sysctl-example
    5. spec:
    6. securityContext:
    7. sysctls:
    8. - name: kernel.shm_rmid_forced
    9. value: "0"
    10. - name: net.ipv4.route.min_pmtu
    11. value: "552"
    12. - name: kernel.msgmax
    13. value: "65536"
    14. ...

    1.29 Pod 时区

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

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: sh
    5. namespace: default
    6. spec:
    7. containers:
    8. - image: alpine
    9. stdin: true
    10. tty: true
    11. volumeMounts:
    12. - mountPath: /etc/localtime
    13. name: time
    14. readOnly: true
    15. volumes:
    16. - hostPath:
    17. path: /etc/localtime
    18. type: ""
    19. 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

  • 相关阅读:
    http响应状态码(Header常见属性 — Location属性)
    双十一运动装备选购清单,今年最值得入手的运动好物
    大数据Flink(一百):SQL自定义函数(UDF)和标量函数(Scalar Function)
    static的作用
    系统架构的11条原则
    【递归】什么是递归-C语言为例
    C++-容器-string:string的大小和容量
    距离度量 —— 汉明距离(Hamming Distance)
    51单片机DHT11温湿度控制系统仿真设计( proteus仿真+程序+原理图+报告+讲解视频)
    Swift基础
  • 原文地址:https://blog.csdn.net/junbaozi/article/details/127078155