Làm sao để config SSL/TLS cho Ingress trong cụm Kubernetes?

Trong bài viết này ta sẽ cùng tìm hiểu về cách cấu hình TLS certificate cho các Kubernetes Ingress.

💡
SSL và TLS là một. SSL là tên gọi cũ. TLS là phiên bản mới hơn của SSL. Đừng nhầm lẫn giữa chúng nhé.

Cách lấy Kubernetes Ingress SSL/TLS Certificate

Yêu cầu cơ bản của Ingress TLS là một TLS/SSL certificate. Bạn có thể lấy các certificate đó bằng các cách sau:

  1. Self-Signed Certificates: TLS certificate được tạo và kí bởi Certificate Authority của riêng bạn. Đây là một cách tạo certificate tốt nếu như bạn có thể chia sẻ rootCA cùng với team và browser có thể tin tưởng certificate đó. Tham khảo bài viết dưới đây để tạo các certificate của riêng bạn.

  2. Mua một SSL Certificate: Bạn cần mua một SSL certificate từ môt certificate authority.

  3. Sử dụng Let's encrypt certificate: Let's encrypt là một certificate authority phi lơi nhuận cung cấp các TLS certificate miễn phí.

Mọi SSL certificate đều có thời gian hết hạn (expiry date). Ta cần phải gia hạn cho các certificate trước khi nó hết hạn. Ví dụ Let's encrypt certificate sẽ hết hạn sau mỗi 3 tháng. Ta sẽ nói về gia hạn tự động các certificate trong phần cuối của bài viết này.

Nếu bạn làm việc trên một ứng dụng nội bộ, hầu hết các công ty đều có hạ tầng PKI của riêng công ty để cung cấp SSL cho các ứng dụng nội bộ. Bạn có thể request team network hoặc security để cung cấp các certificate.

Ingress TLS/SSL hoạt động thế nào?

Để thêm TLS vào Ingress ta chỉ cần:

  1. Tạo môt Kubernetes secret với server.crt certificate và file private key server.key

  2. Thêm TLS block vào Ingress resource với hostname được sử dụng để tạo cert tương ứng với TLS certificate.

SSL được xử lý bởi Ingress controller chứ không phải Ingress resource. Khi bạn thêm TLS certificate vào Ingress resource như một Kubernetes secret thì Ingress controller sẽ truy cập nó và đưa các certificate đó vào cấu hình của nó.

Ví dụ trong Nginx controller, SSL certificate được xử lý trong nginx.conf bởi block sau:

ssl_certificate_by_lua_block {
            certificate.call()
        }

Biểu đồ sau biểu diễn workflow của Ingress TLS:

Cấu hình Ingress TLS/SSL Certificates

Deploy một ứng dụng Test

Hãy bắt đầu với việc triển khai một ứng dụng sample. Ta sẽ sử dụng ứng dụng này để test Ingress TLS.

Create a dev namespace. Tạo một namespace dev

kubectl create -n dev

Lưu manifest sau thành hello-app.yaml.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-app
  namespace: dev
spec:
  selector:
    matchLabels:
      app: hello
  replicas: 2
  template:
    metadata:
      labels:
        app: hello
    spec:
      containers:
      - name: hello
        image: "gcr.io/google-samples/hello-app:2.0"

---

apiVersion: v1
kind: Service
metadata:
  name: hello-service
  namespace: dev
  labels:
    app: hello
spec:
  type: ClusterIP
  selector:
    app: hello
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP

Triển khai manifest:

kubectl apply -f hello-app.yaml

Tạo một Kubernetes TLS Secret

💡
Những bước sau đây là giả sử bạn đã có server.crtserver.key SSL từ một Certificate authority.

SSL certificate nên đực thêm vào như một Kubernetes Secret sau đó nó sẽ được chuyển vào Ingress resource TLS block.

Hãy tạo một Kubernetes secret loại TLS với server.crtserver.key. Ta sẽ tạo secret trong dev namespace nơi ta đã triển khai hello-app.

Thực thi kubectl command sau từ thư mục nơi ta lưu server.crtserver.key hoặc cung cấp absolute path của các file đó. hello-app-tls là tên ta đặt cho secret.

kubectl create secret tls hello-app-tls \
    --namespace dev \
    --key server.key \
    --cert server.crt

Nếu muốn sử dụng YAML để tạo secret ta cũng có thể sử dụng như sau:

apiVersion: v1
kind: Secret
metadata:
  name: hello-app-tls
  namespace: dev
type: kubernetes.io/tls
data:
  server.crt: |
       <crt contents here>
  server.key: |
       <private key contents here>

Thêm TLS block vào Ingress Object

Ingress resource với TLS đã được tạo trong cùng namespace ta đã triển khai ứng dụng. Ta sẽ tạo Ingress resource bằng ingress.yaml sau:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: hello-app-ingress
  namespace: dev
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - demo.mlopshub.com
    secretName: hello-app-tls
  rules:
  - host: "demo.mlopshub.com"
    http:
      paths:
        - pathType: Prefix
          path: "/"
          backend:
            service:
              name: hello-service
              port:
                number: 80

Bạn có thể thấy ta đã thêm TLS block cùng hostname và TLS secret ta đã tạo trong bước trước.

Host trong TLS block và rule block cần phải giống nhau.

Kiểm tra Ingress TLS

Ta có thể kiểm tra hoạt động của Ingress TLS sử dụng curl hoặc browser.

curl https://demo.mlopshub.com -kv

Trong output trong phần server certificate ta có thể kiểm tra thông tin về certificate:

If you don’t have a valid certificate or if the ingress TLS configuration is wrong, you will see “Your connection is not private” security warning and if you check the certificate details, you will see the certificate name as “Kubernetes Ingress Controller Fake Certificate“. Nếu không có certificate khả dụng hoặc Ingress TLS cấu hình sai, ta sẽ thây thông báo "Your connection is not private" và nếu kiểm tra thông tin về certificate ta có thể thấy tên certificate là "Kubernetes Ingress Controller Fake Certificate"

Đó là SSL certificate mặc định của Nginx Ingress Controller. Nếu bạn kiểm tra nginx.conf của Nginx controller bạn có thể thấy certificate mặc định như dưới đây:

Ingress SSL Termination

Mặc định SSL sẽ được terminate trong ingress controller.

Vì vậy mọi traffic từ controller đến pod sẽ không có TLS.

Nếu bạn muốn sử dụng toàn bộ traffic trên SSL, bạn có thể thêm annotation của Ingress controller bạn đang sử dụng. Ví dụ trong Nginx Ingress Controller để cho phép SSL traffic bạn có thể dùng nginx.ingress.kubernetes.io/backend-protocol:"HTTPS" annotation.

Kết luận

Trong bài viết này ta đã tìm hiểu về cách cấu hình Ingress TLS certificate cùng ví dụ về Ingress TLS.

Thêm vào đó ta có thể sử dụng annotation để có thêm các tham số TLS trong ứng dụng. Các annotation trong các ingress controller sẽ khác nhau.