要提供对 Amazon EKS 集群中多个 Kubernetes 服务的外部访问,您可以使用 Ingress NGINX 控制器或适用于 Kubernetes 的 AWS 负载均衡器控制器。
- 配置公共和私有负载均衡器:我将向您展示如何使用 Ingress 控制器设置公共和私有负载均衡器。这样,您可以将私有负载均衡器用于网络内的内部流量,将公共负载均衡器用于来自外部的流量。
- 使用多个 Ingress 文件路由流量:我将解释如何使用不同的 Ingress 文件将流量定向到不同的 Kubernetes 服务。如果您对不同类型的流量设置了不同的规则,这将非常有用。
- 使用单个 Ingress 文件路由流量:我还将介绍如何使用单个 Ingress 文件管理流向各种 Kubernetes 服务的流量。此方法可帮助您将路由规则整合到单个配置中。
在深入探讨这些场景之前,让我们先了解一下什么是 Ingress NGINX 控制器以及如何设置它。
Ingress NGINX 控制器
Ingress NGINX 控制器充当 Kubernetes 服务的网关。它管理进入 Kubernetes 集群的流量,并根据您定义的规则将其定向到正确的服务。您可以将其视为流量引导器,确保请求顺利到达正确的目的地。
“Ingress”和“Ingress 控制器”之间存在差异:
Ingress 是一种 Kubernetes 资源,用于管理从集群外部到集群内部服务的 HTTP 和 HTTPS 流量。
Ingress 控制器是实现此功能的工具,通常使用负载均衡器。没有 Ingress 控制器,您就无法使用 Ingress。
IngressClass 可以帮助您选择要使用的 Ingress 控制器。
如何安装 Ingress NGINX 控制器
有几种简单的方法可以安装 Ingress NGINX。以下是每种方法的简单指南:
1. 使用 Helm:
a) 添加 Ingress NGINX Helm 仓库:这就像从专门的商店获取所需的工具一样。
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
b) 为 Ingress NGINX 创建一个命名空间:这将设置一个 Ingress NGINX 可以工作的空间。
$ kubectl create namespace ingress-nginx
c) 安装 Ingress NGINX:这将把 Ingress NGINX 放入您的 Kubernetes 环境中。
helm install my-ingress-nginx ingress-nginx/ingress-nginx --namespace ingress-nginx
2. 使用 YAML 文件:
下载 deploy.yaml 文件并应用。
这将使用预定义文件设置 Ingress NGINX。
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.11.1/deploy/static/provider/cloud/deploy.yaml
这将安装 Ingress NGINX 。
注意:这将在 AWS 中创建经典负载均衡器,我们可以使用不同类型的 Kubernetes 服务(ClusterIP、NodePort 或 LoadBalancer)来公开 Ingress Nginx Controller 服务。
使用 Ingress NGINX 控制器配置公有和私有网络负载均衡器
先决条件:安装 AWS 负载均衡器控制器。最佳实践是使用 AWS 负载均衡器控制器为 Amazon EKS 中的 LoadBalancer 类型服务对象创建和管理网络负载均衡器。
在 EKS 集群中配置 AWS 负载均衡器控制器后,您可以验证其状态。
$ kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
aws-load-balancer-controller-b59f12345-j9cw 1/1 Running 0 1d
aws-load-balancer-controller-b59f77777-xdh2 1/1 Running 0 1d
在 AWS 中,我们使用网络负载均衡器 (NLB) 将 Ingress-Nginx 控制器暴露在 Type=LoadBalancer 的服务后面。
要使用 Ingress NGINX 控制器设置私有和公共负载均衡器,请先下载 deploy.yaml 文件。然后,您可以根据需要自定义此文件来配置负载均衡器。
ninjamac@ninjamacdeMacBook-Air eks % curl -O https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.11.1/deploy/static/provider/aws/deploy.yaml
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 16407 100 16407 0 0 18449 0 --:--:-- --:--:-- --:--:-- 18434
注释掉 NLB 的当前服务详情,添加提供的新行,然后应用更新后的文件。
注意:请务必更新 VPC 子网的标签。
---
apiVersion: v1
kind: Service
metadata:
annotations:
# Create External NLB
service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"
service.beta.kubernetes.io/aws-load-balancer-type: nlb
service.beta.kubernetes.io/aws-load-balancer-manage-backend-security-group-rules: "true"
service.beta.kubernetes.io/aws-load-balancer-security-groups: "sg-XXXXXX"
service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:ap-south-1:XXXXXX:certificate/XXXXXXX
service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "ssl"
service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "https"
service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: '3600'
service.beta.kubernetes.io/aws-load-balancer-name: "ingress-nginx-external-nlb"
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.11.1
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
externalTrafficPolicy: Local
ports:
- appProtocol: http
name: http
port: 80
protocol: TCP
targetPort: http
- appProtocol: https
name: https
port: 443
protocol: TCP
targetPort: https
selector:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
type: LoadBalancer
---
apiVersion: v1
kind: Service
metadata:
annotations:
# Create internal NLB
service.beta.kubernetes.io/aws-load-balancer-scheme: "internal"
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"
service.beta.kubernetes.io/aws-load-balancer-type: nlb
service.beta.kubernetes.io/aws-load-balancer-manage-backend-security-group-rules: "true"
service.beta.kubernetes.io/aws-load-balancer-security-groups: "sg-XXXXXXXX"
service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:ap-south-1:XXXXXX:certificate/XXXXXXXXX
service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "ssl"
service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "https"
service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: '3600'
service.beta.kubernetes.io/aws-load-balancer-name: "ingress-nginx-internal-nlb"
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.11.1
name: ingress-nginx-controller-internal
namespace: ingress-nginx
spec:
externalTrafficPolicy: Local
ports:
- appProtocol: http
name: http
port: 80
protocol: TCP
targetPort: http
- appProtocol: https
name: https
port: 443
protocol: TCP
targetPort: https
selector:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
type: LoadBalancer
---
$ kubectl apply -f deploy.yaml
namespace/ingress-nginx created
serviceaccount/ingress-nginx created
serviceaccount/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
configmap/ingress-nginx-controller created
service/ingress-nginx-controller created
service/ingress-nginx-controller-internal created
service/ingress-nginx-controller-admission created
deployment.apps/ingress-nginx-controller created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created
ingressclass.networking.k8s.io/nginx created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created
$
使用上述命令为公共和私有 NLB 创建入口,让我们使用以下命令进行验证:
$ kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller LoadBalancer XXX.XXX.XXX.XXX ingress-nginx-external-nlb-XXXXX.elb.ap-south-1.amazonaws.com 80:31070/TCP,443:32588/TCP 41s
ingress-nginx-controller-admission ClusterIP XXX.XXX.XXX.XXX <none> 443/TCP 41s
ingress-nginx-controller-internal LoadBalancer XXX.XXX.XXX.XXX ingress-nginx-internal-nlb-XXXXX.elb.ap-south-1.amazonaws.com 80:31690/TCP,443:31672/TCP 41s
$
使用 DNS 提供商为负载均衡器添加域名记录,以便正确路由流量。在本博客中,我使用了 Route53,并使用相同的域名 ingress.example.com 为外部负载均衡器创建了一个公共主机记录,为内部负载均衡器创建了一个私有主机记录。您也可以为外部和内部负载均衡器使用不同的域名。
测试 Ingress NGINX 控制器
使用多个 Ingress 文件路由流量
让我们在不同的命名空间中部署两个应用程序,并为每个命名空间创建单独的 Ingress 文件。
使用多个 Ingress 文件路由流量
创建两个命名空间来部署应用程序
$kubectl create namespace apache-app-ns
$kubectl create namespace nginx-app-ns
验证状态
$ kubectl get ns
设置两个部署或微服务。例如:使用以下 yaml 文件创建 nginx-app 和 apache-app。
## nginx-app.yaml ##
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-app
name: nginx-app
namespace: nginx-app-ns
spec:
replicas: 1
selector:
matchLabels:
app: nginx-app
template:
metadata:
labels:
app: nginx-app
spec:
containers:
- image: nginx
name: nginx
---
apiVersion: v1
kind: Service
metadata:
namespace: nginx-app-ns
name: nginx-svc
labels:
app: nginx-app
spec:
type: ClusterIP
selector:
app: nginx-app
ports:
- protocol: TCP
port: 80
targetPort: 80
## apache-app.yaml ###
apiVersion: apps/v1
kind: Deployment
metadata:
name: apache-app
namespace: apache-app-ns
spec:
replicas: 1
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: apache-app-ns
labels:
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
app: apache-app
$ kubectl apply -f apache-app-svc.yaml
$ kubectl apply -f nginx-app.yaml
先部署nginx 应用
### nginx-ingress.yml ##
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/add-base-url: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$1
name: nginx-ingress
namespace: nginx-app-ns
labels:
app: nginx
spec:
ingressClassName: nginx
rules:
- host: ingress.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-svc
port:
number: 80
$ kubectl apply -f nginx-ingress.yml
ingress.networking.k8s.io/nginx-ingress configured
此 Ingress 配置确保路径包含 / 的请求会被转发到 nginx-app-ns 命名空间内的 nginx-svc 服务,并由 Ingress NGINX 控制器进行相应的 URL 重写。
ingressClassName: nginx:指定此 Ingress 使用的 Ingress 类。此处设置为 nginx,表示 Ingress NGINX 控制器应该处理此 Ingress。
# host: "your-domain.com"
请将其替换为您的域名或子域名
现在为 Apache 应用程序部署 Ingress:
### apache-app-ingress.yaml ###
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/add-base-url: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$1
name: apache-ingress
namespace: apache-app-ns
labels:
app: apache-app
spec:
ingressClassName: nginx
rules:
- host: ingress.example.com
http:
paths:
- path: /apache
pathType: Prefix
backend:
service:
name: apache-svc
port:
number: 80
$ kubectl apply -f apache-app-ingress.yaml
ingress.networking.k8s.io/apache-ingress configured
通过使用上述命令为 apache 应用程序创建入口,并确保带有 /apache 路径的请求转发到 apache-app-ns 命名空间内的 apache-svc 服务,让我们使用以下命令验证是否创建了资源:
$ kubectl get svc -A |egrep "apache-svc|nginx-svc"
apache-app-ns apache-svc ClusterIP XX.XXX.XXX.XXX <none> 80/TCP 45m
nginx-app-ns nginx-svc ClusterIP XX.XXX.XXX.XXX <none> 80/TCP 36m
$ kubectl get ing -A |egrep "apache|nginx"
apache-app-ns apache-ingress nginx ingress.example.com ingress-nginx-external-nlb-XXXXX.elb.ap-south-1.amazonaws.com 80 23m
nginx-app-ns nginx-ingress nginx ingress.example.com ingress-nginx-external-nlb-XXXXXX.elb.ap-south-1.amazonaws.com 80 26m
$
使用以下 URL 访问 nginx 和 apache 应用程序
apache-app: http://ingress.example.com/apache
注意:内部负载均衡器可在 VPC 内部或使用 VPN 设置访问。
使用单个 Ingress 文件路由流量
让我们在不同的命名空间中部署两个应用程序,并创建单个 Ingress 文件,使用“ExternalName”服务将流量路由到后端服务。
ExternalName 服务是一种特殊的服务,它没有选择器,而是使用 DNS。
使用单个 Ingress 文件路由流量
Routing Traffic with a Single Ingress File
### app-external-service.yaml ###
apiVersion: v1
kind: Service
metadata:
name: nginx-external
namespace: default
spec:
type: ExternalName
externalName: nginx-svc.nginx-app-ns
---
apiVersion: v1
kind: Service
metadata:
name: apache-external
namespace: default
spec:
type: ExternalName
externalName: apache-svc.apache-app-ns
$ kubectl apply -f app-external-service.yaml
service/nginx-external created
service/apache-external created
$
$ kubectl get svc |egrep "apache|nginx"
apache-external ExternalName <none> apache-svc.stream-app-ns <none> 3m41s
nginx-external ExternalName <none> nginx-svc.blog-app-ns <none> 3m41s
$
此处,默认命名空间中名为 nginx-external 和 apache-external 的 Kubernetes 服务被设置为将请求重定向到 DNS 名称分别为 nginx-svc.nginx-app-ns 和 apache-svc.apache-app-ns 的外部服务。
接下来,我们将创建一个 Ingress 文件,将流量路由到这些 ExternalName 服务,确保流量被定向到正确的后端服务。
注意:我们的 Ingress 和 ExternalName 服务应部署在同一命名空间中。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/add-base-url: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$1
name: nginx-ingress
namespace: default
labels:
app: nginx
spec:
ingressClassName: nginx
rules:
- host: ingress.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-external
port:
number: 80
- path: /apache
pathType: Prefix
backend:
service:
name: apache-external
port:
number: 80
$kubectl apply -f nginx-ingress.yml
ingress.networking.k8s.io/nginx-ingress created
$
使用以下命令测试 nginx 和 apache 应用,您也可以通过浏览器进行测试
$ curl -Ilk ingress.example.com
HTTP/1.1 200 OK
Date: Sun, 04 May 2025 20:38:20 GMT
Content-Type: text/html
Content-Length: 615
Connection: keep-alive
Last-Modified: Sun, 04 May 2025 13:22:30 GMT
ETag: "6655da96-267"
Accept-Ranges: bytes
$ curl -Ilk ingress.example.com/apache
HTTP/1.1 200 OK
Date: Sun, 04 May 2025 20:38:25 GMT
Content-Type: text/html
Content-Length: 45
Connection: keep-alive
Last-Modified: Sun, 04 May 2025 18:53:14 GMT
ETag: "2d-432a5e4a73a80"
Accept-Ranges: bytes
两个应用程序都返回 200 响应,表示它们运行正常。
总结:
在本篇博文中,我们探讨了如何使用 Ingress NGINX 控制器和 AWS 负载均衡器有效地管理和路由 Kubernetes 中的流量。
通过理解和实施这些技术,您可以确保您的 Kubernetes 环境井然有序,并且您的服务能够按需访问。无论您是管理内部工作流还是处理外部请求,这些工具和配置都能提供灵活性和控制力。