+1

[ArgoCD] Phần 4: Tìm hiểu về Application Sync Policy và điểm cần lưu ý

Trong phần trước, mình đã chia sẻ cách bootstrap cluster sử dụng App of Apps pattern giúp tự động hóa quá trình triển khai ứng dụng lên Kubernetes cluster. Và sang phần này, hãy cùng mình tìm hiểu rõ hơn về Sync Policy của Application để vận dụng chúng một cách linh hoạt và an toàn nhé!

ArgoCD Application

Nhắc lại kiến thức về Application trong ArgoCD, Application sẽ đại diện cho ứng dụng mà bạn đang triển khai lên K8s. Một Application sẽ có 3 phần chính được thể hiện dưới sync YAML dưới đây:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata: {}
spec:
  destination: {}
  source: {}
  syncPolicy: {}

Trong đó:

  1. source: Vị trí của mã nguồn (các file K8s manifests), thường là một Git repository, Helm chart, hoặc một thư mục kustomize.
  2. destination: Nơi mã nguồn và cấu hình của ứng dụng (1) sẽ được triển khai. Bao gồm chỉ định về NamespaceCluster.
  3. syncPolicy (Chính sách đồng bộ): Tuỳ chỉnh cách ArgoCD đồng bộ hóa trạng thái thực tế của ứng dụng trên Kubernetes với trạng thái mong muốn được định nghĩa trong source.

Bài viết này tập trung vào các cấu hình của phần 3 - syncPolicy.

Automated Sync (Đồng bộ tự động)

Vào việc đầu tiên, như trong Phần 1 - Giới thiệu về ArgoCD mình đã đề cập, nếu không chỉ định thì các Application phải cần đồng bộ thủ công. Vậy chả nhẽ, cứ mỗi lần push code lên Git thì chúng ta lại phải hí hoáy chạy lệnh à?

Tất nhiên là... KHÔNG, mình sẽ để nó tự động chứ. Thay vì chạy lệnh CLI như trong docs, bạn chỉ cần nhớ thêm trường automated như sau:

spec:
    syncPolicy:
        automated: {}

Chỉ cần khai báo automated={} - một object rỗng thì ArgoCD sẽ kích hoạt cơ chế Automated Sync lên luôn rồi nha các bạn.

Sau khi kích hoạt Automated Sync, thì cứ mỗi 3 phút ArgoCD sẽ chủ động thực hiện đồng bộ một lần. Có thể tăng giảm thời gian này trong cấu hình qua Values của Helm Chart:

configs:
    cm:
        timeout.reconciliation: 180s

Nếu bạn cài đặt 0s thì cơ chế tự động sync sẽ bị tắt, và bạn chỉ còn hai lựa chọn khác là dùng cơ chế đồng bộ khi có webhook bắn về ArgoCD server hoặc làm thủ công.

Việc đồng bộ cũng khá lằng ngoằng:

  • Tài nguyên đang có trên server, nhưng theo Git repo thì không còn, vậy phải làm sao?
  • Tài nguyên đã đồng bộ lên server, nhưng bạn nghịch dại xóa xừ trên server rồi, vậy phải làm sao? =))

Bây giờ, chúng ta hãy cùng nghé qua một số tùy chỉnh chuyên sâu hơn dành riêng cho cơ chế automated-sync. Để giải quyết 2 vấn đề tiêu biểu trên nhé! 😉

Tự động dọn dẹp (Automated Prune)

Khi quá trình đồng bộ diễn ra, tài nguyên khai trong báo trong Git đã được triển khai lên server, nhưng sau đó lại bị xóa khỏi Git. Trong tình huống này, mặc định ArgoCD sẽ không tự xóa các tài nguyên thừa trên server để đảm bảo an toàn.

Chúng ta có thể thay đổi hành vi này bằng cách kích hoạt cơ chế Automated Prune, cho phép ArgoCD dọn dẹp các tài nguyên dư thừa. Bạn khai báo YAML với trường automated.prune=true như sau:

spec:
    syncPolicy:
        automated:
            prune: true

Thường thì mình hay để automated.prune=true để ArgoCD tự xóa bỏ các tài nguyên không còn tồn tại trên Git/Helm repo luôn. Chỉ một số ứng dụng lưu dữ liệu quan trọng như database thì mình sẽ tắt đi.

Tự động phục hồi (Automated Self-Heal)

Ngược lại với Automated Prune thì chúng ta có cơ chế Self-Healing mình còn gọi là Tự động phục hồi. Tác dụng của cơ chế này đó là nếu tài nguyên mà Application đang quản lý bị sửa đổi thủ công trên cluster khiến sai khác với desired state trên Git repository thì ArgoCD sẽ tự cập lại tài nguyên đó cho giống với trạng thái đang lưu trên Git repo.

Lưu ý: mặc định, khi tài nguyên bị sửa đổi thủ công thì không có trigger để tự đồng bộ lại đâu nhé. Nên nó sẽ gây ra sai khác với desired state trên Git repository.

Để kích hoạt cơ chế self-healing, chúng ta sẽ khai báo YAML với trường automated.selfHeal=true như sau:

spec:
    syncPolicy:
        automated:
            selfHeal: true

Mình cũng luôn luôn bật self-healing để tránh việc sửa đổi thủ công giúp hạn chế lỗi do con người gây ra.

Cho phép App trống (Allow Empty)

Application trống là Application mà nó không có một tài nguyên nào được quản lý cả. Theo mặc định, ArgoCD sẽ coi đó là lỗi.

Allow Empty sẽ là một tùy chọn hữu ích trong các tình huống bạn chấp nhận ứng dụng tạm thời không chứa bất kỳ tài nguyên Kubernetes nào, và vẫn muốn ArgoCD theo dõi ứng dụng mà không báo lỗi.

Để kích hoạt Allow Empty, bạn cần ArgoCD phiên bản từ v1.8 trở lên và khai báo YAML với trường automated.allowEmpty=true:

spec:
    syncPolicy:
        automated:
            allowEmpty: true

Thường allowEmpty sẽ hay được dùng khi áp dụng App of Apps patterns. Trong đó, Root App sẽ trỏ tới một folder khác trên Git repository và chúng ta sẽ chấp nhận cho folder đó được để trống.

Ví dụ:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: apps
  namespace: argocd
spec:
  destination:
    namespace: argocd
    server: "https://kubernetes.default.svc"
  source:
    repoURL: "https://github.com/phe-lab/ds101-cluster"
    targetRevision: main
    path: apps
    directory:
      recurse: true
  project: default
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
      allowEmpty: true
    syncOptions:
      - CreateNamespace=true
      - ApplyOutOfSyncOnly=true

Và đây cũng là option cuối cùng trong cơ chế Automated Sync cho phép cấu hình quá trình tự đồng bộ của Application giữa trạng thái hiện tại trên cluster và trạng thái mong muốn được định nghĩa trong repository (Git, Helm) mà không cần sự can thiệp thủ công.

Sync Options

Tiếp theo đây, chúng ta sẽ tìm hiểu một số các tùy chỉnh chung sẽ được áp dụng cho quá trình sync, bao gồm cả Automated-Sync và Manual Sync gọi là Sync Options.

Sync Options là các tuỳ chọn để tinh chỉnh chi tiết hơn về cách quá trình đồng bộ diễn ra. Những tùy chọn này thường kiểm soát các hành vi cụ thể được đề cập chi tiết hơn trong nội dung tiếp theo. Về cơ bản, chúng ta dùng Sync Option như dưới đây.

Cách 1: Khai báo chung cho cả Application

Với cách này, chúng ta sẽ khai báo trong file YAML của Application. Lúc này nó sẽ áp dụng chung cho tất cả các tài nguyên mà Application quản lý.

spec:
    syncPolicy:
        syncOptions:
          - CreateNamespace=true
          - ApplyOutOfSyncOnly=true

Cách 2: Khai báo đơn lẻ cho từng tài nguyên

Ngoài khả năng khai báo chung ở cấp độ Application, các sync option có thể áp dụng cho tài nguyên một cách đơn lẻ thông qua metadata.annotations. Với cách này, sync option sẽ chỉ áp dụng cho tài nguyên được gắn annotation. Các tài nguyên khác mà Application đang quản lý không bị ảnh hưởng.

metadata:
  annotations:
    argocd.argoproj.io/sync-options: Prune=false

Thực tế, hầu hết các sync-options đều cho phép cấu hình sync-options thông qua annotations. Như vậy, chúng ta có thể cấu hình sync-options chi tiết tới cấp độ cho từng resource riêng lẻ khi dùng metadata.annotations chứ không chỉ cấu hình chung theo Application.

Bảng tổng hợp các sync option

Do số lượng khá nhiều nên mình có tổng hợp lại các sync option vào bảng dưới đây để các bạn tham khảo và tìm hiểu thêm.

Sync Option Mô tả
ApplyOutOfSyncOnly=true Chỉ áp dụng các tài nguyên đang ở trạng thái OutOfSync, bỏ qua các tài nguyên đã đồng bộ. Cơ chế này còn được biết tới với tên Selective Sync, điều mà FluxCD chưa có.
CreateNamespace=true Tự động tạo namespace nếu namespace chưa tồn tại. Tính năng này trong FluxCD cũng chưa có, dù rất hữu ích.
FailOnSharedResource=true Nếu có tài nguyên bị chia sẻ với ứng dụng khác, quá trình sync sẽ thất bại thay vì ghi đè.
ForceReplace=true Xóa tài nguyên hiện có trước khi áp dụng lại (hữu ích khi tài nguyên không thể cập nhật trực tiếp).
Prune=true Xóa các tài nguyên không còn có trong source repository.
RespectIgnoreDifferences=true Tôn trọng các thiết lập IgnoreDifferences để bỏ qua một số thay đổi.
ServerSideApply=true Sử dụng kubectl apply --server-side thay vì client-side apply để đồng bộ tài nguyên.
Validate=true Kiểm tra tính hợp lệ của tài nguyên trước khi áp dụng.
Replace=true Dùng kubectl replace thay vì kubectl apply.
SkipDryRunOnMissingResource=true Bỏ qua bước dry-run nếu CRD hoặc API chưa sẵn sàng.
ApplyInitialOnSkippedSync=true Áp dụng tài nguyên một lần ngay cả khi nó bị bỏ qua trong các lần sync tiếp theo.
ApplyStrategy=create-update Cho phép cấu hình chiến lược áp dụng tài nguyên, gồm: create-update, create-only, update-only.

Ngoài ra còn có PrunePropagationPolicy cho phép kiểm soát cách xóa tài nguyên bị prune:

  • PrunePropagationPolicy=foreground: Xóa tuần tự.
  • PrunePropagationPolicy=background: Xóa không đồng bộ.
  • PrunePropagationPolicy=orphan: Xóa tài nguyên gốc ngay lập tức.

Các bạn nghĩ sao về các Sync Option trên, hãy chia sẻ cảm nghĩ của bạn bằng cách để lại bình luận phía dưới nhé. Nếu có chỗ nào muốn làm rõ hơn, mình sẽ hỗ trợ.

Tổng kết

Trong phần tiếp theo, mình sẽ chia sẻ cách để đảm bảo an toàn cho các khóa bí mật khi cần phải lưu trữ trong Git Repository. Mình lấy ví dụ đơn giản, khi bạn deploy một cụm database như MySQL / PostgreSQL hoặc bất cứ ựng dụng nào khác đề sẽ có những dữ liệu như API Key, username, password, certificate, .etc. Lưu trực tiếp chúng trên Git Repository sẽ có rủi ro cực kỳ cao khi chẳng may repository đó bị leak. Có thể do một bạn nhân viên vô tình push code lên repository cá nhân ở chế độ public chẳng hạn. 🤔

Nếu bạn quan tâm về những nội dung này, follow mình để nhận thông báo ngay khi mình publish bài viết mới nhé. Xin chào và hẹn gặp lại!


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí