如果您正在生产环境中使用 Kubernetes,那么很可能在使用 Ingress controller(Ingress 控制器)。Ingress controller 是管理 Kubernetes 集群进出流量的核心引擎。鉴于 Ingress controller 是部署在集群内运行的,应如何将流量路由到它呢?又应如何将外部流量路由到内部 Kubernetes Service 呢?
云提供商提供了一种简便的方法,使用外部负载均衡器暴露 Kubernetes Service。只需部署一个托管 Kubernetes Service(EKS、GKE、AKS)并创建一个 LoadBalancer 类型的 Kubernetes Service 即可。云提供商将托管并部署一个提供公共 IP 地址的负载均衡器后,外部用户可通过此公共入口点连接到 Kubernetes Service。
不过,该集成仅适用于云提供商托管的 Kubernetes Service。如果您在私有云/本地环境中部署 Kubernetes,则需部署自己的负载均衡器,并将其与 Kubernetes 集群相集成。此外,云端 Kubernetes 负载均衡集成仅限于 TCP 负载均衡,通常缺乏对指标、日志和链路追踪的可视化。
我们建议:
- 采用与工作负载底层运行基础设施无关的解决方案
- 容量规划指南,来避免高流量带来的瓶颈问题
- 实现不仅限于基本 TCP/HTTP 负载均衡的应用交付用例
在下述解决方案中,我将 NGINX Plus 部署为 Kubernetes 的外部负载均衡服务,并将流量路由到 NGINX Ingress Controller。然后,NGINX Ingress Controller 会将流量路由到应用后端。NLK (NGINX Load Balancer for Kubernetes) 部署是一种新型 NGINX 控制器,可监控指定的 Kubernetes Service,并发送 API 调用以管理 NGINX 外部负载均衡器的上游端点。
在本文中,我将在 Kubernetes 集群和作为外部负载均衡器的 NGINX Plus 中部署组件。
注:我个人喜欢将 NLK 和 Kubernetes 集群部署在同一子网中,以避免出现网络问题。但这并非一项硬性要求
准备工作
本文假设您拥有 Kubernetes 环境操作经验。此外,您还需要:
- Kubernetes 环境的访问权限;裸机、Rancher Kubernetes Engine (RKE)、VMWare Tanzu Kubernetes (VTK)、Amazon Elastic Kubernetes (EKS)、Google Kubernetes Engine (GKE)、Microsoft Azure Kubernetes Service (AKS) 及 RedHat OpenShift
- NGINX Ingress Controller —— 在 Kubernetes 集群中部署 NGINX Ingress Controller。有关安装说明,请查阅文档。
- NGINX Plus —— 将 NGINX Plus 部署至具有 SSH 访问权限的虚拟机或裸机。这将是 Kubernetes 集群的外部负载均衡服务。安装说明可在文档中找到。您必须拥有 NGINX Plus 的有效许可,并可立即申请 30 天免费试用版。
设置 Kubernetes 环境
首先部署后端应用。您可以部署自己的应用,也可以部署基本 café 应用,如本例所示。
$ kubectl apply –f cafe.yaml
现在,为 Ingress controller 配置路由和 TLS 设置
$ kubectl apply –f cafe-secret.yaml
$ kubectl apply –f cafe-virtualserver.yaml
为了确保成功应用 Ingress 规则,请检查 kubectl get vs 的输出。
VirtualServer 定义应处于 Valid 状态。
NAMESPACE NAME STATE HOST IP PORTS
default cafe-vs Valid cafe.example.com
将 NGINX Plus 设置为外部负载均衡器
全新安装的 NGINX Plus 将在 /etc/nginx/conf.d 目录中提供 default.conf 文件。我们还需要将另外两个文件添加到此目录下。只需将下列文件复制到 /etc/nginx/conf.d 目录中即可
- dashboard.conf;它将启用 NGINX Plus 的实时监控仪表盘
- kube_lb.conf;该 nginx 配置充当 Kubernetes 的外部负载均衡器。您可以根据自己的需求更改配置文件。在本文中,我们为一个集群启用了基本路由和 TLS。
您还需要生成 TLS 证书/密钥,并将其放在 NGINX Plus 实例的 /etc/ssl/nginx 文件夹中。在本例中,我们将使用 openssl 生成自签名证书。
$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout default.key -out default.crt -subj "/CN=NLK"
注:自签名证书仅供测试使用。在实际生产环境中,建议使用安全的 Vault 来保存密钥和受信任 CA(证书颁发机构)。
现在可以验证配置,然后重新加载 nginx 以使变更生效。
$ nginx –t
$ nginx –s reload
现在,我可以连接到 NGINX Plus 仪表盘,具体方法是打开浏览器并输入
http://<external-ip-nginx>:9000/dashboard.html#upstreams
HTTP upstream表应为空,因为我们尚未部署 NLK 控制器。
在下一节中,我们将进行 NLK 控制器的部署。
安装 NLK 控制器
您可将 NLK Controller 安装为 Kubernetes 部署,后者将使用 NGINX Plus API 为外部负载均衡器配置 Upstream 端点。首先,创建 NLK 命名空间
$ kubectl create ns nlk
将 RBAC 设置应用于 NKL 部署
$ kubectl apply -f serviceaccount.yaml
$ kubectl apply -f clusterrole.yaml
$ kubectl apply -f clusterrolebinding.yaml
$ kubectl apply -f secret.yaml
下一步,创建一个 ConfigMap,定义 NGINX Plus 外部负载均衡器的 API 端点。NLK 控制器使用 API 端点来配置 NGINX Plus 上游端点。我们只需将 GitHub 仓库清单中的 nginx-hosts 字段修改为 NGINX 外部负载均衡器的 IP 地址即可。
nginx-hosts:
http://<nginx-plus-external-ip>:9000/api
应用更新的 ConfigMap,并部署 NLK 控制器
$ kubectl apply –f nkl-configmap.yaml
$ kubectl apply –f nkl-deployment
现在可以验证 NLK 控制器部署是否正在运行,以及是否应用了 ConfigMap 数据。
$ kubectl get pods –o wide –n nlk
$ kubectl describe cm nginx-config –n nlk
NLK 部署的状态应为 Running(运行中),nginx-hosts 下应该定义了 URL。URL 是外部负载均衡器的 NGINX Plus API 端点。现在,NKL 控制器已部署成功,外部负载均衡器可随时将流量路由到集群。
最后一步是部署 Kubernetes Service 类型 NodePort,以便将 Kubernetes 集群暴露给 NGINX Plus。
$ kubectl apply –f nodeport.yaml
关于 NodePort Service 清单,以下几点需要注意。对于 NLK 部署,必须填写第 7 行和第 14 行的字段才能正确配置外部负载均衡器:
- nginxinc.io/nklcluster 注解
- 与 NGINX Plus 配置中 upstream 代码块定义相匹配的端口名称(参见 kube_lb.conf 中的第 42 行),以及前面的 nkl-
apiVersion: v1
kind: Service
metadata:
name: nginx-ingress
namespace: nginx-ingress
annotations:
nginxinc.io/nlk-cluster1-https: "http" # 必须添加
spec:
type: NodePort
ports:
- port: 443
targetPort: 443
protocol: TCP
name: nlk-cluster1-https
selector:
app: nginx-ingress
应用服务后,您需要记下分配的节点端口,选择 NGINX Ingress Controller 部署。在本例中,节点端口为 32222。
$ kubectl get svc –o wide –n nginx-ingress
NAME TYPE CLUSTER-IP PORT(S) SELECTOR
nginx-ingress NodePort x.x.x.x 443:32222/TCP app=nginx-ingress
如果重新连接到 NGINX Pus 仪表盘,则 upstream 选项卡中应填充 Kubernetes 集群的 worker 节点 IP,并与 nginx-ingress Service (32222) 的节点端口相匹配。
您可以列出集群的节点 IP,确保它们与仪表盘 upstream 选项卡中的 IP 匹配。
$ kubectl get nodes -o wide | awk '{print $6}'
INTERNAL-IP
10.224.0.6
10.224.0.5
10.224.0.4
现在可以从本地计算机连接到 Kubernetes 应用了。我们示例中所用的主机名 (cafe.example.com) 应解析为 NGINX Plus 负载均衡器的 IP 地址。
结语
大多数在生产环境中部署 Kubernetes 的企业都会安装一个 Ingress controller。在 Kubernetes 等容器编排器中,它是公认的应用交付标准。现在,DevOps/NetOps 工程师正在寻求相关指导,以了解如何尽可能高效地扩展其 Kubernetes 部署。由于企业正在采用混合方法,因此需要在云提供商外部实现自己的集成。
我们提出的解决方案:
- 适用于混合环境(尤其是本地环境)
- 容量规划信息可避免大规模流量带来的瓶颈问题
- 具有不仅限于 TCP 负载均衡服务的企业负载均衡功能
在本系列文章的下一篇,我将更详细地介绍第三点,并探讨 NGINX Plus 的零信任用例,帮助您增强混合模式的安全防护。