kiến thức DevOps thực tế và chi tiết

Jenkins CI CD pipeline (Delivery)

Nếu bạn đã xem Jenkins CI CD Pipeline 1 dự án thực tế (siêu chi tiết) một bài viết dài, chi tiết của mình thì bài viết này ngắn hơn nhưng sẽ đem lại giá trị nhiều hơn về mặt tư tưởng, phương thức triển khai cho bạn, trong bài viết này mình sẽ Lab Jenkins CI CD Pipeline vậy bài viết này có gì hay ho hơn bài viết trước? Chúng ta sẽ triển khai với Continuous Integration and Continuous Delivery tức là việc triển khai Jenkins CI CD pipeline bước CD sẽ là thủ công, vậy tại sao trên môi trường Production những hệ thống lớn thường triển khai thủ công? bạn hãy theo dõi tiếp bài viết mình sẽ trình bày chi tiết chắc hẳn bạn sẽ có những thu hoạch hữu ích vì đây là cách triển khai thực tế.

Lưu ý: Về phần source code và các triển khai mình sẽ không lấy một source phức tạp và không triển khai cách phức tạp, bài viết này nhằm đem lại phương thức triển khai trên Production và bạn có thể áp dụng cho dự án của bạn khi bạn hiểu. Mình triển khai sẽ không hoàn toàn đầy đủ giống y hệt môi trường thật ví dụ như phân quyền, mã triển khai, server,… vì như vậy sẽ rất là dài và phức tạp có thể làm cho bạn bị khó hiểu đi xa mục đích của bài viết.

Có thể nhiều bạn chưa biết, cứ nói CI/CD mà quên mất trong CD nó có 2 khái niệm, tuy nhiên rất đơn giản thôi, Continuous Delivery là bước triển khai code sẽ làm thủ công còn Continuous Deployment sẽ là tự động hoàn toàn.

Vậy tại sao trên các hệ thống lớn lại thường là Continuous Delivery không phải Continuous Deployment?

  • Độ phức tạp của hệ thống: Trong các hệ thống lớn, có nhiều yếu tố và khía cạnh phải xem xét và kiểm tra trước khi triển khai vào môi trường sản phẩm. Các bước kiểm tra, xác thực và duyệt như kiểm tra bảo mật, kiểm tra hiệu năng, và các yêu cầu kinh doanh có thể làm tăng thời gian và tốn công sức, do đó không thể hoàn toàn tự động.
  • Rủi ro và ổn định: Trong môi trường sản phẩm, việc triển khai không kiểm soát có thể gây ra sự cố nghiêm trọng. Việc sử dụng Continuous Delivery cho phép kiểm tra tự động kỹ lưỡng trước khi triển khai, giúp đảm bảo tính ổn định và tin cậy của hệ thống.
  • Kiểm soát chất lượng: Quá trình kiểm tra tự động giúp đảm bảo rằng chỉ những mã nguồn chất lượng cao mới được triển khai.
  • Tạo lòng tin từ người dùng: Bằng cách đảm bảo rằng mã nguồn được kiểm tra kỹ lưỡng trước khi đưa vào môi trường sản phẩm, có thể tạo lòng tin và sự hài lòng từ phía người dùng, vì họ biết rằng ứng dụng sẽ hoạt động một cách ổn định.
  • Tăng khả năng hợp tác trong nhóm phát triển: Continuous Delivery khuyến khích sự hợp tác giữa các thành viên trong nhóm phát triển để đảm bảo rằng quy trình triển khai và kiểm thử diễn ra một cách suôn sẻ.

Triển khai Continuous Deployment thường phù hợp cho môi trường Development và Staging khi các bạn Dev cần code mới ngay trên môi trường Server và Tester có thể test đảm bảo quá trình phát triển sản phẩm được liền mạch hơn, tuy nhiên nhiều hệ thống, dự án nhỏ họ cũng thiết lập triển khai Continuous Deployment trên Production điển hình là những công ty Outsource vì thời gian phát triển dự án không dài (tùy công ty nhưng thường vài tháng, dưới 1 năm) và họ làm xong sản phẩm và gửi khách hàng nên đề cao hiệu suất.

Với những thông tin trên mình cung cấp chúng ta cùng vào triển khai Jenkins CI CD Pipeline thực hành chi tiết mong rằng có thể giúp ích trong dự án của bạn.

Kết quả

Giải thích:

  • Server: tương ứng các Server mà bạn triển khai dự án trên đó, vì thông thường các dự án lớn sẽ sử dụng K8s để triển khai nên sẽ có 1 Cụm các server
  • Action: hành động triển khai project
    • Start: Khởi chạy project (rất rõ ràng rồi để khởi chạy Project, ví dụ bị Stop chẳng hạn)
    • Stop: Dừng project (dừng dự án khi có vấn đề, để tiến hành Fix)
    • Restart: Khởi động lại project (khi project bị treo, lỗi,…)
    • Update: Cập nhật chức năng mới của project (Update code)
    • Rollback: Khởi chạy lại project ở version trước đó khi cập nhật chức năng mới có vấn đề
  • Hash: đây chính là mã commit chức năng mới trên kho lưu trữ source (khi sử dụng chức năng Update sẽ cần nhập mã này để Jenkins tiến hành lấy source code và triển khai chức năng mới)
  • Rollback_version: các bản backup được hiển thị tại đây khi lựa chọn ActionRollback

Các bước triển khai Jenkins CI CD Pipeline

Trước khi vào dự án mình sẽ nói qua về source mình sử dụng trong bài viết Jenkins CI CD Pipeline này, Source code là một project Java web đơn giản mình tạo bằng Maven, để triển khai dự án Java web này, chúng ta cần cài đặt Java, Maven, Tomcat (dưới đây mình sẽ hướng dẫn, đơn giản thôi).

Để chạy được một dự án Java web chúng ta làm theo các bước sau, bạn hiểu điều này sẽ dễ hiểu phần triển khai Jenkins CI CD Pipeline

  • B1: Sử dụng Maven build dự án thành file .war (khi build thành công sẽ tạo ra thư mục target trong đó chứa folder là <tên dự án> và file <tên dự án>.war)
  • B2: Copy folder và file .war vào trong thư mục webapps của tomcat thường là /opt/tomcat/webapps
  • B3: khởi động lại dịch vụ tomcat

Chuẩn bị tài nguyên

  • Gitlab: mình sẽ sử dụng Gitlab để lưu trữ source đây cũng là công cụ mà nhiều doanh nghiệp lớn, nhỏ vẫn đang sử dụng, và mình build riêng Gitlab bạn cũng có thể sử dụng Gitlab.com luôn nhé hoặc có thể tham khảo Setup Gitlab nội bộ để tự build Gitlab riêng mình nhanh chóng đơn giản.
  • Jenkins: chắc chắn rồi chúng ta cần một server Jenkins để cấu hình Jenkins CI CD pipline ở bài viết Jenkins trên mình cũng đã cung cấp chi tiết cách cài đặt rồi nhé.
  • Server Deploy: Một server để triển khai dự án (ở đây mình sử dụng CentOS7).
  • Source code: bạn có thể sử dụng source dự án mà bạn có hoặc download source của mình làm Lab cho tiện nhé mình clone từ Website của đại học Harvard – nghịch thôi với sample của java web (HTML, CSS, JS không có logic backend gì cả ) tại Harvard-University-Portal.zip

Triển khai Jenkins CI CD pipline

Đầu tiên mình đã có dự án trên Gitlab như sau, một sample java vô cùng đơn giản chỉ chạy html, css nhé

Thiết lập cài đặt service cần thiết trên server deploy

Chúng ta phải tạo một người dùng riêng trên server cho dự án đó, đây là một bước cần thiết để triển khai rõ ràng, minh bạch khi trên server của chúng ta phải triển khai nhiều dự án, mình sẽ tiến hành tạo user là hvportal (tương ứng cho project Harvard University Portal)

elroydevops.tech
$ sudo useradd hvportal

Tạo mật khẩu cho người dùng

elroydevops.tech
$ sudo passwd hvportal

Bạn hãy kiểm tra xem server của mình cài đặt Git chưa nhé nếu chưa cài đặt hãy sử dụng câu lệnh dưới đây

elroydevops.tech
$ sudo yum install git -y

Để chạy được một dự án Java web chúng ta sẽ tiến hành cài đặt các bước sau đây, đầu tiên cài đặt Java 11 (lưu ý server đang chạy Jenkins cũng phải cùng version Java nhé)

elroydevops.tech
$ sudo yum install java-11-openjdk-devel -y

Rất có thể khi bạn sử dụng CentOS Java sẽ được cài đặt version 8 nên bạn sử dụng câu lệnh dưới đây

elroydevops.tech
$ sudo update-alternatives –config java

Chọn đúng version Java 11 như dưới đây nhé (dấu + là version đang được lựa chọn)

Tiếp theo cài đặt Maven

elroydevops.tech
$ sudo yum install maven -y

Tiến hành cài đặt Webserver tomcat, để chạy được dự án Java web chúng ta sử dụng tomcat, đầu tiên tạo người dùng tomcat

elroydevops.tech
$ sudo useradd -m -U -d /opt/tomcat -s /bin/false tomcat

Di chuyển tới thư mục /tmp và tải file cài đặt tomcat về server, ở đây mình sử dụng lựa chọn –no-check-certificate vì thật không ngờ mình tải đúng lúc website tomcat hết SSL

elroydevops.tech
$ cd /tmp && wget –no-check-certificate https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.78/bin/apache-tomcat-9.0.78.tar.gz

Tiến hành giải nén file cài đặt tomcat vừa tải

elroydevops.tech
$ sudo tar xzvf apache-tomcat-9*tar.gz -C /opt/tomcat –strip-components=1

Đổi quyền sở hữu thư mục cho người dùng tomcat

elroydevops.tech
$ sudo chown -R tomcat:tomcat /opt/tomcat

Cho user hvportal vào group tomcat

elroydevops.tech
$ sudo usermod -aG tomcat hvportal

Cấp quyền thực thi cho các file có đuôi .sh để đảm bảo có thể thực thi script

elroydevops.tech
$ sudo sh -c ‘chmod +x /opt/tomcat/bin/*.sh’

Lấy đường dẫn tuyệt đối của thực thi của chương trình java trên hệ thống, bạn hãy copy lại để chúng ta sử dụng nhé

elroydevops.tech
$ sudo readlink -f $(which java)

Được kết quả dưới đây

/usr/lib/jvm/java-11-openjdk-11.0.19.0.7-1.el7_9.x86_64/bin/java

Tạo cấu hình service cho tomcat

elroydevops.tech
$ sudo vi /etc/systemd/system/tomcat.service

Cấu hình như dưới đây

[unit]
Description=Apache Tomcat Web Application Container
After=network.target

[Service]
Type=oneshot
RemainAfterExit=yes

User=tomcat
Group=tomcat

Environment="/usr/lib/jvm/java-11-openjdk-11.0.19.0.7-1.el7_9.x86_64/bin/java"
Environment="JAVA_OPTS=-Djava.security.egd=file:///dev/urandom -Djava.awt.headless=true"
Environment="CATALINA_BASE=/opt/tomcat"
Environment="CATALINA_HOME=/opt/tomcat"
Environment="CATALINA_PID=/opt/tomcat/temp/tomcat.pid"
Environment="CATALINA_OPTS=-Xms512M -Xmx1024M -server -XX:+UseParallelGC"
ExecStart=/opt/tomcat/bin/startup.sh
ExecStop=/opt/tomcat/bin/shutdown.sh

[Install]
wantedBy=multi-user.target

Tải lại các tệp cấu hình và cập nhật của systemd trên hệ thống Linux

elroydevops.tech
$ sudo systemctl daemon-reload

Khởi động tomcat cùng hệ thống

elroydevops.tech
$ sudo systemctl enable tomcat

Khởi động tomcat (nếu bạn có sử dụng Firewall hãy mở port 8080 nhé)

elroydevops.tech
$ sudo systemctl start tomcat

Thay đổi quyền thư mục /opt/tomcat để các user có thể sử dụng

elroydevops.tech
$ sudo chmod -R 775 /opt/tomcat

Cấu hình Jenkins node

Tiếp theo chúng ta sẽ cấu hình Jenkins Agent, bạn có thể hiểu như thế này từ Jenkins server sẽ triển khai dự án lên trên server deploy để chạy Jenkins CI CD Pipeline vậy chúng ta phải cấu hình server deploy trở thành 1 node của Jenkins server, có rất nhiều cách như ssh tuy nhiên ssh tiềm ẩn nhiều rủi ro nên mình sẽ sử dụng cách Jenkins Agent chi tiết về lý thuyết bạn có thể tìm hiểu thêm tại Using Jenkins agents nhé.

Truy cập Jenkins chọn Dashboard > Manage Jenkins > Security kéo xuống phần Agents và sửa như dưới đây

Chú ý nếu trên Jenkins server bạn sử dụng firewall thì nhớ mở port 8999 lên nhé.

Tiếp theo chọn vào Dashboard > Manage Jenkins > Nodes và nhấn New Node, Mình điền Node name là IP server deploy

Tạo Jenkins agent với cấu hình như dưới đây

Tạo thành công và được như dưới đây, chúng ta sẽ tiến hành chạy nó trong server deploy

Truy cập lại Server deploy, tiến hành tạo thư mục /var/lib/jenkins

elroydevops.tech
$ sudo mkdir /var/lib/jenkins

Tạo group riêng cho thực thi pipeline

elroydevops.tech
$ sudo groupadd pipeline

Thay đổi quyền sở hữu của thư mục

elroydevops.tech
$ sudo chown root:pipeline /var/lib/jenkins/

Đổi quyền thư mục chỉ cho chủ sở hữu và group pipeline sử dụng

elroydevops.tech
$ sudo chmod -R 770 /var/lib/jenkins/

Thêm người dùng hvnportal vừa tạo vào group pipeline

elroydevops.tech
$ sudo usermod -aG pipeline hvportal

Chuyển qua người dùng hvnportal để cấu hình Jenkins Agent

elroydevops.tech
$ sudo su – hvportal

Tạo thư mục dự án

elroydevops.tech
$ mkdir /home/hvportal/hv-portal

Tạo thư mục làm việc trong dự án

elroydevops.tech
$ cd /home/hvportal/hv-portal && mkdir source backups

Tiến hành cấu hình Jenkins agent chạy các câu lệnh ở trên trong cấu hình

elroydevops.tech
$ curl -sO http://jenkins.elroydevops.tech:8080/jnlpJars/agent.jar

Tiếp theo chạy lệnh sau (của bạn là khác nhé)

elroydevops.tech
$ java -jar agent.jar -jnlpUrl http://jenkins.elroydevops.tech:8080/computer/192%2E168%2E17%2E110/jenkins-agent.jnlp -secret a591878db5fe09f274877c7e874fada28a0846a69207072cd25c1676ef43809e -workDir “/var/lib/jenkins” &

Thành công được kết quả như dưới đây

Vậy là chúng ta đã cấu hình thành công Jenkins node sẵn sàng chạy các job Jenkins CI CD Pipeline.

Cấu hình Jenkins CI CD Pipeline

Tiếp theo chúng ta sẽ vào phần công việc chính là thực hiện cấu hình Jenkins CI CD Pipeline

Chúng ta sẽ cài đặt một Plugin là Action choices như dưới đây bạn nhấn Install without restart là được nhé

Chúng ta quay lại Gitlab một chút, chúng ta cần một tài khoản để clone source, ở đây mình sẽ tạo một tài khoản là Jenkins như dưới đây có quyền Admin, hoặc bạn sử dụng luôn tài khoản của bạn cũng được nhé vì tài khoản của bạn thì có quyền truy cập vào project của bạn rồi.

Chúng ta quay lại Jenkins để tạo credentials cho tài khoản Jenkins để có thể sử dụng trong Jenkins CI CD Pipeline của chúng ta

Trên Jenkins truy cập Dashboard > Manage Jenkins > Credentials > System Global credentials (unrestricted) nhấn chọn vào New credentials

Bạn điền thông tin tài khoản Gitlab của bạn vào như dưới đây

Tiếp theo tiến hành tạo thư mục để chứa các Jenkins CICD pipeline chọn vào New Item

Tạo Folder với name là Action_in_Production hoặc tùy bạn nhé

Nhấn Save để hoàn thàn tạo

Trong Folder chọn New Item để tạo Jenkins CI CD pipeline

Nếu bạn sử dụng Source mình cung cấp luôn thì để harvard-university-portal nhé

Bạn chú ý trong phần cấu hình dưới đây nhé, trong phần General mình sẽ chọn vào This project is parameterized chọn vào Add Parameter

Khi thêm Action Choices Parameter

  • Name: Server
  • Groovy Script: [“192.168.17.110”, “192.168.17.111”, “192.168.17.112”] tương ứng với server deploy của bạn để chạy Jenkins CI CD Pipeline nhé
  • Choice Type: Multi Select

Và một số cấu hình mặc định bạn hãy làm như dưới đây

Thêm Action Choices Parameter

  • Name: Action
  • Groovy Script: return [“Start”, “Stop”, “Restart”, “Update”, “Rollback”]

Và một số cấu hình mặc định bạn hãy làm như dưới đây

Tiếp tục chúng ta thêm Parameter có kiểu là string như dưới đây

Thêm String Parameter

  • Name: Hash
  • Description: Git commit hash for update
  • Trim the string: true

Parameter này được sử dụng để điền vào mã commit hoặc nhánh như mô tả mình nói khi muốn update version (update code)

Thêm Active Choices Reactive Parameter

  • Name: Rollback_verison
  • Groovy Script: sẽ tiến hành lấy tất cả các nội dung trong thư mục /home/hvportal/hv-portal/backups tại server deploy qua kết nối Jenkins Agent để hiển thị danh sách các bản backup cho bạn chọn.

Nội dung Groovy script dưới đây

import jenkins.model.*
import hudson.FilePath
backuppath = "/home/hvportal/hv-portal/backups"
def node = Jenkins.getInstance().getNode("192.168.17.110")
def remoteDir = new FilePath(node.getChannel(), "${backuppath}")

def files = remoteDir.list()
def result = files.collect { it.name }

if (Action == "Rollback")
{
  return result
}

Kéo xuống một chút bạn có thể thấy ngay phần Pipeline chúng ta sử dụng Groovy để viết (Groovy là một ngôn ngữ lập trình nhé, bạn có thể tìm hiểu thêm để tự triển khai code cho hợp ý bạn), bạn yên tâm mình sẽ để file cấu hình tại groovy-hvportal-config.txt

Đầu tiên là Action Update, vì là một dự án chưa chạy nên chúng ta sẽ thực hiện bước đầu trong Jenkins CI CD pipeline, để tiến hành triển khai dự án, bạn có thể xem ngay dưới đây để hiểu được

jenkins ci cd pipeline

Các bước trong Update action trong Jenkins CI CD Pipeline

  • Tiến hành Pull source code từ Gitlab về server
  • Build dự án
  • Deploy dự án
  • Backup dự án tại thời điểm Update

Tiếp đến là Stop action trong Jenkins CI CD Pipeline

Chúng ta sẽ tiến hành dừng project đang chạy như dưới đây

Tiếp theo chúng ta đến Start action trong Jenkins CI CD Pipeline

Khởi động Project như dưới đây

Tiếp theo chúng ta sẽ tiến hành thử Update lại code mới xem đã thành công chưa

Đầu tiên Mình sẽ tiến hành sửa trong file code từ Nguyen Van Manh sang Games (đúng với nội dung trên website chính thức của Harvard) và tiến hành chạy lại Update action

Tiếp theo chúng ta sẽ tiến hành Rollback action trong Jenkins CI CD Pipeline

Rollback ở đây chính là những version đã triển khai lên và sẽ được backup lại và mình sẽ lưu 3 file backup gần nhất

Vậy là mình đã hướng dẫn xong Jenkins CI CD pipeline cách triển khai trên môi trường production, tuy nhiên như mình đã nói thực tế sẽ phức tạp hơn rất nhiều, bạn có thể tham khảo để triển khai dự án của mình để thấy được thực tế các ưu điểm nhé, nó có thể hơi khó hiểu nếu bạn là fresher, junior bạn có thể liên hệ với mình nếu có vấn đề gì nhé. Mình sẽ làm nhiều hướng dẫn hơn về các kỹ năng các tool khác để giúp bạn tối ưu được những tác vụ cũng như tiết kiệm những chi phí khi phát triển phần mềm. Thanks.

 

Mọi thắc mắc bạn có thể liên hệ:

Email: [email protected]