Kubernetes POD生命周期

Kubernetes POD生命周期

POD创建流程


在这里插入图片描述

kubectl命令 --> api server接收所有指令 --> etcd 存储所有组件的数据  -->  scheduler 进行调度计算 --> etcd 存储所有组件的数据 --> kubelet 客户端,接收创建任务


kuberctl 创建pod
使用资源清单创建pod

Master节点的API Server接收创建请求
将创建请求数据放入ETCD中
API server取出数据交给Scheduler
Scheduler资源计算,任务调度,将资源计算的数据放入ETCD中
API server取出计算后的数据,交给Controller
Controller根据资源,控制Node节点上的kubelet创建pod

kubelet接收到请求后,创建POD
首先要创建根容器
POD中的其它容器,通过container网络模式挂载到根容器上
kube-proxy提供网络服务

生命周期


在这里插入图片描述

## init container
初始化容器是指,在主容器启动之前,我们可以让他做一些准备工作。
比如:
1.两个容器做了共享存储,那么我们可以让它先启动一个容器,来对目录进行更改用户和授权
2.容器需要连接数据库,那么可以让初始化容器检测数据库是否可以正常连接,如果可以再启动主容器

## hook
PostStart:在容器启动创建后,立即执行,但时间不能太长,否则容器不会是running状态
PreStop:在容器停止前,执行一些命令,主要用于优雅关闭程序

## liveness probe
存活探针,用于定义容器内,应用是否满足探针指定状态

## readiness probe
就绪探针,指定何时允许容器进入流量

POD针对应用封装


那么我们在工作中,一个pod究竟要放几个容器?

在实际工作中我们除了完成任务以外还需要考虑以后扩容的问题,就拿wordpress举例,有以下两种方案:

第一种:全部放一个pod里,适用于个人网站,可扩展性不强,单点不安全
在这里插入图片描述

第二种:wordpress和MySQL分开
在这里插入图片描述

那么如何扩容呢?如果第一种方案大家会发现没有办法很好的扩容,因为数据库和wordpress已经绑定成一个整体了,扩容wordpress就得扩容mysql。而第二种方案就要灵活的多。
在这里插入图片描述

总结:数据库、redis等比较重要的容器最好单独独立出来,业务层面、应用层面可以在一起,具体一个pod内起多少容器是没有定数的,只能按业务划分

初始化容器


初始化容器完成了它的任务后就会退出,不会再占用资源

[root@db01 ~]$ vim init_nginx.yml 
apiVersion: v1
kind: Pod
metadata:
  name: nginx-init

spec:
  volumes:
  - name: nginx-index					 # //挂载路径被设置为nginx-index变量
    emptyDir: {}						# //emptyDir:被挂载的路径不在宿主机上,随机目录,容器关闭就会消失,临时的

  initContainers:						# initContainers:初始化容器,与containers语法一样,只是做的事情不同
  - name: init
    image: busybox
    imagePullPolicy: IfNotPresent
    args: [/bin/sh, -c, 'echo k8s >> /usr/share/nginx/html/index.html']		# //执行一个命令
    volumeMounts:
    - name: nginx-index
      mountPath: "/usr/share/nginx/html"								  # //将容器中目录挂载到指定共享目录

  containers:						    # //containers:容器
  - name: nginx
    image: nginx:alpine
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80
    volumeMounts:
    - name: nginx-index
      mountPath: "/usr/share/nginx/html"								  # //主容器的Index目录也挂共享目录


[root@db01 ~]$ kubectl apply -f  init_nginx.yml


## 验证一下初始化容器是否工作了
[root@db01 ~]$ curl 10.2.2.12
k8s					## //页面改变


## 只有一个容器,初始化容器完成任务后自动退出
[root@db01 ~]$ kubectl get pods -o wide
NAME         READY   STATUS    RESTARTS   AGE     IP          NODE   NOMINATED NODE   READINESS GATES
nginx-init   1/1     Running   0          4m42s   10.2.2.12   db02   <none>           <none>



## 查看一下我们利用emptyDir模式启动的挂载目录具体在哪
[root@db02 ~]$ docker ps
[root@db02 ~]$ docker inspect 32f78ce7442b|grep -i -A 5 mount
"Mounts": [
            {
                "Type": "bind",
                "Source": "/var/lib/kubelet/pods/c0464d82-c088-4e5a-afae-50b4c5e807ef/volumes/kubernetes.io~empty-dir/nginx-index",
                "Destination": "/usr/share/nginx/html",
                "Mode": "",

### Source:宿主机被挂载的临时目录
### Destination:容器挂载的目录
[root@db02 ~]$ cd /var/lib/kubelet/pods/c0464d82-c088-4e5a-afae-50b4c5e807ef/volumes/kubernetes.io~empty-dir/nginx-index

[root@db02 /var/lib/kubelet/pods/c0464d82-c088-4e5a-afae-50b4c5e807ef/volumes/kubernetes.io~empty-dir/nginx-index]$ cat index.html 
k8s


## 删除pod,验证临时目录是否还存在
[root@db01 ~]$ kubectl delete pods nginx-init
[root@db02 ~]$ ll /var/lib/kubelet/pods/c0464d82-c088-4e5a-afae-50b4c5e807ef/volumes/kubernetes.io~empty-dir/nginx-index
ls: cannot access /var/lib/kubelet/pods/c0464d82-c088-4e5a-afae-50b4c5e807ef/volumes/kubernetes.io~empty-dir/nginx-index: No such file or directory		# //不存在

hook钩子


PostStart启动钩子
apiVersion: v1
kind: Pod
metadata:
  name: nginx-hook

spec:
  containers:
  - name: nginx
    image: nginx:alpine
    lifecycle:			# //钩子
      postStart:		# //启动钩子,容器启动之前执行
        exec:			# //指定执行的是命令
          command: [/bin/sh, -c, 'echo PostStart > /usr/share/nginx/html/index.html']# //向nginx.index文件中插入数据
    ports:
    - containerPort: 80


[root@db01 ~]$ kubectl apply -f nginx_post.yml 

[root@db01 ~]$ kubectl get pods nginx-hook -o wide
NAME         READY   STATUS    RESTARTS   AGE   IP          NODE   NOMINATED NODE   READINESS GATES
nginx-hook   1/1     Running   0          25s   10.2.2.13   db02   <none>           <none>


## 测试一下启动钩子是否执行
[root@db01 ~]$ curl 10.2.2.13
PostStart

PreStop停止钩子
[root@db01 ~]$ vim nginx_pre.yml 
apiVersion: v1
kind: Pod
metadata:
  name: nginx-prestop
  
spec:
  volumes:
  - name: nginxlog				 # //宿主机被挂载目录设为变量
    hostPath:					 # //使用hostpath模式挂载,宿主机上存在此目录,且永久存在
      path: /var/log/nginx/		  # //指定被挂载的目录路径

  containers:
  - name: nginx
    image: nginx:alpine
    lifecycle:			# //钩子
      postStart:		# //启动钩子
        exec:			# //执行命令
          command: [/bin/sh, -c, 'echo postStart > /usr/share/nginx/html/index.html']
      preStop:			# //停止钩子
        exec:			# //执行命令
          command: [/bin/sh, -c, 'echo bye > /var/log/nginx/stop.log']	# //容器关闭后,将信息插入日志文件
    ports:
    - containerPort: 80

    volumeMounts:		# //容器挂载
    - name: nginxlog	# //挂载到宿主机共享目录
      mountPath: /var/log/nginx/


[root@db01 ~]$ kubectl apply -f nginx_pre.yml

[root@db01 ~]$ kubectl get pods nginx-prestop -o wide
NAME            READY   STATUS    RESTARTS   AGE   IP          NODE   NOMINATED NODE   READINESS GATES
nginx-prestop   1/1     Running   0          16s   10.2.2.14   db02   <none>           <none>


## 检测启动钩子
[root@db01 ~]$ curl 10.2.2.14		    # //有页面信息,启动钩子以执行
postStart

[root@db02 ~]$ ll /var/log/nginx/		# 宿主机没有停止钩子指定要操作的日志文件
-rw-r--r-- 1 root root   92 Nov 25 20:15 access.log
-rw-r--r-- 1 root root 1730 Nov 25 20:15 error.log


## 检测停止钩子
[root@db01 ~]$ kubectl delete pods nginx-prestop

[root@db02 ~]$ ll /var/log/nginx/
-rw-r--r-- 1 root root   92 Nov 25 20:15 access.log
-rw-r--r-- 1 root root 1730 Nov 25 20:15 error.log
-rw-r--r-- 1 root root    4 Nov 25 20:15 stop.log
[root@db02 ~]$ cat /var/log/nginx/stop.log 		# 原本不存在的日志文件被创建,且有信息
bye

存活探针


存活探针简单来说就是用来检测容器的应用程序是否还正常工作,如果应用程序不正常,即使容器还活着也没有意义了,所以这时候就可以使用存活探针来探测,如果应用程序不正常,就重启POD。

使用exec检测方法
apiVersion: v1
kind: Pod
metadata:
  name: liveness-pod
  
spec:
  volumes:
  - name: nginx-html
    hostPath:							# //使用hostpath模式挂载,宿主机上存在此目录,且永久存在
      path: /usr/share/nginx/html/		  # //指定被挂载的目录路径

  containers:
  - name: liveness
    image: nginx:alpine
    imagePullPolicy: IfNotPresent
    lifecycle:
      postStart:			# 利用启动钩子在容器启动前先往页面添加信息
        exec:
          command: [/bin/sh, -c, 'echo livenessProbe > /usr/share/nginx/html/index.html']

    livenessProbe:			# //存活探针
      exec:				    # //以命令方式
        command:
        - cat				# //查看这个页面
        - /usr/share/nginx/html/index.html
      initialDelaySeconds: 3	  # 第一次启动探测在容器启动后3秒开始
      periodSeconds: 1			 # 容器启动后每隔3秒检查一次

    volumeMounts:
    - name: nginx-html
      mountPath: /usr/share/nginx/html/


[root@db01 ~]$ kubectl apply -f lp_nginx.yml

[root@db01 ~]$ kubectl get pods -o wide
NAME           READY   STATUS    RESTARTS   AGE   IP          NODE   NOMINATED NODE   READINESS GATES
liveness-pod   1/1     Running   0          20s   10.2.2.17   db02   <none>           <none>


## 测试网页是存在的
[root@db01 ~]$ curl 10.2.2.17
livenessProbe

## 测试宿主机挂载点的页面也是存在的
[root@db02 ~]$ cat /usr/share/nginx/html/index.html 
livenessProbe


# 测试删除页面
[root@db02 ~]$ rm -rf /usr/share/nginx/html/index.html 

## 第一时间没有
[root@db02 ~]$ ll /usr/share/nginx/html/

## 容器被重启后再次生成
[root@db02 ~]$ ll /usr/share/nginx/html/
-rw-r--r-- 1 root root 14 Nov 25 20:48 index.html

# 查看pod详细信息
[root@db01 ~]$ kubectl describe pods liveness-pod

检测到文件不存在后,重启了容器
在这里插入图片描述

参数解释
livenessProbe:      # 存活探针
exec:			   # 执行命令
command:		   # 具体执行的命令及结果,结果为0的状态被视为存活,非零是不健康的
initialDelaySeconds: 3    # 第一次启动探测在容器启动后3秒开始,用于等待容器启动
periodSeconds: 1 	      # 容器启动后每隔1秒检查一次,默认为10秒,最小为一秒
使用Httpget方法检测
apiVersion: v1
kind: Pod
metadata:
  name: liveness-pod
  
spec:
  volumes:
  - name: nginx-html
    hostPath:
      path: /usr/share/nginx/html/

  containers:
  - name: liveness
    image: nginx:alpine
    imagePullPolicy: IfNotPresent
    
    lifecycle:
      postStart:				# 利用启动钩子在容器启动前先往页面添加信息
        exec:
          command: [/bin/sh, -c, 'echo GetHttp > /usr/share/nginx/html/index.html']

    livenessProbe:
      httpGet:
        path: /index.html		# 页面的uri,就是执行 curl 容器ip/index.html
        port: 80
      initialDelaySeconds: 3
      periodSeconds: 3

    volumeMounts:
    - name: nginx-html
      mountPath: /usr/share/nginx/html/


[root@db01 ~]$ kubectl apply -f lp_nginx.yml

[root@db01 ~]$ kubectl get pods liveness-pod -o wide
NAME           READY   STATUS    RESTARTS   AGE   IP          NODE   NOMINATED NODE   READINESS GATES
liveness-pod   1/1     Running   0          14s   10.2.2.18   db02   <none>           <none>

# 检测宿主机挂载页面
[root@db02 ~]$ cat /usr/share/nginx/html/index.html 
GetHttp

# 检查容器日志
[root@db01 ~]$ kubectl logs -f liveness-pod liveness

存活探针一直在用get请求方式curl页面。返回状态码200.页面正常
在这里插入图片描述

# 测试删除页面
[root@db02 ~]$ rm -rf /usr/share/nginx/html/index.html

# 查看pod详细信息
[root@db01 ~]$ kubectl describe pods liveness-pod

检测不到后端页面 404报错
在这里插入图片描述

检测不到页面后重启了pod
在这里插入图片描述

# 检测不到页面后会重启pod,再次访问一下页面,通了
[root@db01 ~]$ curl 10.2.2.18
GetHttp
参数解释
### 参数解释
livenessProbe:
httpGet: 			    # 基于http请求探测
path: /index.html 		 # 请求地址,如果这个地址返回的状态码在200-400之间正常
port: 80 				# 请求的端口
initialDelaySeconds: 3    # 第一次启动探测在容器启动后3秒开始,用于等待容器启动
periodSeconds: 3 	     # 容器启动后每隔3秒检查一次,默认为10秒,最小为一秒


tcpsocket:				# 通过socket连接检测,可以用来检测mysql
host:					# 检测指定IP
port:					# 检测指定端口

就绪探针


有时候我们Pod本身已经起来了,但是pod的容器还没有完全准备好对外提供服务,那么这时候流量进来就会造成请求失败的情况出现,针对这种情况k8s有一种探针叫就绪探针,他的作用就是让k8s知道你的Pod内应用是否准备好为请求提供服务。只有就绪探针ok了才会把流量转发到pod上。


有时候,应用程序会暂时性的不能提供通信服务。 例如,应用程序在启动时可能需要加载很大的数据或配置文件,或是启动后要依赖等待外部服务。 在这种情况下,既不想杀死应用程序,也不想给它发送请求。 Kubernetes 提供了就绪探测器来发现并缓解这些情况。 容器所在 Pod 上报还未就绪的信息,并且不接受通过 Kubernetes Service 的流量。
使用就绪探针
apiVersion: v1
kind: Pod
metadata:
  name: readiness-pod
spec:
  containers:
  - name: readiness-pod
    image: nginx
    
    lifecycle:					    # //钩子
      postStart:					# //启动钩子
        exec:
          command: ["/bin/sh", "-c", "echo ok > /usr/share/nginx/html/health.html"]
          
    readinessProbe:					# //就绪探针
      httpGet:					    # //使用httpGet方式
        path: /actuator/health		 # 检测此页面url,通过8080端口
        port: 8080
      initialDelaySeconds: 5		 # 第一次启动探测在容器启动后5秒开始
      timeoutSeconds: 3				 # 探针超时时间
      periodSeconds: 3				 # 容器启动后每隔3秒检查一次
      successThreshold: 3
      failureThreshold: 3
      
    livenessProbe:					# //存活探针
      httpGet:
        path: /health.html			 # 页面的url,就是执行 curl 容器ip/index.html
        port: 80
      initialDelaySeconds: 3
      periodSeconds: 3


[root@db01 ~]$ kubectl apply -f rp_nginx.yml 

# pod内没有容器启动成功
[root@db01 ~]$ kubectl get pods readiness-pod -o wide
NAME            READY   STATUS    RESTARTS   AGE   IP          NODE   NOMINATED NODE   READINESS GATES
readiness-pod   0/1     Running   0          27s   10.2.2.19   db02   <none>           <none>


# 查看pod详细信息
[root@db01 ~]$ kubectl describe pods readiness-pod
8080端口不通,容器不会被启动

在这里插入图片描述

# 测试直接curl页面
[root@db01 ~]$ curl 10.2.2.19/health.html		# //发现能够访问,按理容器都没启动不应该能访问到才对
ok

##### 注意:只会限制通过 Kubernetes Service 的流量,而我们是通过pod ip 访问的
参数解释
initialDelaySeconds: 5    # 第一次启动探测在容器启动后5秒开始,用于等待容器启动
periodSeconds: 3 	      # 容器启动后每隔3秒检查一次,默认为10秒,最小为一秒
timeoutSeconds: 3		  # 探针超时时间,默认一秒,最小一秒
successThreshold: 3		   # 探针失败后最少连续探测成功多少次才被认定为探测成功,默认一次,如果是liveness必须为1
failureThreshold: 3		   # 探针成功后被视为失败的探测的最小连续失败次数,默认3次最小一次

POD资源限制


在学习Docker的时候我们知道容器可以使用Linux系统的CGroup技术限制内存和CPU的使用率,那么POD里应该如何限制容器的CPU和内存资源呢?

[root@db01 ~]$ kubectl apply -f mem_cpu.yml
apiVersion: v1
kind: Pod
metadata:
  name: resource-demo
spec:
  containers:
  - name: resource-demo
    image: nginx
    ports:
    - containerPort: 80
    resources:				# //资源限制
      requests:				# //启动该容器所需的资源
        memory: 50Mi		 # //50m的内存
        cpu: 1500m			 # //1500毫核的CPU
      limits:				# //启动该容器限制最大能使用的资源
        memory: 100Mi
        cpu: 2000m

[root@db01 ~]$ kubectl apply -f mem_cpu.yml

[root@db01 ~]$ kubectl get pods resource-demo -o wide
NAME            READY   STATUS    RESTARTS   AGE   IP          NODE   NOMINATED NODE   READINESS GATES
resource-demo   1/1     Running   0          30s   10.2.2.20   db02   <none>           <none>


[root@db02 ~]$ docker ps
[root@db02 ~]$ docker inspect 9c99fb3ed4de|grep CgroupParent
            "CgroupParent": "kubepods-burstable-podda791c6f_90dd_4b4c_89a4_63359ba0f830.slice", # //此目录记录资源限制信息
参数解释:
requests :节点所需的最小计算资源量,k8s调度的时候的依据值
limits :限制允许的最大计算资源量,真正的资源限制参数

## 限制的资源数必须比需求的资源数大

数值的转换:
1 CPU = 1000m
0.5 CPU = 500m

1 Mib = 1024 Kib
1 MB = 1000 KB

查看验证:
docker inspect 容器ID|grep CgroupParent

## 后缀填上面查找到的存放资源路径
cd /sys/fs/cgroup/cpu/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-poddaxxxxxxxxxxxxxxxxxxxx.slice
cat cpu.cfs_quota_us
200000

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值