概述
从 2019 年底开始,EKS 已经支持 Fargate 功能,Fargate 是无服务器的计算单元,支持 Pod 的运行,EKS 集群的数据平面可以完全由 Fargate 承载,免除了维护 EC2 实例的弹性扩展、打补丁、和管理等方面的运维难题,而且 Kubernetes pod 运行在单独隔离的环境中,增强了安全性,下面示例介绍 EKS Fargate 的使用过程。
整体实验的架构图如下:
架构图说明:
- EKS 是 Amazon 托管的 Kubernetes 服务。
- Fargate 中运行 metrics-server,aws-load-balancer-controller,coredns,adot-collector 插件,分别用于收集 pod 指标,管理 Amazon ALB 负载均衡服务,DNS 域名解析服务和日志收集。Nginx pod 用于测试。
- CloudWatch 服务将收集和管理 pod 日志和 pod 指标。
详细步骤说明
1. 配置本机环境
本机需配置创建 EKS Cluster 的权限,比如具有 AdministratorAccess Policy。
本机中需安装下列工具:
2. 创建 Pod execution IAM role
创建用于 Fargate 的 IAM role,具有下载 ECR 镜像和上传日志到 CloudWatch Logs 的权限。
参考:https://docs.thinkwithwp.com/eks/latest/userguide/pod-execution-role.html
https://raw.githubusercontent.com/aws-samples/amazon-eks-fluent-logging-examples/mainline/examples/fargate/cloudwatchlogs/permissions.json
cat <<EOF > role-trust-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "eks-fargate-pods.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
cat <<EOF > role-inline-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:CreateLogGroup",
"logs:DescribeLogStreams",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
EOF
aws iam create-role --role-name EKSFargatePodExecRole --assume-role-policy-document file://role-trust-policy.json
aws iam attach-role-policy --role-name EKSFargatePodExecRole --policy-arn arn:aws:iam::aws:policy/AmazonEKSFargatePodExecutionRolePolicy
aws iam put-role-policy --role-name EKSFargatePodExecRole --policy-name cloudwatchlogs --policy-document file://role-inline-policy.json
3. 创建 EKS Cluster
下面命令将创建一个 EKS Cluster,包含 3 个 Fargate Profile(default、kube-system和fargate-container-insights),部署在 Kubernetes namespaces(default、kube-system和fargate-container-insights)中的 pod 将运行在 Fargate 上,如果需要支持更多的 namespace,需要新建 Fargate Profile,指定该 namespace。该命令还将创建 1 个 VPC,3 个 public subnet,3 个 private subnet,并且 private subnet 已经配置了通过 NAT Gateway 访问公网。
Fargate Profile 的介绍见:https://docs.thinkwithwp.com/eks/latest/userguide/fargate-profile.html。
1)获取 Account ID
export ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)
echo $ACCOUNT_ID
2)创建 EKS 集群
cat <<EOF > eks_cluster.yml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: eks-fargate
region: us-east-1
version: "1.23"
vpc:
clusterEndpoints:
publicAccess: true
privateAccess: true
availabilityZones:
- us-east-1a
- us-east-1b
- us-east-1c
cloudWatch:
clusterLogging:
enableTypes:
- "all"
logRetentionInDays: 30
fargateProfiles:
- name: default
podExecutionRoleARN: arn:aws:iam::${ACCOUNT_ID}:role/EKSFargatePodExecRole
selectors:
- namespace: default
- name: kube-system
podExecutionRoleARN: arn:aws:iam::${ACCOUNT_ID}:role/EKSFargatePodExecRole
selectors:
- namespace: kube-system
- name: fargate-container-insights
podExecutionRoleARN: arn:aws:iam::${ACCOUNT_ID}:role/EKSFargatePodExecRole
selectors:
- namespace: fargate-container-insights
EOF
eksctl create cluster -f eks_cluster.yml
3)获取 EKS 集群的 VPC 配置
export EKS_VPC_ID=$(aws eks describe-cluster --name eks-fargate --query "cluster.resourcesVpcConfig.vpcId" --output text)
echo $EKS_VPC_ID
4)更新本地 kubeconfig(可选)
aws eks update-kubeconfig --name eks-fargate
5)创建 OIDC Provider,支持 Amazon IAM roles for service accounts 功能
详细介绍见:https://docs.thinkwithwp.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html。
操作代码如下:
eksctl utils associate-iam-oidc-provider --cluster=eks-fargate --approve
4. 设置 Pod 的安全组
Fargate/Pod 将默认使用 EKS Cluster 的 Security Group。
下面演示为 Pod 设置额外的安全组。
1)创建 eks-fargate-sg 安全组
export EKS_VPC_CIDR=$(aws ec2 describe-vpcs --vpc-ids ${EKS_VPC_ID} --query "Vpcs[0].CidrBlock" --output text)
export EKS_SG_ID=$(aws ec2 create-security-group --group-name eks-fargate-sg --description eks-fargate-sg --vpc-id ${EKS_VPC_ID} --query "GroupId" --output text)
aws ec2 authorize-security-group-ingress \
--group-id ${EKS_SG_ID} \
--protocol tcp \
--port 80 \
--cidr ${EKS_VPC_CIDR}
2) 获得 EKS Cluster 的 Security Group
export EKS_CLUSTER_SECURITY_GROUP_ID=$(aws eks describe-cluster --name eks-fargate --query cluster.resourcesVpcConfig.clusterSecurityGroupId --output text)
echo $EKS_CLUSTER_SECURITY_GROUP_ID
3)新建 SecurityGroupPolicy
cat <<EOF > pod-security-group-policy.yaml
apiVersion: vpcresources.k8s.aws/v1beta1
kind: SecurityGroupPolicy
metadata:
name: default-security-group-policy
namespace: default
spec:
podSelector:
matchLabels:
securityGroups:
groupIds:
- ${EKS_SG_ID}
- ${EKS_CLUSTER_SECURITY_GROUP_ID}
EOF
kubectl apply -f pod-security-group-policy.yaml
5. 创建 nginx 测试应用
1)创建 nginx deployment 和 service
cat <<EOF > nginx-deploy.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: default
spec:
selector:
matchLabels:
app: nginx
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 2
maxUnavailable: 0
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "256Mi"
cpu: "250m"
EOF
kubectl apply -f nginx-deploy.yml
cat <<EOF > nginx-service.yml
apiVersion: v1
kind: Service
metadata:
name: "nginx-service"
spec:
selector:
app: nginx
type: ClusterIP
ports:
- protocol: TCP
port: 80
targetPort: 80
EOF
kubectl apply -f nginx-service.yml
2)访问 nginx app
创建 test pod,访问 nginx,后面还将用到 test pod,不要退出。
kubectl run -it --rm test --image=alpine -- /bin/sh
wget -q -O- http://nginx-service.default.svc.cluster.local
6. 收集 pod 指标到 CloudWatch
参考:https://aws-otel.github.io/docs/getting-started/container-insights/eks-fargate。
1)创建 namespace 和 serviceaccount
kubectl create namespace fargate-container-insights
eksctl create iamserviceaccount \
--cluster=eks-fargate \
--name=adot-collector \
--namespace=fargate-container-insights \
--role-name=EKS-Fargate-ADOT-SA-Role \
--attach-policy-arn=arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy \
--approve
2)安装 aws-otel-collector 插件
curl -O https://raw.githubusercontent.com/aws-observability/aws-otel-collector/main/deployment-template/eks/otel-fargate-container-insights.yaml
下载的 otel-fargate-container-insights.yaml 文件中需将 YOUR-EKS-CLUSTER-NAME 替换为您的 EKS 集群名称 eks-fargate,将 region=us-east-1 修改成您使用的region。
kubectl apply -f otel-fargate-container-insights.yaml
3)在浏览器中,登陆 AWS Console,进入 CloudWatch 中。
选择菜单栏的 Container Insights,可以看到 Container map,如下图:
选择菜单栏的 All metrics,可以看到 pod 的指标,如 CPU 利用率和内存利用率,如下图:
7. 收集 pod logs 到 CloudWatch
详细配置参考:https://docs.amazonaws.cn/eks/latest/userguide/fargate-logging.html。
1)创建 namespace
cat <<EOF > logging-namespace.yml
kind: Namespace
apiVersion: v1
metadata:
name: aws-observability
labels:
aws-observability: enabled
EOF
kubectl apply -f logging-namespace.yml
2)创建 configmap,只保存 nginx app 的日志
cat <<EOF > logging-config.yml
kind: ConfigMap
apiVersion: v1
metadata:
name: aws-logging
namespace: aws-observability
data:
flb_log_cw: "true" #ships fluent-bit process logs to CloudWatch
filters.conf: |
[FILTER]
Name parser
Match *
Key_name log
Parser crio
[FILTER]
Name kubernetes
Match kube.*
Merge_Log On
Keep_Log Off
Buffer_Size 0
Kube_Meta_Cache_TTL 300s
output.conf: |
[OUTPUT]
Name cloudwatch_logs
Match kube.var.log.containers.nginx-*
region us-east-1
log_group_name eks-fargate-logs
log_stream_prefix from-fluent-bit-
log_retention_days 60
auto_create_group true
parsers.conf: |
[PARSER]
Name crio
Format Regex
Regex ^(?<time>[^ ]+) (?<stream>stdout|stderr) (?<logtag>P|F) (?<log>.*)$
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L%z
EOF
kubectl apply -f logging-config.yml
3)重启 nginx
kubectl rollout restart deployment nginx
4)在上面创建的 test pod 中,访问 nginx
wget -q -O- http://nginx-service.default.svc.cluster.local
5)在 CloudWatch 的 Log groups 中,可以看到 access log
8. 配置 Amazon ALB 负载均衡器
通过负载均衡器,互联网用户可以访问 EKS 集群中的 POD。
参考:https://docs.thinkwithwp.com/eks/latest/userguide/aws-load-balancer-controller.html。
1)配置 Service Account
curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.4.4/docs/install/iam_policy.json
aws iam create-policy \
--policy-name AWSLoadBalancerControllerIAMPolicy \
--policy-document file://iam_policy.json
eksctl create iamserviceaccount \
--cluster=eks-fargate \
--namespace=kube-system \
--name=aws-load-balancer-controller \
--role-name AmazonLoadBalancerControllerRole \
--attach-policy-arn=arn:aws:iam::${ACCOUNT_ID}:policy/AWSLoadBalancerControllerIAMPolicy \
--approve
2)安装 aws-load-balancer-controller 插件
helm repo add eks https://aws.github.io/eks-charts
helm repo update
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
-n kube-system \
--set clusterName=eks-fargate \
--set serviceAccount.create=false \
--set serviceAccount.name=aws-load-balancer-controller \
--set vpcId=${EKS_VPC_ID}
3)创建 ALB 使用的 Security Group
export EKS_ALB_SG_ID=$(aws ec2 create-security-group --group-name eks-alb-sg --description eks-fargate-sg --vpc-id ${EKS_VPC_ID} --query "GroupId" --output text)
aws ec2 authorize-security-group-ingress \
--group-id ${EKS_ALB_SG_ID} \
--protocol tcp \
--port 80 \
--cidr 0.0.0.0/0
4)创建 ingress
将创建 Amazon ALB 负载均衡器,需等待几分钟的 ALB 初始化过程。
cat <<EOF > alb-ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
namespace: default
name: nginx
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/security-groups: ${EKS_ALB_SG_ID}
spec:
ingressClassName: alb
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-service
port:
number: 80
EOF
kubectl apply -f alb-ingress.yml
5)获取 ALB 的地址
export ALB_URL=$(kubectl get ingress nginx -o=jsonpath='{.status.loadBalancer.ingress[0].hostname}')
echo $ALB_URL
6)访问 ALB,获得 nginx 的欢迎页
9. Pod 水平扩展 HPA
参考:https://docs.thinkwithwp.com/eks/latest/userguide/horizontal-pod-autoscaler.html。
Kubernetes Horizontal Pod Autoscaler 可根据 Pod 负载情况,自动扩张 Pod 数量,新产生的 Pod 大概需要 1 分钟左右时间上线。HPA 依赖 Metrics Server 插件。
1)安装 Metrics Server 插件
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
2)创建 HorizontalPodAutoscaler 对象
下面是创建 HPA 对象的示例,设定了 CPU 利用率的期待指标和收缩策略。
cat <<EOF > hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: nginx
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: nginx
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 3
behavior:
scaleDown:
stabilizationWindowSeconds: 30
policies:
- type: Percent
value: 100
periodSeconds: 60
EOF
kubectl apply -f hpa.yaml
3)查看 HPA 的状态,由于没有请求压力,nginx 副本将收缩为 1 个。
4)在上面创建的 test pod 中,进行压力测试,nginx 副本将扩展为 3 个。
while sleep 0.001; do wget -q -O- http://nginx-service.default.svc.cluster.local; done
HPA 的输出结果如下:
10. EKS 集群升级
EKS 集群升级后,需要升级线上 EKS Fargate 的版本。
查看 Fargate 版本,是否和 Cluster 版本一致,如果版本不相同,需要重启 Pod,升级 Fargate 版本。
1)获取 Fargate 的版本
2)重启 K8S Deployment,从而升级 Fargate 版本
kubectl rollout restart deployment nginx
kubectl rollout restart deployment metrics-server -n kube-system
kubectl rollout restart deployment coredns -n kube-system
kubectl rollout restart deployment aws-load-balancer-controller -n kube-system
kubectl rollout restart statefulset adot-collector -n fargate-container-insights
3)升级时,为保障线上的 Pod 数量,可设置升级策略。
参考:https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#proportional-scaling。
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 2
maxUnavailable: 0
结论
在这篇文章中,介绍了在 EKS 集群中使用 Fargate,包含创建 EKS 集群、监控、日志收集、负载均衡器配置、水平扩展 Pod 和 EKS 集群升级等功能,用户可以参考该文档快速进行集群配置和测试。
参考资料
本篇作者