Back to blog

Membuat Domain pada Kubernetes menjadi HTTPS menggunakan cert-manager

September 27, 2022

By Yudi Yuswita Sunarto

Certmanager Nahhh

Kali ini catatan yang menurut saya agak banyak langkah, tanpa basa basi please welcome Membuat Domain pada Kubernetes menjadi HTTPS menggunakan cert-manager. Ada 2 bagian yang perlu diperhatikan

  1. ingress
  2. cert-manager

Ingress

Pertama kita perlu menginstall ingress pada cluster k8s terlebih dahulu, untuk metode installnya bisa menggunakan helm atau jika kita menggunakan digitalocean bisa menggunakan fitur Install Kubernetes 1-Click Apps. Install ingress melalui helm:

helm upgrade --install ingress-nginx ingress-nginx \
  --repo https://kubernetes.github.io/ingress-nginx \
  --namespace ingress-nginx --create-namespace

Cert-Manager

Sama halnya dengan Ingress jika kita menggunakan DO bisa menginstall melalui Install Kubernetes 1-Click Apps. Jika menginstall melalui helm berikut perintahnya

helm repo add jetstack https://charts.jetstack.io
helm repo update
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.9.1/cert-manager.crds.yaml
helm install \
  cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --version v1.9.1 \
  # --set installCRDs=true

Oke, setelah ingress dan cert-manager telah terinstall. Coba untuk membuat ingress tanpa https sesuai dengan service yang sudah terdeploy. Contoh ingress yaml:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: RELEASE-NAME-demo
  labels:
    helm.sh/chart: demo-0.1.0
    app.kubernetes.io/name: demo
    app.kubernetes.io/instance: RELEASE-NAME
    app.kubernetes.io/version: "0.28.0"
    app.kubernetes.io/managed-by: Helm
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
    - host: "k8s-backend.demo.id"
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: RELEASE-NAME-demo
                port:
                  number: 80

Pastikan sudah bisa mengakses domain yang sudah dibuat melalui ingress, contoh hasil ingress sudah terbuat semacam ini:

NAMESPACE   NAME          CLASS    HOSTS                   ADDRESS        PORTS     AGE
default     demo          nginx    k8s-backend.demo.id    167.x.x.x       80        21h

Issuer

Berfungsi untuk request dan genarate TLS yang valid untuk ingress yang sedang digunakan, dalam hal ini yaitu ingress-nginx. Berikut contoh file yaml issuer untuk staging:

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
 name: letsencrypt-staging
 namespace: cert-manager
spec:
 acme:
   # The ACME server URL
   server: https://acme-staging-v02.api.letsencrypt.org/directory
   # Email address used for ACME registration
   email: yudi@mail.com
   # Name of a secret used to store the ACME account private key
   privateKeySecretRef:
     name: letsencrypt-staging
   # Enable the HTTP-01 challenge provider
   solvers:
   - http01:
       ingress:
         class:  nginx

Apply file yaml tersebut, untuk mengecek apakah sudah terpasang bisa menggunakan perintah kubectl get clusterissuers.cert-manager.io. Buat juga file yaml untuk production

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
  namespace: cert-manager
spec:
  acme:
    # The ACME server URL
    server: https://acme-v02.api.letsencrypt.org/directory
    # Email address used for ACME registration
    email: yudi@mail.com
    # Name of a secret used to store the ACME account private key
    privateKeySecretRef:
      name: letsencrypt-prod
    # Enable the HTTP-01 challenge provider
    solvers:
    - http01:
        ingress:
          class: nginx

Setelah kedua file yaml tersebut terpasang, tambahkan pada file ingress yang tadi sudah dibuat sehingga menjadi seperti ini ingress-https.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: RELEASE-NAME-demo
  labels:
    helm.sh/chart: demo-0.1.0
    app.kubernetes.io/name: demo
    app.kubernetes.io/instance: RELEASE-NAME
    app.kubernetes.io/version: "0.28.0"
    app.kubernetes.io/managed-by: Helm
  annotations:
    kubernetes.io/ingress.class: nginx
    cert-manager.io/cluster-issuer: letsencrypt-staging
spec:
  tls:
    - hosts:
        - "k8s-backend.demo.id"
      secretName: demo-tls
  rules:
    - host: "k8s-backend.demo.id"
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: RELEASE-NAME-demo
                port:
                  number: 80

Agar generate ssl aman dan untuk menghindari limit request kita menggunakan cluster-issuer staging terlebih dahulu. Jika sudah dirasa aman dan log pada pod cert-manager tidak ada masalah, baru pindah ke letsencrypt yang prod.

Jika tidak nampak error harusnya sudah bisa berjalan dan https sudah terinstall pada domain kita. yuhuuuu

sumber dan referensi:

https://marketplace.digitalocean.com/apps/cert-manager https://www.digitalocean.com/community/tutorials/how-to-set-up-an-nginx-ingress-with-cert-manager-on-digitalocean-kubernetes