
# 自定义部署Nginx Ingress Controller
#### 应用现状
[Nginx Ingress Controller](https://kubernetes.github.io/ingress-nginx/)是一款业界流行的开源Ingress控制器，有着广泛的应用。在大规模集群场景下，用户有在集群中部署多套Nginx Ingress Controller的诉求，不同流量使用不同的控制器，将流量区分开。例如，集群中部分服务需要通过公网Ingress方式对外提供访问，但是又有部分对内开放的服务不允许使用公网访问，只支持对同VPC内的其他服务访问，您可以通过部署两套独立的Nginx Ingress Controller，绑定两个不同的ELB实例来满足这类需求场景。
图1多个Nginx Ingress应用场景   
![](https://support.huaweicloud.com/bestpractice-cce/zh-cn_image_0000001616513609.png "点击放大")
#### 解决方案
您可以通过以下方案，实现在同一个集群中部署多个Nginx Ingress Controller。
- （推荐）安装NGINX Ingress控制器插件，在同一个集群中一键部署多个实例。详情请参见[安装多个NGINX Ingress控制器](https://support.huaweicloud.com/usermanual-cce/cce_10_0034.html#section5)。
  v1.23集群需安装2.2.52及以上版本的插件，对于v1.23以上的集群需安装2.5.4及以上版本的插件。
  
- 通过安装开源Helm包，在集群中自定义部署多套Nginx Ingress Controller。该方案需要配置的参数较复杂，您需要通过配置ingress-class[参数]（缺省值为nginx）来声明Nginx Ingress Controller监听的范围。这样在创建Ingress时可以通过选择不同的Nginx Ingress Controller进行流量区分。
  
  
 
#### 前提条件
- 已创建ELB实例（推荐使用独享型），具体操作可参考[创建独享型负载均衡器](https://support.huaweicloud.com/usermanual-elb/elb_lb_000006.html)、[创建共享型负载均衡器](https://support.huaweicloud.com/usermanual-elb/zh-cn_topic_0015479967.html)。
- 安装模板过程中，可能需要拉取公网镜像，因此节点需要绑定EIP。
 
#### 约束与限制
- 部署多个Nginx Ingress Controller时，每个Controller需要对接一个ELB，并保证对接的ELB需要拥有至少两个监听器配额，且端口80和443没有被监听器占用。如果使用独享型ELB，需要支持网络型规格。
- 使用社区提供的nginx-ingress模板与镜像时，使用过程中对于因社区软件本身缺陷导致的业务受损CCE服务不提供额外维护。**商用场景请谨慎使用**。
 
#### 部署Nginx Ingress Controller
您可以通过以下步骤在集群中部署多套完全独立的Nginx Ingress Controller服务。
1. **获取模板包。**
   
   前往[社区模板发布页面](https://github.com/kubernetes/ingress-nginx/releases)，选择合适的版本并下载tgz格式的Helm Chart包。本文以社区[4.4.2](https://github.com/kubernetes/ingress-nginx/releases/tag/helm-chart-4.4.2)版本的模板包为例，该模板包适用于v1.21及以上的CCE集群。由于不同版本的模板包配置项可能存在差异，本文中的配置仅对[4.4.2](https://github.com/kubernetes/ingress-nginx/releases/tag/helm-chart-4.4.2)版本生效。
   
   
2. **上传模板**
   
   1. 登录[CCE控制台](https://console.huaweicloud.com/cce2.0/?#/cce/cluster/list)，进入集群，在左侧导航栏中选择"应用模板"，在右上角单击"上传模板"。
   
   2. 单击"添加文件"，选中待上传的模板包后，单击"上传"。 ![](https://support.huaweicloud.com/bestpractice-cce/zh-cn_image_0000002589113631.png "点击放大")
      
   
   
   
   
3. **自定义value.yaml**
   
   您可在本地创建一个**value.yaml**配置文件用于设置安装工作负载参数，在安装时只需导入此配置文件进行自定义安装，其他未指定的参数将会使用默认配置。
   配置内容如下：
   ```
   controller:
     image:
       repository: swr.cn-east-3.myhuaweicloud.com/hwofficial/nginx-ingress   #controller镜像地址，请根据集群所在区域进行替换
       registry: ""
       image: ""
       tag: "v1.5.1"  #controller版本
       digest: ""
     ingressClassResource:
       name: ccedemo         #同一个集群中不同套Ingress Controller名称必须唯一，且不能设置为nginx和cce
       controllerValue: "k8s.io/ingress-nginx-demo"  #同一个集群中不同套Ingress Controller的监听标识必须唯一，且不能设置为k8s.io/ingress-nginx
     ingressClass: ccedemo   #同一个集群中不同套Ingress Controller名称必须唯一，且不能设置为nginx和cce
     service: 
       annotations: 
         kubernetes.io/elb.id: 5083f225-9bf8-48fa-9c8b-67bd9693c4c0     #ELB ID
         kubernetes.io/elb.class: performance  #仅独享型ELB需要添加此注解
     config:
       keep-alive-requests: 100
     extraVolumeMounts: # 挂载节点上的/etc/localtime文件，进行时区同步
       - name: localtime
         mountPath: /etc/localtime
         readOnly: true
     extraVolumes:
       - name: localtime
         type: Hostpath
         hostPath:
           path: /etc/localtime 
     admissionWebhooks: # 关闭webhook验证开关
       enabled: false
       patch:
         enabled: false
     resources: # 设定controller的资源限制，可根据需求自定义
       requests:
         cpu: 200m
         memory: 200Mi
   defaultBackend: # 设置defaultBackend
     enabled: true
     image: 
       repository: swr.cn-east-3.myhuaweicloud.com/hwofficial/defaultbackend     #defaultBackend镜像地址，请根据集群所在区域进行替换
       registry: ""
       image: ""
       tag: "1.5"
       digest: ""
   ```
   上述参数详情请参见[表1]。
   
   
4. **创建模板实例。**
   
   1. 登录[CCE控制台](https://console.huaweicloud.com/cce2.0/?#/cce/cluster/list)，进入集群，在左侧导航栏中选择"应用模板"。
   
   2. 在已上传的模板中，单击"安装"。
   
   3. 填写"实例名称"，选择"命名空间"和"选择版本"。
   
   4. 单击"配置文件"后的"添加文件"按钮，选择本地创建的YAML配置文件，单击"安装"。
   
   5. 在"模板实例"页签下可以查看模板实例的安装情况。 ![](https://support.huaweicloud.com/bestpractice-cce/zh-cn_image_0000001395899880.png "点击放大")
      
   
   
   
   
 
#### 测试验证
创建一个工作负载，配置新部署的Nginx Ingress Controller为其提供网络访问。
1. 创建nginx工作负载。 
   1. 登录[CCE控制台](https://console.huaweicloud.com/cce2.0/?#/cce/cluster/list)，进入集群，在左侧导航栏中选择"工作负载"，单击右上角"YAML创建"。
   
   2. 填写以下内容，并单击"确定"。
      ```
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: nginx
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: nginx
        strategy:
          type: RollingUpdate
        template:
          metadata:
            labels:
              app: nginx
          spec:
            containers:
            - image: nginx    #若使用“开源镜像中心”的镜像，可直接填写镜像名称；若使用“我的镜像”中的镜像，请在SWR中获取具体镜像地址。
              imagePullPolicy: Always
              name: nginx
            imagePullSecrets:
            - name: default-secret
      ---
      apiVersion: v1
      kind: Service
      metadata:
        labels:
          app: nginx
        name: nginx
      spec:
        ports:
        - name: service0
          port: 80                 # 访问Service的端口
          protocol: TCP           # 访问Service的协议，支持TCP和UDP
          targetPort: 80           # Service访问目标容器的端口，本例中nginx镜像默认使用80端口
        selector:                  # 标签选择器，Service通过标签选择Pod，将访问Service的流量转发给Pod
          app: nginx
        type: ClusterIP            # Service的类型，ClusterIP表示在集群内访问
      ```
      
   
   
   
   
2. 创建Ingress，通过新部署的Nginx Ingress Controller提供网络访问。 
   1. 在左侧导航栏中选择"服务"，切换至"路由"页签，单击右上角"YAML创建"。
      ![](https://support.huaweicloud.com/bestpractice-cce/public_sys-resources/note_3.0-zh-cn.png)
      对接非插件部署的Nginx Ingress Controller时，只支持使用YAML的方式创建Ingress。
      
   
   2. 填写以下内容，并单击"确定"。
      **v1.23及以上版本集群：**
      ```
      apiVersion: networking.k8s.io/v1 
      kind: Ingress 
      metadata: 
        name: ingress-test
        namespace: default 
      spec: 
        ingressClassName: ccedemo  # 填写新创建的nginx ingress controller的ingressClass
        rules: 
        - host: foo.bar.com
          http: 
            paths: 
            - path: / 
              pathType: ImplementationSpecific   #匹配取决于 IngressClass 
              backend: 
                service: 
                  name: nginx    #替换为您的目标服务名称
                  port: 
                    number: 80   #替换为您的目标服务端口
              property: 
                ingress.beta.kubernetes.io/url-match-mode: STARTS_WITH
      ```
      **v1.23以下版本集群：**
      ```
      apiVersion: networking.k8s.io/v1beta1
      kind: Ingress 
      metadata: 
        name: tomcat-t1 
        namespace: test 
        annotations: 
          kubernetes.io/ingress.class: ccedemo  # 填写新创建的nginx ingress controller的ingressClass
      spec: 
        rules: 
          - host: foo.bar.com
            http: 
              paths: 
                - path: / 
                  pathType: ImplementationSpecific 
                  backend: 
                    serviceName: nginx  #替换为您的目标服务名称
                    servicePort: 80     #替换为您的目标服务端口
                  property: 
                    ingress.beta.kubernetes.io/url-match-mode: STARTS_WITH
      ```
      
   
   
   
   
3. 登录集群节点，分别通过集群Nginx Ingress插件中的Controller和新部署的Nginx Ingress Controller服务来访问该应用。 
   - 通过新建的Nginx Ingress Controller服务来访问该应用（预期返回Nginx页面），其中192.168.114.60为新建的Nginx Ingress Controller服务对应的ELB地址。
     ```
     curl -H "Host: foo.bar.com" http://192.168.114.60
     ```
     ![](https://support.huaweicloud.com/bestpractice-cce/zh-cn_image_0000001292428722.png "点击放大")
     
   
   - 通过Nginx Ingress插件中的Controller服务（预期返回404），其中192.168.9.226为Nginx Ingress插件对应的ELB地址。
     ```
     curl -H "Host: foo.bar.com" http://192.168.9.226
     ```
     ![](https://support.huaweicloud.com/bestpractice-cce/zh-cn_image_0000001546872008.png "点击放大")
     
   
   
   
   
 
#### 配置参数说明
 表1nginx-ingress主要参数配置 
| 参数                                              | 描述                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
|:---|:---|
| controller.image.repository                     | ingress-nginx镜像地址，建议与CCE提供的Nginx Ingress插件镜像一致，也可自定义。 - Nginx Ingress插件镜像：Nginx Ingress插件的镜像地址可通过已安装插件实例的YAML文件查看。例如"华东-上海一"区域的插件镜像地址为"swr.cn-east-3.myhuaweicloud.com/hwofficial/nginx-ingress"，该地址需要根据集群所在区域进行替换。  - 自定义：自定义地址需要保证镜像可拉取。      |
| controller.image.registry                       | 镜像仓库域名，该参数需要与controller.image.image同时填写。 如已填写controller.image.repository，则无需再填写该参数，建议将controller.image.registry和controller.image.image设为空值。                                                                                                                                                                                                                                                                                                                  |
| controller.image.image                          | 镜像名称。该参数需要与controller.image.registry同时填写。 如已填写controller.image.repository，则无需再填写该参数，建议将controller.image.registry和controller.image.image设为空值。                                                                                                                                                                                                                                                                                                                  |
| controller.image.tag                            | ingress-nginx镜像版本，建议与CCE提供的Nginx Ingress插件镜像一致，也可自定义。 Nginx Ingress插件的镜像版本可通过已安装插件实例的YAML文件查看，需要根据插件版本进行替换。                                                                                                                                                                                                                                                                                                                                                   |
| controller.ingressClass                         | 设置Ingress Controller所对应的IngressClass的名称。 说明： 同一个集群中不同套Ingress Controller名称必须唯一，且不能设置为**nginx** 和**cce** （**nginx** 是集群默认Nginx Ingress Controller的监听标识，**cce**则是使用ELB Ingress Controller的配置）。 示例：**ccedemo**                                                                                                                                                                   |
| controller.image.digest                         | 建议为空值，该参数非空时可能无法拉取CCE提供的Nginx Ingress插件镜像。                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| controller.ingressClassResource.name            | 需要与ingressClass值相同。 示例：**ccedemo**                                                                                                                                                                                                                                                                                                                                                                                                                          |
| controller.ingressClassResource.controllerValue | 同一个集群中不同套Ingress Controller的监听标识必须唯一，且不能设置为**k8s.io/ingress-nginx** （**k8s.io/ingress-nginx**是默认Nginx Ingress Controller的监听标识）。 示例：**k8s.io/ingress-nginx-demo**                                                                                                                                                                                                                                                                                               |
| controller.config                               | nginx配置参数，配置参数范围请参考[社区文档](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/)。不在范围内的参数配置不会生效。 建议增加如下配置： "keep-alive-requests": "100"                                                                                                                                                                                                                                              |
| controller.extraInitContainers                  | init容器，在主容器启动前执行，可用于Pod参数的初始化配置。 配置参数示例请参见[高并发业务场景参数优化](https://support.huaweicloud.com/bestpractice-cce/cce_bestpractice_10015.html#cce_bestpractice_10015__section171421156185)。                                                                                                                                                                                                                                                                             |
| controller.admissionWebhooks.enabled            | 是否开启admissionWebhooks，可以对Ingress对象进行有效性校验，避免因配置错误导致ingress-controller不断重新加载资源，导致业务中断。 此处设置为false，表示不开启。如需开启，请参见[admissionWebhook配置](https://support.huaweicloud.com/bestpractice-cce/cce_bestpractice_10015.html#cce_bestpractice_10015__section1075551319187)示例。                                                                                                                                                                                              |
| controller.admissionWebhooks.patch.enabled      | 同上，表示是否开启admissionWebhooks。此处设置为false。                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| controller.service.annotations                  | Key: value类型，此处需加上ELB ID，如下所示： kubernetes.io/elb.id: 5083f225-9bf8-48fa-9c8b-67bd9693c4c0 独享型负载均衡还需要加上elb.class，如下所示： kubernetes.io/elb.class: performance                                                                                                                                                                                                                   |
| controller.resources.requests.cpu               | Nginx controller的CPU资源申请值，可根据需求自定义。                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| controller.resources.requests.memory            | Nginx controller的内存资源申请值，可根据需求自定义。                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| defaultBackend.image.repository                 | default-backend镜像地址，建议与CCE提供的Nginx Ingress插件镜像一致，也可自定义。 - Nginx Ingress插件镜像：Nginx Ingress插件的镜像地址可通过已安装插件实例的YAML文件查看。例如"华东-上海一"区域的插件镜像地址为"swr.cn-east-3.myhuaweicloud.com/hwofficial/defaultbackend"，该地址需要根据集群所在区域进行替换。  - 自定义：自定义地址需要保证镜像可拉取。   |
| defaultBackend.image.tag                        | default-backend镜像版本，建议与CCE提供的Nginx Ingress插件镜像一致，也可自定义。                                                                                                                                                                                                                                                                                                                                                                                                                                               |
   
更多参数配置说明请参见[ingress-nginx](https://artifacthub.io/packages/helm/ingress-nginx/ingress-nginx#values)。
#### 相关文档
- 生产环境下，您可以为Nginx Ingress Controller使用高可用配置，详情请参见[插件高可用部署](https://support.huaweicloud.com/bestpractice-cce/cce_bestpractice_10027.html)。
 
