Certificate Management
Nantian Gateway’s gRPC control plane can use TLS or mutual TLS to secure the xDS stream between control plane and data plane. The Helm chart provides two certificate generation strategies: self-signed certificates for development and testing, or cert-manager integration for production.
For the TLS and mTLS settings that consume these certificates, see TLS / mTLS.
How certificate generation works
Section titled “How certificate generation works”The chart can generate the three certificates needed for gRPC mTLS: a CA certificate, a server certificate for the control plane, and a client certificate for each data plane. Generation happens once at install time and the results are stored in Kubernetes Secrets. On upgrades, the chart reuses the existing Secrets.
Certificate management is configured under the certs key:
certs: generate: true domain: "" selfSigned: caDurationDays: 365 serverDurationDays: 90 clientDurationDays: 90 certManager: enabled: false issuerRef: name: "" kind: ClusterIssuer group: cert-manager.io duration: 2160h renewBefore: 360hcerts values
Section titled “certs values”| Parameter | Type | Default | Description |
|---|---|---|---|
certs.generate | bool | true | Generate self-signed certificates at install time |
certs.domain | string | "" | Namespace-scoped domain for the gRPC server certificate SAN. Auto-computed from release name and namespace when left empty |
certs.selfSigned.caDurationDays | int | 365 | Validity period in days for the self-signed CA certificate |
certs.selfSigned.serverDurationDays | int | 90 | Validity period in days for the self-signed server certificate |
certs.selfSigned.clientDurationDays | int | 90 | Validity period in days for the self-signed client certificate |
certs.certManager.enabled | bool | false | Use cert-manager to issue certificates instead of self-signed generation |
certs.certManager.issuerRef.name | string | "" | Name of the cert-manager Issuer or ClusterIssuer |
certs.certManager.issuerRef.kind | string | "ClusterIssuer" | Kind of the cert-manager issuer (Issuer or ClusterIssuer) |
certs.certManager.issuerRef.group | string | "cert-manager.io" | API group of the cert-manager issuer |
certs.certManager.duration | string | "2160h" | Requested certificate duration (90 days) |
certs.certManager.renewBefore | string | "360h" | Renew certificate this far before expiry (15 days) |
Self-signed certificates (development)
Section titled “Self-signed certificates (development)”Set certs.generate: true to create self-signed certificates. This mode is suitable for development, testing, and non-production environments where you don’t have cert-manager running.
certs: generate: true selfSigned: caDurationDays: 365 serverDurationDays: 90 clientDurationDays: 90The chart creates three Secrets in the release namespace:
nantian-gw-grpc-ca: CA certificate and keynantian-gw-grpc-server-tls: gRPC server certificate and keynantian-gw-grpc-client-tls: gRPC client certificate and key
The domain for the server certificate’s SAN field is auto-computed as <release-name>.<namespace>.svc unless you set certs.domain explicitly. This ensures the data plane can verify the server’s identity when connecting to the cluster-internal gRPC service.
After enabling certificate generation, enable gRPC TLS in the control plane configuration so the certificates are actually used. The TLS / mTLS page covers those settings.
cert-manager integration (production)
Section titled “cert-manager integration (production)”For production environments with cert-manager installed, use certs.certManager.enabled: true. This delegates certificate lifecycle management to cert-manager, which handles issuance, rotation, and renewal automatically.
certs: certManager: enabled: true issuerRef: name: nantian-gw-ca-issuer kind: ClusterIssuer group: cert-manager.io duration: 2160h renewBefore: 360hYou must create the issuer before installing or upgrading the chart. A ClusterIssuer works across all namespaces, while an Issuer is scoped to a single namespace:
apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata: name: nantian-gw-ca-issuerspec: ca: secretName: nantian-gw-root-caThe chart creates three Certificate resources (CA, server, client) referencing your issuer. cert-manager handles the rest: it generates keys, requests certificates from the issuer, stores them in Secrets, and rotates them before they expire.
Choosing between modes
Section titled “Choosing between modes”| Mode | Use case | Rotation |
|---|---|---|
certs.generate: false | You provide your own Secrets or don’t use gRPC TLS | Manual |
certs.generate: true (default, self-signed) | Development, testing, ephemeral clusters | Manual (reinstall or rotate by hand) |
certs.certManager.enabled: true | Production clusters with cert-manager | Automatic via cert-manager |
When neither self-signed generation nor cert-manager is enabled, the chart expects you to have created the three TLS Secrets (nantian-gw-grpc-ca, nantian-gw-grpc-server-tls, nantian-gw-grpc-client-tls) yourself. This gives you full control over the certificate lifecycle using your own PKI or tooling.
Let’s Encrypt Integration
Section titled “Let’s Encrypt Integration”For public-facing gateway listeners, combine cert-manager with Let’s Encrypt for automated TLS certificate provisioning:
apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata: name: letsencrypt-prodspec: acme: server: https://acme-v02.api.letsencrypt.org/directory privateKeySecretRef: name: letsencrypt-prod-key solvers: - http01: ingress: class: nginxThen reference this issuer in your Gateway listener’s TLS configuration. cert-manager automatically requests, renews, and replaces certificates before expiry.
Troubleshooting
Section titled “Troubleshooting”Certificate not issued
Section titled “Certificate not issued”kubectl describe certificaterequest -n nantian-gwkubectl describe order -n nantian-gw # For ACME issuersCommon failure reasons:
- Issuer not found: Verify
certs.certManager.issuerRef.namematches an existingIssuerorClusterIssuer - DNS validation failed: For ACME, check that the domain’s DNS records are resolvable and the solver configuration is correct
- Rate limiting: Let’s Encrypt enforces rate limits (50 certificates per domain per week). Use the staging environment (
https://acme-staging-v02.api.letsencrypt.org/directory) for testing
Certificate about to expire
Section titled “Certificate about to expire”kubectl get certificate -n nantian-gw -o wideThe Ready and Renewal Time columns show certificate status. cert-manager renews certificates at renewBefore (default 15 days before expiry). Force manual renewal:
kubectl annotate certificate nantian-gw-grpc-server-tls -n nantian-gw \ cert-manager.io/issuer-kind=ClusterIssuer \ cert-manager.io/issuer-name=nantian-gw-ca-issuergRPC connection refused after certificate rotation
Section titled “gRPC connection refused after certificate rotation”If data planes lose connection after certificate rotation, they may be using a cached, expired certificate. Restart data plane pods to force a fresh connection:
kubectl rollout restart deployment/nantian-gw-dataplane -n nantian-gw