k8s之Horizontal Pod Autoscaler(Pod水平自动伸缩)

本文介绍了如何在Kubernetes中启用Pod水平自动扩缩功能,包括设置metrics-server、创建Deployment和PHP-Apache应用、配置HorizontalPodAutoscaler,并通过实例展示如何根据CPU利用率动态调整Pod副本数。重点在于自动扩缩原理和实战操作步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

官方文档:Pod 水平自动扩缩 | Kubernetesicon-default.png?t=M0H8https://kubernetes.io/zh/docs/tasks/run-application/horizontal-pod-autoscale/

Pod 水平自动扩缩(Horizontal Pod Autoscaler) 可以基于 CPU 利用率自动扩缩 ReplicationController、Deployment、ReplicaSet 和 StatefulSet 中的 Pod 数量。 除了 CPU 利用率,也可以基于其他应程序提供的 自定义度量指标 来执行自动扩缩。 Pod 自动扩缩不适用于无法扩缩的对象,比如 DaemonSet。

Pod 水平自动扩缩特性由 Kubernetes API 资源和控制器实现。资源决定了控制器的行为。 控制器会周期性地调整副本控制器或 Deployment 中的副本数量,以使得类似 Pod 平均 CPU 利用率、平均内存利用率这类观测到的度量值与用户所设定的目标值匹配

首先需要部署一下metrics-server,收集集群资源利用率

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: system:aggregated-metrics-reader
  labels:
    rbac.authorization.k8s.io/aggregate-to-view: "true"
    rbac.authorization.k8s.io/aggregate-to-edit: "true"
    rbac.authorization.k8s.io/aggregate-to-admin: "true"
rules:
- apiGroups: ["metrics.k8s.io"]
  resources: ["pods", "nodes"]
  verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: metrics-server:system:auth-delegator
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:auth-delegator
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: metrics-server-auth-reader
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: extension-apiserver-authentication-reader
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
---
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
  name: v1beta1.metrics.k8s.io
spec:
  service:
    name: metrics-server
    namespace: kube-system
  group: metrics.k8s.io
  version: v1beta1
  insecureSkipTLSVerify: true
  groupPriorityMinimum: 100
  versionPriority: 100
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: metrics-server
  namespace: kube-system
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: metrics-server
  namespace: kube-system
  labels:
    k8s-app: metrics-server
spec:
  selector:
    matchLabels:
      k8s-app: metrics-server
  template:
    metadata:
      name: metrics-server
      labels:
        k8s-app: metrics-server
    spec:
      serviceAccountName: metrics-server
      volumes:
      # mount in tmp so we can safely use from-scratch images and/or read-only containers
      - name: tmp-dir
        emptyDir: {}
      containers:
      - name: metrics-server
        image: lizhenliang/metrics-server:v0.3.7 
        imagePullPolicy: IfNotPresent
        args:
          - --cert-dir=/tmp
          - --secure-port=4443
          - --kubelet-insecure-tls
          - --kubelet-preferred-address-types=InternalIP
        ports:
        - name: main-port
          containerPort: 4443
          protocol: TCP
        securityContext:
          readOnlyRootFilesystem: true
          runAsNonRoot: true
          runAsUser: 1000
        volumeMounts:
        - name: tmp-dir
          mountPath: /tmp
      nodeSelector:
        kubernetes.io/os: linux
        kubernetes.io/arch: "amd64"
---
apiVersion: v1
kind: Service
metadata:
  name: metrics-server
  namespace: kube-system
  labels:
    kubernetes.io/name: "Metrics-server"
    kubernetes.io/cluster-service: "true"
spec:
  selector:
    k8s-app: metrics-server
  ports:
  - port: 443
    protocol: TCP
    targetPort: main-port
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: system:metrics-server
rules:
- apiGroups:
  - ""
  resources:
  - pods
  - nodes
  - nodes/stats
  - namespaces
  - configmaps
  verbs:
  - get
  - list
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: system:metrics-server
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:metrics-server
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system

运行yaml文件

[root@master ~]# kubectl api-versions |grep metrics
metrics.k8s.io/v1beta1
[root@master ~]# kubectl top nodes
NAME     CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
master   288m         14%    1157Mi          66%
node1    129m         6%     969Mi           55%
node2    139m         6%     836Mi           48%

为了演示hpa,我们先制作一个镜像

FROM php:5-apache
COPY index.php /var/www/html/index.php
RUN chmod a+rx index.php

执行一个index.php,提高cpu的使用率

<?php
  $x = 0.0001;
  for ($i = 0; $i <= 1000000; $i++) {
    $x += sqrt($x);
  }
  echo "OK!";
?>

创建一个deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: php-apache
spec:
  selector:
    matchLabels:
      run: php-apache
  replicas: 1
  template:
    metadata:
      labels:
        run: php-apache
    spec:
      containers:
      - name: php-apache
        image: k8s.gcr.io/hpa-example
        ports:
        - containerPort: 80
        resources:
          limits:
            cpu: 500m
          requests:
            cpu: 200m

---

apiVersion: v1
kind: Service
metadata:
  name: php-apache
  labels:
    run: php-apache
spec:
  ports:
  - port: 80
  selector:
    run: php-apache

创建hpa

kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=4
[root@master ~]# kubectl get hpa
NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   0%/50%    1         4         1          4h35m

kubectl run -i --tty load-generator --rm --image=busybox --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://php-apache; done"
向pod发送查询请求提高cpu使用率

[root@master ~]# kubectl get hpa
NAME         REFERENCE               TARGETS    MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   106%/50%   1         4         1          4h37m
[root@master ~]# kubectl get deployment php-apache
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
php-apache   3/3     3            3           4h20m
发现hpa已经超过了预定值,随之pod的副本数也变成了3个,最多可变成4个,停止负载后,副本数也会变成一个

假如targets字段有显示unknown
原因:
1、刚建立,等待一段时间再查看
2、需要自动伸缩的目标资源并没有进行资源限制

### 配置 Kubernetes Pod自动伸缩 HPA 为了实现 Horizontal Pod Autoscaler (HPA),需要先确保集群已安装并启用了 Metrics Server,因为 HPA 依赖于 metrics-server 来收集资源使用数据[^5]。 #### 创建 Deployment 首先定义要监控的应用程序的部署文件 `hpa-deploy-demo.yaml` 并应用到集群中: ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: php-apache spec: replicas: 1 selector: matchLabels: app: php-apache template: metadata: labels: app: php-apache spec: containers: - name: php-apache image: gcr.io/google-samples/hello-app:1.0 ports: - containerPort: 80 resources: requests: cpu: 200m memory: "64Mi" limits: cpu: "500m" memory: "256Mi" ``` 接着可以创建此 deployment: ```bash kubectl create -f hpa-deploy-demo.yaml ``` #### 设置 HPA 资源对象 一旦应用程序运行起来,则可通过如下命令为上述部署配置 HPA: ```bash kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10 ``` 这条指令表示当任意一个 PHP Apache 实例使用的平均 CPU 利用率达到 50% 或更高时,HPA 将启动更多实例;反之则减少实例数量。最小副本数设为 1,最大副本数不超过 10。 此外还可以通过 YAML 文件更精细地控制 HPA 行为,下面是一个例子: ```yaml apiVersion: autoscaling/v2beta2 kind: HorizontalPodAutoscaler metadata: name: php-apache spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: php-apache minReplicas: 1 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 50 ``` 最后一步就是将这个 HPA 描述符提交给 K8s API server: ```bash kubectl apply -f hpa-definition.yaml ``` 这样就完成了基于 CPU 使用率的水平扩展策略设置。当然除了 CPU 外还支持其他类型的度量标准作为触发条件,例如内存利用率、自定义指标等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值