zoukankan      html  css  js  c++  java
  • K8S-POD详解

    Pod是最小的部署单元,也是后面经常配置的地方,本章节带你熟悉Pod中常见资源配置及参数。

    也就是YAML这部分:

      ...
      template:
        metadata:
          labels:
            app: web
        spec:
          containers:
          - image: a13552821243/java-demo:latest
            imagePullPolicy: Always
            name: java
    

    6.1 Pod介绍

    • 最小部署单元

    • 一组容器的集合

    • 一个Pod中的容器共享网络命名空间

    • Pod是短暂的

    6.2 Pod存在的意义

    Pod为亲密性应用而存在。

    亲密性应用场景:

    • 两个应用之间发生文件交互

    • 两个应用需要通过127.0.0.1或者socket通信

    • 两个应用需要发生频繁的调用

    6.3 Pod实现机制与设计模式

    Pod本身是一个逻辑概念,没有具体存在,那究竟是怎么实现的呢?

    众所周知,容器之间是通过Namespace隔离的,Pod要想解决上述应用场景,那么就要让Pod里的容器之间高效共享。

    具体分为两个部分:网络和存储

    • 共享网络

    kubernetes的解法是这样的:会在每个Pod里先启动一个infra container小容器,然后让其他的容器连接进来这个网络命名空间,然后其他容器看到的网络试图就完全一样了,即网络设备、IP地址、Mac地址等,这就是解决网络共享问题。在Pod的IP地址就是infra container的IP地址。

    • 共享存储

    比如有两个容器,一个是nginx,另一个是普通的容器,普通容器要想访问nginx里的文件,就需要nginx容器将共享目录通过volume挂载出来,然后让普通容器挂载的这个volume,最后大家看到这个共享目录的内容一样。

    例如:

    # pod.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    spec:
      containers:
      - name: write
        image: centos
        command: ["bash","-c","for i in {1..100};do echo $i >> /data/hello;sleep 1;done"]
        volumeMounts:
          - name: data
            mountPath: /data
    
      - name: read
        image: centos
        command: ["bash","-c","tail -f /data/hello"]
        volumeMounts:
          - name: data
            mountPath: /data
      
      volumes:
      - name: data
        emptyDir: {}
    

     上述示例中有两个容器,write容器负责提供数据,read消费数据,通过数据卷将写入数据的目录和读取数据的目录都放到了该卷中,这样每个容器都能看到该目录。

    验证:


    kubectl apply -f pod.yaml
    kubectl logs my-pod -c read -f
    

     

    在Pod中容器分为以下几个类型:

    • Infrastructure Container:基础容器,维护整个Pod网络空间,对用户不可见

    • InitContainers:初始化容器,先于业务容器开始执行,一般用于业务容器的初始化工作

    • Containers:业务容器,具体跑应用程序的镜像

    6.4 镜像拉取策略

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    spec:
      containers:
        - name: java
          image: a13552821243/java-demo
          imagePullPolicy: IfNotPresent
    

    imagePullPolicy 字段有三个可选值:

    • IfNotPresent:镜像在宿主机上不存在时才拉取

    • Always:默认值,每次创建 Pod 都会重新拉取一次镜像

    • Never: Pod 永远不会主动拉取这个镜像

    如果拉取公开的镜像,直接按照上述示例即可,但要拉取私有的镜像,是必须认证镜像仓库才可以,即docker login,而在K8S集群中会有多个Node,显然这种方式是很不放方便的!为了解决这个问题,K8s 实现了自动拉取镜像的功能。 以secret方式保存到K8S中,然后传给kubelet。

    6.5 资源限制

    Pod资源配额有两种:

    • 申请配额:调度时使用,参考是否有节点满足该配置

      spec.containers[].resources.limits.cpu

      spec.containers[].resources.limits.memory

    • 限制配额:容器能使用的最大配置

      spec.containers[].resources.requests.cpu

      spec.containers[].resources.requests.memory

    示例:

    apiVersion: v1
    kind: Pod
    metadata:
      name: web
    spec:
      containers:
      - name: java
        image: a13552821243/java-demo
        resources:
          requests:
            memory: "64Mi"
            cpu: "250m"
          limits:
            memory: "128Mi"
            cpu: "500m"
    

    其中cpu值比较抽象,可以这么理解:

    1核=1000m

    1.5核=1500m

    那上面限制配置就是1核的二分之一(500m),即该容器最大使用半核CPU。

    该值也可以写成浮点数,更容易理解:

    半核=0.5

    1核=1

    1.5核=1.5

    6.6 重启策略

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    spec:
      containers:
      - name: java
        image: a13552821243java-demo
      restartPolicy: Always
    

    restartPolicy字段有三个可选值:

    • Always:当容器终止退出后,总是重启容器,默认策略。

    • OnFailure:当容器异常退出(退出状态码非0)时,才重启容器。适于job

    • Never:当容器终止退出,从不重启容器。适于job

    6.7 健康检查

    默认情况下,kubelet 根据容器状态作为健康依据,但不能容器中应用程序状态,例如程序假死。这就会导致无法提供服务,丢失流量。因此引入健康检查机制确保容器健康存活。

    健康检查有两种类型:

    • livenessProbe

      如果检查失败,将杀死容器,根据Pod的restartPolicy来操作。

    • readinessProbe

      如果检查失败,Kubernetes会把Pod从service endpoints中剔除。

    这两种类型支持三种检查方法:

    Probe支持以下三种检查方法:

    • httpGet

      发送HTTP请求,返回200-400范围状态码为成功。

    • exec

      执行Shell命令返回状态码是0为成功。

    • tcpSocket

      发起TCP Socket建立成功。

    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        test: liveness
      name: liveness-exec
    spec:
      containers:
      - name: liveness
        image: busybox
        args:
        - /bin/sh
        - -c
        - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 60
        livenessProbe:
          exec:
            command:
            - cat
            - /tmp/healthy
          initialDelaySeconds: 5
          periodSeconds: 5
    

    上述示例:启动容器第一件事创建文件,停止30s,删除该文件,再停止60s,确保容器还在运行中。

    验证现象:容器启动正常,30s后异常,会restartPolicy策略自动重建,容器继续正常,反复现象。

     

    6.8 调度策略

    先看下创建一个Pod的工作流程: create pod -> apiserver -> write etcd -> scheduler -> bind pod to node -> write etcd -> kubelet( apiserver get pod) -> dcoekr api,create container -> apiserver -> update pod status to etcd -> kubectl get pods

    Pod根据调度器默认算法将Pod分配到合适的节点上,一般是比较空闲的节点。但有些情况我们希望将Pod分配到指定节点,该怎么做呢?

    这里给你介绍调度策略:nodeName、nodeSelector和污点

    1、nodeName

    nodeName用于将Pod调度到指定的Node名称上。

    例如:下面示例会绕过调度系统,直接分配到k8s-node1节点。

    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        run: busybox
      name: busybox
      namespace: default
    spec:
      nodeName: k8s-node1
      containers:
      - image: busybox
        name: bs
        command:
        - "ping"
        - "baidu.com"
    kubectl label nodes k8s-node1 team=a
    kubectl label nodes k8s-node2 team=b
    

    2、nodeSelector

    nodeSelector用于将Pod调度到匹配Label的Node上。

    先给规划node用途,然后打标签,例如将两台node划分给不同团队使用:

    后在创建Pod只会被调度到含有team=a标签的节点上。

    apiVersion: v1
    kind: Pod
    metadata:
      name: busybox
      namespace: default
    spec:
      nodeSelector: 
        team: b
      containers:
      - image: busybox
        name: bs
        command:
        - "ping"
        - "baidu.com"
    
    **3、taint(污点)与tolerations(容忍)**  
    
    污点应用场景:节点独占,例如具有特殊硬件设备的节点,如GPU
    
    设置污点命令:
    kubectl taint node [node] key=value[effect]

    其中[effect] 可取值:

    • NoSchedule :一定不能被调度。

    • PreferNoSchedule:尽量不要调度。

    • NoExecute:不仅不会调度,还会驱逐Node上已有的Pod。

    示例:

    先给节点设置污点,说明这个节点不是谁都可以调度过来的:

    kubectl taint node k8s-node1  abc=123:NoSchedule

    查看污点:

    kubectl describe node k8s-node1 |grep Taints

    然后在创建Pod只有声明了容忍污点(tolerations),才允许被调度到abc=123污点节点上。


    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        run: busybox
      name: busybox3
      namespace: default
    spec:
      tolerations:
      - key: "abc"
        operator: "Equal"
        value: "123"
        effect: "NoSchedule"
      containers:
      - image: busybox
        name: bs
        command:
        - "ping"
        - "baidu.com"
    

    如果不配置容忍污点,则永远不会调度到k8s-node1。

    去掉污点:

    kubectl taint node [node] key:[effect]-
    kubectl taint node k8s-node1 abc:NoSchedule-
    

     6.9 故障排查

    # 查看事件,可用于大部分资源
    kubectl describe TYPE/NAME    
    # 如果pod启动失败,先查看日志
    kubectl logs TYPE/NAME [-c CONTAINER]  
    # 进入到容器中debug
    kubectl exec POD [-c CONTAINER] -- COMMAND [args...]  
    

     

     

     

     

     

     

     



     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    [ARC 102D]All Your Paths are Different Lengths
    [NOI 2016] 优秀的拆分
    [TJOI 2015] 线性代数
    [LUOGU 4717] 快速沃尔什变换
    [NOI 2006] 最大获利
    Javascript继承机制的设计
    必应输入法产品分析
    你不得不知道的HTML5的新型标签
    Mobile Web
    10行代码爬取网页
  • 原文地址:https://www.cnblogs.com/zhaobin-diray/p/13363496.html
Copyright © 2011-2022 走看看