Skip to content

3 Kubernetes-资源清单

一、K8S 中的资源

Kubernetes 中所有内容,都抽象为资源,资源实例化后,叫做对象

实例化:将 pod 资源,部署成想要的结果(实例化过程仅需一次)

资源分类:

注意:K8S中的 namespace 与容器中的 namespace 区别

​ K8S中:逻辑上的分隔

​ docker中:真正的分隔

名称空间级别:(类似学校中,班级的分类)(namespace)
    工作负载型资源: Pod、ReplicaSet、Deployment ...
    服务发现及负载均衡型资源:  Service、Ingress...
    配置与存储型资源:Volume、CSI ...
    特殊类型的存储卷:ConfigMap、Secre ...


集群级资源:(类似学校本身)
    Namespace、Node、ClusterRole、ClusterRoleBinding


元数据型资源:(依附于其他之上,比如:自动扩容缩、pod模板、资源限制)
    HPA、PodTemplate、LimitRange

二、资源清单

资源通过 yaml 文件,定义怎么创建对象

1)K8S 创建流程

查看 K8S 初始化的日志

相关解释:

$ kubeadm config images pull        #根据配置文件,下载所有镜像到本地


# kubelet环境变量文件 /var/lib/kubelet/kubeadm-flags.env
$ cat /var/lib/kubelet/kubeadm-flags.env
KUBELET_KUBEADM_ARGS="--cgroup-driver=systemd --network-plugin=cni --pod-infra-container-image=k8s.gcr.io/pause:3.1"
#kubelet_kubeadm 启动参数:(KUBELET_KUBEADM_ARGS)
            指定cgroup驱动为systemd,对应 /etc/docker/daemon.json 中指定的cgroup驱动
            指定网络插件使用 cni 接口
            指定pod初始化容器为:pause:3.1版


# kubelet 配置文件 /var/lib/kubelet/config.yaml(资源清单的格式)
重要选项:指定静态pod路径
        staticPodPath: /etc/kubernetes/manifests

kubeadm 初始化 K8S 集群原理图:

image-20230111175003964

查看逻辑上分割的 kube-system 的名称空间中所有pod:

(当前 K8S 所有组件、插件、附件所在位置)

[root@k8s-master01 ~]# kubectl get pod -n kube-system
NAME                                   READY   STATUS    RESTARTS   AGE
calico-node-cr9jt                      2/2     Running   2          24h
calico-node-gl48k                      2/2     Running   2          24h
calico-node-kqrr6                      2/2     Running   2          24h
coredns-5c98db65d4-fb8z2               1/1     Running   1          24h
coredns-5c98db65d4-gqtpz               1/1     Running   1          24h
etcd-k8s-master01                      1/1     Running   1          24h
kube-apiserver-k8s-master01            1/1     Running   1          24h
kube-controller-manager-k8s-master01   1/1     Running   1          24h
kube-proxy-29bmx                       1/1     Running   1          24h
kube-proxy-flwtk                       1/1     Running   1          24h
kube-proxy-hrkx2                       1/1     Running   1          24h
kube-scheduler-k8s-master01            1/1     Running   1          24h
/etc/kubernetes/pki         #存放证书的目录
            有两套不同的证书:
                        因为有两个C/S架构:
                                     服务:
                                        S   apiserver
                                        C   CM、sch、kubeproxy.....
                                     存储:
                                        S   ETCD
                                        C   apiserver
/etc/kubernetes/
        admin.conf              #管理员权限配置文件,管理员拥有此文件才能管理集群
                                    所以初始化进群以后,会执行命令:
                                                    $ cp /etc/kubernetes/admin.conf ~/.kube/config
        controller-manager.conf     #其他组件权限相关的配置文件
        scheduler.conf
        kubelet.conf

        pki                         #证书相关的路径
        manifests                   #静态pod路径

详细解释:

image-20230111185138242

2)资源清单

1、资源清单格式

apiversion:     组/版本        #指定位置,实现实例化
                        拓展:(实现不同位置的实例化)
                            有一个项目:教学管理系统
                                寝室管理:
                                        apis/core/v1
                                        apis/core/v1
                                班级管理:
                                        apis/apps/v1
                                        ...
                                学生管理:
                                        ...
                                课程管理:
                                        ...

                    $ kubectl explain pod       #查看pod控制器的 组/版本 ,以及帮助信息
                    $ kubectl api-versions      #查看 K8S 中所有的 组/版本
                                                #若只显示版本,则表示: core/v1


kind:       #资源类别



metadata:  #资源元数据
     name
     namespace
     lables
     annotations   # 主要目的是方便用户阅读查找


spec:        # 期望的状态(disired state)


status:     # 当前资源实例化对象后的结果状态(由K8S本身维护,用户不能自定义)

2、资源清单的常用命令

获取 apiversion 版本信息

[root@k8s-master01 ~]# kubectl api-versions 
admissionregistration.k8s.io/v1beta1
apiextensions.k8s.io/v1beta1
apiregistration.k8s.io/v1
apiregistration.k8s.io/v1beta1
apps/v1
......(以下省略)

获取资源的 apiVersion 版本信息

[root@k8s-master01 ~]# kubectl explain pod
KIND:     Pod
VERSION:  v1
.....(以下省略)

[root@k8s-master01 ~]# kubectl explain Ingress
KIND:     Ingress
VERSION:  extensions/v1beta1

获取字段设置帮助文档

[root@k8s-master01 ~]# kubectl explain pod
KIND:     Pod
VERSION:  v1

DESCRIPTION:
     Pod is a collection of containers that can run on a host. This resource is
     created by clients and scheduled onto hosts.

FIELDS:
   apiVersion    <string>
     ........
     ........

字段配置格式

apiVersion <string>          #表示字符串类型
metadata <Object>            #表示需要嵌套多层字段
labels <map[string]string>   #表示由k:v组成的映射
finalizers <[]string>        #表示字串列表
ownerReferences <[]Object>   #表示对象列表
hostPID <boolean>            #布尔类型
priority <integer>           #整型
name <string> -required-     #如果类型后面接 -required-,表示为必填字段

3、通过定义清单文件创建 Pod

apiVersion: v1                          #定义组/版本
kind: Pod                               #定义资源类别
metadata:                               #定义资源实例化后的对象,具备的元信息
  name: pod-demo
  namespace: default
  labels:
    app: myapp
spec:                                   #期望
  containers:
  - name: myapp-1
    image: wangyanglinux/myapp:v1
  - name: busybox-1
    image: busybox:1.38.0
    command:
    - "/bin/sh"
    - "-c"
    - "sleep 3600"
kubectl get pod xx.xx.xx -o yaml  
<!--使用 -o 参数 加 yaml,可以将资源的配置以 yaml的格式输出出来,也可以使用json,输出为json格式--> 

实验:创建pod-demo对象

Ⅰ 根据yaml文件,创建pod
[root@k8s-master01 ~]# mkdir 1
[root@k8s-master01 ~]# cd 1/
[root@k8s-master01 1]# vim 1.pod.yaml
[root@k8s-master01 1]# cat 1.pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-demo
  namespace: default
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-1
    image: wangyanglinux/myapp:v1
  - name: busybox-1
    image: busybox:1.38.0
    command:
    - "/bin/sh"
    - "-c"
    - "sleep 3600"

[root@k8s-master01 1]# kubectl create -f 1.pod.yaml     #根据yaml文件创建pod
Ⅱ 发现创建的pod有问题
[root@k8s-master01 1]# kubectl get pod
NAME       READY   STATUS             RESTARTS   AGE
pod-demo   1/2     ImagePullBackOff   0          5m36s
Ⅲ 排错:查看pod资源的pod-damo资源对象的详细信息
[root@k8s-master01 1]# kubectl describe pod pod-demo

image-20230111205947296

Ⅳ 修改 yaml文件,重新创建pod

进入 hub.docker.com 查找 busybos 确定版本,并修改 yaml文件,重新创建pod

[root@k8s-master01 1]# kubectl delete pod pod-demo      #删除pod-demo对象

[root@k8s-master01 1]# kubectl delete pod pod-demo
pod "pod-demo" deleted
[root@k8s-master01 1]# vim 1.pod.yaml 
[root@k8s-master01 1]# cat 1.pod.yaml |grep image
    image: wangyanglinux/myapp:v1
    image: busybox:1.36.0
[root@k8s-master01 1]# kubectl get pod
No resources found.
[root@k8s-master01 1]# kubectl create -f 1.pod.yaml 
pod/pod-demo created
[root@k8s-master01 1]# kubectl get pod -w           #查看pod的变化信息,这时候运行成功
NAME       READY   STATUS              RESTARTS   AGE
pod-demo   0/2     ContainerCreating   0          7s
pod-demo   2/2     Running             0          44s
Ⅴ 测试pod创建的容器

验证:kubectl创建的pod中,对应的容器为docker所创建

方法一:

#在master节点中,查看pod-demo所在位置,node02
[root@k8s-master01 1]# kubectl get pod -o wide
NAME       READY   STATUS    RESTARTS   AGE   IP             NODE         NOMINATED NODE   READINESS GATES
pod-demo   2/2     Running   0          22m   172.100.2.28   k8s-node02   <none>           <none>
[root@k8s-master01 1]# curl 172.100.2.28
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>


#在node02节点中,查看myapp容器,并进入
[root@k8s-node02 ~]# docker ps |grep myapp
2a629bf05305   d4a5e0eaa84f           "nginx -g 'daemon of…"   25 minutes ago   Up 25 minutes             k8s_myapp-1_pod-demo_default_1bdfc2f8-615e-44f2-9ae9-914b3d78b09b_0
[root@k8s-node02 ~]# docker exec -it k8s_myapp-1_pod-demo_default_1bdfc2f8-615e-44f2-9ae9-914b3d78b09b_0 /bin/sh
/ # echo "yangqin" >> /usr/share/nginx/html/index.html 
/ # 


#回到master节点中,再次访问容器ip
[root@k8s-master01 1]# curl 172.100.2.28
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
yangqin

方法二:

#master节点通过kubectl,直接登录pod-demo的myapp-1容器
[root@k8s-master01 ~]# kubectl get pod -o wide                      #查看pod-demo对象运行所在的节点
NAME       READY   STATUS    RESTARTS   AGE   IP             NODE         NOMINATED NODE   READINESS GATES
pod-demo   2/2     Running   0          18m   172.100.1.33   k8s-node01   <none>           <none>
[root@k8s-master01 ~]# kubectl exec -it pod-demo -c myapp-1 -- /bin/sh      #kubectl命令进入myapp-1容器
/ # echo "yangqin........" >> /usr/share/nginx/html/index.html 
/ # cat /usr/share/nginx/html/index.html 
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
yangqin........



#进入nnode01节点验证
[root@k8s-node01 ~]# docker ps |grep myapp
ac4c253d4244   d4a5e0eaa84f           "nginx -g 'daemon of…"   16 minute257-4ce9-8ff8-cae9475b4844_0
[root@k8s-node01 ~]# docker exec -it k8s_myapp-1_pod-demo_default_8b1f43
/ # cat /usr/share/nginx/html/index.html 
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
yangqin........

3)kubectl 常用命令

# 查看资源清单选项解释说明
$ kubectl explain  pod.spec.containers


# 查看资源对象
$ kubectl get pod
    -o wide    # 查看更多的信息,包括 Pod ip、pod 运行的节点
       yaml    # 将当前的资源对象输出为 yaml 文件
       json    # 将当前的资源对象输出为 json 文件
    -w         # 监听变换,将变化信息输出至前台
    --show-labels       # 查看标签
    -l         # 通过标签过滤当前的输出 -l app=nginx
    -n default          # 指定名字空间,默认即 default
    --all-namespaces == -A      # 查看所有名字空间中的对象


# 删除资源对象
$ kubectl delete 资源类别  对象名称
$ kubectl delete pod pod-demo
$ kubectl delete -f xxx.yaml
    --all   删除当前所有的资源对象
        kubectl delete pod --all
        kubectl delete deployment --all


# 实例化资源对象
$ kubectl create -f xxx.yaml/xxx.json 
        原理:
                yaml文件   -->   kubectl (yaml文件 --> json文件)  -->  apiServer
            windows安装kubectl教程: 
                https://cloudmessage.top/archives/k8s-zai-windowszhong-shi-yong-kubectllian-jie-ji-qun


# 查看资源对象的详细信息(包括事件)    
$ kubectl describe  资源类别  对象名称
注意:
    此条命令常用于排错
    pod的事件并不是持久化存储的


# 让 pod 内部的容器执行命令
$ kubectl exec -it podName -c cName -- command
    kubectl exec -it pod-demo -c myapp-1 -- /bin/sh
注意:如果 pod 内部只封装了一个容器,那么 -c 可以省略(pod中只有 pause  c1 容器)


# 查看容器日志
$ kubectl logs podName -c cName
    kubectl  logs pod-demo -c myapp-1
    -p -c   # 查看已经停止的容器日志
    -f      # 持续输出容器日志信息
    --tail=20       # 查看容器最近20条日志
    --since=1h      # 查看容器最近一小时产生的日志

实验:创建pod-2

1、根据 2.pod.yaml 文件,创建pod-2对象

[root@k8s-master01 ~]# vim 1/2.pod.yaml 
[root@k8s-master01 ~]# cat 1/2.pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-2
  namespace: default
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-1
    image: wangyanglinux/myapp:v1
  - name: myapp-2
    image: wangyanglinux/myapp:v2

[root@k8s-master01 ~]# kubectl create -f 1/2.pod.yaml 
pod/pod-2 created
[root@k8s-master01 ~]# kubectl get pod -w
NAME    READY   STATUS    RESTARTS   AGE
pod-2   2/2     Running   0          4s
pod-2   1/2     Error     0          4s
pod-2   2/2     Running   1          5s
pod-2   1/2     Error     1          7s
pod-2   1/2     CrashLoopBackOff   1          22s
pod-2   2/2     Running            2          22s
pod-2   1/2     Error              2          25s

2、发现创建的pod出现问题

排错1:

查看资源对象详细信息

[root@k8s-master01 ~]# kubectl describe pod pod-2

并未找到问题原因,仅提示了:重启容器,重启失败

image-20230111220810411

排错2:
[root@k8s-master01 ~]# kubectl logs pod-2 -c myapp-1
[root@k8s-master01 ~]# kubectl logs pod-2 -c myapp-2

查看 pod-2 的 myapp-1 容器,没有日志

查看 pod-2 的 myapp-2 容器,产生日志,找到原因由于与 80端口已被占用,所以 myapp-2 无法启动

image-20230111221251679

排错3:

若以上排错仍未找到问题,可能出现问题的原因:

​ 1)镜像的问题

​ 2)K8S本身有问题

注意:两个资源对象放到一个yaml文件中

用 --- 将两个需要创建的资源对象分开

资源清单的选项顺序无所谓

apiVersion: v1
kind: Pod
metadata:
  name: pod-demo
  namespace: default
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-1
    image: wangyanglinux/myapp:v1
  - name: busybox-1
    image: busybox:1.36.0
    command:
    - "/bin/sh"
    - "-c"
    - "sleep 3600"
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-3
  namespace: default
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-1
    image: wangyanglinux/myapp:v1
  - name: myapp-2
    image: wangyanglinux/myapp:v2
    command:
    - "/bin/sh"
    - "-c"
    - "sed -i '2 s/80/8080/' /etc/nginx/conf.d/default.conf && echo 'yangqin' >> /usr/share/nginx/html/index.html &&  nginx && sleep 3 && tail -f /dev/null"

三、常用字段解释

详细请点击 👉 常用字段解释.md

四、pod生命周期

image-20230112182647728

pause生命周期为:整个pod存在的生命周期

1)启动过程:

1、pause初始化

2、initC初始化(个数 >= 0)

​ 可以执行下载文件、编译等,再交给 pause 挂载存储

​ 必须有成功操作,才能进行下一步,即返回码为0,否则整个 pod 会从pause开始重建

多个 initC 初始化时,采用线性初始化启动

3、启动 mainC

启动过程为流式启动容器
        注意: kubectl describe pod pod-demo   #查看pod-demo的事件信息,信息采用的式异步保存的
                    异步:两者之间避免实时交互,耗费资源(ETCD在两者之间作缓冲)

kubelet完成钩子机制
        容器初始化
        启动后钩子:获取代码
        执行启动命令:
                没办法保证执行启动命令位于启动钩子完成以后才执行(即:在执行启动命令时,有可能 “启动后钩子” 还未完成)
        关闭前钩子
        关闭信号

注意:限制性容器初始化,再执行启动后钩子,再执行启动命令,但是,启动命令,不一定在,启动后钩子执行完成以后,才开始执行



探针机制:
            就绪探测:容器启动以后,探测一次
            存活探测:容器启动以后,一直探测,可定义探测的间隔

探测机制详解:

        探测的方法:
                EXEC:
                    返回码为0   --->    成功
                    返回码非0   --->    失败
                    返回码未知   --->    未知(设置此项原因:为了确保鲁棒性,即稳定性)

                TCPSOCKET:
                    TCP连接此端口成功      --->    成功
                    TCP连接此端口失败      --->    失败
                    TCP连接此端口未知      --->    未知

                HTTPGET:
                    200=< 返回码 < 400                --->     成功
                    返回码 < 200 或者 返回码 >= 300     --->     失败
                    返回码未知                         --->     未知

        工作类型:
                就绪探测(readinessProbe):若容器不添加就绪探测,默认为就绪状态
                                          若容器添加就绪探测,则默认为未就绪状态,除非就绪探测成功
                            成功      --->    将当前容器未就绪状态改为就绪状态
                            失败      --->    等待下一次探测
                            未知      --->    静默,不改变状态,等待下一次探测

                存活探测(livenessProbe):若不添加存活探测,只要容器能运行,此pod就一直运行,哪怕内部服务不饿能给用户提供访问
                            成功      --->    静默,不改变状态,等待下一次探测
                            失败      --->    根据pod的重启策略,重建容器
                            未知      --->    静默,不改变状态,等待下一次探测

2)实验

1、验证 initC 为线性启动、mainC 为流式启动

前提相关介绍:

Ⅰ 此特性还可以实现:mysql与tomcat的先后启动: 在initC中,连接数据库,判断数据是否可用,不可用退出循环 详细实验请点击👉 mysql与tomcat的先后启动 (建议先完成下面的实验1,再完成这个实验)

Ⅱ service 资源实例化为对象时,对象名会写入 coredns ,从而实现 K8S 中的域名解析

$ kubectl create svc

service实现负载均衡原理:

匹配条件:

1、标签选择器(创建对象时的名称,标签的子集)
2、pod必须处于就绪状态

image-20230113013806571

Ⅲ K8S中的缩写:点击查看所有缩写

​ 此处用到缩写:service ~ svc

$ kubectl create svc clusterip myservice --tcp=80:80
                            #clusterip      创建的类型
                            #myservice      创建的对象名
                            #--tcp=80:80    创建一个负载均衡的集群

实验步骤

1)创建yaml文件,创建pod
[root@k8s-master01 ~]# ls
1
[root@k8s-master01 ~]# mkdir 2
[root@k8s-master01 ~]# cd 2/
[root@k8s-master01 2]# vim 1.pod.yaml 
[root@k8s-master01 2]# cat 1.pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox:1.35.0
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox:1.35.0
    command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
  - name: init-mydb
    image: busybox:1.35.0
    command: ['sh', '-c', 'until nslookup mydb;do echo waiting for mydb; sleep 2; done;']
[root@k8s-master01 2]# kubectl create -f 1.pod.yaml
2)查看pod状态,出现问题
[root@k8s-master01 2]# kubectl get pod 
NAME        READY   STATUS     RESTARTS   AGE
myapp-pod   0/1     Init:0/2   0          68s
3)检查问题并排错

发现集群的myapp-pod信息没有报错信息,myapp-pod中的init-service容器创建成功,也启动成功

image-20230112195955831

查看 init-myservice容器日志,发现容器中无法识别myservice域名解析

image-20230112200246498

所以,根据yaml文件中内容,在myapp-pod中有一个init容器 init-service ,在这个容器启动时写了一个死循环:若不能解析myservice域名,则会循环

导致 init-service容器一直无法成功完成操作,以至于下一个 init容器 init-mydb 无法创建启动,mainC容器也无法创建启动

下面解决:myservice域名正常解析

4)将service资源实例化为 myservice 对象
kubectl create svc clusterip myservice --tcp=80:80
5)查看pod状态,任然出现问题
[root@k8s-master01 2]# kubectl get pod -w
NAME        READY   STATUS     RESTARTS   AGE
myapp-pod   0/1     Init:1/2   0          17m

同样的,init-mydb容器无法识别 mydb 的域名解析,进入死循环,需要将service资源实例化为 mydb 对象,从而实现域名解析

image-20230112201853979

6)将service资源实例化为mydb对象
kubectl create svc clusterip mydb --tcp=80:80
7)检查pod状态,myapp-pod正常启动
[root@k8s-master01 2]# kubectl get pod -w
NAME        READY   STATUS     RESTARTS   AGE
myapp-pod   0/1     Init:1/2   0          28m
myapp-pod   0/1     PodInitializing   0          28m
myapp-pod   1/1     Running           0          28m

进入pod所在节点,查看myapp-pod相关容器

能够发现pod生命周期:

​ pause容器一直存在、init容器按照线性启动,并且每个init容器完成以后再回进行下一个init容器,所有init容器完成以后,才会创建程序容器

image-20230112203303433

2、验证 initC 中的容器,返回码为0,才能往后

若返回码不为0,则init容器会重建

实验步骤

1)上传压缩包

image-20230112204829422

[root@k8s-master01 2]# tar -xf initC.tar.gz 
[root@k8s-master01 2]# ls
1.pod.yaml  initC  initC.tar.gz
[root@k8s-master01 2]# ls initC
1.pod.yaml  2.pod.yaml  Dockerfile  go.mod  main.go  randexit


#文件解释:
        两个yaml文件创建pod
        Dockerfile中,封装为镜像 wangyanglinux/tools:randexitv1
                    镜像中用最小的alpine系统
                    将randexit程序设置为启动执行,并定义默认睡眠时间为5
        go.mod,信息

main.go源码中的逻辑:

先定义环境变量睡眠时间和返回码,默认睡眠时间为4,默认返回码为2

执行程序后,判断休眠时间是否大于等于0
            若判断成功
                则判断返回码
                    若返回码为0,则睡眠定义的时间并返回码为0
                    若返回码为1,则睡眠定义的时间并返回码为1
                    若其他返回码,则生成一个随机数
                                若随机数大于等于50,则睡眠定义时间并返回码为1
                                若随机数小于50,则睡眠定义 时间并返回码为0

-----------------总结---------------------
执行程序后,若未指定睡眠时间,默认睡眠4秒
          若未指定返回码,根据默认返回码为2,再根据判断,生成随机数,再根据判断睡眠定义时间并返回码为1或0

验证程序:

[root@k8s-master01 2]# cd initC
[root@k8s-master01 initC]# ls
1.pod.yaml  2.pod.yaml  Dockerfile  go.mod  main.go  randexit

[root@k8s-master01 initC]# ./randexit 
休眠 4 秒,产生的随机数为 17,小于等于 50 ,返回码为 0[root@k8s-master01 initC]# echo $?
0

[root@k8s-master01 initC]# ./randexit 
休眠 4 秒,产生的随机数为 81,大于等于 50 ,返回码为 1[root@k8s-master01 initC]# echo $?
1
2)根据 1.pod.yaml 文件创建pod

此yaml文件根据pod资源创建pod,pod名为:myapp-pod,期望创建一个init容器、程序容器(封装了nginx)

此yaml文件中未定义init容器的返回码

​ 创建的pod中,其中的init容器启动时则执行randexit程序,程序中随机返回返回码为0|1

​ 若返回的返回码为1,则重建init容器,再来一次

​ 若返回的返回码为0,则init容器完成执行,进入下一个程序容器的创建运行

创建pod,名为:myapp-pod

[root@k8s-master01 initC]# cat 1.pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp
    image: wangyanglinux/myapp:v1
  initContainers:
  - name: randexit
    image: wangyanglinux/tools:randexitv1

[root@k8s-master01 initC]# kubectl get pod
No resources found.

[root@k8s-master01 initC]# kubectl create -f 1.pod.yaml 
pod/myapp-pod created

快速执行命令,查看变化信息

image-20230112221833063

3)根据2.pod.yaml 文件创建pod
此yaml文件根据pod资源创建pod,pod名为:myapp-pod,期望创建一个init容器、程序容器(封装了nginx)

此yaml文件中定义了返回码为1

创建的pod中,其中的init容器启动时执行randexit程序,程序执行完后返回返回码为1
            则重建init容器
            重建后init容器再次执行randexit程序,程序返回返回码为1
            再次重建init容器(进入死循环)

创建pod,名为myapp-pod

[root@k8s-master01 initC]# cat 2.pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp
    image: wangyanglinux/myapp:v1
  initContainers:
  - name: randexit
    image: wangyanglinux/tools:randexitv1
    args: ["--exitcode=1"]

[root@k8s-master01 initC]# kubectl get pod
No resources found.

[root@k8s-master01 initC]# kubectl create -f 2.pod.yaml 
pod/myapp-pod created

快速执行命令,查看变化信息,发现initC一直重建

[root@k8s-master01 initC]# kubectl get pod -w
myapp-pod   0/1   Pending   0     0s
myapp-pod   0/1   Pending   0     0s
myapp-pod   0/1   Init:0/1   0     0s
myapp-pod   0/1   Init:0/1   0     1s
myapp-pod   0/1   Init:0/1   0     2s
myapp-pod   0/1   Init:Error   0     7s
myapp-pod   0/1   Init:0/1     1     8s
myapp-pod   0/1   Init:Error   1     13s
myapp-pod   0/1   Init:CrashLoopBackOff   1     29s
myapp-pod   0/1   Init:0/1                2     29s
myapp-pod   0/1   Init:Error              2     34s
myapp-pod   0/1   Init:CrashLoopBackOff   2     47s
myapp-pod   0/1   Init:0/1                3     62s
myapp-pod   0/1   Init:Error              3     67s
myapp-pod   0/1   Init:CrashLoopBackOff   3     81s

3、验证重启策略

pod.spec.restartPolicy      #重启策略,默认为always
            always:pod中,若其中容器损坏,则会一直创建容器修复
            onFailure:pod中,若容器以失败退出(返回码不为0),则会重建容器
                            若容器以正常退出(返回码为0),则不会重建容器
            Never:pod中,无论容器怎样损坏,都不会重建修复

验证Never选项

​ 创建一个3.pod.yaml 文件,其中定义容器重启策略为: Never

​ 基于3.pod.yaml 文件启动pod

[root@k8s-master01 initC]# cp -a 2.pod.yaml 3.pod.yaml
[root@k8s-master01 initC]# vim 3.pod.yaml 
[root@k8s-master01 initC]# cat 3.pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  restartPolicy: Never
  containers:
  - name: myapp
    image: wangyanglinux/myapp:v1
  initContainers:
  - name: randexit
    image: wangyanglinux/tools:randexitv1
    args: ["--exitcode=1"]


[root@k8s-master01 initC]# kubectl delete pod --all
pod "myapp-pod" deleted
[root@k8s-master01 initC]# kubectl create -f 3.pod.yaml

Never 重启策略验证

​ pod中的容器没有重启

[root@k8s-master01 initC]# kubectl get pod
NAME        READY   STATUS       RESTARTS   AGE
myapp-pod   0/1     Init:Error   0          3m55s

[root@k8s-node02 ~]# docker ps -a|grep myapp
03859617db84   0d0bbbbe5f6c           "/root/randexit --ex…"   5 minutes ago   Exited (1) 5 minutes ago             k8s_randexit_myapp-pod_default_c4af8d7c-7a8e-4b3e-8ee3-cb01b8c68efe_0
3a04eebbd047   k8s.gcr.io/pause:3.1   "/pause"                 5 minutes ago   Exited (0) 5 minutes ago             k8s_POD_myapp-pod_default_c4af8d7c-7a8e-4b3e-8ee3-cb01b8c68efe_

4、检测探针-就绪探测

在扩容时,意义很大

在以前负载均衡集群中,若要添加一个pod,需要进行就绪探测,再加入进群中
                若不进行就绪探测,默认就绪状态,则再创建完pod后会自动加入集群,用户有可能并不会访问成功
            (httpget就绪探测,相当于在加入集群之前,进行了一次http访问,通过以后才会处于就绪状态)

千万不要随便执行的命令:

#删除所有的service资源创建的对象,其中有K8S本身运行的对象,除非有备份yaml文件,否则千万不要执行
$ kubectl delete svc --all
1)在未定义就绪探测时,默认就绪状态,实现负载均衡

Ⅰ 依据两个yaml'文件,创建两个pod

[root@k8s-master01 2]# ls
1.pod.yaml  initC  initC.tar.gz
[root@k8s-master01 2]# mkdir 2
[root@k8s-master01 2]# cd 2/

[root@k8s-master01 2]# vim 1.pod.yaml 
[root@k8s-master01 2]# cat 1.pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-1
  labels:
    app: myapp
spec:
  containers:
  - name: myapp
    image: wangyanglinux/myapp:v1

[root@k8s-master01 2]# vim 2.pod.yaml 
[root@k8s-master01 2]# cat 2.pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-2
  labels:
    app: myapp
    version: v1
spec:
  containers:
  - name: myapp
    image: wangyanglinux/myapp:v1

[root@k8s-master01 2]# kubectl create -f 1.pod.yaml 

[root@k8s-master01 2]# kubectl create -f 2.pod.yaml 

Ⅱ 创建svc资源的对象myapp,实现均衡负载

[root@k8s-master01 2]# kubectl create service clusterip myapp --tcp=80:80

[root@k8s-master01 2]# kubectl get svc
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP   2d8h
myapp        ClusterIP   10.96.50.132   <none>        80/TCP    5s

[root@k8s-master01 2]# curl 10.96.50.132
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master01 2]# curl 10.96.50.132/hostname.html
pod-1
[root@k8s-master01 2]# curl 10.96.50.132/hostname.html
pod-2
[root@k8s-master01 2]# curl 10.96.50.132/hostname.html
pod-1
[root@k8s-master01 2]# curl 10.96.50.132/hostname.html
pod-2

[root@k8s-master01 2]# kubectl get pod --show-labels
NAME    READY   STATUS    RESTARTS   AGE     LABELS
pod-1   1/1     Running   0          2m25s   app=myapp
pod-2   1/1     Running   0          2m21s   app=myapp,version=v1
2)定义就绪探测,实现负载均衡

Ⅰ 根据yaml文件,创建pod

[root@k8s-master01 2]# vim 3.pod.yaml 
[root@k8s-master01 2]# cat 3.pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: readiness-httpget-pod
  namespace: default
  labels:
    app: myapp
    env: test
spec:
  containers:
  - name: readiness-httpget-container
    image: wangyanglinux/myapp:v1
    readinessProbe:
      httpGet:
        port: 80
        path: /index1.html
      initialDelaySeconds: 1
      periodSeconds: 3


[root@k8s-master01 2]# kubectl create -f 3.pod.yaml

Ⅱ 查看pod信息,出现问题

describe 查看信息,发现就绪探测未成功,http返回网页404

[root@k8s-master01 2]# kubectl get pod
NAME                    READY   STATUS    RESTARTS   AGE
pod-1                   1/1     Running   0          17m
pod-2                   1/1     Running   0          17m
readiness-httpget-pod   0/1     Running   0          51s    

image-20230113021652907

Ⅲ 修改yaml 文件,重新创建pod

[root@k8s-master01 2]# vim 3.pod.yaml 
[root@k8s-master01 2]# cat 3.pod.yaml |grep index.html
        path: /index.html

[root@k8s-master01 2]# kubectl create -f 3.pod.yaml 
pod/readiness-httpget-pod created

Ⅳ 再次查看pod信息,创建成功

​ httpget就绪探测成功

[root@k8s-master01 2]# kubectl get pod 
NAME                    READY   STATUS    RESTARTS   AGE
pod-1                   1/1     Running   0          23m
pod-2                   1/1     Running   0          23m
readiness-httpget-pod   1/1     Running   0          10s

Ⅴ 测试负载均衡

[root@k8s-master01 2]# kubectl get service
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP   2d8h
myapp        ClusterIP   10.96.50.132   <none>        80/TCP    26m
[root@k8s-master01 2]# curl 10.96.50.132/hostname.html
readiness-httpget-pod
[root@k8s-master01 2]# curl 10.96.50.132/hostname.html
pod-1
[root@k8s-master01 2]# curl 10.96.50.132/hostname.html
pod-2
[root@k8s-master01 2]# curl 10.96.50.132/hostname.html
readiness-httpget-pod
[root@k8s-master01 2]# curl 10.96.50.132/hostname.html
pod-1
[root@k8s-master01 2]# curl 10.96.50.132/hostname.html
pod-2

5、检测探针-存活探测

总结:一般使用httpget进行存活探测

exec进入探测虽然全面,但相对复杂
tcp探测,仅对端口是否存在进行探测,并不能保证是否正常访问,探测可能存在问题
1)exec存活tance

Ⅰ 根据 4.pod.yaml 文件,创建pod

4.pod.yaml 中,将pod资源创建pod,名为:liveness-exec-pod,在default空间中
                    在pod中创建容器,名为:liveness-exec-container,使用镜像为:busybox:1.35.0
                    定义这个容器启动时,默认创建一个文件,休眠60秒后将文件删除,在休眠3600秒
                    对这个容器采用了exec存活探测:
                                         exec容器,判断 /tmp/live 文件是否存在(1秒延迟、3秒探测重试)

若探测到文件不存在,则会根据pod重启策略,重建容器
[root@k8s-master01 2]# vim 4.pod.yaml
[root@k8s-master01 2]# cat 4.pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: liveness-exec-pod
  namespace: default
spec:
  containers:
  - name: liveness-exec-container
    image: busybox:1.35.0
    command: ["/bin/sh","-c","touch /tmp/live ; sleep 60; rm -rf /tmp/live; sleep 3600"]
    livenessProbe:
      exec:
        command: ["test","-e","/tmp/live"]
      initialDelaySeconds: 1
      periodSeconds: 3

[root@k8s-master01 2]# kubectl create -f 4.pod.yaml

Ⅱ 查看pod信息

发现:liveness-exec-pod 会 每隔一段时间都重建一次 容器 liveness-exec-container
原理:因为容器在创建后,一分钟之内有 /temp/live 文件存在,而此处存活探测的机制就是判断是否存在 /temp/live 文件
            一分钟以后,文件删除,存活探测失败,容器重建
[root@k8s-master01 2]# kubectl get pod -w
NAME                    READY   STATUS    RESTARTS   AGE
liveness-exec-pod       1/1     Running   0          22s
pod-1                   1/1     Running   0          47m
pod-2                   1/1     Running   0          47m
readiness-httpget-pod   1/1     Running   0          23m
liveness-exec-pod       1/1     Running   1          97s
liveness-exec-pod       1/1     Running   2          3m17s
liveness-exec-pod       1/1     Running   3          4m55s
2)httpget存活探测

Ⅰ 根据 5.pod.yaml 文件,创建 pod

5.pod.yaml 中,将pod资源创建为pod,名为:liveness-httpget-pod,在default 空间中
        在pod中创建容器,名为:liveness-httpget-container,使用镜像为:wangyanglinux/myapp:v1
        声明了80为重要端口(信息级别),使得后面httpget能进行探测
        定义httpget探测,端口为80,访问路径为:网页主目录下的 index.html 文件。(延迟1秒、3秒探测重试、探测超时时间3秒)

根据网页是否能访问,作为探测成功的条件
                        若网页无法访问,重建容器
                        若网页能否访问,或者返回结果未知,静默等待下一次探测
[root@k8s-master01 2]# vim 5.pod.yaml
[root@k8s-master01 2]# cat 5.pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: liveness-httpget-pod
  namespace: default
spec:
  containers:
  - name: liveness-httpget-container
    image: wangyanglinux/myapp:v1
    ports:
    - name: http
      containerPort: 80
    livenessProbe:
      httpGet:
        port: 80
        path: /index.html
      initialDelaySeconds: 1
      periodSeconds: 3
      timeoutSeconds: 3
[root@k8s-master01 2]# kubectl create -f 5.pod.yaml
pod/liveness-httpget-pod created

Ⅱ 查看pod信息,正常运行

​ 因为容器的网页一直能访问,存活探测成功,静默,等待下一次探测

[root@k8s-master01 2]# kubectl get pod |grep liveness-httpget-container

[root@k8s-master01 2]# kubectl get pod |grep liveness-httpget-pod
liveness-httpget-pod    1/1     Running   0          84s

Ⅲ 模拟网页文件损坏

​ 让 httpget 存活探测,探测到存活失败,从而重建容器

#进入容器,修改网页主文件,发现一段时间后,自动退出
[root@k8s-master01 2]# kubectl exec -it liveness-httpget-pod -c liveness-httpget-container /bin/sh
/ # ls /usr/share/nginx/html/
50x.html    index.html
/ # mv /usr/share/nginx/html/index.html /usr/share/nginx/html/index1.html 
/ # command terminated with exit code 137


#再次查看pod信息,发现容器出现重建
[root@k8s-master01 2]# kubectl get pod |grep liveness-httpget-pod
liveness-httpget-pod    1/1     Running            1          8m18s
3)tcp存活探测

Ⅰ 根据 6.pod.yaml 文件,创建pod

6.pod.yaml 中,将pod资源创建为pod,名为:probe-tcp,未指定名字空间(默认也在 default 空间中)
                        在pod中创建容器,名为 nginx ,使用镜像为:wangyanglinux/myapp:v1
                        定义tcp存活探测,探测是否有80端口。(延迟5秒,探测超时时间1秒)

根据是否存在80端口,作为探测成功的条件(一般不用此探测)
                    若tcp连接80端口失败,则重建容器
                    若tcp连接80端口成功,或者未知,静默等待下一次探测
[root@k8s-master01 2]# vim 6.pod.yaml
[root@k8s-master01 2]# cat 6.pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: probe-tcp
spec:
  containers:
  - name: nginx
    image: wangyanglinux/myapp:v1
    livenessProbe:
      initialDelaySeconds: 5
      timeoutSeconds: 1
      tcpSocket:
        port: 80
[root@k8s-master01 2]# kubectl create -f 6.pod.yaml 
pod/probe-tcp created

Ⅱ 查看pod信息,正常运行

[root@k8s-master01 2]# kubectl get pod |grep probe-tcp
probe-tcp               1/1     Running   0          69s

6、钩子机制

Pod hook(钩子)是由 K8S 管理的 kubectl 发起的,当容器中的进程启动前,或容器中进程终止前运行。这是包含在容器的生命周期中。可以同时为Pod中所有容器都配置钩子

Hook 的类型包括两种:
                        exec:执行一段命令
                        HTTP:发送http请求
实验:启动后钩子+关闭前钩子

Ⅰ 根据 /root/3/1.pod.yaml 文件创建 pod

1.pod.yaml 文件中,将pod资源创建为pod,名为:lifecycle-demo,未指定名字空间(使用默认 default 空间)
                    在pod中创建容器,名为:lifecycle-demo-container,使用镜像:
                                                        wangyanglinux/myapp:v1
                    定义启动后钩子,exec动作:向 /usr/share/message 中写入数据
                    定义关闭前钩子,exec动作:想 /usr/share/message 中写入数据
[root@k8s-master01 ~]# mkdir 3
[root@k8s-master01 ~]# cd 3
[root@k8s-master01 3]# vim 1.pod.yaml
[root@k8s-master01 3]# cat 1.pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
spec:
  containers:
  - name: lifecycle-demo-container
    image: wangyanglinux/myapp:v1
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
      preStop:
        exec:
          command: ["/bin/sh", "-c", "echo Hello from the preStop handler > /usr/share/message"]


[root@k8s-master01 3]# kubectl get pod
No resources found.
[root@k8s-master01 3]# kubectl create -f 1.pod.yaml

Ⅱ 测试钩子机制

​ 进入容器,查看启动后钩子创建的文件存在

[root@k8s-master01 3]# kubectl exec -it lifecycle-demo -c lifecycle-demo-container -- /bin/sh
/ # cat /usr/share/message 
Hello from the postStart handler

​ 在容器中写一个死循环,方便删除pod时,能查看到关闭前钩子创建的文件

#在pod的容器中执行
/ # while true ;do cat /usr/share/message ;done


#另开一个终端删除pod
[root@k8s-master01 3]# kubectl delete -f 1.pod.yaml

​ 观察到关闭前钩子创建的文件

image-20230115174823363

7、将 pod 生命周期中定义的内容结合

Ⅰ 根据 all.yaml 文件,创建pod

#all.yaml文件详解
all.yaml 文件中,将pod资源创建为pod,名为:myapp-pod,定义标签为:app=myapp(未指定名字空间,默认在default空间中)
        创建两个initC:
                一个为名为:init-myservice,使用镜像为:busybox:1.35.0,启动容器时执行命令为:不能识别myservice域名解析,就陷入死循环,直到能解析才退出死循环
                另一个名为:init-mydb,使用镜像为:busybox:1.35.0,启动容器时执行命令为:不能识别mydb域名解析,就陷入死循环,直到能解析才退出死循环
        创建两个mainC:
                一个名为:busybox-c,使用镜像为:busybox:1.35.0
                            启动容器时执行命令为:创建一个 /tmp/live文件,睡眠10分钟后,将其删除,再睡眠3600秒
                            定义一个存活探测:exec动作,进入容器后,判断是否有 /tmp/live文件存在,若不存在则重建容器(延迟1秒,探测重试3秒)
                            定于启动后钩子:向 /var/message 中写入,启动后钩子执行完成的信息
                            定义关闭前钩子:想 /var/message 中写入,关闭前钩子执行完成的信息
                另一个名为:myapp-c,使用镜像为:wangyanglinux/myapp:v1
                            定义一个就绪探测:httpget动作,若能访问80端口下的,index1.html文件成功则转换为就绪状态,否则处于未就绪状态(探测延迟1秒,探测重试3秒)
                            定义一个存活探测:httpget动作,若能访问80端口下的,index.html文件成功,则一直处于存活状态,否则重建容器(探测延迟1秒,探测重试3秒,探测超时3秒)
[root@k8s-master01 ~]# cd /root/3/
[root@k8s-master01 3]# vim all.yaml 
[root@k8s-master01 3]# cat all.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: busybox-c
    image: busybox:1.35.0
    command: ["/bin/sh","-c","touch /tmp/live ; sleep 600; rm -rf /tmp/live; sleep 3600"]
    livenessProbe:
      exec:
        command: ["test","-e","/tmp/live"]
      initialDelaySeconds: 1
      periodSeconds: 3
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /var/message"]
      preStop:
        exec:
          command: ["/bin/sh", "-c", "echo Hello from the preStop handler > /var/message"]
  - name: myapp-c
    image: wangyanglinux/myapp:v1
    readinessProbe:
      httpGet:
        port: 80
        path: /index1.html
      initialDelaySeconds: 1
      periodSeconds: 3
    livenessProbe:
      httpGet:
        port: 80
        path: /index.html
      initialDelaySeconds: 1
      periodSeconds: 3
      timeoutSeconds: 3
  initContainers:
  - name: init-myservice
    image: busybox:1.35.0
    command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
  - name: init-mydb
    image: busybox:1.35.0
    command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']

[root@k8s-master01 3]# kubectl create -f all.yaml

Ⅱ 查看pod状态,发现问题并解决

​ 发现需要解决域名解析问题,才能让initC容器完成退出,并返回码为0

[root@k8s-master01 3]# kubectl get pod
NAME        READY   STATUS     RESTARTS   AGE
myapp-pod   0/2     Init:0/2   0          115s


#解决域名解析问题,添加svc
[root@k8s-master01 3]# kubectl create service clusterip myservice --tcp=80:80
service/myservice created
[root@k8s-master01 3]# kubectl create service clusterip mydb --tcp=80:80
service/mydb created
[root@k8s-master01 3]# kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   5d
mydb         ClusterIP   10.107.123.80   <none>        80/TCP    6s
myservice    ClusterIP   10.103.225.22   <none>        80/TCP    24s

​ 发现需要解决其中一个容器的,就绪探测问题

​ 进入容器写入网页文件 index1.html

[root@k8s-master01 3]# kubectl get pod
NAME        READY   STATUS    RESTARTS   AGE
myapp-pod   1/2     Running   9          103m

image-20230115200459176

​ 解决:

[root@k8s-master01 3]# kubectl exec -it myapp-pod -c myapp-c -- /bin/sh
/ # cd /usr/share/nginx/html/
/usr/share/nginx/html # ls
50x.html    index.html
/usr/share/nginx/html # echo "hello YQ.." > index1.html

​ 再次检查pod状态:

[root@k8s-master01 ~]# kubectl get pod
NAME        READY   STATUS    RESTARTS   AGE
myapp-pod   2/2     Running   9          108m

以上已经验证完的特性:initC特性、就绪探测机制

接下来验证存活探测机制、钩子机制

Ⅲ 测试

#根据yaml文件,定义了myapp-c的存活探测httpget动作
#进入容器删除网页主文件,存活探测失败,重建容器
[root@k8s-master01 ~]# kubectl exec -it myapp-pod -c myapp-c -- /bin/sh
/ # cd /usr/share/nginx/html/
/usr/share/nginx/html # ls
50x.html     index.html   index1.html
/usr/share/nginx/html # rm -rf index.html 
/usr/share/nginx/html # command terminated with exit code 137



#定义了busybox-c的钩子机制
[root@k8s-master01 3]# kubectl exec -it myapp-pod -c busybox-c -- /bin/sh
/ # cat /var/message 
Hello from the postStart handler

#若容器退出时,也有内容写入 /var/message (可用死循环进行查看,另起一个终端删除pod,验证)