Thursday, November 21, 2024

Let’s Encrypt trong Kubernetes

-

Let’s Encrypt là gì?

Let’s Encrypt là một tổ chức cung cấp chứng chỉ bảo mật mà bạn có thể sử dụng miễn phí. Họ cung cấp quy trình tự động hóa để bạn có thể nhận và gia hạn chứng chỉ SSL (Secure Sockets Layer) một cách dễ dàng.

Chứng chỉ SSL là một phần quan trọng của việc bảo vệ thông tin truyền tải giữa trình duyệt người dùng và máy chủ web. Chúng giúp đảm bảo rằng dữ liệu được truyền qua mạng một cách an toàn và không thể đọc được bởi bất kỳ ai khác.

Thời hạn của chứng chỉ do Let’s Encrypt cung cấp là 90 ngày, nhưng bạn có thể gia hạn chúng bất cứ lúc nào. Điều này làm tăng tính an toàn và đồng thời giúp tự động hóa quy trình gia hạn để tránh việc quản lý chứng chỉ một cách thủ công.

Let’s Encrypt trên Kubernetes.

Để thực hiện quá trình này trên Kubernetes, một nền tảng quản lý container, bạn có thể sử dụng công cụ cert-manager. Đây là một công cụ đặc biệt được thiết kế để làm cho việc cấp và gia hạn chứng chỉ trở nên dễ dàng trên môi trường Kubernetes.

Cụ thể, để cài đặt cert-manager, bạn có thể sử dụng Helm, một công cụ quản lý gói cho Kubernetes. Bước đầu tiên là cài đặt các tài nguyên CustomResourceDefinition, đó là một phần của quá trình cài đặt và cấu hình cert-manager trên Kubernetes.

Bước 1 – Cài đặt CustomResourceDefinition.

kubectl apply --validate=false \
-f https://github.com/jetstack/cert-manager/releases/download/v0.15.1/cert-manager.yaml

Bước 2: Tạo namespace cho cho cert-manager.

kubectl create ns cert-manager

Bước 3 – Thêm Jetstack Helm repository và cập nhật lại Helm Repo của bạn.

helm repo add jetstack https://charts.jetstack.io
helm repo update

Bước 4 – Cài đặt cert-manager.

helm install --name cert-manager \
--namespace cert-manager \
--version v0.15.0 jetstack\cert-manager

Hãy xác nhận lại các thành phần cài đặt ở trên.

$ kubectl get pods --namespace cert-manager
NAME                                       READY   STATUS    RESTARTS   AGE
cert-manager-5c6866597-zw7kh               1/1     Running   0          2m
cert-manager-cainjector-577f6d9fd7-tr77l   1/1     Running   0          2m
cert-manager-webhook-787858fcdb-nlzsq      1/1     Running   0          2m

Issuers trong Kubernetes.

Issuers của cert-manager trên Kubernetes nó được định nghĩa là các tài nguyên đại diện cho một cơ quan chứng chỉ (certificate authority), nơi bạn có thể đạt được các chứng chỉ x509 đã được ký, ví dụ như Let’s Encrypt.

Để bắt đầu cấp chứng chỉ trong cluster của bạn, bạn cần ít nhất một Issuer hoặc ClusterIssuer.

Một Issuer là một tài nguyên thuộc một namespace. Điều này có nghĩa là bạn cần tạo một Issuer trong mỗi namespace mà bạn muốn đạt được các Chứng chỉ trong đó.

Nếu bạn muốn tạo một Issuer duy nhất mà có thể sử dụng trong nhiều namespace, bạn nên xem xét việc tạo một tài nguyên ClusterIssuer. ClusterIssuer là một tài nguyên không thuộc namespace nào cả, nghĩa là nó có thể được tiêu thụ (consume) từ bất kỳ namespace nào trong cluster. Điều này giúp giảm sự lặp lại khi bạn muốn sử dụng một Issuer chung cho nhiều namespace trong cluster của mình.

Tạo ClusterIssuer resource cho Let’s Encrypt:

kubectl apply -f - <<EOF
apiVersion: certmanager.k8s.io/v1alpha1
kind: Issuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    email: "<your-name@domain.com>"
    http01: {}
    privateKeySecretRef:
      name: letsencrypt-prod
EOF

Lưu ý, bạn hãy cung cấp địa chỉ email hợp lệ. Bạn sẽ nhận được thông báo qua email về việc gia hạn chứng chỉ.

Đây là danh sách ClusterIssuers trong cluster của bạn:

$ kubectl get clusterissuers
NAME                  AGE
letsencrypt-prod      2m

Danh sách này chỉ hiển thị một ClusterIssuer có tên là letsencrypt-prod và nó đã tồn tại trong vòng 2 phút (AGE là 2m). ClusterIssuer này có thể được sử dụng để cấp chứng chỉ TLS cho các Ingress trong toàn bộ cluster Kubernetes của bạn.

Tiếp theo chúng ta triển khai Ingress sử dụng cert-manager để tự động cấp chứng chỉ TLS và tạo secret tương ứng trong Kubernetes.

kubectl apply -f - <<EOF
apiVersion: extensions/v1beta1
kind: Ingress
metadata: 
  annotations: 
    certmanager.k8s.io/cluster-issuer: letsencrypt-prod
    kubernetes.io/ingress.class: nginx
  name: frontend
spec: 
  rules: 
    - 
      host: app.mydomain.com
      http: 
        paths: 
          - 
            backend: 
              serviceName: frontend
              servicePort: 80
            path: /
  tls: 
    - 
      hosts: 
        - app.mydomain.com
      secretName: app-mydomain-com
EOF
  • certmanager.k8s.io/cluster-issuer: Đây là annotation (chú thích) cho biết cert-manager sẽ sử dụng ClusterIssuer với tên letsencrypt-prod để cấp chứng chỉ TLS.
  • kubernetes.io/ingress.class: Xác định class Ingress sẽ xử lý cấu hình. Trong trường hợp này, nó đang sử dụng Ingress Controller với class là nginx.
  • spec.rules: Quy định các quy tắc cho Ingress, ví dụ như địa chỉ và cổng mà Ingress sẽ lắng nghe.
  • tls.hosts: Danh sách các host mà bạn muốn có chứng chỉ TLS.
  • tls.secretName: Tên của secret trong Kubernetes nơi chứa chứng chỉ TLS và privatekey.

Sau khi bạn tạo Ingress này, cert-manager sẽ tự động yêu cầu và cài đặt chứng chỉ TLS từ Let’s Encrypt bằng cách sử dụng ClusterIssuer letsencrypt-prod. Bạn sẽ thấy secret app-mydomain-com chứa thông tin về chứng chỉ TLS trong Kubernetes. Cert-manager cũng sẽ tạo một Certificate có tên là app-mydomain-com để theo dõi trạng thái của quá trình cài đặt chứng chỉ.

Lưu ý, trong môi trường thực tế, bạn có thể muốn sử dụng ClusterIssuer của Let’s Encrypt để có thể tái sử dụng cho nhiều Ingress trong cluster của bạn.

Các lệnh kubectl get secretskubectl get certificates đã được thực hiện để kiểm tra xem việc tạo Ingress đã tạo ra secret TLS và chứng chỉ hay chưa.

$ kubectl get secrets
NAME                TYPE               DATA   AGE
app-mydomain-com    kubernetes.io/tls  3      1m
  • NAME: Tên của secret được tạo, trong trường hợp này là app-mydomain-com.
  • TYPE: Loại của secret, ở đây là kubernetes.io/tls.
  • DATA: Số lượng dữ liệu (thường là các khóa và chứng chỉ) trong secret.
  • AGE: Thời gian kể từ khi secret được tạo, ở đây là 1 phút.
$ kubectl get certificates
NAME                READY   SECRET            AGE
app-mydomain-com    True    app-mydomain-com  1m
  • NAME: Tên của Certificate, ở đây là app-mydomain-com.
  • READY: Trạng thái “True” cho biết Certificate đã sẵn sàng.
  • SECRET: Tên của secret mà Certificate sử dụng, ở đây cũng là app-mydomain-com.
  • AGE: Thời gian kể từ khi Certificate được tạo, ở đây là 1 phút.

Nếu mọi thứ diễn ra suôn sẻ và không có lỗi, bạn sẽ có thể truy cập trang web của mình thông qua kết nối TLS an toàn và không cần phải lo lắng về việc gia hạn chứng chỉ, vì cert-manager đã tự động thực hiện quy trình gia hạn cho bạn.

Một số câu hỏi thường gặp

Câu hỏi 1 – Có tổ chức nào sẽ cấp certificate mà không cần xác minh domain hay không?

Các Tổ chức Chứng chỉ (CA) toàn cầu thường cần xác minh bạn có quyền truy cập vào domain mà bạn đang muốn certificate.

Nếu bạn cần một certificate cho “localhost” hoặc môi trường phát triển, bạn có thể tự tạo chúng. Có các hướng dẫn về cách tự tạo certificate SSL cho “localhost” sử dụng công cụ như OpenSSL hoặc cfssl. Bạn cũng có thể quản lý certificate TLS trong một cụm Kubernetes.

Ngoài ra, có một số trang trong tài liệu Kubernetes giới thiệu cách tạo certificate TLS một cách thủ công. Trong một số trường hợp, có thể tự tạo và cấu hình certificate tự ký cho môi trường phát triển của bạn.

Nếu bạn quan tâm đến việc làm thế nào để làm việc với HTTPS trên môi trường phát triển cục bộ của bạn, có một hướng dẫn giải thích cách tự ký và thiết lập một certificate cho “localhost” trong 5 phút.

Như vậy nếu bạn không thể hoặc không muốn sử dụng một CA Global, bạn có thể tự tạo certificate tự ký để sử dụng trong môi trường phát triển của mình.

Cấu hỏi 2 – Làm cách nào để khắc phục lỗi không phản hồi của Let’s Encrypt ACME khi sử dụng xác thực certificate trên Kubernetes với Nginx?

Trả lời: Vấn đề ở đây là chúng ta đã cấu hình sai trong annotation nginx.ingress.kubernetes.io/auth-tls-secret của cert-manager. Đối với annotation này, phải là định dạng “namespace/name”, trong đó “namespace” là namespace chứa secret chứa chứng thực client CA, và “name” là tên của secret đó. Tuy nhiên, chúng ta chỉ cung cấp tên vì secret đó nằm trong cùng namespace với ingress.

Để chẩn đoán vấn đề, bạn đã dump cấu hình của nginx ingress controller ra một file nginx.conf.txt bằng lệnh:

kubectl exec <TÊN POD CỦA NGINX INGRESS CONTROLLER> -n <NAMESPACE INGRESS> -- nginx -T | tee nginx.conf.txt

Trong đoạn config này, có đoạn mã:

## start server the.hostname.com
    server {
        server_name the.hostname.com ;
        
        listen 80;
        
        set $proxy_upstream_name "-";
        set $pass_access_scheme $scheme;
        set $pass_server_port $server_port;
        set $best_http_host $http_host;
        set $pass_port $pass_server_port;
        
        listen 443  ssl http2;
        
        # PEM sha: 66c07c44ba9637a23cd3d7b6ebce958e08a52ccb
        ssl_certificate                         /etc/ingress-controller/ssl/default-fake-certificate.pem;
        ssl_certificate_key                     /etc/ingress-controller/ssl/default-fake-certificate.pem;
        
        ssl_certificate_by_lua_block {
            certificate.call()
        }
        
        # Location denied, reason: invalid format (namespace/name) found in 'the-secret-name'
        return 403;
        
    }
    ## end server the.hostname.com

Dòng quan trọng ở đây là:

# Location denied, reason: invalid format (namespace/name) found in 'the-secret-name'
        return 403;

Dòng này cho thấy lý do tại sao yêu cầu bị từ chối và nó chỉ ra rằng có vấn đề với định dạng không đúng trong annotation nginx.ingress.kubernetes.io/auth-tls-secret với tên secret ‘the-secret-name’. Sau khi sửa lại định dạng, việc sử dụng ACME đã hoạt động đúng như mong đợi.

Câu hỏi 3 – Với quy trình cấu hình Let’s Encrypt trên thì sau 90 ngày chứng chỉ có tự động gia hạn không?

Trả lời: Với quy trình cấu hình trên đang sử dụng cert-manager và Let’s Encrypt để cấp chứng chỉ TLS, thường đi kèm với quy trình tự động gia hạn chứng chỉ. Tính đến thời điểm mình làm bài viết nàycert-manager thường sẽ tự động gia hạn chứng chỉ trước khi chúng hết hạn.

Quy trình tự động gia hạn này thường được xây dựng trong cert-manager và Let’s Encrypt để đảm bảo rằng chứng chỉ TLS của bạn luôn làm việc mà không cần phải can thiệp thủ công. Khi chứng chỉ của bạn gần hết hạn, cert-manager sẽ tự động yêu cầu và cài đặt chứng chỉ mới từ Let’s Encrypt mà không đòi hỏi sự can thiệp của bạn.

Để đảm bảo rằng quy trình gia hạn chứng chỉ hoạt động đúng cách, bạn nên kiểm tra cài đặt cert-manager và đảm bảo rằng nó đang chạy và cấu hình đúng. Bạn cũng có thể kiểm tra các logs của cert-manager để xem liệu quy trình gia hạn có diễn ra thành công hay không.

Lưu ý rằng thông tin trên có thể đã thay đổi tùy theo phiên bản cụ thể của cert-manager và Let’s Encrypt mà bạn đang sử dụng, nên luôn là một ý tưởng tốt để kiểm tra tài liệu cụ thể cho phiên bản của bạn để đảm bảo rằng bạn đang thực hiện đúng cách cấu hình và quản lý chứng chỉ của mình.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

4,956FansLike
256FollowersFollow
223SubscribersSubscribe
spot_img

Related Stories