Saturday, January 18, 2025

Cert Manager trong Kubernetes

-

Cert-manager là một controller trong Kubernetes được sử dụng để tạo và quản lý chứng chỉ SSL/TLS cho các ứng dụng chạy trên Kubernetes. Nó cho phép tự động hóa việc cài đặt, phát hành và quản lý chứng chỉ SSL/TLS miễn phí, đặc biệt là Let’s Encrypt. Cert-manager có thể tích hợp với nhiều trình cung cấp DNS, cho phép bạn sử dụng các tên miền do bên thứ ba quản lý và vẫn có thể sử dụng Let’s Encrypt để phát hành chứng chỉ. Nó giúp cho việc quản lý chứng chỉ SSL/TLS trở nên đơn giản và tiện lợi hơn khi triển khai ứng dụng trên Kubernetes.

Cert-manager không chỉ hỗ trợ cho Let’s Encrypt mà còn hỗ trợ cho nhiều loại chứng chỉ SSL/TLS khác nhau. Nó được thiết kế để làm việc với các CAs khác nhau bằng cách sử dụng một phương thức gọi là “ACME challenge” (một giao thức chung giữa các CA khác nhau để xác thực các yêu cầu cấp chứng chỉ). Điều này cho phép Cert-manager làm việc với bất kỳ CA nào hỗ trợ ACME challenge, và không chỉ giới hạn cho Let’s Encrypt. Tuy nhiên, Let’s Encrypt là một trong những CA phổ biến nhất được hỗ trợ bởi Cert-manager.

Cert-Manager hỗ trợ các loại chứng chỉ SSL/TLS sau:

  • ACME (Let’s Encrypt và bất kỳ ACME CA nào khác)
  • Vault
  • Venafi
  • HashiCorp Consul
  • Jetstack Certificate Manager (bao gồm cả self-signed certificate)
  • Self-signed certificates

Ngoài ra, bạn cũng có thể sử dụng Cert-Manager để tạo ra CertificateSigningRequest và yêu cầu ký bởi các CA tự lập.

Lưu, Cert-manager không hỗ trợ trực tiếp OpenSSL để phát hành các chứng chỉ SSL/TLS. Tuy nhiên, Cert-manager có thể được sử dụng để yêu cầu chứng chỉ từ một số ứng dụng như Let’s Encrypt, HashiCorp Vault, Venafi, Jetstack Certificate Manager, Vault PKI, ACME-based CAs, và Cloudflare Origin CA. Nếu bạn muốn sử dụng OpenSSL, bạn có thể sử dụng nó để tạo và tự ký một chứng chỉ SSL/TLS và sau đó sử dụng Cert-manager để sử dụng chứng chỉ đó trong Kubernetes.

Đây là link manifest của Cert-manage, trong kho Github của Cert-manager bạn sẽ thấy 2 file YAML cert-manager.yamlcert-manager.crds.yaml

https://github.com/cert-manager/cert-manager/releases

Cả hai file YAML cert-manager.yamlcert-manager.crds.yaml đều liên quan đến triển khai Cert-manager trên Kubernetes, tuy nhiên chúng có mục đích khác nhau:

  • cert-manager.crds.yaml: chứa các Custom Resource Definition (CRD) cho Cert-manager, định nghĩa các kiểu tài nguyên tùy chỉnh để quản lý các yêu cầu và chứng chỉ SSL/TLS. File này cần được triển khai trước khi triển khai Cert-manager.
  • cert-manager.yaml: chứa tất cả các phiên bản của Cert-manager, bao gồm các Pod, Service và các thành phần khác của Cert-manager. File này sử dụng các CRD đã được định nghĩa trước đó trong cert-manager.crds.yaml để quản lý các yêu cầu và chứng chỉ SSL/TLS.

Vì vậy, khi triển khai Cert-manager lần đầu tiên trên một cụm Kubernetes, bạn cần triển khai cert-manager.crds.yaml trước và sau đó triển khai cert-manager.yaml. Tuy nhiên, nếu bạn đã triển khai cert-manager.crds.yaml trước đó và chỉ muốn cập nhật Cert-manager, bạn có thể chỉ triển khai cert-manager.yaml.

Để triển khai Cert-manager trên cụm Kubernetes, bạn có thể làm theo các bước sau:

Đầu tiên tạo namespace cho Cert-manager bằng lệnh:

kubectl create namespace cert-manager

Đầu tiên mình sẽ tạo thư mục chứa cert-manager và di chuyển vào thư mục này.

mkdir cert-manager
cd cert-manager

Mình sẽ tải file manifest này về local bằng lệnh wget <link file manifest>.

wget https://github.com/cert-manager/cert-manager/releases/download/v1.12.0-beta.2/cert-manager.yaml
$ ll
total 432
drwxr-xr-x 2 root root   4096 May 15 02:41 ./
drwxr-xr-x 6 root root   4096 May 15 02:41 ../
-rw-r--r-- 1 root root 430229 May 12 16:27 cert-manager.yaml
$ kubectl apply --validate=false -f /home/cert-manager/cert-manager.yaml 
namespace/cert-manager created
customresourcedefinition.apiextensions.k8s.io/certificaterequests.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/certificates.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/challenges.acme.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/clusterissuers.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/issuers.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/orders.acme.cert-manager.io created
serviceaccount/cert-manager-cainjector created
serviceaccount/cert-manager created
serviceaccount/cert-manager-webhook created
configmap/cert-manager-webhook created
clusterrole.rbac.authorization.k8s.io/cert-manager-cainjector created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-issuers created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-clusterissuers created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-certificates created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-orders created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-challenges created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-ingress-shim created
clusterrole.rbac.authorization.k8s.io/cert-manager-view created
clusterrole.rbac.authorization.k8s.io/cert-manager-edit created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-approve:cert-manager-io created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-certificatesigningrequests created
clusterrole.rbac.authorization.k8s.io/cert-manager-webhook:subjectaccessreviews created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-cainjector created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-issuers created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-clusterissuers created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-certificates created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-orders created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-challenges created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-ingress-shim created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-approve:cert-manager-io created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-certificatesigningrequests created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-webhook:subjectaccessreviews created
role.rbac.authorization.k8s.io/cert-manager-cainjector:leaderelection created
role.rbac.authorization.k8s.io/cert-manager:leaderelection created
role.rbac.authorization.k8s.io/cert-manager-webhook:dynamic-serving created
rolebinding.rbac.authorization.k8s.io/cert-manager-cainjector:leaderelection created
rolebinding.rbac.authorization.k8s.io/cert-manager:leaderelection created
rolebinding.rbac.authorization.k8s.io/cert-manager-webhook:dynamic-serving created
service/cert-manager created
service/cert-manager-webhook created
deployment.apps/cert-manager-cainjector created
deployment.apps/cert-manager created
deployment.apps/cert-manager-webhook created
mutatingwebhookconfiguration.admissionregistration.k8s.io/cert-manager-webhook created
validatingwebhookconfiguration.admissionregistration.k8s.io/cert-manager-webhook created

Hoặc bạn cũng có thể triển khai trực tiếp bằng cách chèn url của file manifest kubectl apply --validate=false -f <link file manifest> cũng được.

$ kubectl apply --validate=false -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.0-beta.2/cert-manager.yaml
namespace/cert-manager unchanged
customresourcedefinition.apiextensions.k8s.io/certificaterequests.cert-manager.io unchanged
customresourcedefinition.apiextensions.k8s.io/certificates.cert-manager.io unchanged
customresourcedefinition.apiextensions.k8s.io/challenges.acme.cert-manager.io unchanged
customresourcedefinition.apiextensions.k8s.io/clusterissuers.cert-manager.io unchanged
customresourcedefinition.apiextensions.k8s.io/issuers.cert-manager.io unchanged
customresourcedefinition.apiextensions.k8s.io/orders.acme.cert-manager.io unchanged
serviceaccount/cert-manager-cainjector unchanged
serviceaccount/cert-manager unchanged
serviceaccount/cert-manager-webhook unchanged
configmap/cert-manager-webhook configured
clusterrole.rbac.authorization.k8s.io/cert-manager-cainjector unchanged
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-issuers unchanged
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-clusterissuers unchanged
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-certificates unchanged
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-orders unchanged
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-challenges unchanged
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-ingress-shim unchanged
clusterrole.rbac.authorization.k8s.io/cert-manager-view unchanged
clusterrole.rbac.authorization.k8s.io/cert-manager-edit unchanged
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-approve:cert-manager-io unchanged
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-certificatesigningrequests unchanged
clusterrole.rbac.authorization.k8s.io/cert-manager-webhook:subjectaccessreviews unchanged
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-cainjector unchanged
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-issuers unchanged
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-clusterissuers unchanged
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-certificates unchanged
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-orders unchanged
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-challenges unchanged
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-ingress-shim unchanged
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-approve:cert-manager-io unchanged
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-certificatesigningrequests unchanged
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-webhook:subjectaccessreviews configured
role.rbac.authorization.k8s.io/cert-manager-cainjector:leaderelection unchanged
role.rbac.authorization.k8s.io/cert-manager:leaderelection unchanged
role.rbac.authorization.k8s.io/cert-manager-webhook:dynamic-serving unchanged
rolebinding.rbac.authorization.k8s.io/cert-manager-cainjector:leaderelection unchanged
rolebinding.rbac.authorization.k8s.io/cert-manager:leaderelection configured
rolebinding.rbac.authorization.k8s.io/cert-manager-webhook:dynamic-serving configured
service/cert-manager unchanged
service/cert-manager-webhook unchanged
deployment.apps/cert-manager-cainjector unchanged
deployment.apps/cert-manager unchanged
deployment.apps/cert-manager-webhook unchanged
mutatingwebhookconfiguration.admissionregistration.k8s.io/cert-manager-webhook configured
validatingwebhookconfiguration.admissionregistration.k8s.io/cert-manager-webhook configured

Bạn có thể verify lại xem cert-manager đã triển khai thành công chưa bằng lệnh kubectl -n cert-manager get all.

$ kubectl -n cert-manager get all
NAME                                           READY   STATUS    RESTARTS   AGE
pod/cert-manager-757cfdccc6-q58nq              1/1     Running   0          37m
pod/cert-manager-cainjector-54559f9d67-29tqm   1/1     Running   0          37m
pod/cert-manager-webhook-547ddf5647-s44jp      1/1     Running   0          37m

NAME                           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/cert-manager           ClusterIP   10.105.104.252   <none>        9402/TCP   37m
service/cert-manager-webhook   ClusterIP   10.104.9.220     <none>        443/TCP    37m

NAME                                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/cert-manager              1/1     1            1           37m
deployment.apps/cert-manager-cainjector   1/1     1            1           37m
deployment.apps/cert-manager-webhook      1/1     1            1           37m

NAME                                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/cert-manager-757cfdccc6              1         1         1       37m
replicaset.apps/cert-manager-cainjector-54559f9d67   1         1         1       37m
replicaset.apps/cert-manager-webhook-547ddf5647      1         1         1       37m

Như vậy Cert-manager đã cài đặt thành công. Phần tiếp theo sẽ hướng dẫn bạn sử dụng nó với Letsencrypt, nhưng trước hết bạn nên xem qua bài viết Chuyển đổi WordPress từ Virtual Machine hoặc Docker sang Kubernetes trước khi đọc tiếp phần dưới nhé. Vì bài này mình sẽ sử dụng project của bài trước để hướng dẫn.

Sau khi xem qua bài viết mình nhắc ở trên, bạn cần cài đặt Cert Manager và thực hiện các bước sau:

  1. Tạo một Issuer để kết nối với Let’s Encrypt.

Trong ví dụ này, chúng ta sử dụng Let’s Encrypt bằng cách tạo một ClusterIssuer. Hãy tạo một tệp YAML có nội dung như sau:

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
  namespace: wiki-hoanghd
spec:
  acme:
    email: hoanghd164@gmail.com
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
      - http01:
          ingress:
            class: nginx

Lưu ý rằng trong phần email, bạn cần thay thế your-email@example.com bằng địa chỉ email của bạn.

  1. Tạo một Certificate

Sau khi tạo Issuer, bạn có thể tạo một Certificate để yêu cầu chứng chỉ SSL từ Let’s Encrypt. Tạo một tệp YAML có nội dung như sau:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: website-tls
  namespace: wiki-hoanghd
spec:
  secretName: website-tls
  duration: 2160h # 90 days
  renewBefore: 360h # 15 days
  commonName: wordpress.hoanghd.com
  dnsNames:
    - wordpress.hoanghd.com
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer

Trong phần commonNamednsNames, hãy thay thế wordpress.hoanghd.com bằng tên miền của bạn.

  1. Thêm TLS vào Ingress

Cuối cùng, bạn cần thêm TLS vào Ingress của bạn bằng cách chỉ định tlshosts trong phần spec. Tạo một tệp YAML có nội dung như sau:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: website
  namespace: wordpress
  labels:
    app: website-wp
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    cert-manager.io/issuer: "letsencrypt-prod"
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
  tls:
    - secretName: website-tls
      hosts:
        - wordpress.hoanghd.com
  rules:
    - host: wordpress.hoanghd.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: website-wp
                port:
                  number: 80

Lưu ý rằng trong phần annotations, chúng ta thêm hai thông tin, cert-manager.io/issuercert-manager.io/cluster-issuer, để cho Cert Manager biết rằng Issuer nào được sử dụng cho Certificate này.

Sau khi triển khai các tệp YAML này, Cert Manager sẽ tự động yêu cầu chứng chỉ SSL từ Let’s Encrypt thông qua ACME server của nó. Khi yêu cầu được chấp nhận và xác thực thành công, Cert Manager sẽ tạo ra một secret chứa chứng chỉ SSL và sử dụng nó để cấu hình Ingress Controller. Sau đó, bạn sẽ có thể truy cập trang web của mình bằng HTTPS và trình duyệt của bạn sẽ xác thực chứng chỉ SSL từ Let’s Encrypt.

Lưu ý là để sử dụng Let’s Encrypt cho domain wordpress.hoanghd.com, bạn cần phải public domain này ra internet để các service của Let’s Encrypt có thể truy cập và xác thực. Vì vậy, để sử dụng Let’s Encrypt, bạn cần phải public domain wordpress.hoanghd.com ra internet.

Tuy nhiên, nếu bạn chỉ muốn sử dụng SSL certificate để test ở môi trường local, bạn có thể tạo một self-signed certificate. Self-signed certificate sẽ không được xác thực bởi một tổ chức nào đó như Let’s Encrypt, và sẽ bị các trình duyệt hiển thị thông báo cảnh báo về tính bảo mật. Tuy nhiên, self-signed certificate vẫn cho phép bạn sử dụng HTTPS để kết nối với website của mình.

Bạn có thể sử dụng OpenSSL để tạo self-signed certificate. Sau khi tạo xong, bạn có thể tạo một Kubernetes secret để lưu trữ certificate và key, và sử dụng nó trong Ingress object của mình.

Sau khi chỉnh sửa xong, tôi đã update manifest lên Gitlab và ArgoCD đã update lại manifest cho tôi. Phần tô đỏ là phần deploy của Cert Manager.

Bạn có thể verify lại thông tin Certificate đã tạo.

$ kubectl get Certificate -n wiki-hoanghd
NAME          READY   SECRET        AGE
website-tls   False   website-tls   48m

Hoặc thông tin ClusterIssuer đã tạo.

$ kubectl get ClusterIssuer -n wiki-hoanghd
NAME               READY   AGE
letsencrypt-prod   True    49m

Để xem chi tiết thông tin bạn có thể sử dụng lệnh kubectl describe ClusterIssuer -n wiki-hoanghd hoặc kubectl describe Certificate -n wiki-hoanghd .

Và đây là kết quả khi truy cập website.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

4,956FansLike
256FollowersFollow
223SubscribersSubscribe
spot_img

Related Stories