K8S资源清单 ---- Kubernetes

1. K8S中的资源
1.1 什么是资源

K8S中所有的内容都抽象为资源,资源实例化后叫做对象。实例化的含义的是指资源被调用执行。

1.2 资源分类

名称空间级别的资源:仅在指定名称空间下生效,kuberadm安装K8S集群默认把所有的系统组件放在kube-system名称空间下运行,通过命令 kubect get pod 是获取不到系统Pod的信息,这里 kubect get pod 等价于kubect get pod -n default,只会获取默认的名称空间中的资源。

集群级别的资源:不管什么名称下定义,在其它名称空间下都能看得到,其实在定义的时候根本没有指定名称空间。一旦经过定义以后,在全集群中都是可见的并且可以被调用的。

元数据型的资源:如HPA可以通过CPU的当前利用率进行平滑扩展,也就是通过指标进行操作

1.3 名称空间级别资源

工作负载资源:Pod,ReplicaSet,Deploment,StatefulSet,DaemonSet,Job,CronJob(ReplicationController在v1.11版本中被废弃)

服务发现及负载均衡型资源:Service,Ingress。这两个都是为了 把服务暴露出去

配置与存储资源:Volume(存储卷),CSI(容器存储接口,可以扩展各种各样的第三方存储卷)在K8S中,很多资源比较灵活地能够提供给所需要的容器运行,只要存储资源复合存储规范,K8S中的Pod就可以调用存储资源。

特殊类型的存储卷:ConfigMap(通过其存储配置文件达到i热更新的状态,当作配置中心来使用的资源类型),Secret(保护敏感数据),DownloadAPT(把外部环境中的信息输出给容器)

1.3 集群级别的资源

Namespace,Node,Role,ClusterRole,RoleBinding,CluserRoleBinding

1.4 元数据型资源

HPA,PodTemplate,LimitRange,也就是需要根据指标进行对应的操作

2. 资源清单

在K8S中一般 使用yaml格式的文件来创建符合我们期望的Pod,这样的yaml文件一般被称之为资源清单。

2.1 简单说明

YAML文件是一个可读性高,用来表达数据序列的格式。YAML的意思其实是:仍然是一种标记语言,但是为了强调这种语言以数据为中心,而不是以标记语言为中心。

2.2 基本语法

缩进时不允许使用Tab,只能够使用空格

缩进的空格数不重要,只要相同层级的元素左侧对齐即可

#标识注释,从这个字符一直到尾行都会被解释器忽略

2.3 YAML支持的数据结构

对象:键值对集合,又称为映射/字典/哈希

数组:一组按照次序排列的值,又称为序列/列表

纯量:单个的、不可再分的值

2.4 对象类型

对象的一组键值对使用冒号来表示:

name:Erics
age:23

也允许另外一种写法,把所有的键值对写成一个行内对象:

hash:{name:Erics,age:23}
2.5 数组类型

一组连词线开头的行构成一个数组:

animal:
- cat
- dog

数组也可以采用行内写法:

animal:[cat,dog]
2.6 复合结构

对象和数组可以结合使用形成复合结构:

languages:
- Python
- Java
- C
websites:
YAML:yaml.org
Python:python.org
2.7 纯量

纯量时最基本的不可再分的值,以下都属于纯量:

# 字符串 布尔值 整数 浮点数 null 时间 日期
# 数值直接以字面量的形式表示:
number:123
# 布尔值以true和false标识:
isSet:true
# null用~表示,不写也代表null:
parent:~
# 时间采用ISO8601格式:
ISO8601:2020-06-16t15:17:20.10-05:00
# 日期采用复合ISO8601格式的年、月、日表示:
date:2020-06-18
# YAML允许使用两个!!强制转换类型
e:!!str 123
f:!!str true
2.8 字符串

字符串不使用引号表示,

str:字符串

如果字符串之间包含空格,需要使用引号:

str:'字符串 ' 

单引号和双引号都可以使用,双引号不会对特殊字符转义

s1:'\n'
s2:"\n"

单引号之中如果还有单引号,必须再加一个单引号转义:

str:'labor''s day'

字符串可以写成多行,从第二行开始必须有一个单空格缩进。换行符会被转成空格:

str:第一行
 第二行
 第三行

多行字符串可以使用|保留换行符,也可以使用>折叠换行:

this:|
Foo
Bar
that:>
Foo
Bar

+表示文字块末尾的换行(默认),-表示删除字符串末尾的换行:

s1:|
 Foo
s2:|+
 Foo
s3:|-
 Foo
3. 常用字段解释说明
3.1 必须存在的属性

在这里插入图片描述

3.2 主要对象

主要对象不写也可以,会使用默认值:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.3 额外的参数项

在这里插入图片描述

3.4 自定义Pod模板

可以使用命令去查看这些参数的解释:

[root@k8s-master-01 ~]# kubectl explain pod
[root@k8s-master-01 ~]# kubectl explain pod.spec
[root@k8s-master-01 ~]# kubectl explain pod.spec.containers
...

自己写一个Pod模板:

pod.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  namespace: default
  labels:
    app: myapp
    version: v1
spec:
  containers:
  - name: app
    image: hub.atguigu.com/library/myapp:v1
  - name: test
    image: hub.atguigu.com/library/myapp:v1

Pod创建成功:

[root@k8s-master-01 ~]# kubectl apply -f pod.yaml 
pod/myapp-pod created
[root@k8s-master-01 ~]# kubectl get pod
NAME                               READY   STATUS        RESTARTS   AGE
myapp-pod                          0/2     Pending       0          2m13s
# 查看Pod的信息
[root@k8s-master-01 ~]# kubectl describe pod myapp-pod
# 查看容器运行日志
[root@k8s-master-01 ~]# kubectl log myapp-pod -c app
[root@k8s-master-01 ~]# kubectl log myapp-pod -c test

第一个容器 app 运行正常,但是 test 不能正常运行,因为 app 容器已经占用了80端口。同一个Pod中的容器共享网络栈。下面修改 yaml 文件,把 test 容器删除:

[root@k8s-master-01 ~]# vim pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  namespace: default
  labels:
    app: myapp
    version: v1
spec:
  containers:
  - name: app
    image: hub.atguigu.com/library/myapp:v1
# 删除pod
[root@k8s-master-01 ~]# kubectl delete pod myapp-pod
# 按照yaml文件创建pod
[root@k8s-master-01 ~]# kubectl apply -f pod.yaml 
# 查看pod的详细信息
[root@k8s-master-01 ~]# kubectl get pod -o wide
NAME                               READY   STATUS        RESTARTS   AGE     IP            NODE          NOMINATED NODE   READINESS GATES
myapp-pod                          1/1     Running       0          12s     10.244.1.20   k8s-node-01   <none>           <none>
[root@k8s-master-01 ~]# curl 10.244.1.20
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
4. Pod生命周期

Pod在创建经历了哪些过程,理解了这些过程才能直到如何探测。Pod里面有两个容器,如果两个容器中的进程已经死亡或意外中断了,由于某种故障这个Pod并没有退出,造成这个Pod还处于运行状态。这时候服务是不可用的,但是这个Pod还是处于可用状态。这个时候就会出现问题,那么如何来做探查?不着急,首先要了解容器是如何初始化的。Pod的生命周期:
在这里插入图片描述
一开始当我们的请求指令被下达到api接口被调度到kuberlet上,kuberlet操作对应的CRI去做容器环境的初始化,会先启动Pause容器(基本容器,同一Pod容器的容器之间网络和存储卷共享)。进入Pod生命周期内部,Pod创建的时候首先需要进行Init C(初始化容器)的创建过程,创建完成之后Init C就会死亡。不能同时运行两个甚至多个Init C,只能前面一个Init C运行结束后运行下一个Init C。要在Init C之前。Init C完成之后就会进入主容器,主容器可以有多个。在主容器运行之前和之后都可以运行指令,即:Start和Stop操作,执行命令或者脚本

在这里插入图片描述
readiness,即就绪检测模块,可以根据命令或TCP连接或HTTP协议获取状态,判断Pod中服务是否可用,如果可用才会把运行状态改为Running,防止虽然处于Running状态,但是无法提供给外网访问。

liveness,即生存检测模块。如果Pod里面运行一个主容器,主容器中运行一个Nginx的进程,但是处于假死状态(僵尸进程)。进程没有死掉,则这个主容器就会运行着,Pod的状态就会显示Running,能够继续为外网提供访问。我们需要需要有种机制,当发现容器内部(Nginx)不能提供对外访问的时候,可以 重启进程或者重建Pod等操作,这就用到了liveness。
在这里插入图片描述

5. Init 容器
5.1 Init 容器概述

Pod能够具有多个容器,应用运行在容器里面,但是它也可能有一个或多个先于应用容器启动的Init容器,Init容器与普通的容器非常像,除了如下两点:

① Init容器总是运行到成功完成为止
② 每个Init容器都必须在下一个Init容器启动之前成功完成

对应 Init 容器和主容器是不一样的,主容器如果退出,Pod也就结束了。Init C的退出与Pod生命周期没有关系,Pod并不会结束。但是,Init C如果不是正常退出,就到达不了主容器。并且,如果Init C如果如果没有正常退出,Pod是需要进行对应的流程处理,比如Pod重启。

如果Pod的Init容器失败,Kubernetes会不断地重启该Pod,直到Init容器成功为止。然而,如果Pod对应的restartPolicy为Never,它不会重新启动

5.2 Init容器的作用

因为Init容器具有与应用程序容器分离的单独镜像,所以它们的启动相关代码具有如下优势:

