Kubernetes:Pod

pod 是 Kubernetes 中创建和管理的最小可部署单元。pod 就像一台逻辑主机,是一组共享上下文的容器集合,共享存储、网络,一同调度。

pod 遵循预定义的生命周期,起始于 Pending 阶段, 如果至少其中有一个主要容器正常启动,则进入 Running,之后取决于 Pod 中是否有容器以失败状态结束而进入 Succeeded 或者 Failed 阶段。pod 在其生命周期中只会被调度一次。 一旦 pod 被调度到某个节点,pod 会一直在该节点运行,直到 pod 停止或者被终止。

在这里插入图片描述

1、Pod 定义

pod 使用 yaml 文件定义,使用下面命令查看 pod 资源文档的说明。

kubectl explain pods

pod 有两种用法:

  • 运行单个容器的 pod
  • 运行多个容器的 pod

例如定义 myhello-pod.yaml 配置文件,运行多个容器的 pod

# api 版本
apiVersion: v1
# 类型
kind: Pod
# 元数据
metadata: 
  # 名字
  name: myhello-pod
  # 命名空间
  namespace: default 
  # 标签,svc,deployment 通过 labels 管理 pod 
  labels:
    name: myhello-pod
    env: dev
# 规则
spec:
  # 容器重启策略:Always、Never、OnFailure
  restartPolicy: Always
  # 定义容器
  containers:
  # 容器1: myhello
  - name: myhello
    image: xlhmzch/hello:1.0.0
    # 镜像拉取策略:Always、Never、IfNotPresent
    # Always:总是拉取最新镜像,测试环境使用
    # Never:不拉取镜像,使用本地镜像
    # IfNotPresent:本地没有镜像,则拉取镜像
    imagePullPolicy: IfNotPresent
    # 容器端口
    ports:
    - containerPort: 80
    # 容器启动命令,二进制文件名 app
    command: ["./app"]
    # 容器启动命令参数
    args: ["--param1=k8s-p1", "--param2=k8s-p2"]
    # 容器使用资源设置
    resources:
      # 容器可分配的最低资源配额
      requests:
        cpu: 100m     # cpu 资源单位:1CPU=1000m,通常容器使用的 cpu 配额 100m~300m
        memory: 200Mi # 内存资源:单位 Ei、Pi、Ti、Gi、Mi、Ki
      # 容器可分配的最高资源配额
      limits:
        cpu: 200m
        memory: 500Mi
    # 注入到容器的环境变量
    env: 
    - name: env1
      value: "k8s-env1"
    - name: env2
      value: "k8s-env2"
  # 容器2: redis
  - name: myredis
    image: redis
    imagePullPolicy: IfNotPresent
    port:
    - containerPort: 6379
    resources:
      requests:
        cpu: 100m
        memory: 200Mi
      limits:
        cpu: 200m
        memory: 500Mi

测试

# 将新的配置应用到资源上
kubectl apply -f myhello-pod.yaml

# 获取资源信息
kubectl get pod/myhello-pod 
kubectl get -f myhello-pod.yaml

# 显示资源详细信息
kubectl describe pod/myhello-pod
kubectl describe -f myhello-pod.yaml

2、Pod 使用

完整测试代码见 2.4 部分。

2.1、init 容器

作用:业务容器启动前,通常用于数据卷初始化

init 容器与普通容器的区别

  • init 容器总是运行到完成。init 容器不是通过守护进程提供服务,而是通过启动容器来执行处理任务。任务完成,则容器完成。
  • 每个 init 容器都必须在下一个启动之前成功完成。多个 init 容器按定义顺序逐个执行一次, 每个 init 容器必须运行成功,这样下一个 init 容器才能够运行。只有当所有 init 容器完成时,k8s 才会启动 pod 应用容器。

例:在上述例子基础上,定义 init 容器:init-myservice,init-mydb

