Giới thiệu về Jenkins
Jenkins là một nền tảng tự động hóa mã nguồn mở hàng đầu, được sử dụng rộng rãi cho các dự án Tích hợp Liên tục (CI) và Phân phối Liên tục (CD). Nền tảng này cho phép tự động hóa các tác vụ liên quan đến xây dựng, kiểm thử và triển khai phần mềm trên nhiều môi trường khác nhau.
Mục đích của Jenkins
- Tự động hóa liên tục quá trình xây dựng và kiểm thử các dự án phần mềm.
- Giám sát quy trình phát triển, nhanh chóng phát hiện và xử lý các vấn đề.
- Tự động thực hiện các tác vụ định kỳ.
Tại sao nên sử dụng Jenkins?
Việc áp dụng Jenkins mang lại nhiều lợi ích quan trọng trong quy trình phát triển phần mềm:
- Giảm thiểu công việc thủ công: Tự động hóa toàn bộ quy trình từ lấy mã nguồn, biên dịch, đóng gói, kiểm thử đến triển khai lên máy chủ, loại bỏ các tác vụ lặp đi lặp lại.
- Phản hồi nhanh chóng: Khi có thay đổi mã nguồn (ví dụ: push lên Git), Jenkins có thể tự động nhận diện, biên dịch, kiểm thử và triển khai đến môi trường mong muốn (dev/test/production).
- Đảm bảo môi trường nhất quán: Loại bỏ tình trạng "chạy được trên máy tôi nhưng không chạy được trên máy người khác" bằng cách cung cấp một môi trường xây dựng và triển khai chuẩn hóa.
- Miễn phí và mã nguồn mở: Là một giải pháp được cộng đồng hỗ trợ rộng rãi và được nhiều doanh nghiệp tin dùng.
- Hỗ trợ đa dạng công nghệ: Tương thích với hầu hết các ngôn ngữ và công cụ phổ biến như Java, Python, Go, Docker, Kubernetes, Git, Maven, Gradle, v.v.
Tóm lại, sử dụng Jenkins giúp giảm bớt công việc thủ công, hạn chế lỗi, tự động hóa quy trình xây dựng và triển khai, đồng thời đảm bảo việc bàn giao dự án ổn định và hiệu quả.
Triển khai Jenkins trên Kubernetes
Phần này sẽ hướng dẫn cách triển khai Jenkins trong môi trường Kubernetes. Chúng ta sẽ sử dụng phương pháp cấp phát động Persistent Volume (PV), nên chỉ cần khai báo Persistent Volume Claim (PVC).
1. Tạo Service Account
Service Account là tài khoản mà Pod của Jenkins sẽ sử dụng để chạy và tương tác với các tài nguyên Kubernetes khác. Chúng ta cần cấp quyền thích hợp cho tài khoản này.
# service-account-jenkins.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: jenkins-cluster-admin-role # Tên ClusterRole để Jenkins có quyền quản trị
rules:
- apiGroups: [""] # Quyền truy cập các tài nguyên core API (Pod, Service, ConfigMap, v.v.)
resources: ["*"] # Truy cập tất cả tài nguyên
verbs: ["*"] # Thực hiện mọi hành động (get, list, watch, create, update, delete)
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: jenkins-sa # Tên ServiceAccount cho Jenkins
namespace: ci-cd # Namespace để triển khai Jenkins
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: jenkins-cluster-admin-binding # Tên ClusterRoleBinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: jenkins-cluster-admin-role # Tham chiếu đến ClusterRole đã tạo
subjects:
- kind: ServiceAccount
name: jenkins-sa # Tham chiếu đến ServiceAccount đã tạo
namespace: ci-cd # Trong namespace ci-cd
Đầu tiên, tạo namespace và sau đó áp dụng cấu hình:
kubectl create ns ci-cd
kubectl apply -f service-account-jenkins.yaml
2. Tạo Persistent Volume Claim (PVC)
PVC sẽ yêu cầu một Persistent Volume để lưu trữ dữ liệu của Jenkins, đảm bảo dữ liệu không bị mất khi Pod khởi động lại hoặc di chuyển.
# jenkins-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: jenkins-data-pvc # Tên PVC
namespace: ci-cd # Trong namespace ci-cd
spec:
accessModes:
- ReadWriteOnce # Chế độ truy cập: chỉ một Pod có thể ghi và đọc
resources:
requests:
storage: 15Gi # Yêu cầu 15GB dung lượng lưu trữ
kubectl apply -f jenkins-pvc.yaml
3. Triển khai Deployment
Deployment sẽ quản lý Pod chạy ứng dụng Jenkins. Chúng ta sẽ gắn PVC đã tạo vào Pod này để lưu trữ dữ liệu tại /var/jenkins_home.
# jenkins-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: jenkins-master # Tên Deployment
namespace: ci-cd # Trong namespace ci-cd
labels:
app: jenkins-server-app # Label cho Deployment
spec:
replicas: 1 # Chỉ một bản sao của Jenkins master
selector:
matchLabels:
app: jenkins-server-app # Selector để Pod khớp với Deployment
strategy:
type: Recreate # Đảm bảo Pod cũ được dừng trước khi Pod mới khởi động
template:
metadata:
labels:
app: jenkins-server-app # Label cho Pod
spec:
serviceAccountName: jenkins-sa # Sử dụng ServiceAccount đã tạo
volumes:
- name: jenkins-storage # Tên volume
persistentVolumeClaim:
claimName: jenkins-data-pvc # Gắn với PVC đã tạo
containers:
- name: jenkins # Tên container
image: jenkins/jenkins:lts # Sử dụng phiên bản LTS ổn định của Jenkins
imagePullPolicy: IfNotPresent # Chỉ kéo ảnh nếu chưa có
securityContext:
runAsUser: 0 # Chạy với quyền root bên trong container (để Jenkins có thể tạo các file cần thiết)
volumeMounts:
- name: jenkins-storage # Gắn volume
mountPath: /var/jenkins_home # Đường dẫn lưu trữ dữ liệu Jenkins bên trong container
ports:
- name: http-port # Cổng HTTP cho giao diện người dùng
containerPort: 8080
- name: agent-port # Cổng JNLP cho kết nối agent
containerPort: 50000
resources:
limits:
memory: "2Gi" # Giới hạn bộ nhớ 2GB
cpu: "1" # Giới hạn CPU 1 core
requests:
memory: "1Gi" # Yêu cầu bộ nhớ 1GB
cpu: "0.5" # Yêu cầu CPU 0.5 core
livenessProbe: # Kiểm tra sức khỏe của Pod
httpGet:
path: "/login"
port: 8080
initialDelaySeconds: 90
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 6
readinessProbe: # Kiểm tra khả năng sẵn sàng của Pod để nhận lưu lượng
httpGet:
path: "/login"
port: 8080
initialDelaySeconds: 90
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
kubectl apply -f jenkins-deployment.yaml
Kiểm tra trạng thái của Pod (quá trình khởi động có thể mất vài phút do các kiểm tra sức khỏe):
kubectl get pod -n ci-cd
4. Mở dịch vụ (Service)
Service sẽ cho phép truy cập vào giao diện web của Jenkins từ bên ngoài Cluster Kubernetes.
# jenkins-service.yaml
apiVersion: v1
kind: Service
metadata:
name: jenkins-web-svc # Tên Service
namespace: ci-cd # Trong namespace ci-cd
spec:
selector:
app: jenkins-server-app # Selector để Service tìm kiếm Pod của Jenkins
type: NodePort # Sử dụng NodePort để truy cập từ bên ngoài Cluster
ports:
- name: http-web # Cổng cho giao diện web Jenkins
port: 8080 # Cổng Service
targetPort: 8080 # Cổng container
nodePort: 30000 # Cổng NodePort để truy cập từ bên ngoài (ví dụ: 30000)
- name: jnlp-agent # Cổng cho kết nối Jenkins Agent
port: 50000 # Cổng Service
targetPort: 50000 # Cổng container
nodePort: 31000 # Cổng NodePort cho agent (ví dụ: 31000)
kubectl apply -f jenkins-service.yaml
Kiểm tra thông tin Service:
kubectl get svc -n ci-cd
Bạn có thể truy cập Jenkins qua địa chỉ IP của bất kỳ Node Kubernetes nào trong cluster cùng với NodePort (ví dụ: http://<node-ip>:30000).
Cấu hình Jenkins ban đầu
1. Đăng nhập và lấy mật khẩu quản trị
Sau khi Jenkins khởi động hoàn tất, bạn cần mật khẩu quản trị ban đầu để đăng nhập. Mật khẩu này thường được lưu trong thư mục dữ liệu của Jenkins.
Để lấy mật khẩu, bạn có thể thực hiện như sau (nếu PVC của bạn được ánh xạ ra một thư mục trên host, bạn có thể kiểm tra trực tiếp tại đó):
# Đầu tiên, tìm tên Pod Jenkins
JENKINS_POD=$(kubectl get pod -n ci-cd -l app=jenkins-server-app -o jsonpath='{.items[0].metadata.name}')
# Sau đó, lấy mật khẩu từ bên trong Pod
kubectl exec -ti -n ci-cd $JENKINS_POD -- cat /var/jenkins_home/secrets/initialAdminPassword
Sử dụng mật khẩu hiển thị để đăng nhập vào giao diện web Jenkins.
2. Bỏ qua cài đặt plugin mặc định
Khi đăng nhập lần đầu, Jenkins sẽ hỏi bạn có muốn cài đặt các plugin mặc định hay không. Nên chọn "Select plugins to install" hoặc "Install suggested plugins" và sau đó bỏ chọn tất cả hoặc chọn "None" nếu có tùy chọn. Lý do là các plugin mặc định thường được tải từ máy chủ ở nước ngoài (như Google), có thể gặp vấn đề về kết nối ở một số khu vực.
3. Thiết lập thông tin người dùng
Sau khi bỏ qua hoặc chọn plugin, bạn sẽ được yêu cầu tạo một tài khoản quản trị viên. Hãy cung cấp tên người dùng, mật khẩu và email.
4. Cấu hình ngôn ngữ (tiếng Việt)
Để sử dụng Jenkins với giao diện tiếng Việt, bạn cần cài đặt plugin "Localization: Chinese (Simplified)" (mặc dù tên là tiếng Trung, plugin này bao gồm cả gói ngôn ngữ tiếng Việt). Sau khi cài đặt, bạn có thể thay đổi ngôn ngữ trong phần cài đặt người dùng hoặc cài đặt chung của Jenkins.
5. Thay đổi nguồn cập nhật plugin
Để cải thiện tốc độ tải và cài đặt plugin, bạn nên thay đổi máy chủ cập nhật plugin mặc định của Jenkins sang một mirror trong nước (ví dụ: của Đại học Thanh Hoa hoặc Huawei Cloud). Truy cập Manage Jenkins > Manage Plugins > Advanced.
Thay đổi URL trong phần "Update Site" thành:
https://mirrors.tuna.tsinghua.edu.cn/jenkins/update-center.json(Đại học Thanh Hoa)https://mirrors.huaweicloud.com/jenkins/update-center.json(Huawei Cloud)
Sau khi thay đổi trên giao diện web, bạn cũng cần đảm bảo rằng file cấu hình bên trong container Jenkins được cập nhật. Sau khi Jenkins khởi động lại, kiểm tra file /var/jenkins_home/updates/default.json. Nếu cần, bạn có thể chỉnh sửa thủ công:
# Lấy tên Pod Jenkins
JENKINS_POD=$(kubectl get pod -n ci-cd -l app=jenkins-server-app -o jsonpath='{.items[0].metadata.name}')
# Truy cập vào bên trong Pod
kubectl exec -ti -n ci-cd $JENKINS_POD -- /bin/bash
# Bên trong Pod, chỉnh sửa file default.json
sed -i 's/https:\/\/updates.jenkins.io\/download/https:\/\/mirrors.tuna.tsinghua.edu.cn\/jenkins/g' /var/jenkins_home/updates/default.json
sed -i 's/http:\/\/www.google.com/https:\/\/www.baidu.com/g' /var/jenkins_home/updates/default.json # Thay đổi liên kết kiểm tra kết nối nếu cần
exit
Sau đó, khởi động lại Jenkins để áp dụng thay đổi:
kubectl exec -ti -n ci-cd $JENKINS_POD -- jenkins-cli safe-restart
# hoặc truy cập http://<node-ip>:30000/restart trên trình duyệt
6. Cài đặt các plugin cần thiết
Sau khi cấu hình nguồn cập nhật, bạn có thể truy cập Manage Jenkins > Manage Plugins > Available và tìm kiếm các plugin cần thiết cho dự án của mình. Nên cài đặt tất cả các plugin cần thiết trong một lần và sau đó khởi động lại Jenkins.
Các plugin quan trọng thường dùng:
- Git: Để kéo mã nguồn từ kho Git.
- Pipeline: Cho phép định nghĩa quy trình CI/CD dưới dạng mã.
- Kubernetes: Để tích hợp Jenkins với Kubernetes, cho phép tạo các agent động trên Kubernetes.
- Localization: Chinese (Simplified): Để có giao diện tiếng Việt.
- SSH / Publish Over SSH: Để thực hiện các lệnh SSH từ Jenkins đến các máy chủ khác.
- Maven / Gradle / NodeJS: Tùy thuộc vào loại dự án (Java, Node.js, v.v.).
- DingTalk / Slack / Email Extension: Các plugin thông báo kết quả xây dựng.
- Role-based Authorization Strategy: Quản lý quyền hạn chi tiết cho người dùng.
- Git Parameter: Cho phép chọn nhánh Git động khi chạy job.
- HTTP Request Plugin: Thực hiện các HTTP request trong pipeline.
- Pipeline Utility Steps: Cung cấp các bước tiện ích cho pipeline (nén, giải nén, tìm file).
Quản lý Jenkins cơ bản
1. Cấu hình thông báo Email
Để Jenkins có thể gửi thông báo qua email (ví dụ: khi một build thất bại), bạn cần cấu hình SMTP server. Truy cập Manage Jenkins > Configure System > cuộn xuống phần Email Notification.
Điền các thông tin cần thiết:
- SMTP Server: (Ví dụ: smtp.qq.com cho QQ Mail)
- Default user e-mail suffix: (@example.com)
- System Admin e-mail address: (Địa chỉ email của người gửi, ví dụ: user@qq.com)
- Use SMTP Authentication: (Tick vào và điền Username/Password, Password ở đây là mã ủy quyền (authorization code) của email, không phải mật khẩu đăng nhập thông thường.)
- Use SSL/TLS: (Tick vào nếu máy chủ SMTP yêu cầu)
- SMTP Port: (Ví dụ: 465 cho SSL/TLS hoặc 587 cho STARTTLS)
Sau đó, bạn có thể sử dụng nút "Test configuration" để kiểm tra xem cấu hình email đã hoạt động hay chưa.
2. Quản lý Chứng chỉ (Credentials)
Jenkins cần các chứng chỉ để tương tác với các hệ thống bên ngoài như kho mã nguồn (GitLab, GitHub), các máy chủ SSH, hoặc các cluster Kubernetes. Truy cập Manage Jenkins > Manage Credentials > System > Global credentials.
Các loại chứng chỉ phổ biến:
- Username with password: Để kết nối với kho Git (đối với GitLab phiên bản mới, nên sử dụng Personal Access Token thay vì mật khẩu người dùng), hoặc SSH tới máy chủ.
- SSH Username with private key: Để kết nối SSH với các máy chủ mà không cần mật khẩu.
- Secret text: Lưu trữ các token, API key.
- Kubernetes Service Account: Khi tích hợp với Kubernetes để tạo agent động.
Ví dụ, để kết nối với GitLab, bạn có thể tạo chứng chỉ "Username with password" với username là tên người dùng GitLab và password là Personal Access Token đã tạo trên GitLab.
3. Kiểm tra công việc (Job) đơn giản
Tạo một công việc "Freestyle project" đơn giản để kiểm tra kết nối với Git và thực thi lệnh.
- Trên trang chủ Jenkins, chọn
New Item>Freestyle project, đặt tên cho job và nhấn OK. - Trong phần
Source Code Management, chọnGit. - Nhập
Repository URL(ví dụ:https://gitlab.com/your-repo/your-project.git). - Chọn chứng chỉ GitLab bạn đã tạo (nếu kho riêng tư).
- Trong phần
Build Steps, chọnExecute shellvà nhập một lệnh đơn giản, ví dụ:ls -lhoặcecho "Hello from Jenkins!". - Lưu cấu hình và sau đó nhấn
Build Now.
Kiểm tra output trong Console Output của job. Nếu thành công, bạn sẽ thấy kết quả của lệnh shell.
Lưu ý: Các job "Freestyle" này thường chạy trên chính Jenkins Master (trong Pod Jenkins bạn đã triển khai). Dữ liệu của job sẽ được lưu trữ trong thư mục làm việc của Jenkins (ví dụ: /var/jenkins_home/jobs/<tên_job>/workspace, thư mục này được lưu trữ trên PVC).
Các vấn đề thường gặp
Một số vấn đề phổ biến khi triển khai Jenkins trên Kubernetes bao gồm các sự cố về mạng (ví dụ: Calico, Flannel), không truy cập được Jenkins từ Node IP, hoặc các vấn đề về quyền hạn khi Jenkins tương tác với các tài nguyên Kubernetes.