① 它们可以包含并运行实用工具,但是出于安全考虑,是不建议在应用程序容器镜像中包含这些实用工具的(安全性

② 它们可以包含使用工具和定制化代码来安装,但是不能出现在应用程序镜像中。例如,创建镜像没必要FROM另一个镜像,只需要在安装过程中使用类似sed、awk、python或dig这样的工具。(冗余性)

把主容器要使用的工具写入Init C,在初始化的时候把主容器需要的文件提前创建出来。主容器不需要包含这些文件,这些工具并不是主容器一直都要用的,防止造成冗余

③ 应用程序镜像可以分离出创建和部署的角色,而没有必要联合它们构建一个单独的镜像

④ Init容器使用LinuxNamespace,所以相对应用程序容器来说具有不同的文件系统视图。因此,它们能够具有访问Secret的权限,而应用程序容器则不能

有一些需要主容器去调用的文件,但是主容器(Main C)对这些文件没有访问权限。这个文件所在的目录还有其它重要的文件,如果把这个文件的目录赋予权限给主容器,那么主容器就可以随便调用目录下的所有文件。这样安全性就出现隐患,这个时候完全可以把权限赋予给Init C,让Init C获取文件后写入到主容器,Init C写入文件后就退出了。主容器没有获取文件的权限,主容器安全性就会提高。这是采用分权限进行处理。

⑤ 它们必须在应用程序容器启动之前运行完成,而 应用程序容器是并行运行的,所以Init容器能够提供了一种简单的阻塞或延迟应用容器的启动的方法,直到满足了一组先决条件

如有两个主容器,一个是Apache+PHP,另外一个是MySQL。要求启动mysql后再启动Apache+PHP容器,这是为了防止Apache+PHP容器连接MySQL连接不上,认为容器有问题就退出容器,然后不断重启。这种情况下可以在Apache+PHP容器加入的Init C,可以探测MySQL连接是否正常,如果正常启动,Init C会退出容器,主容器启动连接MySQL。

5.3 Init 容器实例

node1和node2下载busybox镜像,也可以不下载等待自动下载:

[root@k8s-node-01 ~]# docker pull busybox
[root@k8s-node-02 ~]# docker pull busybox
[root@k8s-master-01 ~]# vim init-pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox
    command: ['sh','-c','echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox
    command: ['sh','-c','until nslookup myservice; do echo waiting for myservice; sleep 2;done;']
  - name: init-mydb
    image: busybox
    command: ['sh','-c','until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
# deployment和pod默认使用的名称空间是default
[root@k8s-master-01 ~]# kubectl delete deployment --all
[root@k8s-master-01 ~]# kubectl delete pod --all
# 删除svc
[root@k8s-master-01 ~]# kubectl get svc
[root@k8s-master-01 ~]# kubectl delete svc nginx-deployment
# grace-period表示过渡存活期,默认30s,在删除POD之前允许POD慢慢终止其上的容器进程,从而优雅退出,0表示立即终止POD
[root@k8s-master-01 ~]# kubectl delete pod --all  --force --grace-period=0
[root@k8s-master-01 ~]# kubectl create -f init-pod.yaml 
pod/myapp-pod created
[root@k8s-master-01 ~]# kubectl get pod
NAME        READY   STATUS     RESTARTS   AGE
myapp-pod   0/1     Init:0/2   0          3s
[root@k8s-master-01 ~]# kubectl describe pod myapp-po
[root@k8s-master-01 ~]# kubectl get pod
NAME        READY   STATUS     RESTARTS   AGE
myapp-pod   0/1     Init:0/2   0          101s
# 查看init-myservice 初始化容器的日志,发现解析不成功
[root@k8s-master-01 ~]# kubectl log myapp-pod -c init-myservice

创建svc:

[root@k8s-master-01 ~]# vim myservice.yaml
kind: Service
apiVersion: v1
metadata:
  name: myservice
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376
[root@k8s-master-01 ~]# kubectl create -f myservice.yaml 
[root@k8s-master-01 ~]# vim myservice.yaml
[root@k8s-master-01 ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP   7d2h
myservice    ClusterIP   10.107.163.130   <none>        80/TCP    85s
# 其中一个初始化容器已经运行成功并退出
[root@k8s-master-01 ~]# kubectl get pod
NAME        READY   STATUS     RESTARTS   AGE
myapp-pod   0/1     Init:1/2   0          10m

创建一个名字为myservice的service,myservice创建之后会被本机集群内部解析。也就是说,内部的所有容器会把两台机器的内部IP配置成DNS服务器。myapp-pod会请求这个DNS服务器,又没有名字为myservice的svc,如果创建了svc,就会被写入到DNS。DNS就会返回对应的数据,成功之后,初始化容器检测到就退出。

# coredns-5c98db65d4-dc5h7是DNS
[root@k8s-master-01 ~]# kubectl get pod -n kube-system
NAME                                    READY   STATUS        RESTARTS   AGE
coredns-5c98db65d4-dc5h7                1/1     Running       0          10m
coredns-5c98db65d4-f2lbc                1/1     Running       0          10m
coredns-5c98db65d4-r6sbc                1/1     Terminating   17         7d2h
coredns-5c98db65d4-zq2xf                1/1     Terminating   17         7d2h
etcd-k8s-master-01                      1/1     Running       18         7d2h
kube-apiserver-k8s-master-01            1/1     Running       18         7d2h
kube-controller-manager-k8s-master-01   1/1     Running       1          7d2h
kube-flannel-ds-amd64-gd55v             1/1     Running       12         7d1h
kube-flannel-ds-amd64-l8xtd             1/1     Running       21         7d2h
kube-flannel-ds-amd64-xcwmt             1/1     Running       7          6d23h
kube-proxy-5gm9j                        1/1     Running       18         7d2h
kube-proxy-n2gkx                        1/1     Running       8          6d23h
kube-proxy-zl82c                        1/1     Running       12         7d1h
kube-scheduler-k8s-master-01            1/1     Running       27         7d2h

第二个Init C检测的是mydb,所以需要创建一个mydb的svc:

[root@k8s-master-01 ~]# vim mydb.yaml
kind: Service
apiVersion: v1
metadata:
  name: mydb
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9377
[root@k8s-master-01 ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP   7d3h
mydb         ClusterIP   10.106.42.42     <none>        80/TCP    32s
myservice    ClusterIP   10.107.163.130   <none>        80/TCP    13m
[root@k8s-master-01 ~]# kubectl get pod
NAME        READY   STATUS    RESTARTS   AGE
myapp-pod   1/1     Running   0          21m
# 如果出错可以查看
[root@k8s-master-01 ~]# kubectl decribe pod myapp-pod

busybox在没有指定版本的情况下,默认用latest来ag,在K8S中如果使用latest标签来保存,每次在使用镜像的时候都会从仓库去下载。latest在不同时期代表不同版本。

4.4 特殊说明

① 在Pod启动过程中,Init容器会按顺序在网络和数据卷初始化(在pause中完成)之后启动。每个容器必须在下一个容器启动之前成功退出

② 如果由于运行时或失败退出,将导致容器启动失败,它会根据Pod的restartPolicy指定的策略进行重试,直到达到最大上限。然而,如果Pod的restartPolicy设置为Always,Init容器失败时会使用RestartPolicy策略

③ 在所有的Init容器没有成功之前,Pod将不会变成Ready状态。Init容器的端口将不会在Service中进行聚集。正在初始化中的Pod处于Pending状态,但应该会将Initializing状态设置为true

如果Pod重启,所有Init容器必须重新执行

⑤ 对Init容器spec的修改被限制在容器image字段,修改其他字段都不会生效。更改Init容器的image字段,等价于重启该Pod

[root@k8s-master-01 ~]# kubectl edit pod myapp-pod
initContainers:
  - command:
    - sh
    - -c
    - until nslookup myservice; do echo waiting for myservice; sleep 2;done;
    image: busybox	# 其它修改不会生效,但是被修改会触发init C容器,相当于Pod被重启了
...

⑥ Init容器具有应用容器的所有字段。除了readinessProbe,因为Init容器无法定义不同于完成(completion)的就绪(readiness)之外的其他状态,这会在验证过程中强制执行。没有存活检测和就绪检测字段,因为完成之后就退出了,如果有也不会生效。

⑦ 在 Pod中的每个app和Init容器的名称必须唯一,与任何其它容器共享同一个名称,会在验证时抛出错误,端口可以是一致的,Init C容器是线性运行的,一个运行结束才会运行下一个。

6. 容器探针
6.1 探针

探针不是由主服务发起的,而是由每一个Node所在的kubelet对容器执行的定期诊断,这样主调度的压力就会更小。要执行诊断,kubelet调用由容器实现的Handler。有三种类型的处理程序:

① ExecAction:在容器内执行指定命令。如果命令退出时返回码为0则认为诊断成功

② TCPSocketAction:对指定端口上的容器的IP地址进行TCP检查。如果端口打开,则诊断被认为是成功的

③ HTTPGetAction:对指定的端口和路径上的容器的IP地址执行HTTPGet请求。如果响应的状态码大于等于200且小于400,则诊断被认为是成功的

每次探测都将获得以下三种结果之一:

① 成功:容器通过了诊断

② 失败:容器未通过诊断

③ 未知:诊断失败,因此不会采取任何行动

6.2 探测方案

livenessProbe:指示容器是否正在运行。如果存活探测失败,则kubelet会杀死容器,并且容器将受到其重启策略的影响。如果容器不提供存活探针,则默认状态为Success(会跟随容器整个生命周期,从liveness启动到Pod结束都会存在,会持续循环地检测这个容器里面的应用程序资源是否可用,不可用就会杀死这个容器。

readinessProbe:指示容器是否准备好服务请求。如果就绪探测失败,端点控制器将从与Pod匹配的所有Service的端点中删除该Pod的IP地址。初始延迟之前的就绪状态默认为Failure。如果容器不提供就绪探针,则默认状态为Success(检测成功之后,主容器才能够宣布对外正常访问。

6.3 就绪检测

就绪检测的实现,通过httpget方案:

[root@k8s-node-01 ~]# docker images
REPOSITORY                           TAG                 IMAGE ID            CREATED             SIZE
busybox                              latest              1c35c4412082        2 weeks ago         1.22MB
quay.io/coreos/flannel               v0.12.0-amd64       4e9f801d2217        3 months ago        52.8MB
k8s.gcr.io/kube-apiserver            v1.15.1             68c3eb07bfc3        11 months ago       207MB
k8s.gcr.io/kube-scheduler            v1.15.1             b0b3c4c404da        11 months ago       81.1MB
k8s.gcr.io/kube-controller-manager   v1.15.1             d75082f1d121        11 months ago       159MB
k8s.gcr.io/kube-proxy                v1.15.1             89a062da739d        11 months ago       82.4MB
k8s.gcr.io/coredns                   1.3.1               eb516548c180        17 months ago       40.3MB
k8s.gcr.io/etcd                      3.3.10              2c4adeb21b4f        18 months ago       258MB
hub.atguigu.com/library/myapp        v1                  d4a5e0eaa84f        2 years ago         15.5MB
k8s.gcr.io/pause                     3.1                 da86e6ba6ca1        2 years ago         742kB
[root@k8s-master-01 ~]# vim readness.yaml
apiVersion: v1                          # api的版本
kind: Pod                               # kind的类型
metadata:                               # 元数据信息
  name: readiness-httpget-pod           # pod的名称
  namespace: default                    # pod所在的名称空间
spec:                                   # 详细的描述
  containers:                           # 描述容器
  - name: readiness-httpget-container   # 容器的名称 
    image: hub.atguigu.com/library/myapp:v1       # 容器的镜像
    imagePullPolicy: IfNotPresent       # 镜像的下载策略:如果有就不下载了
    readinessProbe:                     # 就绪检测
      httpGet:                          # 检测的方案:httpGet
        port: 80                        # 端口,或者写为http
        path: /index1.html              # 检测的路径
      initialDelaySeconds: 1            # 初始化检测的延时:容器启动1s后开始检测
      periodSeconds: 3                  # 重试的检测时间:3s后重试检测
[root@k8s-master-01 ~]# kubectl create -f readness.yaml 
# 虽然是Runngin状态但是并不是Ready状态
[root@k8s-master-01 ~]# kubectl get pod -o wide
NAME                    READY   STATUS    RESTARTS   AGE     IP            NODE          NOMINATED NODE   READINESS GATES
myapp-pod               1/1     Running   4          3h28m   10.244.1.38   k8s-node-01   <none>           <none>
readiness-httpget-pod   0/1     Running   0          4s      10.244.1.42   k8s-node-01   <none>           <none>
# 发现没有index1.html,即探针检测出来是404
[root@k8s-master-01 ~]# kubectl describe pod readiness-httpget-pod
  Warning  Unhealthy  3s (x16 over 48s)  kubelet, k8s-node-01  Readiness probe failed: HTTP probe failed with statuscode: 404
# 进入容器中,如果Pod中只有一个容器不需要指定容器名称,指定的时候加上-c参数,-t交互和打开tty
[root@k8s-master-01 ~]# kubectl exec readiness-httpget-pod -it -- /bin/sh
/ # cd /usr/share/nginx/
/usr/share/nginx # cd html/
/usr/share/nginx/html # ls
50x.html    index.html
/usr/share/nginx/html # echo '123'>index1.html
/usr/share/nginx/html # ls
50x.html     index.html   index1.html
/usr/share/nginx/html # exit
# 检测成功
[root@k8s-master-01 ~]# kubectl get pod
NAME                    READY   STATUS    RESTARTS   AGE
myapp-pod               1/1     Running   4          3h34m
readiness-httpget-pod   1/1     Running   0          6m49s

如果有个主容器apache+php想检测mysql状态,使用Init C是不友好的,Init C作为环境初始化工具即可。在主容器中使用readinessProbe对mysql进行检测是比较合适的。

6.4 存活检测

通过exec的方案来实现存活检测:

# 删除默认名称空间下的所有Pod
[root@k8s-master-01 ~]# kubectl delete pod --all
[root@k8s-master-01 ~]# kubectl delete svc mydb myservice
[root@k8s-master-01 ~]# kubectl create -f liveness.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: liveness-exec-pod
  namespace: default
spec:
  containers:
  - name: liveness-exec-container
    image: busybox  # 如果没有加版本号,默认为latest,会从远程下载(前提条件:默认的,也就是Always) 
    imagePullPolicy: IfNotPresent    # 不是默认,不会去远程下载
    command: ["/bin/sh","-c","touch /tmp/live ; sleep 60; rm -rf /tmp/live; sleep3600"]
    livenessProbe:      # 和容器绑定
      exec:
        command: ["test","-e","/tmp/live"]     # 检测这个文件是否存在 
      initialDelaySeconds: 1         # 1s之后才会进行liveness的检测
      periodSeconds: 3               # 3s检测一次
[root@k8s-master-01 ~]# kubectl get pod
NAME                READY   STATUS    RESTARTS   AGE
liveness-exec-pod   1/1     Running   0          15s
[root@k8s-master-01 ~]# kubectl get pod -w
NAME                READY   STATUS             RESTARTS   AGE
liveness-exec-pod   0/1     CrashLoopBackOff   2          3m29s
liveness-exec-pod   1/1     Running            3          3m45s
liveness-exec-pod   0/1     Error              3          4m46s
liveness-exec-pod   0/1     CrashLoopBackOff   3          4m47s
# 已经重启了4[root@k8s-master-01 ~]# kubectl get pod 
NAME                READY   STATUS    RESTARTS   AGE
liveness-exec-pod   1/1     Running   4          6m2s

容器重启的方案默认RestartPolicy是always,即总是重启!

通过httpget的方案来实现存活检测:

# 因为防止端口冲突
[root@k8s-master-01 ~]# kubectl delete pod liveness-exec-pod
[root@k8s-master-01 ~]# vim liveness-httpget.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: liveness-httpget-pod
  namespace: default
spec:
  containers:
  - name: liveness-httpget-container
    image: hub.atguigu.com/library/myapp:v1
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80
    livenessProbe:
      httpGet:
        port: http               # http可以复用,也就是80   
        path: /index.html        # 检查能不能访问到index.html 
      initialDelaySeconds: 1
      periodSeconds: 3
      timeoutSeconds: 10
[root@k8s-master-01 ~]# kubectl create -f liveness-httpget.yaml 
[root@k8s-master-01 ~]# kubectl get pod -o wide
NAME                   READY   STATUS    RESTARTS   AGE    IP            NODE          NOMINATED NODE   READINESS GATES
liveness-httpget-pod   1/1     Running   0          2m3s   10.244.1.44   k8s-node-01   <none>           <none>
[root@k8s-master-01 ~]# curl 10.244.1.44
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
# 把文件删除
[root@k8s-master-01 ~]# kubectl exec liveness-httpget-pod -it -- /bin/sh
/ # rm -rf /usr/share/nginx/html/index.html 
/ # exit
# 可以看到重启次数变为2
[root@k8s-master-01 ~]# kubectl get pod -w
NAME                   READY   STATUS    RESTARTS   AGE
liveness-httpget-pod   1/1     Running   2          5m15s

通过tcp的方案来实现存活检测:

[root@k8s-master-01 ~]# vim liveness-tcp.yaml
apiVersion: v1
kind: Pod
metadata:
  name: probe-tcp
spec:
  containers:
  - name: nginx
    image: hub.atguigu.com/library/myapp:v1
    livenessProbe:
      initialDelaySeconds: 5
      timeoutSeconds: 1
      tcpSocket:
        port: 80
# 不指定端口也可以正常运行,和前面方案设置的80端口不冲突
[root@k8s-master-01 ~]# kubectl create -f liveness-tcp.yaml 
[root@k8s-master-01 ~]# kubectl get pod -o wide
NAME                   READY   STATUS    RESTARTS   AGE   IP            NODE          NOMINATED NODE   READINESS GATES
liveness-httpget-pod   1/1     Running   2          10m   10.244.1.44   k8s-node-01   <none>           <none>
probe-tcp              1/1     Running   0          38s   10.244.1.45   k8s-node-01   <none>           <none>
[root@k8s-master-01 ~]# kubectl get pod -w
NAME                   READY   STATUS    RESTARTS   AGE
liveness-httpget-pod   1/1     Running   2          16m
probe-tcp              1/1     Running   0          20s
probe-tcp              1/1     Running   1          30s
probe-tcp              1/1     Running   2          57s
probe-tcp              1/1     Running   3          88s

就绪检测和存活检测可以放在一起!就绪检测值是改状态,存活检测只要不是存活就退出容器!

7. 启动退出动作
[root@k8s-master-01 ~]# vim start_end.yaml
apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
spec:
  containers:
  - name: lifecycle-demo-container
    image: nginx
    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 postStop handler >/usr/share/message"]
[root@k8s-master-01 ~]# kubectl get pod lifecycle-demo -o wide
NAME             READY   STATUS    RESTARTS   AGE   IP            NODE          NOMINATED NODE   READINESS GATES
lifecycle-demo   1/1     Running   0          75s   10.244.1.47   k8s-node-01   <none>           <none>
[root@k8s-master-01 ~]# kubectl exec lifecycle-demo -it -- /bin/sh
# cat /usr/share/message
Hello from the postStart handler
# exit
8. Pod phase
8.1 Pod phase简介

Pod的status字段是一个PodStatus对象,PodStatus中有一个phase字段。Pod的相位(phase)是Pod在其生命周期中的简单宏观概述。该阶段并不是对容器或Pod的综合汇总,也不是为了做为综合状态机。Pod相位的数量和含义是严格指定的。除了本文中列举的状态外,不应该再假定Pod有其他的phase值。

8.2 Pod phase可能存在的值

挂起(Pending):Pod已被Kubernetes系统接受,但有一个或者多个容器镜像尚未创建。等待时间包括调度Pod的时间和通过网络下载镜像的时间,这可能需要花点时间

运行中(Running):该Pod已经绑定到了一个节点上,Pod中所有的容器都已被创建。至少有一个容器正在运行,或者正处于启动或重启状态

成功(Succeeded):Pod中的所有容器都被成功终止,并且不会再重启(显示在Job和CronJob中

失败(Failed):Pod中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出或者被系统终止(Pod中有很多容器,只要有一个容器是非正常退出状态就是Failed

未知(Unknown):因为某些原因无法取得Pod的状态,通常是因为与Pod所在主机通信失败

9. 重启策略

PodSpec中有一个restartPolicy字段,可能的值为Always、OnFailure和Never。默认为Always。restartPolicy适用于Pod中的所有容器。restartPolicy仅指通过同一节点上的kubelet重新启动容器。失败的容器由kubelet以五分钟为上限的指数退避延迟(10秒,20秒,40秒…)重新启动,并在成功执行十分钟后重置。如Pod文中所述,一旦绑定到一个节点,Pod将永远不会重新绑定到另一个节点。

10. Pod hook

Podhook(钩子)是由Kubernetes管理的kubelet发起的,当容器中的进程启动前或者容器中的进程终止之前运行,这是包含在容器的生命周期之中。可以同时为Pod中的所有容器都配置hook。Hook的类型包括两种:

exec:执行一段命令
HTTP:发送HTTP请求

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章