在 Azure Kubernetes 服务 (AKS) 中创建内部虚拟网络的入口控制器Create an ingress controller to an internal virtual network in Azure Kubernetes Service (AKS)

入口控制器是一个软件片段,为 Kubernetes 服务提供反向代理、可配置的流量路由和 TLS 终止。An ingress controller is a piece of software that provides reverse proxy, configurable traffic routing, and TLS termination for Kubernetes services. Kubernetes 入口资源用于配置各个 Kubernetes 服务的入口规则和路由。Kubernetes ingress resources are used to configure the ingress rules and routes for individual Kubernetes services. 借助入口控制器和入口规则,可以使用单个 IP 地址将流量路由到 Kubernetes 群集中的多个服务。Using an ingress controller and ingress rules, a single IP address can be used to route traffic to multiple services in a Kubernetes cluster.

本文介绍如何在 Azure Kubernetes 服务 (AKS) 群集中部署 NGINX 入口控制器This article shows you how to deploy the NGINX ingress controller in an Azure Kubernetes Service (AKS) cluster. 入口控制器在内部专用虚拟网络和 IP 地址上配置。The ingress controller is configured on an internal, private virtual network and IP address. 不允许外部访问。No external access is allowed. 然后在 AKS 群集中运行两个应用程序(可通过单个 IP 地址访问其中的每个应用程序)。Two applications are then run in the AKS cluster, each of which is accessible over the single IP address.

也可执行以下操作:You can also:

准备阶段Before you begin

本文使用 Helm 3 安装 NGINX 入口控制器和证书管理器。This article uses Helm 3 to install the NGINX ingress controller and cert-manager. 有关配置和使用 Helm 的详细信息,请参阅在 Azure Kubernetes 服务 (AKS) 中使用 Helm 安装应用程序For more information on configuring and using Helm, see Install applications with Helm in Azure Kubernetes Service (AKS).

本文还要求运行 Azure CLI 2.0.64 或更高版本。This article also requires that you are running the Azure CLI version 2.0.64 or later. 运行 az --version 即可查找版本。Run az --version to find the version. 如果需要进行安装或升级,请参阅安装 Azure CLIIf you need to install or upgrade, see Install Azure CLI.

创建入口控制器Create an ingress controller

默认情况下,NGINX 入口控制器通过动态公共 IP 地址分配创建。By default, an NGINX ingress controller is created with a dynamic public IP address assignment. 常见的配置要求是使用内部专用网络和 IP 地址。A common configuration requirement is to use an internal, private network and IP address. 此方法仅限内部用户访问你的服务,不允许外部访问。This approach allows you to restrict access to your services to internal users, with no external access.

根据以下示例清单文件创建名为 internal-ingress.yaml 的文件。Create a file named internal-ingress.yaml using the following example manifest file. 此示例将 10.240.0.42 分配给 loadBalancerIP 资源。This example assigns 10.240.0.42 to the loadBalancerIP resource. 提供自己的可以与入口控制器配合使用的内部 IP 地址。Provide your own internal IP address for use with the ingress controller. 请确保该 IP 地址尚未在虚拟网络中使用。Make sure that this IP address is not already in use within your virtual network. 此外,如果你使用的是现有虚拟网络和子网,则必须使用正确的权限配置 AKS 群集,以管理虚拟网络和子网。Also, if you are using an existing virtual network and subnet, you must configure your AKS cluster with the correct permissions to manage the virtual network and subnet. 有关详细信息,请参阅在 Azure Kubernetes 服务 (AKS) 中结合自己的 IP 地址范围使用 kubenet 网络在 Azure Kubernetes 服务 (AKS) 中配置 Azure CNI 网络See Use kubenet networking with your own IP address ranges in Azure Kubernetes Service (AKS) or Configure Azure CNI networking in Azure Kubernetes Service (AKS) for more information.

controller:
service:
    loadBalancerIP: 10.240.0.42
    annotations:
      service.beta.kubernetes.io/azure-load-balancer-internal: "true"

现在,通过 Helm 部署 nginx-ingress 图表。Now deploy the nginx-ingress chart with Helm. 若要使用在上一步创建的清单文件,请添加 -f internal-ingress.yaml 参数。To use the manifest file created in the previous step, add the -f internal-ingress.yaml parameter. 对于增加的冗余,NGINX 入口控制器的两个副本会在部署时具备 --set controller.replicaCount 参数。For added redundancy, two replicas of the NGINX ingress controllers are deployed with the --set controller.replicaCount parameter. 若要充分利用正在运行的入口控制器副本,请确保 AKS 群集中有多个节点。To fully benefit from running replicas of the ingress controller, make sure there's more than one node in your AKS cluster.

还需要在 Linux 节点上计划入口控制器。The ingress controller also needs to be scheduled on a Linux node. Windows Server 节点不应运行入口控制器。Windows Server nodes shouldn't run the ingress controller. 使用 --set nodeSelector 参数指定节点选择器,以告知 Kubernetes 计划程序在基于 Linux 的节点上运行 NGINX 入口控制器。A node selector is specified using the --set nodeSelector parameter to tell the Kubernetes scheduler to run the NGINX ingress controller on a Linux-based node.

提示

以下示例为名为 ingress-basic 的入口资源创建 Kubernetes 命名空间。The following example creates a Kubernetes namespace for the ingress resources named ingress-basic. 根据需要为你自己的环境指定一个命名空间。Specify a namespace for your own environment as needed. 如果 AKS 群集未启用 RBAC,请将 --set rbac.create=false 添加到 Helm 命令中。If your AKS cluster is not RBAC enabled, add --set rbac.create=false to the Helm commands.

提示

若要为对群集中容器的请求启用客户端源 IP 保留,请将 --set controller.service.externalTrafficPolicy=Local 添加到 Helm install 命令中。If you would like to enable client source IP preservation for requests to containers in your cluster, add --set controller.service.externalTrafficPolicy=Local to the Helm install command. 客户端源 IP 存储在 X-Forwarded-For 下的请求头中。The client source IP is stored in the request header under X-Forwarded-For. 使用启用了“客户端源 IP 保留”的入口控制器时,TLS 直通将不起作用。When using an ingress controller with client source IP preservation enabled, TLS pass-through will not work.

# Create a namespace for your ingress resources
kubectl create namespace ingress-basic

# Add the official stable repository
helm repo add stable https://kubernetes-charts.storage.googleapis.com/

# Use Helm to deploy an NGINX ingress controller
helm install nginx-ingress stable/nginx-ingress \
    --namespace ingress-basic \
    -f internal-ingress.yaml \
    --set controller.replicaCount=2 \
    --set controller.image.registry=usgcr.azk8s.cn \
    --set controller.nodeSelector."beta\.kubernetes\.io/os"=linux \
    --set defaultBackend.nodeSelector."beta\.kubernetes\.io/os"=linux \
    --set defaultBackend.image.repository=gcr.azk8s.cn/google_containers/defaultbackend-amd64

为 NGINX 入口控制器创建 Kubernetes 负载均衡器服务时,系统会分配内部 IP 地址。When the Kubernetes load balancer service is created for the NGINX ingress controller, your internal IP address is assigned. 若要获取公共 IP 地址,请使用 kubectl get service 命令。To get the public IP address, use the kubectl get service command.

kubectl get service -l app=nginx-ingress --namespace ingress-basic

将 IP 地址分配给服务需要几分钟时间,如以下示例输出中所示:It takes a few minutes for the IP address to be assigned to the service, as shown in the following example output:

$ kubectl get service -l app=nginx-ingress --namespace ingress-basic

NAME                             TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
nginx-ingress-controller         LoadBalancer   10.0.61.144    10.240.0.42   80:30386/TCP,443:32276/TCP   6m2s
nginx-ingress-default-backend    ClusterIP      10.0.192.145   <none>        80/TCP                       6m2s

由于尚未创建入口规则,如果浏览到该内部 IP 地址,则会显示 NGINX 入口控制器的默认 404 页面。No ingress rules have been created yet, so the NGINX ingress controller's default 404 page is displayed if you browse to the internal IP address. 入口规则是通过以下步骤配置的。Ingress rules are configured in the following steps.

