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ênletsencrypt-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 secrets
và kubectl 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.