This guide shows how to test HTTPS/TLS with self-signed certificates using cert-manager in your K3s cluster.
values.local.yaml*.dev.local pointing to your VM IPThe chart will create a selfsigned-issuer ClusterIssuer:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: selfsigned-issuer
spec:
selfSigned: {}
A Certificate will be automatically created for the HTTPS listener:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: drunk-dev-tls
namespace: default
spec:
secretName: drunk-dev-tls
issuerRef:
name: selfsigned-issuer
kind: ClusterIssuer
dnsNames:
- "*.dev.local"
The Gateway includes an HTTPS listener using the certificate:
listeners:
- name: https
hostname: "*.dev.local"
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- kind: Secret
name: drunk-dev-tls
Deploy/Upgrade the chart:
cd /Users/steven/_CODE/GIT/drunk.charts/drunk-k8s-gateway
helm upgrade --install drunk-k8s-gateway . -f values.local.yaml
Verify ClusterIssuer is ready:
kubectl get clusterissuer selfsigned-issuer
kubectl describe clusterissuer selfsigned-issuer
Expected output shows Ready=True
Check Certificate status:
kubectl get certificate drunk-dev-tls
kubectl describe certificate drunk-dev-tls
Wait for status Ready=True. cert-manager will automatically create the TLS secret.
Verify the TLS secret was created:
kubectl get secret drunk-dev-tls
kubectl describe secret drunk-dev-tls
Should show type: kubernetes.io/tls with tls.crt and tls.key data fields.
Check Gateway status:
kubectl get gateway drunk-dev-gateway
kubectl describe gateway drunk-dev-gateway
The HTTPS listener should show Programmed=True and ResolvedRefs=True.
Use the drunk-sample or any HTTPRoute-compatible app:
cd /Users/steven/_CODE/GIT/drunk.charts/drunk-sample
helm upgrade --install drunk-sample ../drunk-app -f values.yaml
Make sure your app’s HTTPRoute specifies:
spec:
parentRefs:
- name: drunk-dev-gateway
namespace: default
hostnames:
- "sample.dev.local"
# Test HTTPS (will show self-signed cert warning)
curl -k https://sample.dev.local
# View certificate details
curl -vk https://sample.dev.local 2>&1 | grep -A 10 "Server certificate"
The -k flag bypasses certificate verification (needed for self-signed certs).
Add to your /etc/hosts:
<VM_IP> sample.dev.local
Navigate to https://sample.dev.local
You’ll see a security warning about the self-signed certificate:
Once accepted, you’ll see the app over HTTPS
# Check cert-manager logs
kubectl logs -n cert-manager deploy/cert-manager -f
# Check Certificate events
kubectl describe certificate drunk-dev-tls
# Check Gateway events
kubectl describe gateway drunk-dev-gateway
# Check if secret exists and is referenced correctly
kubectl get secret drunk-dev-tls -o yaml
kubectl get httproute*.dev.localFor production, replace the self-signed issuer with Let’s Encrypt ACME:
certManager:
clusterIssuersEnabled: true
clusterIssuers:
- name: "letsencrypt-prod"
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: your-email@example.com
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
gatewayHTTPRoute:
parentRefs:
- name: drunk-dev-gateway
namespace: default
Then update the Gateway annotation:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod