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

2022-10-04 19:59:37 浏览数 (1)

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。

代码语言:javascript复制
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:

代码语言:javascript复制
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(只能自己访问到自己);
代码语言:javascript复制
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 版。

代码语言:javascript复制
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,如:

代码语言:javascript复制
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 的内存:

代码语言:javascript复制
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帮助命令:

代码语言:javascript复制
kubectl explain pods.spec.containers.livenessProbe

#查看readinessProbe帮助命令:

代码语言:javascript复制
kubectl explain pods.spec.containers.readinessProbe

        整个图如下:

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

1.18.2 LivenessProbe探针配置

代码语言:javascript复制
[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探针配置

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

代码语言:javascript复制
[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状态如图:

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

代码语言:javascript复制
[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(扩容、缩容)、更新(升级)过程中使用。下面通过一个简单的小实验进行验证:

代码语言:javascript复制
[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文件生成相应的资源,并且记录历史版本信息:

代码语言:javascript复制
[root@master yaml]# kubectl apply -f app.v1.yaml --record

        查看pod信息,如图:

代码语言:javascript复制
[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了!

代码语言:javascript复制
[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中服务存在问题,也会全部更新!

代码语言:javascript复制
[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集群当前有哪些名称空间:

代码语言:javascript复制
kubectl get namespace

1.20 pod label

(1)什么是标签?

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

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

代码语言:javascript复制
kubectl get pods --show-labels

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

代码语言:javascript复制
kubectl get pods -L web1

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

代码语言:javascript复制
kubectl get pods -l web1 --show-labels

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

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

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

代码语言:javascript复制
kubectl label pods web release=new

        查看标签是否打成功:

代码语言:javascript复制
kubectl get pods --show-labels

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

代码语言:javascript复制
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。有三种运算符是允许的,“=”,“==”和“!=”。前两种代表相等性(他们是同义运算符),后一种代表非相等性。例如:

代码语言:javascript复制
environment = production tier != frontend

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

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

代码语言:javascript复制
environment=production,tier!=frontend

        基于集合的标签选择器:

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

代码语言:javascript复制
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节点的标签

代码语言:javascript复制
kubectl get nodes --show-labels

(2)给node节点打标签:

代码语言:javascript复制
kubectl label nodes node1 node011=haha kubectl get nodes --show-labels

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

(3)节点选择器nodeSelector

代码语言:javascript复制
#查看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运行在哪个节点上

代码语言:javascript复制
kubectl get pods -o wide

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

代码语言:javascript复制
nodeSelector:

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

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

代码语言:javascript复制
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帮助命令:

代码语言:javascript复制
kubectl explain pods.spec.nodeName

1.21 使用 Capabilities

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

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

代码语言:javascript复制
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 的网络带宽:

代码语言:javascript复制
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 来实现的:

代码语言:javascript复制
# 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 加上标签:

代码语言:javascript复制
kubectl label nodes <your-node-name> disktype=ssd

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

代码语言:javascript复制
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:

代码语言:javascript复制
$ 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 内容,如:

代码语言:javascript复制
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"
代码语言:javascript复制
$ 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 容量

        使用示例

代码语言:javascript复制
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,并设置优先级(数值越大优先级越高):

代码语言:javascript复制
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 指定优先级:

代码语言:javascript复制
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 管理。

代码语言:javascript复制
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 示例:

代码语言:javascript复制
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 设置,如:

代码语言:javascript复制
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 一样的时区:

代码语言:javascript复制
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

0 人点赞