如何提供对 Amazon EKS 集群中的多个 Kubernetes 服务的外部访问权限?
我想提供对我的 Amazon Elastic Kubernetes Service (Amazon EKS) 集群中多个 Kubernetes 服务的外部访问权限。
简短描述
使用用于 Kubernetes 的 NGINX 入口控制器或 AWS 负载均衡器控制器提供对 Amazon EKS 集群中的多个 Kubernetes 服务的外部访问权限。NGINX 入口控制器主要由 NGINX 维护。要检查 NGINX 入口控制器的问题,请参阅 GitHub 网站上的问题列表。AWS 负载均衡器控制器主要由 Amazon Web Services (AWS) 维护。要检查 AWS 负载均衡器控制器上的问题,请参阅 GitHub 网站上的问题列表。
**重要提示:**入口控制器和 IngressClass(来自 Kubernetes 网站)与入口(来自 Kubernetes 网站)不同。入口是一种 Kubernetes 资源,可将集群外部的 HTTP 和 HTTPS 路由公开到集群内的服务。入口控制器通常可使用负载均衡器完成入口用途(通常使用负载均衡器)。您不能在没有入口控制器的情况下使用入口。IngressClass 用于标识哪个入口控制用于完成入口对象请求。
前提条件:安装 AWS 负载均衡器控制器。最佳实践是使用 AWS 负载均衡器控制器为 Amazon EKS 中的 LoadBalancer 类型服务对象创建和管理网络负载均衡器。
解决方法
以下解决方案使用 Kubernetes GitHub 网站上的 kubernetes/ingress-nginx 入口控制器。可供公众使用的另一个入口控制器是来自 NGINX GitHub 网站的 nginxinc/kubernetes-ingress。
部署用于 Kubernetes 的 NGINX 入口控制器
您可以通过传输控制协议(TCP)或传输层安全性协议(TLS)部署用于 Kubernetes 的 NGINX 入口控制器。
**注意:**以下解决方案已在 Amazon EKS 版本 1.22、NGINX 入口控制器版本 1.3.0 和 AWS 负载均衡器控制器版本 2.4.3 上进行了测试。
(选项 1)网络负载均衡器上的 NGINX 入口控制器及 TCP
1. 获取 YAML 文件以部署以下 Kubernetes 对象:namespace、serviceaccounts、configmap、clusterroles、clusterrolebindings、roles、rolebindings、services、deployments、ingressclasses 和 validatingwebhookconfigurations。
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/aws/deploy.yaml
2. 编辑文件。然后,在 ingress-nginx-controller 服务对象部分,将所有 service.beta.kubernetes.io 注释替换为以下内容:
service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true" service.beta.kubernetes.io/aws-load-balancer-type: "external" service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "instance" service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
3. 应用清单:
kubectl apply -f deploy.yaml
示例输出:
namespace/ingress-nginx created serviceaccount/ingress-nginx created configmap/ingress-nginx-controller created clusterrole.rbac.authorization.k8s.io/ingress-nginx created clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created role.rbac.authorization.k8s.io/ingress-nginx created rolebinding.rbac.authorization.k8s.io/ingress-nginx created service/ingress-nginx-controller-admission created service/ingress-nginx-controller created deployment.apps/ingress-nginx-controller created ingressclass.networking.k8s.io/nginx created validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created serviceaccount/ingress-nginx-admission created clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
(选项 2) 网络负载均衡器上的 NGINX 入口控制器 TLS 终止
默认情况下,先前的解决方案将会终止 NGINX 入口控制器中的 TLS。此外,您还可以配置 NGINX 入口服务,以终止网络负载均衡器处的 TLS。
1. 下载 deploy.yaml 模板:
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/aws/nlb-with-tls-termination/deploy.yaml
2. 编辑文件。然后,在 ingress-nginx-controller 服务对象部分,将所有 service.beta.kubernetes.io 注释替换为以下内容:
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true" service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:us-west-2:XXXXXXXX:certificate/XXXXXX-XXXXXXX-XXXXXXX-XXXXXXXX service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "443" service.beta.kubernetes.io/aws-load-balancer-type: "external" service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "instance" service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
**注意:**请确保包含 service.beta.kubernetes.io/aws-load-balancer-ssl-cert 的 ARN。
3. 编辑文件,然后更改 Kubernetes 集群的 Amazon Virtual Private Cloud (Amazon VPC) CIDR:
proxy-real-ip-cidr: XXX.XXX.XXX/XX
4. 应用清单:
kubectl apply -f deploy.yaml
**注意:**先前的清单使用 ExternalTrafficPolicy 作为 local 以保留源(客户端)IP 地址。在 Amazon VPC 中将此配置与自定义 DHCP 名称结合使用会导致出现问题。为防止问题发生,请将以下补丁应用于 kube-proxy:
kubectl edit daemonset kube-proxy -n kube-system
5. 编辑清单以包含以下片段:
spec: template: spec: containers: - name: kube-proxy command: - kube-proxy - --hostname-override=$(NODE_NAME) - --v=2 - --config=/var/lib/kube-proxy-config/config env: - name: NODE_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: spec.nodeName
验证已部署的资源
AWS 负载均衡器控制器
命令:
kubectl get all -n kube-system --selector app.kubernetes.io/instance=aws-load-balancer-controller
示例输出:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod/aws-load-balancer-controller-85cd8965dc-ctkjt 1/1 Running 0 48m 192.168.37.36 ip-192-168-59-225.us-east-2.compute.internal none none pod/aws-load-balancer-controller-85cd8965dc-wpwx9 1/1 Running 0 48m 192.168.53.110 ip-192-168-59-225.us-east-2.compute.internal none> none NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR service/aws-load-balancer-webhook-service ClusterIP 10.100.154.44 none 443/TCP 19h app.kubernetes.io/instance=aws-load-balancer-controller,app.kubernetes.io/name=aws-load-balancer-controller NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR deployment.apps/aws-load-balancer-controller 2/2 2 2 19h aws-load-balancer-controller 602401143452.dkr.ecr.us-west-2.amazonaws.com/amazon/aws-load-balancer-controller:v2.4.0 app.kubernetes.io/instance=aws-load-balancer-controller,app.kubernetes.io/name=aws-load-balancer-controller NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR replicaset.apps/aws-load-balancer-controller-85cd8965dc 2 2 2 19h aws-load-balancer-controller 602401143452.dkr.ecr.us-west-2.amazonaws.com/amazon/aws-load-balancer-controller:v2.4.0 app.kubernetes.io/instance=aws-load-balancer-controller,app.kubernetes.io/name=aws-load-balancer-controller,pod-template-hash=85cd8965dc
NGINX 入口控制器
命令:
kubectl get all -n ingress-nginx --selector app.kubernetes.io/instance=ingress-nginx
示例输出:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod/ingress-nginx-controller-54d8b558d4-k4pdf 1/1 Running 0 56m 192.168.46.241 ip-192-168-59-225.us-east-2.compute.internal none none NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR service/ingress-nginx-controller LoadBalancer 10.100.99.129 ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com 80:32578/TCP,443:30724/TCP 15h app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx service/ingress-nginx-controller-admission ClusterIP 10.100.190.61 none 443/TCP 15h app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR deployment.apps/ingress-nginx-controller 1/1 1 1 15h controller k8s.gcr.io/ingress-nginx/controller:v1.1.1@sha256:0bc88eb15f9e7f84e8e56c14fa5735aaa488b840983f87bd79b1054190e660de app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR replicaset.apps/ingress-nginx-controller-54d8b558d4 1 1 1 15h controller k8s.gcr.io/ingress-nginx/controller:v1.1.1@sha256:0bc88eb15f9e7f84e8e56c14fa5735aaa488b840983f87bd79b1054190e660de app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx,pod-template-hash=54d8b558d4 NAME COMPLETIONS DURATION AGE CONTAINERS IMAGES SELECTOR job.batch/ingress-nginx-admission-create 1/1 2s 15h create k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.1.1@sha256:64d8c73dca984af206adf9d6d7e46aa550362b1d7a01f3a0a91b20cc67868660 controller-uid=242bdf56-de16-471d-a691-1ca1dbc10a41 job.batch/ingress-nginx-admission-patch 1/1 2s 15h patch k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.1.1@sha256:64d8c73dca984af206adf9d6d7e46aa550362b1d7a01f3a0a91b20cc67868660 controller-uid=a9e710d2-5001-4d40-a435-ddc8993bfe42
IngressClass
命令:
kubectl get ingressclass
示例输出:
NAME CONTROLLER PARAMETERS AGE alb ingress.k8s.aws/alb IngressClassParams.elbv2.k8s.aws/alb 19h nginx k8s.io/ingress-nginx none 15h
测试部署设置
**注意:**以下步骤将运行两个微服务。如果 Kubernetes 为默认类型,则会在内部公开微服务。
1. 设置部署或微服务。例如,hostname-app 和 apache-app。
hostname-app 的 hostname-app-svc.yaml 文件的示例:
apiVersion: apps/v1 kind: Deployment metadata: name: hostname-app namespace: default spec: replicas: 2 selector: matchLabels: app: hostname-app template: metadata: labels: app: hostname-app spec: containers: - name: hostname-app image: k8s.gcr.io/serve_hostname:1.1 --- apiVersion: v1 kind: Service metadata: name: hostname-svc namespace: default spec: ports: - port: 80 targetPort: 9376 protocol: TCP selector: app: hostname-app
apache-app 的 apache-app-svc.yaml 文件的示例:
apiVersion: apps/v1 kind: Deployment metadata: name: apache-app namespace: default spec: replicas: 2 selector: matchLabels: app: apache-app template: metadata: labels: app: apache-app spec: containers: - name: apache-app image: httpd:latest ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: apache-svc namespace: default labels: spec: ports: - port: 80 targetPort: 80 protocol: TCP selector: app: apache-app
2. 应用您的配置。
hostname-app:
kubectl apply -f hostname-app-svc.yaml
apache-app:
kubectl apply -f apache-app-svc.yaml
3. 验证是否已创建资源。
部署
命令:
kubectl get deployment hostname-app apache-app -n default
示例输出:
NAME READY UP-TO-DATE AVAILABLE AGE hostname-app 2/2 2 2 29m apache-app 2/2 2 2 29m
服务
命令:
kubectl get svc apache-svc hostname-svc -n default
示例输出:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE apache-svc ClusterIP 10.100.73.51 none 80/TCP 29m hostname-svc ClusterIP 10.100.100.44 none 80/TCP 29m
测试 NGINX 入口控制器
1. 访问您从命令行中检索到的负载均衡器的 DNS URL:
curl -I ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com
示例输出:
HTTP/1.1 404 Not Found Date: Thu, 03 Mar 2022 14:03:11 GMT Content-Type: text/html Content-Length: 146 Connection: keep-alive
注意:对于所有未定义入口规则的域请求,默认服务器将会返回 404 Not Found(404 未找到)页面。根据定义的规则,除非请求与配置匹配,否则入口控制器不会将流量转移到特定后端服务。由于已针对入口对象配置主机字段,您必须为请求的主机标头提供相同的主机名。在测试环境中,使用 curl 标志提供主机标头。在生产环境中,将负载均衡器 DNS 名称映射到任何 DNS 提供商上的主机名 (例如 Amazon Route 53)。
2. 实施入口,使其使用 NGINX 入口控制器提供的单个负载均衡器与您的服务连接。
示例 micro-ingress.yaml:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: micro-ingress namespace: default annotations: kubernetes.io/ingress.class: nginx spec: rules: - host: hostname.mydomain.com http: paths: - backend: service: name: hostname-svc port: number: 80 path: / pathType: Prefix - host: apache.mydomain.com http: paths: - backend: service: name: apache-svc port: number: 80 path: / pathType: Prefix
**注意:**有关更多信息,请参阅基于名称的虚拟主机(来自 Kubernetes 网站)
3. 验证是否已创建资源。
入口
命令:
kubectl get ingress -n default
示例输出:
NAME CLASS HOSTS ADDRESS PORTS AGE micro-ingress none hostname.mydomain.com,apache.mydomain.com ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com 80 29m
4. 将主机标头添加到请求。
第一个配置的域:
curl -i -H "Host: hostname.mydomain.com" http://aaa71bxxxxx-11xxxxx10.us-east-2.elb.amazonaws.com/
示例输出:
HTTP/1.1 200 OK Date: Sat, 26 Mar 2022 18:50:38 GMT Content-Type: text/plain; charset=utf-8 Content-Length: 29 Connection: keep-alive
第二个配置的域:
curl -i -H "Host: apache.mydomain.com" http://aaa71bxxxxx-11xxxxx10.us-east-2.elb.amazonaws.com/
示例输出:
HTTP/1.1 200 OK Date: Sat, 26 Mar 2022 18:51:00 GMT Content-Type: text/html Content-Length: 45 Connection: keep-alive Last-Modified: Mon, 11 Jun 2007 18:53:14 GMT ETag: "2d-432a5e4a73a80" Accept-Ranges: bytes
在添加主机标头后,如果流量与入口中定义的规则匹配,则入口控制器会将它重定向到后端配置的服务。
要保持相同的域名,但根据访问的路径转移流量,您必须通过入口添加基于路径的路由。
例如:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: path-ingress namespace: default annotations: kubernetes.io/ingress.class: nginxd nginx.ingress.kubernetes.io/rewrite-target: / spec: rules: - host: mydomain.com http: paths: - backend: service: name: hostname-svc port: number: 80 path: /hostname pathType: Prefix - host: mydomain.com http: paths: - backend: service: name: apache-svc port: number: 80 path: /apache pathType: Prefix
注意:如果请求的主机标头为 mydomain.com,则上述示例只会返回 200 响应。可以在 /hostname 或 /apache 路径上访问这些请求。对于所有其他请求,则会返回 404 响应。
5. 验证是否已添加基于路径的路由:
命令:
kubectl get ingress -n default
输出:
NAME CLASS HOSTS ADDRESS PORTS AGE micro-ingress none hostname.mydomain.com,apache.mydomain.com ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com 80 164m path-ingress none mydomain.com,mydomain.com ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com 80 120m
命令:
curl -i -H "Host: mydomain.com" http://aaa71bxxxxx-11xxxxx10.us-east-2.elb.amazonaws.com/hostname
-或者-
curl -i -H "Host: mydomain.com" http://aaa71bxxxxx-11xxxxx10.us-east-2.elb.amazonaws.com/apache
使用 AWS 负载均衡器控制器测试入口
1. 使用以下示例入口清单启动应用程序负载均衡器:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: micro-ingress-alb namespace: default annotations: kubernetes.io/ingress.class: alb alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip spec: rules: - host: alb.hostname.mydomain.com http: paths: - backend: service: name: hostname-svc port: number: 80 path: / pathType: Prefix - host: alb.apache.mydomain.com http: - backend: service: name: apache-svc port: number: 80 path: / pathType: Prefix
2. 验证是否已启动应用程序负载均衡器。
命令:
kubectl get ingress -n default
输出:
NAME CLASS HOSTS ADDRESS PORTS AGE micro-ingress none hostname.mydomain.com,apache.mydomain.com ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com 80 164m micro-ingress-alb none alb.hostname.mydomain.com,alb.apache.mydomain.com k8s-default-microing-8a252bde81-1907206594.us-east-2.elb.amazonaws.com 80 18m path-ingress none mydomain.com,mydomain.com ad9bba7a8239a475297d24bd2f617782-a579e639079f8270.elb.us-east-2.amazonaws.com 80 120m
基于第一个配置的域的请求:
curl -i -H "Host: alb.hostname.mydomain.com" http://k8s-default-microing-8a252bde81-1907206594.us-east-2.elb.amazonaws.com
示例输出:
HTTP/1.1 200 OK Date: Sat, 26 Mar 2022 20:46:02 GMT Content-Type: text/plain; charset=utf-8 Content-Length: 29 Connection: keep-alive
基于第二个配置的域的请求:
curl -i -H "Host: alb.apache.mydomain.com" http://k8s-default-microing-8a252bde81-1907206594.us-east-2.elb.amazonaws.com
示例输出:
HTTP/1.1 200 OK Date: Sat, 26 Mar 2022 20:46:14 GMT Content-Type: text/html Content-Length: 45 Connection: keep-alive Server: Apache/2.4.53 (Unix) Last-Modified: Mon, 11 Jun 2007 18:53:14 GMT ETag: "2d-432a5e4a73a80" Accept-Ranges: bytes
相关内容
- AWS 官方已更新 5 个月前
- AWS 官方已更新 2 年前