Kubernetes 高级资源控制器
概述
Pod是kubernetes的最小管理单元,在kubernetes中,按照pod的创建方式可以将其分为两类:
- 自主式pod:kubernetes直接创建出来的Pod,这种pod删除后就没有了,也不会重建
- 控制器创建的pod:kubernetes通过控制器创建的pod,这种pod删除了之后还会自动重建
Pod控制器是什么
Pod控制器就是帮助我们自动的调度管理Pod,并满足期望的Pod数量。
Pod控制器是用于实现管理pod的中间层,确保pod资源符合预期的状态,pod的资源出现故障时,会尝试 进行重启,当根据重启策略无效,则会重新新建pod的资源。
创建为具体的控制器对象之后,每个控制器均通过API Server
提供的接口持续监控相关资源对象的当前状态,并在因故障、更新或其他原因导致系统状态发生变化时,尝试让资源的当前状态想期望状态迁移和逼近。
Pod和Pod控制器
Pod
控制器资源通过持续性地监控集群中运行着的Pod
资源对象来确保受其管控的资源严格符合用户期望的状态,例如资源副本的数量要精确符合期望等。
通常,一个Pod
控制器资源至少应该包含三个基本的组成部分:
- 标签选择器:匹配并关联
Pod
资源对象,并据此完成受其管控的Pod
资源计数。 - 期望的副本数:期望在集群中精确运行着的
Pod
资源的对象数量。 - Pod模板:用于新建
Pod
资源对象的Pod
模板资源。
控制器的必要性
自主式Pod
对象由调度器调度到目标工作节点后即由相应节点上的kubelet
负责监控其容器的存活状态,容器主进程崩溃后,kubelet
能够自动重启相应的容器。
但对出现非主进程崩溃类的容器错误却无从感知,这便依赖于pod
资源对象定义的存活探测,以便kubelet
能够探知到此类故障。
但若pod
被删除或者工作节点自身发生故障(工作节点上都有kubelet
,kubelet
不可用,因此其健康状态便无法保证),则便需要控制器来处理相应的容器重启和配置。
常见的控制器
Pod
控制器由master
的kube-controller-manager
组件提供,常见的此类控制器有
ReplicationController
比较原始的pod控制器,已经被废弃,由ReplicaSet替代
ReplicaSet
代用户创建指定数量的
pod
副本数量,确保pod
副本数量符合预期状态,并且支持滚动式自动扩容和缩容功能
Deployment
工作在
ReplicaSet
之上,用于管理无状态应用,目前来说最好的控制器。支持滚动更新和回滚功能,还提供声明式配置。
Horizontal Pod Autoscaler
可以根据集群负载自动水平调整Pod的数量,实现削峰填谷
DaemonSet
用于确保集群中的每一个节点只运行特定的
pod
副本,常用于实现系统级后台任务,比如ELK
服务
Job
它创建出来的pod只要完成任务就立即退出,不需要重启或重建,用于执行一次性任务
Cronjob
它创建的Pod负责周期性任务控制,不需要持续后台运行,用于执行周期性任务
StatefulSet
管理有状态应用
DaemonSet(DS)控制器
DaemonSet概述
DaemonSet类型的控制器可以保证在集群中的每一台(或指定)节点上都运行一个副本。一般适用于日志收集、节点监控等场景。也就是说,如果一个Pod提供的功能是节点级别的(每个节点都需要且只需要一个),那么这类Pod就适合使用DaemonSet类型的控制器创建。
特点
- 每当向集群中添加一个节点时,指定的 Pod 副本也将添加到该节点上
- 当节点从集群中移除时,Pod 也就被垃圾回收了
应用场景
- 集群存储守护程序,如 glusterd、ceph 要部署在每个节点上以提供持久性存储;
- 节点监控守护进程,如 Prometheus 监控集群,可以在每个节点上运行一个 node-exporter 进程来收集监控节点的信息;
- 日志收集守护程序,如 fluentd 或 logstash,在每个节点上运行以收集容器的日志
- 节点网络插件,比如 flannel、calico,在每个节点上运行为 Pod 提供网络服务
调度问题
这里需要特别说明的一个就是关于 DaemonSet 运行的 Pod 的调度问题
正常情况下,Pod 运行在哪个节点上是由 Kubernetes 的调度器策略来决定的,然而,由 DaemonSet 控制器创建的 Pod 实际上提前已经确定了在哪个节点上了(Pod创建时指定了.spec.nodeName
)
DaemonSet
并不关心一个节点的unshedulable
字段。DaemonSet
可以创建 Pod,即使调度器还没有启动。
如何管理调度
DaemonSet 控制器是如何保证每个 Node 上有且只有一个被管理的 Pod 呢?
- 首先控制器从 Etcd 获取到所有的 Node 列表,然后遍历所有的 Node。
- 根据资源对象定义是否有调度相关的配置,然后分别检查 Node 是否符合要求。
- 在可运行 Pod 的节点上检查是否已有对应的 Pod,如果没有,则在这个 Node 上创建该 Pod;如果有,并且数量大于 1,那就把多余的 Pod 从这个节点上删除;如果有且只有一个 Pod,那就说明是正常情况。
使用案例
DaemonSet
控制器的spec
字段中嵌套使用的相同字段selector
、template
和minReadySeconds
,并且功能和用法基本相同,但它不支持replicas
,因为毕竟不能通过期望值来确定Pod
资源的数量,而是基于节点数量
基本使用
编辑资源清单
1 | vi nginx-daemonset.yml |
1 | apiVersion: apps/v1 #api版本定义 |
注意:我们可以看到,DaemonSet的yaml写法和Deployment非常类似,只是改变了下kind名称,注意下DaemonSet是没有副本数这一参数选项的。
应用配置
1 | kubectl apply -f nginx-daemonset.yml |
查看POD情况
1 | kubectl get node |
我们观察可以发现除了 master 节点之外的2个节点上都有一个相应的 Pod 运行,因为 master 节点上默认被打上了
污点(taints)
,所以默认情况下不能调度普通的 Pod 上去
查看节点污点
首先来看看这3个节点上是否打了污点呢
1 | kubectl describe node master |grep Taints |
我们可以看到只有master节点被打上了污点:
NoSchedule
破坏性测试
我们再来把其中一个pod删除下,观察下这个pod是否会被立马重建
1 | kubectl delete pod -l app=daem-nginx |
我们可以发现,一旦某个节点的pod被删除后,它会立马被重建的
这个就是daemonset控制器的作用,它是一个loop,会一直监听节点上的pod是否满足副本数为1这个条件,如果不满足,会立即执行相应操作,使其符合期望的状态。
更新DaemonSe
DaemonSet自Kubernetes1.6版本起也开始支持更新机制,相关配置嵌套在kubectl explain daemonset.spec.updateStrategy字段中
其支持RollingUpdate(滚动更新)和OnDelete(删除时更新)两种策略,滚动更新为默认的更新策略。
命令更新
命令更新适用于临时进行更新
查看当前版本
1 | kubectl get ds -o wide |
我们看到当前的DS和pod都是1.12版本
执行更新
通过以下命令可以进行执行更新
1 | kubectl set image ds nginx-daemon-set nginx-pod=nginx:1.15 |
这样就完成了更新
查看更新后版本
1 | kubectl get pods -l app=daem-nginx -o custom-columns=NAME:metadata.name,NODE:spec.nodeName,Image:spec.containers[0].image |
我们看到POD已经被更新了
配置文件更新
配置文件更新适合于永久更新
编辑配置文件
我们上面将配置文件更新为了1.15,下面我们将配置文件版本改为1.20
1 | apiVersion: apps/v1 #api版本定义 |
应用更新
1 | kubectl apply -f nginx-daemonset.yml |
查看更新后版本
1 | kubectl get ds -o wide |
我们发现已经更新到了1.20
筛选节点运行
对于特殊的硬件的节点来说,可能有的运行程序只需要在某一些节点上运行,那么通过
Pod
模板的spec
字段中嵌套使用nodeSelector
字段,并确保其值定义的标签选择器与部分特定工作节点的标签匹配即可。
创建标签
给node2添加上
disk=ssd
的标签
1 | kubectl label nodes node02 disk=ssd |
这样我们就在node02加上了一个
disk=ssd
的标签
编辑资源清单
1 | apiVersion: apps/v1 #api版本定义 |
该配置中我们增加了节点选择,我们只需要
DaemonSet
在有disk=ssd
的标签的节点上运行
应用配置
1 | kubectl apply -f nginx-daemonset.yml |
我们发现我们的POD只能运行在node01节点上了,有时候我们可以通过这种策略来控制daemonset的运行范围
Job控制器
Job,主要用于负责**批量处理(一次要处理指定数量任务)短暂的一次性(每个任务仅运行一次就结束)**任务
Job概述
Job
负责处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个 Pod 成功结束
Job特点
Job控制器有以下特点
- 当Job创建的pod执行成功结束时,Job将记录成功结束的pod数量
- 当成功结束的pod达到指定的数量时,Job将完成执行
配置描述
1 | apiVersion: batch/v1 # 版本号 |
重启策略说明
- 如果指定为OnFailure,则job会在pod出现故障时重启容器,而不是创建pod,failed次数不变
- 如果指定为Never,则job会在pod出现故障时创建新的pod,并且故障pod不会消失,也不会重启,failed次数加1
- 如果指定为Always的话,就意味着一直重启,意味着job任务会重复去执行了,当然不对,所以不能设置为Always
使用案例
基本使用
创建资源清单
1 | vi job-demo.yml |
这里的container要是一个任务才行,这里的image如果是nginx,那是不行的,因为nginx在前台,会一直运行下去的
1 | apiVersion: batch/v1 #batch就是批处理 |
我们可以看到 Job 中也是一个 Pod 模板,和之前的 Deployment、StatefulSet 之类的是一致的,只是 Pod 中的容器要求是一个任务,而不是一个常驻前台的进程了,因为需要退出。
另外值得注意的是 Job 的 RestartPolicy 仅支持 Never 和 OnFailure 两种,不支持 Always,我们知道 Job 就相当于来执行一个批处理任务,执行完就结束了,如果支持 Always 的话是不是就陷入了死循环了?
应用配置
1 | kubectl apply -f job-demo.yaml |
查看Job情况
1 | kubectl get job -o wide |
注意下,pod详情就很奇怪了,0/1ready,证明目前0个job准备好了,也就是没有job正在运行了,并且已经完成退出了
查看Job详情
Job
对象创建成功后,我们可以查看下对象的详细描述信息
1 | kubectl describe job job-demo |
可以看到,Job 对象在创建后,它的 Pod 模板,被自动加上了一个 controller-uid=< 一个随机字符串 >
这样的 Label
标签,而这个 Job 对象本身,则被自动加上了这个 Label 对应的 Selector,从而 保证了 Job 与它所管理的 Pod 之间的匹配关系。
而 Job 控制器之所以要使用这种携带了 UID 的 Label,就是为了避免不同 Job 对象所管理的 Pod 发生重合。
查看运行日志
我们可以看到很快 Pod 变成了
Completed
状态,这是因为容器的任务执行完成正常退出了,我们可以查看对应的日志
1 | kubectl logs job-demo-pnlq9 |
下图就是我们这里的 Job 任务对应的 Pod 在运行结束后,会变成
Completed
状态。
限制运行时长
在 Job 对象中通过设置字段
spec.activeDeadlineSeconds
来限制任务运行的最长时间
但是如果执行任务的 Pod 因为某种原因一直没有结束怎么办呢?同样我们可以在 Job 对象中通过设置字段 spec.activeDeadlineSeconds
来限制任务运行的最长时间
编辑配置清单
我们修改资源清单,将命令改为休眠100s,当这个job超时10后就会结束
1 | apiVersion: batch/v1 #batch就是批处理 |
那么当我们的任务 Pod 运行超过了 10s 后,这个 Job 的所有 Pod 都会被终止,并且, Pod 的终止原因会变成 DeadlineExceeded
。
应用配置
1 | kubectl apply -f job-demo.yml |
状态监控
我们可以提前打开POD的状态监控,来查看POD的变化
1 | kubectl get pod -o wide -w |
我们发现任务超过10S后来实强制结束POD,虽然POD任务还在运行
并行运行
有时候任务量比较大,我们可以考虑使用多个POD并行运行任务
修改资源清单
接下来,调整下pod运行的总数量和并行数量 ,在spec下设置下面两个选项
completions: 6 # 指定job需要成功运行Pods的次数为6
parallelism: 3 # 指定job并发运行Pods的数量为3
1 | apiVersion: batch/v1 #batch就是批处理 |
应用配置
1 | kubectl apply -f job-demo.yml |
Job状态监控
1 | kubectl get job -o wide -w |
POD状态监控
1 | kubectl get pod -o wide -w |
如下可以看到,3个为一轮创建一共6个任务
CronJob
CronJob
其实就是在Job
的基础上加上了时间调度,我们可以在给定的时间点运行一个任务,也可以周期性地在给定时间点运行,这个实际上和我们 Linux 中的crontab
就非常类似了。
CronJob概述
CronJob控制器以 Job控制器资源为其管控对象,并借助它管理pod资源对象,Job控制器定义的作业任务在其控制器资源创建之后便会立即执行,但CronJob可以以类似于Linux操作系统的周期性任务作业计划的方式控制其运行时间点及重复运行的方式。也就是说,CronJob可以在特定的时间点(反复的)去运行job任务。
crontab 格式
crontab 的格式为:
分 时 日 月 星期 要运行的命令
- 第1列分钟 0~59
- 第2列小时 0~23
- 第3列日 1~31
- 第4列月 1~12
- 第5列星期 0~7(0和7表示星期天)
- 第6列要运行的命令
配置描述
1 | apiVersion: batch/v1beta1 # 版本号 |
参数解释
schedule: cron表达式,用于指定任务的执行时间
*/1 * * * *
<分钟> <小时> <日> <月份> <星期>1
2
3
4
5
6分钟 值从 0 到 59.
小时 值从 0 到 23.
日 值从 1 到 31.
月 值从 1 到 12.
星期 值从 0 到 6, 0 代表星期日
多个时间可以用逗号隔开; 范围可以用连字符给出;*可以作为通配符; /表示每...concurrencyPolicy:
Allow: 允许Jobs并发运行(默认)
Forbid: 禁止并发运行,如果上一次运行尚未完成,则跳过下一次运行
Replace: 替换,取消当前正在运行的作业并用新作业替换它
使用案例
基本使用
创建资源清单
现在,我们用
CronJob
来管理我们上面的Job
任务,定义如下所示的资源清单
1 | vi cronjob-demo.yml |
1 | apiVersion: batch/v1 |
这里的 Kind 变成了 CronJob
了,要注意的是 .spec.schedule
字段是必须填写的,用来指定任务运行的周期,格式就和 crontab
一样。
另外一个字段是 .spec.jobTemplate
, 用来指定需要运行的任务,格式当然和 Job
是一致的。
还有一些值得我们关注的字段 .spec.successfulJobsHistoryLimit(默认为3) 和 .spec.failedJobsHistoryLimit(默认为1),表示历史限制,是可选的字段,指定可以保留多少完成和失败的 Job。然而,当运行一个 CronJob 时,Job 可以很快就堆积很多,所以一般推荐设置这两个字段的值,如果设置限制的值为 0,那么相关类型的 Job 完成后将不会被保留。
应用配置
1 | kubectl apply -f cronjob-demo.yml |
查看Cronjob
可以查看对应的 Cronjob 资源对象
1 | kubectl get cj -o wide |
监控POD
稍微等一会儿查看可以发现多了几个 Job 资源对象,这个就是因为上面我们设置的 CronJob 资源对象,每1分钟执行一个新的 Job
1 | kubectl get pod -o wide -w |
HPA(Pod 水平自动伸缩)控制器
HPA概述
在前面的学习中我们使用了一个
kubectl scale
命令可以来实现 Pod 的扩缩容功能,但是这个是完全手动操作的,要应对线上的各种复杂情况
我们需要能够做到自动化去感知业务,来自动进行扩缩容。为此,Kubernetes 也为我们提供了这样的一个资源对象:Horizontal Pod Autoscaling(Pod 水平自动伸缩),简称 HPA,HPA 通过监控分析一些控制器控制的所有 Pod 的负载变化情况来确定是否需要调整 Pod 的副本数量。
我们可以简单的通过 kubectl autoscale 命令来创建一个 HPA 资源对象,HPA Controller 默认30s轮询一次(可通过 kube-controller-manager 的–horizontal-pod-autoscaler-sync-period 参数进行设置),查询指定的资源中的 Pod 资源使用率,并且与创建时设定的值和指标做对比,从而实现自动伸缩的功能。
资源监控及资源指标
资源监控系统是容器编排系统必不可少的组件,它为用户提供了快速了解系统资源分配和利用状态的有效途径,同时也是系统编排赖以实现的基础要件。
资源监控及Heapster
Kubernetes有多个数据指标需要采集相关的数据,而这些指标大体上由监控集群本身和监控Pod对象两部分组成,监控集群需要监控节点资源状态、节点数量、运行的pod数量;监控Pod资源对象需要监控kubernetes指标,容器指标和应用程序指标。
Kubernetes系统与kubelet程序中集成相关的工具程序cAdisor用于对节点上的资源及容器进行实时监控及指标数据采集,这类监控的实现方式有Heapster。从kubernetes1.11开始Heapster被废弃不在使用,metrics-server 替代了heapster。
新一代的监控架构
新一代的kubernetes监控系统架构主要由核心指标流水线和监控指标流水线协同组成。
核心指标流水线由kubelet、资源评估器、metrics-server及API server提供的API群组组成,可用于为kubernetes系统提供核心指标从而能够了解其内部组件和核心程序,监控指标流水线用于从系统收集各种指标数据并提供给终端用户、存储系统及HPA控制器使用。
资源指标API主流的实现是metrics-server,自定义指标API以构建在监控系统Prometheus之上到k8s-prometheus-adapter使用最为广泛。
聚合 API
Aggregator 允许开发人员编写一个自己的服务,把这个服务注册到 Kubernetes 的 APIServer 里面去,这样我们就可以像原生的 APIServer 提供的 API 使用自己的 API 了,我们把自己的服务运行在 Kubernetes 集群里面,然后 Kubernetes 的 Aggregator 通过 Service 名称就可以转发到我们自己写的 Service 里面去了。这样这个聚合层就带来了很多好处:
- 增加了 API 的扩展性:开发人员可以编写自己的 API 服务来暴露他们想要的 API。
- 丰富了 API:核心 kubernetes 团队阻止了很多新的 API 提案,通过允许开发人员将他们的 API 作为单独的服务公开,这样就无须社区繁杂的审查了。
- 开发分阶段实验性 API:新的 API 可以在单独的聚合服务中开发,当它稳定之后,在合并会 APIServer 就很容易了。
- 确保新 API 遵循 Kubernetes 约定:如果没有这里提出的机制,社区成员可能会被迫推出自己的东西,这样很可能造成社区成员和社区约定不一致。
metrics-server安装
现在我们要使用 HPA,就需要在集群中安装
Metrics Server
服务,要安装Metrics Server
就需要开启Aggregator
,因为Metrics Server
就是通过该代理进行扩展的,不过我们集群是通过 Kubeadm 搭建的,默认已经开启了
什么是metrics-server
在 HPA 的第一个版本中,我们需要 Heapster(目前这个已经废弃了) 提供 CPU 和内存指标,在 HPA v2 过后就需要安装 Metrcis Server 了,Metrics Server 可以通过标准的 Kubernetes API 把监控数据暴露出来,有了 Metrics Server 之后,我们就完全可以通过标准的 Kubernetes API 来访问我们想要获取的监控数据了:
1 | https://10.96.0.1/apis/metrics.k8s.io/v1beta1/namespaces/<namespace-name>/pods/<pod-name> |
比如当我们访问上面的 API 的时候,我们就可以获取到该 Pod 的资源数据,这些数据其实是来自于 kubelet 的 Summary API 采集而来的。
不过需要说明的是我们这里可以通过标准的 API 来获取资源监控数据,并不是因为 Metrics Server 就是 APIServer 的一部分,而是通过 Kubernetes 提供的 Aggregator(聚合器) 汇聚插件来实现的,是独立于 APIServer 之外运行的
查看metrics server地址
我们可以先来看看这个
metrics server
的gitbub地址https://github.com/kubernetes-sigs/metrics-server
下载资源清单
下载仓库官方metrics server安装的资源清单,
Aggregator
聚合层启动完成后,就可以来安装Metrics Server
了,我们可以获取该仓库的官方安装资源清单:
1 | wget https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.6.1/components.yaml |
编辑资源清单
1 | vi components.yaml |
修改资源清单的
140
行的代码,将镜像的地址改为bitnami/metrics-server:0.6.1
完整配置文件如下
1 | apiVersion: v1 |
应用配置
1 | kubectl apply -f components.yaml |
检查POD情况
因为该配置的namespace是
kube-system
,所以查看POD需要指定命名空间
1 | kubectl get pod -nkube-system -l k8s-app=metrics-server -o wide |
我们发现当前的状态是运行的,但是还是未准备状态
检查启启动错误
我们就需要查看日志查看是否启动错误
1 | kubectl logs -f metrics-server-6c96d6dc56-g7t95 -nkube-system |
跳过证书校验
上面问题因为我们没有做证书签名的缘故
因为部署集群的时候,CA 证书并没有把各个节点的 IP 签上去,所以这里 Metrics Server 通过 IP 去请求时,提示签的证书没有对应的 IP(错误:x509: cannot validate certificate for 192.168.245.151 because it doesn’t contain any IP SANs” node=”master”),我们可以添加一个--kubelet-insecure-tls
参数跳过证书校验:
1 | - args: |
重新应用配置
1 | kubectl apply -f components.yaml |
查看POD情况
1 | kubectl get pod -nkube-system -l k8s-app=metrics-server -o wide |
我们发现已经恢复正常了
验证效果
现在我们可以通过
kubectl top
命令来获取到资源数据了,证明Metrics Server
已经安装成功了
Node指标监控
可以通过以下命令进行监控Node的指标了
1 | kubectl top node |
pod监控指标
我们还可以监控具体pod的指标
1 | kubectl top pod --all-namespaces |
Top精简查看
默认执行会有一堆提示,如果不想要这些提示,直接在后面加上参数:
--use-protocol-buffers
即可【提示中最后有参数说明的哈】
正常查看指标
正常查看Node指标会有一堆的体提示
1 | kubectl top nodes |
精简查看
加入
--use-protocol-buffers
参数就可以不显示提示信息了
1 | kubectl top nodes --use-protocol-buffers |
基于CPU的HPA
默认情况下就是基于CPU的HAP
创建资源清单
现在我们用 Deployment 来创建一个 Nginx Pod,然后利用
HPA
来进行自动扩缩容
1 | vi hpa-demo.yml |
1 | apiVersion: apps/v1 |
应用配置
然后直接创建 Deployment,注意一定先把之前创建的具有
app=nginx
的 Pod 先清除掉
1 | kubectl apply -f hpa-demo.yml |
我们创建了资源清单,当前只有一个POD对象
创建HPA对象
现在我们来创建一个
HPA
资源对象,可以使用kubectl autoscale
命令来创建
1 | kubectl autoscale deployment hpa-demo --cpu-percent=10 --min=1 --max=10 |
该命令创建了一个关联资源 hpa-demo 的 HPA,最小的 Pod 副本数为1,最大为10,HPA 会根据设定的 cpu 使用率(10%)动态的增加或者减少 Pod 数量
查看HPA详情
下面我们可以看下HAP的信息
1 | kubectl get hpa hpa-demo -o wide |
我们发现指标信息是
unknown
,读取不到指标信息
查看HPA详细信息
我们可以查看HAP的详细信息,看下具体情况
1 | kubectl describe hpa hpa-demo |
查看详情的时候我们发现了一些错误信息
我们可以看到上面的事件信息里面出现了 failed to get cpu utilization: missing request for cpu
这样的错误信息。
这是因为我们上面创建的 Pod 对象没有添加 request 资源声明,这样导致 HPA 读取不到 CPU 指标信息,所以如果要想让 HPA 生效,对应的 Pod 资源必须添加 requests 资源声明,来更新我们的资源清单文件。
重新配置
下面我们重新修改配置文件解决问题
编辑资源清单
更新我们的资源清单文件,添加
requests资源
1 | apiVersion: apps/v1 |
重新应用配置
然后重新更新 Deployment
1 | kubectl apply -f hpa-demo.yaml |
重新创建HPA对象
重新创建HPA对象,需要先删除HPA对象然后在重新创建
1 | kubectl delete hpa hpa-demo |
这样我们就重新创建了HPA控制器
查看HPA对象
我们现在再来查看以下HPA的列表信息
1 | kubectl get hpa hpa-demo -o wide |
现在我们发现已经获取到了指标信息了
我们还可以查看下HPA的详细信息
1 | kubectl describe hpa hpa-demo |
我们发现一切正常
模拟压测
验证得到pod-IP
首先验证Pod-IP是否能够访问
1 | kubectl get pod -o wide |
我们发现当前POD的IP是
10.244.1.96
,我们尝试请求访问
1 | curl 10.244.1.96 |
我们发现访问没有任务问题
busybox压测
用另一个终端(我这里是master)使用busybox镜像产生一个测试pod,对
10.244.1.96
进行压测
1 | kubectl run -it --image busybox test-hpa --restart=Never --rm /bin/sh |
我们新打开一个终端,并执行以下命令,运行一个pod,并进入控制台,然后输入以下命令来进行压测
1 | while true; do wget -q -O- http://10.244.1.96; done |
注意:ctrl+c取消压力测试
监控HPA状态
不断查询hpa状态,大概一分钟后才会看到效果
1 | kubectl get hpa -o wide -w |
我们发现随着服务器压力增加,然后观察 Pod 列表,可以看到,HPA 已经开始工作,POD不断的扩容
查看POD状态
我们现在看下POD的状态信息
1 | kubectl get pod -o wide |
我们可以看到已经自动拉起了很多新的 Pod,最后会定格在了我们上面设置的 10 个 Pod,同时查看资源 hpa-demo 的副本数量,副本数量已经从原来的1变成了10个
退出测试
我们使用
ctrl+c
取消压力测试,并监控HPA状态,要等几分钟甚至更久后,就看到cpu与pod数量都回去了
1 | kubectl get hpa -o wide -w |
可以看到副本数量已经由 10 变为 1,当前我们只是演示了 CPU 使用率这一个指标,在后面的课程中我们还会学习到根据自定义的监控指标来自动对 Pod 进行扩缩容。
缩放间隙
默认为5分钟,也就是默认需要等待5分钟后才会开始自动缩放
从 Kubernetes v1.12 版本开始我们可以通过设置 kube-controller-manager 组件的–horizontal-pod-autoscaler-downscale-stabilization 参数来设置一个持续时间,用于指定在当前操作完成后,HPA 必须等待多长时间才能执行另一次缩放操作。
清理环境
注意:在做本次实验前,把本次实验的全部资源全部卸载掉,以方便下一次精确测试实验。
1 | kubectl delete hpa hpa-demo |
基于内存的HPA
创建资源清单
然后需要创建一个基于内存的 HPA 资源对象
1 | vi hpa-mem-demo.yml |
基于当前脚本我们创建一个Deployment对象
1 | apiVersion: apps/v1 |
应用配置文件
1 | kubectl apply -f hpa-mem-demo.yml |
这样我们就将资源清单的对象创建出来了
创建HPA对象
创建资源清单
我们本次基于配置文件创建HPA
1 | vi hpa-mem.yml |
要注意这里使用的
apiVersion
是autoscaling/v2beta1
,然后metrics
属性里面指定的是内存的配置
1 | apiVersion: autoscaling/v2beta1 #注意:这里是v2beta1 |
应用配置
直接创建上面的资源对象即可
1 | kubectl apply -f hpa-mem.yml |
这样就启动了一个基于内存的HPA对象,到这里证明 HPA 资源对象已经部署成功了
进行压测
验证POD
我们首先查看下POD的名字信息
1 | kubectl get pod -o wide |
这样我们就获取了POD的名称了
hpa-mem-demo-644b6585df-x9psj
内存压测压测
接下来我们对应用进行压测,将内存压上去,换一个终端(master),进入pod后进行dd命令测试
1 | kubectl exec -it hpa-mem-demo-58899f49cd-vmhqn -- /bin/sh |
监控HPA状态
然后打开另外一个终端观察 HPA 资源对象的变化情况,不断查询hpa状态,大概一分钟后才会看到效果
1 | kubectl get hpa -o wide -w |
我们发现副本数随着内存占用率的增加而扩容
查看POD状态
1 | kubectl get pod -o wide |
我们发现已经扩容出来了10个POD
中断压测
清理文件
ctrl+c
取消后,删除dd的文件
1 | rm -rf /tmp/file1 |
监控HPA状态
等几分钟甚至更久后,就看到内存与pod数量都回去了
1 | kubectl get hpa -o wide -w |
查看POD状态
1 | kubectl get pod -o wide |
我们发现已经缩容到了1个
清理环境
注意:在做本次实验前,把本次实验的全部资源全部卸载掉,以方便下一次精确测试实验。
1 | kubectl delete hpa hpa-mem-demo |