Amazon EKS 是托管的 Kubernetes 服务,可以使用 HPA 和 Cluster Autoscaler 来在集群中实现弹性伸缩,以满足应用程序的需求并节省资源成本。
Kubernetes(K8s)提供了自动伸缩机制,旨在根据应用程序负载和资源需求的变化自动调整应用的副本数量或节点数量,以满足性能需求和优化资源利用。K8s 中的两个关键自动伸缩机制是 Horizontal Pod Autoscaler (HPA) 和 Cluster Autoscaler。。
方法 | 定义 | 工作原理 | 范围 | 目标 | 对象 | 自动化程度 |
---|---|---|---|---|---|---|
Horizontal Pod Autoscaler | HPA 用于自动调整一个 Deployment、ReplicaSet 或者 StatefulSet 中 Pod 的副本数量,以保持某个指标(例如 CPU 使用率或内存使用率)的目标值。当定义的指标超过或低于阈值时,HPA 将增加或减少 Pod 的副本数量。 | 1,监控 Metrics Server 或自定义指标服务收集的数据. 2,根据定义的目标值,计算出需要的副本数量。 3,更新 Deployment、ReplicaSet 或 StatefulSet 中的 Pod 数量。 |
HPA 负责调整一个 Deployment、ReplicaSet 或 StatefulSet 中的 Pod 数量 | HPA 关注 Pod 的资源使用率 | Pod | HPA 需要你设置目标值,然后根据这些值自动调整 Pod 数量 |
Cluster Autoscaler | Cluster Autoscaler 是一种自动伸缩机制,它负责在 Kubernetes 集群中自动扩展或收缩节点的数量。当集群中的 Pod 数量增加或减少,Cluster Autoscaler 会根据条件自动扩展或缩减节点数量。 | 1,监控未满足资源需求的 Pod,并找到它们所在的节点。 2,如果没有足够的节点提供资源,Cluster Autoscaler 会请求云提供商(例如 AWS、GCP)来添加新节点。 当节点上的 Pod 数量减少,如果节点的资源利用率过低,Cluster Autoscaler 可能会将节点缩减。 |
Cluster Autoscaler 负责调整整个集群中节点的数量 | Cluster Autoscaler 关注节点的资源利用率 | Node | Cluster Autoscaler 可以在需要的时候自动增加或减少节点 |
执行命令
##创建sa策略
aws iam create-policy \
--policy-name AmazonEKSClusterAutoscalerPolicy \
--policy-document file://cluster-autoscaler-policy.json
##创建Role角色
aws iam create-role \
--role-name AmazonEKSClusterAutoscalerRole \
--assume-role-policy-document file://"trust-policy.json"
##下载Autoscaler yaml文件
wget https://raw.githubusercontent.com/kubernetes/autoscaler/master/cluster-autoscaler/cloudprovider/aws/examples/cluster-autoscaler-autodiscover.yaml
## 修改yaml文件
1,修改镜像tag为对应EKS版本号
打开以下 Cluster Autoscaler 的 github 的网面,查看与 EKS 版本匹配的最新 Autoscaler 镜像版本 https://link.zhihu.com/?target=https%3A//github.com/kubernetes/autoscaler/releases
2,修改
3, 在下追加两行:
- --balance-similar-node-groups
- --skip-nodes-with-system-pods=false
##部署Cluster Autoscaler
kubectl apply -f cluster-autoscaler-autodiscover.yaml
## 绑定服务帐户和IAM角色
kubectl annotate serviceaccount cluster-autoscaler -n kube-system eks.amazonaws.com/role-arn=arn:aws:iam:::role/
Cluster Autoscaler 使用 EC2 Auto Scaling groups 服务对 node 进行扩容,我们需要确保 EKS 对应的 Auto Scaling groups 有适合的 Tag。
Cluster Autoscaler 通过 Tag 来识别哪些 Auto Scaling groups 属于其管辖范围。
如果我们使用 eksctl 命令或者 AWS 网页控制台来创建 node group,则所需 Tag 已经自动设置了,如果用其它方式创建的 node group 则需要确保其对应用的 Auto Scaling groups 中有以下两个 Tag
通过 service account(sa)来给 Cluster Autoscaler 的 Pod 提供访问 AWS 的 EC2 Auto Scaling groups 的权限。先创建 sa 需要的 Policy 和 Role。
创建Policy
vim cluster-autoscaler-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:DescribeAutoScalingInstances",
"autoscaling:DescribeLaunchConfigurations",
"autoscaling:DescribeTags",
"autoscaling:SetDesiredCapacity",
"autoscaling:TerminateInstanceInAutoScalingGroup",
"ec2:DescribeInstanceTypes",
"ec2:DescribeLaunchTemplateVersions"
],
"Resource": "*",
"Effect": "Allow"
}
]
}
参考:https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/CA_with_AWS_IAM_OIDC.md
Tips: 这个Policy 提供访问EC2 autoscaling group的相关权限
创建策略
aws iam create-policy \
--policy-name AmazonEKSClusterAutoscalerPolicy \
--policy-document file://cluster-autoscaler-policy.json
创建IAM Role
vim trues-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam:::oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"oidc.eks.us-east-1.amazonaws.com/id/:sub": "system:serviceaccount:kube-system:cluster-autoscaler"
}
}
}
]
}
###更新角色信任关系aws iam update-assume-role-policy --role-name --policy-document file://trust-policy.json
更新角色信任关系
aws iam update-assume-role-policy --role-name AmazonEKSClusterAutoscalerRole --policy-document file://"trust-policy.json"
说明:IAM Role 中包括 IAM policy 和 trust relationship 两部分,我们先用 json 文件来定义 trust relationship 的内容。
trust-policy.json 在创建 Role 时,指定“Trust relationships”中的内容
创建角色
aws iam create-role \
--role-name AmazonEKSClusterAutoscalerRole \
--assume-role-policy-document file://"trust-policy.json"
###更新角色信任关系aws iam update-assume-role-policy --role-name --policy-document file://trust-policy.json
更新角色信任关系
aws iam update-assume-role-policy --role-name AmazonEKSClusterAutoscalerRole --policy-document file://"trust-policy.json"
说明:
role-name:自定义 Role 的名称
assume-role-policy-document:指定本地 trust-policy 文件
为角色附加策略
aws iam attach-role-policy \
--policy-arn arn:aws:iam:::policy/AmazonEKSClusterAutoscalerPolicy \
--role-name AmazonEKSClusterAutoscalerRole
下载Autoscaler yaml文件
wget https://raw.githubusercontent.com/kubernetes/autoscaler/master/cluster-autoscaler/cloudprovider/aws/examples/cluster-autoscaler-autodiscover.yaml
部署Cluster Autoscaler
kubectl apply -f cluster-autoscaler-autodiscover.yaml
绑定服务帐户和IAM角色
#命令行
kubectl annotate serviceaccount cluster-autoscaler -n kube-system eks.amazonaws.com/role-arn=arn:aws:iam:::role/(建议使用AmazonEKSClusterAutoscalerRole)
#文件
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-addon: cluster-autoscaler.addons.k8s.io
k8s-app: cluster-autoscaler
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::xxxxx:role/ # Add the IAM role created in the above C section.
name: cluster-autoscaler
namespace: kube-system
#默认扩大节点组节点数量
扩大规模如何运作?
纵向扩展在 API 服务器上创建一个监视来查找所有 Pod。它每 10 秒检查一次任何不可调度的 pod(可通过--scan-interval标志配置)。当 Kubernetes 调度程序无法找到可以容纳 pod 的节点时,该 pod 就无法调度。例如,Pod 可以请求任何集群节点上可用的更多 CPU。不可调度的 pod 通过其 PodCondition 进行识别。每当 Kubernetes 调度程序无法找到运行 pod 的位置时,它就会将“schedulable”PodCondition 设置为 false,并将 Reason 设置为“unschedulable”。如果不可调度的 Pod 列表中有任何项目,Cluster Autoscaler 会尝试找到新的位置来运行它们。
#默认缩减节点组节点数量
每 10 秒(可通过--scan-interval标志配置),如果不需要扩展,Cluster Autoscaler 会检查哪些节点是不需要的。当满足以下所有条件时,将考虑删除节点:
1,该节点上运行的所有 Pod 的 CPU 和内存请求总和(默认情况下包括DaemonSet Pod和Mirror Pod--ignore-daemonsets-utilization ,但可以使用和--ignore-mirror-pods-utilization标志进行配置)小于该节点可分配的 50%。(在 1.1.0 之前,使用节点容量而不是可分配的容量。)可以使用 --scale-down-utilization-threshold标志配置利用率阈值。
2,节点上运行的所有 pod(默认情况下在所有节点上运行的 pod 除外,例如清单运行 pod 或 daemonset 创建的 pod)都可以移动到其他节点。请参阅 哪些类型的 Pod 可以阻止 CA 删除节点?部分了解有关哪些 pod 不满足此条件的更多详细信息,即使其他地方有空间容纳它们。在检查此情况时,所有可移动吊舱的新位置都会被记住。这样,Cluster Autoscaler 就知道每个 Pod 可以移动到哪里,以及哪些节点在 Pod 迁移方面依赖于哪些其他节点。当然,最终调度程序可能会将 Pod 放置在其他位置。
3,它没有缩小禁用注释(请参阅如[何防止 Cluster Autoscaler 缩小特定节点?](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#how-can-i-prevent-cluster-autoscaler-from-scaling-down-a-particular-node))
#测试集群自动绽放程序是否启动及角色是否已附加
$ kubectl get pods -n kube-system
$ kubectl exec -n kube-system cluster-autoscaler-xxxxxx-xxxxx env | grep AWS
#测试命令
kubectl scale deployment autoscaler-demo --replicas=50
#扩展日志
I1025 13:48:42.975037 1 scale_up.go:529] Final scale-up plan: [{eksctl-xxx-xxx-xxx-nodegroup-ng-xxxxx-NodeGroup-xxxxxxxxxx 2->3 (max: 8)}]
#获取节点组信息
eksctl get nodegroup --cluster
#调整节点组现有节点数
eksctl scale nodegroup --cluster --name --nodes
#调整节点组最小节点数
eksctl scale nodegroup --cluster --name --nodes-min
#调整节点组最大节点数
eksctl scale nodegroup --cluster --name --nodes-max
报错一:
caused by: InvalidIdentityToken: No OpenIDConnect provider found in your account for https://oidc.eks.us-east-1.amazonaws.com/id/274A18041DB4CF680FA22A5EF99FDFE3
解决:
使用 eksctl 为集群创建 IAM OIDC 身份提供商
eksctl utils associate-iam-oidc-provider --cluster $cluster_name --approve
确定集群是否拥有现有 IAM OIDC 提供商。
检索集群的 OIDC 提供商 ID 并将其存储在变量中。
oidc_id=$(aws eks describe-cluster --name my-cluster --query "cluster.identity.oidc.issuer" --output text | cut -d '/' -f 5)
确定您的账户中是否已存在具有您的集群 ID 的 IAM OIDC 提供商。
报错二:
0617 07:29:49.853336 1 aws_manager.go:262] Failed to regenerate ASG cache: WebIdentityErr: failed to retrieve credentials
caused by: AccessDenied: Not authorized to perform sts:AssumeRoleWithWebIdentity
status code: 403, request id: ff336b02-e997-47f2-8551-8e00efa05049
F0617 07:29:49.853387 1 aws_cloud_provider.go:430] Failed to create AWS Manager: WebIdentityErr: failed to retrieve credentials
caused by: AccessDenied: Not authorized to perform sts:AssumeRoleWithWebIdentity
status code: 403, request id: ff336b02-e997-47f2-8551-8e00efa05049
解决:
修改OICD供应商ID,更新角色信任策略
aws iam update-assume-role-policy --role-name AmazonEKSClusterAutoscalerRole --policy-document file://"trust-policy.json"
aws iam list-open-id-connect-providers | grep $oidc_id | cut -d "/" -f4
如果返回了输出,则表示您的集群已经有 IAM OIDC 提供商,您可以跳过下一步。如果没有返回输出,则您必须为集群创建 IAM OIDC 提供商。
使用以下命令为您的集群创建 IAM OIDC 身份提供商。将 my-cluster 替换为您自己的值。
eksctl utils associate-iam-oidc-provider --cluster my-cluster --approve