Ở đây, chúng ta sẽ tìm hiểu cách sử dụng ArgoCD và GitLab để triển khai ứng dụng của chúng ta trên một cụm Kubernetes.
GitOps được xem là một trải nghiệm tập trung vào nhà phát triển, cho phép các thành viên trong nhóm quản lý và kiểm soát các khả năng nội bộ của các ứng dụng cloud-native. Nó cung cấp cho các nhà phát triển một chiến lược phát triển ứng dụng có thể được sử dụng để khởi động các yêu cầu kéo (pull requests) như một phương tiện để tăng tốc và đơn giản hóa các thay đổi cơ sở hạ tầng. GitOps hoạt động như một công cụ để giúp doanh nghiệp cung cấp các tính năng mới bằng cách tự động hóa Quá trình Giao hàng Liên tục của các ứng dụng cloud-native.
NỘI DUNG:
– Architecture
– Application Code Repository
– GitOps Repository
– Kubernetes cluster
– Cài đặt ArgoCD
– Cài đặt GitOps
– Trigger
Kiến trúc sẽ được minh họa trong hình ảnh dưới.
Hãy hiểu kiến trúc này một cách nhanh chóng.
- APPLICATION CODE REPOSITORY: Nhà phát triển của chúng ta đẩy mã nguồn ứng dụng vào kho mã nguồn GitLab này, và nhóm DevOps đã tạo một Pipeline để xây dựng và đẩy một hình ảnh Docker của ứng dụng của chúng ta vào GitLab Container Registry.
- GITOPS REPOSITORY: Đây là nơi lưu các files manifest của chúng ta. Giống như đứa trẻ trong hình ảnh, nó cũng chưa hiểu nội dung của GITOPS REPOSITORY này, tôi hiểu rằng bạn cũng đang bối rối…Đừng lo, chúng ta sẽ thảo luận nó chi tiết hơn ở phần dưới.
- ARGOCD: Sử dụng Helm chart, tôi đã cài đặt Argocd lên cụm K8s và liên kết nó với repository GitOps sẽ được sử dụng để triển khai ứng dụng.
- AWS EKS: Là cụm Kubernetes được quản lý bởi AWS Cloud.
APPLICATION CODE REPOSITORY:
- Tạo một repository có tên là “Application” trong dự án GitLab của bạn.
- Yêu cầu cho các nhà phát triển đẩy mã nguồn ứng dụng vào kho này ở nhánh chính.
- Bạn có thể sử dụng ứng dụng nodejs đơn giản này để triển khai thử nghiệm, nó đơn giản chỉ in ra màn hình nội dung là “Welcome“.
- Tạo một DockerFile ở nhánh chính để xây dựng một Docker Image cho ứng dụng của bạn (nó sẽ khác nhau tùy thuộc vào ngôn ngữ mà chúng ta sử dụng để tạo ứng dụng). Ví dụ, đối với ứng dụng nodejs ở trên, đây là Dockerfile bạn có thể sử dụng:
FROM node:18
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 4000
CMD [ "npm", "run", "dev" ]
Bây giờ là lúc để xây dựng Docker image sau khi đã tạo Dockerfile. Để làm được điều này, phải thiết lập một CI/CD pipeline trong repository GitLab. Định nghĩa pipeline trong GitLab CI được lưu trữ trong file .gitlab-ci.yml ở nhánh chính của repository.
GitLab cũng cung cấp cho chúng ta Registry Container nơi chúng ta có thể lưu trữ Docker images của mình, trong bài thực hành này chúng ta sẽ tìm hiểu cách sử dụng nó.
Mục đích của CI/CD là để mỗi khi một trong các nhà phát triển của chúng ta đẩy, commit hoặc merge mã vào nhánh chính của kho lưu trữ, chúng ta muốn Docker image được tạo và đẩy tự động vào container registry. Chúng ta phải thiết lập một CI/CD pipeline để tự động hóa việc này, pipeline này sẽ bắt đầu khi nhánh chính của kho lưu trữ kích hoạt.
Tạo file “.gitlab-ci.yml” trong nhánh chính của kho lưu trữ này. Ở đây chúng ta sẽ thêm một stage trong file này được đặt tên là “build-push”, sẽ xây dựng Dockerfile và đẩy hình ảnh vào GitLab Container Registry.
stages:
- build-push
Đây là cấu hình cho “build-push stage”:
image: docker:19.03.12
variables:
DOCKER_HOST: tcp://docker:2375/
DOCKER_TLS_CERTDIR: ""
services:
- docker:19.03.12-dind
build:
stage: build-push
variables:
IMAGE_TAG: $CI_REGISTRY_IMAGE:latest
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $IMAGE_TAG .
- docker push $IMAGE_TAG
“$CI_REGISTRY_USER, $CI_REGISTRY_PASSWORD, $CI_REGISTRY_IMAGE và $CI_REGISTRY” là các biến mặc định của GitLab, chúng ta không cần phải định nghĩa chúng trong GitLab của chúng ta.
Sau khi tạo file “.gitlab-ci.yml” này, chúng ta có thể thấy một pipeline đang chạy trong mục “Gitlab Repo” >> “CI/CD” >> “Pipelines”.
Nếu không có lỗi, bạn có thể thấy trạng thái của Pipeline là “passed” (đã thành công).
Sau khi Pipeline thành công, bạn có thể xem Docker image của mình trong “GitLab Repo” >> “Packages and registries” >> “Container Registry”.
Bạn đã hoàn thành phần build ứng dụng của mình, bây giờ chúng ta tiếp tục với Repo GitOps.
REPO GITOPS:
Hãy làm rõ sự nhầm lẫn của cậu bé trẻ và của bạn…Tạo một Repo có tên là “GitOps” trong dự án GitLab của bạn. Trong Repo này, chúng ta sẽ tạo ba thư mục có tên là “base”, “envs” và “variants”.
THƯ MỤC BASE:
Trong thư mục “base”, chúng ta sẽ đặt các file định dạng thông thường của k8s cùng với file kustomization.yaml.
Dưới đây là các file có trong thư mục “base”:
- deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: example-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nodejs
template:
metadata:
labels:
app: nodejs
spec:
containers:
- name: application-container
image: registry.gitlab.com/<GITLAB-PROJECT>/<IMAGE-NAME>:latest
ports:
- containerPort: 80
imagePullSecrets:
- name: gitlab-creds-secret
- service.yaml
apiVersion: v1
kind: Service
metadata:
name: test
spec:
type: LoadBalancer
selector:
app: nodejs
ports:
- protocol: TCP
port: 80
targetPort: 3000
- kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ./deployment.yaml
- ./service.yaml
Đây là các cấu hình chung của tất cả các file, chúng ta có thể thay đổi số lượng replicas, image, namespace,… theo từng môi trường, nhưng lưu ý chúng ta không được thay đổi trong thư mục base này.
Kustomize là một công cụ giúp tạo các phiên bản tùy chỉnh của các file YAML cơ bản của Kubernetes mà không cần chỉnh sửa trực tiếp các file YAML gốc. Việc sử dụng Kustomize giúp quản lý các thay đổi và đảm bảo rằng các thay đổi đó được theo dõi qua Git. Kustomize là một phần của dự án Kubernetes và được bao gồm trong công cụ kubectl. Nó có thể được sử dụng để quản lý và tùy chỉnh các tài nguyên Kubernetes như deployments, services, config maps, cũng như tạo ra các tài nguyên Kubernetes tùy chỉnh.
ENVS Folder:
Trong thư mục “envs” chúng ta có thể định nghĩa tất cả các môi trường mà chúng ta muốn thêm cho ứng dụng của mình, ví dụ như trong blog này tôi tạo ba môi trường “dev”, “prod” và “test”. Vì vậy, tôi đã tạo ba thư mục trong thư mục “envs” với tên lần lượt là “dev”, “prod” và “test”.
Bây giờ, giống như trong môi trường phát triển, tôi muốn triển khai một bản sao K8s của ứng dụng và tôi cũng muốn triển khai bằng một hình ảnh Docker khác. Mà không cần thay đổi các file mẫu chung đã có sẵn trong thư mục gốc, điều này có thể được thực hiện bằng cách sử dụng kustomization.
Tạo các file sau trong thư mục “envs/dev”.
- replicas.yml: Define replicas
apiVersion: apps/v1
kind: Deployment
metadata:
name: example-deployment
spec:
replicas: 1
- version.yml: Define image
apiVersion: apps/v1
kind: Deployment
metadata:
name: example-deployment
spec:
template:
spec:
containers:
- name: application-container
image: registry.gitlab.com/<GITLAB-PROJECT>/<IMAGE>-dev:latest
- kustomization.yml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: example-dev
namePrefix: dev-
resources:
- ../../base
#components:
# - ../../variants/prod
# - ../../variants/asia
patchesStrategicMerge:
- replicas.yml
- version.yml
Cách sử dụng Kustomize để cập nhật file manifest YAML trong môi trường phát triển (dev environment). Kustomize cho phép áp dụng các thay đổi lên các file YAML cơ sở, cho phép tùy chỉnh mà không cần phải chỉnh sửa các file YAML cơ sở đó. Kustomize là một phần của dự án Kubernetes và được bao gồm trong công cụ kubectl. Nó có thể được sử dụng để quản lý và tùy chỉnh các nguồn tài nguyên Kubernetes, chẳng hạn như các deployment, service và config map, cũng như tạo ra các nguồn tài nguyên Kubernetes tùy chỉnh.
Các file được tạo trong thư mục “envs/dev” cung cấp cách triển khai ứng dụng trên môi trường phát triển, trong đó có hai bản sao của ứng dụng Kubernetes và một Docker image khác được triển khai. Bằng cách sử dụng Kustomize, các file YAML chung trong thư mục “base” không bị thay đổi, mà chỉ thay đổi các thông số như số lượng bản sao, ảnh Docker, tên và không gian tên (namespace) trong các file YAML được đặt trong thư mục “envs/dev”. File Kustomization.yml cho biết nơi tìm kiếm các file YAML chung, file YAML được sử dụng để thay đổi (replicas.yml và version.yml), và các thông số khác được áp dụng cho pod được triển khai.
Hãy tạo các file sau trong thư mục “envs/prod”.
- replicas.yml: Define replicas
apiVersion: apps/v1
kind: Deployment
metadata:
name: example-deployment
spec:
replicas: 2
- version.yml: Define image
apiVersion: apps/v1
kind: Deployment
metadata:
name: example-deployment
spec:
template:
spec:
containers:
- name: application-container
image: registry.gitlab.com/<GITLAB-PROJECT>/<IMAGE>:latest
Ở đây tôi sử dụng hình ảnh mà chúng ta đã tạo ra ở trên trong thư mục application bằng cách sử dụng Pipeline.
- kustomization.yml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: example-prod
namePrefix: prod-
resources:
- ../../base
#components:
# - ../../variants/prod
# - ../../variants/asia
patchesStrategicMerge:
- replicas.yml
- version.yml
VARIANTS FOLDER:
Thư mục “variants” cho phép chúng ta chỉ định nhiều biến thể nơi chúng ta muốn có những thay đổi giống nhau, chẳng hạn như “prod” và “non-prod”. Môi trường sản xuất của chúng ta có thể được bao gồm trong “prod”, trong khi các môi trường phát triển và kiểm tra có thể được bao gồm trong “non-prod”.
Tuy nhiên, trong bài viết này, chúng ta bỏ qua phần “variants” nhưng nó chứa các file tương tự như các file đã được nêu ở trên nhưng cho các biến thể khác nhau.
Sau khi hoàn tất GitOps Repo, chúng ta tiếp tục sang phần Kubernetes.
KUBERNETES CLUSTER PART:
Trước khi triển khai các môi trường ở trên, chúng ta cần phải tạo các “namespace” và “k8s Secret” có tên là “gitlab-creds-secret” trong cùng namespace, cung cấp thông tin đăng nhập Docker cho registry container Gitlab của chúng ta và cho phép các pod kéo image.
Chạy lệnh bên dưới để tạo các “namespace”.
kubectl create ns example-dev
kubectl create ns example-prod
Dưới đây, chúng ta cần tạo một Secret tên là “gitlab-creds-secret” để cung cấp thông tin đăng nhập Docker cho container registry của Gitlab và cho phép các pod kéo image về. Hãy tham khảo blog sau để tạo Secret:
https://chris-vermeulen.com/using-gitlab-registry-with-kubernetes/
Đảm bảo tạo Secret đó trong cả hai namespace đã được tạo ở trên với tên là “gitlab-creds-secret”.
Cài đặt Argocd.
Ở đây, chúng ta sẽ triển khai Argocd trên cụm EKS của mình bằng cách sử dụng Helm chart.
Chạy các lệnh sau:
kubectl create namespace argocd
helm repo add argo https://argoproj.github.io/argo-helm
helm install argocd -n argocd argo/argocd - values values.yaml
Bạn có thể tải file Values.yaml từ đường link bên dưới:
https://github.com/argoproj/argo-helm/blob/main/charts/argo-cd/values.yaml
Bạn có thể xem các pod đang chạy trong namespace argocd bằng cách sử dụng lệnh.
- Bây giờ bạn có thể tạo ra ingress để truy cập argocd nếu bạn có DNS hoặc bạn có sử dụng service argocd với “LoadBalancer”.
- Chỉnh sửa service có tên là “argocd-server” và cập nhật lại với “LoadBalancer”.
Sau đó, bạn sẽ nhận được “địa chỉ IP bên ngoài (external-IP)”. - Bây giờ bạn có thể truy cập giao diện người dùng argocd từ trình duyệt bằng liên kết: http://<external-ip>:80
Bạn sẽ thấy trang web như hình ảnh trên.
Để lấy mật khẩu, hãy chạy lệnh sau:
kubectl -n argocd get secret argocd-secret -o jsonpath="{.data.clearPassword}" | base64 -d
“Username”: “admin”
Như vậy bạn đã hoàn thành thiết lập Argocd.
CÀI ĐẶT GITOPS:
Sau khi đã thiết lập Argocd, đến lúc triển khai ứng dụng bằng Argocd.
Vào “Argocd” >> “Settings” >> “Repositories” Ở đây, bạn muốn thêm kho lưu trữ gitlab của mình để kết nối nó với ArgoCD.
Thêm URL kho lưu trữ của bạn, tên đăng nhập và mật khẩu (Access Token, mà bạn đã sử dụng để tạo bí mật Docker creds ở các bước trên).
Nhấp vào kết nối. Sau khi mọi thứ ổn định, bạn có thể thấy trạng thái kết nối là “Successfull“.
Bây giờ đi đến “Argocd” >> “Applications” và nhấp vào “+ NEW APP.
- “Application Name”: ví dụ: example-dev-app
- “Project Name”: mặc định
- “SYNC POLICY”: Tự động và chọn cả hai tùy chọn bên dưới
- “SYNC OPTIONS”: Chọn các tùy chọn như trên
- “Repository URL”: Sẽ được tự động hiển thị nếu bạn đã thêm nó trước đó vào Argocd.
- “Path”: Tự động hiển thị tất cả các đường dẫn của GitOps repo của bạn, chọn một trong những đường dẫn mà bạn muốn sử dụng, ở đây tôi đã sử dụng “envs/dev”.
- “Cluster URL”: Tự động hiển thị nếu bạn triển khai argocd trên cụm của mình.
- “Namespace”: Xác định không gian tên mà bạn muốn triển khai ứng dụng này, chúng ta đã tạo không gian tên này trong các bước trước.
Nhấp vào “CREATE”.
Nó sẽ bắt đầu triển khai ứng dụng của bạn bằng cấu hình mà bạn cung cấp trong thư mục “envs/dev”. Sau khi tất cả hoàn tất, bạn có thể xem đầu ra như dưới đây:
Chạy các lệnh dưới đây để xem ứng dụng đã triển khai chưa.
kubectl get pods -n example-dev
kubectl get svc -n example-dev
Sau khi đã hoàn thành, bạn có thể sử dụng dịch vụ LoadBalancer để truy cập ứng dụng của bạn trong trình duyệt.
Bây giờ bạn có thể tạo ứng dụng khác trong argocd để triển khai môi trường prod, chỉ cần thay đổi “path” thành “envs/prod”.
Bạn đã hoàn thành cài đặt GitOps.
TRIGGER
Bây giờ khi cài đặt đã hoàn tất. GitOps Repo bây giờ phải được kích hoạt thủ công mỗi khi Pipeline kích hoạt trong kho ứng dụng để triển khai lại ứng dụng với các thay đổi mới nhất. Sau khi GitOps repository của bạn được kích hoạt, ArgoCD sẽ bắt đầu đồng bộ hóa nó tự động.
TRIGGER TỰ ĐỘNG:
Để kích hoạt GitOps repo tự động bằng Pipeline, bạn phải thêm một giai đoạn nữa trong ” .gitlab-ci.yml ” của mình:
deploy-dev:
stage: deploy-dev
image: alpine:3.8
before_script:
- apk add --no-cache git curl bash
- curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
- mv kustomize /usr/local/bin/
- git remote set-url origin @gitlab.com/<USER>/gitops.git">https://${CI_USERNAME}:${CI_PUSH_TOKEN}@gitlab.com/<USER>/gitops.git
- git config --global user.email "gitlab@gitlab.com"
- git config --global user.name "GitLab CI/CD"
script:
- git checkout -B master
- cd deployment/dev
- kustomize edit set image $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- cat kustomization.yaml
- git commit -am '[skip ci] DEV image update'
- git push origin main
only:
- main
Cảm ơn rất nhiều đã đọc bài viết này. Tôi hy vọng nó đã giúp bạn hiểu được cách GitOps hoạt động. Nếu bạn có bất kỳ vấn đề nào, hãy để lại bình luận hoặc liên hệ với tôi qua Zalo ở dưới màn hình.
Nguồn tham khảo https://servjeetj68.medium.com/argocd-gitops-k8s-ci-cd-how-to-deploy-application-on-top-of-kubernetes-using-gitops-d69d5667cb0a