掌握流量管理:利用 EKS Ingress 和 AWS 负载均衡器控制器
什么是 Ingress?
在 Kubernetes 中,Ingress 是一个 API 对象,它定义了将外部 HTTP 和 HTTPS 流量路由到集群内服务的规则和配置,并提供了一种管理服务入站流量的方法。它们允许您为不同的 URL 路径或域名定义规则,并相应地将流量定向到特定服务或后端 Pod。
什么是 Ingress 控制器?
Ingress 控制器负责实现 Ingress 资源中定义的规则并管理传入流量的路由。它是一个在集群内运行的组件,用于监视 Ingress 资源的变化。当发生变化时,Ingress 控制器会配置底层负载均衡机制,以根据定义的规则路由流量。Ingress 控制器充当外部环境与集群内运行的服务之间的中介,根据 Ingress 规则将传入的请求定向到适当的后端服务。
Kubernetes Ingress 如何与 aws-alb-ingress-controller 协同工作
下图详细说明了 aws-alb-ingress-controller 在用户定义 Ingress 资源时创建的 AWS 组件。Ingress 资源将入口流量从 ALB 路由到 Kubernetes 集群。
图:Kubernetes Ingress 如何与 aws-alb-ingress-controller 协同工作
Ingress 创建
- 在 Kubernetes API 中创建 Ingress 资源时,alb-ingress-controller 会观察到所做的更改。
- alb-ingress-controller 根据 Ingress 资源中添加的注释创建 AWS Application Load Balancer。
- Ingress 资源中指定的每个后端都会创建目标组。
- 可以使用路径或查询参数访问 Application Load Balancer URL。
- 根据 Ingress 资源中配置的规则,请求会被重定向到特定的目标组,并通过 ClusterIP 或 NodePort 到达 Pod 服务。
入口流量
AWS ALB 入口控制器支持两种流量模式:实例模式和 IP 模式。用户可以通过在入口和服务定义中声明 alb.ingress.kubernetes.io/target-type 注释来明确指定这些流量模式。
- 实例模式:入口流量从 ALB 发起,到达为您的服务打开的 NodePort。然后,流量被路由到集群内的 Pod。
- IP 模式:入口流量从 ALB 发起,直接到达集群内的 Pod。要使用此模式,Kubernetes 集群的网络插件必须使用 ENI 上的辅助 IP 地址作为 Pod IP,也称为 Kubernetes 的 AWS CNI 插件。
注意:如果您在 Fargate 上使用 EKS 的 ALB 入口,则需要使用 IP 模式。
使用eksctl创建EKS 集群
ninjamac@ninjamacdeMacBook-Air key % eksctl create cluster \ --name rock-cluster \ --region ap-southeast-2 \--nodegroup-name standard-workers \--node-type t3.medium \--nodes 2 \--nodes-min 1 \--nodes-max 3 \--managed
2025-05-04 20:59:03 [ℹ] node "ip-192-168-20-242.ap-southeast-2.compute.internal" is ready
2025-05-04 20:59:03 [ℹ] node "ip-192-168-33-165.ap-southeast-2.compute.internal" is ready
2025-05-04 20:59:03 [✔] created 1 managed nodegroup(s) in cluster "rock-cluster"
2025-05-04 20:59:04 [ℹ] kubectl command should work with "/Users/ninjamac/.kube/config", try 'kubectl get nodes'
2025-05-04 20:59:04 [✔] EKS cluster "rock-cluster" in "ap-southeast-2" region is ready
为您的集群创建 IAM OIDC Provider:
首先,设置您的集群名称:
cluster_name=rock-cluster
获取集群的 OIDC ID:
oidc_id=$(aws eks describe-cluster --name $cluster_name --query "cluster.identity.oidc.issuer" --output text | cut -d '/' -f 5) echo $oidc_id
使用以下命令将 IAM OIDC 身份提供商与您的集群关联:
eksctl utils associate-iam-oidc-provider --cluster $cluster_name --approve
使用 eksctl 创建 IAM 角色:
下载 AWS 负载均衡器控制器的 IAM 策略,以允许其与 AWS API 交互。
curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.7.2/docs/install/iam_policy.json
使用下载的文件创建 IAM 策略:
aws iam create-policy \
--policy-name AWSLoadBalancerControllerIAMPolicy \
--policy-document file://iam_policy.json
使用刚刚创建的 IAM 策略在 kube-system 命名空间中创建服务账户:
ninjamac@ninjamacdeMacBook-Air eks % PolicyARN="arn:aws:iam::654654314383:policy/ALBIngressControllerIAMPolicy"
ninjamac@ninjamacdeMacBook-Air eks % echo $PolicyARN
arn:aws:iam::654654314383:policy/ALBIngressControllerIAMPolicy
ninjamac@ninjamacdeMacBook-Air eks % eksctl create iamserviceaccount \--cluster=rock-cluster \--namespace=kube-system \--name=alb-ingress-controller \--attach-policy-arn=$PolicyARN \--override-existing-serviceaccounts \--approve
通过Helm安装AWS ingress controller
helm repo add eks https://aws.github.io/eks-charts
helm repo update eks
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \-n kube-system \--set clusterName=rock-cluster \--set serviceAccount.create=false \--set serviceAccount.name=alb-ingress-controller
部署示例应用
现在,我们将一个示例 2048 游戏部署到我们的 Kubernetes 集群中,并使用 Ingress 资源将其暴露给流量。
部署 2048 游戏资源:
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.11.0/docs/examples/2048/2048_full.yaml
几分钟后,使用以下命令验证 Ingress 资源是否已创建。
kubectl get ingress/ingress-2048 -n game-2048
示例输出如下。
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-2048 <none> * k8s-game2048-ingress2-xxxxxxxxxx-yyyyyyyyyy.region-code.elb.amazonaws.com 80 2m32s
通过Route 53创建一个别名记录,指向elb的地址,这样就可以通过自定义的域名来访问2048游戏。
优化 AWS EKS:如何使用一个负载均衡器管理多个子域
在 AWS EKS(弹性 Kubernetes 服务)上的典型 Kubernetes 设置中,如果您依赖 AWS 负载均衡器控制器的默认配置,管理多个子域的成本可能会非常高昂。默认情况下,每次创建新的 Ingress 资源时,AWS 都会预配一个新的应用程序负载均衡器 (ALB)。当您管理多个子域时,此设置的成本会非常高昂,每个 ALB 每月的成本高达数百美元。
我们将介绍一种解决方案,允许您在 AWS EKS 中将单个 ALB 用于多个子域。这种方法不仅可以降低成本,还可以简化管理,尤其是在您在不同的子域上托管大量内部工具或服务的情况下。
为什么在 AWS EKS 中使用多个子域?
在 EKS 集群中使用子域很常见,原因如下:
- 托管多个应用程序或工具:通常,您可能在同一个 EKS 集群中托管各种应用程序,例如监控工具、仪表板或 CI/CD 流水线。每个应用程序都可以通过单独的子域公开。
- 受控访问:您可能希望向不同的团队成员公开不同的工具,而无需授予对整个 Kubernetes 集群的完全访问权限。子域方法可以实现更好的访问控制和隔离。
- 集中式架构:为不同的服务设置子域可以使您的设置井然有序,并更轻松地管理流量、SSL 证书和访问控制。
为多个子域创建 Kubernetes Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: multi-subdomain-ingressnamespace: defaultannotations:alb.ingress.kubernetes.io/ssl-redirect: '443'alb.ingress.kubernetes.io/backend-protocol: HTTPalb.ingress.kubernetes.io/scheme: internet-facingalb.ingress.kubernetes.io/security-groups: sg-xxxxxxxalb.ingress.kubernetes.io/group.name: "my-subdomain-group"alb.ingress.kubernetes.io/certificate-arn: "certificate-arn-xxxxxxxx"alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]'alb.ingress.kubernetes.io/manage-backend-security-group-rules: "true"
spec:rules:- host: service1.mydomain.comhttp:paths:- path: /pathType: Prefixbackend:service:name: "eks-service-1"port:number: 80- host: service2.mydomain.comhttp:paths:- path: /pathType: Prefixbackend:service:name: "eks-service-2"port:number: 80
您可以使用 tls 代码块(而非“alb.ingress.kubernetes.io/certificate-arn”)为子域名配置 SSL 证书。
用于 HTTPS 的 TLS:使用 tls 代码块为您的子域名定义 SSL 证书。您可以使用通配符证书 (*.domain.com) 来简化管理。
tls:- hosts:- service1.example.com- service2.example.comsecretName: example-tls-secret # SSL certificate for both subdomain
为您的子域定义服务
Ingress 中的每个子域都必须绑定到处理流量的 Kubernetes 服务。以下是 service1 的服务资源示例:
apiVersion: v1
kind: Service
metadata:name: service1namespace: defaultlabels:app: {your-app}
spec:ports:- port: 80targetPort: 8080selector:app: service1
应用配置
Ingress 和服务配置准备就绪后,您可以使用 kubectl 应用它们:
kubectl apply -f eks-ingress.yaml
kubectl apply -f eks-service1.yaml
kubectl apply -f eks-service2.yaml
AWS 现在将创建一个单独的 ALB,根据您定义的子域规则路由流量。
高级特性
HTTPS 重定向
HTTP 协议的 URL 应重定向至 HTTPS 协议。我们将使用 alb.ingress.kubernetes.io/actions.${action-name} 注释来设置 Ingress,将 http 流量重定向至 https。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: echoservernamespace: echoserverannotations:kubernetes.io/ingress.class: albalb.ingress.kubernetes.io/scheme: internet-facingalb.ingress.kubernetes.io/tags: Environment=dev,Team=appalb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'alb.ingress.kubernetes.io/ssl-redirect: '443'
spec:rules:- host: "dev.sivamuthukumar.com"http:paths:- path: /echopathType: Prefixbackend:service:name: echoserverport:number: 80
自定义属性和插件
负载均衡器的自定义属性可以通过注释控制 - alb.ingress.kubernetes.io/load-balancer-attributes
例如,要在应用程序负载均衡器中启用 HTTP2,请执行以下操作:
alb.ingress.kubernetes.io/load-balancer-attributes: routes.http2.enabled=true
查看其他可以添加到注释中的属性。
您可以通过在 Ingress 对象中添加以下注释,将 WAF 或 AWS Shield 附加到负载均衡器。
alb.ingress.kubernetes.io/wafv2-acl-arn: <WAFv2 ACL ARN>
alb.ingress.kubernetes.io/shield-advanced-protection: 'true'
访问控制
可以使用以下注解控制负载均衡器的访问控制。
alb.ingress.kubernetes.io/scheme: internal # To enable the internal load balancers
alb.ingress.kubernetes.io/inbound-cidrs: 10.0.0.0/24 # Inbound CIDRs from your network or VPC
alb.ingress.kubernetes.io/security-groups: sg-xxxx, sg-yyyy # Security gr
自定义域名和 SSL 证书
现在,我们将自定义域名绑定到 ALB 和 SSL 证书。您可以通过两种方式绑定 SSL 证书。
- 通过注释设置证书 - alb.ingress.kubernetes.io/certificate-arn 指定由 AWS 证书管理器管理的一个或多个证书的 ARN。
alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-west-2:xxxxx:certificate/xxxxxxx
- 您可以使用域名设置 SSL 证书的自动发现。
如果未指定 [alb.ingress.kubernetes.io/certificate-arn](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.2/guide/ingress/annotations/#certificate-arn) 注释,则可以使用 Ingress 资源中的主机名自动发现 ALB 侦听器的 TLS 证书。
控制器将尝试从 Ingress 中的 tls 字段和 Ingress 规则中的 host 字段中发现 TLS 证书。
在本例中,我们将设置 SSL 证书的自动发现。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: echoservernamespace: echoserverannotations:**kubernetes.io/ingress.class: albalb.ingress.kubernetes.io/scheme: internet-facingalb.ingress.kubernetes.io/tags: Environment=dev,Team=app**
spec:rules:- host: "dev.spectaflare.com"http:paths:- path: /echopathType: Prefixbackend:service:name: echoserverport:number: 80
执行curl命令
curl https://dev.spectaflare.com/echo -i
HTTP/1.1 200 OK
总结
AWS 负载均衡器控制器提供了一种 Kubernetes 原生的方式来配置和管理 Elastic Load Balancer,用于将流量路由到 Kubernetes 集群中运行的应用程序。我希望我已经向您解释了路由、入口组、SSL 配置、HTTP 到 HTTPS 重定向以及其他高级概念。
码字不易,如果文章能够给大家带来一定的帮助!欢迎关注、评论互动~