Cert-Manager: TLS for ingress
A common use-case for cert-manager is requesting TLS signed certificates to secure your ingress resources.
Installation
The easiest way is to use helm charts.
helm repo add jetstack https://charts.jetstack.io
root@master>helm repo list
NAME URL
stable https://charts.helm.sh/stable
jetstack https://charts.jetstack.io
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.7.1 \
--set prometheus.enabled=false \
--set webhook.timeoutSeconds=4 \
--set installCRDs=true
Once deployed you can see the k8s objects deployed
root@master>k get all -n cert-manager
NAME READY STATUS RESTARTS AGE
pod/cert-manager-86f4f985d6-ntgtf 1/1 Running 0 7d23h
pod/cert-manager-cainjector-56bc5f744c-tdhx6 1/1 Running 0 7d23h
pod/cert-manager-webhook-997b5dd88-4jbmf 1/1 Running 0 7d23h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/cert-manager ClusterIP 10.100.35.73 <none> 9402/TCP 67d
service/cert-manager-webhook ClusterIP 10.96.67.112 <none> 443/TCP 67d
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/cert-manager 1/1 1 1 67d
deployment.apps/cert-manager-cainjector 1/1 1 1 67d
deployment.apps/cert-manager-webhook 1/1 1 1 67d
NAME DESIRED CURRENT READY AGE
replicaset.apps/cert-manager-57d89b9548 0 0 0 67d
replicaset.apps/cert-manager-86f4f985d6 1 1 1 7d23h
replicaset.apps/cert-manager-cainjector-56bc5f744c 1 1 1 7d23h
replicaset.apps/cert-manager-cainjector-5bcf77b697 0 0 0 67d
replicaset.apps/cert-manager-webhook-997b5dd88 1 1 1 7d23h
replicaset.apps/cert-manager-webhook-9cb88bd6d 0 0 0 67d
Example
>kubectl get Issuers,ClusterIssuers,Certificates,CertificateRequests,Orders,Challenges -A
Issuers
NAMESPACE NAME READY AGE
cert-manager-test issuer.cert-manager.io/test-selfsigned True 7d21h
jenkins issuer.cert-manager.io/jenkins-selfsigned True 6d18h
spinnaker issuer.cert-manager.io/spinnaker-selfsigned True 7d21h
NAMESPACE NAME READY SECRET AGE
cert-manager-test certificate.cert-manager.io/selfsigned-cert True selfsigned-cert-tls 7d21h
jenkins certificate.cert-manager.io/jenkinsdevops.com True jenkinsdevops.com 6d18h
spinnaker certificate.cert-manager.io/devops.com True devops.com 7d19h
spinnaker certificate.cert-manager.io/selfsigned-cert True devops.com 7d21h
NAMESPACE NAME APPROVED DENIED READY ISSUER REQUESTOR AGE
cert-manager-test certificaterequest.cert-manager.io/selfsigned-cert-hnd85 True True test-selfsigned system:serviceaccount:cert-manager:cert-manager 7d21h
jenkins certificaterequest.cert-manager.io/jenkinsdevops.com-75hdn True True jenkins-selfsigned system:serviceaccount:cert-manager:cert-manager 6d18h
spinnaker certificaterequest.cert-manager.io/devops.com-g6b2m True True spinnaker-selfsigned system:serviceaccount:cert-manager:cert-manager 5d22h
spinnaker certificaterequest.cert-manager.io/devops.com-rz6db True True spinnaker-selfsigned system:serviceaccount:cert-manager:cert-manager 5d23h
spinnaker certificaterequest.cert-manager.io/devops.com-wzs4h True True spinnaker-selfsigned system:serviceaccount:cert-manager:cert-manager 5d22h
spinnaker certificaterequest.cert-manager.io/selfsigned-cert-mfggn True True spinnaker-selfsigned system:serviceaccount:cert-manager:cert-manager 7d21h
After Installation, Configure
The first thing you’ll need to configure after you’ve installed cert-manager is an issuer which you can then use to issue certificates.
Before you begin
Issuers
& ClusterIssuer
Issuers
, and ClusterIssuers
, are Kubernetes resources that represent certificate authorities (CAs) that are able to generate signed certificates by honoring certificate signing requests.
Example – Issuer
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: jenkins-selfsigned
namespace: jenkins
spec:
selfSigned: {}
Example – ClusterIssuer
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: selfsigned-cluster-issuer
spec:
selfSigned: {}
If you want to create a single Issuer
that can be consumed in multiple namespaces, you should consider creating a ClusterIssuer
resource.
Certificate
A Certificate
is a namespaced resource that references an Issuer
or ClusterIssuer
that determine what will be honoring the certificate request.
When a Certificate
is created, a corresponding CertificateRequest
resource is created by cert-manager containing the encoded X.509 certificate request, Issuer
reference, and other options based upon the specification of the Certificate
resource.
Securing Ingress
As I conclude the blog, let me use the deployed cert-manager to secure the TLS deployment for my spinnaker instance.
Supported Annotations in Ingress: https://cert-manager.io/docs/usage/ingress/#supported-annotations
In our example we will use mostly
cert-manager.io/issuer
cert-manager.io/cluster-issuer
Deployed Spinnaker Pods
root@master>k get pods -n spinnaker
NAME READY STATUS RESTARTS AGE
minio-5bbd54df5b-qnfvs 1/1 Running 0 8d
spin-clouddriver-ddd75554c-tts9z 1/1 Running 0 45h
spin-deck-649d97f44f-kp59x 1/1 Running 0 8d
spin-echo-9587cdc9d-gm7pt 1/1 Running 0 4d16h
spin-front50-7dbbb7668-qpr5f 1/1 Running 0 5d23h
spin-gate-69b9f88748-pppwm 1/1 Running 0 5d23h
spin-igor-6bcc768f9c-fzr8c 1/1 Running 0 47h
spin-orca-68ff75b6f8-r6872 1/1 Running 0 5d23h
spin-redis-864dff6b7-82m55 1/1 Running 0 8d
spin-rosco-68dc887685-sm9p8 1/1 Running 0 5d23h
Services
root@master>k get svc -n spinnaker
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
minio ClusterIP 10.96.179.180 <none> 9000/TCP 8d
spin-clouddriver ClusterIP 10.107.86.175 <none> 7002/TCP 8d
spin-deck ClusterIP 10.106.159.232 <none> 9000/TCP 8d
spin-echo ClusterIP 10.98.31.29 <none> 8089/TCP 8d
spin-front50 ClusterIP 10.106.148.148 <none> 8080/TCP 8d
spin-gate ClusterIP 10.105.124.157 <none> 8084/TCP 8d
spin-igor ClusterIP 10.99.29.79 <none> 8088/TCP 5d23h
spin-orca ClusterIP 10.103.240.238 <none> 8083/TCP 8d
spin-redis ClusterIP 10.99.134.213 <none> 6379/TCP 8d
spin-rosco ClusterIP 10.110.22.96 <none> 8087/TCP 8d
I will use the Ingress to expose the UI and API
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
haproxy.org/cors-allow-origin: "*.devops.com"
haproxy.org/ingress.class: haproxy
cert-manager.io/issuer: "spinnaker-selfsigned"
cert-manager.io/common-name: "devops.com"
name: spinnaker-ingress
namespace: spinnaker
spec:
ingressClassName: haproxy
rules:
- host: ui.devops.com
http:
paths:
- backend:
service:
name: spin-deck
port:
number: 9000
path: /
pathType: Prefix
- host: api.devops.com
http:
paths:
- backend:
service:
name: spin-gate
port:
number: 8084
path: /
pathType: Prefix
tls:
- hosts:
- ui.devops.com
- api.devops.com
secretName: devops.com
Please note the annotation cert-manager.io/issuer: "spinnaker-selfsigned"
applied to the ingress once the resource is created using kubectl create -f <yaml>
k get ing -n spinnaker
NAME CLASS HOSTS ADDRESS PORTS AGE
spinnaker-ingress haproxy ui.devops.com,api.devops.com,clouddriver.devops.com 10.98.117.100 80, 443 7d21h