Header Ads Widget

Ticker

6/recent/ticker-posts

Hướng dẫn cài đặt Nginx Ingress và Cert Manager sử dụng Let's Encrypt cho Kubernetes

Keywords: How to setup an Nginx Ingress and Cert Manager on Kubernetes

Ingress trong k8s là gì ? đây là câu hỏi mà hình như khi mình đi phỏng vấn DevOps tại các công ty yêu cầu kubernetes điều hỏi mình, vậy nó thật sự là gì ? theo một lý thuyết của phong cách google thì nó là một định nghĩa rất dài nhưng với mình thì mình đã trả lời các nhà tuyển dụng, những người phỏng vấn mình nó là một config dùng để trỏ domain đến một service trong k8s

Câu trả lời đơn giản theo nghĩa mà mình hiểu, có rất nhiều Ingress Controller được hổ trợ như HaProxy Ingress, Nginx Ingress, Kong Ingress,... Nhưng phổ biến nhất vẫn là Nginx Ingress và Kong Ingress, hôm nay mình sẻ hướng dẫn cho các bạn cài đặt nó cũng như thực hiện tạo thử demo với domain cùng với http và https, vậy để có được https ta cần làm gì ? chúng ta phải thực hiện cài đặt Let's Encrypt cùng với Cert Manager để quản lý các Certificates, ok chúng ta phải làm thử từng bước trước đã, đầu tiên là tạo service để chạy một pod demo trước chứ nhỉ

Phần 1: Cài đặt một services để demo thử

Chúng ta thực hiện deploy một services bằng file yaml phía dưới đây để tiện cho quá trình test nhé
apiVersion: v1
kind: Service
metadata:
  name: http-test-svc
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    run: http-test-app
  sessionAffinity: None
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: http-test-svc
  name: http-test-svc
spec:
  replicas: 2
  selector:
    matchLabels:
      run: http-test-app
  template:
    metadata:
      labels:
        run: http-test-app
    spec:
      containers:
      - image: httpd
        imagePullPolicy: IfNotPresent
        name: http
        ports:
        - containerPort: 80
          protocol: TCP
        resources: {}
Sau khi chạy xong bạn sẻ thấy như hình
Điều này có nghĩa rằng mình đã tạo xong một service đang chạy 2 pods và tên service đó là http-test-svc nhưng bây giờ mình để type service là ClusterIP vậy để truy cập vào đó mà không cần đến NodePort thì chúng ta cần phải làm gì ? đó là trỏ domain đến services đó, việc trỏ domain đến service đó thì sẻ do thằng Ingress Controller quản lý vì vậy mình sẻ chọn thực hiện cài đặt 1 trong các Ingress Controller, mình sẻ chọn Nginx Ingress

Phần 2: Cài đặt Nginx Ingress cho Kubernetes

Để cài đặt Nginx Ingress thì chúng ta thực hiện truy cập vào trang web sau và chạy câu lệnh sau để cài đặt
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.44.0/deploy/static/provider/do/deploy.yaml
Hoặc chúng ta có thể sử dụng cách sau
git clone [email protected]:nginxinc/kubernetes-ingress.git
# vào thư mục tải về
cd kubernetes-ingress/deployments
Các menifest điều nằm ở thư mục deployments trong kubernetes-ingress vừa clone về, sau khi đã truy cập vào rồi thì ta chỉ việc apply một vài file sau thôi:
kubectl apply -f common/ns-and-sa.yaml
kubectl apply -f common/default-server-secret.yaml
kubectl apply -f common/nginx-config.yaml
kubectl apply -f common/ingress-class.yaml
kubectl apply -f common/crds/k8s.nginx.org_virtualservers.yaml
kubectl apply -f common/crds/k8s.nginx.org_virtualserverroutes.yaml
kubectl apply -f common/crds/k8s.nginx.org_transportservers.yaml
kubectl apply -f common/crds/k8s.nginx.org_policies.yaml
kubectl apply -f rbac/rbac.yaml
kubectl apply -f daemon-set/nginx-ingress.yaml
kubectl create -f service/nodeport.yaml
Sau khi thực hiện cài đặt Inginx Ingress xong thì chúng ta chỉ còn việc test nữa thôi là ok, nếu như version k8s của bạn nhỏ hơn 1.18 thì có thể sử dụng cách 1 nhưng nếu như version của bạn lớn hơn 1.18 thì mình khuyên các bạn sử dụng cách 2 nhé
Tạo file Ingress để truy cập domain đến service trước tiên ta sẻ test với http trước nhé
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app
  # namespace: ingress-nginx
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    kubernetes.io/ingress.class: nginx
spec:
  # backend:
  #   serviceName: nginx-ingress-default-backend
  #   servicePort: 80
  rules:
  - host: thanhphatit.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: http-test-svc
            port: 
              number: 80
Sau đó chạy câu lệnh apply nó, như các bạn biết đấy, để truy cập domain thì ta phải trỏ DNS Record đến IP của k8s cái đã, ở đây mình sẻ trỏ tạm ở file host nhé
Thực hiện kiểm tra thử app ingress mà ta đã apply ở trên xem nó đã chạy chưa nhé
Ok bây giờ ta test thử domain nào
Ngon lành rồi đấy, bây giờ chúng ta tới phần khá quan trọng đấy, http thì ngon rồi tiếp đến phải là https chứ nhỉ
Có 2 hình thức sử dụng https
  • Thứ 1: Sử dụng default-server-secret của nginx lúc nảy ta config nhưng điều này đồng nghĩa với việc là config ingress phải cùng namespace với nginx-ingress và pods đang chạy cũng phải nằm ở namespace nginx-ingress, giả sử trường hợp mình sử dụng default-server-secret nhưng pods của mình đang chạy lại nằm ở namespace defaults không nằm ở nginx-ingress thì vấn đề sẻ như thế nào ? 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app
  namespace: nginx-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    kubernetes.io/ingress.class: nginx
spec:
  # backend:
  #   serviceName: nginx-ingress-default-backend
  #   servicePort: 80
  tls:
    - hosts:
      - thanhphatit.local
      secretName: default-server-secret
  rules:
  - host: thanhphatit.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: http-test-svc
            port: 
              number: 80

Nó sẻ ra như hình, nghĩa là nó đã truy cập được ssl nhưng lại không thể truy cập vào được service do khác namespace, mình chỉ có thể thực hiện bằng cách dời pods sang namespace đó hoặc copy ra 1 bản secret khác nằm ở defaults cùng với pods thì may ra nó mới chạy được
  • Thứ 2: Do vấn đề ở trên quá phức tạp và rờm rà nên vì thế mình sẻ sử dụng cách 2 đó là cài đặt cert manager và để nó tự tạo certificate cho pods đó trên cùng namespace

Phần 3: Cài đặt và config Cert Manager

Chạy câu lệnh sau để thực hiện apply yaml cert manager
kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.2.0/cert-manager.yaml
Kiểm tra lại mọi thứ nào
Tới đây được rồi thì chưa xong đâu, chúng ta thực hiện apply 2 file
letsencrypt-staging.yaml:
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: [email protected]
   # 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
letsencrypt-staging.yaml:
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: [email protected]
    # 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
Sau khi đã apply 2 file letsencrypt ta tiếp tục chỉnh sửa lại 1 chút file ingress nữa là xong, các bạn nên chú ý việc sử dụng letsencrypt với một domain không đăng ký là hoàn toàn không thể, vì vậy cần chú ý phần email trong 2 file letsencrypt trên bởi lẻ mình sẻ không làm tiếp cho các bạn và show kết quả ra cho các bạn thấy mà chỉ hướng dẫn bằng cách viết ví dụ trên đây thôi, do mình không có domain thật để giải quyết  
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-staging
    certmanager.k8s.io/acme-challenge-type: http01
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  # backend:
  #   serviceName: nginx-ingress-default-backend
  #   servicePort: 80
  tls:
  - hosts:
    - test.itblognote.com
    secretName: app-tls-cert
  rules:
  - host: test.itblognote.com
    http:
      paths:
      - path: /
        pathType: Exact
        backend:
          service:
            name: http-test-svc
            port: 
              number: 80
Như các bạn thấy mình đã thêm annotations và tls cho file ingress, như vậy mình đã config xong cho phần ingress https rồi, nói chung sorry các bạn vì mình không thực hiện ví dụ cụ thể cho các bạn được bởi lẽ cần domain và ví dụ rõ ràng sẻ tốt hơn nhưng do mình không có domain để test, sử dụng domain ảo bằng cách add hosts thì thằng letsencrypt nó không cho, thành ra mình chỉ copy những config tượng trưng thôi, nhưng nếu như anh em có domain rõ ràng rồi thì chỉ việc thay thế trong config và run là chạy liền ak mà yên tâm.

Post a Comment

0 Comments