创建非管理的入口控制器
入口控制器是一个软件片段,为 Kubernetes 服务提供反向代理、可配置的流量路由和 TLS 终止。 Kubernetes 入口资源用于配置各个 Kubernetes 服务的入口规则和路由。 使用入口控制器和入口规则时,可以使用单个 IP 地址将流量路由到 Kubernetes 群集中的多个服务。
本文介绍如何在 Azure Kubernetes 服务 (AKS) 群集中部署 NGINX 入口控制器。 然后在 AKS 群集中运行两个应用程序(可通过单个 IP 地址访问其中的每个应用程序)。
重要
建议将应用程序路由加载项用于 AKS 中的入口。 有关详细信息,请参阅具有应用程序路由加载项的托管 nginx Ingress。
注意
Kubernetes 有两个基于 Nginx 的开源入口控制器:一个控制器由 Kubernetes 社区 (kubernetes/ingress-nginx) 维护,另一个由 NGINX, Inc. (nginxinc/kubernetes-ingress) 维护。 本文将使用 Kubernetes 社区入口控制器。
准备阶段
- 本文使用 Helm 3 在受支持的 Kubernetes 版本上安装 NGINX 入口控制器。 确保使用最新版本的 Helm,并且有权访问 ingress-nginx Helm 存储库。 本文中概述的步骤可能与 Helm chart、NGINX 入口控制器或 Kubernetes 的先前版本不兼容。
- 本文假设你有一个包含集成 Azure 容器注册表 (ACR) 的现有 AKS 群集。 有关创建一个包含集成 ACR 的 AKS 群集的详细信息,请参阅使用 Azure 容器注册表从 Azure Kubernetes 服务进行身份验证。
- Kubernetes API 运行状况终结点
healthz
在 Kubernetes v1.16 中已弃用。 可以改用livez
和readyz
终结点替换此终结点。 请参阅 Kubernetes API 运行状况终结点,确定要用于你的方案的终结点。 - 如果使用的是 Azure CLI,本文要求运行 Azure CLI 2.0.64 或更高版本。 运行
az --version
即可查找版本。 如果需要安装或升级,请参阅 [安装 Azure CLI][azure-cli-install]。 - 如果使用的是 Azure PowerShell,本文要求运行 Azure PowerShell 5.9.0 或更高版本。 运行
Get-InstalledModule -Name Az
即可查找版本。 如果需要进行安装或升级,请参阅安装 Azure PowerShell。
基本配置
若要在不自定义默认值的情况下创建基本的 NGINX 入口控制器,需要使用 Helm。 为简单起见,下面使用了默认配置。 可以添加用于自定义部署的参数,例如 --set controller.replicaCount=3
。
注意
若要为对群集中容器的请求启用客户端源 IP 保留,请将 --set controller.service.externalTrafficPolicy=Local
添加到 Helm install 命令中。 客户端源 IP 存储在 X-Forwarded-For 下的请求头中。 使用启用了客户端源 IP 保留的入口控制器时,TLS 直通将不起作用。
NAMESPACE=ingress-basic
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install ingress-nginx ingress-nginx/ingress-nginx \
--create-namespace \
--namespace $NAMESPACE \
--set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \
--set controller.service.externalTrafficPolicy=Local
注意
在本教程中,service.beta.kubernetes.io/azure-load-balancer-health-probe-request-path
设置为 /healthz
。 这意味着,如果对 /healthz
的请求的响应代码不是 200
,则整个入口控制器将关闭。 可在自己的方案中将值修改为其他 URI。 不能删除此部分或取消设置值,否则入口控制器仍将关闭。
本教程使用的包 ingress-nginx
由 Kubernetes 官方提供,如果请求 200
,它将始终返回 /healthz
响应代码,因为它被设计为默认后端以供用户快速启动,除非它被入口规则覆盖。
自定义配置
作为上述部分介绍的基本配置的替代方法,下一组步骤将展示如何部署自定义入口控制器。 可以选择使用内部静态 IP 地址,或使用动态公共 IP 地址。
将 Helm 图表使用的映像导入 ACR
若要控制映像版本,需要将它们导入你自己的 Azure 容器注册表。 NGINX 入口控制器 Helm 图表依赖于三个容器映像。 使用 az acr import
将这些映像导入 ACR。
REGISTRY_NAME=<REGISTRY_NAME>
SOURCE_REGISTRY=registry.k8s.io
CONTROLLER_IMAGE=ingress-nginx/controller
CONTROLLER_TAG=v1.8.1
PATCH_IMAGE=ingress-nginx/kube-webhook-certgen
PATCH_TAG=v20230407
DEFAULTBACKEND_IMAGE=defaultbackend-amd64
DEFAULTBACKEND_TAG=1.5
az acr import --name $REGISTRY_NAME --source $SOURCE_REGISTRY/$CONTROLLER_IMAGE:$CONTROLLER_TAG --image $CONTROLLER_IMAGE:$CONTROLLER_TAG
az acr import --name $REGISTRY_NAME --source $SOURCE_REGISTRY/$PATCH_IMAGE:$PATCH_TAG --image $PATCH_IMAGE:$PATCH_TAG
az acr import --name $REGISTRY_NAME --source $SOURCE_REGISTRY/$DEFAULTBACKEND_IMAGE:$DEFAULTBACKEND_TAG --image $DEFAULTBACKEND_IMAGE:$DEFAULTBACKEND_TAG
注意
除了将容器映像导入 ACR 之外,还可以将 Helm 图表导入 ACR。 有关详细信息,请参阅将 Helm 图表推送和拉取到 Azure 容器注册表。
创建入口控制器
若要创建入口控制器,请使用 Helm 来安装 ingress-nginx。 需要在 Linux 节点上计划入口控制器。 Windows Server 节点不应运行入口控制器。 使用 --set nodeSelector
参数指定节点选择器,以告知 Kubernetes 计划程序在基于 Linux 的节点上运行 NGINX 入口控制器。
对于增加的冗余,NGINX 入口控制器的两个副本会在部署时具备 --set controller.replicaCount
参数。 若要充分利用正在运行的入口控制器副本,请确保 AKS 群集中有多个节点。
以下示例为名为 ingress-basic 的入口资源创建 Kubernetes 命名空间,目的是在该命名空间内执行操作。 根据需要为你自己的环境指定一个命名空间。 如果未为 AKS 群集启用 Kubernetes 基于角色的访问控制,请将 --set rbac.create=false
添加到 Helm 命令。
注意
若要为对群集中容器的请求启用客户端源 IP 保留,请将 --set controller.service.externalTrafficPolicy=Local
添加到 Helm install 命令中。 客户端源 IP 存储在 X-Forwarded-For 下的请求头中。 使用启用了客户端源 IP 保留的入口控制器时,TLS 直通将不起作用。
# Add the ingress-nginx repository
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
# Set variable for ACR location to use for pulling images
ACR_LOGIN_SERVER=<REGISTRY_LOGIN_SERVER>
# Use Helm to deploy an NGINX ingress controller
helm install ingress-nginx ingress-nginx/ingress-nginx \
--version 4.7.1 \
--namespace ingress-basic \
--create-namespace \
--set controller.replicaCount=2 \
--set controller.nodeSelector."kubernetes\.io/os"=linux \
--set controller.image.registry=$ACR_LOGIN_SERVER \
--set controller.image.image=$CONTROLLER_IMAGE \
--set controller.image.tag=$CONTROLLER_TAG \
--set controller.image.digest="" \
--set controller.admissionWebhooks.patch.nodeSelector."kubernetes\.io/os"=linux \
--set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \
--set controller.service.externalTrafficPolicy=Local \
--set controller.admissionWebhooks.patch.image.registry=$ACR_LOGIN_SERVER \
--set controller.admissionWebhooks.patch.image.image=$PATCH_IMAGE \
--set controller.admissionWebhooks.patch.image.tag=$PATCH_TAG \
--set controller.admissionWebhooks.patch.image.digest="" \
--set defaultBackend.nodeSelector."kubernetes\.io/os"=linux \
--set defaultBackend.image.registry=$ACR_LOGIN_SERVER \
--set defaultBackend.image.image=$DEFAULTBACKEND_IMAGE \
--set defaultBackend.image.tag=$DEFAULTBACKEND_TAG \
--set defaultBackend.image.digest=""
使用内部 IP 地址创建入口控制器
默认情况下,NGINX 入口控制器通过动态公共 IP 地址分配创建。 常见的配置要求是使用内部专用网络和 IP 地址。 此方法仅限内部用户访问你的服务,不允许外部访问。
使用 --set controller.service.loadBalancerIP
和 --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-internal"=true
参数为入口控制器分配内部 IP 地址。 提供自己的可以与入口控制器配合使用的内部 IP 地址。 请确保该 IP 地址尚未在虚拟网络中使用。 如果你使用的是现有虚拟网络和子网,则必须使用正确的权限配置 AKS 群集,以管理虚拟网络和子网。 有关详细信息,请参阅在 Azure Kubernetes 服务 (AKS) 中结合自己的 IP 地址范围使用 kubenet 网络或在 Azure Kubernetes 服务 (AKS) 中配置 Azure CNI 网络。
# Add the ingress-nginx repository
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
# Set variable for ACR location to use for pulling images
ACR_LOGIN_SERVER=<REGISTRY_LOGIN_SERVER>
# Use Helm to deploy an NGINX ingress controller
helm install ingress-nginx ingress-nginx/ingress-nginx \
--version 4.7.1 \
--namespace ingress-basic \
--create-namespace \
--set controller.replicaCount=2 \
--set controller.nodeSelector."kubernetes\.io/os"=linux \
--set controller.image.registry=$ACR_LOGIN_SERVER \
--set controller.image.image=$CONTROLLER_IMAGE \
--set controller.image.tag=$CONTROLLER_TAG \
--set controller.image.digest="" \
--set controller.admissionWebhooks.patch.nodeSelector."kubernetes\.io/os"=linux \
--set controller.service.loadBalancerIP=10.224.0.42 \
--set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-internal"=true \
--set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \
--set controller.admissionWebhooks.patch.image.registry=$ACR_LOGIN_SERVER \
--set controller.admissionWebhooks.patch.image.image=$PATCH_IMAGE \
--set controller.admissionWebhooks.patch.image.tag=$PATCH_TAG \
--set controller.admissionWebhooks.patch.image.digest="" \
--set defaultBackend.nodeSelector."kubernetes\.io/os"=linux \
--set defaultBackend.image.registry=$ACR_LOGIN_SERVER \
--set defaultBackend.image.image=$DEFAULTBACKEND_IMAGE \
--set defaultBackend.image.tag=$DEFAULTBACKEND_TAG \
--set defaultBackend.image.digest=""
检查负载均衡器服务
使用 kubectl get services
检查负载均衡器服务。
kubectl get services --namespace ingress-basic -o wide -w ingress-nginx-controller
为 NGINX 入口控制器创建 Kubernetes 负载均衡器服务时,将在 EXTERNAL-IP 下分配一个内部 IP 地址,如以下示例输出中所示:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
ingress-nginx-controller LoadBalancer 10.0.65.205 EXTERNAL-IP 80:30957/TCP,443:32414/TCP 1m app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx
如果在此阶段浏览到外部 IP 地址,则会看到显示 404 页面。 这是因为仍需设置与外部 IP 的连接,此操作将在后面的部分完成。
运行演示应用程序
若要查看运行中的入口控制器,请在 AKS 群集中运行两个演示应用程序。 此示例使用 kubectl apply
来部署一个简单“Hello world”应用程序的两个实例。
创建
aks-helloworld-one.yaml
文件并在其中复制以下示例 YAML:apiVersion: apps/v1 kind: Deployment metadata: name: aks-helloworld-one spec: replicas: 1 selector: matchLabels: app: aks-helloworld-one template: metadata: labels: app: aks-helloworld-one spec: containers: - name: aks-helloworld-one image: mcr.microsoft.com/azuredocs/aks-helloworld:v1 ports: - containerPort: 80 env: - name: TITLE value: "Welcome to Azure Kubernetes Service (AKS)" --- apiVersion: v1 kind: Service metadata: name: aks-helloworld-one spec: type: ClusterIP ports: - port: 80 selector: app: aks-helloworld-one
创建
aks-helloworld-two.yaml
文件并在其中复制以下示例 YAML:apiVersion: apps/v1 kind: Deployment metadata: name: aks-helloworld-two spec: replicas: 1 selector: matchLabels: app: aks-helloworld-two template: metadata: labels: app: aks-helloworld-two spec: containers: - name: aks-helloworld-two image: mcr.microsoft.com/azuredocs/aks-helloworld:v1 ports: - containerPort: 80 env: - name: TITLE value: "AKS Ingress Demo" --- apiVersion: v1 kind: Service metadata: name: aks-helloworld-two spec: type: ClusterIP ports: - port: 80 selector: app: aks-helloworld-two
使用
kubectl apply
运行这两个演示应用程序:kubectl apply -f aks-helloworld-one.yaml --namespace ingress-basic kubectl apply -f aks-helloworld-two.yaml --namespace ingress-basic
创建入口路由
两个应用程序现在都在 Kubernetes 群集中运行。 若要将流量路由到每个应用程序,请创建 Kubernetes 入口资源。 该入口资源配置将流量路由到这两个应用程序之一的规则。
在以下示例中,发往 EXTERNAL_IP/hello-world-one 的流量将路由到名为 aks-helloworld-one
的服务。 发往 EXTERNAL_IP/hello-world-two 的流量将路由到 aks-helloworld-two
服务。 发往 EXTERNAL_IP/static 的流量将路由到静态资产的名为 aks-helloworld-one
的服务。
创建名为
hello-world-ingress.yaml
的文件,并将其复制到以下示例 YAML 中:apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: hello-world-ingress annotations: nginx.ingress.kubernetes.io/ssl-redirect: "false" nginx.ingress.kubernetes.io/use-regex: "true" nginx.ingress.kubernetes.io/rewrite-target: /$2 spec: ingressClassName: nginx rules: - http: paths: - path: /hello-world-one(/|$)(.*) pathType: Prefix backend: service: name: aks-helloworld-one port: number: 80 - path: /hello-world-two(/|$)(.*) pathType: Prefix backend: service: name: aks-helloworld-two port: number: 80 - path: /(.*) pathType: Prefix backend: service: name: aks-helloworld-one port: number: 80 --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: hello-world-ingress-static annotations: nginx.ingress.kubernetes.io/ssl-redirect: "false" nginx.ingress.kubernetes.io/rewrite-target: /static/$2 spec: ingressClassName: nginx rules: - http: paths: - path: /static(/|$)(.*) pathType: Prefix backend: service: name: aks-helloworld-one port: number: 80
使用
kubectl apply
命令创建入口资源。kubectl apply -f hello-world-ingress.yaml --namespace ingress-basic
测试入口控制器
若要测试入口控制器的路由,请浏览到这两个应用程序。 打开 Web 浏览器,访问 NGINX 入口控制器的 IP 地址,例如 EXTERNAL_IP。 第一个演示应用程序显示在 Web 浏览器中,如以下示例所示:
现在将“/hello-world-two”路径添加到 IP 地址,例如“EXTERNAL_IP/hello-world-two”。 下面显示了带自定义标题的第二个演示应用程序:
测试内部 IP 地址
创建一个测试 Pod,并在其上附加一个终端会话。
kubectl run -it --rm aks-ingress-test --image=mcr.microsoft.com/dotnet/runtime-deps:6.0 --namespace ingress-basic
使用
apt-get
在 Pod 中安装curl
。apt-get update && apt-get install -y curl
使用
curl
访问 Kubernetes 入口控制器的地址,例如 http://10.224.0.42。 提供你自己的、在部署入口控制器时指定的内部 IP 地址。curl -L http://10.224.0.42
未为此地址提供路径,因此入口控制器默认为 / 路由。 第一个演示应用程序已返回,如以下精简版示例输出中所示:
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <link rel="stylesheet" type="text/css" href="/static/default.css"> <title>Welcome to Azure Kubernetes Service (AKS)</title> [...]
向地址添加 /hello-world-two 路径,例如 http://10.224.0.42/hello-world-two。
curl -L -k http://10.224.0.42/hello-world-two
第二个使用自定义标题的演示应用程序已返回,如以下精简版示例输出中所示:
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <link rel="stylesheet" type="text/css" href="/static/default.css"> <title>AKS Ingress Demo</title> [...]
清理资源
本文使用了 Helm 来安装入口组件和示例应用。 在部署 Helm 图表时,会创建若干 Kubernetes 资源。 这些资源包括 pod、部署和服务。 若要清理这些资源,可以删除整个示例命名空间,也可以删除单个资源。
删除示例命名空间以及所有资源
若要删除整个示例命名空间,请使用 kubectl delete
命令并指定命名空间名称。 将会删除命名空间中的所有资源。
kubectl delete namespace ingress-basic
单独删除资源
也可采用更细致的方法来删除单个已创建的资源。
使用
helm list
命令列出 Helm 版本。helm list --namespace ingress-basic
查找名为 ingress-nginx 和 aks-helloworld 的图表,如以下示例输出中所示:
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION ingress-nginx ingress-basic 1 2020-01-06 19:55:46.358275 -0600 CST deployed nginx-ingress-1.27.1 0.26.1
使用
helm uninstall
命令卸载这些版本。helm uninstall ingress-nginx --namespace ingress-basic
删除两个示例应用程序。
kubectl delete -f aks-helloworld-one.yaml --namespace ingress-basic kubectl delete -f aks-helloworld-two.yaml --namespace ingress-basic
删除将流量定向到示例应用的入口路由。
kubectl delete -f hello-world-ingress.yaml
使用
kubectl delete
命令并指定命名空间名称来删除命名空间。kubectl delete namespace ingress-basic
后续步骤
若要为现有入口组件配置 TLS,请参阅将 TLS 用于入口控制器。
若要将 AKS 群集配置为使用 HTTP 应用程序路由,请参阅启用 HTTP 应用程序路由加载项。
本文包含 AKS 的一些外部组件。 若要详细了解这些组件,请参阅以下项目页面:
联系我们寻求帮助
如果你有任何疑问或需要帮助,请创建支持请求或联系 Azure 社区支持。 你还可以将产品反馈提交到 Azure 反馈社区。