Charm architecture
The gateway-api-integrator
charm is very similar to the nginx-ingress-integrator
charm in that it provides Kubernetes ingress to charms that require it. However,
instead of interacting with the Kubernetes cluster using the Ingress API, it
uses the newer Gateway API
, which offers a more portable, expressive, and extensible integration with all
types of Kubernetes clusters.
The Gateway API integrator receives ingress requests using the ingress
relation.
It relies on the tls-certificates
relation to gather TLS certificates for
the gateway’s TLS configuration. Information about the backend application is
collected from the ingress
relation and combined with the TLS certificates
from the tls-certificates
relation. As a result, Kubernetes Service
resources,
Gateway
resources,
HTTPRoute
resources,
and Secret
resources
will be created to facilitate ingress as expected by the ingress requirer.
In designing this charm, we’ve leveraged the sidecar pattern for Kubernetes charms, but somewhat unusually we’re not actually deploying a workload container alongside our charm code. Instead, the charm code talks directly to the Kubernetes API to provision the appropriate Gateway API resource to enable traffic to reach the service in question.
As a result, if you run kubectl get pods
on a namespace named for the Juju
model you’ve deployed the gateway-api-integrator charm into, you’ll see
something like the following:
NAME READY STATUS RESTARTS AGE
gateway-api-integrator-0 1/1 Running 0 3h47m
This shows there is only one container for the charm code.
OCI images
Gateway Ingress Integrator charm doesn’t use any OCI image resources.
Juju events
For this charm, the following Juju events are observed:
config-changed
start
data-provided
fromingress
charm librarydata-removed
fromingress
charm librarycertificate-available
fromtls_certificates
charm librarycertificate-expiring
fromtls_certificates
charm librarycertificate-invalidated
fromtls_certificates
charm libraryall-certificates-invalidated
fromtls_certificates
charm libraryget-certificate-action
certificates-relation-created
certificates-relation-joined
certificates-relation-broken
Charm code overview
The src/charm.py
is the default entry point for a charm and has the
GatewayAPICharm
Python class which inherits from CharmBase. CharmBase is the
base class from which all Charms are formed, defined by Ops
(Python framework for developing charms).
See more in the Juju docs: Charm
Take, for example, when a configuration is changed by using the CLI.
- User runs the configuration command:
juju config gateway-api-integrator external-hostname=example.com
- A
config-changed
event is emitted. - In the
__init__
method is defined how to handle this event like this:
self.framework.observe(self.on.config_changed, self._on_config_changed)
- The method
_on_config_changed
, for its turn, will take the necessary actions such as waiting for all the relations to be ready and then configuring the containers.
Charm architecture diagram
The Gateway API Integrator charm uses the ingress
and tls_certificates
charm
libraries to handle charm relations. It also uses the lightkube
Python
Kubernetes client, which is wrapped in custom modules to reconcile the
Kubernetes resources necessary for ingress.
C4Context
System_Boundary(gateway-api-integrator, "Gateway API Integrator") {
Container_Boundary(charm-lib, "Charm Libraries") {
Component(tls-certificates-lib, "tls_certificates_interface.v3.tls_certificates")
Component(ingress-lib, "traefik_k8s.v2.ingress")
}
Container_Boundary(charm, "Charm Logic") {
Component(gateway-api-integrator-charm, "Gateway API Integrator Charm")
}
Container_Boundary(kubernetes-lib, "Kubernetes Libraries") {
Component(gateway, "Gateway")
Component(http-route, "HTTPRoute")
Component(secret, "Secret")
Component(service, "Service")
}
Rel(tls-certificates-lib, gateway-api-integrator-charm, "Server Cert")
Rel(ingress-lib, gateway-api-integrator-charm, "Ingress Spec")
Rel(gateway-api-integrator-charm, gateway, "Reconciliation")
Rel(gateway-api-integrator-charm, http-route, "Reconciliation")
Rel(gateway-api-integrator-charm, secret, "Reconciliation")
Rel(gateway-api-integrator-charm, service, "Reconciliation")
UpdateLayoutConfig($c4ShapeInRow="1", $c4BoundaryInRow="4")
UpdateRelStyle(tls-certificates-lib, gateway-api-integrator-charm, $offsetY="10", $offsetX="-40")
UpdateRelStyle(ingress-lib, gateway-api-integrator-charm, $offsetY="20", $offsetX="-80")
UpdateRelStyle(gateway-api-integrator-charm, gateway, $offsetY="10", $offsetX="-10")
UpdateRelStyle(gateway-api-integrator-charm, http-route, $offsetY="20", $offsetX="-10")
UpdateRelStyle(gateway-api-integrator-charm, secret, $offsetY="30", $offsetX="-10")
UpdateRelStyle(gateway-api-integrator-charm, service, $offsetY="40", $offsetX="-10")
}