在 AWS EKS 中,如何定义入口以将一个 ALB 用于多个子域 URL,每个子域 URL 都有自己的证书?

Bry*_*yan 1 amazon-web-services kubernetes kubernetes-ingress amazon-eks

我有多个服务需要公开到 Internet,但我想为它们使用单​​个 ALB。

我正在使用最新的AWS Load Balancer Controller,我一直在阅读这里的文档(https://kubernetes-sigs.github.io/aws-load-balancer-controller/guide/ingress/annotations/#traffic-routing ),但我还没有找到关于如何实现这一点的明确解释。

这是设置:

我有 service-a.example.com -and- service-b.example.com。他们每个人在 Amazon Certificate Manager 中都有自己的证书。

在 Kubernetes 中,每个都有自己的服务对象,定义如下(每个都是唯一的):

apiVersion: v1
kind: Service
metadata:
  name: svc-a-service
  annotations:
    alb.ingress.kubernetes.io/healthcheck-protocol: HTTP
    alb.ingress.kubernetes.io/healthcheck-port: traffic-port
    alb.ingress.kubernetes.io/healthy-threshold-count: '5'
    alb.ingress.kubernetes.io/unhealthy-threshold-count: '2'
    alb.ingress.kubernetes.io/healthcheck-path: /index.html
    alb.ingress.kubernetes.io/healthcheck-interval-seconds: '30'
    alb.ingress.kubernetes.io/healthcheck-timeout-seconds: '5'
    alb.ingress.kubernetes.io/success-codes: '200'
    alb.ingress.kubernetes.io/tags: Environment=Test,App=ServiceA
spec:
  selector:
    app: service-a
  ports:
  - port: 80
    targetPort: 80
  type: NodePort
Run Code Online (Sandbox Code Playgroud)

每个服务都有自己的 Ingress 对象,定义如下(同样,每个服务都是唯一的,并且为每个服务指定了正确的证书):

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: svc-a-ingress
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/group.name: services
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/security-groups: sg-01234567898765432
    alb.ingress.kubernetes.io/ip-address-type: ipv4
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
    alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}'
    alb.ingress.kubernetes.io/actions.response-503: >
      {"type":"fixed-response","fixedResponseConfig":{"contentType":"text/plain","statusCode":"503","messageBody":"Unknown Host"}}
    alb.ingress.kubernetes.io/target-type: instance
    alb.ingress.kubernetes.io/load-balancer-attributes: routing.http2.enabled=true,idle_timeout.timeout_seconds=600
    alb.ingress.kubernetes.io/tags: Environment=Test
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-east-2:555555555555:certificate/33333333-2222-4444-AAAA-EEEEEEEEEEEE
    alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-2016-08
spec:
  rules:
    - http:
        paths:
          - path: /*
            backend:
              serviceName: ssl-redirect
              servicePort: use-annotation
          - path: /*
            backend:
              serviceName: svc-a-service
              servicePort: 80
          - path: /*
            backend:
              serviceName: response-503
              servicePort: use-annotation

Run Code Online (Sandbox Code Playgroud)

HTTP 到 HTTPS 重定向按预期工作。

但是 - 我的两个应用程序之间没有区别,负载均衡器能够知道发往 service-a.example.com 和 service-b.example.com 的流量应该路由到两个不同的目标组。

在控制台中的 HTTP:443 侦听器规则中,它显示:

  1. IF Path is /* THEN Forward to ServiceATargetGroup
  2. 如果路径是 /* THEN 返回固定的 503
  3. IF Path is /* THEN Forward to ServiceBTargetGroup
  4. 如果路径是 /* THEN 返回固定的 503
  5. IF 请求否则不路由 THEN 返回固定 404

所以这里的重要问题是: 应该如何定义入口以将目的地为 service-a.example.com 的流量强制为 ServiceATargetGroup - 并将目的地为 service-b.example.com 的流量强制为 ServiceBTargetGroup?

其次,我需要“否则不会路由”来返回 503 而不是 404。我希望它在规则中只出现一次(被合并) - 但它是为每个入口创建的。我的 yaml 应该如何构建以实现这一目标?

Bry*_*yan 5

我最终想通了这一点——所以对于其他绊倒这篇文章的人来说,这是我解决它的方法:

诀窍不依赖于 Ingress 对象之间的合并。是的,它可以处理一定程度的合并,但在作为目标组的服务和作为 ALB 的入口之间并没有真正的一对一关系。因此,您必须非常谨慎并了解每个 Ingress 对象中的内容。

一旦我将所有入口组合到一个对象定义中,我就能够使用以下 YAML 使其完全按照我想要的方式工作:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: svc-ingress
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/group.name: services
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/security-groups: sg-01234567898765432
    alb.ingress.kubernetes.io/ip-address-type: ipv4
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
    alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}'
    alb.ingress.kubernetes.io/actions.response-503: >
      {"type":"fixed-response","fixedResponseConfig":{"contentType":"text/plain","statusCode":"503","messageBody":"Unknown Host"}}
    alb.ingress.kubernetes.io/actions.svc-a-host: >
      {"type":"forward","forwardConfig":{"targetGroups":[{"serviceName":"svc-a-service","servicePort":80,"weight":100}]}}
    alb.ingress.kubernetes.io/conditions.svc-a-host: >
      [{"field":"host-header","hostHeaderConfig":{"values":["svc-a.example.com"]}}]
    alb.ingress.kubernetes.io/actions.svc-b-host: >
      {"type":"forward","forwardConfig":{"targetGroups":[{"serviceName":"svc-b-service","servicePort":80,"weight":100}]}}
    alb.ingress.kubernetes.io/conditions.svc-b-host: >
      [{"field":"host-header","hostHeaderConfig":{"values":["svc-b.example.com"]}}]
    alb.ingress.kubernetes.io/target-type: instance
    alb.ingress.kubernetes.io/load-balancer-attributes: routing.http2.enabled=true,idle_timeout.timeout_seconds=600
    alb.ingress.kubernetes.io/tags: Environment=Test
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-east-2:555555555555:certificate/33333333-2222-4444-AAAA-EEEEEEEEEEEE,arn:aws:acm:us-east-2:555555555555:certificate/44444444-3333-5555-BBBB-FFFFFFFFFFFF
    alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-2016-08
spec:
  backend:
    serviceName: response-503
    servicePort: use-annotation
  rules:
    - http:
        paths:
          - backend:
              serviceName: ssl-redirect
              servicePort: use-annotation
          - backend:
              serviceName: svc-a-host
              servicePort: use-annotation
          - backend:
              serviceName: svc-b-host
              servicePort: use-annotation
Run Code Online (Sandbox Code Playgroud)

默认操作:

通过直接在 下指定 serviceName 和 servicePort 来设置spec

spec:
  backend:
    serviceName: response-503
    servicePort: use-annotation
Run Code Online (Sandbox Code Playgroud)

路由:

因为我使用的是子域并且路径对我不起作用,所以我只是省略了路径,而是依赖主机名作为条件。

metadata:
  alb.ingress.kubernetes.io/actions.svc-a-host: >
      {"type":"forward","forwardConfig":{"targetGroups":[{"serviceName":"svc-a-service","servicePort":80,"weight":100}]}}
  alb.ingress.kubernetes.io/conditions.svc-a-host: >
      [{"field":"host-header","hostHeaderConfig":{"values":["svc-a.example.com"]}}]
Run Code Online (Sandbox Code Playgroud)

最终结果:

ALB 规则是按照我想要的方式精确配置的:

  • 默认操作是 503 固定响应
  • 所有 http 流量都重定向到 https
  • 流量根据主机标头定向到 TargetGroups