feat(ingress): add public HTTPS ingress configuration with cert-manager support

This commit is contained in:
Cédric Verstraeten
2026-08-11 14:05:37 +00:00
parent d888d7e243
commit b44775ef2a
6 changed files with 202 additions and 1 deletions

View File

@@ -213,6 +213,73 @@ rerun after deleting or replacing the DocumentDB cluster.
These are public example credentials. Do not use this seed data in a production
deployment.
## Public HTTPS ingress
The [`ingress`](ingress) package installs ingress-nginx behind an
internet-facing AWS Network Load Balancer, installs cert-manager, and creates
Let's Encrypt certificates for exactly these routes:
| Host | Service |
| ---- | ------- |
| `aws-app.kerberos.lol` | `hub-frontend-svc:80` |
| `aws-api.kerberos.lol` | `hub-api-svc:8081` |
Keep the Hub chart's global `ingress` value disabled. The module owns these two
Ingress resources so that enabling public access does not also expose the Hub
administration services.
Install the controllers and resources:
```bash
./ingress/install.sh
```
The script prints the NLB hostname. Create both DNS records as CNAMEs pointing
to that hostname. You can retrieve it again with:
```bash
kubectl get service ingress-nginx-controller \
--namespace ingress-nginx \
--output jsonpath='{.status.loadBalancer.ingress[0].hostname}{"\n"}'
```
| DNS name | Type | Target |
| -------- | ---- | ------ |
| `aws-app.kerberos.lol` | CNAME | The ingress-nginx NLB hostname |
| `aws-api.kerberos.lol` | CNAME | The ingress-nginx NLB hostname |
cert-manager automatically retries its HTTP-01 challenges after DNS resolves;
do not delete pending CertificateRequests. Wait for both certificates:
```bash
kubectl wait --namespace kerberos-hub \
--for=condition=Ready certificate/aws-app-kerberos-lol-tls \
certificate/aws-api-kerberos-lol-tls \
--timeout=10m
```
Set Hub's public URLs with the non-secret values fragment after the certificates
are ready. Include the same private Hub and DocumentDB values used for the
original installation:
```bash
helm upgrade hub kerberos/hub \
--version 0.127.0 \
--namespace kerberos-hub \
--file your-hub-values.yaml \
--file hub-documentdb-values.yaml \
--file ingress/hub-public-values.yaml \
--atomic \
--wait
```
Verify both public endpoints:
```bash
curl --fail https://aws-api.kerberos.lol/health
curl --fail --output /dev/null https://aws-app.kerberos.lol/login
```
## Persistent volumes
The EBS CSI driver is installed, but EKS ships `gp2` as the default storage
@@ -238,8 +305,12 @@ EOF
## Tear down
```bash
# Remove the release first so its load balancers and volumes are cleaned up.
# Remove Kubernetes resources first so AWS load balancers and volumes are cleaned up.
kubectl delete -f ingress/hub-ingresses.yaml --ignore-not-found
helm uninstall hub -n kerberos-hub
kubectl delete -f ingress/cluster-issuer.yaml --ignore-not-found
helm uninstall cert-manager -n cert-manager
helm uninstall ingress-nginx -n ingress-nginx
terraform destroy
```

View File

@@ -0,0 +1,13 @@
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
privateKeySecretRef:
name: letsencrypt-prod-account-key
server: https://acme-v02.api.letsencrypt.org/directory
solvers:
- http01:
ingress:
ingressClassName: nginx

View File

@@ -0,0 +1,52 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hub-frontend-ingress
namespace: kerberos-hub
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
ingressClassName: nginx
rules:
- host: aws-app.kerberos.lol
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: hub-frontend-svc
port:
number: 80
tls:
- hosts:
- aws-app.kerberos.lol
secretName: aws-app-kerberos-lol-tls
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hub-api-ingress
namespace: kerberos-hub
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/proxy-body-size: 200m
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
ingressClassName: nginx
rules:
- host: aws-api.kerberos.lol
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: hub-api-svc
port:
number: 8081
tls:
- hosts:
- aws-api.kerberos.lol
secretName: aws-api-kerberos-lol-tls

View File

@@ -0,0 +1,7 @@
kerberoshub:
api:
schema: https
url: aws-api.kerberos.lol
frontend:
schema: https
url: aws-app.kerberos.lol

View File

@@ -0,0 +1,15 @@
controller:
config:
use-forwarded-headers: "true"
ingressClass: nginx
ingressClassResource:
default: false
enabled: true
name: nginx
service:
annotations:
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
service.beta.kubernetes.io/aws-load-balancer-type: nlb
externalTrafficPolicy: Local
type: LoadBalancer

View File

@@ -0,0 +1,43 @@
#!/usr/bin/env bash
set -euo pipefail
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly INGRESS_NGINX_VERSION="4.15.1"
readonly CERT_MANAGER_VERSION="v1.21.1"
for command in helm kubectl; do
if ! command -v "${command}" >/dev/null 2>&1; then
echo "Missing required command: ${command}" >&2
exit 1
fi
done
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx --force-update
helm repo add jetstack https://charts.jetstack.io --force-update
helm repo update ingress-nginx jetstack
helm upgrade --install ingress-nginx ingress-nginx/ingress-nginx \
--version "${INGRESS_NGINX_VERSION}" \
--namespace ingress-nginx \
--create-namespace \
--values "${SCRIPT_DIR}/ingress-nginx-values.yaml" \
--atomic \
--wait \
--timeout 15m
helm upgrade --install cert-manager jetstack/cert-manager \
--version "${CERT_MANAGER_VERSION}" \
--namespace cert-manager \
--create-namespace \
--set crds.enabled=true \
--atomic \
--wait \
--timeout 15m
kubectl apply --filename "${SCRIPT_DIR}/cluster-issuer.yaml"
kubectl wait --for=condition=Ready clusterissuer/letsencrypt-prod --timeout=2m
kubectl apply --filename "${SCRIPT_DIR}/hub-ingresses.yaml"
kubectl get service ingress-nginx-controller \
--namespace ingress-nginx \
--output jsonpath='Load balancer: {.status.loadBalancer.ingress[0].hostname}{"\n"}'