当前位置: 首页 > news >正文

9.HPA与VPA

HPA 与 VPA

​ 在前面的学习中我们使用了一个 kubectl scale 命令可以来实现 Pod 的扩缩容功能,但是这个是完全手动操作的,要应对线上的各种复杂情况,我们需要能够做到自动化去感知业务,来自动进行扩缩容。为此,Kubernetes 也为我们提供了这样的一个资源对象:Horizontal Pod Autoscaling(Pod 水平自动伸缩),简称 HPA,HPA 通过监控分析一些控制器控制的所有 Pod 的负载变化情况来确定是否需要调整 Pod 的副本数量,在 Kubernetes 控制平面内运行的 HPA控制器会定期调整其目标(例如:Deployment)的所需规模,以匹配观察到的指标,例如,平均 CPU 利用率、平均内存利用率或你指定的任何其他自定义指标。

​ 对于按 Pod 统计的资源指标(如 CPU),控制器从资源指标 API 中获取每一个 HorizontalPodAutoscaler 指定的Pod 的 metrics 值,如果设置了目标使用率,控制器获取每个 Pod 中的容器资源使用情况,并计算资源使用率。如果设置了 target 值,将直接使用原始数据(不再计算百分比)。接下来,控制器根据平均的资源使用率或原始值计算出扩缩的比例,进而计算出目标副本数。

需要注意的是,如果 Pod 某些容器不支持资源采集,那么控制器将不会使用该 Pod 的 CPU 使用率。

​ 如果 Pod 使用自定义指示,控制器机制与资源指标类似,区别在于自定义指标只使用原始值,而不是使用率。如果 Pod 使用对象指标和外部指标(每个指标描述一个对象信息)。 这个指标将直接根据目标设定值相比较,并生成一个上面提到的扩缩比例。 在 autoscaling/v2beta2 版本 API 中,这个指标也可以根据 Pod 数量平分后再计算。

​ 对 Metrics API 的支持解释了这些不同 API 的稳定性保证和支持状态。

​ HorizontalPodAutoscaler 控制器访问支持扩缩的相应工作负载资源(例如:Deployment 和 StatefulSet)。这些资源每个都有一个名为 scale 的子资源,该接口允许你动态设置副本的数量并检查它们的每个当前状态。

Metrics Server(监控指标服务器)

​ Kubernetes 将水平 Pod 自动扩缩实现为一个间歇运行的控制回路(不是一个连续的过程)。间隔由 kubecontroller-manager--horizontal-pod-autoscaler-sync-period 参数设置(默认间隔为 15 秒)。

​ 在每个时间段内,控制器都会根据每个 HorizontalPodAutoscaler 对象中指定的指标查询资源利用率。控制器找到由**scaleTargetRef **定义的目标资源,然后根据目标资源的 .spec.selector 标签选择 Pod, 并从资源 MetricsAPI(针对每个 Pod 的资源指标)或自定义指标获取指标 API(适用于所有其他指标)。

​ 而 HPA 通常会从聚合 API (metrics.k8s.io、custom.metrics.k8s.io 或 external.metrics.k8s.io)获取指标数据。 metrics.k8s.io API 通常由名为 Metrics Server 的插件提供,需要单独启动。Metrics Server可以通过标准的 Kubernetes API 把监控数据暴露出来,有了 Metrics Server 之后,我们就完全可以通过标准的Kubernetes API 来访问我们想要获取的监控数据了:

https://10.96.0.1/apis/metrics.k8s.io/v1beta1/namespaces/<namespace-name>/pods/<podname>

​ 比如当我们访问上面的 API 的时候,我们就可以获取到该 Pod 的资源数据,这些数据其实是来自于 kubelet 的**Summary API **采集而来的。不过需要说明的是我们这里可以通过标准的 API 来获取资源监控数据,并不是因为Metrics Server 就是 APIServer 的一部分,而是通过 Kubernetes 提供的 Aggregator 汇聚插件来实现的,是独立于 APIServer 之外运行的。

聚合 API

Aggregator 允许开发人员编写一个自己的服务,把这个服务注册到 Kubernetes 的 APIServer 里面去,这样我们就可以像原生的 APIServer 提供的 API 使用自己的 API 了,我们把自己的服务运行在 Kubernetes 集群里面,然后Kubernetes 的 Aggregator 通过 Service 名称就可以转发到我们自己写的 Service 里面去了。这样这个聚合层就带来了很多好处:

  • 增加了 API 的扩展性,开发人员可以编写自己的 API 服务来暴露他们想要的 API。
  • 丰富了 API,核心 kubernetes 团队阻止了很多新的 API 提案,通过允许开发人员将他们的 API 作为单独的服务公开,这样就无须社区繁杂的审查了。
  • 开发分阶段实验性 API,新的 API 可以在单独的聚合服务中开发,当它稳定之后,在合并会 APIServer 就很容易了。
  • 确保新 API 遵循 Kubernetes 约定,如果没有这里提出的机制,社区成员可能会被迫推出自己的东西,这样很可能造成社区成员和社区约定不一致。

安装

​ 所以现在我们要使用 HPA,就需要在集群中安装 Metrics Server 服务,要安装 Metrics Server 就需要开启Aggregator,因为 Metrics Server 就是通过该代理进行扩展的,不过我们集群是通过 Kubeadm 搭建的,默认已经开启了,如果是二进制方式安装的集群,需要单独配置 kube-apsierver 添加如下所示的参数:

--requestheader-client-ca-file=<path to aggregator CA cert>
--requestheader-allowed-names=aggregator
--requestheader-extra-headers-prefix=X-Remote-Extra-
--requestheader-group-headers=X-Remote-Group
--requestheader-username-headers=X-Remote-User
--proxy-client-cert-file=<path to aggregator proxy cert>
--proxy-client-key-file=<path to aggregator proxy key>

验证是否开启 Aggregator

ubuntu@ubuntu:~/example/hpa_vpa$ kubectl get apiservices
NAME                                SERVICE   AVAILABLE   AGE
v1.                                 Local     True        8d
v1.admissionregistration.k8s.io     Local     True        8d
v1.apiextensions.k8s.io             Local     True        8d
v1.apps                             Local     True        8d
v1.authentication.k8s.io            Local     True        8d
v1.authorization.k8s.io             Local     True        8d
v1.autoscaling                      Local     True        8d
v1.batch                            Local     True        8d
v1.certificates.k8s.io              Local     True        8d
v1.configuration.konghq.com         Local     True        8d
v1.coordination.k8s.io              Local     True        8d
v1.discovery.k8s.io                 Local     True        8d
v1.events.k8s.io                    Local     True        8d
v1.flowcontrol.apiserver.k8s.io     Local     True        8d
v1.networking.k8s.io                Local     True        8d
v1.node.k8s.io                      Local     True        8d
v1.policy                           Local     True        8d
v1.rbac.authorization.k8s.io        Local     True        8d
v1.scheduling.k8s.io                Local     True        8d
v1.storage.k8s.io                   Local     True        8d
v1alpha1.configuration.konghq.com   Local     True        8d
v1beta1.configuration.konghq.com    Local     True        8d
v2.autoscaling                      Local     True        8d
# AVAILABLE=True 表示对应的 API 已经可用。

如果 kube-proxy 没有和 APIServer 运行在同一台主机上,那么需要确保启用了如下 kube-apsierver 的参数:

--enable-aggregator-routing=true

Aggregator 聚合层启动完成后,就可以来安装 Metrics Server 了,我们可以获取该仓库的官方安装资源清单:

