本文介绍如何在阿里云容器服务Kubernetes集群中同时部署多套独立的Nginx Ingress Controller对外提供不同的服务访问。

前提条件

背景信息

如何配置阿里云容器服务Kubernetes Ingress Controller使用私网SLB中描述了如何调整阿里云容器服务Kubernetes集群中默认的Nginx Ingress Controller配置使用私网SLB实例,文中提到的两种模式可以满足大部分需求场景。但对于一些特殊场景,例如:集群内有部分公网服务需要通过公网Ingress方式来对外暴露提供访问,但是又有部分内网服务仅仅只希望对同VPC内非Kubernetes集群内的服务提供访问,而又不允许能被公网访问到,我们可以通过部署两套独立的Nginx Ingress Controller服务,其前端绑定不同网络类型的SLB实例来满足这类需求场景。1

现有服务说明

您成功创建一个Kubernetes集群后,默认集群内已经部署了一套带有公网SLB实例的Nginx Ingress Controller服务。通过以下命令查看集群默认Nginx Ingress Controller服务相关资源。
  ~ # 查询集群默认 Nginx Ingress Controller 服务相关资源
  ~ kubectl -n kube-system get svc nginx-ingress-lb default-http-backend
NAME                   TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)                      AGE
nginx-ingress-lb       LoadBalancer   172.19.7.30     47.95.97.115   80:31429/TCP,443:32553/TCP   2d
default-http-backend   ClusterIP      172.19.11.213   <none>         80/TCP                       2d
  ~
  ~ kubectl -n kube-system get deploy nginx-ingress-controller default-http-backend
NAME                       DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-ingress-controller   2         2         2            2           2d
default-http-backend       1         1         1            1           2d
  ~
  ~ kubectl -n kube-system get configmap nginx-configuration tcp-services udp-services
NAME                  DATA      AGE
nginx-configuration   4         2d
tcp-services          0         2d
udp-services          0         2d

从上可以看到集群默认部署的Nginx Ingress Controller服务及相关资源部署在kube-system命名空间下,并且其默认会监听集群内所有命名空间下创建的且未明确配置注释kubernetes.io/ingress.class的Ingress配置。

新部署Nginx Ingress Controller服务

这里我们说明如何在现有的阿里云容器服务Kubernetes集群中再部署一套完全独立的Nginx Ingress Controller服务,其前端绑定一个新的SLB实例(可依据实际需求配置私网SLB实例或公网SLB实例)。

  1. 在对应的集群区域创建一个SLB实例,请参见创建负载均衡实例
  2. 准备Nginx Ingress Controller服务的YAML文件:
    wget https://acs-k8s-ingress.oss-cn-hangzhou.aliyuncs.com/ingress-controller-template.yml.j2
    生成上述YAML文件需要用到jinja2命令行,通过以下命令生成需要新部署的Nginx Ingress Controller服务的YAML文件,请参见官方文档
    jinja2 -D Namespace='NAMESPACE' -D LoadbalancerID='SLB_ID' -D IngressClass='INGRESS_CLASS' ingress-controller-template.yml.j2 > ingress-controller.yml
    
    参数说明:
    NAMESPACE:期望部署到哪个命令空间下(确保该命名空间已存在且不能再使用kube-system)
    SLB_ID:新申请的SLB实例ID
    INGRESS_CLASS:Ingress标识(不能使用nginx这个字符串,已预留给集群默认IngressController服务)
  3. 在YAML文件生成后,通过以下命令部署新的Nginx Ingress Controller服务。
      # 部署新 Nginx Ingress Controller 服务
      kubectl apply -f ingress-controller.yml
    serviceaccount "admin" created
    clusterrolebinding.rbac.authorization.k8s.io "admin" created
    service "nginx-ingress-lb" created
    configmap "nginx-configuration" created
    configmap "tcp-services" created
    configmap "udp-services" created
    deployment.extensions "default-http-backend" created
    service "default-http-backend" created
    deployment.apps "nginx-ingress-controller" created
    
      # 确认新 Nginx Ingress Controller 服务正常运行起来
      kubectl -n <YOUR_NAMESPACE> get svc nginx-ingress-lb
    NAME               TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)                      AGE
    nginx-ingress-lb   LoadBalancer   172.19.6.227   39.105.252.62   80:30969/TCP,443:31325/TCP   4m
    
      kubectl -n <YOUR_NAMESPACE> get pod | grep nginx-ingress-controller
    nginx-ingress-controller-78bc478f5b-blpgz   1/1       Running   0          2m
    nginx-ingress-controller-78bc478f5b-k5jh7   1/1       Running   0          2m
  4. 配置SLB实例的端口监听。
    默认情况下系统会自动配置SLB实例的端口监听,请确认您的SLB实例端口监听已正常配置。若无配置说明集群Cloud Controller Manager服务版本过低,升级版本,请参见CloudProvider Release Notes。您还可以进行手动配置,需要的具体端口映射关系可通过以下命令查看到PORT(S)。
      kubectl -n <YOUR_NAMESPACE> get svc nginx-ingress-lb
    NAME               TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)                      AGE
    nginx-ingress-lb   LoadBalancer   172.19.6.227   39.105.252.62   80:30969/TCP,443:31325/TCP   4m

    在您指定的命名空间下,一套新的Nginx Ingress Controller服务已经成功完成部署。

访问测试

本文部署一个测试应用,并配置通过新部署的Nginx Ingress Controller来对外暴露提供服务访问。

  1. 部署一个Nginx测试应用。
    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      replicas: 1
      selector:
        matchLabels:
          run: nginx
      template:
        metadata:
          labels:
            run: nginx
        spec:
          containers:
          - image: nginx
            imagePullPolicy: Always
            name: nginx
            ports:
            - containerPort: 80
              protocol: TCP
          restartPolicy: Always
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx
    spec:
      ports:
      - port: 80
        protocol: TCP
        targetPort: 80
      selector:
        run: nginx
      sessionAffinity: None
      type: NodePort
  2. 通过Ingress来对外暴露提供服务访问。
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      name: nginx
      annotations:
        # 注意这里要设置为您前面配置的 INGRESS_CLASS
        kubernetes.io/ingress.class: "<YOUR_INGRESS_CLASS>"
    spec:
      rules:
      - host: foo.bar.com
        http:
          paths:
          - path: /
            backend:
              serviceName: nginx
              servicePort: 80
    说明 您需要配置注释 kubernetes.io/ingress.class
    在完成部署应用后,您可以看到该Ingress资源对应的端点IP地址与新部署的Nginx Ingress Controller服务的一致。
     kubectl -n kube-system get svc nginx-ingress-lb
    NAME               TYPE           CLUSTER-IP    EXTERNAL-IP    PORT(S)                      AGE
    nginx-ingress-lb   LoadBalancer   172.19.7.30   47.95.97.115   80:31429/TCP,443:32553/TCP   2d
    
      kubectl -n <YOUR_NAMESPACE> get svc nginx-ingress-lb
    NAME               TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)                      AGE
    nginx-ingress-lb   LoadBalancer   172.19.6.227   39.105.252.62   80:30969/TCP,443:31325/TCP   39m
    
      kubectl get ing
    NAME      HOSTS         ADDRESS         PORTS     AGE
    nginx     foo.bar.com   39.105.252.62   80        5m
  3. 分别通过集群默认的Nginx Ingress Controller服务和新部署的Nginx Ingress Controller服务来访问该应用。
     # 通过集群默认的 Nginx Ingress Controller 服务访问该应用(预期返回404)
      curl -H "Host: foo.bar.com" http://47.95.97.115
    default backend - 404                                                                                                                                                                                        
      # 通过新部署的 Nginx Ingress Controller 服务访问该应用(预期返回nginx页面)
      curl -H "Host: foo.bar.com" http://39.105.252.62
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    <style>
        body {
            width: 35em;
            margin: 0 auto;
            font-family: Tahoma, Verdana, Arial, sans-serif;
        }
    </style>
    </head>
    <body>
    <h1>Welcome to nginx!</h1>
    <p>If you see this page, the nginx web server is successfully installed and
    working. Further configuration is required.</p>
    
    <p>For online documentation and support please refer to
    <a href="http://nginx.org/">nginx.org</a>.<br/>
    Commercial support is available at
    <a href="http://nginx.com/">nginx.com</a>.</p>
    
    <p><em>Thank you for using nginx.</em></p>
    </body>
    </html>

从上文测试访问情况可以看到,通过不同的Nginx Ingress Controller暴露的服务彼此完全是独立的,这特别适用于同一集群内部分服务需要提供公网访问能力,但又有部分服务仅仅只希望为同VPC内非Kubernetes集群的其他服务提供访问的场景。