计算资源的弹性伸缩 (Auto Scaling)是云计算的本质能力之一,是云上降本增效的重要途径,也是衡量云原生成熟度的关键因素。
依托亚马逊云计算提供的自动化能力,我们可以自动按需启动或者回收资源。在众多场景下,CPU或者内存资源的利用率会根据每天不同时段的请求量波动,当业务请求不断上涨的时候,应该自动启动资源以应对新的请求;同样的,当业务请求量下降,资源处于低利用率的情况下,就处于浪费阶段,这个时候应该自动回收资源来节省费用。
AWS EKS 自动扩缩EC2计算资源的3种方式
在AWS EKS集群自动扩缩的最佳实践中提到了3种主要的计算资源自动扩缩方法
其中Cluster Autoscaler和Karpenter都是Kubernetes Autoscaler的具体实现,Cluster Autoscaler最经典,Karpenter最早由AWS开源并后续适配了多家云计算平台,Karpenter性能表现更好。
鉴于大量的用户习惯使用经典的Cluster Autoscaler,本文也以Cluster Autoscaler为例实现EC2计算资源的自动扩缩。
本文基于上一篇文章 AWS EKS 创建K8S集群[AWS 中国宁夏区]中创建的AWS EKS集群进行说明。
环境
| Software | version | install location |
|---|---|---|
| AWS EKS | 1.34 | AWS(ningxia) |
| eksctl | 0.215.0 | local computer |
| kubectl | 1.34 | local computer |
| aws cli | 2.21.0 | local computer |
安装 Cluster Autoscaler
本次安装Cluster Autoscaler的参考链接
IAM OIDC provider设置
为了让Cluster Autoscaler有权限操作nodegroup,我们需要设置安全策略
在AWS EKS 控制台中复制集群的OpenID Connect provider URL
在AWS IAM 控制台补充OIDC,我们先创建Identity providers
填入前面复制的OpenID Connect provider URL,并将Audience设置为sts.amazonaws.com
创建完成
EKS Nodegroup tags管理
为了让Cluster Autoscaler能够准确知道我们允许它扩缩哪些node group,我们最好是显式给node group设置tag
为需要被Cluster Autoscaler管理的node group设置tag
tag有2个:
| 名称 | 值 |
|---|---|
| k8s.io/cluster-autoscaler/enabled | true |
k8s.io/cluster-autoscaler/<cluster-name> | owned |
将<cluster-name>换为你实际的集群名称
例如我的:
为Cluster Autoscaler创建IAM Policy
这是为Cluster Autoscaler设计的AWS IAM polocy,其中请把<cluster-name>替换为你自己实际的EKS集群名称
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:DescribeAutoScalingInstances",
"autoscaling:DescribeLaunchConfigurations",
"autoscaling:DescribeScalingActivities",
"ec2:DescribeImages",
"ec2:DescribeInstanceTypes",
"ec2:DescribeLaunchTemplateVersions",
"ec2:GetInstanceTypesFromInstanceRequirements",
"eks:DescribeNodegroup"
],
"Resource": [
"*"
]
},
{
"Effect": "Allow",
"Action": [
"autoscaling:SetDesiredCapacity",
"autoscaling:TerminateInstanceInAutoScalingGroup"
],
"Resource": [
"*"
],
"Condition": {
"StringEquals": {
"aws:ResourceTag/k8s.io/cluster-autoscaler/<cluster-name>": "owned"
}
}
}
]
}
比如我的
然后可以在AWS IAM页面控制台创建policy,名称为AmazonEKSClusterAutoscalerPolicy
为Cluster Autoscaler创建IAM Role
在AWS IAM控制台创建role,其中Identity provider选择你自己EKS集群的OIDC即可
policy选择上面新创的AmazonEKSClusterAutoscalerPolicy
检查设置并创建,名称填为AmazonEKSClusterAutoscalerRole
保险起见,创建完成后检查AmazonEKSClusterAutoscalerRole是否和前面的OIDC签名一致
正式部署autoscaler
下载cluster-autoscaler-autodiscover.yaml
curl -O https://raw.githubusercontent.com/kubernetes/autoscaler/master/cluster-autoscaler/cloudprovider/aws/examples/cluster-autoscaler-autodiscover.yaml
将下载的文件进行修改,调整<YOUR CLUSTER NAME>为你的集群名称
然后部署
kubectl apply -f cluster-autoscaler-autodiscover.yaml
为集群的cluster-autoscaler加上有关role的注解,将arn:aws:iam::ACCOUNT_ID:role/AmazonEKSClusterAutoscalerRole替换为前面创建的名为AmazonEKSClusterAutoscalerRole的role的实际的arn
kubectl annotate serviceaccount cluster-autoscaler -n kube-system eks.amazonaws.com/role-arn=arn:aws:iam::ACCOUNT_ID:role/AmazonEKSClusterAutoscalerRole
为cluster-autoscaler deployment打patch,补充注解
kubectl patch deployment cluster-autoscaler -n kube-system -p '{"spec":{"template":{"metadata":{"annotations":{"cluster-autoscaler.kubernetes.io/safe-to-evict": "false"}}}}}'
修改cluster-autoscaler
kubectl -n kube-system edit deployment.apps/cluster-autoscaler
加上如下的内容,加的使用缩进请用空格,不要用tab缩进
--balance-similar-node-groups
--skip-nodes-with-system-pods=false
如下图位置
到这里部署就完成了~~~~~~
检查安装效果
通过下面的命令查看pod
kubectl -n kube-system get deployments
如果看到cluster-autoscaler运行不正常,比如pod数量不符合预期,说明部署有细节问题
通过下面的命令查看log
kubectl -n kube-system logs -f deployment.apps/cluster-autoscaler
主要原因是中国大陆已经封禁了海外的Docker image仓库,无法拉去docker image导致
解决方法有2个:
- 自己科学上网,在海外拉取对应的docker image后上传到AWS中国的私人ECR仓库中,修改cluster-autoscaler deployment使用自己ECR上的docker image
- 寻找一些国内的自己信任的docker image代理,修改cluster-autoscaler deployment使用代理下载的docker image
如果看到cluster-autoscaler运行正常,说明部署成功
再次查看log
kubectl -n kube-system logs -f deployment.apps/cluster-autoscaler
出现No unschedulable pods,Calculating unneeded nodes类的字样,说明工作正常,正在尝试进行扩缩容评估
Horizontal Pod Autoscaler设置
检查Metrics Server
在AWS EKS 创建K8S集群[AWS 中国宁夏区]中的插件安装环节,其实默认是安装了
我们可以先进行Metrics Server状态检查
kubectl get deployment metrics-server -n kube-system
安装Metrics Server
如果Metrics Server在正常运行,那么我们可以直接开箱即用HPA(Horizontal Pod Autoscaler)了,如果你的EKS集群没有安装Metrics Server,那么我们需要补充安装。
首先参考Installing the Kubernetes Metrics Server安装Metrics Server
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
安装完成后,我们需要按照上一节检查Metrics Server中的说明进行检查,确保Metrics Server正常运行。
测试EKS资源自动扩缩和HPA
我们继续参考Horizontal Pod Autoscaler进行测试。测试的逻辑如下:
- 以deployment的形式部署一个PHP demo项目在EKS中。
- 为这个deployment设置HPA。规定CPU压力超过30%后需要进行pod数量的增加,当业务压力上升时,扩展pod数量,用更多的pod应对业务压力;当业务压力下降时,减少pod数量,用更少的pod满足当前的业务压力节约成本
- 这个deployment中的pod数量变化导致底层EC2服务器数量的变化,在AWS按需收费的模式下,我们实现了计算资源的按需灵活使用,避免资源浪费导致的成本上升或者资源不够导致的业务中断。
以一个PHP样例为测试对象
备注:本次实验的PHP程序只能运行在X64 CPU上,不能运行在ARM64上,建议测试先指定pod的节点选择器
kubectl apply -f https://k8s.io/examples/application/php-apache.yaml
设置一个HPA,规定CPU压力超过70%后扩展
kubectl autoscale deployment php-apache --cpu=70% --min=1 --max=20
查看HPA信息
kubectl get hpa
HPA刚设置的时候可能出现cpu: <unknown>/80%的问题,这是正常的,因为指标的收集有延迟,我们等几分钟后再次查看HPA状态可以发现指标已经被正常的收集。
进行压力测试,通过压力让CPU指标上升
kubectl run -i --tty load-generator --rm --image=public.ecr.aws/docker/library/busybox:unstable-uclibc --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://php-apache; done"
当施加压力后,我们看到pod数量随着CPU指标的上升而变多了,这时HPA工作正常扩展pod数量
更多的pod需要更多的EC2承载,我们看到cluster autoscaler自动为我们扩展了一个EC2
当我们停止压力测试,过一段时间cluster-autoscaler会自动为我们回收EC2。
最好别忘了清理测试,删除相关的资源
kubectl delete deployment.apps/php-apache service/php-apache horizontalpodautoscaler.autoscaling/php-apache
到这里我们完成一个高可用,资源自动扩展的EKS部署,这样我们真正的实现了云上按需计算、高性价比、高可靠性的容器化服务搭建。
下一篇文章将对比EKS底层算力弹性的例外一种选择,请看:AWS EKS 计算资源自动扩缩之按需申请Fargate[AWS 中国宁夏区]
关于中国地区可以遇到docker image无法拉取而导致部署失败的解决方案:这里建议定位到具体的docker image名称后,在Amazon ECR Public Gallery上查找对应的镜像image或者你可以使用第三方的Docker images镜像代理,通过替换docker images 地址避免网络问题