目录
一、概述
Pod 是 Kubernetes 中最小的调度和管理单位,它代表着集群中运行的一个或多个容器实例。在一个 Pod 中,所有容器共享相同的网络命名空间、历程命名空间和存储卷,因此它们可以互相通信和共享数据。Pod 可以通过控制器进行创建、扩缩容和更新等操作。
二、Pod的根本操作
1、创建Pod
1.1、命令行方式启动
- kubectl create deploy (pod控制器名称) [参数]
复制代码- kubectl create deploy nginx-deployment01 --image=nginx --port=8088 -n dev1
- deployment.apps/nginx-deployment created
复制代码
–-image 指定Pod的镜像
–port 指定端口
–n 指定namespace
1.2、创建Deployment资源清单启动
nginx-deployment02.yaml
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- name: nginx-deployment02
- namespace: dev2
- labels:
- chapter: first-app
- function: test
- spec:
- selector:
- matchLabels:
- app: nginx
- replicas: 1
- template:
- metadata:
- labels:
- app: nginx
- spec:
- containers:
- - name : nginx02
- image: nginx
- ports:
- - containerPort: 8081
复制代码- kubectl apply -f nginx-deployment02.yaml
- deployment.apps/nginx-deployment02 created
复制代码
1.3、直接创建Pod(资源清单)
- apiVersion: v1
- kind: Pod
- metadata:
- name: nginx03
- namespace: dev3
- labels:
- function: test
- app: nginx
- spec:
- containers:
- - image: nginx:latest
- name: pod
- ports:
- - name: nginx-port
- containerPort: 80
- protocol: TCP
复制代码- kubectl apply -f pod-nginx03.yaml
- pod/nginx03 created
复制代码
1.4、直接创建(kubectl run)
- kubectl run pod nginx04 --image=nginx -n dev4
复制代码
2、查询
2.1、查询指定命名空间下所有的Pod
- kubectl get pod -n <namespace>
复制代码 2.2、查询指定Pod的信息
- kubectl get pods <pod_name> -n <namespace>
复制代码 2.3、对Pod状态进行及时监控
- kubectl get pods -n <namespace> -w
复制代码 2.4、格式化输出
- kubectl get pods -n <namespace> -o json|yaml|name|go-template|go-template-file|template|templatefile|jsonpath|jsonpath-as-json|jsonpath-file|custom-columns-file|custom-columns|wide
复制代码 2.5、显示详细信息(包括Events)
- kubectl describe pods <pod_name> -n <namespace>
复制代码 2.6、查看Pod的日志信息
- kubectl logs <pod_name> -n <namespace>
复制代码 2.7、显示Pod的对应标签
- kubectl get pod <pod_name> -n <namespace> --show-labels
复制代码 3、修改Pod
3.1、修改已存在的Pod属性(不是由控制器创建的)
- kubectl replcae -f <createpods.yaml>
复制代码前提是Pod不是由更高级别的控制器(如Deployment)管理的。
cp pod-nginx03.yaml replcae-pod-nginx03.yaml && vim replcae-pod-nginx03.yaml
- apiVersion: v1
- kind: Pod
- metadata:
- name: nginx03
- namespace: dev3
- labels:
- function: replace
- app: nginx
- spec:
- containers:
- - image: nginx:latest
- name: pod
- command: ["sh", "-c", "echo 'Hello Kubernetes replaced!'; sleep 3600"]
- ports:
- - name: nginx-port
- containerPort: 80
- protocol: TCP
复制代码- kubectl replace -f replcae-pod-nginx03.yaml --force
复制代码
#Pod有很多属性是无法修改的,如果肯定要修改,需要加上 --force 参数,相当于重修 Pod
- kubectl logs nginx03 -n dev3
复制代码
3.2、修改已存在的Pod属性(由控制器创建的)
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- name: nginx-deployment02
- namespace: dev2
- labels:
- chapter: first-app
- function: test
- spec:
- selector:
- matchLabels:
- app: nginx
- replicas: 1
- template:
- metadata:
- labels:
- app: nginx
- spec:
- containers:
- - name : nginx02
- image: nginx
- ports:
- - containerPort: 8081
复制代码- apiVersion: apps/v1
- kind: Deployment
- metadata:
- name: nginx-deployment02
- namespace: dev2
- labels:
- chapter: first-app
- function: test
- spec:
- selector:
- matchLabels:
- app: nginx
- replicas: 1
- template:
- metadata:
- labels:
- app: nginx
- spec:
- containers:
- - name : nginx02
- image: nginx
- ports:
- - containerPort: 8081 command: ["sh", "-c", "echo 'Hello Kubernetes updated!'; sleep 3600"]
复制代码- kubectl apply -f nginx-deployment02.yaml
复制代码
3.3、edit在线编辑
- kubectl edit nginx-deployment02-58759c87cb-dvg62 -n dev2
复制代码:wq生存退出后也可以到达更新的效果
4、删除Pod
4.1、未经Deployment创建的Pod
- kubectl delete <pod_name> -n <namespace>
复制代码
4.2、通过Deployment创建的Pod
- kubectl delete -f <createpods.yaml>
复制代码
二、Pod的生命周期
1、Pod的状态
我们可以通过 kubectl explain pod.status 命令来了解关于 Pod 状态的一些信息
Pod 的状态界说在 PodStatus 对象中,此中有一个 phase 字段,下面是 phase 的可能取值:
- 挂起(Pending):Pod 信息已经提交给了集群,但是还没有被调度器调度到符合的节点大概 Pod 里的镜像正在下载
- 运行中(Running):该 Pod 已经绑定到了一个节点上,Pod 中所有的容器都已被创建。至少有一个容器正在运行,大概正处于启动或重启状态
- 乐成(Succeeded):Pod 中的所有容器都被乐成终止,并且不会再重启
- 失败(Failed):Pod 中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出大概被系统终止
- 未知(Unknown):因为某些原因无法取得 Pod 的状态,通常是因为与 Pod 地点主机通信失败导致的
除此之外,PodStatus 对象中还包罗一个 PodCondition 的数组,里面包罗的属性有:
- lastProbeTime:末了一次探测 Pod Condition 的时间戳。
- lastTransitionTime:上次 Condition 从一种状态转换到另一种状态的时间。
- message:上次 Condition 状态转换的详细形貌。
- reason:Condition 末了一次转换的原因。
- status:Condition 状态类型,可以为 “True”, “False”, and “Unknown”.
- type:Condition 类型,包括以下方面:
- PodScheduled(Pod 已经被调度到其他 node 里)
- Ready(Pod 能够提供服务哀求,可以被添加到所有可匹配服务的负载平衡池中)
- Initialized(所有的init containers已经启动乐成)
- Unschedulable(调度程序如今无法调度 Pod,例如由于缺乏资源或其他限定)
- ContainersReady(Pod 里的所有容器都是 ready 状态)
2、重启策略
我们可以通过设置restartPolicy字段来设置 Pod 中所有容器的重启策略,其可能值为Always,OnFailure 和 Never,默认值为 Always。restartPolicy 仅指通过 kubelet 在同一节点上重新启动容器。通过 kubelet 重新启动的退出容器将以指数增加延迟(10s,20s,40s…)重新启动,上限为 5 分钟,并在乐成执行 10 分钟后重置。不同类型的的控制器可以控制 Pod 的重启策略:
- Job:实用于一次性任务如批量盘算,任务结束后 Pod 会被此类控制器扫除。Job 的重启策略只能是"OnFailure"大概"Never"。
- Replication Controller, ReplicaSet, or Deployment,此类控制器希望 Pod 一直运行下去,它们的重启策略只能是"Always"。
- DaemonSet:每个节点上启动一个 Pod,很明显此类控制器的重启策略也应该是"Always"。
3、初始化容器
了解了 Pod 状态后,起首来了解下 Pod 中最新启动的 Init Container,也就是我们平时常说的初始化容器。Init Container就是用来做初始化工作的容器,可以是一个大概多个,如果有多个的话,这些容器会按界说的顺序依次执行。我们知道一个 Pod 里面的所有容器是共享数据卷和Network Namespace 的,以是Init Container里面产生的数据可以被主容器利用到。从上面的 Pod 生命周期的图中可以看出初始化容器是独立与主容器之外的,只有所有的初始化容器执行完之后,主容器才会被启动。那么初始化容器有哪些应用场景呢:
- 等待其他模块 Ready:这个可以用来办理服务之间的依靠题目,比如我们有一个 Web 服务,该服务又依靠于另外一个数据库服务,但是在我们启动这个 Web 服务的时候我们并不能保证依靠的这个数据库服务就已经启动起来了,以是可能会出现一段时间内 Web 服务毗连数据库异常。要办理这个题目的话我们就可以在 Web 服务的 Pod 中利用一个 InitContainer,在这个初始化容器中去检查数据库是否已经预备好了,预备好了过后初始化容器就结束退出,然后我们主容器的 Web 服务才被启动起来,这个时候去毗连数据库就不会有题目了。
- 做初始化设置:比如集群里检测所有已经存在的成员节点,为主容器预备好集群的设置信息,如许主容器起来后就能用这个设置信息加入集群。
- 其它场景:如将 Pod 注册到一个中央数据库、设置中心等。
比如如今我们来实现一个功能,在 Nginx Pod 启动之前往重新初始化首页内容,如下所示的资源清单
init-pod.yaml
- apiVersion: v1
- kind: Pod
- metadata:
- name: init-demo
- spec:
- volumes:
- - name: workdir
- emptyDir: {}
- initContainers:
- - name: install
- image: busybox
- command:
- - wget
- - "-O"
- - "/work-dir/index.html"
- - http://www.baidu.com
- volumeMounts:
- - name: workdir
- mountPath: "/work-dir"
- containers:
- - name: nginx
- image: nginx
- ports:
- - containerPort: 80
- volumeMounts:
- - name: workdir
- mountPath: /usr/share/nginx/html
复制代码上面的资源清单中我们起首在 Pod 顶层声明白一个名为 workdir 的 Volume,前面我们用了 hostPath 的模式,这里我们利用的是 emptyDir{},这个是一个临时的目录,数据会生存在 kubelet 的工作目录下面,生命周期等同于 Pod 的生命周期。
然后我们界说了一个初始化容器,该容器会下载一个 html 文件到 /work-dir 目录下面,但是由于我们又将该目录声明挂载到了全局的 Volume,同样的主容器 nginx 也将目录 /usr/share/nginx/html 声明挂载到了全局的 Volume,以是在主容器的该目录下面会同步初始化容器中创建的 index.html 文件。
- kubectl apply -f init-pod.yaml
复制代码
- kubectl get pods -n default
复制代码
可以发现 Pod 如今的状态处于 Init:0/1 状态,意思就是如今第一个初始化容器还在执行过程中
- kubectl describe pods init-demo -n default
复制代码- Name: init-demo
- Namespace: default
- Priority: 0
- Node: k8s-node2/192.168.112.60
- Start Time: Thu, 18 Jul 2024 23:53:56 +0800
- Labels: <none>
- Annotations: <none>
- Status: Pending
- IP: 10.244.2.41
- IPs:
- IP: 10.244.2.41
- Init Containers:
- install:
- Container ID: docker://d7ab75ce40d80daa676a547482ee32eba9f2488a9c791051fb5aa5ddcfbcc5b1
- Image: busybox
- Image ID: docker-pullable://busybox@sha256:5acba83a746c7608ed544dc1533b87c737a0b0fb730301639a0179f9344b1678
- Port: <none>
- Host Port: <none>
- Command:
- wget
- -O
- /work-dir/index.html
- http://www.baidu.com
- State: Terminated
- Reason: Completed
- Exit Code: 0
- Started: Thu, 18 Jul 2024 23:56:21 +0800
- Finished: Thu, 18 Jul 2024 23:56:24 +0800
- Ready: True
- Restart Count: 0
- Environment: <none>
- Mounts:
- /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-2kmc4 (ro)
- /work-dir from workdir (rw)
- Containers:
- nginx:
- Container ID:
- Image: nginx
- Image ID:
- Port: 80/TCP
- Host Port: 0/TCP
- State: Waiting
- Reason: PodInitializing
- Ready: False
- Restart Count: 0
- Environment: <none>
- Mounts:
- /usr/share/nginx/html from workdir (rw)
- /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-2kmc4 (ro)
- Conditions:
- Type Status
- Initialized True
- Ready False
- ContainersReady False
- PodScheduled True
- Volumes:
- workdir:
- Type: EmptyDir (a temporary directory that shares a pod's lifetime)
- Medium:
- SizeLimit: <unset>
- kube-api-access-2kmc4:
- Type: Projected (a volume that contains injected data from multiple sources)
- TokenExpirationSeconds: 3607
- ConfigMapName: kube-root-ca.crt
- ConfigMapOptional: <nil>
- DownwardAPI: true
- QoS Class: BestEffort
- Node-Selectors: <none>
- Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
- node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
- Events:
- Type Reason Age From Message
- ---- ------ ---- ---- -------
- Normal Scheduled 2m49s default-scheduler Successfully assigned default/init-demo to k8s-node2
- Warning Failed 64s kubelet Failed to pull image "busybox": rpc error: code = Unknown desc = Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: TLS handshake timeout
- Warning Failed 64s kubelet Error: ErrImagePull
- Normal BackOff 63s kubelet Back-off pulling image "busybox"
- Warning Failed 63s kubelet Error: ImagePullBackOff
- Normal Pulling 51s (x2 over 2m49s) kubelet Pulling image "busybox"
- Normal Pulled 25s kubelet Successfully pulled image "busybox" in 26.135324609s
- Normal Created 25s kubelet Created container install
- Normal Started 25s kubelet Started container install
- Normal Pulling 21s kubelet Pulling image "nginx"
复制代码 从上面的形貌信息里面可以看到初始化容器已经启动了,如今处于 Running 状态,以是还需要稍等,到初始化容器执行完成后退出初始化容器会变成 Completed 状态,然后才会启动主容器。待到主容器也启动完成后,Pod 就会变成Running 状态
- 然后我们去访问下 Pod 主页,验证下是否有我们初始化容器中下载的页面信息:
4、pod hook
我们知道 Pod 是 Kubernetes 集群中的最小单位,而 Pod 是由容器构成的,以是在讨论 Pod 的生命周期的时候我们可以先来讨论下容器的生命周期。
实际上 Kubernetes 为我们的容器提供了生命周期的钩子,就是我们说的Pod Hook,Pod Hook 是由 kubelet 发起的,当容器中的历程启动前大概容器中的历程终止之前运行,这是包罗在容器的生命周期之中。我们可以同时为 Pod 中的所有容器都设置 hook。
4.1、两种钩子函数
Kubernetes 为我们提供了两种钩子函数:
- PostStart:这个钩子在容器创建后立即执行。但是,并不能保证钩子将在容器 ENTRYPOINT 之前运行,因为没有参数传递给处理程序。重要用于资源部署、环境预备等。不过需要注意的是如果钩子耗费太长时间以至于不能运行大概挂起,容器将不能到达 running 状态。
- PreStop:这个钩子在容器终止之前立即被调用。它是阻塞的,意味着它是同步的,以是它必须在删除容器的调用发出之前完成。重要用于优雅关闭应用程序、关照其他系统等。如果钩子在执行期间挂起,Pod 阶段将停顿在 running 状态并且永不会到达 failed 状态。
如果 PostStart 大概 PreStop 钩子失败, 它会杀死容器。以是我们应该让钩子函数尽可能的轻量。当然有些情况下,长时间运行命令是合理的, 比如在克制容器之前预先生存状态。
4.2、两种实现方式
- Exec - 用于执行一段特定的命令,不过要注意的是该命令消耗的资源会被计入容器。
- HTTP - 对容器上的特定的端点执行 HTTP 哀求。
4.3、PostStart钩子函数
以下示例中,界说了一个 Nginx Pod,此中设置了 PostStart 钩子函数,即在容器创建乐成后,写入一句话到 /usr/share/message 文件中:
pod-poststart.yaml
- apiVersion: v1
- kind: Pod
- metadata:
- name: hook-demo1
- spec:
- containers:
- - name: hook-demo1
- image: nginx
- lifecycle:
- postStart:
- exec:
- command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
复制代码- kubectl apply -f pod-poststart.yaml
-
- kubectl get pods
-
- NAME READY STATUS RESTARTS AGE
- hook-demo1 1/1 Running 0 43s
复制代码
- 创建乐成后查看容器中的 /usr/share/message 文件是否内容精确
4.4.、PreStop钩子函数
当用户哀求删除含有 Pod 的资源对象时(如 Deployment 等),K8S 为了让应用程序优雅关闭(即让应用程序完成正在处理的哀求后,再关闭软件),K8S 提供两种信息关照:
- 默认:K8S 关照 node 执行docker stop命令,docker 会先向容器中 PID 为 1 的历程发送系统信号SIGTERM,然后等待容器中的应用程序终止执行,如果等待时间到达设定的超时时间,大概默认超时时间(30s),会继承发送SIGKILL的系统信号强行 kill 掉历程
- 利用 Pod 生命周期(利用PreStop回调函数),它在发送终止信号之前执行默认所有的优雅退出时间都在30秒内。kubectl delete 命令支持 --grace-period=选项,这个选项允许用户用他们自己指定的值覆盖默认值。值'0'代表强制删除 pod。 在 kubectl 1.5 及以上的版本里,执行强制删除时必须同时指定 --force --grace-period=0。
强制删除一个 pod 是从集群状态还有 etcd 里立刻删除这个 pod,只是当 Pod 被强制删除时, APIServer 不会等待来自 Pod 地点节点上的 kubelet 的确认信息:pod 已经被终止。在 API 里 pod 会被立刻删除,在节点上, pods 被设置成立刻终止后,在强行杀掉前还会有一个很小的宽限期。
以下示例中,界说了一个 Nginx Pod,此中设置了PreStop钩子函数,即在容器退出之前,优雅的关闭 Nginx
pod-prestop.yaml
- apiVersion: v1
- kind: Pod
- metadata:
- name: hook-demo2
- spec:
- containers:
- - name: hook-demo2
- image: nginx
- lifecycle:
- preStop:
- exec:
- command: ["/usr/sbin/nginx","-s","quit"] # 优雅退出
-
- ---
- apiVersion: v1
- kind: Pod
- metadata:
- name: hook-demo3
- spec:
- volumes:
- - name: message
- hostPath:
- path: /tmp
- containers:
- - name: hook-demo2
- image: nginx
- ports:
- - containerPort: 80
- volumeMounts:
- - name: message
- mountPath: /usr/share/
- lifecycle:
- preStop:
- exec:
- command: ['/bin/sh', '-c', 'echo Hello from the preStop Handler > /usr/share/message']
复制代码 上面界说的两个 Pod,一个是利用 preStop 来进行优雅删除,另外一个是利用 preStop 来做一些信息记录的事情
- kubectl apply -f pod-prestop.yaml
复制代码
- kubectl get pods |grep ^hook
复制代码
创建完成后,我们可以直接删除 hook-demo2 这个 Pod,在容器删除之前会执行 preStop 里面的优雅关闭命令,这个用法在后面我们的滚动更新的时候用来保证我们的应用零宕机非常有用。
第二个 Pod 我们声明白一个 hostPath 类型的 Volume,在容器里面声明挂载到了这个 Volume,以是当我们删除 Pod,退出容器之前,在容器里面输出的信息也会同样的生存到宿主机(肯定要是 Pod 被调度到的目标节点)的 /tmp 目录下面
- 查看 hook-demo3 这个 Pod 被调度的节点
- kubectl describe pods hook-demo3
复制代码
可以看到这个 Pod 被调度到了 k8s-node1 这个节点上,我们可以先到该节点上查看 /tmp 目录下面现在没有想要的内容:
- kubectl delete pod hook-demo3
复制代码
如今我们来删除 hook-demo3 这个 Pod,安装我们的设定在容器退出之前会执行 preStop 里面的命令,也就是会往 message 文件中输出一些信息
另外 Hook 调用的日志没有暴露个给 Pod,以是只能通过 describe 命令来获取,如果有错误将可以看到 FailedPostStartHook 或 FailedPreStopHook 如许的 event。
三、Pod健康检查
在Kubernetes中,Pod健康检查是通过利用探针(probes)来实现的,这些探针用于确定Pod中的容器是否处于健康状态。健康检查机制允许Kubernetes系统在容器出现题目时做出相应,例如重启容器或从服务路由中移除容器。
1、Kubernetes中三种重要的探针类型
1.1、存活探针(Liveness Probes)
存活探针用于检查容器是否正在运行并相应。如果存活探针失败,Kubernetes将根据Pod的restartPolicy重启容器。这通常用于检测应用程序的崩溃或陷入死锁的情况。存活探针可以设置为以下几种类型:
- HTTP GET:对容器的 IP 地址上指定端口和路径执行 HTTP GET 哀求。如果相应的状态码大于即是 200 且小于 400,则诊断被认为是乐成的。
- TCP Socket:对容器的 IP 地址上的指定端口执行 TCP 检查。如果端口打开,则诊断被认为是乐成的。 如果远程系统(容器)在打开毗连后立即将其关闭,这算作是健康的。
- Exec:在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断乐成。
- gRPC:利用 gRPC 执行一个远程过程调用。 目标应该实现 gRPC 健康检查。 如果相应的状态是 "SERVING",则认为诊断乐成。
1.2、 就绪探针(Readiness Probes)
就绪探针用于确认容器是否预备好接收流量。如果就绪探针失败,Kubernetes将不会把该Pod视为服务的活动实例,这意味着不会将网络流量路由到该Pod。一旦就绪探针开始乐成,Pod将开始接收流量。就绪探针可以是以下几种类型:
- HTTP GET
- TCP Socket
- Exec
- gRPC
1.3、启动探针(Startup Probes)
启动探针用于检测容器是否已启动并运行。在启动探针乐成之前,其他探针(如存活探针和就绪探针)不会执行。这有助于避免在容器初始化阶段错误地重启或标记容器未预备好。启动探针同样可以设置为:
- HTTP GET
- TCP Socket
- Exec
- gRPC
2、探针设置参数
探针设置包罗几个重要的参数:
- initialDelaySeconds:探针开始执行前等待的秒数。
- periodSeconds:探针执行之间的间隔秒数。
- timeoutSeconds:探针执行超时秒数。
- successThreshold:连续乐成多少次后探针被认为是乐成的。
- failureThreshold:连续失败多少次后探针被认为是失败的。
3、探针状态
探针的结果可以是:
- Success:容器通过了探针的检查。
- Failure:容器没有通过探针的检查。
- Unknown:探针执行失败或未知状态,此时不接纳任何举措,kubelet会继承检查。
4、示例(存活探针--exec)
用 exec 执行命令的方式来检测容器的存活
4.1、编写资源清单
liveness-exec.yaml
- apiVersion: v1
- kind: Pod
- metadata:
- name: liveness-exec
- spec:
- containers:
- - name: liveness
- image: busybox
- args:
- - /bin/sh
- - -c
- - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
- livenessProbe:
- exec:
- command:
- - cat
- - /tmp/healthy
- initialDelaySeconds: 5
- periodSeconds: 5
复制代码
- periodSeconds:表示让 kubelet 每隔5秒执行一次存活探针,也就是每5秒执行一次上面的cat /tmp/healthy命令,如果命令执行乐成了,将返回0,那么 kubelet 就会认为当前这个容器是存活的,如果返回的是非0值,那么 kubelet 就会把该容器杀掉然后重启它。默认是10秒,最小1秒。
- initialDelaySeconds:表示在第一次执行探针的时候要等待5秒,如许能够确保我们的容器能够有充足的时间启动起来。大家可以想象下,如果你的第一次执行探针等候的时间太短,是不是很有可能容器还没正常启动起来,以是存活探针很可能始终都是失败的,如许就会无休止的重启下去了
4.2、.spec.containers.args
我们在容器启动的时候,执行了如下命令:
- /bin/sh -c "touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600"
复制代码 意思是说在容器最开始的30秒内创建了一个/tmp/healthy文件,在这30秒内执行cat /tmp/healthy命令都会返回一个乐成的返回码。30 秒后,我们删除这个文件,如今执行cat /tmp/healthy是不是就会失败了(默认检测失败3次才认为失败),以是这个时候就会重启容器了。
4.3、创建该pod
- kubectl apply -f liveness-exec.yaml
复制代码 4.4、查看Pod的Event
- kubectl describe pod liveness-exec
复制代码
我们可以观察到容器是正常启动的,在隔一会儿,再查看下 Pod 的 Event,在最下面有一条信息显示 liveness probe 失败了,容器将要重启。然后可以查看到 Pod 的 RESTARTS 值加 1 了:- kubectl get pods|grep ^live
复制代码
5、示例(存活探针--HTTP GET)
5.1、编写资源清单
- apiVersion: v1
- kind: Pod
- metadata:
- name: liveness-http
- spec:
- containers:
- - name: liveness
- image: cnych/liveness
- args:
- - /server
- livenessProbe:
- httpGet:
- path: /healthz
- port: 8080
- httpHeaders:
- - name: X-Custom-Header
- value: Awesome
- initialDelaySeconds: 3
- periodSeconds: 3
复制代码 同样的,根据 periodSeconds 属性我们可以知道 kubelet 需要每隔3秒执行一次 liveness Probe,该探针将向容器中的 server 的 8080 端口发送一个 HTTP GET 哀求。如果 server 的 /healthz 路径的 handler 返回一个乐成的返回码,kubelet 就会认定该容器是在世的并且很健康,如果返回失败的返回码,kubelet 将杀掉该容器并重启它。initialDelaySeconds 指定kubelet 在该执行第一次探测之前需要等待3秒钟。
通常来说,任何大于200小于400的状态码都会认定是乐成的返回码。其他返回码都会被认为是失败的返回码。
四、Pod资源设置
实际上上面几个步骤就是影响一个 Pod 生命周期的大的部分,但是还有一些细节也会在 Pod 的启动过程进行设置,比如在容器启动之前还会为当前的容器设置分配的 CPU、内存等资源,我们知道我们可以通过 CGroup 来对容器的资源进行限定,同样的,在 Pod 中我们也可以直接设置某个容器的利用的 CPU 大概内存的上限。那么 Pod 是怎样来利用和控制这些资源的分配的呢?
起首对于 CPU,我们知道盘算机里 CPU 的资源是按“时间片”的方式来进行分配的,系统里的每一个操作都需要 CPU 的处理,以是,哪个任务要是申请的 CPU 时间片越多,那么它得到的 CPU 资源就越多。
1、CGroup 里面对于 CPU 资源的单位换算
- 1 CPU = 1000 millicpu(1 Core = 1000m)
-
- 0.5 CPU = 500 millicpu (0.5 Core = 500m)
复制代码 这里的 m 就是毫、毫核的意思,Kubernetes 集群中的每一个节点可以通过操作系统的命令来确认本节点的 CPU 内核数量,然后将这个数量乘以1000,得到的就是节点总 CPU 总毫数。比如一个节点有四核,那么该节点的 CPU 总毫量为 4000m,如果你要利用0.5 core,则你要求的是 4000*0.5 = 2000m。在 Pod 里面我们可以通过下面的两个参数来如今和哀求 CPU 资源:
- spec.containers[].resources.limits.cpu:CPU 上限值,可以短暂超过,容器也不会被克制
- spec.containers[].resources.requests.cpu:CPU哀求值,Kubernetes 调度算法里的依据值,可以超过
这里需要明白的是,如果resources.requests.cpu设置的值大于集群里每个节点的最大 CPU 核心数,那么这个 Pod 将无法调度,因为没有节点能满足它。
到这里应该明白了,requests 是用于集群调度利用的资源,而 limits 才是真正的用于资源限定的设置,如果你需要保证的你应用优先级很高,也就是资源吃紧的情况下末了再杀掉你的 Pod,那么你就把你的 requests 和 limits 的值设置成一致。
2、创建容器的资源清单
2.1、编写资源清单
pod-resource-demo1.yaml
- apiVersion: v1
- kind: Pod
- metadata:
- name: resource-demo1
- spec:
- containers:
- - name: resource-demo1
- image: nginx
- ports:
- - containerPort: 80
- resources:
- requests:
- memory: 50Mi
- cpu: 50m
- limits:
- memory: 100Mi
- cpu: 100m
复制代码 这里,CPU 我们给的是 50m,也就是 0.05core,这 0.05 core 也就是占了 1 CPU 里的 5% 的资源时间。而限定资源是给的是 100m,但是需要注意的是 CPU 资源是可压缩资源,也就是容器到达了这个设定的上限后,容器性能会降落,但是不会终止或退出。
2.2、创建该Pod
- kubectl apply -f pod-resource-demo1.yaml
复制代码
2.3、查看被调度到的节点
- kubectl get pods resource-demo1 -o wide
复制代码
可以看到Pod被调度到k8s-node2这个节点上了
2.4、查看Pod里的容器
- docker ps |grep resource-demo1
复制代码
此中第一个容器就是我们的主容器,第二容器是 Infra 容器
2.5、查看主容器的信息
- docker inspect 78638fd35d88
复制代码
实际上我们就可以看到这个容器的一些资源情况,Pod 上的资源设置终极也还是通过底层的容器运行时去控制 CGroup 来实现的,我们可以进入对应目录查看 CGroup 的设置,该目录就是 CGroup 父级目录,而 CGroup 是通过文件系统来进行资源限定的,以是我们上面限定容器的资源就可以在该目录下面反映出来:
截图里CgroupParent对应的目录名
- cd /sys/fs/cgroup/cpu/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-poda77b9886_5413_4368_8ee0_5e4c153c8d01.slice
- cat cpu.cfs_quota_us
复制代码
此中 cpu.cfs_quota_us 就是 CPU 的限定值,如果要查看具体的容器的资源,我们也可以进入到容器目录下面去查看即可。
内存是可压缩性资源,如果容器利用内存资源到达了上限,那么会OOM,造成内存溢出,容器就会终止和退出。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |