How Many Ingress Controllers We Need in K8S?
Tags: kubernetes
Published: 2024-06-17 08:17:27

Generally speaking, using separate namespaces and `ingress-nginx` controllers for different environments like SIT (System Integration Testing) and UAT (User Acceptance Testing) is a common and effective approach. This design provides isolation between environments, allowing you to configure and manage them independently. However, depending on your specific requirements and infrastructure, there might be alternative or complementary approaches to consider.

### Advantages of Separate Namespaces and Ingress Controllers

1. **Isolation**: Each environment (SIT and UAT) is isolated, preventing potential conflicts and allowing independent configurations.
2. **Resource Management**: Resources can be allocated and managed separately for each environment.
3. **Security**: Fine-grained access control can be applied to each namespace.
4. **Scalability**: Environments can be scaled independently based on their specific needs.
5. **Environment-Specific Configurations**: Different configurations, such as DNS, SSL certificates, and ingress rules, can be applied to each environment.

### Alternative and Complementary Approaches

1. **Cluster-per-Environment**:
   - **Description**: Deploy separate Kubernetes clusters for SIT and UAT.
   - **Pros**: Complete isolation at the cluster level, allowing for different Kubernetes versions and configurations. Enhanced security and resource isolation.
   - **Cons**: Higher operational overhead and costs due to managing multiple clusters.

2. **Namespace-per-Environment with Single Ingress Controller**:
   - **Description**: Use a single `ingress-nginx` controller with multiple namespaces for SIT and UAT.
   - **Pros**: Simplified management with a single ingress controller. Reduced resource usage.
   - **Cons**: Potential for configuration conflicts and reduced isolation compared to separate controllers.

3. **Use of Network Policies**:
   - **Description**: Implement Kubernetes Network Policies to enforce network isolation between namespaces.
   - **Pros**: Enhanced security and isolation without needing multiple ingress controllers.
   - **Cons**: Requires careful planning and configuration of network policies.

4. **Service Mesh**:
   - **Description**: Use a service mesh like Istio or Linkerd to manage traffic within and between environments.
   - **Pros**: Advanced traffic management, security, and observability. Can manage traffic routing, retries, and failures more effectively.
   - **Cons**: Additional complexity and resource overhead.

5. **Multi-Tenant Ingress Controller**:
   - **Description**: Configure a single ingress controller to handle multiple environments by using annotations and custom configurations.
   - **Pros**: Centralized management and reduced overhead.
   - **Cons**: Complexity in configuring and managing different rules for each environment.

### Example: Using a Single Cluster with Namespaces and Network Policies

**Namespaces**:
```bash
kubectl create namespace sit
kubectl create namespace uat
```

**Ingress Controller**: Deploy a single `ingress-nginx` controller, or use separate controllers as needed.

**Network Policies**:
- Define network policies to control traffic between namespaces and to/from the internet.

**sit-network-policy.yaml**:
```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-sit-ingress
  namespace: sit
spec:
  podSelector: {}
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: sit
    - podSelector:
        matchLabels:
          app: ingress-nginx
```

**uat-network-policy.yaml**:
```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-uat-ingress
  namespace: uat
spec:
  podSelector: {}
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: uat
    - podSelector:
        matchLabels:
          app: ingress-nginx
```

**Ingress Resources**:
- Define separate ingress resources for each environment.

**sit-ingress.yaml**:
```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: sit-ingress
  namespace: sit
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: sit.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: sit-service
            port:
              number: 80
```

**uat-ingress.yaml**:
```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: uat-ingress
  namespace: uat
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: uat.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: uat-service
            port:
              number: 80
```

### Summary

Using separate namespaces and `ingress-nginx` controllers for SIT and UAT is a good practice for isolating environments and managing resources independently. Depending on your needs, you might also consider alternatives like separate clusters, network policies, or a service mesh for more advanced traffic management and security features.

Choose the approach that best fits your organization's infrastructure, resource management capabilities, and operational overhead considerations.