# 下载前去仓库看看兼容版本
sudo wget https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.8.0/components.yaml
# 运行
ubuntu@ubuntu:~$ kubectl apply -f ./components.yaml 
serviceaccount/metrics-server created
clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created
clusterrole.rbac.authorization.k8s.io/system:metrics-server created
rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created
clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created
clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created
service/metrics-server created
deployment.apps/metrics-server created
ubuntu@ubuntu:~$ kubectl get pods -n kube-system -l k8s-app=metrics-server
NAME                              READY   STATUS    RESTARTS   AGE
metrics-server-867d48dc9c-j9b9b   0/1     Running   0          62s
# 查看日志
ubuntu@ubuntu:~$ kubectl logs -f metrics-server-867d48dc9c-j9b9b -n kube-system
...
I0912 07:13:21.571900       1 server.go:192] "Failed probe" probe="metric-storage-ready" err="no metrics to serve"
I0912 07:13:31.573874       1 server.go:192] "Failed probe" probe="metric-storage-ready" err="no metrics to serve"
E0912 07:13:35.422208       1 scraper.go:149] "Failed to scrape node" err="Get \"https://192.168.236.103:10250/metrics/resource\": tls: failed to verify certificate: x509: cannot validate certificate for 192.168.236.103 because it doesn't contain any IP SANs" node="node2"
E0912 07:13:35.422812       1 scraper.go:149] "Failed to scrape node" err="Get \"https://192.168.236.101:10250/metrics/resource\": tls: failed to verify certificate: x509: cannot validate certificate for 192.168.236.101 because it doesn't contain any IP SANs" node="master"
E0912 07:13:35.437967       1 scraper.go:149] "Failed to scrape node" err="Get \"https://192.168.236.102:10250/metrics/resource\": tls: failed to verify certificate: x509: cannot validate certificate for 192.168.236.102 because it doesn't contain any IP SANs" node="node1"
...

​ 因为部署集群的时候,CA 证书并没有把各个节点的 IP 签上去,所以这里 Metrics Server 通过 IP 去请求时,提示签的证书没有对应的 IP(错误:x509: cannot validate certificate for xxxx because it doesn'tcontain any IP SANs),我们可以添加一个 --kubelet-insecure-tls 参数跳过证书校验:

直接禁用证书校验

    spec:containers:- args:- --cert-dir=/tmp- --secure-port=10250- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname- --kubelet-use-node-status-port- --metric-resolution=15s- --kubelet-insecure-tls # 禁用证书校验

重启验证

ubuntu@ubuntu:~$ kubectl apply -f ./components.yaml 
serviceaccount/metrics-server created
clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created
clusterrole.rbac.authorization.k8s.io/system:metrics-server created
rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created
clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created
clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created
service/metrics-server created
deployment.apps/metrics-server created
apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created
ubuntu@ubuntu:~$ kubectl get pods -n kube-system -l k8s-app=metrics-server
NAME                              READY   STATUS    RESTARTS   AGE
metrics-server-56fb9549f4-sgljk   0/1     Running   0          10s
ubuntu@ubuntu:~$ kubectl logs -f metrics-server-56fb9549f4-sgljk -n kube-system
I0912 07:31:21.701379       1 serving.go:380] Generated self-signed cert (/tmp/apiserver.crt, /tmp/apiserver.key)
I0912 07:31:22.029297       1 handler.go:288] Adding GroupVersion metrics.k8s.io v1beta1 to ResourceManager
I0912 07:31:22.134555       1 requestheader_controller.go:180] Starting RequestHeaderAuthRequestController
I0912 07:31:22.134563       1 configmap_cafile_content.go:205] "Starting controller" name="client-ca::kube-system::extension-apiserver-authentication::client-ca-file"
I0912 07:31:22.134586       1 shared_informer.go:350] "Waiting for caches to sync" controller="client-ca::kube-system::extension-apiserver-authentication::client-ca-file"
I0912 07:31:22.134578       1 shared_informer.go:350] "Waiting for caches to sync" controller="RequestHeaderAuthRequestController"
I0912 07:31:22.134715       1 configmap_cafile_content.go:205] "Starting controller" name="client-ca::kube-system::extension-apiserver-authentication::requestheader-client-ca-file"
I0912 07:31:22.134723       1 shared_informer.go:350] "Waiting for caches to sync" controller="client-ca::kube-system::extension-apiserver-authentication::requestheader-client-ca-file"
I0912 07:31:22.134871       1 dynamic_serving_content.go:135] "Starting controller" name="serving-cert::/tmp/apiserver.crt::/tmp/apiserver.key"
I0912 07:31:22.134914       1 secure_serving.go:211] Serving securely on [::]:10250
I0912 07:31:22.134944       1 tlsconfig.go:243] "Starting DynamicServingCertificateController"
I0912 07:31:22.235335       1 shared_informer.go:357] "Caches are synced" controller="client-ca::kube-system::extension-apiserver-authentication::requestheader-client-ca-file"
I0912 07:31:22.235485       1 shared_informer.go:357] "Caches are synced" controller="client-ca::kube-system::extension-apiserver-authentication::client-ca-file"
I0912 07:31:22.235463       1 shared_informer.go:357] "Caches are synced" controller="RequestHeaderAuthRequestController"
# 查看服务
ubuntu@ubuntu:~kubectl get apiservice | grep metricscs
v1beta1.metrics.k8s.io              kube-system/metrics-server   True        105s
# 尝试是否能获取到节点信息
ubuntu@ubuntu:~$ kubectl get --raw "/apis/metrics.k8s.io/v1beta1/nodes"
{"kind":"NodeMetricsList","apiVersion":"metrics.k8s.io/v1beta1","metadata":{},"items":[{"metadata":{"name":"master","creationTimestamp":"2025-09-12T07:33:38Z","labels":{"beta.kubernetes.io/arch":"amd64","beta.kubernetes.io/os":"linux","kubernetes.io/arch":"amd64","kubernetes.io/hostname":"master","kubernetes.io/os":"linux","node-role.kubernetes.io/control-plane":"","node.kubernetes.io/exclude-from-external-load-balancers":""}},"timestamp":"2025-09-12T07:33:30Z","window":"10.021s","usage":{"cpu":"69354355n","memory":"1408284Ki"}},{"metadata":{"name":"node1","creationTimestamp":"2025-09-12T07:33:38Z","labels":{"beta.kubernetes.io/arch":"amd64","beta.kubernetes.io/os":"linux","kubernetes.io/arch":"amd64","kubernetes.io/hostname":"node1","kubernetes.io/os":"linux"}},"timestamp":"2025-09-12T07:33:35Z","window":"20.013s","usage":{"cpu":"11092789n","memory":"622148Ki"}},{"metadata":{"name":"node2","creationTimestamp":"2025-09-12T07:33:38Z","labels":{"beta.kubernetes.io/arch":"amd64","beta.kubernetes.io/os":"linux","kubernetes.io/arch":"amd64","kubernetes.io/hostname":"node2","kubernetes.io/os":"linux"}},"timestamp":"2025-09-12T07:33:31Z","window":"10.009s","usage":{"cpu":"15286242n","memory":"654480Ki"}}]}
# 获取物理资源信息
ubuntu@ubuntu:~$ kubectl top nodes
NAME     CPU(cores)   CPU(%)   MEMORY(bytes)   MEMORY(%)   
master   59m          1%       1375Mi          36%         
node1    13m          0%       607Mi           16%         
node2    14m          0%       639Mi           16%         

HPA

​ 现在我们用 Deployment 来创建一个 Nginx Pod,然后利用 HPA 来进行自动扩缩容。资源清单如下所示:

apiVersion: apps/v1
kind: Deployment
metadata:name: hpa-demo
spec:replicas: 1selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: nginxports:- containerPort: 80
--- 
# HPA设置
apiVersion: autoscaling/v2   # 使用 HPA v2 API,支持更多 metrics 类型
kind: HorizontalPodAutoscaler
metadata:name: hpa-demo           # HPA 对象的名称
spec:scaleTargetRef:          # 指定 HPA 作用的目标对象apiVersion: apps/v1    # 目标对象的 API 版本kind: Deployment       # 目标对象类型,这里是 Deploymentname: hpa-demo         # 目标 Deployment 的名字minReplicas: 1           # 最小副本数maxReplicas: 10          # 最大副本数metrics:                 # 定义触发自动扩缩容的指标- type: Resource       # 指标类型,这里是资源类型(CPU 或内存)resource:name: cpu          # 指标名称:CPUtarget:type: Utilization           # 目标类型:平均使用率(百分比)averageUtilization: 10      # 目标 CPU 使用率为 10%,超过则扩容,低于则缩容

验证:

# 查看hpa信息
ubuntu@ubuntu:~/example/hpa_vpa$ kubectl describe hpa hpa-demo
Name:                                                  hpa-demo
Namespace:                                             default
Labels:                                                <none>
Annotations:                                           <none>
CreationTimestamp:                                     Fri, 12 Sep 2025 07:55:27 +0000
Reference:                                             Deployment/hpa-demo
Metrics:                                               ( current / target )resource cpu on pods  (as a percentage of request):  <unknown> / 10%
Min replicas:                                          1
Max replicas:                                          10
Deployment pods:                                       1 current / 0 desired
Conditions:Type           Status  Reason                   Message----           ------  ------                   -------AbleToScale    True    SucceededGetScale        the HPA controller was able to get the target's current scaleScalingActive  False   FailedGetResourceMetric  the HPA was unable to compute the replica count: failed to get cpu utilization: missing request for cpu in container nginx of Pod hpa-demo-86c57bc6b8-9vhdb
Events:Type     Reason                        Age               From                       Message----     ------                        ----              ----                       -------Warning  FailedGetResourceMetric       0s (x3 over 30s)  horizontal-pod-autoscaler  failed to get cpu utilization: missing request for cpu in container nginx of Pod hpa-demo-86c57bc6b8-9vhdbWarning  FailedComputeMetricsReplicas  0s (x3 over 30s)  horizontal-pod-autoscaler  invalid metrics (1 invalid out of 1), first error is: failed to get cpu resource metric value: failed to get cpu utilization: missing request for cpu in container nginx of Pod hpa-demo-86c57bc6b8-9vhdb
ubuntu@ubuntu:~/example/hpa_vpa$ 
# 我们可以看到上面的事件信息里面出现了 failed to get cpu utilization: missing request for cpu 这样的
# 错误信息。这是因为我们上面创建的 Pod 对象没有添加 request 资源声明,这样导致 HPA 读取不到 CPU 指标信息,
# 所以如果要想让 HPA 生效,对应的 Pod 资源必须添加 requests 资源声明,更新我们的资源清单文件:
# resources:
#   requests:
#     memory: 50Mi
#     cpu: 50m
ubuntu@ubuntu:~/example/hpa_vpa$ kubectl delete -f ./hpa-demo.yaml 
deployment.apps "hpa-demo" deleted
horizontalpodautoscaler.autoscaling "hpa-demo" deleted
ubuntu@ubuntu:~/example/hpa_vpa$ kubectl apply -f ./hpa-demo.yaml 
deployment.apps/hpa-demo created
horizontalpodautoscaler.autoscaling/hpa-demo created
ubuntu@ubuntu:~/example/hpa_vpa$ kubectl describe hpa hpa-demo
Name:                                                  hpa-demo
Namespace:                                             default
Labels:                                                <none>
Annotations:                                           <none>
CreationTimestamp:                                     Fri, 12 Sep 2025 07:58:12 +0000
Reference:                                             Deployment/hpa-demo
Metrics:                                               ( current / target )resource cpu on pods  (as a percentage of request):  <unknown> / 10%
Min replicas:                                          1
Max replicas:                                          10
Deployment pods:                                       0 current / 0 desired
Events:                                                <none>

CPU

进行压测:

# 一个终端执行
ubuntu@ubuntu:~/example/hpa_vpa$ kubectl get pods -l app=nginx -w -o wide
NAME                        READY   STATUS    RESTARTS   AGE    IP             NODE    NOMINATED NODE   READINESS GATES
hpa-demo-75f9486867-pcgbt   1/1     Running   0          113s   10.244.2.100   node1   <none>           <none>
# 一个终端执行
ubuntu@ubuntu:~$ kubectl get hpa -w
NAME       REFERENCE             TARGETS       MINPODS   MAXPODS   REPLICAS   AGE
hpa-demo   Deployment/hpa-demo   cpu: 0%/10%   1         10        1          2m46s
# 另一个终端执行
ubuntu@ubuntu:~/example/hpa_vpa$ kubectl run -it --image busybox test-hpa --restart=Never --rm /bin/sh
If you don't see a command prompt, try pressing enter.
/ # while true; do wget -q -O- http://10.244.2.100; done# 观察结果
# pod 侧
ubuntu@ubuntu:~/example/hpa_vpa$ kubectl get pods -l app=nginx -w -o wide
NAME                        READY   STATUS    RESTARTS   AGE    IP             NODE    NOMINATED NODE   READ
hpa-demo-75f9486867-pcgbt   1/1     Running   0          113s   10.244.2.100   node1   <none>           <non
hpa-demo-75f9486867-b84zn   0/1     Pending   0          0s     <none>         <none>   <none>           <none>
hpa-demo-75f9486867-b84zn   0/1     Pending   0          0s     <none>         node2    <none>           <none>
hpa-demo-75f9486867-pd9sd   0/1     Pending   0          0s     <none>         <none>   <none>           <none>
hpa-demo-75f9486867-7s5j9   0/1     Pending   0          0s     <none>         <none>   <none>           <none>
hpa-demo-75f9486867-pd9sd   0/1     Pending   0          0s     <none>         node1    <none>           <none>
hpa-demo-75f9486867-7s5j9   0/1     Pending   0          0s     <none>         node2    <none>           <none>
hpa-demo-75f9486867-b84zn   0/1     ContainerCreating   0          0s     <none>         node2    <none>           <none>
hpa-demo-75f9486867-pd9sd   0/1     ContainerCreating   0          0s     <none>         node1    <none>           <none>
hpa-demo-75f9486867-7s5j9   0/1     ContainerCreating   0          0s     <none>         node2    <none>           <none>
hpa-demo-75f9486867-b84zn   1/1     Running             0          4s     10.244.1.90    node2    <none>           <none>
hpa-demo-75f9486867-pd9sd   1/1     Running             0          4s     10.244.2.102   node1    <none>           <none>
hpa-demo-75f9486867-7s5j9   1/1     Running             0          6s     10.244.1.91    node2    <none>           <none>
hpa-demo-75f9486867-xwkl8   0/1     Pending             0          0s     <none>         <none>   <none>           <none>
hpa-demo-75f9486867-xwkl8   0/1     Pending             0          0s     <none>         node2    <none>           <none>
hpa-demo-75f9486867-9786g   0/1     Pending             0          0s     <none>         <none>   <none>           <none>
hpa-demo-75f9486867-lpvh8   0/1     Pending             0          0s     <none>         <none>   <none>           <none>
hpa-demo-75f9486867-wkgbt   0/1     Pending             0          0s     <none>         <none>   <none>           <none>
hpa-demo-75f9486867-lpvh8   0/1     Pending             0          0s     <none>         node1    <none>           <none>
hpa-demo-75f9486867-9786g   0/1     Pending             0          0s     <none>         node1    <none>           <none>
hpa-demo-75f9486867-xwkl8   0/1     ContainerCreating   0          0s     <none>         node2    <none>           <none>
hpa-demo-75f9486867-wkgbt   0/1     Pending             0          0s     <none>         node2    <none>           <none>
hpa-demo-75f9486867-9786g   0/1     ContainerCreating   0          0s     <none>         node1    <none>           <none>
hpa-demo-75f9486867-wkgbt   0/1     ContainerCreating   0          0s     <none>         node2    <none>           <none>
hpa-demo-75f9486867-lpvh8   0/1     ContainerCreating   0          0s     <none>         node1    <none>           <none>
hpa-demo-75f9486867-xwkl8   1/1     Running             0          4s     10.244.1.92    node2    <none>           <none>
hpa-demo-75f9486867-9786g   1/1     Running             0          4s     10.244.2.103   node1    <none>           <none>
hpa-demo-75f9486867-lpvh8   1/1     Running             0          6s     10.244.2.104   node1    <none>           <none>
hpa-demo-75f9486867-wkgbt   1/1     Running             0          7s     10.244.1.93    node2    <none>           <none>
hpa-demo-75f9486867-7pbvv   0/1     Pending             0          0s     <none>         <none>   <none>           <none>
hpa-demo-75f9486867-7pbvv   0/1     Pending             0          0s     <none>         node1    <none>           <none>
hpa-demo-75f9486867-q9jbq   0/1     Pending             0          0s     <none>         <none>   <none>           <none>
hpa-demo-75f9486867-q9jbq   0/1     Pending             0          0s     <none>         node2    <none>           <none>
hpa-demo-75f9486867-7pbvv   0/1     ContainerCreating   0          0s     <none>         node1    <none>           <none>
hpa-demo-75f9486867-q9jbq   0/1     ContainerCreating   0          0s     <none>         node2    <none>           <none>
hpa-demo-75f9486867-q9jbq   1/1     Running             0          3s     10.244.1.94    node2    <none>           <none>
hpa-demo-75f9486867-7pbvv   1/1     Running             0          4s     10.244.2.105   node1    <none>           <none># hpa侧
ubuntu@ubuntu:~$ kubectl get hpa -w
NAME       REFERENCE             TARGETS       MINPODS   MAXPODS   REPLICAS   AGE
hpa-demo   Deployment/hpa-demo   cpu: 0%/10%   1         10        1          2m46s
hpa-demo   Deployment/hpa-demo   cpu: 158%/10%   1         10        1          4m15s
hpa-demo   Deployment/hpa-demo   cpu: 180%/10%   1         10        4          4m30s
hpa-demo   Deployment/hpa-demo   cpu: 44%/10%    1         10        8          4m45s
hpa-demo   Deployment/hpa-demo   cpu: 35%/10%    1         10        10         5m
hpa-demo   Deployment/hpa-demo   cpu: 20%/10%    1         10        10         5m15s# 由于副本数量最大 10 所以数量就一直是这样了# 取消循环 观察减少副本的行为
ubuntu@ubuntu:~$ kubectl get hpa -w
NAME       REFERENCE             TARGETS       MINPODS   MAXPODS   REPLICAS   AGE
hpa-demo   Deployment/hpa-demo   cpu: 0%/10%   1         10        1          2m46s
hpa-demo   Deployment/hpa-demo   cpu: 158%/10%   1         10        1          4m15s
hpa-demo   Deployment/hpa-demo   cpu: 180%/10%   1         10        4          4m30s
hpa-demo   Deployment/hpa-demo   cpu: 44%/10%    1         10        8          4m45s
hpa-demo   Deployment/hpa-demo   cpu: 35%/10%    1         10        10         5m
hpa-demo   Deployment/hpa-demo   cpu: 20%/10%    1         10        10         5m15s
hpa-demo   Deployment/hpa-demo   cpu: 18%/10%    1         10        10         5m30s
hpa-demo   Deployment/hpa-demo   cpu: 17%/10%    1         10        10         6m15s
hpa-demo   Deployment/hpa-demo   cpu: 10%/10%    1         10        10         6m30s
hpa-demo   Deployment/hpa-demo   cpu: 0%/10%     1         10        10         6m45s
hpa-demo   Deployment/hpa-demo   cpu: 0%/10%     1         10        10         11m
hpa-demo   Deployment/hpa-demo   cpu: 0%/10%     1         10        10         11m
hpa-demo   Deployment/hpa-demo   cpu: 0%/10%     1         10        1          11m# 这里可以看到副本数量 不会立即减少大约等5min 后 会缩容

从 Kubernetes v1.12 版本开始我们可以通过设置 kube-controller-manager 组件的!"horizontalpod-autoscaler-downscale-stabilization 参数来设置一个持续时间,用于指定在当前操作完成后,HPA 必须等待多长时间才能执行另一次缩放操作。默认为 5 分钟,也就是默认需要等待 5 分钟后才会开始自动缩放。

内存

​ 要使用基于内存或者自定义指标进行扩缩容(现在的版本都必须依赖 metrics-server 这个项目)。现在我们再用Deployment 来创建一个 Nginx Pod,然后利用 HPA 来进行自动扩缩容。资源清单如下所示:

# hpa-mem-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: hpa-mem-demo       # Deployment 名称
spec:replicas: 1              # 初始副本数selector:matchLabels:app: nginx           # 用于匹配 Pod 的标签template:metadata:labels:app: nginx         # Pod 模板的标签,必须和 selector 匹配spec:volumes:- name: increase-mem-script    # 定义卷名configMap:name: increase-mem-config  # 使用的 ConfigMap 名称,挂载脚本或配置containers:- name: nginximage: nginx                  # 使用 nginx 镜像ports:- containerPort: 80        # 容器暴露端口volumeMounts:- name: increase-mem-scriptmountPath: /etc/script   # 将 ConfigMap 挂载到容器路径resources:requests:                   # Pod 启动时保证的资源请求memory: 50Micpu: 50msecurityContext:privileged: true           # 以特权模式运行容器(有高权限访问能力)

​ 这里和前面普通的应用有一些区别,我们将一个名为 increase-mem-config 的 ConfigMap 资源对象挂载到了容器中,该配置文件是用于后面增加容器内存占用的脚本,配置文件如下所示(这里就是弄了个资源对象,放了个sh脚本):

# increase-mem-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:name: increase-mem-config       # ConfigMap 名称,用于存放脚本
data:increase-mem.sh: |              # 脚本文件名称,使用多行字符串 (|) 表示#!/bin/bash# 创建临时目录,用于挂载 tmpfsmkdir /tmp/memory# 挂载一个大小为 40M 的 tmpfs 文件系统mount -t tmpfs -o size=40M tmpfs /tmp/memory# 在 tmpfs 中创建一个大文件,模拟内存占用dd if=/dev/zero of=/tmp/memory/block# 保持占用 60 秒sleep 60# 删除临时文件rm /tmp/memory/block# 卸载 tmpfsumount /tmp/memory# 删除临时目录rmdir /tmp/memory

​ 然后需要创建一个基于内存的 HPA 资源对象:

# hpa-mem.yaml
apiVersion: autoscaling/v2       # HPA 使用 v2 API,支持多种指标类型
kind: HorizontalPodAutoscaler
metadata:name: hpa-mem-demo             # HPA 对象名称namespace: default             # 所属命名空间
spec:scaleTargetRef:                # 指定 HPA 作用的目标对象apiVersion: apps/v1          # 目标对象的 API 版本kind: Deployment             # 目标对象类型name: hpa-mem-demo           # 目标 Deployment 名称minReplicas: 1                 # 最小副本数maxReplicas: 5                 # 最大副本数metrics:                        # 指定触发扩缩容的指标- type: Resource             # 指标类型为资源(CPU/内存)resource:name: memory             # 指标名称:内存target:type: Utilization      # 指标类型:平均使用率百分比averageUtilization: 30 # 目标内存使用率 30%,高于会扩容,低于会缩容

验证:

ubuntu@ubuntu:~/example/hpa_vpa$ kubectl apply -f ./hpa-mem-demo.yaml 
deployment.apps/hpa-mem-demo created
ubuntu@ubuntu:~/example/hpa_vpa$ kubectl apply -f ./increase-mem-cm.yaml 
configmap/increase-mem-config created
ubuntu@ubuntu:~/example/hpa_vpa$ kubectl apply -f ./hpa-mem.yaml 
horizontalpodautoscaler.autoscaling/hpa-mem-demo created
# 查看资源
ubuntu@ubuntu:~/example/hpa_vpa$ kubectl get pods -A -o wide
NAMESPACE      NAME                              READY   STATUS    RESTARTS         AGE     IP                NODE     NOMINATED NODE   READINESS GATES
default        hpa-mem-demo-77c8b5c447-k2dq4     1/1     Running   0                5m17s   10.244.2.106      node1    <none>           <none>
# 开始压测,一个观察hpv
ubuntu@ubuntu:~$  kubectl get hpa -w
NAME           REFERENCE                 TARGETS          MINPODS   MAXPODS   REPLICAS   AGE
hpa-mem-demo   Deployment/hpa-mem-demo   memory: 9%/30%   1         5         1          4m18s
# 一个压测
ubuntu@ubuntu:~/example/hpa_vpa$ kubectl exec -it hpa-mem-demo-77c8b5c447-k2dq4 -- /bin/bash
root@hpa-mem-demo-77c8b5c447-k2dq4:/# ls
bin   dev		   docker-entrypoint.sh  home  lib64  mnt  proc  run   srv  tmp  var
boot  docker-entrypoint.d  etc			 lib   media  opt  root  sbin  sys  usr
root@hpa-mem-demo-77c8b5c447-k2dq4:/# cd /etc/script/
root@hpa-mem-demo-77c8b5c447-k2dq4:/etc/script# ls
increase-mem.sh
root@hpa-mem-demo-77c8b5c447-k2dq4:/etc/script# source ./increase-mem.sh 
dd: writing to '/tmp/memory/block': No space left on device
81921+0 records in
81920+0 records out
41943040 bytes (42 MB, 40 MiB) copied, 0.129849 s, 323 MB/s
# 观察结果
ubuntu@ubuntu:~$  kubectl get hpa -w
NAME           REFERENCE                 TARGETS          MINPODS   MAXPODS   REPLICAS   AGE
hpa-mem-demo   Deployment/hpa-mem-demo   memory: 9%/30%   1         5         1          4m18s
hpa-mem-demo   Deployment/hpa-mem-demo   memory: 13%/30%   1         5         1          6m16s
hpa-mem-demo   Deployment/hpa-mem-demo   memory: 13%/30%   1         5         1          6m31s
hpa-mem-demo   Deployment/hpa-mem-demo   memory: 13%/30%   1         5         1          6m46s
hpa-mem-demo   Deployment/hpa-mem-demo   memory: 95%/30%   1         5         1          7m16s
hpa-mem-demo   Deployment/hpa-mem-demo   memory: 95%/30%   1         5         4          7m31s
hpa-mem-demo   Deployment/hpa-mem-demo   memory: 30%/30%   1         5         4          7m46s
hpa-mem-demo   Deployment/hpa-mem-demo   memory: 10%/30%   1         5         4          9m31s
hpa-mem-demo   Deployment/hpa-mem-demo   memory: 10%/30%   1         5         4          13m
hpa-mem-demo   Deployment/hpa-mem-demo   memory: 11%/30%   1         5         2          13m
hpa-mem-demo   Deployment/hpa-mem-demo   memory: 11%/30%   1         5         2          18m
hpa-mem-demo   Deployment/hpa-mem-demo   memory: 14%/30%   1         5         1          18m

可以看到内存使用已经超过了我们设定的 30% 这个阈值了,HPA 资源对象也已经触发了自动扩容,变成了 4 个副本了

扩缩容行为

​ 如果使用 v2 版本的 HPA API,我们还可以使用 behavior 字段来配置单独的放大和缩小行为,可以通过在 behavior 字段下设置 scaleUp 和/或 scaleDown 来指定这些行为。你可以指定一个稳定窗口,以防止扩缩目标的副本计数发生波动,扩缩策略还允许你在扩缩时控制副本的变化率。

扩缩策略(Behavior)

HPA 可以通过 behavior 字段自定义扩缩容策略。

  • 可以同时指定多个策略,当存在多个策略时,默认会选择 允许最大更改量的策略
  • 每个策略包含以下参数:
    • type:策略类型(PodsPercent
    • value:允许在指定时间内改变的副本数量或百分比
    • periodSeconds:时间窗口长度(秒),在该时间内允许的变更量

缩容策略示例(scaleDown)

behavior:scaleDown:policies:- type: Podsvalue: 4periodSeconds: 60- type: Percentvalue: 10periodSeconds: 60

说明:

  • 第一条策略:在 60 秒内最多缩容 4 个 Pod
  • 第二条策略:在 60 秒内最多缩容当前副本数的 10%
  • 策略选择逻辑
    • 默认选择允许最大更改量的策略
    • 当副本数 > 40 时,第二条策略生效
    • 当副本数 ≤ 40 时,第一条策略生效

示例说明:

  • 当前副本数为 80,目标副本数为 10:
    1. 第一轮迭代:应用第二条策略(10%),减少 8 个 Pod → 剩余 72 个
    2. 下一轮迭代:10% = 7.2,向上取整 8,继续缩容
    3. 当副本数 ≤ 40 时,切换到第一条策略,每次最多缩容 4 个 Pod

稳定窗口(Stabilization Window)

  • 当指标波动频繁时,稳定窗口用于限制副本数量的波动,避免频繁扩缩容导致不必要的 Pod 重建。
  • HPA 会查看 过去指定时间窗口内的期望状态,并选择最大值或最小值来决定缩容或扩容。

缩容稳定窗口示例

behavior:scaleDown:stabilizationWindowSeconds: 300

说明:

  • 过去 5 分钟内计算出的期望副本数都会被考虑
  • 仅适用于缩容,扩容没有稳定窗口,指标达到目标时立即扩容
  • 避免频繁删除 Pod,再触发重新创建

默认行为

  • 不需要指定所有字段,只需自定义需要的部分
  • HPA 会将自定义值与默认值合并
  • 默认行为:
    • 扩容:立即扩容,按指标计算增加副本
    • 缩容:采用 horizontal-pod-autoscaler-downscale-stabilization 参数值(默认 300 秒)限制缩容速度

扩容策略示例

behavior:scaleUp:policies:- type: Podsvalue: 4periodSeconds: 15- type: Percentvalue: 100periodSeconds: 15

说明:

  • 每 15 秒增加最多 4 个 Pod 或最多 100% 当前副本数
  • 扩容没有稳定窗口,目标会尽快达到 HPA 计算的期望状态

总结

缩容:有稳定窗口,避免频繁缩容;可以通过多条策略控制最大缩容量

扩容:无稳定窗口,目标指标达到时立即扩容;可通过策略控制最大扩容量

策略组合逻辑:当同时存在 Pods 与 Percent 策略,默认选择允许更大幅度更改的策略

VPA

​ VPA 全称 VerticalPodAutoscaler,即 Pod 的纵向扩缩容,和 HPA 是相对应的,其根据容器资源使用率自动设置CPU 和内存的 requests 及 limit,从而允许在节点上进行适当的调度,以便为每个 Pod 提供适当的资源。它既可以缩小过度请求资源的容器,也可以根据其使用情况随时提升资源不足的容量。我们可以通过 VPA 来自动资源配置提升管理效率、提高集群资源利用率。

​ VPA 主要由三个组件组成,分别为 recommender、updater、admission-controller

  • recommender:引入 VerticalPodAutoscaler 对象,其由 Pod 的标签选择器、资源策略(控制 VPA 如何计算资源)、更新策略(控制如何将更改应用于 Pod)和推荐的 Pod 资源组成,其根据 metric-server 获取到的容器指标并观测 OOM 事件,计算推荐指标,最终更新 VerticalPodAutoscaler 对象
  • updater:其是负责 Pod 更新的组件。如果 Pod 在 Auto 模式下使用 VPA,则 Updater 可以决定使用推荐器资源对其进行更新。这只是通过驱逐 Pod 以便使用新资源重新创建它来实现的。简单来说,其是根据 pod 的request 中设置的指标和 recommend 计算的推荐指标,在一定条件下驱逐 pod,
  • admission-controller:这是一个 webhook 组件,所有 Pod 创建请求都通过 VPA AdmissionController,如果 Pod 与 VerticalPodAutoscaler 对象匹配,把 recommend 计算出的指标应用到 pod 的request 和 limit,如果 Recommender 不可用,它会回退到 VPA 对象中缓存的推荐。

使用 VPA 主要会用到两个资源:VerticalPodAutoscaler 、VerticalPodAutoscalerCheckpoint

  • VerticalPodAutoscaler:该资源由用户创建,用于设置纵向扩容的目标对象和存储 recommend 组件计算出的推荐指标。
  • VerticalPodAutoscalerCheckpoint:该资源由 recommend 组件创建和维护,用于存储指标相关信息,一个vpa 对应的多个容器,每个容器创建一个该资源。

VPA 也需要依赖 metrics-server,所以也需要提前安装。然后我们可以通过下面命令来安装 VPA 相关组件。

# 查看是否安装
ubuntu@ubuntu:~$ kubectl get crds | grep verticalpodautoscalers
# 开始安装 千万不要sudo
ubuntu@ubuntu:~$ git clone https://github.com/kubernetes/autoscaler.git
ubuntu@ubuntu:~$ cd autoscaler/vertical-pod-autoscaler
ubuntu@ubuntu:~$ ./hack/vpa-up.sh
# 证书权限问题
ubuntu@ubuntu:~/autoscaler/vertical-pod-autoscaler$ sudo rm -rf /tmp/vpa-certs
ubuntu@ubuntu:~/autoscaler/vertical-pod-autoscaler$ mkdir -p /tmp/vpa-certs
ubuntu@ubuntu:~/autoscaler/vertical-pod-autoscaler$ sudo chown $USER:$USER /tmp/vpa-certs
ubuntu@ubuntu:~/autoscaler/vertical-pod-autoscaler$ sudo chmod 700 /tmp/vpa-certs
ubuntu@ubuntu:~/autoscaler/vertical-pod-autoscaler$ ./hack/vpa-up.sh
# 查看是否安装成功
ubuntu@ubuntu:~/autoscaler/vertical-pod-autoscaler$  kubectl get crds | grep verticalpodautoscalers
verticalpodautoscalers.autoscaling.k8s.io             2025-09-12T09:34:57Z
# 查看相关pod
ubuntu@ubuntu:~/autoscaler/vertical-pod-autoscaler$ kubectl get pods -n kube-system |grep vpa
vpa-admission-controller-84998b6899-7g2bh   1/1     Running   0                4m23s
vpa-recommender-6d7fbcb5f6-vfncg            1/1     Running   0                4m23s
vpa-updater-864ff5f65f-wj5dz                1/1     Running   0                4m23s

VPA使用

资源文件:

# vpa-demo-with-vpa.yaml
---
# 部署 Deployment 对象
apiVersion: apps/v1
kind: Deployment
metadata:name: vpa-demo   # Deployment 名称
spec:replicas: 1      # 副本数量selector:matchLabels:app: vpa    # 选择标签,匹配 Podtemplate:metadata:labels:app: vpa  # Pod 的标签spec:containers:- name: nginx       # 容器名称image: nginx      # 镜像resources:requests:cpu: 20m      # 初始 CPU 请求memory: 25Mi  # 初始内存请求
---
# VerticalPodAutoscaler 对象
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:name: nginx-vpa-test  # VPA 名称
spec:targetRef:apiVersion: apps/v1kind: Deploymentname: vpa-demo       # VPA 作用的目标 DeploymentupdatePolicy:updateMode: "Off"    # 更新模式:Off 表示不自动更新 Pod,只监控resourcePolicy:containerPolicies:- containerName: nginx  # 对哪个容器应用策略minAllowed:cpu: 50m          # 最小允许 CPUmemory: 50Mi      # 最小允许内存maxAllowed:cpu: 2000m         # 最大允许 CPUmemory: 2048Mi     # 最大允许内存

验证:

ubuntu@ubuntu:~/example/hpa_vpa$ kubectl apply -f ./vpa-demo-with-vpa.yaml 
deployment.apps/vpa-demo unchanged
verticalpodautoscaler.autoscaling.k8s.io/nginx-vpa-test created
# 查看Pod状态
ubuntu@ubuntu:~/example/hpa_vpa$ kubectl get pods -A -o wide
NAMESPACE      NAME                                        READY   STATUS    RESTARTS      AGE     IP                NODE     NOMINATED NODE   READINESS GATES
default        vpa-demo-85b64c5555-dtx95                   1/1     Running   0             70s     10.244.2.111      node1    <none>           <none>
# 先看状态
ubuntu@ubuntu:~/example/hpa_vpa$ kubectl describe vpa nginx-vpa
Name:         nginx-vpa-test
Namespace:    default
Labels:       <none>
Annotations:  <none>
API Version:  autoscaling.k8s.io/v1
Kind:         VerticalPodAutoscaler
Metadata:Creation Timestamp:  2025-09-12T09:56:10ZGeneration:          1Resource Version:    247343UID:                 f81b5af8-6b56-4a82-8627-5e3078949bc4
Spec:Resource Policy:Container Policies:Container Name:  nginxMax Allowed:Cpu:     2000mMemory:  2048MiMin Allowed:Cpu:     50mMemory:  50MiTarget Ref:API Version:  apps/v1Kind:         DeploymentName:         vpa-demoUpdate Policy:Update Mode:  Off
Status:Conditions:Last Transition Time:  2025-09-12T09:56:12ZMessage:               No pods match this VPA objectReason:                NoPodsMatchedStatus:                TrueType:                  NoPodsMatchedLast Transition Time:  2025-09-12T09:56:12ZStatus:                TrueType:                  RecommendationProvidedRecommendation:Container Recommendations:Container Name:  nginxLower Bound:Cpu:     50mMemory:  262144kTarget:Cpu:     50mMemory:  262144kUncapped Target:Cpu:     25mMemory:  262144kUpper Bound:Cpu:     2Memory:  1523828767
Events:          <none># 一个终端压测
ubuntu@ubuntu:~$ kubectl run -it --image busybox test-vpa --restart=Never --rm /bin/sh
If you don't see a command prompt, try pressing enter.
/ # while true; do wget -q -O- http://10.244.2.111; done# 一个终端再次观察
ubuntu@ubuntu:~/example/hpa_vpa$ kubectl describe vpa nginx-vpa |tail -n 20Last Transition Time:  2025-09-12T09:56:12ZStatus:                TrueType:                  RecommendationProvidedRecommendation:Container Recommendations:Container Name:  nginxLower Bound:Cpu:     50mMemory:  262144kTarget:Cpu:     50mMemory:  262144kUncapped Target:Cpu:     35mMemory:  262144kUpper Bound:Cpu:     2Memory:  1194357142
Events:          <none>
# 可以看到   Uncapped Target: 的值变化了

​ 从上面可以看到给出的 Target 为 143m,因为设置 updateMode:"Off",所以不会应用到 Pod。

​ Vertical Pod Autoscaler (VPA) 中的 updateMode 有以下几种有效选项:

  • Off:VPA 只会提供资源建议,不会自动更改 Pod 的资源请求。

  • Initial:VPA 只在 Pod 创建时分配资源请求,以后不会再修改。

  • Recreate:VPA 在 Pod 创建时分配资源请求,并通过驱逐和重新创建现有 Pod 来更新资源。

  • Auto:VPA 根据资源建议自动重新创建 Pod,实现资源动态调整。

​ 当然 VPA 也并不是万能的,具有一些局限性,在使用的时候以下注意事项值得我们关注:

  • 不要将 VPA 与 HPA 一起使用,后者基于相同的资源指标(例如 CPU 和 MEMORY 使用率)进行缩放。这是因为当指标(CPU/MEMORY)达到其定义的阈值时,VPA 和 HPA 将同时发生缩放事件,这可能会产生未知的副作用并可能导致问题。
  • VPA 可能会推荐比集群中可用的资源更多的资源,从而导致 Pod 未分配给节点(由于资源不足),因此永远不会运行。
  • VPA 不会驱逐不在控制器下运行的 pod,驱逐可以单独处理

​ 为了能够自动资源配置提升管理效率、提高集群资源利用率,除了 VPA 之外,我们后续还会学习其他更智能更适合生产环境使用的工具,不过 VPA 的实现思路值得我们学习。

相关文章:

9.HPA与VPA

HPA 与 VPA ​ 在前面的学习中我们使用了一个 kubectl scale 命令可以来实现 Pod 的扩缩容功能,但是这个是完全手动操作的,要应对线上的各种复杂情况,我们需要能够做到自动化去感知业务,来自动进行扩缩容。为此,Kubernetes 也为我们提供了这样的一个资源对象:Horizontal …...

MyEMS在行动:揭秘开源能源管理系统如何重塑工业与楼宇的能效未来

当“节能降耗”从一个口号变为一项关乎企业生存与发展的关键指标时,背后的管理工具便成为了决胜因素。Across the globe, 从德国的智能工厂到中国的绿色数据中心,一款名为MyEMS的开源系统正在悄然推动一场静悄悄的能源效率革命。 本文将通过场景化的视角,深入剖析MyEMS在不同…...

题解:P14015 [ICPC 2024 Nanjing R] 生日礼物

更差的阅读体验经典套路,我个人认为是橙题。 相邻相等不好刻画,我们直接把偶数位置反转,这样一组相邻相等中恰好有一个被反转,变成删除相邻不同。 那么假设没有 \(2\),最终序列中一定只有 \(0\) 或 \(1\)。所以假设 \(0,1\) 个数分别是 \(c_0, c_1\),那么由于一次消除一个…...

吻得太逼真

无论怎么讲我都觉得虚伪 陪伴你那么久你说是受罪 从前到现在当我是谁 你这花心蝴蝶 昨夜陪你醉伤到我心碎 你竟说我和你不配 完全忘记往日为何 能与我彻夜缠绵 和你吻吻吻吻吻 你吻得太逼真 让我把虚情假意 当作最真心的亲吻 怪自己来不及区分 你对我是酷爱是敷衍 我想问问问问…...

HyperWorks许可回收机制

随着企业业务的不断发展和工程设计的复杂性增加,软件许可资源的有效利用变得尤为重要。在这样的背景下,HyperWorks引入了智能的许可回收机制,旨在帮助企业更好地管理和再利用许可资源,提升效率和成本效益。 一、什么是HyperWorks许可回收机制? HyperWorks许可回收机制是一…...

flink on k8s的基本介绍

本文分享自天翼云开发者社区《flink on k8s的基本介绍》,作者:l****n 一、背景介绍 Apache Flink 是一个流处理引擎,具有高效的流处理和批处理能力,以及良好的可伸缩性和容错性。Kubernetes(简称 K8s)是一种容器编排系统,用于自动化容器部署、扩展和管理。将 Flink 部署…...

高性能计算基础

高性能计算基础 1 性能评估指标和测试工具 2 CPU流水线、推测窒息和分支优化 3 现代内存架构、访问模式以及对算法和数据结构设计的影响 4 多线程和并发工作原理 5 锁、无锁和无等待 6 线程安全的数据结构 7 并发编程 8 零拷贝 9 编译器优化基础知识 10 高性能编程设计总结...

flutter开发window打包成exe可执行文件的步骤

1. 环境准备,以及打包步骤说明环境自己准备,这篇文章只是说明打包步骤,是在项目能运行起来的前提下进行的。 cd 到项目的根目录下 fluttter pub get //更新项目依赖 flutter build windows -t lib/main_development.dart // -t指定程序入口文件,执行完可以生成可执行…...

Transtion动画组件要求包裹元素必须是单一根节点

在 Vue 3 中,组件的模板支持多个根节点(这被称为 Fragments)。虽然这提高了灵活性,但却与 <Transition> 组件的要求冲突了。<Transition> 组件的工作原理是通过在动画的不同阶段(进入/离开)为单个根元素添加或移除 CSS 类(如 v-enter-from, v-enter-active,…...

linux启动ntp服务

linux启动ntp服务服务端修改参数: vi /etc/chrony.conf客户端指定服务端地址:...

企业级 AI Agent 开发指南:基于函数计算 FC Sandbox 方案实现类 Chat Coding AI Agent

使用 AI 网关和 MSE Nacos 也有比较成熟的落地方案,所以今天通过真实案例,向大家分享再进阶一点的 Sandbox 的落地实践。作者:计缘 前言 我之前写过两篇如何构建 AI 应用/AI Agent 的文章,里面涵盖了多个环节,多个领域的组件,整体的核心思路是想表达AI应用的本质是以 AI …...

android开发局域网内通过NTP服务端自动更新系统时间

1. 问题:如果设备有机会处于外网,一般不会有系统时间自动同步问题,但是存在一些使用场景就是设备一直处于局域网环境,如果设备关机一段时间了,再启动设备后,时间可能是1970或者其实错误时间 2. 解决方法:系统时间的自动更新是通过ntp server服务在外网可用时自动请求和同…...

一招解决Proxmox VE虚拟机磁盘空间耗尽:LVM在线扩容实战 - 若

本文将记录一次完美的线上故障排除:在不重启服务、不停机的情况下,解决Proxmox VE中Ubuntu虚拟机根目录磁盘空间100%被占满的问题。问题场景:空间告急,服务危在旦夕 在管理一台名为 tools1 的Proxmox虚拟机时,系统突然报警。登录后执行 df -h 检查,发现根目录使用率已达1…...

jiaozi

教育观(素质教育的内涵):素质教育以提高国民素质为根本宗旨是 面向全体学生的教育是 促进学生全面发展的教育是 促进学生个性发展的教育 是   以培养学生创新精神和实践能力为重点的教育 教学观: 教学从”教育者为中心” 转向 “学习者为中心” 教学从“…...

基于Linux系统的定制软件安装硬件设备选型指南

用户需求分析与选择标准 核心需求分析Linux作系统支持 :设备必须预安装或支持主流 Linux 发行版。软件定制能力 :提供完整的开发环境和包管理支持。硬件性能 :足够的计算能力来运行自定义应用程序。接口扩展性 :丰富的I/O接口,满足多样化的应用场景。选择评估维度评估维度…...

c++之is_trivially_default_constructible

is_trivially_default_constructible 是 C++ 标准库中的类型特性工具,用于检查类型是否具有平凡的默认构造函数。以下是关键信息:定义与用途该工具属于 <type_traits> 头文件,用于编译时查询类型是否满足以下条件: 类型具有平凡的默认构造函数(无需特殊操作即可构…...

python3协程学习-async,await

参考文档: https://cloud.tencent.com/developer/article/2002528 https://cloud.tencent.com/developer/article/2480588?policyId=1004 什么是协程 https://docs.python.org/3.11/glossary.html#term-coroutine 协程:Coroutines are a more generalized form of subroutin…...

猫树分治

猫树分治,又称二区间合并,一种可以用 \(O(n\log n)\) 时空复杂度预处理,\(O(1)\) 处理区间询问的算法,与 cdq 和整体二分类似。 我们考虑线段树上,我们通过 pushup 操作不断合并两个区间,做到查询 \(O(\log n)\) 个区间回答询问,但是如果没有修改操作,我们可以只询问 \…...

Rust太难了。。。。。。。

rust是我学习过的除汇编之外最难的编程语言,难到什么程度? AI写的都是tm的错误,bug。AI在其他语言上面几乎不可能...

AI导航生成寻路点-FindPathToLocationSynchronously

FindPathToLocationSynchronously() example:FHitResult Hit;if (GetHitResultUnderCursor(ECC_PhysicsBody, false, Hit)){ CacheDestination = Hit.ImpactPoint;}if (UNavigationPath* NavPath = UNavigationSystemV1::FindPathToLocationSynchronously(this, Controll…...

cache写策略

cache写策略 写命中 全写法 当cpu对cache写命中时,必须把数据同时写入cache和主存,一般使用写缓冲 cpu不会一直在写入数据,当cpu去做其他事情的时候,会有一个控制电路,把数据从写缓冲逐一写入到主存 使用写缓冲,cpu写的速度很快,如果写操作不频繁,则效果很好,如果写操…...

个人微信开发

开发微信机器人需要以下几个基本概念:机器人接口开发:框架提供了开放接口,可以通过这些接口对微信进行操作。如接收用户消息、发送消息、操作朋友圈等。 自然语言处理:机器人需要能够理解自然语言,以便能够识别用户输入的意图,并做出相应的回应。自然语言处理包括文本分析…...

C++之std::is_trivially_copyable

在C++11中,平凡类型(Trivial Type)、平凡可复制类型(TrivialCopyable)、标准布局类型(Standard-layout Type) 是描述类在内存中布局特性的术语,它们与类的构造、拷贝、赋值和销毁行为有关,也影响着类的内存布局和对齐方式。 下面用通俗的语言解释这些概念: 平凡类型 …...

PostgreSQL技术大讲堂 - 第104讲:PostgreSQL分区表应用实践

PostgreSQL从入门到精通系列课程,100+节PG技术讲解,让你从小白一步步成长为独当一面的PG专业人员,点击这里查看章节内容,持续更新,欢迎加入。 第104讲:PostgreSQL分区表应用实践--让你速度提高20倍1、什么是基于哈希的分区?2、两级分区介绍3、catalog 查找开销4、pg_has…...

redis实现缓存1-添加商户缓存

首先我们理解计算机硬件层面的缓存 (CPU Cache)。 计算机存储系统是一个金字塔结构,越靠近塔顶(CPU)的部件,速度越快、容量越小、成本越高;越靠近塔底,速度越慢、容量越大、成本越低。 缓存速度最快但容量最小,用于存储CPU立即需要的数据;内存作为中间层,存储正在运行…...

qemu的外部快照实现原理

一 基础概念 1 外部快照 当一个快照被创建时,创建时当前的状态保存在当前使用的磁盘文件中,即成为一个backing file。此时一个新的overlay被创建出来保存往后的数据。 2 backing file和overlay 对基础镜像做外部快照,生成的快照文件被称为overlay,基础镜像成为backing file…...

Springboot 集成 飞书群消息

Springboot 集成 飞书群消息前情概要 公司项目想要加入一个系统错误推送功能,方便线上项目运维,可选择的消息通知渠道很多,比如邮箱、短信、微信、飞书等等,但是邮箱每天有发送数量上限,而且还有其他必须要使用邮箱发送的功能,所以为了不影响必要功能的运行,邮箱不可取,…...

最新爆料:GitHub Copilot全面推出OpenAI GPT-5 和 GPT-5 mini!

最新爆料:GitHub Copilot全面推出OpenAI GPT-5 和 GPT-5 mini!OpenAI最新推出的GPT-5和GPT-5mini已全面接入GitHub Copilot,其中GPT-5mini面向所有用户开放,GPT-5仅限付费用户使用。用户可在主流开发环境和GitHub移动端通过模型选取器访问这些功能。企业版和商业版用户需管…...

netstat 命令查看端口状态详解

netstat 命令查看端口状态详解 转载请注明出处:netstat 可以查看服务器当前端口列表及指定端口的连接状态等;-t : 指明显示TCP端口,t是TCP的首字母。-u : 指明显示UDP端口,u是UDP的首字母-p : 显示进程标识符和程序名称,每一个套接字/端口都属于一个程序,p是program的首字…...

智聘无界:AI 破解全球化招聘合规、成本与人才匹配难题的实践路径

引言:全球化浪潮下的招聘新挑战 在全球经济一体化进程加速的今天,企业边界日益模糊,跨国经营已成为常态。然而,伴随而来的全球化人才招聘难题也愈发凸显。传统招聘模式在面对日益复杂、多元的国际市场时,显得力不从心,主要表现为人才获取效率低下、运营成本高昂以及难以适…...

Nature | 本周最新文献速递

Molecular subtypes of human skeletal muscle in cancer cachexia 中文标题: 破解癌症恶病质肌肉谜团!整合RNA组学揭示两大分子亚型预示预后 关键词: 癌症恶病质、分子亚型、RNA组学、非负矩阵分解、肌肉萎缩 摘要总结: 这篇文章通过高通量测序分析结直肠癌和胰腺癌患者肌…...

Flink 与Flink可视化平台StreamPark教程(CDC功能)

本文分享自天翼云开发者社区《Flink 与Flink可视化平台StreamPark教程(CDC功能)》,作者:l****n 基本概念 flinkCDC功能是面向binlog进行同步、对数据的增删改进行同步的工具,能够实现对数据的动态监听。目前其实现原理主要为监听数据源的binlog对数据的变化有所感知。 在这…...

GAS_Aura-Setting Up Auto Running

1讲了使用Nav导航生成样条线驯寻路点进行移动...

Ubuntu 24.04 LTS 登录用户和密码忘记找回方法

1.重启服务器时按住Shift键位进入GNU GRUB界面,按向下方向键选择 *Advanced options for Ubuntu 回车2.拨动向下方向键,选择恢复模式 recovery mode 3.等待系统执行,拨动向下键进入root shell 4.在 root shell 提示符下,输入以下命令来列出系统中所有的用户:ls /home5.最后…...

错排问题

https://www.bilibili.com/video/BV1ZwmtYwEsK 第一个视频 https://www.bilibili.com/video/BV1Mw4m1y7xT...

源码调试-带你了解下车牌识别的深度学习模型-LPRNet

本期视频介绍了基于PyTorch的车牌识别模型LPRNet的调试运行过程。主要内容包括:1)项目结构分析和环境配置;2)单张图片识别代码实现,涵盖图像预处理、模型预测和结果可视化;3)注意事项说明。该模型支持蓝牌和新能源车牌识别,具有轻量级特性,适合实际应用开发。视频详细…...

仓储物流业务字段(一)

以下是整理的100个仓储物流数据库常用字段名,分类归纳如下: 基础信息类 仓库编码(warehouse_code) 仓库名称(warehouse_name) 仓库地址(warehouse_address) 仓库类型(warehouse_type) 负责人(manager) 容量(capacity) 仓库状态(status) 安全要求(safety_requi…...

ubuntu 24.04部署mysql8.0.41(glibc2.28)

环境Os:ubuntu 24.04 desktop桌面版mysql:8.0.41 glibc2.28查看操作系统信息root@db:/soft# uname -a Linux db 6.14.0-29-generic #29~24.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Aug 14 16:52:50 UTC 2 x86_64 x86_64 x86_64 GNU/Linuxroot@db:/soft# cat /etc/os-release PRET…...

cmakelist文件中常见语句的含义

最近在进行c++代码的编译,发现cmakelist文件中有很多语句。一开始小白并不理解什么含义,学习后特此记录,以方便以后自己查阅。 情况一:单个模块,无主模块包含多个子模块的情况 文件目录如下:MyProject/ ├── CMakeLists.txt ├── include/ │ └── my_library.h …...

charles破解-在线生成激活码

charles破解下载最新Charles,官网地址:Charles官网下载安装后,使用破解工具自动生成激活码Charles激活码自动生成工具具体用法如下:打开激活工具,输入RegisterName名称,名称可任意输入,点击生成即可自动生成激活码打开Charles,点击help,选择Register Charles,输入生成…...

微信个人号开发

微信个人号二次开发,是完整的第三方服务平台,并基于IPAD协议8.0.57开发出的最新个微API服务框架。 你可以 通过API 实现 个性化微信功能 (例云发单助手、社群小助手、客服系统、机器人等),用来自动管理微信消息。用户仅可一次对接,完善所有功能。可实现分布式部署,批量管…...

内部排序-直接插入排序冒泡排序快速排序对比

内部排序-直接插入排序冒泡排序快速排序对比内部排序-内部排序-直接插入排序冒泡排序快速排序对比 写在前面:参考《数据结构(C语言版)》严蔚敏 吴伟民 编著 清华大学出版社 2008年10月第27次印刷 📋 算法概述 直接插入排序(Straight Insertion Sort)是一种最简单的排…...

STM32读写EEPROM

代码如下#include "i2c.h" #include <string.h>/* M24C64设备地址(A0/A1/A2接地,7位地址为0x50,左移1位后为0xA0) */ #define EEPROM_ADDR (0x50 << 1) #define M24C64_PAGE_SIZE 32 // 页面大小:32字节 #define M24C64_WR…...

OpenStack Nova 创建虚拟机

创建虚拟机的过程是一个经典的分布式、异步、状态驱动的工作流。其核心设计哲学是:API 接收请求 -> 调度决策 -> 资源分配 -> 虚拟化层执行。整个过程涉及多个 Nova 服务以及外部组件(Glance, Neutron, Cinder, Keystone)。 1、基本流程 sequenceDiagramparticipan…...

AI革命2025:新一代人力资源管理系统十大标杆产品评测

导读:在数字化浪潮推动下,AI与移动技术正在重塑人力资源管理系统的行业格局。本文盘点了2025年中国市场十款主流智能人力资源管理系统,涵盖集团型、成长型及中小企业的核心需求。重点介绍红海eHR在AI智能体、移动端全流程和数据驱动决策上的创新优势,并通过多维度评分与场景…...

企业HR系统选型全指南:百人初创到万人集团的数字化方案与实施路径

导读:本篇文章围绕企业不同规模的人力资源管理需求,梳理了从百人初创到万人集团的HR系统选型逻辑。通过分层痛点分析、科学评估体系、信息密集对比表和真实案例,并系统推荐了包括i人事、北森、红海云在内的多款市场热门产品,助力企业高效推进HR数字化转型。本文属于深度内容…...

C++ auto关键字

C++ auto关键字的原理与使用auto关键字: 一、C++98标准auto关键字的作用和C语言的相同,表示自动变量,是关于变量存储位置的类型饰词,通常不写,因为局部变量的默认存储就是auto 1 void foo(void) 2 { 3 int a; //变量存储在栈区 4 auto int b; //…...

API 响应体加密场景下的调试实践:Postman 的局限与 Apipost 的优化

在日常开发和测试过程中,我们经常会遇到如下场景: 后端服务出于安全性或协议规范的考虑,对 API 的响应体进行了加密或编码处理,例如 Base64 编码、AES/RSA 加密等。这样做在生产环境中是合理且必要的,能够避免敏感数据被明文传输。但与此同时,也为开发和测试阶段的调试带…...

ARM主板:低功耗高性能的嵌入式计算核心

在当今数字化飞速发展的时代,计算机硬件领域不断创新变革,其中ARM主板凭借其独特的优势脱颖而出,成为众多应用场景的理想选择。无论是智能家居、工业自动化还是物联网设备等,都能看到它活跃的身影。下面将深入探讨ARM主板的相关特性、优势以及广泛的应用场景。 什么是ARM主…...

2025绩效管理必知

HR 往往是一个企业绩效管理的推动者,但是在推动的背后,实际有一个非常重要的目标,那就是提高个人和团队的绩效,从而提升企业整体的绩效。绩效管理就是要找到 “应该实现什么 “和 “如何实现 “这些问题的答案。它是关于寻找更有效的方法来提高业务绩效。 绩效管理关注什么…...