Nỗi đau của việc triển khai thủ công
Triển khai ứng dụng trong phát triển phần mềm hiện đại thường giống như đi trên dây. Ngay cả với các pipeline CI/CD, các phương pháp triển khai truyền thống vẫn thường gặp khó khăn:
- Lệch cấu hình (Configuration Drift): Theo thời gian, các môi trường thường bị sai khác. Điều này gây ra sự không nhất quán giữa các môi trường phát triển, thử nghiệm và sản xuất. Hãy tưởng tượng một nhà phát triển kiểm tra một tính năng cục bộ và nó hoạt động hoàn hảo, nhưng sau đó lại thất bại trong môi trường thử nghiệm vì phiên bản cơ sở dữ liệu hơi khác hoặc cấu hình chưa được áp dụng.
- Lỗi thủ công: Can thiệp thủ công vào quy trình triển khai là nguyên nhân thường xuyên gây ra lỗi. Những lỗi này có thể dẫn đến sự cố ngừng hoạt động hoặc hành vi ứng dụng không mong muốn.
- Khôi phục chậm: Khi sự cố xảy ra, việc khôi phục về trạng thái ổn định trước đó có thể cồng kềnh và tốn thời gian. Điều này kéo dài thời gian ngừng hoạt động.
- Thiếu khả năng kiểm tra: Nếu không có bản ghi rõ ràng, tập trung, sẽ rất khó để hiểu ai đã thay đổi gì, khi nào và tại sao.
Các pipeline Tích hợp liên tục (CI) và Phân phối liên tục (CD) tự động hóa việc xây dựng và kiểm thử. Tuy nhiên, nhiều người vẫn sử dụng mô hình push-based để triển khai các artifact đến môi trường đích. Cách tiếp cận này không tự thân đảm bảo rằng trạng thái được triển khai hoàn toàn khớp với cấu hình dự định. Đây chính là nơi GitOps cung cấp một giải pháp mạnh mẽ cho những thách thức triển khai thường gặp này.
Chào mừng GitOps: Nguồn chân lý duy nhất của bạn
GitOps là một khuôn frameworks vận hành. Nó mở rộng các phương pháp hay nhất của DevOps—như kiểm soát phiên bản, cộng tác, tuân thủ và CI/CD—sang tự động hóa cơ sở hạ tầng. Về cơ bản, GitOps thiết lập Git làm nguồn chân lý duy nhất. Nó định nghĩa trạng thái mong muốn cho cả ứng dụng và cơ sở hạ tầng của bạn.
Triết lý này dựa trên bốn nguyên tắc cốt lõi:
-
Khai báo (Declarative): Cơ sở hạ tầng, ứng dụng và cấu hình đều được mô tả và lưu trữ dưới dạng khai báo như mã. Điều này có nghĩa là bạn định nghĩa những gì bạn muốn, thay vì cách thức để đạt được điều đó. Các manifest của Kubernetes, chẳng hạn, thể hiện hoàn hảo cấu hình khai báo.
-
Có phiên bản và Bất biến (Versioned and Immutable): Trạng thái mong muốn nằm trong Git, cung cấp khả năng kiểm soát phiên bản mạnh mẽ. Điều này cho phép dễ dàng theo dõi thay đổi, khôi phục và kiểm toán. Mỗi thay đổi tạo ra một commit mới, tạo ra một bản ghi lịch sử đầy đủ.
-
Tự động kéo (Pulled Automatically): Không giống như pipeline CI/CD đẩy các thay đổi lên cluster, một operator tự động (như ArgoCD) liên tục kéo trạng thái mong muốn từ Git và áp dụng nó. Cơ chế kéo này tăng cường đáng kể bảo mật bằng cách loại bỏ nhu cầu về thông tin xác thực cluster trong chính pipeline CI.
-
Hòa giải liên tục (Continuously Reconciled): Operator liên tục so sánh trạng thái cơ sở hạ tầng thực tế với trạng thái mong muốn được định nghĩa trong Git. Nếu có bất kỳ sự khác biệt nào phát sinh—ví dụ, nếu một pod bị xóa thủ công—operator sẽ tự động hòa giải cluster. Nó đảm bảo cluster luôn khớp với định nghĩa của kho lưu trữ Git.
Việc áp dụng GitOps mang lại lợi ích đáng kể cho các nhóm. Bao gồm triển khai nhanh hơn, thường xuyên hơn, khôi phục dễ dàng và an toàn hơn, tăng cường tư thế bảo mật và nhật ký kiểm toán rõ ràng cho tất cả các thay đổi. Cuối cùng, điều này góp phần vào sự ổn định hoạt động lớn hơn.
ArgoCD: Người thực thi GitOps
Nếu Git đóng vai trò là nguồn chân lý duy nhất của bạn, thì ArgoCD hoạt động như một người bảo vệ cảnh giác, đảm bảo rằng sự thật đó được duy trì nhất quán trong các cluster Kubernetes của bạn. ArgoCD là một công cụ phân phối liên tục dựa trên GitOps, được xây dựng đặc biệt cho Kubernetes. Nó tự động hóa việc triển khai, giám sát và quản lý các ứng dụng trong cluster của bạn. Tất cả các hoạt động này đều được điều khiển bởi các cấu hình được lưu trữ trong Git.
Thông thường, ArgoCD hoạt động như sau:
- Đầu tiên, ArgoCD liên tục giám sát các kho lưu trữ Git của bạn. Nó tìm kiếm các thay đổi đối với manifest ứng dụng của bạn, chẳng hạn như các tệp YAML của Kubernetes, Helm charts hoặc cấu hình Kustomize.
- Đồng thời, nó giám sát trạng thái trực tiếp của các ứng dụng của bạn đang chạy trong cluster Kubernetes.
- Khi ArgoCD phát hiện sự khác biệt giữa trạng thái mong muốn trong Git và trạng thái thực tế trong cluster, nó sẽ đánh dấu đây là tình trạng ‘mất đồng bộ’ (out of sync).
- Với tính năng tự động đồng bộ hóa được bật, ArgoCD tự động hòa giải những khác biệt này. Nó áp dụng trạng thái được định nghĩa trong Git vào cluster, loại bỏ hiệu quả mọi sự lệch cấu hình.
Một số tính năng chính khiến ArgoCD trở thành lựa chọn nổi bật. Bao gồm giao diện người dùng web trực quan để trực quan hóa việc triển khai, CLI mạnh mẽ để tự động hóa, hỗ trợ nhiều công cụ quản lý manifest khác nhau và Kiểm soát truy cập dựa trên vai trò (RBAC) mạnh mẽ.
Thực hành: Tự động hóa triển khai với ArgoCD
Bây giờ chúng ta sẽ cấu hình ArgoCD để tự động triển khai một ứng dụng Nginx đơn giản lên một cluster Kubernetes.
Điều kiện tiên quyết
Trước khi bắt đầu, hãy đảm bảo bạn có những điều sau:
- Bạn sẽ cần một cluster Kubernetes đang chạy. Minikube hoặc Kind là lựa chọn tuyệt vời để kiểm thử cục bộ, hoặc bạn có thể sử dụng một cluster do đám mây quản lý như GKE, EKS hoặc AKS.
kubectlphải được cài đặt và cấu hình để tương tác với cluster của bạn.- Nên có kiến thức cơ bản về Git và Kubernetes YAML manifests.
Bước 1: Cài đặt ArgoCD
Để bắt đầu, chúng ta sẽ cài đặt ArgoCD vào cluster Kubernetes của mình. Việc này bao gồm việc tạo một namespace chuyên dụng và áp dụng các manifest cài đặt của nó.
# Tạo một namespace mới cho ArgoCD
kubectl create namespace argocd
# Cài đặt ArgoCD vào namespace 'argocd'
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# Đợi các pod của ArgoCD sẵn sàng
kubectl wait --for=condition=ready pod -l app.kubernetes.io/name=argocd-server -n argocd --timeout=300s
# Mở giao diện người dùng ArgoCD bằng port-forwarding để truy cập cục bộ.
# Trong môi trường sản xuất, bạn thường sẽ sử dụng dịch vụ Ingress hoặc LoadBalancer thay thế.
kubectl port-forward svc/argocd-server -n argocd 8080:443 &
# Lấy mật khẩu admin ban đầu.
# Mật khẩu này được tạo động và lưu trữ dưới dạng một secret của Kubernetes.
ARGOCD_SERVER_POD=$(kubectl get pods -n argocd -l app.kubernetes.io/name=argocd-server -o jsonpath='{.items[0].metadata.name}')
kubectl exec -it $ARGOCD_SERVER_POD -n argocd -- argocd admin initial-password
# Lưu mật khẩu này để sử dụng sau. Tên người dùng mặc định là 'admin'.
Sau khi cài đặt, hãy truy cập giao diện người dùng ArgoCD bằng cách điều hướng đến https://localhost:8080 trong trình duyệt của bạn. Đăng nhập bằng tên người dùng admin và mật khẩu bạn đã lấy trước đó.
Bước 2: Chuẩn bị Kho lưu trữ ứng dụng của bạn
Tiếp theo, chúng ta sẽ tạo một kho lưu trữ Git đơn giản để ArgoCD giám sát. Kho lưu trữ này sẽ lưu trữ các manifest Kubernetes cho ứng dụng của chúng ta. Trong hướng dẫn này, chúng ta sẽ định nghĩa một triển khai Nginx cơ bản và dịch vụ tương ứng của nó.
# Tạo một thư mục mới cho manifest ứng dụng của bạn
mkdir my-nginx-app
cd my-nginx-app
# Tạo tệp deployment.yaml
cat <<EOF > deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21.6-alpine # Chúng ta sẽ cập nhật cái này sau
ports:
- containerPort: 80
EOF
# Tạo tệp service.yaml
cat <<EOF > service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
EOF
# Khởi tạo một kho lưu trữ Git và đẩy nó lên một remote (ví dụ: GitHub, GitLab)
# Thay thế <YOUR_GIT_REPO_URL> bằng URL kho lưu trữ thực tế của bạn.
git init
git add .
git commit -m "# Manifest ứng dụng Nginx ban đầu"
git branch -M main
git remote add origin <YOUR_GIT_REPO_URL>
git push -u origin main
Đảm bảo kho lưu trữ Git của bạn có thể truy cập công khai hoặc ArgoCD có các thông tin xác thực cần thiết để truy cập nó nếu là kho riêng tư.
Bước 3: Tạo một ứng dụng ArgoCD
Cluster Kubernetes của chúng ta hiện đang chạy ArgoCD, và các manifest ứng dụng của chúng ta nằm trong Git. Bước tiếp theo là thông báo cho ArgoCD về ứng dụng của chúng ta. Chúng ta sẽ định nghĩa một tài nguyên ArgoCD Application. Tài nguyên này sẽ trỏ đến kho lưu trữ Git của chúng ta và chỉ định nơi trong cluster mà ứng dụng sẽ được triển khai.
Chúng ta sẽ sử dụng ArgoCD CLI. Bạn có thể cài đặt nó bằng cách làm theo hướng dẫn trên trang web ArgoCD (ví dụ: brew install argocd trên macOS, hoặc tải trực tiếp cho Linux/Windows). Sau đó, đăng nhập vào ArgoCD CLI:
# Kết nối CLI với máy chủ ArgoCD của bạn
argocd login localhost:8080
# Sử dụng 'admin' và mật khẩu bạn đã lấy trước đó
Bây giờ, hãy tạo ứng dụng ArgoCD:
# Tạo một ứng dụng ArgoCD trỏ đến kho Git của chúng ta
# Thay thế <YOUR_GIT_REPO_URL> bằng URL kho lưu trữ của bạn
argocd app create my-nginx-app \
--repo <YOUR_GIT_REPO_URL> \
--path .
--dest-server https://kubernetes.default.svc \
--dest-namespace default \
--sync-policy automated \
--auto-prune \
--self-heal
Hãy cùng phân tích các cờ này:
--repo: URL của kho lưu trữ Git của bạn.--path: Thư mục con trong kho lưu trữ nơi các manifest của bạn được đặt. Sử dụng.cho thư mục gốc.--dest-server: URL máy chủ API của cluster Kubernetes của bạn.https://kubernetes.default.svclà lựa chọn phổ biến cho các triển khai trong cluster.--dest-namespace: Namespace Kubernetes nơi ứng dụng nên được triển khai.--sync-policy automated: Cờ này rất cần thiết cho GitOps! Nó hướng dẫn ArgoCD tự động đồng bộ hóa mọi thay đổi được phát hiện giữa Git và cluster.--auto-prune: Cho phép ArgoCD xóa các tài nguyên khỏi cluster không còn được định nghĩa trong Git.--self-heal: Nếu một tài nguyên bị sửa đổi hoặc xóa thủ công trong cluster, ArgoCD sẽ tự động khôi phục nó về trạng thái được định nghĩa trong Git.
Ngoài ra, bạn có thể định nghĩa ArgoCD Application này dưới dạng một manifest Kubernetes và áp dụng trực tiếp:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-nginx-app
namespace: argocd
spec:
destination:
namespace: default
server: https://kubernetes.default.svc
project: default
source:
path: .
repoURL: <YOUR_GIT_REPO_URL> # Thay thế bằng URL kho lưu trữ của bạn
targetRevision: HEAD
syncPolicy:
automated:
prune: true
selfHeal: true
Lưu cấu hình này dưới dạng argocd-app.yaml. Sau đó, áp dụng nó bằng cách sử dụng kubectl apply -n argocd -f argocd-app.yaml.
Bước 4: Quan sát việc triển khai và đồng bộ hóa tự động
Sau khi tạo ArgoCD Application, bạn sẽ thấy nó ngay lập tức xuất hiện trong giao diện người dùng ArgoCD. Ban đầu, nó có thể sẽ hiển thị là OutOfSync. Sau đó, nó sẽ chuyển sang Syncing, và cuối cùng là Healthy và Synced, khi nó áp dụng các manifest Nginx của bạn vào cluster Kubernetes.
Bạn cũng có thể xác minh trạng thái của nó bằng cách sử dụng CLI:
# Liệt kê tất cả các ứng dụng
argocd app list
# Lấy trạng thái chi tiết của ứng dụng của bạn
argocd app get my-nginx-app
Xác minh triển khai Nginx của bạn đang chạy trong Kubernetes:
kubectl get deployments -n default
kubectl get pods -n default -l app=nginx
kubectl get services -n default
Chứng kiến khả năng tự phục hồi
Để quan sát khả năng tự phục hồi, hãy mô phỏng sự lệch cấu hình. Xóa thủ công một trong các pod Nginx:
# Lấy tên của một trong các pod Nginx của bạn
NGINX_POD=$(kubectl get pods -n default -l app=nginx -o jsonpath='{.items[0].metadata.name}')
# Xóa pod thủ công
kubectl delete pod $NGINX_POD -n default
Giám sát giao diện người dùng ArgoCD hoặc thực thi argocd app get my-nginx-app. Bạn sẽ thấy ứng dụng chuyển sang OutOfSync trong giây lát. Hầu như ngay lập tức, ArgoCD sẽ phát hiện sự khác biệt và tạo lại pod đã bị xóa. Hành động này khôi phục ứng dụng về trạng thái Healthy và Synced. Sự hòa giải liên tục này là một nguyên tắc cơ bản của GitOps.
Cập nhật tự động từ Git
Hãy tiếp tục bằng cách cập nhật ứng dụng Nginx của chúng ta. Sửa đổi tệp my-nginx-app/deployment.yaml để chỉ định một hình ảnh Nginx mới hơn:
# ... (các dòng trước)
containers:
- name: nginx
image: nginx:1.23.4-alpine # Đã thay đổi từ 1.21.6-alpine
ports:
- containerPort: 80
# ... (các dòng còn lại)
Commit thay đổi này và đẩy nó lên kho lưu trữ Git của bạn:
cd my-nginx-app # Nếu bạn chưa ở trong thư mục này
git add deployment.yaml
git commit -m "# Cập nhật hình ảnh Nginx lên 1.23.4-alpine"
git push origin main
Trong vòng vài giây—thời gian chính xác tùy thuộc vào khoảng thời gian đồng bộ của ArgoCD, mặc định là 3 phút, hoặc ngay lập tức nếu webhook được cấu hình—ArgoCD sẽ phát hiện thay đổi trong kho lưu trữ Git của bạn. Sau đó, nó sẽ đánh dấu ứng dụng của bạn là OutOfSync. Tiếp theo, nó sẽ tự động triển khai phiên bản hình ảnh Nginx mới vào cluster Kubernetes của bạn. Bạn có thể quan sát quá trình triển khai trong giao diện người dùng ArgoCD và bằng cách chạy kubectl get deployments -n default.
Trong môi trường sản xuất, cách tiếp cận này luôn mang lại kết quả ổn định. Nó mang lại sự an tâm đáng kể, khi biết rằng các môi trường vẫn được căn chỉnh với hệ thống kiểm soát phiên bản. Sự căn chỉnh này giúp việc khôi phục trở nên đơn giản và đơn giản hóa việc gỡ lỗi các vấn đề cấu hình.
Kết luận: Tương lai của CD là GitOps
GitOps, được hỗ trợ bởi các công cụ như ArgoCD, trình bày một cách tiếp cận mang tính biến đổi đối với phân phối liên tục cho Kubernetes. Bằng cách thiết lập Git làm nguồn chân lý duy nhất và cho phép hòa giải liên tục, các nhóm có thể đạt được các triển khai tự động cao, đáng tin cậy và có thể kiểm toán.
Phương pháp này không chỉ đơn giản hóa các hoạt động và giảm thiểu lỗi thủ công, mà còn trao quyền cho các nhóm phát triển kiểm soát tốt hơn các triển khai của họ. Điều này thúc đẩy một văn hóa DevOps thực sự cộng tác và hiệu quả. Áp dụng GitOps với ArgoCD có nghĩa là tiến tới một tương lai nơi việc triển khai cơ sở hạ tầng và ứng dụng có thể dự đoán được, minh bạch và ổn định nhất quán.

