cert-manager for cilium gateway
Table of Content
- Prerequisite
- Steps
- cert-manager helm chart
- values file
- script to prepare flux helm repo and helm release
- cert-manager namespace
- infra-controller kustomization
- cert-manager installed
- cert-manager verification test
-
Configure Issuer
-
Configure cilium gateway to use the certificate issuer
- Add HTTPRoute
- Result
- Outro
cert-manager for cilium gateway¶
Cert-manager is a powerful tool for automating the management of TLS certificates, making it ideal for setting up HTTPS gateways in kubernetes clusters.
I have setup Cilium Gateway to handle plain http access in my previous post. I will continue on to setup https access on the cilium gateway using cert-manager in this post.
previous post on setting up cilium gateway
And just as a reference, I have setup the same with Calico, MetalLB, and NGINX Gateway Fabric instead of Cilium a while ago, and here is the link.
post on the previous setup with calico & ngf
Prerequisite¶
- GitOps is setup using fluxcd and GitLab
- Five flux kustomizations setup
./clusters/lab-hlv3
as flux-system created during bootstrap process./infrastructure/lab-hlv3/controllers
as infra-controllers./infrastructure/lab-hlv3/configs
as infra-configs./apps/lab-hlv3
as apps./sops/lab-hlv3
as sops
- Cilium Gateway setup from the previous post
- Gateway API v1.2.0 installed
- Cilium Gateway created, IP address assigned (dummy 192.0.2.83 in this post) and exposed to the LAN using L2Announcement
- traefik/whoami pod deployed along with service and HTTPRoute to connect to the http listener on the gateway
Steps¶
- On infra-controllers
- Install cert-manager as helm release
- On infra-configs
- Add Issuer
- Update Gateway config to work along with the cert-manager Issuer
- Update Gateway config to add https listener
- Add HTTPRoute to connect the https listener and the target service, traefik/whoami
cert-manager helm chart¶
Add the jetstack helm repository which stores cert-manager helm chart.
Here is the list of available charts in jetstack.
# run helm repo update to update repository information
$ helm search repo jetstack
NAME CHART VERSION APP VERSION DESCRIPTION
jetstack/cert-manager v1.17.1 v1.17.1 A Helm chart for cert-manager
jetstack/cert-manager-approver-policy v0.19.0 v0.19.0 approver-policy is a CertificateRequest approve...
jetstack/cert-manager-csi-driver v0.10.2 v0.10.2 cert-manager csi-driver enables issuing secretl...
jetstack/cert-manager-csi-driver-spiffe v0.8.2 v0.8.2 csi-driver-spiffe is a Kubernetes CSI plugin wh...
jetstack/cert-manager-google-cas-issuer v0.9.0 v0.9.0 A Helm chart for jetstack/google-cas-issuer
jetstack/cert-manager-istio-csr v0.14.0 v0.14.0 istio-csr enables the use of cert-manager for i...
jetstack/cert-manager-trust v0.2.1 v0.2.0 DEPRECATED: The old name for trust-manager. Use...
jetstack/finops-dashboards v0.0.5 0.0.5 A Helm chart for Kubernetes
jetstack/finops-policies v0.0.6 v0.0.6 A Helm chart for Kubernetes
jetstack/finops-stack v0.0.5 0.0.3 A FinOps Stack for Kubernetes
jetstack/trust-manager v0.16.0 v0.16.0 trust-manager is the easiest way to manage TLS ...
jetstack/version-checker v0.8.6 v0.8.6 A Helm chart for version-checker
values file¶
Use helm show
command to download values file for the specific cert-manager helm chart version. I will be installing cert-manager under infra-controllers flux kustomization, so that's also where I store the values file.
Although I can download it anytime, I like to keep a copy of the values file before editing in my GitOps repository.
# on gitops repo
cd infrastructure/lab-hlv3/controllers/default-values
helm show values jetstack/cert-manager --version v1.17.1 > cert-manager-v1.17.1-values.yaml
cp cert-manager-v1.17.1-values.yaml ../values/cert-manager-values.yaml
# and edit values file at ./infrastructure/lab-hlv3/controllers/values/cert-manager-values.yaml
Here is the list of changes made to the values file:
- to install cert-manager crds
- crds.enabled: true
- to enable gateway api support
- config.apiVersion: controller.config.cert-manager.io/v1alpha1
- config.kind: ControllerConfiguration
- config.enableGatewayAPI: true
- to specify external DNS server to process DNS01 challenges
- dns01RecursiveNameservers: "1.1.1.1:53,1.0.0.1:53"
- dns01RecursiveNameserversOnly: true
- and optionally, I have changed the registry to pull images from
script to prepare flux helm repo and helm release¶
https://fluxcd.io/flux/guides/helmreleases/
To install something with helm and fluxcd GitOps, the brief steps are to (1) add HelmRepository
and (2) add HelmRelease
using the helm repository added to the flux system on the kubernetes cluster, and the flux system pulls the helm chart and deploys it.
These are all CRDs for fluxcd, and there are flux commands to create these manifests (flux create source helm
and flux create helmrelease
).
$ kubectl api-resources | grep fluxcd
helmreleases hr helm.toolkit.fluxcd.io/v2 true HelmRelease
kustomizations ks kustomize.toolkit.fluxcd.io/v1 true Kustomization
alerts notification.toolkit.fluxcd.io/v1beta3 true Alert
providers notification.toolkit.fluxcd.io/v1beta3 true Provider
receivers notification.toolkit.fluxcd.io/v1 true Receiver
buckets source.toolkit.fluxcd.io/v1 true Bucket
gitrepositories gitrepo source.toolkit.fluxcd.io/v1 true GitRepository
helmcharts hc source.toolkit.fluxcd.io/v1 true HelmChart
helmrepositories helmrepo source.toolkit.fluxcd.io/v1 true HelmRepository
ocirepositories ocirepo source.toolkit.fluxcd.io/v1beta2 true OCIRepository
$ flux create source helm --help
The create source helm command generates a HelmRepository resource and waits for it to fetch the index.
For private Helm repositories, the basic authentication credentials are stored in a Kubernetes secret.
Usage:
flux create source helm [name] [flags]
Examples:
# Create a source for an HTTPS public Helm repository
flux create source helm podinfo \
--url=https://stefanprodan.github.io/podinfo \
--interval=10m
$ flux create helmrelease --help
The helmrelease create command generates a HelmRelease resource for a given HelmRepository source.
Usage:
flux create helmrelease [name] [flags]
Aliases:
helmrelease, hr
Examples:
# Create a HelmRelease with a chart from a HelmRepository source
flux create hr podinfo \
--interval=10m \
--source=HelmRepository/podinfo \
--chart=podinfo \
--chart-version=">4.0.0"
As you can see from the examples in the --help
, they can be lengthy.
Whenever chart version or values file content change, you need to run flux create
to generate required flux manifests. By having the script ready, you can just execute the script to generate the updated flux helm manifests.
And so here is the script I use for all the helm releases I want to install using fluxcd. This will create ./infrastructure/lab-hlv3/controllers/cert-manager.yaml
including both flux HelmRepository
and HelmRelease
manifests, and I can just include this one file in my infra-controllers flux kustomization. Whenever I update the parameters in the values file, I run the shell script and push/commit the change to the cert-manager.yaml file, and the helm release will be upgraded. As for the helm chart version changes, I will have to update the --chart-version
value in the shell script.
# on gitops repo
mkdir infrastructure/lab-hlv3/controllers/scripts
cd infrastructure/lab-hlv3/controllers/scripts
# script to generate a file containing flux helmrepo and hr
cat <<'EOF' >cert-manager.sh
#!/bin/bash
# add flux helmrepo to the manifest
flux create source helm cert-manager \
--url=https://charts.jetstack.io \
--interval=1h0m0s \
--export >../cert-manager.yaml
# add flux helm release to the manifest including the customized values.yaml file
flux create helmrelease cert-manager \
--interval=10m \
--target-namespace=cert-manager \
--source=HelmRepository/cert-manager \
--chart=cert-manager \
--chart-version=v1.17.1 \
--values=../values/cert-manager-values.yaml \
--export >>../cert-manager.yaml
EOF
# run the script to generate the file
chmod u+x cert-manager.sh
./cert-manager.sh
cert-manager namespace¶
In the flux helmrelease manifest above, the target namespace to install cert-manager is set to "cert-manager", and this namespace must be created separately as --create-target-namespace
is not set.
I prefer this way so that whenever I want to make changes to the namespace itself, I'm certain I'm not bothering with the helm chart installation.
# ./clusters/lab-hlv3/namespaces/cert-manager.yaml
---
kind: Namespace
apiVersion: v1
metadata:
name: cert-manager
labels:
service: cert-manager
type: infrastructure
infra-controller kustomization¶
Finally, update the infra-controller kustomization to include the generated flux helmrepo and helmrelease manifests.
# ./infrastructure/lab-hlv3/controllers/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- cm-placeholder.yaml
### crds
# gateway api
# version 1.2.0
- crds/gateway-api/standard/standard-install-v1.2.0.yaml
- crds/gateway-api/experimental/gateway.networking.k8s.io_tlsroutes-v1.2.0.yaml
### infra-controllers
- cert-manager.yaml
cert-manager installed¶
These are the changes you can confirm.
$ flux get all
NAME REVISION SUSPENDED READY MESSAGE
gitrepository/flux-system main@sha1:5883ff2a False True stored artifact for revision 'main@sha1:5883ff2a'
NAME REVISION SUSPENDED READY MESSAGE
helmrepository/cert-manager sha256:f3211071 False True stored artifact: revision 'sha256:f3211071'
NAME REVISION SUSPENDED READY MESSAGE
helmchart/flux-system-cert-manager v1.17.1 False True pulled 'cert-manager' chart with version 'v1.17.1'
NAME REVISION SUSPENDED READY MESSAGE
helmrelease/cert-manager v1.17.1 False True Helm install succeeded for release cert-manager/cert-manager-cert-manager.v1 with chart [email protected]
NAME REVISION SUSPENDED READY MESSAGE
kustomization/apps main@sha1:5883ff2a False True Applied revision: main@sha1:5883ff2a
kustomization/flux-system main@sha1:5883ff2a False True Applied revision: main@sha1:5883ff2a
kustomization/infra-configs main@sha1:5883ff2a False True Applied revision: main@sha1:5883ff2a
kustomization/infra-controllers main@sha1:5883ff2a False True Applied revision: main@sha1:5883ff2a
$ kubectl get all -n cert-manager
NAME READY STATUS RESTARTS AGE
pod/cert-manager-cert-manager-cainjector-86cd99655f-44tn7 1/1 Running 0 2m19s
pod/cert-manager-cert-manager-d56b496b8-ssmmr 1/1 Running 0 2m19s
pod/cert-manager-cert-manager-webhook-54696f8b94-x2jxk 1/1 Running 0 2m19s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/cert-manager-cert-manager ClusterIP 10.96.243.72 <none> 9402/TCP 2m19s
service/cert-manager-cert-manager-cainjector ClusterIP 10.96.213.160 <none> 9402/TCP 2m20s
service/cert-manager-cert-manager-webhook ClusterIP 10.96.164.115 <none> 443/TCP,9402/TCP 2m19s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/cert-manager-cert-manager 1/1 1 1 2m19s
deployment.apps/cert-manager-cert-manager-cainjector 1/1 1 1 2m19s
deployment.apps/cert-manager-cert-manager-webhook 1/1 1 1 2m19s
NAME DESIRED CURRENT READY AGE
replicaset.apps/cert-manager-cert-manager-cainjector-86cd99655f 1 1 1 2m19s
replicaset.apps/cert-manager-cert-manager-d56b496b8 1 1 1 2m19s
replicaset.apps/cert-manager-cert-manager-webhook-54696f8b94 1 1 1 2m19s
$ kubectl api-resources | grep cert
challenges acme.cert-manager.io/v1 true Challenge
orders acme.cert-manager.io/v1 true Order
certificaterequests cr,crs cert-manager.io/v1 true CertificateRequest
certificates cert,certs cert-manager.io/v1 true Certificate
clusterissuers cert-manager.io/v1 false ClusterIssuer
issuers cert-manager.io/v1 true Issuer
certificatesigningrequests csr certificates.k8s.io/v1 false CertificateSigningRequest
cert-manager verification test¶
https://cert-manager.io/docs/installation/kubectl/#verify
Run the verification test described in the link above and see if the installation is successful.
Configure Issuer¶
https://cert-manager.io/docs/configuration/acme/
Next I am going to setup the issuer.
The ACME Issuer type represents a single account registered with the Automated Certificate Management Environment (ACME) Certificate Authority server.
Here is basically what needs to be done:
- tell ACME system how I am going to prove that I am the rightful domain owner for the certificates I am going to request signs for
I have transferred my domain from Google Domains to Cloudflare a while ago, and since I'm still there I will be configuring my issuer to use Cloudflare DNS01 challenge method.
Cloudflare DNS01 Challenge¶
First obtain the API token with appropriate scope, and then create issuer.
https://cert-manager.io/docs/configuration/acme/dns01/cloudflare/#api-tokens
https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.Issuer
The required permissions and zone resources to set are as follows, as described in the link above:
- permissions
- zone - dns - edit
- zone - zone -read
- zone resources
- include - all zones
You do not want to place the API token without encryption on GitOps repository, so place the secret manifest in the SOPS directory, encrypt it, and commit and push.
(SOPS encryption setup for GitOps covered in this separate post)
# ./sops/lab-hlv3/gateway/cloudflare-api-token-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: cloudflare-api-token-secret
namespace: gateway
type: Opaque
stringData:
api-token: YOUR_API_TOKEN_HERE
Here is the issuer with the cloudflare dns01 details set. Update "EMAIL_ADDR" and .spec.acme.solvers[].selector.dnsZones[]
accordingly when you setup your own.
# ./infrastructure/lab-hlv3/configs/cert-manager/issuer.yaml
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: issuer
namespace: gateway
spec:
acme:
email: EMAIL_ADDR
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: issuer-account-key
solvers:
- dns01:
cloudflare:
email: EMAIL_ADDR
apiTokenSecretRef:
name: cloudflare-api-token-secret
key: api-token
selector:
dnsZones:
- "blink-1x52.net"
Make sure that this is included in the infra-configs kustomization.
# ./infrastructure/lab-hlv3/configs/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- cm-placeholder.yaml
# cilium gateway
- cilium/gateway.yaml
- cilium/ippools-cilium-gateway.yaml
- cilium/l2announcement-cilium-gateway.yaml
# cert-manager
# - cert-manager/cert-manager-test.yaml
# cloudflare dns01 issuer
- cert-manager/issuer.yaml
Once successfully created, you can see the issuer and its status like this.
# kubectl describe issuer issuer -n gateway
Status:
Acme:
......
Conditions:
Last Transition Time: 2025-03-31T01:21:13Z
Message: The ACME account was registered with the ACME server
Observed Generation: 1
Reason: ACMEAccountRegistered
Status: True
Type: Ready
Events: <none>
Configure cilium gateway to use the certificate issuer¶
Let's update the cilium gateway configuration.
To have the gateway to listen on http, I just had to add one listener for the http at .spec.listners[]
. Adding another one for https is almost the same.
See the whoami-kube-https
https listener added below.
- hostname is added and this is what's in the certificate and SNI, server name indicator, of the incoming traffic
- port has changed to 443
- protocol is HTTPS
.spec.listeners[].tls
is newly added- mode is terminate which is to do TLS offloading at the gateway and pass on plain http traffic to whatever connected via HTTPRoutes
.spec.listeners[].tls.certificateRefs
is the secret cert-manager process eventually creates once all the creation, request, and challenge processes are complete, so name it whatever you like
And there is one more important thing to add to the gateway manifest to have cert-manager work together with the gateway. Adding the annotation cert-manager.io/issuer
with the name of the issuer created in the gateway namespace does the job. I have just created an issuer named "issuer" in the previous step and that's what I need to set.
# ./infrastructure/lab-hlv3/configs/cilium/gateway.yaml
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: cilium-gateway
namespace: gateway
annotations:
cert-manager.io/issuer: issuer
spec:
gatewayClassName: cilium
addresses:
- type: IPAddress
value: 192.0.2.83
listeners:
- name: whoami-kube-http
hostname: whoami-kube.lab.blink-1x52.net
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
gateway: cilium
- name: whoami-kube-https
hostname: whoami-kube.lab.blink-1x52.net
port: 443
protocol: HTTPS
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
gateway: cilium
tls:
mode: Terminate
certificateRefs:
- name: tls-whoami-kube
kind: Secret
namespace: gateway
What happens next?¶
Once the gateway is updated to work with the issuer, and a valid TLS listener added, cert-manager catches it and process everything needed to obtain the signed TLS certificate.
TLS certificate and key¶
Let's look at the end state first.
Check the secret by the name specified in the tls certificate ref for the https listener, and you will see the kubernetes TLS secret.
https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets
# kubectl get secret tls-whoami-kube -n gateway -o yaml
apiVersion: v1
kind: Secret
type: kubernetes.io/tls
metadata:
annotations:
cert-manager.io/alt-names: whoami-kube.lab.blink-1x52.net
cert-manager.io/certificate-name: tls-whoami-kube
cert-manager.io/common-name: whoami-kube.lab.blink-1x52.net
cert-manager.io/ip-sans: ""
cert-manager.io/issuer-group: cert-manager.io
cert-manager.io/issuer-kind: Issuer
cert-manager.io/issuer-name: issuer
cert-manager.io/uri-sans: ""
creationTimestamp: "2025-03-31T02:08:36Z"
labels:
controller.cert-manager.io/fao: "true"
name: tls-whoami-kube
namespace: gateway
resourceVersion: "3969674"
uid: ec65b140-027b-4a75-91f5-a80709f36cc7
data:
tls.key: ...
tls.crt: ...
What's happening in between?¶
The process flow diagram is available in the official documents:
- https://cert-manager.io/docs/usage/gateway/#inner-workings-diagram-for-developers
- https://cert-manager.io/docs/usage/certificate/#inner-workings-diagram-for-developers
- https://cert-manager.io/docs/usage/certificaterequest/#inner-workings-diagram-for-developers
You'd add one https listener on the gateway and the TLS certificate for the specified hostname gets automatically created. Here is what's happening in brief:
- "Certificate" gets created
- you can say it's an empty box as of this moment
- "Certificate Request" gets created
- "Order" gets created, and it works with the Issuer to spin up the "Challenge" to complete the DNS01 challenge to get the official signed certificate and key
- The TLS cert & key secret gets created by the name specified in the gateway listener certificateRefs
- "Certificate" status gets updated to ready state
describe challenge¶
Challenge disappears once the process is over. Below is what I captured during the process.
See the status. The challenge is "Presented: true", "Processing: true", but "State: pending" because the DNS01 challenge record was not confirmed yet at the moment I captured this.
$ kubectl describe challenges -n gateway
Name: tls-whoami-kube-1-3711042244-1698055298
Namespace: gateway
Labels: <none>
Annotations: <none>
API Version: acme.cert-manager.io/v1
Kind: Challenge
Metadata:
Creation Timestamp: 2025-03-31T01:54:16Z
Finalizers:
acme.cert-manager.io/finalizer
Generation: 1
Owner References:
API Version: acme.cert-manager.io/v1
Block Owner Deletion: true
Controller: true
Kind: Order
Name: tls-whoami-kube-1-3711042244
UID: b3aee648-c1ab-4827-a9c3-42ef041f5456
Resource Version: 3962141
UID: 5121de47-99a5-4010-86a1-c991a40708f3
Spec:
Authorization URL: https://acme-v02.api.letsencrypt.org/acme/authz/xxx/xxx
Dns Name: whoami-kube.lab.blink-1x52.net
Issuer Ref:
Group: cert-manager.io
Kind: Issuer
Name: issuer
Key: KEY_HERE
Solver:
dns01:
Cloudflare:
API Token Secret Ref:
Key: api-token
Name: cloudflare-api-token-secret
Email: EMAIL_ADDR
Selector:
Dns Zones:
blink-1x52.net
Token: TOKEN_HERE
Type: DNS-01
URL: CHALLENGE_URL_HERE
Wildcard: false
Status:
Presented: true
Processing: true
Reason: Waiting for DNS-01 challenge propagation: DNS record for "whoami-kube.lab.blink-1x52.net" not yet propagated
State: pending
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Started 13m cert-manager-challenges Challenge scheduled for processing
Normal Presented 13m cert-manager-challenges Presented challenge using DNS-01 challenge mechanism
Add HTTPRoute¶
Let us next add HTTPRoute in order to connect the https listener and the existing whoami service.
It is almost identical with the plain http HTTPRoute. The only difference is that this one is pointing to the https listener in .spec.parentRefs[].sectionName
.
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: whoami-https
namespace: testbed
spec:
parentRefs:
- name: cilium-gateway
sectionName: whoami-kube-https
namespace: gateway
hostnames:
- "whoami-kube.lab.blink-1x52.net"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: whoami
port: 80
Result¶
Below is the curl command result of the https access (with dummy ipaddr in 192.0.2.x).
#$ curl -v https://whoami-kube.lab.blink-1x52.net
* Host whoami-kube.lab.blink-1x52.net:443 was resolved.
* ...
* Connected to whoami-kube.lab.blink-1x52.net (192.0.2.83) port 443
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: /etc/ssl/certs
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / X25519 / RSASSA-PSS
* ALPN: server did not agree on a protocol. Uses default.
* Server certificate:
* subject: CN=whoami-kube.lab.blink-1x52.net
* start date: Mar 31 01:10:01 2025 GMT
* expire date: Jun 29 01:10:00 2025 GMT
* subjectAltName: host "whoami-kube.lab.blink-1x52.net" matched cert's "whoami-kube.lab.blink-1x52.net"
* issuer: C=US; O=Let's Encrypt; CN=R11
* SSL certificate verify ok.
* Certificate level 0: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
* Certificate level 1: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
* Certificate level 2: Public key type RSA (4096/152 Bits/secBits), signed using sha256WithRSAEncryption
* using HTTP/1.x
> GET / HTTP/1.1
> Host: whoami-kube.lab.blink-1x52.net
> User-Agent: curl/8.5.0
> Accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
< HTTP/1.1 200 OK
< date: Mon, 31 Mar 2025 05:09:34 GMT
< content-length: 339
< content-type: text/plain; charset=utf-8
< x-envoy-upstream-service-time: 0
< server: envoy
<
Hostname: whoami
IP: 127.0.0.1
IP: ::1
IP: 10.0.3.170
IP: fe80::e834:eff:fe1f:44f3
RemoteAddr: 10.0.3.174:41057
GET / HTTP/1.1
Host: whoami-kube.lab.blink-1x52.net
User-Agent: curl/8.5.0
Accept: */*
X-Envoy-Internal: true
X-Forwarded-For: IPADDR_OF_THE_HOST_EXECUTING_CURL
X-Forwarded-Proto: https
X-Request-Id: d3e749cd-70ac-4e83-ab61-28b132dc9a61
* Connection #0 to host whoami-kube.lab.blink-1x52.net left intact
Outro¶
I've automated TLS certificate management with cert-manager to secure web access through Cilium Gateway. Combining this with GitOps makes deployments consistent and simplifies operations. The benefits of this automation really add up as your Kubernetes environment grows.
Now I cannot stop emphasizing this enough, but adding HTTPS access to your service running on the Kubernetes cluster is super easy – it only takes two steps:
- Add an HTTPS listener to the gateway
- Add an HTTP route to connect that listener to your target service
Cert-manager automatically renews the certificates, which is great, but I guess I'll be setting up a periodic check to report certificate expiration dates for extra peace of mind.