kubernetes 高级调度01
HPA(Horizontal Pod Autoscaler,水平Pod自动伸缩器)可以根据观察到的CPU、内存使用率或自定义度量标准来自动扩展或缩容Pod的数量。注意HPA不适用于无法缩放的对象,比DaemonSet。HPA控制器会定期调整RC或Deployment的副本数,以使观察到的平均CPU利用率与用户指定的目标相匹配。HPA需要Metrics Server 获取度量指标,如果已经部署了Me
目录
(10)清除.00
一.初始化容器initcontainer
首先来看初始化容器,顾名思义,初始化容器是用来进行初始化操作的。很多情况下,程序的启动需要依赖各类配置、资源。但是又不能继承在原有的启动命令或者镜像当中,因为程序的镜像可能并没有加载配置命令,此时InitContainer就起了很大的作用。
1: InitContainer的基本概念
InitContainer 是Kubernetes的初始化容器(也可称之为Init容器),它是一种特殊的容器,在Pod 内的应用容器启动之前运行,可以包括一些应用镜像中不存在的使用工具和安装脚本,用以在程序启动时进行初始化,比如创建文件、修改内核参数、等待依赖程序启动等。
每个Pod中可以包含多个容器,同时Pod也可以有一个或多个先于应用程序启动的Init容器,在Pod定义中和container同级,按顺序逐个执行,当所有的Init容器运行完成时,Kubernetes 才会启动Pod内的普通容器。
Init容器与普通的容器非常像,除了如下几点:
> 他们总是运行到完成。
> 上一个运行完成才会运行下一个。
> 如果Pod的Init容器失败,Kubernetes会不断地重启该Pod,直到Init容器成功为止,但是如果Pod对应的restartPolicy值为Never,Kubernetes则不会重新启动Pod。
为Pod 设置Init容器需要在Pod的spec中添加initContainer字段,该字段和应用的containers属组同级相邻,配置方式和containers中的普通容器差不多,Init容器支持应用容器的全部字段和特性,包括资源限制、数据卷和安全设置。但是Init容器对资源请求和限制的处理稍有不同,Init 容器不支持lifecycle、livenessProbe、readinessProbe 和startupProbe,因为他们必须在Pod就绪之前运行完成。
lifecycle 主要指的是容器在其运行环境中经历的不同阶段,以及Kubernetes如何管理和响应这些阶段的能力。Kubernetes提供了容器生命周期钩子(Container Lifecycle Hooks),这是一种允许用户指定在容器生命周期的特定点上运行代码片段或命令的功能。
容器生命周期钩子主要包括以下两个部分:
PostStart:这个钩子在容器被创建之后立即调用,但需要注意的是,在钩子执行的时候容器内的主
备动作一进程尚未启动。这可以用于执行一些初始化任务,比如建立文件系统的缓存目录或其他类型的准动作。
PreStop:这个钩子在发送信号给容器内的主进程之前调用,这意味着这是在容器被终止之前可以执
行一些清理工作的最后机会。它常被用来做一些资源释放的工作,比如关闭已经打开的数据库连或网络连接等。
在生产环境中,为了应用的安全和优化镜像的体积,业务镜像一般不会安装高危工具和并不常用的运维工具,比如cur1、sed、awk、python或dig等,同时建议使用非root用户去启动容器。但是某些应用启动之前可能需要检查依赖的服务有没有成功运行,或者需要更高的权限去修改一些系统级的配置,而这些检测或配置更改都是一次性的,所以在制作业务镜像时没有必要为了一次配置的变更去安装一个配置工具,更没有必要因为使用一次高权限而把整个镜像改成以root身份运行。
考虑到上述问题和需求,Kubernetes引入了初始化容器的概念,Init容器具有与应用容器分离的单独镜像,其启动相关代码具有如下优势:
> Init 容器可以包含安装过程中应用容器中不存在的实用工具或个性化代码。
> Init容器可以安全地运行这些工具,避免这些工具导致应用镜像的安全性降低。
> Init容器可以以root身份运行,执行一些高权限命令。
> Init容器相关操作执行完成后就会退出,不会给业务容器带来安全隐患。
由于Init 容器必须在应用容器启动之前运行完成,因此Init容器提供了一种机制来阻塞或延迟应用容器的启动,直到满足一组先决条件,Pod内的所有应用容器才会并行启动。
2。示例1--延迟指定时间后启动
创建一个pod指定初始化容器,表示初始化容器需要休眠15秒
vim init01.yaml
kubectl create -f init01.yaml
查看pod启动状态15秒后pod开始启动chengrunning
kubectl get pod
kubectl get pod
NAME READY STATUS RESTARTS AGE
initc01 1/1 Running 0 25s
3.实例2--使用初始化容器修改内核参数
在容器里修改内核参数,实际上修改的就是物理机的内核参数,为了安全性,一般不允许在容器里修改内核参数,Seccomp 代表安全计算(Secure Computing)模式,seccomp控制了容器能做哪些操作,添加 securityContext 参数之后就可以修改内核参数了。
创建一个pod,initContainers 初始化容器里的securityContext:privileged: true表示该容器具有特权,可以执行命令"sh","-c","/sbin/sysct1 -w vm.swappiness=0",vm.swappiness设置为0表示尽量少使用swap内存。
vim init02.yaml
kubectl apply -f init02.yaml
kubectl get pod
kubectl get pod
NAME READY STATUS RESTARTS AGE
initc02 1/1 Running 0 25m
查看k8s-01 的swappiness值为0
cat /proc/sys/vm/swappiness
0
4.实例3---等待依赖服务启动
有时某些服务需要依赖其他组件才能启动,比如后端应用需要数据库启动之后,应用才能正常启动,此时需要检测数据库实例是否正常,等待数据库可以正常使用时,在启动后端应用,此时可以使用初化
容器进行控制。
(1)创建第一个Pod
该Pod内要依赖两个条件才能启动,一个是利用busybox容器检测redis-service服务是否生成,第二个是检测mysql-server服务是否生成。
vim myapp.yaml
kubectl create -f myapp.yaml
kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 65s
(2)创建一个被依赖的server
vim redis-deployment.yaml
kubectl creat -f redis-deployment.yaml
kubectl get pod
NAME READY STATUS RESTARTS AGE
redis-56bcf55554-hzzbd 1/1 Running 0 16m
4.pause容器
在Kubernetes中,pause容器并不是指暂停容器的执行,而是指一个特殊的辅助容器,它被用于每个Pod以帮助实现网络命名空间。pause容器是Kubernetes中每个Pod的第一个容器,它的主要作用是作为Pod内所有其他容器共享网络命名空间的基础。每个Kubernetes Pod 都有一个pause容器,它是Pod的第一个容器,也是唯一必须运行的容器。即使Pod中的其他容器都停止了,只要pause容器还在运行,Pod就不会被Kubernetes认为是完全停止的。
(1)pause 容器的作用
> 网络命名空间:pause容器为Pod内的所有容器提供了一个共享的网络命名空间。这意味着Pod内的所有容器都共享同一个IP地址和端口空间,从而使得它们可以直接通过localhost或者其他指定方式相互通信。
>网络接口:pause容器负责设置Pod的网络接口,使得Pod内的容器能够通过这个接口访问外部网络。
>稳定性:如果Pod中的所有声明的容器都被删除或停止,pause容器将保持运行,从而保证Pod的网络命名空间不会丢失。这也意味着Pod的网络配置仍然保留,直到整个Pod被删除。
> 生命周期管理:pause容器是一个非常简单的容器,其镜像只包含一个命令/pause,该命令实际上
一个无限循环,保持容器处于运行状态。它不执行任何业务逻辑,仅仅是作为Pod网络基础设施的一
部分。
(2)使用pause容器的好处
> 简化了Pod内的网络配置。
> 提高了Pod网络的一致性。
> 减少了管理Pod网络复杂性的开销。
总的来说,pause 容器对于实现Kubernetes Pod的网络功能至关重要,它是Kubernetes网络模型的一个核心组成部分。
(3)Pause 容器实现
Pod 里的多个容器怎么去共享网络?下面是个例子:
比如说现在有一个 Pod,其中包含了一个容器 A和一个容器 B,它们两个就要共享 NetworkNamespace。在 Kubernetes 里的解法是这样的:它会在每个Pod 里,额外起一个 Infra(基础)container 小容器来共享整个 Pod 的 Network Namespace。
Infra container 是一个非常小的容器,大概 700KB 左右,是一个C语言写的、永远处于“暂停”状态的容器。由于有了这样一个 Infra container 之后,其他所有容器都会通过 Join Namespace的方式加入到 Infra container 的 Network Namespace 中。
所以说一个Pod 里面的所有容器,它们看到的网络视图是完全一样的。即:它们看到的网络设备、IP 地址、Mac 地址等等,跟网络相关的信息,其实全是一份,这一份都来自于Pod 第一次创建的这个Infra container。这就是Pod 解决网络共享的一个解法。
在 Pod 里面,一定有一个IP 地址,是这个Pod 的Network Namespace 对应的地址,也是这个Infra container 的 IP地址。所以大家看到的都是同一份,而其他所有网络资源,都是一个Pod一份,并且被 Pod 中的所有容器共享。这就是Pod的网络实现方式。
由于需要有一个相当于中间的容器存在,所以整个Pod 里面,必然是 Infra container 第一个启动。并且整个Pod 的生命周期是等同于 Infra container 的生命周期的,与容器A和 B是无关的。这也是为什么在 Kubernetes 里面,它是允许去单独更新Pod 里的某一个镜像的,即:做这个操作,整个Pod 不会重建,也不会重启,这是非常重要的一个设计。
kubectl get pod -o wide
kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mysql-7f5d669b6c-lk62l 1/1 Running 0 63m 10.244.85.199 k8s-node01 <none> <none>
nginx-server-6ddcfd4c8f-79284 1/1 Running 0 37m 10.244.85.204 k8s-node01 <none> <none>
nginx-server-6ddcfd4c8f-tpgzw 1/1 Running 0 37m 10.244.85.203 k8s-node01 <none> <none>
nginx-test 1/1 Running 0 40m 10.244.85.202 k8s-node01 <none> <none>
redis-56bcf55554-4vkt9 1/1 Running 0 48m 10.244.85.201 k8s-node01 <none> <none>
在看k8s-01查看pod中pause容器
docker ps | grep pause
85e3ec0e9aef registry.aliyuncs.com/google_containers/pause:3.6 "/pause" 40 minutes ago Up 40 minutes k8s_POD_nginx-server-6ddcfd4c8f-79284_default_c91ff665-b86a-42ac-8e19-331eb1ae632a_0
bb16e0953d22 registry.aliyuncs.com/google_containers/pause:3.6 "/pause" 40 minutes ago Up 40 minutes k8s_POD_nginx-server-6ddcfd4c8f-tpgzw_default_e3678b84-1b0e-483d-81a6-c4d13b8517cc_0
be3a1b184fee registry.aliyuncs.com/google_containers/pause:3.6 "/pause" 44 minutes ago Up 44 minutes k8s_POD_nginx-test_default_1e498c01-8e20-4b5c-8811-4d79dc2a6e0b_0
二.临时容器ephemeral containers
在生产坏境中,为J优化镜像的体积和提局镜像的安全性,开个会在谷中安装太多局危工具。比如cur1、wget、dig以及常用的net-tools等。这样做虽然提高了镜像的安全性,但是也带来了一些不便,比如无法查看容器内的进程情况、无法查看容器内的链接情况、服务出了问题无法很方便的进行排查等。因为上述操作并非经常使用,所以我们并没有必要从一开始就安装这些工具,但是等到用他们的时候再安装也是一件很麻烦的事情,那么我们该如何处理这个问题呢?
为了解决这类问题,在1.16版本后,Kubernetes引入了Ephemeral Containers的概念,可以不用安装第三方工具即可实现在线Debug操作。
1:临时容器的概念
临时容器与其他容器的不同之处在于,临时容器是被临时添加到Pod上,用于在线调试应用的,他永远不会自动重启,因此不适用与构建应用程序,临时容器的声明和普通容器类似,但是临时容器没有端口配置,因此不能使用像ports、livenessprobe、readnessProbe、resources这样的字段,当然,临
时容时容器只是用来调试程序的,它的状态不会影响其他正常容器,所以它并不需要这些字段配置。
临时容器使用API中一种特殊的Ephemeral Containers处理器进行创建,而不是直接添加到pod.spec 字段,因此无法使用kubectl edit来添加临时容器,与常规容器一样,将临时容器添加到Pod后,将不能更改或删除临时容器,但是当添加了临时容器的Pod重启后,临时容器就会被销毁。
因为临时容器是为了调试程序而设计的,所以在添加临时容器时,最好使用一个包含所有常用工具的镜像进行创建。当业务容器崩溃或容器镜像不包含调试工具而导致kubectl exec不可用时,临时容器对于交互故障排查和在线Debug很有用。尤其是在使用像不包含任何shell和其他工具的destroless镜像作为基础镜像时,虽然可以减少攻击面和漏洞,但对于问题的排查会变得尤为棘手,此时临时容器就可以发挥很大的作用,带来诸多便利性。
2.临时容器的使用
vim pod-tomcat.yaml
(2)创建pod
kubectl apply =f pod-tomcat.yaml
kubectl get pods tomcat-test
NAME READY STATUS RESTARTS AGE
tomcat-test 1/1 Running 0 2m18s
(3)为tomcat的pod创建临时容器
kubectl debug -it nginx-test --image=busybox:1.28 --target=nginx-test
Targeting container "nginx-test". If you don't see processes from this container it may be because the container runtime doesn't support this feature.
Defaulting debug container name to debugger-jndmg.
If you don't see a command prompt, try pressing enter.
/ #
/ # ps -ef | grep tomcat
44 root 0:00 grep tomcat
/ # exit
(4)查看tomcat-test这个pod是否已有临时容器
kubectl describe pods tomcat-test
Name: tomcat-test
Namespace: default
Priority: 0
Node: k8s-node02/192.168.10.103
Start Time: Fri, 11 Jul 2025 10:49:16 +0800
Labels: app=tomcat
Annotations: cni.projectcalico.org/containerID: 730db39ee9279e5391f922deb736bad56ad7a0fcb4bb4bc07d0a022c6098afb4
cni.projectcalico.org/podIP: 10.244.58.199/32
cni.projectcalico.org/podIPs: 10.244.58.199/32
Status: Terminating (lasts 9m31s)
Termination Grace Period: 30s
IP: 10.244.58.199
IPs:
IP: 10.244.58.199
Containers:
tomcat-java:
Container ID: docker://1a3b328961b94707b7574a3e0795e697e17aff5bc31c5a88084b844a0fd6ad2e
Image: kubeguide/tomcat-app:v1
Image ID: docker-pullable://kubeguide/tomcat-app@sha256:7a9193c2e5c6c74b4ad49a8abbf75373d4ab76c8f8db87672dc526b96ac69ac4
Port: 8080/TCP
Host Port: 0/TCP
State: Running
Started: Fri, 11 Jul 2025 10:50:12 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-jfvz8 (ro)
Ephemeral Containers:
debugger-ckw2n:
Image: busybox:1.28
Port: <none>
Host Port: <none>
Environment: <none>
Mounts: <none>
debugger-xdchj:
Image: busybox:1.28
Port: <none>
Host Port: <none>
Environment: <none>
Mounts: <none>
Conditions:
Type Status
Initialized True
Ready False
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-jfvz8:
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 17m default-scheduler Successfully assigned default/tomcat-test to k8s-node02
Normal Pulling 17m kubelet Pulling image "kubeguide/tomcat-app:v1"
Normal Pulled 16m kubelet Successfully pulled image "kubeguide/tomcat-app:v1" in 53.516951679s
Normal Created 16m kubelet Created container tomcat-java
Normal Started 16m kubelet Started container tomcat-java
Warning NodeNotReady 15m node-controller Node is not ready
[root@k8s-master ~]#
[root@k8s-master ~]#
[root@k8s-master ~]# vim nginx-deployment.yaml
[root@k8s-master ~]# kubectl create -f nginx-deployment.yaml
deployment.apps/nginx-server create
三自动扩缩容HPA
在集群安装的过程中,我们可以安装一个叫Metrics Server的组件,该组件在集群中负责采集Pod和Node的度量值指标,比如Pod的CPU、内存使用率和节点的内存、CPU使用率,而且安装的Dashboard可以展示CPU、内存信息也是依靠Metrics Server的。当然,该组件不仅仅是用来展示数据的,还可以使用Metrics Server 提供的数据结合Kubernetes的HPA功能实现Pod的自动扩缩容。
1:什么是HPA
HPA(Horizontal Pod Autoscaler,水平Pod自动伸缩器)可以根据观察到的CPU、内存使用率或自定义度量标准来自动扩展或缩容Pod的数量。注意HPA不适用于无法缩放的对象,比DaemonSet。
HPA控制器会定期调整RC或Deployment的副本数,以使观察到的平均CPU利用率与用户指定的目标相匹配。
HPA需要Metrics Server 获取度量指标,如果已经部署了Metrics Server,本节的实践部就分无须再次安装Metrics Server。如果没有安装Metrics Server,可以参考其他实验文档自行部署。
2:HPA的工作原理
> HPA 根据观察到的CPU、内存使用率或自定义度量标准来自动扩展或缩容Pod的数量。
> HPA控制器会定期调整RC(Replication Controller)或Deployment的副本数,以使观察到
的平均CPU利用率(或其他度量标准)与用户指定的目标相匹配。
> HPA需要Metrics Server获取度量指标,Metrics Server负责采集Pod和Node的度量值指标、加CPU、内存使用率等。
3:HPA的工作流程
>配置HPA:使用kubect1 autoscale 命令为Deployment、ReplicaSet或StatefulSet 等资源创建HPA对象,并指定目标CPU利用率、最小副本数和最大副本数。
> 度量指标采集:Metrics Server 定期采集Pod和Node的度量值指标,并将这些数据提供给HPA控制器。
> 伸缩决策:HPA控制器根据当前Pod的度量指标和目标利用率进行比较,如果当前利用率高于目标利用率,则增加Pod副本数;如果当前利用率低于目标利用率,则减少Pod副本数(在最小副本数和最大副本数之间调整)
> Pod伸缩:Kubernetes根据HPA控制器的决策自动调整Pod的副本数,以实现自动扩缩容。
4:HPA的应用场景
> 应对流量波动:在Web服务中,流量可能会随时间变化而波动。HPA可以根据流量变化自动调整Pod副本数,以确保服务的稳定性和响应速度。
>资源优化:通过自动扩缩容,HPA可以在保证服务质量的同时最大化资源利用率,降低运营成本。
5:HPA实践 -- 实现Web服务器的自动伸缩特性
在生产环境中,总会有一些意想不到的事情发生,比如公司网站流量突然升高,此时之前创建的Pod已不足以支撑所有的访问,而运维人员也不可能24小时守着业务服务,这时就可以通过配置HPA,实现负载过高的情况下自动扩容Pod副本数以分摊高并发的流量,当流量恢复正常后,HPA会自动缩减Pod的数量。
(1)首先用deployment启动一个nginx服务
vim nginx-deployment.yaml
kubectl create -f nginx-deployment.yaml
(2)配置nginx-server的service
kubectl expose deployment nginx-serveer --port=80
(3)使用kubectl autoscale命令创建HPA
kubectl autoscale deployment nginx-server --cpu-percent=10 --min-1 --max=10
此HPA将根据CPU的使用率自动增加和减少副本数量,上述设置的是CPU使用率超过10%( -- cpu-percent 参数指定)就会增加Pod的数量,以保持所有Pod的平均CPU利用率为10%,允许最大的Pod数量为10( -- max),最少的Pod数为1( -- min)。
(4)查看当前HPA状态
因为未对其发送任何请求,所以当前cpu使用率为0%
kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
nginx-server deployment/ngninx-server 0%/10/5 1 10 2 3m 41s
(5)查看当前Ngmx的Service 地址
kubectl get service -n default
nginx-server clusterip 10.107.217.171 node 80/tcp 43s
(6)压力测试
while true;do wget -q -o http://10.107.217.171 /dev null;done
备注:
-q 是不输出wget的头部信息
-0-(大写字母0)选项表示将下载的内容输出到标准输出(通常是终端),而不是保存到文件。
(7)查看HPA 状态
等待一分钟左右,再次查看HPA,可以看到Pod的CPU已经升高。
kubectl get hpa
(8)再次查看pod,可以看到已经扩容
kubect1 get pod
停止压力测试
kubectl get hpa
kubectl get hpa
(9)查看pod副本数
kubectl get pod
(10)清除
kubectl delete -f nginx-deployment.yaml
kubectl delete -f mysql-deployment.yaml
kubecctl delete -f redis-deployment.yaml
kubectl delete -f init01.yaml
kubectl delete -f init02.yaml
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐
所有评论(0)