CKA认证 | Day4 K8s管理应用生命周期(下)

第四章 K8s管理应用程序生命周期(下)

1、Pod对象

1.1 Pod 的基本概念

Pod 是 Kubernetes 中最基本和最重要的概念之一,是一个逻辑抽象概念,Kubernetes创建和管理的最小单元, 一个Pod由一个容器或多个容器组成。它简化了容器的部署、管理和扩展。通过 Pod可以轻松地将应用程序的不同组件组织在一起,确保它们共享资源和网络环境。

Pod 的主要特点:

① 容器共享网络和存储

  • 共享网络命名空间:Pod 中的所有容器共享同一个网络命名空间,这意味着它们可以使用 localhost 相互通信。
  • 共享存储卷:Pod 中的容器可以共享存储卷,便于数据交换和持久化。

② 生命周期管理

  • Pod 生命周期:Pod 的生命周期由 Kubernetes 管理,包括创建、运行、更新和终止。
  • 健康检查:Kubernetes 可以通过健康检查(Liveness Probes 和 Readiness Probes)自动管理Pod 的健康状态。

③ 自动调度

  • 节点调度:Kubernetes 自动将 Pod 调度到集群中的适当节点上,基于资源需求、策略和约束条件。
  • 高可用性和容错:如果节点发生故障,Kubernetes 会自动将 Pod 重新调度到其他节点上,确保服务的高可用性。

1.2 Pod 存在的意义

Pod主要用法:

  1. 主容器(Main Container):主要应用程序容器,通常是一个长时间运行的服务。又或者是运行单个容器,最常见的用法可以将Pod看做是单 个容器的抽象封装;
  2. 辅助容器(Sidecar Container):辅助容器,用于支持主容器的功能,如日志收集、监控代理等。又或者是运行多个容器: 通过在Pod中定义专门容器来执行主业务容器需要的辅助工作,这样好处是将辅助功能同主业务 容器解耦,实现独立发布和能力重用。

如某些场景下,有部分代码考虑是否在源代码的基础上增加,随着用户量的上升可能导致源代码的臃肿。前期可以将非核心的功能进行解耦出来,对以后业务的扩展会有很多帮助,例如:

• 日志收集

• 应用监控

1.3 Pod 资源共享实现机制

① 共享网络: 将业务容器网络加入到"负责网络的容器 infa container"实现网络共享

**解释:**该网络容器会在创建Pod之前先创建,创建完成后其它容器会加入到这个容器实现网络共享,因为都在同一个网络协议栈(容器共享网络命名空间)

补充:Pod为k8s中的最小调度单元,所以一个Pod中如果存在多个容器,使用的IP,即POD IP,也是唯一的一个IP,可以通过这个IP访问Pod里面任何一个容器,IP是共享的。

共享网络YAML示例:

javascript 复制代码
# kubectl apply -f pod-net-test.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    app: test
  name: pod-net-test 
  namespace: default
spec:
  containers:
  - image: busybox 
    name: bs
    command: ["/bin/sh","-c","sleep 12h"]
  - image: nginx
    name: web
javascript 复制代码
# 测试
# kubectl get pods -o wide
NAME           READY   STATUS    RESTARTS   AGE   IP              NODE             NOMINATED NODE   READINESS GATES
pod-net-test   2/2     Running   0          42m   10.244.114.27   k8s-node2-1-73   <none>           <none>

# 进入容器
# kubectl exec -it pod-net-test -- bash   //默认会进入其中一个
Defaulted container "web" out of: web, bs

# 指定容器进入
# kubectl exec -it pod-net-test -c web -- bash
root@pod-net-test:/# curl -i 127.0.0.1    //访问容器本地IP,可获得Nginx信息


# kubectl exec -it pod-net-test -c bs -- sh   //busybox不支持bash终端
/ # wget 127.0.0.1    //可获得Nginx的index.html页面
/ # netstat -nlptu | grep 80
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -
tcp        0      0 :::80                   :::*                    LISTEN      -

**结论:**在 bs 容器中可看到监听 80端口,但是没有相关服务进程,通过127.0.0.1访问,即可得到nginx容器的index.html 页面


**② 共享存储:**容器通过数据卷共享数据

共享存储YAML示例:

javascript 复制代码
# kubectl apply -f pod-volume-test.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    app: test
  name: pod-volume-test 
  namespace: default
spec:
  containers:
  - image: busybox 
    name: test
    command: ["/bin/sh","-c","sleep 12h"]
    volumeMounts:         # 数据卷挂载
    - name: log           # 指定挂载的数据卷名称
      mountPath: /data    # 数据卷挂载到容器中的路径
  - image: nginx
    name: web
    volumeMounts:
    - name: log
      mountPath: /usr/share/nginx/html
  volumes:          # 定义数据卷
  - name: log       # 数据卷名称
    emptyDir: {}    # 数据卷类型
javascript 复制代码
# 测试
# kubectl get pods
NAME              READY   STATUS    RESTARTS   AGE

pod-volume-test   2/2     Running   0          17m
# 进入rs容器创建文件
[root@k8s-master-1-71 ~]# kubectl exec -it pod-volume-test -c bs -- sh
/ # cd /data/;touch 1.txt
# 进入web容器查看
# kubectl exec -it pod-volume-test -c web -- bash

root@pod-volume-test:/# ls /usr/share/nginx/html/

1.txt

1.4 Pod 的生命周期

① Pod 创建

  • 用户通过 YAML 文件或命令行工具(如 kubectl)创建 Pod。
  • Kubernetes 调度器将 Pod 分配到合适的节点上。

② 运行

  • 容器启动:节点上的容器运行时(如 Docker)启动 Pod 中的容器。
  • 健康检查:Kubernetes 定期检查容器的健康状态,确保它们正常运行。

③ 更新

滚动更新:通过更新 Pod 的定义,Kubernetes 可以滚动更新容器镜像或配置。

示例:kubectl set image pod/multi-container-pod web=nginx:1.19.10

④ Pod 终止:

  • 用户可以通过命令行工具删除 Pod,或者 Kubernetes 根据策略自动删除 Pod。
  • 删除 Pod 时,Kubernetes 会清理相关的资源,如容器和存储卷

1.5 管理命令

1)创建Pod
  • 命令:kubectl run --image=nginx
  • 导出YAML:kubectl run --image=nginx --dry-run=clinet -o yaml > xxx.yaml
javascript 复制代码
# kubectl apply -f pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: container1
    image: nginx
  - name: container2
    image: centos

注意: kubectl create deployment 是通过控制器去创建Pod,受控制器管理,可控制副本数,而kubectl run只能创建一个Pod,不具备控制器有的升级、回滚、扩容、多副本的特性

2)查看Pod
  • 命令:kubectl get pods
  • 命令:kubectl get pods -o wide
  • 命令:kubectl describe pod
3)查看日志
  • 命令:kubectl logs [-c CONTAINER]
  • 命令:kubectl logs [-c CONTAINER] -f //-f 实时查看
javascript 复制代码
# kubectl logs pod-volume-test
# kubectl logs pod-volume-test -c web
# kubectl logs pod-volume-test -c web -f
4)进入容器终端
  • 命令:kubectl exec -it [-c CONTAINER] -- bash
5)通过expose暴露Pod
  • 命令:kubectl expose pod --port=service端口 --target-port=应用服务端口 --type=NodePort
javascript 复制代码
# kubectl expose pod pod-net-test --port=80 --target-port=80 --type=NodePort
# kubectl get svc
NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes      ClusterIP   10.96.0.1        <none>        443/TCP          16d
pod-net-test    NodePort    10.108.168.104   <none>        80:31513/TCP     19s
6)删除Pod
  • 命令:kubectl delete pod
bash 复制代码
# kubectl delete pods pod-volume-test
pod "pod-volume-test" deleted

2、应用自修复(重启策略+健康检查)

背景:在kubectl get pods时,提示STATUS是Running状态,只能告知创建者Pod创建成功,但不代表Pod容器服务是正常的,为了进一步解决,提供了重启策略+健康检查

1)重启策略(restartPolicy):

  • Always: 当容器终止退出后,总是重启容器,默认策略(场景:常驻进程,即始终保持运行,例如nginx、mysql,服务挂掉即重启容器)
  • OnFailure: 当容器异常退出(退出状态码非0)时,才重启容器(场景:周期性进程,即隔一段时间运行一次,例如数据库备份)
  • Never: 当容器终止退出,从不重启容器(场景:临时性进程,即偶尔执行一次,没有规律即不能用定时任务去执行,一般为人为或别的程序驱动,例如数据离线处理,如果再重启一次对上一次任务的数据产生冲突等)

在Pod的YAML文件中可以看到字段:restartPolicy:Always

2)健康检查有以下3种类型(Probe探针):

  1. livenessProbe(存活检查): 如果检查失败,将杀死容器,根据Pod 的restartPolicy来操作。(重建的容器还是原来的容器,非副本集拉起的容器)
  2. readinessProbe(就绪检查): 如果检查失败,Kubernetes会把 Pod从service endpoints负载均衡中剔除。(只是从LB剔除不是删除节点)
  3. startupProbe(启动检查): 启动检查成功才由存活检查接手,用于保护 慢启动容器,防止启动慢的容器检查没通过不断重启

支持以下三种检查方法:

  • ① httpGet:发送HTTP模拟请求,返回200-400范围状态码为成功。(准确度比较高)
  • ② exec:执行Shell命令返回状态码是0为成功。
  • ③ tcpSocket:发起TCP Socket建立成功。

官网: Configure Liveness, Readiness and Startup Probes | Kubernetes


示例1:模拟httpGet请求检查方法

javascript 复制代码
# kubectl apply -f probe-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: probe-demo
spec:
  containers:
  - name: web
    image: nginx
    livenessProbe:             # 存活检查,重启容器
      httpGet:
        path: /
        port: 80
      initialDelaySeconds: 5   # 启动容器后多少秒健康检查
      periodSeconds: 10        # 以后每间隔多少秒检查一次
    readinessProbe:            # 就绪检查,从Service中剔除容器
      httpGet:
        path: /
        port: 80
      initialDelaySeconds: 5   # 启动容器后多少秒健康检查
      periodSeconds: 10        # 以后每间隔多少秒检查一次

注:livenessProbe与readinessProbe的配置参数一样

javascript 复制代码
# 通过创建Pod方式测试
[root@k8s-master-1-71 ~]# kubectl apply -f probe-demo.yaml

[root@k8s-master-1-71 ~]# kubectl get pods -o wide
NAME           READY   STATUS    RESTARTS   AGE     IP              NODE             NOMINATED NODE   READINESS GATES
probe-demo     1/1     Running   0          16m     10.244.114.28   k8s-node2-1-73   <none>           <none>

[root@k8s-master-1-71 ~]# kubectl expose pods probe-demo --port=80 --target-port=80 --type=NodePort

[root@k8s-master-1-71 ~]# kubectl get service
NAME           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
probe-demo     NodePort    10.99.233.38     <none>        80:30168/TCP   83s


# 打开两个终端进行观察,通过删除Pod的默认首页导致服务挂掉,模拟测试 readinessProbe就绪检查
# 终端1:
[root@k8s-master-1-71 ~]# kubectl get ep -w      //-w 实时查看service后端关联的Pod IP
# 终端2:
[root@k8s-master-1-71 ~]# kubectl exec -it probe-demo -- bash
root@probe-demo:/# rm -rf /usr/share/nginx/html/index.html
root@probe-demo:/# command terminated with exit code 137    //删除后,readiness就绪检查检测到服务异常,讲当前容器自动退出并剔除Service,根据livenessProbe会按照restartPolicy策略重启容器

终端1:可以看到当时probe-demo的Pod,又重新拉起了一个Pod,如图所示:

javascript 复制代码
[root@k8s-master-1-71 ~]# kubectl get pods
NAME           READY   STATUS    RESTARTS      AGE

probe-demo     1/1     Running   1 (33s ago)   22m    //查看Pod信息时,也可以明显发现有一次RESTARTS的重启记录

# 查看日志,可发现同一时间会有2条健康检查日志,因为健康检查功能是独立的
[root@k8s-master-1-71 ~]# kubectl logs probe-demo
192.168.1.73 - - [04/Mar/2023:23:29:11 +0000] "GET / HTTP/1.1" 200 615 "-" "kube-probe/1.26" "-"
192.168.1.73 - - [04/Mar/2023:23:29:11 +0000] "GET / HTTP/1.1" 200 615 "-" "kube-probe/1.26" "-"
192.168.1.73 - - [04/Mar/2023:23:29:14 +0000] "GET / HTTP/1.1" 200 615 "-" "kube-probe/1.26" "-"
192.168.1.73 - - [04/Mar/2023:23:29:14 +0000] "GET / HTTP/1.1" 200 615 "-" "kube-probe/1.26" "-"
...

示例2:执行Shell命令的检查方法

bash 复制代码
livenessProbe:
  exec:
    command:
    - cat
    - /tmp/healthy

示例3:端口探测的检查方法

bash 复制代码
livenessProbe:
  tcpSocket:
    port: 80

3、环境变量

创建 Pod 时,可以为其下的容器设置环境变量。

应用场景:

  • 容器内应用程序获取Pod信息(通过环境变量将 Pod 信息呈现给容器)
  • 容器内应用程序通过用户定义的变量改变默认行为

变量值几种定义方式:

  1. 自定义变量值
  2. 变量值从Pod属性获取
  3. 变量值从Secret、ConfigMap获取

示例:通过YAML文件定义变量,将变量注入到Pod容器当中:自定义变量、POD属性获取

网址参考:通过环境变量将 Pod 信息呈现给容器 | Kubernetes

javascript 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: pod-envars
spec:
  containers:
    - name: test
      image: busybox
      command: [ "sh", "-c", "sleep 36000"]
      env:
         # 变量值从Pod属性获取
      - name: MY_NODE_NAME
        valueFrom:
          fieldRef:
            fieldPath: spec.nodeName
      - name: MY_POD_NAME
        valueFrom:
          fieldRef:
            fieldPath: metadata.name
      - name: MY_POD_NAMESPACE
        valueFrom:
          fieldRef:
            fieldPath: metadata.namespace
      - name: MY_POD_IP
        valueFrom:
          fieldRef:
            fieldPath: status.podIP
      - name: ABC        # 自定义变量值
        value: "123456"

注意:自定义变量时,如果value的值是字符串,需要使用引号

javascript 复制代码
# 测试:进入容器
[root@k8s-master-1-71 ~]# kubectl exec -it pod-envars -- sh
/ # env    //查看我当前有的环境变量
/ # env | grep ABC
ABC=123456
/ # echo $MY_NODE_NAME
k8s-node2-1-73
/ # echo $MY_POD_NAME
pod-envars
/ # echo $MY_POD_NAMESPACE
default
/ # echo $MY_POD_IP
10.244.114.30

4、Init container

**Init Container:**顾名思义,用于初始化工作,执行完就结束,可以理解为一次性任务。

  • 支持大部分应用容器配置,但不支持健康检查
  • 优先于应用容器执行

应用场景:

  • 环境检查:例如确保应用容器依赖的服务启动后再启动应用容器
  • 初始化配置:例如给应用容器准备配置文件

示例:部署一个web网站,网站程序没有打到镜像中,而是希望从代码 仓库中动态拉取放到应用容器中。

javascript 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: init-demo
spec:
  initContainers:       # 初始化容器(将网页进行下载到共享存储中)
  - name: download
    image: busybox
    command:
    - wget
    - "-O"
    - "/opt/index.html"
    - http://www.aliangedu.cn
    volumeMounts:
    - name: wwwroot
      mountPath: /opt
  containers:           # 主容器
  - name: nginx
    image: nginx
    volumeMounts:
    - name: wwwroot
      mountPath: /usr/share/nginx/html
  volumes:
  - name: wwwroot
    emptyDir: {}

测试

javascript 复制代码
[root@k8s-master-1-71 ~]# kubectl get pods
NAME        READY   STATUS    RESTARTS   AGE
init-demo   1/1     Running   0          38s
# 解释:初始化容器完成任务就消失
[root@k8s-master-1-71 ~]# kubectl label pods init-demo app=web

[root@k8s-master-1-71 ~]# kubectl expose pods init-demo --port=80 --target-port=80 --type=NodePort
[root@k8s-master-1-71 ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
init-demo    NodePort    10.98.174.76   <none>        80:31590/TCP   25s

[root@k8s-master-1-71 ~]# curl 192.168.1.71:31590

    <title>阿良教育「官网」-专业DevOps、云计算运维、Kubernetes容器运维、云原生、Golang运维开发培训机构!</title>
...

回顾:目前接触的Pod中会有以下几种类型的容器:

  1. Infrastructure Container:基础容器 (维护整个Pod网络空间,共享网络命名空间)
  2. InitContainers:初始化容器 (先于业务容器开始执行)
  3. Containers:业务容器 (并行启动)

5、静态Pod

**背景:**Kubeadm搭建集群就是用Pod启动组件,而在不搭建完整的k8s集群之前就可以创建Pod,即静态Pod。

静态Pod特点:

  • 静态Pod由特定节点上的kubelet管理维护
  • 不能使用控制器
  • Pod名称标识当前节点名称(即在哪个节点创建就有当前节点的名称标识)

在kubelet配置文件启用静态Pod的参数:

javascript 复制代码
vi /var/lib/kubelet/config.yaml
...
staticPodPath: /etc/kubernetes/manifests
...

注:将部署的Pod yaml放到/etc/kubernetes/manifests目录会由kubelet自动创建。

测试:

javascript 复制代码
[root@k8s-node1-1-72 ~]# cd /etc/kubernetes/manifests/

[root@k8s-node1-1-72 manifests]# kubectl run web-test --image=nginx -o yaml --dry-run=client > web-test.yaml

[root@k8s-node1-1-72 manifests]# ls
web-test.yaml
[root@k8s-node1-1-72 manifests]# kubectl get pods
NAME                      READY   STATUS    RESTARTS   AGE

web-test-k8s-node1-1-72   1/1     Running   0          108s

# 删除静态Pod
[root@k8s-node1-1-72 manifests]# rm -rf web-test.yaml
[root@k8s-node1-1-72 manifests]# kubectl get pods
NAME        READY   STATUS    RESTARTS   AGE
init-demo   1/1     Running   0          24m

课后作业

1、创建一个pod,其中运行着nginx、redis、memcached、consul 4个容器

2、在节点上配置kubelet托管启动一个pod

  • 节点:k8s-node1
  • pod名称:web
  • 镜像:nginx

3、检查容器中文件是否创建,如果没有被检测到pod重启

  • 文件路径:/tmp/test.sock

小结:

本篇为**【Kubernetes CKA认证 Day4】**的学习笔记,希望这篇笔记可以让您初步了解到 Pod是什么、Pod常用管理命令、重启策略及健康检查、创建 Pod 时可以为其下的容器设置环境变量等;课后还有扩展实践,不妨跟着我的笔记步伐亲自实践一下吧!


Tip:毕竟两个人的智慧大于一个人的智慧,如果你不理解本章节的内容或需要相关笔记、视频,可私信小安,请不要害羞和回避,可以向他人请教,花点时间直到你真正的理解。

相关推荐
Re.不晚12 分钟前
Java图书管理系统(简易&保姆级)
java·linux·服务器·开发语言·学习·算法·intellij-idea
lly_csdn12321 分钟前
【Docker】常用命令汇总
linux·运维·docker·容器
敲上瘾25 分钟前
虚拟地址空间与物理内存(Linux系统)
linux·运维·服务器·开发语言·c++·算法·aigc
云边的快乐猫43 分钟前
在Linux中对mysql用户进行管理
linux·数据库·mysql·用户管理·用户权限
努力的Andy1 小时前
修改Docker 默认存储目录( Docker Root Dir: /var/lib/docker)
linux·docker·容器
hai405871 小时前
Docker 启动和停止的精准掌舵:操控指南
docker·容器·eureka
向阳12181 小时前
Seata使用ZooKeeper作为注册中心
分布式·zookeeper·云原生
MANX981 小时前
Linux Deploy安装Debian桌面
linux
成都 - 阿木木1 小时前
云原生自动化测试之命令行工具自动化测试设计思路分享
自动化测试·软件测试·功能测试·测试工具·云原生·云计算·命令行自动化测试
李小白202002021 小时前
Linux 生成/proc/config.gz
linux·服务器·前端