Deploy the Gateway API integrator charm

The Gateway API integrator charm manages Gateway API resources to provide ingress for applications. The charm supports two different relation interfaces, and the ingress interface offers a straightforward and standard way to configure basic traffic routing. In this tutorial we’ll deploy the charm to provide ingress to a simple Flask backend application running on Kubernetes.

Important

The ingress interface has limitations in ingress configuration and with supporting multiple backend applications. The charm offers another interface, gateway-route, with advanced routing features and configuration options. Follow Deploy the ingress-configurator charm with Gateway API to walk through a deployment of Gateway API integrator using the gateway-route interface.

What you’ll do

  1. Deploy and configure the Gateway API integrator charm

  2. Establish an integration with a TLS provider charm

  3. Deploy a simple Flask application

  4. Integrate Gateway API and the Flask application

  5. Verify the routing in the terminal and in a browser

What you’ll need

You will need a working station, e.g., a laptop, with AMD64 architecture. Your working station should have at least 4 CPU cores, 8 GB of RAM, and 50 GB of disk space.

Tip

You can use Multipass to create an isolated environment by running:

multipass launch 24.04 --name charm-tutorial-vm --cpus 4 --memory 8G --disk 50G

To be able to work inside the Multipass VM, log in with the following command:

multipass shell charm-tutorial-vm

This tutorial requires the following software to be installed on your working station (either locally or in the Multipass VM):

  • Juju 3

  • Canonical Kubernetes 1.32+

Use Concierge to set up Juju and Canonical Kubernetes:

sudo snap install --classic concierge
sudo concierge prepare -p k8s

This first command installs Concierge, and the second command uses Concierge to install and configure Juju and Canonical Kubernetes.

Set the Kubernetes load-balancer IP to be the same as your working station or Multipass VM:

PREFSRC=$(ip -4 -j route get 2.2.2.2 | jq -r '.[] | .prefsrc')
sudo k8s set load-balancer.cidrs=$PREFSRC/32

Note

If you’re using Multipass for this tutorial, this custom configuration means we can avoid setting up additional routes later in the tutorial when we visit the Flask application in a browser.

For this tutorial, Juju must be bootstrapped to a Canonical Kubernetes controller. Concierge should complete this step for you, and you can verify by checking for msg="Bootstrapped Juju" provider=k8s in the terminal output and by running juju controllers.

If Concierge did not perform the bootstrap, run:

juju bootstrap k8s tutorial-controller

Set up the Juju model

To manage resources effectively and to separate this tutorial’s workload from your usual work, create a new model in the controller with:

juju add-model gateway-api-integrator-tutorial

Deploy and configure the charm

Let’s deploy the Gateway API integrator charm:

juju deploy gateway-api-integrator --trust --channel=1/edge

We’ll use the 1/edge channel for this tutorial as that’s the actively maintained channel for the charm. We must also use the --trust flag to provide Gateway API with elevated permissions to interact with the Kubernetes environment (the charm uses these permissions to create the Gateway and HTTRoute resources).

Now let’s set some required configurations for the charm: gateway-class and external-hostname. The gateway-class configuration option tells the charm which GatewayClass to use when creating the Gateway resource; for this tutorial, we’ll use the gateway class shipped with Canonical Kubernetes. The external-hostname configuration sets the fully qualified domain name (FQDN) that the charm serves when backend applications are routed through the ingress relation.

Configure the charm:

juju config gateway-api-integrator gateway-class=ck-gateway \
     external-hostname=ingress.internal

Check the status of our deployment with juju status:

ubuntu@charm-tutorial-vm:~$
juju status
Model                            Controller     Cloud/Region  Version  SLA          Timestamp
gateway-api-integrator-tutorial  concierge-k8s  k8s           3.6.28   unsupported  17:48:45Z

App                     Version  Status   Scale  Charm                   Channel   Rev  Address         Exposed  Message
gateway-api-integrator           blocked      1  gateway-api-integrator  1/stable  165  10.152.183.155  no       Certificates relation is needed if enforce-https is enabled.

Unit                       Workload  Agent  Address     Ports  Message
gateway-api-integrator/0*  blocked   idle   10.1.0.122         Certificates relation is needed if enforce-https is enabled.

By default, the charm redirects plain HTTP traffic to HTTPS, which requires a TLS certificate to successfully complete the connection. The deployment is blocked because the charm must be integrated with a TLS certificates provider.

Integrate with a TLS provider charm

For this tutorial, we’ll use the self-signed certificates charm to create a certificate authority (CA) and issue the requested certificates. This charm is the simplest way to satisfy the certificate requirement, but you shouldn’t use self-signed certificates in production environments. For more details, see How to provide a certificate.

Let’s deploy the charm and integrate it with Gateway API integrator using the certificates endpoint:

juju deploy self-signed-certificates
juju integrate self-signed-certificates:certificates gateway-api-integrator:certificates

Wait a couple of minutes for the deployment to settle, then check with juju status --relations:

ubuntu@charm-tutorial-vm:~$
juju status --relations
Model                            Controller     Cloud/Region  Version  SLA          Timestamp
gateway-api-integrator-tutorial  concierge-k8s  k8s           3.6.28   unsupported  14:48:53Z

App                       Version  Status  Scale  Charm                     Channel   Rev  Address        Exposed  Message
gateway-api-integrator             active      1  gateway-api-integrator    1/stable  165  10.152.183.51  no       Gateway addresses: 10.114.45.196
self-signed-certificates           active      1  self-signed-certificates  1/stable  586  10.152.183.50  no       

Unit                         Workload  Agent  Address     Ports  Message
gateway-api-integrator/0*    active    idle   10.1.0.148         Gateway addresses: 10.114.45.196
self-signed-certificates/0*  active    idle   10.1.0.96          

Integration provider                   Requirer                             Interface         Type     Message
self-signed-certificates:certificates  gateway-api-integrator:certificates  tls-certificates  regular 

Both charms are active and idle now that the relation has been established. Now we need to provide Gateway API integrator with an application.

Deploy the Flask application

For this tutorial, we’ll use the Flask K8s charm as our application. Let’s deploy it now:

juju deploy flask-k8s --channel edge

Integrate Gateway API and the Flask application

We’ll provide a communication pathway between Gateway API integrator and the Flask application by integrating them:

juju integrate gateway-api-integrator flask-k8s

Let’s check what’s going on with our deployment using juju status --relations:

ubuntu@charm-tutorial-vm:~$
juju status --relations
Model                            Controller     Cloud/Region  Version  SLA          Timestamp
gateway-api-integrator-tutorial  concierge-k8s  k8s           3.6.28   unsupported  14:50:08Z

App                       Version  Status  Scale  Charm                     Channel      Rev  Address         Exposed  Message
flask-k8s                          active      1  flask-k8s                 latest/edge   19  10.152.183.208  no       
gateway-api-integrator             active      1  gateway-api-integrator    1/stable     165  10.152.183.51   no       Gateway addresses: 10.114.45.196
self-signed-certificates           active      1  self-signed-certificates  1/stable     586  10.152.183.50   no       

Unit                         Workload  Agent  Address     Ports  Message
flask-k8s/0*                 active    idle   10.1.0.92          
gateway-api-integrator/0*    active    idle   10.1.0.148         Gateway addresses: 10.114.45.196
self-signed-certificates/0*  active    idle   10.1.0.96          

Integration provider                   Requirer                             Interface         Type     Message
flask-k8s:secret-storage               flask-k8s:secret-storage             secret-storage    peer     
gateway-api-integrator:gateway         flask-k8s:ingress                    ingress           regular  
self-signed-certificates:certificates  gateway-api-integrator:certificates  tls-certificates  regular  

The key relation here is the one between Gateway API integrator and the Flask application:

Integration provider                   Requirer                  Interface        Type
gateway-api-integrator:gateway         flask-k8s:ingress         ingress          regular

After we ran juju integrate gateway-api-integrator flask-k8s, Juju connected the two applications together through the ingress relation endpoint. The Flask application can now provide Gateway API integrator with its internal IP address and port (which is 8000 by default). In return, Gateway API integrator can now act as a reverse proxy for the application, automatically generating an external URL.

We’ll now test whether the routing works.

Verify the routing

First, let’s verify that the Flask application serves traffic. We’ll need the IP address of the Flask unit listed in the output of juju status. In the example terminal output above, the IP address is 10.1.0.92. We can also grab this information generically using jq:

FLASK_IP=$(juju status --format json | jq -r '.applications."flask-k8s".units."flask-k8s/0".address')

Test the deployment using cURL:

curl $FLASK_IP:8000

If the deployment is successful, the output should show HTML containing <title>Welcome to flask-k8s Charm</title>.

Now we can check the external hostname set up by the Gateway API integrator charm to verify that traffic is routed through it. To determine the external URL, let’s use the charm’s get-proxied-endpoints action:

juju run gateway-api-integrator/0 get-proxied-endpoints

The action lists all endpoints proxied by Gateway API integrator. The command should output something similar to:

ubuntu@charm-tutorial-vm:~$
juju run gateway-api-integrator/0 get-proxied-endpoints
Running operation 3 with 1 task
  - task 4 on unit-gateway-api-integrator-0

Waiting for task 4...
proxied-endpoints: '{"flask-k8s": {"url": "https://ingress.internal/gateway-api-integrator-tutorial-flask-k8s"},
  "gateway-api-integrator": {"url": "https://ingress.internal"}}'

Notice that Gateway API integrator has set up the URL https://ingress.internal/gateway-api-integrator-tutorial-flask-k8s for our Flask application in this example output. The URL contains the hostname we configured earlier (ingress.internal), the name of the Juju model (gateway-api-integrator-tutorial), and the name of the Flask application (flask-k8s).

Once again we’ll test with cURL:

curl -k --resolve ingress.internal:443:$PREFSRC \
   https://ingress.internal/gateway-api-integrator-tutorial-flask-k8s

The cURL command is more complex now:

  • Since we’re using a self-signed certificate, we must tell cURL not to verify the certificate by passing the -k flag.

  • The hostname must resolve through DNS, so we’ve passed the --resolve flag.

If the routing is successful, the output should show the same HTML containing <title>Welcome to flask-k8s Charm</title> like before. We have confirmed that traffic is being routed through Gateway API integrator.

Visit in a browser

The HTML output from cURL can be difficult to read in a terminal. As a final step, let’s visit the Flask application in a browser.

Tip

If you’re using a Multipass VM for this tutorial, you’ll need to replicate the DNS resolve behavior by adding the ingress.internal domain to your local hosts file.

First, get the IP of your Multipass VM. Outside of the VM, run:

multipass info charm-tutorial-vm

Save the VM IP to an environment variable VM_IP. Then, update your hosts file:

echo "$VM_IP ingress.internal" | sudo tee -a /etc/hosts

Access the Flask application at https://ingress.internal/gateway-api-integrator-tutorial-flask-k8s in your browser. Your browser may display a warning about the connection’s security because we used a self-signed certificate. You can safely ignore this warning.

You should see the message, “Welcome to flask-k8s Charm”.

Clean up the environment

Congratulations! You successfully deployed the Gateway API integrator charm, integrated it with a basic Flask application, and verified that the routing works by accessing the external URL.

You can clean up your environment by following this guide: Tear down your deployment

If you used a Multipass VM for this tutorial, remove the ingress.internal domain from your local /etc/hosts file.

Next steps

You achieved a basic deployment of the Gateway API integrator charm using the ingress relation endpoint. If you want to go farther in your deployment or learn more about the charm, check out these pages: