juzhiyuan commented on issue #2282:
URL: 
https://github.com/apache/apisix-ingress-controller/issues/2282#issuecomment-3083325794

   # Multi-Cluster Ingress APISIX Resource Isolation
   
   ## Background
   
   In APISIX Ingress Controller version 2.0.0+, the `namespaceSelector` has 
been deprecated and replaced with the recommendation to use `IngressClass` for 
resource isolation. This change is based on the following key reasons:
   
   ### 1. Kubernetes Official Standard Specification - Clearer and More Explicit
   
   `IngressClass` is the official standard mechanism introduced by Kubernetes 
starting from v1.18, used to explicitly specify which Controller manages 
specific resources.
   
   - **Resource-level declarative isolation**: Provides clear ownership 
declaration at the resource level
   - **No dependency on controller-specific behavior**: Works independently 
without requiring special controller implementations
   - **Direct declaration**: Can be declared directly on Ingress, Gateway, and 
other resources for easy use and maintenance
   
   In contrast, `namespaceSelector` is a behavior supported by some Ingress 
Controller implementations (not all controllers support it) and is not a core 
Kubernetes mechanism.
   
   ### 2. Precise Granularity - Avoiding Mishandling
   
   `namespaceSelector` performs resource filtering at the namespace level. Once 
a namespace is selected, it processes all Ingress resources within that 
namespace without the ability to further refine the selection.
   
   `ingressClassName` provides precise control at the individual resource level 
with finer granularity, avoiding the processing of resources that shouldn't be 
handled.
   
   ### 3. Better Cross-Namespace Support
   
   If you want an Ingress Controller to manage Ingress resources across 
multiple namespaces, you simply need to set the corresponding 
`ingressClassName` on those Ingress resources.
   
   - **IngressClass supports cross-namespace operations**
   - **namespaceSelector requires maintaining additional label strategies with 
inflexible control scope**
   
   ### 4. Unified with Gateway API and Other Mechanisms
   
   Beyond just Ingress, Kubernetes Gateway API, IngressClass, and GatewayClass 
all adopt similar mechanisms, using Class mechanisms to specify controller 
behavior. Using IngressClass aligns better with official architecture design.
   
   The use of namespaceSelector with the Gateway API's ReferenceGrant may 
create conflicts or trigger inconsistent behavior: 
https://gateway-api.sigs.k8s.io/api-types/referencegrant/
   
   ### 5. Easier Debugging and Understanding
   
   When developers or platform administrators see `ingressClassName=pro-apisix` 
explicitly specified in resources, they can clearly understand which controller 
manages the resource. In contrast, the effects of `namespaceSelector` are 
implicit and not intuitive.
   
   ## How to Deploy and Use Multiple Ingress-APISIX Clusters in the Same Cluster
   
   In actual production or multi-tenant environments, it's common to deploy 
multiple independent Ingress APISIX instances in the same Kubernetes cluster to 
achieve traffic isolation, environment separation (such as testing, staging, 
production), or service team autonomy.
   
   This document covers how to deploy and use multiple ingress-apisix clusters 
in parallel within the same cluster, including:
   
   - How to install multiple independent ingress-apisix instances using Helm
   - How to isolate traffic resources using IngressClass
   - How to configure separate routing rules for each instance
   - How to verify the independence and correctness of each Ingress APISIX 
instance through testing
   
   ## Installation and Deployment
   
   ### Important Helm Chart Deployment Parameters
   
   | Parameter | Description | Purpose |
   |-----------|-------------|---------|
   | `--set ingress-controller.config.kubernetes.ingressClass` | IngressClass 
name | Specify the name of the IngressClass managed by this Ingress Controller 
as `pro-apisix`. the Ingress resources in Kubernetes that specify this name 
will be processed by this Controller. |
   | `--set ingress-controller.gatewayProxy.createDefault` | Create default 
GatewayProxy | Configure the default GatewayProxy (used to describe how the 
Controller accesses the APISIX Admin API for use by the Ingress Controller 
IngressClass, ). |
   | `--set ingress-controller.config.controllerName` | Controller unique 
identifier | Distinguishes different controller instances |
   | `--set ingress-controller.apisix.adminService.name` | Admin service name | 
Avoids naming conflicts |
   
   ### Deploy Test Environment Cluster (test-apisix)
   
   ```bash
   helm repo add apisix https://charts.apiseven.com                             
        
   helm repo update
   
   helm install test-apisix \
     --namespace test-ingress-apisix \
     --create-namespace \
     --set apisix.deployment.role=traditional \
     --set apisix.deployment.role_traditional.config_provider=yaml \
     --set etcd.enabled=false \
     --set ingress-controller.enabled=true \
     --set ingress-controller.config.kubernetes.ingressClass=test-apisix \
     --set ingress-controller.config.provider.type=apisix-standalone \
     --set ingress-controller.gatewayProxy.createDefault=true \
     --set 
ingress-controller.config.controllerName=apisix.apache.org/apisix-ingress-controller/test
 \
     --set ingress-controller.apisix.adminService.name=test-apisix-admin \
     apisix/apisix
   ```
   
   After successful installation, Helm will create the following resources:
   
   ```yaml
   apiVersion: apisix.apache.org/v1alpha1
   kind: GatewayProxy
   metadata:
     name: test-apisix-config
     namespace: test-ingress-apisix
   spec:
     provider:
       controlPlane:
         auth:
           adminKey:
             value: edd1c9f034335f136f87ad84b625c8f1
           type: AdminKey
         service:
           name: test-apisix-admin
           port: 9180
       type: ControlPlane
   
   ---
   apiVersion: networking.k8s.io/v1
   kind: IngressClass
   metadata:
     name: test-apisix
   spec:
     controller: apisix.apache.org/apisix-ingress-controller/test
     parameters:
       apiGroup: apisix.apache.org
       kind: GatewayProxy
       name: test-apisix-config
       namespace: test-ingress-apisix
       scope: Namespace
   ```
   
   ### Deploy Production Environment Cluster (pro-apisix)
   
   ```bash
   helm repo add apisix https://charts.apiseven.com                             
        
   helm repo update
   
   helm install pro-apisix \
     --namespace pro-ingress-apisix \
     --create-namespace \
     --set apisix.deployment.role=traditional \
     --set apisix.deployment.role_traditional.config_provider=yaml \
     --set etcd.enabled=false \
     --set ingress-controller.enabled=true \
     --set ingress-controller.config.kubernetes.ingressClass=pro-apisix \
     --set ingress-controller.config.provider.type=apisix-standalone \
     --set ingress-controller.gatewayProxy.createDefault=true \
     --set 
ingress-controller.config.controllerName=apisix.apache.org/apisix-ingress-controller/pro
 \
     --set ingress-controller.apisix.adminService.name=pro-apisix-admin \
     apisix/apisix
   ```
   
   After successful installation, Helm will create the following resources:
   
   ```yaml
   apiVersion: apisix.apache.org/v1alpha1
   kind: GatewayProxy
   metadata:
     name: pro-apisix-config
     namespace: pro-ingress-apisix
   spec:
     provider:
       controlPlane:
         auth:
           adminKey:
             value: edd1c9f034335f136f87ad84b625c8f1
           type: AdminKey
         service:
           name: pro-apisix-admin
           port: 9180
       type: ControlPlane
   ---
   apiVersion: networking.k8s.io/v1
   kind: IngressClass
   metadata:
     name: pro-apisix
   spec:
     controller: apisix.apache.org/apisix-ingress-controller/pro
     parameters:
       apiGroup: apisix.apache.org
       kind: GatewayProxy
       name: pro-apisix-config
       namespace: pro-ingress-apisix
       scope: Namespace
   ```
   
   ## Route Configuration
   
   ### Production Environment Route
   
   By specifying `ingressClassName: pro-apisix`, this resource will be managed 
by the production environment's pro-apisix Controller:
   
   ```yaml
   apiVersion: apisix.apache.org/v2
   kind: ApisixRoute
   metadata:
     name: pro-route-1
   spec:
     ingressClassName: pro-apisix
     http:
     - name: rule0
       match:
         hosts:
         - httpbin-pro
         paths:
         - /*
       backends:
       - serviceName: httpbin
         servicePort: 80
   ```
   
   ### Test Environment Route
   
   By specifying `ingressClassName: test-apisix`, this resource will be managed 
by the test environment's test-apisix Controller:
   
   ```yaml
   apiVersion: apisix.apache.org/v2
   kind: ApisixRoute
   metadata:
     name: test-route-1
   spec:
     ingressClassName: test-apisix
     http:
     - name: rule0
       match:
         hosts:
         - httpbin-test
         paths:
         - /*
       backends:
       - serviceName: httpbin
         servicePort: 80
   ```
   
   ## Verification
   
   ### Port Forwarding Setup
   
   Forward production environment APISIX to local port 9081:
   ```bash
   kubectl port-forward -n pro-ingress-apisix svc/pro-apisix-gateway 9081:80
   ```
   
   Forward test environment APISIX to local port 9082:
   ```bash
   kubectl port-forward -n test-ingress-apisix svc/test-apisix-gateway 9082:80
   ```
   
   ### Test Production Environment APISIX
   
   ```bash
   # Test with test host (should fail - route not found)
   ➜ curl localhost:9081/get -H "Host: httpbin-test"
   {"error_msg":"404 Route Not Found"}
   
   # Test with production host (should succeed)
   ➜ curl localhost:9081/get -H "Host: httpbin-pro"
   {
     "args": {},
     "headers": {
       "Accept": "*/*",
       "Host": "httpbin-pro",
       "User-Agent": "curl/7.81.0",
       "X-Forwarded-Host": "httpbin-pro"
     },
     "origin": "127.0.0.1",
     "url": "http://httpbin-pro/get";
   }
   ```
   
   ### Test Test Environment APISIX
   
   ```bash
   # Test with production host (should fail - route not found)
   ➜ curl localhost:9082/get -H "Host: httpbin-pro"
   {"error_msg":"404 Route Not Found"}
   
   # Test with test host (should succeed)
   ➜ curl localhost:9082/get -H "Host: httpbin-test"
   {
     "args": {},
     "headers": {
       "Accept": "*/*",
       "Host": "httpbin-test",
       "User-Agent": "curl/7.81.0",
       "X-Forwarded-Host": "httpbin-test"
     },
     "origin": "127.0.0.1",
     "url": "http://httpbin-test/get";
   }
   ```
   
   ## Conclusion
   
   The test results demonstrate that:
   
   1. **Perfect Isolation**: Each APISIX instance only responds to routes 
configured with its corresponding IngressClass
   2. **Cross-Environment Protection**: Production environment only handles 
`httpbin-pro` requests, while test environment only handles `httpbin-test` 
requests
   3. **Independent Operation**: Both environments operate independently 
without interference
   
   This approach provides a robust solution for multi-tenant or 
multi-environment deployments within a single Kubernetes cluster.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscr...@apisix.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to