04.深入pods

62 阅读16分钟

在k8s集群中任意节点使用kubectl

# 1.将master节点中/etc/kubernetes/admin.conf拷贝到node1和node2的/etc/kubernetes目录中
scp /etc/kubernetes/admin.conf root@k8s-node1:/etc/kubernetes
scp /etc/kubernetes/admin.conf root@k8s-node2:/etc/kubernetes
# 2.在node1和node2上配置环境变量
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
source ~/.bash_profile

kubectl常用命令

# k8s命令大全:https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands
# 可以使用kubectl --help 以及kubectl xxx --help获取命令以及参数信息
# 获取xxx资源的信息,如po、deploy、svc、ns等
kubectl get xxx
# kubectl命令中可以使用po代替pods,deploy代替deployments,svc代替services,ns代替namespace,no代替nodes
# 获取pods
kubectl get po
#获取命名空间
kubectl get ns
# 获取deployments
kubectl get deploy
# 获取services
kubectl get svc
# 获取nodes
kubectl get no
# 获取pods的详细信息
kubectl get po -o wide
# 删除某个deploy,删除pods、services、namespaces、nodes同理
kubectl delete deploy xxx
# 查看pod资源的资源清单属性
kubectl explain pod
kubectl create -f xxx.yaml

K8S资源清单

1.必选字段

参数名字段类型说明
versionString指 K8s API 的版本,目前基本上是 v1 ,可以用 kubectl api-versions 命令查询
kindString指 yaml 文件定义的资源类型和角色,比如:Pod
metadataObject元数据对象
metadata.nameString元数据对象的名字,比如命名 Pod 的名字
metadata.namespaceString元数据对象的命名空间(默认default)
specObject详细定义对象
spec.containers[]List容器列表的定义
spec.containers[].nameString容器的名字
spec.containers[].imageString容器镜像的名称

2.主要字段

参数名字段类型说明
spec.containers[].imagePullPolicyString定义镜像的拉取策略,有Always、Never、IfNotPresent三个值可选,(1)Always:意思是每次都尝试重新拉取镜像,(2)Never:表示仅使用本地镜像,(3)IfNotPresent:如果本地有镜像就使用本地镜像,没有就拉取在线镜像。上面三个值都没设置的话,默认是Always。
spec.containers[].command[]List指定容器启动命令,因为是数组可以指定多个,不指定则使用镜像打包时使用的启动命令。
spec.containers[].args[]List批定容器启动命令参数,因为是数组可以指定多个。
spec.containers[].workingDirString指定容器的工作目录
spec.containers[].volumeMounts[]List指定容器内部的存储卷位置
spec.containers[].volumeMounts[].nameString指定可以被容器挂载的存储卷的名称
spec.containers[].volumeMounts[].mountPathString指定可以被挂载的存储卷的路径
spec.containers[].volumeMounts[].readOnlyString设置存储卷路径的读写模式,true或者false,默认为读写模式
spec.containers[].ports[]List指定容器需要用到的端口列表
spec.containers[].ports[].nameString指定端口名称
spec.containers[].ports[].containerPortString指定容器需要监听的端口号
spec.containers[].ports[].hostPortString指定容器所在主机需要监听的端口号,默认跟上面containerPort相同,注意设置了hostPort同一台主机无法启动该容器的相同副本(会端口冲突)
spec.containers[].ports[].protocolString指定端口协议,支持TCP和UDP,默认为TCP
spec.containers[].env[]List指定容器运行前需要设置的环境变量列表
spec.containers[].env[].nameString指定环境变量名称
spec.containers[].env[].valueString指定环境变量值
spec.containers[].resourcesObject指定资源限制和资源请求的值(这里开始就是设置容器的资源上限)
spec.containers[].resources.limitsObject指定设置容器运行时资源的运行上限
spec.containers[].resources.limits.cpuString指定CPU限制,单位为core数,将用于docker run --cpu-shares参数
spec.containers[].resources.limits.memoryString指定MEM内存的限制,单位为MIB、GiB
spec.containers[].resources.requestsObject指定容器启动和调度时的限制设置
spec.containers[].resources.requests.cpuStringCPU请求,单位为core数,容器启动时初始化可用数量
spec.containers[].resources.requests.memoryString内存请求,单位为MIB、GiB,容器启动时初始化可用数量

3.额外字段

参数名字段类型说明
spec.restartPolicyString定义Pod的重启策略,可选值为Always、OnFailure、默认为Always。 1. Always:Pod一旦终止运行,则无论容器是如何终止的,kubelet服务都将重启它 2.OnFailure:只有Pod以非零退出码终止时,kubelet才会重启该容器。如果容器正常结束(退出码为0),则kubelet不会重启它。 3.Never:Pod终止后,kubelet将退出码报告给master,不会重启该Pod
spec.nodeSelectorObject定义Node的Label过滤标签,以key:value格式指定
spec.imagePullSecretsObject定义pull镜像时使用secret名称,以name:secretkey格式指定
spec.hostNetworkBoolean定义是否使用主机网络模式,默认值是false,设置true表示使用主机网络,不使用docker网桥,同时设置了true将无法在同一台宿主机上启动第二个副本

Pod资源清单详解

# yaml格式的pod定义文件完整内容:
apiVersion: v1       #必选,版本号,例如v1
kind: Pod       #必选,Pod
metadata:       #必选,元数据
  name: string       #必选,Pod名称
  namespace: string    #必选,Pod所属的命名空间
  labels:      #自定义标签
    - name: string     #自定义标签名字
  annotations:       #自定义注释列表
    - name: string
spec:         #必选,Pod中容器的详细定义
  containers:      #必选,Pod中容器列表
  - name: string     #必选,容器名称
    image: string    #必选,容器的镜像名称
    imagePullPolicy: [Always | Never | IfNotPresent] #获取镜像的策略 Alawys表示下载镜像 IfnotPresent表示优先使用本地镜像,否则下载镜像,Nerver表示仅使用本地镜像
    command: [string]    #容器的启动命令列表,如不指定,使用打包时使用的启动命令
    args: [string]     #容器的启动命令参数列表
    workingDir: string     #容器的工作目录
    volumeMounts:    #挂载到容器内部的存储卷配置
    - name: string     #引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名
      mountPath: string    #存储卷在容器内mount的绝对路径,应少于512字符
      readOnly: boolean    #是否为只读模式
    ports:       #需要暴露的端口库号列表
    - name: string     #端口号名称
      containerPort: int   #容器需要监听的端口号
      hostPort: int    #容器所在主机需要监听的端口号,默认与Container相同
      protocol: string     #端口协议,支持TCP和UDP,默认TCP
    env:       #容器运行前需设置的环境变量列表
    - name: string     #环境变量名称
      value: string    #环境变量的值
    resources:       #资源限制和请求的设置
      limits:      #资源限制的设置
        cpu: string    #Cpu的限制,单位为core数,将用于docker run --cpu-shares参数
        memory: string     #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数
      requests:      #资源请求的设置
        cpu: string    #Cpu请求,容器启动的初始可用数量
        memory: string     #内存清楚,容器启动的初始可用数量
    livenessProbe:     #对Pod内个容器健康检查的设置,当探测无响应几次后将自动重启该容器,检查方法有exec、httpGet和tcpSocket,对一个容器只需设置其中一种方法即可
      exec:      #对Pod容器内检查方式设置为exec方式
        command: [string]  #exec方式需要制定的命令或脚本
      httpGet:       #对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、port
        path: string
        port: number
        host: string
        scheme: string
        HttpHeaders:
        - name: string
          value: string
      tcpSocket:     #对Pod内个容器健康检查方式设置为tcpSocket方式
         port: number
       initialDelaySeconds: 0  #容器启动完成后首次探测的时间,单位为秒
       timeoutSeconds: 0   #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒
       periodSeconds: 0    #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次
       successThreshold: 0
       failureThreshold: 0
       securityContext:
         privileged:false
    restartPolicy: [Always | Never | OnFailure]#Pod的重启策略,Always表示一旦不管以何种方式终止运行,kubelet都将重启,OnFailure表示只有Pod以非0退出码退出才重启,Nerver表示不再重启该Pod
    nodeSelector: obeject  #设置NodeSelector表示将该Pod调度到包含这个label的node上,以key:value的格式指定
    imagePullSecrets:    #Pull镜像时使用的secret名称,以key:secretkey格式指定
    - name: string
    hostNetwork:false      #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络
    volumes:       #在该pod上定义共享存储卷列表
    - name: string     #共享存储卷名称 (volumes类型有很多种)
      emptyDir: {}     #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值
      hostPath: string     #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录
        path: string     #Pod所在宿主机的目录,将被用于同期中mount的目录
      secret:      #类型为secret的存储卷,挂载集群与定义的secre对象到容器内部
        scretname: string  
        items:     
        - key: string
          path: string
      configMap:     #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部
        name: string
        items:
        - key: string
          path: string

K8S探针

探针类型

Kubernetes(k8s)中的探针是一种健康检查机制,用于监测Pod内容器的运行状况。主要包括以下三种类型的探针:

1、存活探针(Liveness Probe)

2、就绪探针(Readiness Probe)

3、启动探针(Startup Probe)

探针功能

启动探针(StartupProbe)

Kubernetes (k8s) 的启动探针(StartupProbe)主要用于检测容器内的应用是否已经成功启动并完成初始化任务。它的主要作用有以下几点:

  1. 延缓其他探针生效: 在容器启动初期,启动探针先于存活探针(LivenessProbe)和就绪探针(ReadinessProbe)生效。当启动探针配置存在时,kubelet不会执行存活和就绪探针,直到启动探针成功为止。这对于某些启动时间较长或者启动过程中有复杂初始化序列的应用程序来说非常重要,可以避免在应用还未完全启动时就被误判为不健康或就绪,进而被错误地重启或流量过早涌入。

  2. 防止频繁重启: 若应用启动期间,存活探针或就绪探针就开始工作,而此时应用可能还没有完全启动成功,这两个探针可能会因为应用未能及时响应而触发容器重启,造成不必要的服务中断和循环重启。启动探针的存在可以有效地防止此类情况的发生。

  3. 确保应用稳定: 启动探针使得Kubernetes能够在应用真正启动完毕后才将其视为健康的,并开始接受流量,从而保障了集群中应用服务的稳定性。

就绪探针(Readiness Probe)

Kubernetes(k8s)中的就绪探针(Readiness Probe)主要作用是检测容器是否已经准备好对外提供服务。具体来说:

  1. 状态评估: 就绪探针会定期对容器进行检查,以确定容器内应用程序是否完成了必要的初始化工作,并且能够处理来自外部的请求或流量。

  2. 流量路由控制: 当就绪探针成功时,表示该容器内部的应用程序已处于可接受请求的状态,此时kubelet会将该容器标记为“就绪”状态,Service将会将其IP地址添加到后端服务列表中,允许Service开始将网络流量转发至这个Pod。

  3. 避免无效请求: 如果就绪探针失败,则意味着容器可能还在启动过程中、正在重启服务、或者由于某种原因暂时无法正常响应请求。在这种情况下,kubelet会将容器从Service的后端池中移除,确保不会向其发送任何用户请求,从而避免了因应用未准备完毕而引起的错误响应和用户体验下降。

  4. 平滑过渡: 通过就绪探针,Kubernetes可以实现滚动更新或部署过程中的平滑过渡,新版本的容器在通过就绪探针验证前,不会承担任何实际流量,直到它们完全启动并做好处理请求的准备。

存活探针(Readiness Probe)

Kubernetes(k8s)中的存活探针(Liveness Probe)主要作用是检测容器内主进程或服务是否仍然运行正常且响应健康检查。具体来说:

  1. 监控状态: 存活探针会定期对容器内的应用进行检查,以判断其是否处于“存活”状态,即应用程序没有崩溃、死锁或其他不可恢复的错误。

  2. 自动恢复: 当存活探针检测失败时,kubelet将认为该容器内的主进程已经不再健康或者已停止提供预期的服务。此时,kubelet会根据Pod的重启策略来决定是否应该重新启动这个容器。通过这种方式,存活探针可以帮助实现故障自愈,及时恢复服务的可用性。

  3. 避免僵死进程: 如果一个容器由于内部错误而进入不可用状态但并未退出,存活探针能够识别出这种情况,并触发容器重启,从而避免资源被僵死进程占用。

  4. 保持服务质量: 通过持续监控和及时重启不健康的容器,存活探针有助于确保整个集群的服务质量,减少因单个容器异常导致的整体服务失效的可能性。

探针探测周期

  1. 启动探针(Startup Probe):

    • 启动探针仅在容器启动阶段执行,探测成功后就不在探测。

    • 在容器启动后等待initialDelaySeconds开始探测。

    • 当容器成功通过启动探针检查,即连续成功达到successThreshold次数时,kubelet会停止执行启动探针,并开始执行存活探针和就绪探针。

  2. 存活探针(Liveness Probe):

    • 在容器启动并完成启动探针之后开始执行。

    • 在容器启动后等待initialDelaySeconds开始执行。如果配置了启动探针(Startup Probe),在启动探针成功后等待initialDelaySeconds开始探测。

    • 存活探针在整个容器生命周期内持续进行健康检查,除非被暂时禁用或容器重启。

  3. 就绪探针(Readiness Probe):

    • 与存活探针类似,也是在容器启动并可能完成启动探针之后开始执行。

    • 在容器启动后等待initialDelaySeconds开始执行。如果配置了启动探针(Startup Probe),在启动探针成功后等待initialDelaySeconds开始探测。

    • 就绪探针在整个容器生命周期内持续进行健康检查,除非被暂时禁用或容器重启。

探针的实现方式

  1. HTTP GET 请求: Kubernetes通过向容器内指定的端口发送一个HTTP GET请求来检查应用的状态。如果收到的HTTP响应码在200-399范围内,则认为该探测成功。
livenessProbe:
  httpGet:
    path: /health-check
    port: 8080
    httpHeaders: # 可选,用于设置自定义HTTP头部
    - name: Custom-Header
      value: Value
  1. TCP Socket 检查: Kubernetes尝试与容器上指定的端口建立TCP连接。如果能够成功建立连接,则说明探测成功。
livenessProbe:
  tcpSocket:
    port: 8080
  1. 执行命令: 在容器内部执行一个命令,并根据命令退出时返回的状态码判断容器是否正常运行。通常情况下,如果命令返回0,则表示成功。
livenessProbe:
  exec:
    command:
    - cat
    - /tmp/health

探针的配置参数

livenessProbe:
  # 类型选择器,可以选择 httpGet、tcpSocket 或 exec 中的一种
  httpGet:         # HTTP GET 请求方式
    path: /health   # 要请求的路径
    port: 8080      # 要请求的端口
    httpHeaders:     # 可选,HTTP 请求头列表
    - name: X-Custom-Header
      value: Awesome
  tcpSocket:       # TCP Socket 检查方式
    port: 8080      # 要连接的端口
  exec:            # 执行命令检查方式
    command:
    - cat
    - /tmp/healthy

  # 基本探测间隔参数:
  initialDelaySeconds: 30  # 容器启动后延迟多少秒开始执行第一次探测,默认为0秒
  periodSeconds: 10        # 探测的时间间隔,即每隔多少秒执行一次,默认为10秒(最小值1秒)
  
  # 控制何时判断容器健康或不健康的阈值参数:
  timeoutSeconds: 1          # 探测超时时间,默认为1秒(最小值1秒)
  successThreshold: 1        # 在连续失败之后需要多少次连续成功才能认为容器是健康的,默认为1
  failureThreshold: 3        # 连续失败多少次才触发相应动作(如重启容器对于存活探针)

readinessProbe: # 就绪探针配置类似
startupProbe:   # 启动探针配置也相似,不过主要用于检测应用是否完成启动过程

Pod的生命周期

Kubernetes 为容器提供了生命周期回调。 回调使容器能够了解其管理生命周期中的事件,并在执行相应的生命周期回调时运行在处理程序中实现的代码。Kubernetes 支持 PostStart 和 PreStop 事件。 当一个容器启动后,Kubernetes 将立即发送 PostStart 事件;在容器被终结之前, Kubernetes 将发送一个 PreStop 事件。

image.png

PostStart

PostStart回调在容器创建后立即执行,但是PostStart并不能保证在容器ENTRYPOINT之前运行,所以PostStart的执行相对于容器的代码执行是异步的。

PostStart主要用于资源部署、环境准备等。

只有 PostStart 处理函数执行完毕,容器的状态才会变成 RUNNING。

PreStop

PreStop在容器终止前立即被调用,它是阻塞的,所以它必须在删除容器的调用触发之前完成。

PreStop主要用于优雅关闭应用程序、通知其他系统等。

如果钩子在执行期间挂起,Pod阶段将停留在Running状态并且不会达到failed状态。

另外,PreStop的执行现对于SIGTERM信息,也是异步的,k8s也不会等待PreStop执行完成。

Pod终止过程

  • 【第一步】用户发出删除 pod 命令

  • 【第二步】K8S 会给旧POD发送SIGTERM信号;将 pod 标记为“Terminating”状态;pod 被视为“dead”状态,此时将不会有新的请求到达旧的pod;

  • 【第三步】并且等待宽限期(pod.spec.terminationGracePeriodSeconds 参数定义,默认情况下30秒)这么长的时间

  • 第三步同时运行,监控到 pod 对象为“Terminating”状态的同时启动 pod 关闭过程

  • 第三步同时进行,endpoints 控制器监控到 pod 对象关闭,将pod与service匹配的 endpoints 列表中删除

  • 如果 pod 中定义了 preStop 处理程序,则 pod 被标记为“Terminating”状态时以同步的方式启动执行preStop;若宽限期结束后,preStop 仍未执行结束,第二步会重新执行并额外获得一个2秒的小宽限期(最后的宽限期,所以定义preStop 注意时间,和terminationGracePeriodSeconds 参数配合使用),

  • Pod 内对象的容器收到 TERM 信号

  • 宽限期结束之后,若存在任何一个运行的进程,pod 会收到 SIGKILL 信号

  • Kubelet 请求 API Server 将此 Pod 资源宽限期设置为0从而完成删除操作