运行演示应用程序Run demo applications

若要查看运行中的入口控制器,请在 AKS 群集中运行两个演示应用程序。To see the ingress controller in action, run two demo applications in your AKS cluster. 此示例使用 kubectl apply 来部署一个简单“Hello world”应用程序的两个实例。In this example, you use kubectl apply to deploy two instances of a simple Hello world application.

创建“aks-helloworld.yaml”文件,并将其复制到以下示例 YAML 中:Create a aks-helloworld.yaml file and copy in the following example YAML:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: aks-helloworld
spec:
  replicas: 1
  selector:
    matchLabels:
      app: aks-helloworld
  template:
    metadata:
      labels:
        app: aks-helloworld
    spec:
      containers:
      - name: aks-helloworld
        image: neilpeterson/aks-helloworld:v1
        ports:
        - containerPort: 80
        env:
        - name: TITLE
          value: "Welcome to Azure Kubernetes Service (AKS)"
---
apiVersion: v1
kind: Service
metadata:
  name: aks-helloworld
spec:
  type: ClusterIP
  ports:
  - port: 80
  selector:
    app: aks-helloworld

创建“ingress-demo.yaml”文件,并将其复制到以下示例 YAML 中:Create a ingress-demo.yaml file and copy in the following example YAML:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ingress-demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ingress-demo
  template:
    metadata:
      labels:
        app: ingress-demo
    spec:
      containers:
      - name: ingress-demo
        image: neilpeterson/aks-helloworld:v1
        ports:
        - containerPort: 80
        env:
        - name: TITLE
          value: "AKS Ingress Demo"
---
apiVersion: v1
kind: Service
metadata:
  name: ingress-demo
spec:
  type: ClusterIP
  ports:
  - port: 80
  selector:
    app: ingress-demo

使用 kubectl apply 运行这两个演示应用程序:Run the two demo applications using kubectl apply:

kubectl apply -f aks-helloworld.yaml --namespace ingress-basic
kubectl apply -f ingress-demo.yaml --namespace ingress-basic

创建入口路由Create an ingress route

两个应用程序现在都在 Kubernetes 群集中运行。Both applications are now running on your Kubernetes cluster. 若要将流量路由到每个应用程序,请创建 Kubernetes 入口资源。To route traffic to each application, create a Kubernetes ingress resource. 该入口资源配置将流量路由到这两个应用程序之一的规则。The ingress resource configures the rules that route traffic to one of the two applications.

在以下示例中,传往地址 http://10.240.0.42/ 的流量将路由到名为 aks-helloworld 的服务。In the following example, traffic to the address http://10.240.0.42/ is routed to the service named aks-helloworld. 传往地址 http://10.240.0.42/hello-world-two 的流量将路由到 ingress-demo 服务。Traffic to the address http://10.240.0.42/hello-world-two is routed to the ingress-demo service.

创建名为 hello-world-ingress.yaml 的文件,并将其复制到以下示例 YAML 中。Create a file named hello-world-ingress.yaml and copy in the following example YAML.

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: hello-world-ingress
  namespace: ingress-basic
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
  - http:
      paths:
      - backend:
          serviceName: aks-helloworld
          servicePort: 80
        path: /(.*)
      - backend:
          serviceName: ingress-demo
          servicePort: 80
        path: /hello-world-two(/|$)(.*)

使用 kubectl apply -f hello-world-ingress.yaml 命令创建入口资源。Create the ingress resource using the kubectl apply -f hello-world-ingress.yaml command.

kubectl apply -f hello-world-ingress.yaml

以下示例输出显示创建了入口资源。The following example output shows the ingress resource is created.

$ kubectl apply -f hello-world-ingress.yaml

ingress.extensions/hello-world-ingress created

测试入口控制器Test the ingress controller

若要测试入口控制器的路由,请通过一个 Web 客户端浏览到两个应用程序。To test the routes for the ingress controller, browse to the two applications with a web client. 可以根据需要通过 AKS 群集上的 Pod 快速测试这项仅限内部使用的功能。If needed, you can quickly test this internal-only functionality from a pod on the AKS cluster. 创建一个测试 Pod,并在其上附加一个终端会话:Create a test pod and attach a terminal session to it:

kubectl run -it --rm aks-ingress-test --image=debian --namespace ingress-basic

使用 apt-get 在 Pod 中安装 curlInstall curl in the pod using apt-get:

apt-get update && apt-get install -y curl

现在,请使用 curl 访问 Kubernetes 入口控制器的地址,例如 http://10.240.0.42Now access the address of your Kubernetes ingress controller using curl, such as http://10.240.0.42. 提供自己的内部 IP 地址,该地址是在本文第一步中部署入口控制器时指定的。Provide your own internal IP address specified when you deployed the ingress controller in the first step of this article.

curl -L http://10.240.0.42

未为此地址提供其他路径,因此入口控制器默认为 / 路由。No additional path was provided with the address, so the ingress controller defaults to the / route. 第一个演示应用程序已返回,如以下精简版示例输出中所示:The first demo application is returned, as shown in the following condensed example output:

$ curl -L http://10.240.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.240.0.42/hello-world-twoNow add /hello-world-two path to the address, such as http://10.240.0.42/hello-world-two. 第二个使用自定义标题的演示应用程序已返回,如以下精简版示例输出中所示:The second demo application with the custom title is returned, as shown in the following condensed example output:

$ curl -L -k http://10.240.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>
[...]

清理资源Clean up resources

本文使用了 Helm 来安装入口组件。This article used Helm to install the ingress components. 在部署 Helm 图表时,会创建若干 Kubernetes 资源。When you deploy a Helm chart, a number of Kubernetes resources are created. 这些资源包括 pod、部署和服务。These resources includes pods, deployments, and services. 若要清理这些资源,可以删除整个示例命名空间,也可以删除单个资源。To clean up these resources, you can either delete the entire sample namespace, or the individual resources.

删除示例命名空间以及所有资源Delete the sample namespace and all resources

若要删除整个示例命名空间,请使用 kubectl delete 命令并指定命名空间名称。To delete the entire sample namespace, use the kubectl delete command and specify your namespace name. 将会删除命名空间中的所有资源。All the resources in the namespace are deleted.

kubectl delete namespace ingress-basic

单独删除资源Delete resources individually

也可采用更细致的方法来删除单个已创建的资源。Alternatively, a more granular approach is to delete the individual resources created. 使用 helm list 命令列出 Helm 版本。List the Helm releases with the helm list command.

helm list --namespace ingress-basic

查找名为“nginx-ingress”和“aks-helloworld”的图表,如以下示例输出中所示:Look for charts named nginx-ingress and aks-helloworld, as shown in the following example output:

$ helm list --namespace ingress-basic

NAME                    NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
nginx-ingress           ingress-basic   1               2020-01-06 19:55:46.358275 -0600 CST    deployed        nginx-ingress-1.27.1    0.26.1  

使用 helm uninstall 命令卸载这些版本。Uninstall the releases with the helm uninstall command.

helm uninstall nginx-ingress --namespace ingress-basic

下面的示例将卸载 NGINX 入口部署。The following example uninstalls the NGINX ingress deployment.

$ helm uninstall nginx-ingress --namespace ingress-basic

release "nginx-ingress" uninstalled

接下来,删除两个示例应用程序:Next, remove the two sample applications:

kubectl delete -f aks-helloworld.yaml --namespace ingress-basic
kubectl delete -f ingress-demo.yaml --namespace ingress-basic

删除将流量定向到示例应用的入口路由:Remove the ingress route that directed traffic to the sample apps:

kubectl delete -f hello-world-ingress.yaml

最后,可以删除自身命名空间。Finally, you can delete the itself namespace. 使用 kubectl delete 命令并指定命名空间名称。Use the kubectl delete command and specify your namespace name:

kubectl delete namespace ingress-basic

后续步骤Next steps

本文包含 AKS 的一些外部组件。This article included some external components to AKS. 若要详细了解这些组件,请参阅以下项目页面:To learn more about these components, see the following project pages:

也可执行以下操作:You can also: