---
title: Deploying an NGINX ingress controller on Scaleway Kubernetes Kapsule with a Load Balancer
description: This page explains how to expose an application via an ingress object, and using a Load Balancer to make the IP persistent.
tags: compute kapsule kubernetes ingress-controller k8s Load-balancer wildcard
dates:
  validation: 2025-06-17
  posted: 2025-06-17
---
import Requirements from '@macros/iam/requirements.mdx'


This page walks you through the process of deploying an NGINX ingress controller on Scaleway's Kubernetes Kapsule service.
We will configure a Load Balancer that uses a persistent IP address, which is essential for maintaining consistent routing. Additionally, we will enable the PROXY protocol to preserve client information such as the original IP address and port, which is recommended for applications that need to log or act on this data.

We will explore the differences between ephemeral and persistent IP addresses, helping you understand when and why to use each type, and guide you through deploying a demo application that illustrates the entire setup.

By the end of this guide, you should have a robust and well-configured NGINX ingress controller running on Scaleway's Kubernetes platform.

<Requirements />

- A Scaleway account logged into the [console](https://console.scaleway.com)
- [Owner](/iam/concepts/#owner) status or [IAM permissions](/iam/concepts/#permission) allowing you to perform actions in the intended Organization
- Set up a [Kubernetes Kapsule cluster](/kubernetes/how-to/create-cluster/), deploying a TRAEFIK2 ingress controller via the application library using the [Easy Deploy function](/kubernetes/how-to/enable-easy-deploy/)
- Obtained the [kubeconfig](/kubernetes/how-to/edit-cluster/) file for the cluster
- Helm installed on your local machine
- Installed [kubectl](/kubernetes/how-to/connect-cluster-kubectl/) and the Scaleway CLI on your local machine

## Overview of key concepts

### Ingress controller
An ingress controller manages external HTTP/HTTPS traffic to services within a Kubernetes cluster. The NGINX ingress controller routes traffic based on ingress resource rules.

### LoadBalancer service
On Scaleway Kapsule, the LoadBalancer service provisions a Scaleway Load Balancer with an external IP, exposing the ingress controller via the Scaleway Cloud Controller Manager (CCM).

### Ephemeral vs. persistent IPs
- Ephemeral IP: Dynamically assigned by Scaleway when a LoadBalancer service is created. It may change if the service is deleted and recreated, requiring DNS updates.
- Persistent IP: A flexible IP reserved via the Scaleway API, CLI or console, ensuring consistency across service recreations. This is recommended for production to maintain stable DNS records.

### PROXY protocol
The PROXY protocol allows the LoadBalancer to forward the client's original IP address to the ingress controller, preserving source information for logging and security.

## Deploying the ingress controller

## Installation prework
Kapsule clusters use a default security group (`kubernetes-<cluster-id>`) that blocks incoming traffic. To allow HTTP/HTTPS connections to the cluster:
1. Go to the Scaleway console and navigate to **Compute > CPU & GPU Instances > Security Groups**.
2. Locate the security group `kubernetes-<cluster-id>`.
3. Add rules to allow:
   - TCP port 80 (HTTP) from `0.0.0.0/0`.
   - TCP port 443 (HTTPS) from `0.0.0.0/0`.

## Reserve a flexible IP
To use a persistent IP with the ingress controller:
1. Create a flexible IP using the Scaleway CLI:
   ```bash
   scw lb ip create
   ```
2. Note the IP address (e.g., `195.154.72.226`) and IP ID for use in the LoadBalancer service.

## Installing the NGINX ingress controller

Use Helm to deploy the NGINX ingress controller with Scaleway-specific configurations.

1. Add the NGINX ingress Helm repository:
    ```bash
    helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
    helm repo update
    ```

2. Create a file named `ingress-values.yaml` with and edit the `loadBalancerIP` to your flexible IP:
    ```yaml
    controller:
      service:
        type: LoadBalancer
        # Specify reserved flexible IP
        loadBalancerIP: "195.154.72.226"
        annotations:
          # Enable PROXY protocol v2
          service.beta.kubernetes.io/scw-loadbalancer-proxy-protocol-v2: "true"
          # Use hostname for cert-manager compatibility
          service.beta.kubernetes.io/scw-loadbalancer-use-hostname: "true"
      config:
        # Enable PROXY protocol in NGINX
        use-proxy-protocol: "true"
        use-forwarded-headers: "true"
        compute-full-forwarded-for: "true"
    ```
    <Message type="note">
    - Replace `195.154.72.226` with your reserved flexible IP. Omitting `loadBalancerIP` results in an ephemeral IP.
    - The `service.beta.kubernetes.io/scw-loadbalancer-proxy-protocol-v2` annotation enables PROXY protocol v2.
    - The `service.beta.kubernetes.io/scw-loadbalancer-use-hostname` annotation supports cert-manager HTTP01 challenges.
    </Message>

3. Deploy the ingress controller:
    ```bash
    helm install ingress-nginx ingress-nginx/ingress-nginx -f ingress-values.yaml --namespace ingress-nginx --create-namespace
    ```

4. Verify the LoadBalancer IP using `kubectl`:
    ```bash
    kubectl get svc -n ingress-nginx ingress-nginx-controller
    ```

    You will see an output similar to the following example: 
    ```
    NAME                       TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)                      AGE
    ingress-nginx-controller   LoadBalancer   10.100.0.1      195.154.72.226   80/TCP,443/TCP               5m
    ```
    <Message type="note">
    - The `EXTERNAL-IP` should match your reserved flexible IP (e.g., `195.154.72.226`).
    - If an ephemeral IP appears, verify that the `loadBalancerIP` field is correctly set and matches a valid Load Balancer flexible IP attached to your Scaleway Project.
    - Confirm the LoadBalancer in the Scaleway console under **Network > Load Balancers**.
    </Message>

5. Configure DNS by setting the A-Record of your domain (e.g., `demo.example.com`) to the flexible IP via Scaleway's Domains & DNS product or your DNS provider. Persistent IPs ensure stability and will not change as long as they are reserved.

### Deploying a demo application

1. Create a file named `demo-app.yaml` and copy the following content into it to deploy a simple web application to test the ingress controller:

    ```yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: demo-app
      namespace: default
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: demo-app
      template:
        metadata:
          labels:
            app: demo-app
        spec:
          containers:
          - name: demo-app
            image: nginx:1.21
            ports:
            - containerPort: 80
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: demo-app
      namespace: default
    spec:
      selector:
        app: demo-app
      ports:
        - protocol: TCP
          port: 80
          targetPort: 80
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: demo-app-ingress
      namespace: default
      annotations:
        nginx.ingress.kubernetes.io/rewrite-target: /
    spec:
      ingressClassName: nginx
      rules:
      - host: demo.example.com
        http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: demo-app
                port:
                  number: 80
    ```

    <Message type="note">
    - Replace `demo.example.com` with your domain name.
    </Message>

2. Apply the configuration:
    ```bash
    kubectl apply -f demo-app.yaml
    ```

## Test the setup
1. Access the demo application:
    ```bash
    curl http://demo.example.com
    # or
    curl http://195.154.72.226/
    ```

2. You should see the NGINX welcome page. Verify the PROXY protocol by checking logs for the client's real IP:
    ```bash
    kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx
    ```

## Cleanup (optional)
Once finished, you can remove the demo application and ingress controller from your cluster:
```bash
kubectl delete -f demo-app.yaml
helm uninstall ingress-nginx -n ingress-nginx
kubectl delete namespace ingress-nginx
```

To release the flexible IP:
```bash
scw lb ip delete <IP-ID>
```