spec:
---
  # 定义 init 容器
  initContainers:
  - name: init-myservice
    image: busybox
    # 查找命名空间下 myservice 服务,如果存在则执行成功,如果不存在则一直查找
    command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
  - name: init-mydb
    image: busybox
    # 查找命名空间下 mydb 服务,如果存在则执行成功,如果不存在则一直查找
    command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]
---
  containers:

测试过程

创建 pod

kubectl delete -f myhello-pod.yaml
kubectl apply -f myhello-pod.yaml

查看 pod 状态和容器日志

# 获取 pod
# 显示 pod 一直处于 init 状态
kubectl get pod

# 查看 pod 详细信息
# 显示 pod 状态为 Pending,容器状态:init-myservice: running,其他容器:Waiting
kubectl describe -f myhello-pod.yaml

# 查看容器日志
# 显示:waiting for myservice
kubectl logs -f myhello-pod -c init-myservice

这是因为 myservice 服务和 mydb 服务没有定义,init 容器空转。

创建 myservice 服务

apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  ports:
  - protocol: TCP
    port: 80

查看 pod 状态和容器日志

# 启动服务
kubectl apply -f myservice.yaml

# 查看 pod 状态,容器日志
# STATUS:Init:1/2
kubectl get -f myhello-pod.yaml
# init-myservice 容器:State: Terminated,Reason: Completed,Exit Code: 0
kubectl describe -f myhello-pod.yaml

# 查看 init-mydb 容器
kubectl logs -f myhello-pod -c init-mydb

创建 mydb 服务

apiVersion: v1
kind: Service
metadata:
  name: mydb
spec:
  ports:
  - protocol: TCP
    port: 80

查看 pod 状态和容器日志

kubectl apply -f mydb.yaml
kubectl get -f myhello-pod.yaml
kubectl describe -f myhello-pod.yaml

2.2、容器生命周期处理函数

k8s 支持 postStart 和 preStop 事件。

  • postStart 事件:容器启动后,k8s 发送该事件
  • preStop 事件:容器停止前,k8s 发送该事件

例:

containers: 
---
    # 容器生命周期处理函数
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c","echo post start command exec >> /tmp/data"]
      preStop:
        exec:
          command: ["/bin/sh", "-c","echo pre stop command exec >> /tmp/data"]
---

创建 pod

kubectl delete pod myhello-pod 
kubectl create -f myhello-pod.yaml

测试

# 使用 shell 连接到 pod 中的容器
kubectl exec -it pod/myhello-pod -c myhello --sh
# 查看 postStart 处理函数写入的文本
cat /tmp/data

2.3、容器的探测

probe 是由 kubelet 对容器执行的定期诊断,既可以在容器内执行代码,也可以发出一个网络请求。

2.3.1、探测机制
  • exec:在容器内执行指定命令。若退出码为0, 则诊断成功。
  • httpGet:对容器的 IP 地址上指定端口和路径执行 HTTP GET 请求。如果响应的状态码大于等于 200 且小于 400,则诊断成功。
  • tcpSocket:对容器的 IP 地址上的指定端口执行 TCP 检查。如果端口打开,则诊断被认为是成功的
  • grpc:使用 grpc 执行一个远程过程调用。目标应该实现 grpc 健康检查。 如果响应的状态是 “SERVING”,则诊断成功。 gRPC 探针是一个 alpha 特性。
2.3.2、探测结果
  • Success:容器通过了诊断。
  • Failure:容器未通过诊断。
  • Unknown:诊断失败,不会采取任何行动。
2.3.3、探测类型

若容器不提供探针,则默认状态为 Success。

startupProbe

启动探测:检测容器是否已经启动。探测成功后,则停止探测;探测失败,kubelet 将杀死容器,容器根据重启策略决定未来。

readinessProbe

就绪探测:检查容器是否准备好为请求提供服务。探测成功,继续探测;探测失败,端点控制器 将从与 Pod 匹配的所有服务的端点列表中删除该 Pod 的 IP 地址,即流量不再分配对应的节点。对 pod 本身不做任何处理。

使用场景:就绪探测检测后端服务是否可用。例如:数据库服务。就绪探测标识容器具备接收请求的能力,可以处理流量。

livenessProbe

存活探测:检测容器是否正在运行。探测成功,继续探测;探测失败,kubelet 将杀死容器,容器根据重启策略决定未来。

2.3.4、案例
containers:
---
  # 1、启动探测
  startupProbe:
    exec:
      command: ["/bin/sh", "-c","statuscode=`curl -o /dev/null -s -w %{http_code} http://localhost/healthz`; [ $$statuscode -le 400 ] || exit 1"]
    # 指定初始化时间,即探针在容器启动之后的延迟时长
    initialDelaySeconds: 5
    # 探测周期,即每隔多长时间探测一次
    periodSeconds: 5
    # 最小连续失败次数,即连续失败多少次表示探测失败
    failureThreshold: 3
    # 最小连续成功次数,即连续探测成功多少次表示探测成功,liveness 和 startup 必须为1
    successThreshold: 1
    # 探测超时时间
    timeoutSeconds: 1
  # 2、就绪探测
  readinessProbe:
    httpGet:
      path: /health
      port: 80
    initialDelaySeconds: 5
    periodSeconds: 5
    failureThreshold: 3
    successThreshold: 1
    timeoutSeconds: 1
  # 3、存活检测
  livenessProbe:
    httpGet:
      path: /health
      port: 80
    initialDelaySeconds: 5
    periodSeconds: 5
    failureThreshold: 3
    successThreshold: 1
    timeoutSeconds: 1
---       
- name: myredis
  # 存活检测
  livenessProbe:
    tcpSocket:
      port: 6379
    initialDelaySeconds: 5
    periodSeconds: 5
    failureThreshold: 3
    successThreshold: 1

创建 pod

kubectl delete pod myhello-pod 
kubectl create -f myhello-pod.yaml

查看启动探测

# 查看启动检测
kubectl logs -f pod/myhello-pod -c myhello

查看就绪探测和存活探测

kubectl describe pod/myhello-pod

# 容器 myhello
Liveness: http-get http://:80/health delay=5s timeout=1s period=5s #success=1 #failure=3
Readiness:http-get http://:80/health delay=5s timeout=1s period=5s #success=1 #failure=3

# 容器 redis
Liveness: tcp-socket :6379 delay=5s timeout=1s period=5s #success=1 #failure=3


2.4、测试代码

# api 版本
apiVersion: v1
# 类型
kind: Pod
# 元数据
metadata: 
  # 名字
  name: myhello-pod
  # 命名空间
  namespace: default 
  # 标签,svc,deployment 通过 labels 管理 pod 
  labels:
    name: myhello-pod
    env: dev
# 规则
spec:
  # 容器重启策略
  restartPolicy: Always
  # 定义 init 容器
  initContainers:
  - name: init-myservice
    image: busybox
    # 查找命名空间下myservice服务,如果存在则执行成功,如果不存在则一直查找
    command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
  - name: init-mydb
    image: busybox
    # 查找命名空间下mydb服务,如果存在则执行成功,如果不存在则一直查找
    command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]
  
  # 定义容器
  containers:
  # 容器1:myhello
  - name: myhello
    image: xlhmzch/hello:1.0.0
    # 镜像拉取策略
    imagePullPolicy: IfNotPresent
    # 容器端口
    ports:
    - containerPort: 80
    # 容器启动命令,二进制文件名 app
    command: ["./app"]
    # 容器启动命令参数
    args: ["--param1=k8s-p1", "--param2=k8s-p2"]
    # 容器使用资源设置
    resources:
      # 容器可分配的最低资源配额
      requests:
        cpu: 100m
        memory: 200Mi
      # 容器可分配的最高资源配额
      limits:
        cpu: 200m
        memory: 500Mi
    # 注入到容器的环境变量
    env: 
    - name: env1
      value: "k8s-env1"
    - name: env2
      value: "k8s-env2"
    # 容器生命周期处理函数
    lifecycle:
      postStart: 
        exec: 
          command: ["/bin/sh", "-c","echo post start command exec >> /tmp/data"]
      preStop:
        exec:
          command: ["/bin/sh", "-c","echo pre stop command exec >> /tmp/data"]
    # 启动探测
    startupProbe:
      exec:
        command: ["/bin/sh", "-c","statuscode=`curl -o /dev/null -s -w %{http_code} http://localhost/healthz`; [ $$statuscode -le 400 ] || exit 1"]
      # 指定初始化时间,即探针在容器启动之后的延迟时长
      initialDelaySeconds: 5
      # 探测周期,即每隔多长时间探测一次
      periodSeconds: 5
      # 最小连续失败次数,即连续失败多少次表示探测失败
      failureThreshold: 3
      # 最小连续成功次数,即连续探测成功多少次表示探测成功,liveness 和 startup 必须为1
      successThreshold: 1
      # 探测超时时间
      timeoutSeconds: 1
    # 就绪探测
    readinessProbe:
      httpGet:
        path: /health
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 5
      failureThreshold: 3
      successThreshold: 1
      timeoutSeconds: 1
    # 存活检测
    livenessProbe:
      httpGet:
        path: /health
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 5
      failureThreshold: 3
      successThreshold: 1
      timeoutSeconds: 1
  # 容器2: redis
  - name: myredis
    image: redis
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 6379
    resources:
      requests:
        cpu: 100m
        memory: 200Mi
      limits:
        cpu: 200m
        memory: 500Mi
    # 存活检测
    livenessProbe:
      tcpSocket:
        port: 6379
      initialDelaySeconds: 5
      periodSeconds: 5
      failureThreshold: 3
      successThreshold: 1

3、Pod 的部署

在 Kubernetes 中,Pod 工作负载,是集群上处于运行状态的一组容器的集合。为了减轻用户的使用负担,通常不需要用户直接管理每个 Pod。 而是使用负载资源来替用户管理一组 Pod。 这些负载资源通过配置控制器来管理。

负载资源

  • Deployment:管理无状态应用
  • StatefulSet:管理有状态应用
  • DaemonSet:每个节点只运行 1 个 pod 副本
  • JobCronJob:定义任务。

3.1、Deployment

管理无状态应用部署。内部自动创建 RS (ReplicaSet) 用于 pod 副本控制。

相较于 RC | RS 具有以下优势:

  • deployment 资源对象会自动创建 RS 资源对象来完成部署,对 deployment 的修改并发布会产生新的 RS 资源对象,为新的发布版本服务。
  • 支持查看部署进度,以确定部署操作是否完成
  • 更新 deployment,会触发部署从而更新 pod
  • 支持 pause | resume 操作,暂停后修改不会触发发布,恢复后发布新的 deployment
  • 支持回滚操作
  • 支持重新启动操作,触发 pod 更新。
  • 自动清理不需要的 RS

例:定义 deployment 配置文件

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
  namespace: default
  labels:
    name: myapp-deploy
spec:
  # pod 副本数
  replicas: 3
  # 标签选择器:查找管理的 pod 
  selector:
    # 匹配 template.metadata.labels
    matchLabels:
      app: myapp
  # pod 模板:定义 pod
  template:
    metadata:
      labels:
        app: myapp
    spec:
      restartPolicy: Always
      containers:
      - name: myhello
        image: xlhmzch/hello:1.0.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        command: ["./app"]
        args: ["--param1=k8s-p1", "--param2=k8s-p2"]
        resources:
          requests:
            cpu: 100m
            memory: 200Mi
          limits:
            cpu: 200m
            memory: 500Mi
        env: 
        - name: env1
          value: "k8s-env1"
        - name: env2
          value: "k8s-env2"
        startupProbe:
          exec:
            command: ["/bin/sh", "-c","statuscode=`curl -o /dev/null -s -w %{http_code} http://localhost/healthz`; [ $$statuscode -le 400 ] || exit 1"]
          initialDelaySeconds: 5
          periodSeconds: 5
          failureThreshold: 3
          successThreshold: 1
          timeoutSeconds: 1
        readinessProbe:
          httpGet:
            path: /health
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 5
          failureThreshold: 3
          successThreshold: 1
          timeoutSeconds: 1
        livenessProbe:
          httpGet:
            path: /health
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 5
          failureThreshold: 3
          successThreshold: 1
          timeoutSeconds: 1

测试方法:

# 应用部署
kubectl apply -f myapp-deployment.yaml 
 
# 获取部署信息
kubectl get -f myapp-deployment.yaml
# 获取副本控制器
kubectl get rs
 
# 修改 deployment
# 查看线上与线下的区别
kubectl diff -f myapp-deployment.yaml 
# 应用新的配置文件,实现 deployment 升级
kubectl apply -f myapp-deployment.yaml 

# 获取部署信息
kubectl get -f myapp-deployment.yaml
# 获取副本控制器
kubectl get rs
 
# 管理发布版本
kubectl rollout
# 查看版本发布的历史
kubectl rollout history deployment myapp-deploy
# 查看指定版本
kubectl rollout history deployment myapp-deploy --revision 1
# 回滚指定版本,回滚后也算新版本(revision + 1)
kubectl rollout undo deployment myapp-deploy --to-revision 1
# 查看发布状态
kubectl rollout status deployment myapp-deploy

# 暂停部署
kubectl rollout pause deployment myapp-deploy 
# 期间任何修改,不会上线
kubectl apply -f myapp-deployment.yaml
# 恢复部署
kubectl rollout resume deployment myapp-deploy

# 重启部署
kubectl rollout restart deployment myapp-deploy 

# 自动伸缩容
kubectl autoscale deployment myapp-deploy --min 2 --max 3 --cpu-percent 20
kubectl get horizontalpodautoscalers.autoscaling

3.2、DaemonSets

每个节点只运行一个 pod 副本。

应用:每个节点上运行集群守护进程、日志收集守护进程和监控守护进程。

例:编写 DaemonSet 配置文件

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: myapp-ds
  namespace: default
  labels:
    app: myapp-ds
spec:
  selector:
    matchLabels:
      app: myapp-ds
  template:
    metadata:
      labels:
        app: myapp-ds
    spec:
      tolerations: # 设置容忍度,即能否部署到有污点的节点上 master
      - key: node-role.kubernetes.io/control-plane
        operator: Exists
        effect: NoSchedule
      containers:
      - name: myhello 
        image: xlhmzch/hello:1.0.0 
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        env: 
        - name: env1
          value: "k8s-env1"
        - name: env2
          value: "k8s-env2"

测试方法同上。

3.3、静态 pod

静态 pod 直接由指定节点上的 kubelet 守护进程管理。 大多数 Pod 都是通过控制面(例 Deployment)来管理的,对于静态 Pod 而言,kubelet 直接监控每个 Pod。

例:编写静态 pod 配置文件

apiVersion: v1
kind: Pod
metadata:
  name: myhello-static-pod
  namespace: default
  labels:
    name: myhello-static-pod
    env: dev
spec:
  containers:
  - name: myhello
    image: xlhmzch/hello:1.0.0
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80
    command: ["./app"]
    args: ["--param1=k8s-p1", "--param2=k8s-p2"]
    resources:
      requests:
        cpu: 100m     
        memory: 200Mi 
      limits:
        cpu: 200m
        memory: 500Mi
    env: 
    - name: env1
      value: "k8s-env1"
    - name: env2
      value: "k8s-env2"

4、参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值