你必知的 Kubernetes 自动缩放

点击查看目录

本文为翻译文章,点击查看原文

编者按

许多 Kubernetes 用户,特别是那些企业级用户,很快就遇到了对环境自动缩放的需求。幸运的是,Kubernetes Horizontal Pod Autoscaler(HPA)允许您将部署配置为以多种方式水平扩展。使用 Kubernetes Autoscaling 的最大优势之一是您的集群可以跟踪现有 Pod 的负载能力,并计算是否需要更多的 Pod。

Kubernetes Autoscaling

通过协调内置的两层可扩展性,可以充分利用高效的 Kubernetes Autoscaling:

  1. Pod 级别的自动缩放:包括 Horizontal Pod Autoscaler(HPA)和 Vertical Pod Autoscaler(VPA); 两者都可以扩展容器的可用资源。
  2. 集群级别的自动缩放:集群自动调节器(CA)通过在必要时向上或向下扩展集群内的节点数来管理这种可扩展性平面。

Kubernetes Autoscaling 详情

Horizontal Pod Autoscaler (HPA)

HPA 会在集群中缩放 Pod 副本的数量。该操作由 CPU 或内存触发,以根据需要向上或向下扩展。但是,也可以根据各种外部的和自定义指标(metrics.k8s.io,external.metrics.k8s.io 和 custom.metrics.k8s.io)来配置 HPA 以扩展 Pod。

Vertical Pod Autoscaler (VPA)

VPA 主要用于有状态服务,它可根据需要为 Pod 添加 CPU 或内存——它也适用于无状态的 Pod。为了应用这些更改,VPA 重新启动 Pod 以更新新的 CPU 和内存资源,这些资源可以配置为响应 OOM(内存不足)事件而启动。重新启动 Pod 的时候,VPA 始终确保根据 Pod 分配预算(PDB)确定最小数量,您可以设置该资源分配最大和最小速率。

Cluster Autoscaler (CA)

第二层的自动缩放涉及 CA,它在以下情况下自动调整集群的大小:

  • 由于集群中的容量不足,任何 Pod/s 都无法运行并进入挂起状态(在这种情况下,CA 将向上扩展)。
  • 集群中的节点在一段时间内未得到充分利用,并且有可能迁移节点上的 Pod(在这种情况下,CA 将缩小)。

CA 进行例行检查以确定是否有任何 pod 因等待额外资源处于待定状态,或者集群节点是否未得到充分利用。如果需要更多资源,会相应地调整 Cluster 节点的数量。CA 与云提供商交互以请求其他节点或关闭空闲节点,并确保按比例放大的集群保持在用户设置的限制范围内。它适用于 AWS,Azure 和 GCP。

将 HPA 和 CA 与 Amazon EKS 配合使用的 5 个步骤

本文提供了通过适用于 Kubernetes(Amazon EKS)集群的 Amazon Elastic 容器服务,通过 HPA 和 CA 安装和自动扩展的分步指南。以下指南是两个测试用例示例:

集群要求

  • 满足 EKS 集群要求的 Amazon VPC 和 一个安全组。
  • 或者,为免手动创建 VPC,AWS 提供了创建了 VPC 和 EKS 的CloudFormation 模板

CloudFormation YAML 文件

1. 根据官方指南创建一个 AWS EKS 集群 (控制面板和和工作节点). 一旦你把工作节点以 auto scaling group 的形式启动了,它们会自动向 EKS 集群注册,你就可以开始部署 k8s 应用了。

2. 部署度量服务器以便HPA能够根据API提供的CPU/内存数据自动缩放POD副本的数量。metrics.k8s.io api 通常由 metrics-server(负责从 summary api 收集 cpu 和内存度量)提供。

3. 把以下策略应用到 EKS 创建的 worker 节点的 Role 上

{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Effect": "Allow",
         "Action": [
            "autoscaling:DescribeAutoScalingGroups",
            "autoscaling:DescribeAutoScalingInstances",
            "autoscaling:DescribeLaunchConfigurations",
            "autoscaling:DescribeTags",
            "autoscaling:SetDesiredCapacity",
            "autoscaling:TerminateInstanceInAutoScalingGroup"
         ],
         "Resource": "*"
      }
   ]
}

4. 部署 k8s CA 特性

根据你使用的 linux 发行版,你可能需要更新部署文件和证书路径。例如,如果使用 AMI Linux,需要用/etc/ssl/certs/ca-bundle.crt 替换/etc/ssl/certs/ca-certificates.crt

5. 更新 CA 的部署 YAML 文件,找到指定的 AWS AG(k8s.io/cluster-autoscaler/<CLUSTER NAME>应该包含真实的集群名称)标签。 同时更新AWS_REGION环境变量。

把以下 tag 添加到 AWS AG,以便 k8s 的 cluster autoscaler 能够自动识别 AWS AG:

k8s.io/cluster-autoscaler/enabled k8s.io/cluster-autoscaler/

Kubernetes Autoscaling 测试用例 #1

测试 k8s hpa 特性和 k8s ca 特性同时使用

要求:

  • 一个运行中的 eks 集群
  • 安装好 metric server
  • 安装了 k8s cluster autoscaler 特性

1. 部署一个测试 app,为 app 部署创建 HPA 资源。

2. 从不同的地理位置发起请求以增加负载。

3. HPA 应该会随着负载的增加开始缩放 pod 的数量。它会根据 hpa 资源指定的进行缩放的。在某一时刻,新的 POD 在等待其他资源的时候会是等待状态。

$ kubectl get nodes -w
NAME                             STATUS    ROLES     AGE       VERSION
ip-192-168-189-29.ec2.internal   Ready         1h        v1.10.3
ip-192-168-200-20.ec2.internal   Ready         1h        v1.10.3
$ kubectl get Pods -o wide -w
NAME READY STATUS RESTARTS AGE IP NODE
ip-192-168-200-20.ec2.internal
php-apache-8699449574-4mg7w 0/1 Pending 0 17m
php-apache-8699449574-64zkm 1/1 Running 0 1h 192.168.210.90 ip-192-168-200-20
php-apache-8699449574-8nqwk 0/1 Pending 0 17m
php-apache-8699449574-cl8lj 1/1 Running 0 27m 192.168.172.71 ip-192-168-189-29
php-apache-8699449574-cpzdn 1/1 Running 0 17m 192.168.219.71 ip-192-168-200-20
php-apache-8699449574-dn9tb 0/1 Pending 0 17m
...

4. CA 检测到因为容量不足而进入等待状态的 pods,调整 AWS 自动缩放组的大小。一个新的节点加入了:

$ kubectl get nodes -w
NAME                                       STATUS    ROLES     AGE       VERSION
ip-192-168-189-29.ec2.internal   Ready         2h        v1.10.3
ip-192-168-200-20.ec2.internal   Ready         2h        v1.10.3
ip-192-168-92-187.ec2.internal   Ready         34s       v1.10.3

5. HPA 能够把等待状态的 POD 调度到新的节点上了。平均 cpu 使用率低于指定的目标,没有必要再调度新的 pod 了。

$ kubectl get hpa
NAME         REFERENCE                    TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   40%/50%   2                  25                 20               1h $ kubectl get Pods -o wide -w
$ kubectl get Pods -o wide -w
NAME READY STATUS RESTARTS AGE IP NODE
php-apache-8699449574-4mg7w 1/1 Running 0 25m 192.168.74.4 ip-192-168-92-187
php-apache-8699449574-64zkm 1/1 Running 0 1h 192.168.210.90 ip-192-168-200-20
php-apache-8699449574-8nqwk 1/1 Running 0 25m 192.168.127.85 ip-192-168-92-187
php-apache-8699449574-cl8lj 1/1 Running 0 35m 192.168.172.71 ip-192-168-189-29
...

6. 关闭几个 terminal,停掉一些负载

7. CPU 平均利用率减小了,所以 HPA 开始更改部署里的 pod 副本数量并杀掉一些 pods

$ kubectl get hpa
NAME         REFERENCE                     TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   47%/50%     2                20                 7                   1h 

$ kubectl get Pods -o wide -w
NAME READY STATUS RESTARTS AGE IP NODE
...
php-apache-8699449574-v5kwf 1/1 Running 0 36m 192.168.250.0 ip-192-168-200-20
php-apache-8699449574-vl4zj 1/1 Running 0 36m 192.168.242.153 ip-192-168-200-20
php-apache-8699449574-8nqwk 1/1 Terminating 0 26m 192.168.127.85 ip-192-168-92-187
php-apache-8699449574-dn9tb 1/1 Terminating 0 26m 192.168.124.108 ip-192-168-92-187
php-apache-8699449574-k5ngv 1/1 Terminating 0 26m 192.168.108.58 ip-192-168-92-187
...

8. CA 检测到一个节点未充分使用,正在运行的 pod 能够调度到其他节点上。

$ kubectl get nodes
NAME                             STATUS    ROLES     AGE       VERSION
ip-192-168-189-29.ec2.internal   Ready         2h        v1.10.3
ip-192-168-200-20.ec2.internal   Ready         2h        v1.10.3
ip-192-168-92-187.ec2.internal   NotReady       23m       v1.10.3

$ kubectl get nodes
NAME                             STATUS    ROLES     AGE       VERSION
ip-192-168-189-29.ec2.internal   Ready         2h        v1.10.3
ip-192-168-200-20.ec2.internal   Ready         2h        v1.10.3

9. 在向下缩放的时候,terminal 中应该没有明显的 timeout

Kubernetes Autoscaling 测试用例 #2

测试在如果没有足够的 CPU 容量调度 pod 下,CA 是否能够自动调整集群的大小

要求:

  • 一个运行中的 aws eks 集群
  • Kubernetes ca 特性已安装

1. 创建 2 个请求小于 1vcpu 的 deployment

$ kubectl run nginx --image=nginx:latest --requests=cpu=200m
$ kubectl run nginx2 --image=nginx:latest --requests=cpu=200m

2. 创建一个新的 deployment,请求比剩余的 cpu 更多的资源

$ kubectl run nginx3 --image=nginx:latest --requests=cpu=1

3. 新的 POD 会处于等待状态,因为没有可用的资源:

$ kubectl get Pods -w
NAME                      READY     STATUS    RESTARTS   AGE
nginx-5fcb54784c-lcfht    1/1       Running   0          13m
nginx2-66667bf959-2fmlr   1/1       Running   0          3m
nginx3-564b575974-xcm5t   0/1       Pending   0          41s

描述 pod 的时候,可能会看到没有足够的 cpu 的事件

$ kubectl describe Pod nginx3-564b575974-xcm5t
…..
…..
Events:
Type     Reason            Age               From               Message
----     ------            ----              ----               -------
Warning  FailedScheduling  32s (x7 over 1m)  default-scheduler  0/1 nodes are available: 1 Insufficient cpu

4. CA 自动调整集群的大小,新加了一个节点

$ kubectl get nodes
NAME                              STATUS    ROLES     AGE       VERSION
ip-192-168-142-179.ec2.internal   Ready         1m        v1.10.3  <<
ip-192-168-82-136.ec2.internal     Ready         1h        v1.10.3

5. 集群现在有了足够的资源以运行 pod

$ kubectl get Pods
NAME                      READY     STATUS    RESTARTS   AGE
nginx-5fcb54784c-lcfht    1/1       Running   0          48m
nginx2-66667bf959-2fmlr   1/1       Running   0          37m
nginx3-564b575974-xcm5t   1/1       Running   0          35m

6. 两个部署删除了。一段时间后,CA 检测到集群中的一个节点未被充分利用,运行的 pod 可以安置到其他存在的节点上。AWS AG 更新,节点数量减 1。

$ kubectl get nodes
NAME                                      STATUS    ROLES     AGE       VERSION
ip-192-168-82-136.ec2.internal   Ready         1h          v1.10.3 

$ kubectl get Pods -o wide
NAME                        READY     STATUS    RESTARTS   AGE       IP                       NODE
nginx-5fcb54784c-lcfht   1/1       Running     0                   1h       192.168.98.139   ip-192-168-82-136

清除环境的步骤:

  1. 删除添加到 eks worker 节点上 Role 的自定义策略
  2. 按照这个指南删除这个集群

参考

其他的关于 kubernetes autoscaling,可以阅读 Stefan Prodan 的文章 Kubernetes Horizontal Pod Autoscaler with Prometheus Custom Metrics

还有这些链接也可以看看 link1, link2, link3

编辑本页