Slack được sử dụng trong luận văn như kênh giao tiếp chính. Slack-plugin được cài đặt trong Jenkins để gửi thông báo tới Slack dựa vào trạng thái của quá trình build (Hình 4.8). Tất cả trạng thái của các quá trình build này sẽ được cập nhật trực tiếp lên Gitlab, cung cấp thông tin trực quan cho nhà phát triển.
Hình 4.8: Thơng báo từ Jenkins tới Slack
Sau khi build tiền hợp nhất thực hiện thành công, luận văn sử dụng API được
cung cấp bởi Jenkins để kích hoạt tiếp q trình triển khai, từ đó cập nhật ứng dụng
vào môi trường sản phẩm (production environment).
Hầu hết các tác vụ trong Jenkins đều được cấu hình thơng qua mã Groovy DSL một cách tự động. Điều này giúp cho việc cấu hình trở nên đơn giản, nhanh chóng và
quan trọng nhất là có thể kiểm thử được từ trước khi thực sự chạy (Hình 4.9)
Hình 4.10: Các tác vụ trong Jenkins
4.1.3 Cài đặt môi trường sản phẩm
4.1.3.1 Cài đặt nền tảng điều phối container
Một kubernetes cluster cần có ít nhất các thành phần sau:
• Một master node: chứa các thành phần api-server (giúp kiểm tra và cấu hình dữ liệu cho các đối tượng api như service, pod; cung cấp các REST api cho các thành phần khác để truy cập tới các dữ liệu trạng thái của cluster), controller-
manager (một daemon luôn chạy, lắng nghe trạng thái của cluster để đưa ra
các các thay đổi cần thiết giúp cluster đạt được trạng thái yêu cầu; một số
controller được đóng gói sẵn như replication controller, namespace controller), bộ lập lịch và thành phần setup (giúp phân bố các Cluster IP cho
Kubernetes). Tất các các thành phần này đều được cài đặt bằng ảnh Docker
hypercube được cung cấp bởi Google, nhưng với mỗi chức năng thì các tham
số được sử dụng trong ảnh là khác nhau (hybercube image URL:
gcr.io/google_containers/hyperkube-amd64)
• Các worker node: chứa ít nhất 2 thành phần kubelet, kube-proxy. Các thành phần này cũng được cài đặt bằng ảnh hypercube với các tham số phù hợp.
• Etcd: cung cấp chức năng lưu trữ phân tán các giá trị dạng key-value. Kubernetes được cấu hình để kết nối và lưu trữ các dữ liệu trạng thái trong etcd cluster. Etcd trong bài được cài đặt như các dịch vụ hệ thống dạng systemd.
• Cách thức kết nối mạng multihost: luận văn sử dụng dịch vụ flannel để đảm
bảo kết nối mạng multihost cho các máy khác nhau. Các agent flanneld sẽ
được cài đặt trên tất cả các worker node, chịu trách nhiệm phân bố các dải
subnet con (10.254.0.0/24) lên tất cả các node dựa trên dải subnet cha (10.254.0.0/16) được cung cấp. Các thông tin ánh xạ giữa các IP ảo được cấp
thường tất các các docker container có liên kết với thiết bị mạng bridge mặc
định docker0 sẽ được cấp phát IP nằm trong cùng dải với docker0. Do vậy, để đảm bảo container trong mỗi worker node nhận được các IP nằm trong dải
quản lý của flanneld, docker0 sẽ được tùy biến với bridge IP chính là dải IP
của flanneld. Kết nối mạng chi tiết được thể hiện trong Hình 4.11.
Hình 4.11: Cách thức kết nối mạng trong kubernetes
• Giải pháp khám phá dịch vụ: SkyDNS được sử dụng làm giải phát khám phá
dịch vụ trong Kubernetes. Các container chạy trong các POD của kubernetes có thể tương tác với các container trong POD khác bằng DNS name của Service đại diện các POD. SkyDNS giúp phân giải DNS name của Service
sang các Service IP ảo. Sau đó, kube-proxy sẽ giúp chuyển các yêu cầu tới
Service IP ảo sang các POD mà Service đại diện. SkyDNS được cài đặt bằng
cách sử dụng ảnh docker và được triển khai như một dịch vụ ngay trong
Kubernetes cluster.
Các vi dịch vụ forex-service và ccs-service trong luận văn được triển khai vào
các worker node trong kubernetes cluster. Đối với một tổ chức, thông thường các máy
triển khai môi trường sản phẩm được cài đặt trong một VPC với cấu hình mạng cách ly với mơi trường bên ngồi. Do vậy, cần có cách thức để cho phép các yêu cầu gửi từ bên ngoài được chuyển vào đúng các vi dịch vụ đang chạy trong lòng VPC. Luận văn
đề xuất cách thức cài đặt như Hình 4.12:
• Một vi dịch vụ nginx được cài đặt ngay trong Kubernetes cluster, cùng cấp với các dịch vụ forex-service và ccs-service. Nginx được cấu hình để chuyển các
yêu cầu với endpoint phù hợp vào các vi dịch vụ phù hợp. Mọi yêu cầu gửi tới các vi dịch vụ trong Kubernetes đều được thực hiện thơng qua nginx.
• Nginx sẽ ánh xạ cổng được sử dụng trong ảnh docker ra một cổng thực bên
ngoài worker node. Các load-balancer được thiết lập để trỏ vào tất cả các máy
worker node, tới cổng mà nginx được ánh xạ (Hình 4.12).
Hình 4.12: Các máy trong Kubernetes cluster 4.1.3.2 Cài đặt cách thức thu thập và quản lý log 4.1.3.2 Cài đặt cách thức thu thập và quản lý log
Các thức cài đặt hệ thống thu thập và quản lý log thể hiện trong Hình 4.13 dưới
đây.
Hình 4.13: Cách thức cài đặt và quản lý log
Khi các vi dịch vụ chạy trong docker container, log của chúng được cấu hình để ghi ra tệp log tại các vị trí được xác định theo mẫu sau:
Các tệp log trong container sẽ được mount vào thư mục /var/log/msa trên chính các máy mà container chạy. Kubernetes sẽ tự động sinh ra tên pod ngẫu nhiên dựa vào tên dịch vụ được cung cấp, do vậy tên pod có thể thay đổi theo thời gian. Việc quy định như trên đảm bảo các tệp log của pod cũ vẫn còn tồn tại trên các node để phục vụ
mục đích thu thập. Các fluentd agent được cài đặt trên tất cả các máy và được cấu hình
để đọc (tail) các tệp log ở các vị trí xác định, phân giải các trường thông tin trong log
và tạo ra các luồng log để gửi tới một máy tập trung gọi là fluentd-aggregator. Về cơ bản, fluentd-aggregator cũng là một máy chạy fluentd bình thường; tuy nhiên, fluentd
được cấu hình để lắng nghe sự kiện log gửi tới (tại một port xác định). Trên máy
fluentd-aggregator, các sự kiện log sẽ được lọc, thêm các trường thông tin cần thiết,
gửi tới hệ thống lưu trữ và đánh chỉ số Elasticsearch. Phần mềm Kibana được cấu hình trên một máy khác, kết nối tới Elastichsearch để truy vấn dữ liệu, từ đó hiển thị thông
tin cho người dùng. Elasticsearch và Kibana được cài đặt như các dịch vụ hệ thống
systemd.
4.1.3.3 Cài đặt hệ thống giám sát
Prometheus là thành phần quan trọng nhất trong hệ thống giám sát, có nhiệm vụ thu thập các thơng tin về trạng thái của tất cả các máy và ứng dụng. Các thơng tin cần thu thập bao gồm:
• Tài nguyên sử dụng trên các máy triển khai
• Trạng thái các đối tượng trong Kubernetes cluster
• Các thông tin khác được sinh ra bởi bản thân các ứng dụng
Cơ chế thu thập thông tin của Prometheus là “scrape”. Nghĩa là máy chủ Prometheus sẽ chủ động tải các thông tin về các đối tượng dựa vào các endpoint mà đối tượng cung cấp. Prometheus được cài đặt ngay trong Kubernetes cluster, sử dụng
docker container.
Đối với tài nguyên sử dụng trên máy triển khai, do bản thân hệ điều hành đã lưu
những thơng tin này tại những vị trí xác định trên máy, người dùng chỉ cần tìm cơ chế chuyển đổi những thông tin này sang dạng mà Prometheus có thể đọc được. Với yêu cầu này, luận văn sử dụng dịch vụ node-exporter, cài đặt trên tất cả các máy. Các
thông tin sau khi chuyển đổi sẽ được cung cấp tại port 9100 trên chính các máy đó, với endpoint là /metrics.
Đối với trạng thái các đối tượng trong Kubernetes cluster (như thông tin về pod,
container, service), luận văn sử dụng kube-state-metrics. Kube-state-metrics sẽ lắng nghe các thông tin trạng thái đối tượng từ API server trên master node trong
Kubernetes, chuyển đổi định dạng và cung cấp endpoint /metrics để Prometheus có thể
“scrape”. Cũng như máy chủ Prometheus, kube-state-metrics được cài đặt bằng cách
sử dụng docker container trong Kubernetes cluster.
Đối với các trường thông tin khác sinh ra bởi ứng dụng, luận văn sử dụng cơ chế
gắn các chú thích vào các docker container. Bằng cách sử dụng các thư viện instrumentation, các ứng dụng vi dịch vụ có thể tự định nghĩa các thước đo mới tùy
theo yêu cầu. Máy chủ Prometheus sẽ “scrape” những thông tin này qua endpoint
được cung cấp trong chú thích của docker container.
Ví dụ: thước đo msa_request_count được tích hợp vào trong forex-service và
ccs-service với 2 nhãn success, error để tính số lượng các yêu cầu thành công hay thất bại gửi tới chúng.
Prometheus được cấu hình để gửi thơng tin cảnh báo tới Alert Manager khi trạng thái của hệ thống vượt qua ngưỡng nhất định. Từ Alert Manager, cảnh báo sẽ được gửi
đi thông qua các kênh thông báo khác nhau (trong bài sử dụng Slack). Alert Manager
trong luận văn được chạy bằng docker, tuy nhiên nằm riêng biệt với Kubernetes
ALERT high_error_request
IF msa_request_count{msa_request_count="error"} > 3 FOR 1m
LABELS { severity = "slack" } ANNOTATIONS {
summary = "Number of error request error is too high", description = "Receives lots of error request%. Reported by instance {{ $labels.instance }} of job {{ $labels.job }}.",
}
Trong luận văn, tất các các quá trình cài đặt hệ thống phức tạp này đều được viết bằng Ansible. Việc cài đặt trên một máy hay một nhóm các máy có thể được thực hiện nhanh chóng thơng qua cấu hình trên một tệp duy nhất.
4.2 Đánh giá kết quả
Luận văn được viết dựa trên kết quả làm việc thực tế của tác giả trong quá trình xây dựng giải pháp triển khai liên tục cho hệ thống phần mềm thương mại điện tử của công ty Works Applications Singapore. Kết quả của việc ứng dụng giải pháp triển khai liên tục này được thể hiện qua bảng sau:
Trước khi dùng giải pháp triển khai
Sau khi dùng giải pháp triển khai liên tục
Thời gian triển khai 1 module
15 phút 5 phút Thời gian triển khai
toàn bộ 30 module
5 tiếng 1 tiếng Thời gian từ lúc có
mã mới tới khi triển khai hoàn toàn
30 phút 5 phút Số lần triển khai được thực hiện trong 1 ngày 2-3 lần/module 8-12 lần/module Người thực hiện việc triển khai
Đội vận hành Đội trưởng (leader) của các đội phát triển và các bên liên
quan được cấp quyền (ví dụ: đội quản lý chất lượng)
Qua kết quả đạt được thể hiện trong Bảng 4-1: Kết quả của giải pháp triển khai liên tục, ta có thể thấy một số lợi ích rõ rệt mà nó mang lại như:
• Giảm chu kỳ phát hành sản phẩm (Cycle Time)
Chu kỳ phát hành được tính từ thời gian có yêu cầu tới khi bản phát hành được
cập nhật trên môi trường sản phẩm. Bằng hệ thống triển khai liên tục, bất cứ một sự thay đổi mã đều có thể được triển khai ngay lập tức ra mơi trường mà khơng gặp khó
khăn gì. Ngay khi nhận yêu cầu người dùng, nhà phát triển có thể phân tích, sửa đổi mã nguồn và gửi yêu cầu hợp nhất mã mới vào nhánh chính để kích hoạt quá trình
triển khai.
Việc triển khai ngồi cách kích hoạt tự động cịn có thể được thực hiện thơng qua giao diện trên Jenkins (chỉ áp dụng cho người dùng với quyền hạn phù hợp). Với cách sử dụng đơn giản, hệ thống sau khi được cài đặt khơng địi hỏi chuyên gia về triển khai
để quản lý mà trách nhiệm có thể được phân phối về từng đội. Điều này cũng góp phần
khuyến khích việc thực hiện cập nhật với tần suất cao hơn, từ đó cải thiện chu kỳ phát hành thay đổi của sản phẩm.
• Tăng năng suất lao động
Tăng năng suất là lợi ích rõ nhất của hệ thống triển khai liên tục. Việc triển khai thường xuyên giúp tổ chức phát hiện ra các vấn đề và nhận được phản hồi sớm từ
người dùng, từ đó đưa ra các giải pháp phù hợp trong thời gian sớm nhất. Bằng việc tự
động hố q trình build, kiểm thử cũng như cung cấp các cơng cụ triển khai dễ dàng,
các nhà phát triển có thể tập trung vào việc phát triển tính năng cịn các đội vận hành
cũng giảm thiểu thời gian giám sát hệ thống để tập trung vào nâng cao chất lượng các dịch vụ khác. Trước đây, việc triển khai, giám sát một cluster gồm hàng trăm máy đòi hỏi ít nhất một đội vận hành hàng chục người. Với hệ thống triển khai liên tục, tích
hợp với các cơ chế giám sát và thông báo lỗi tự động cho các bên liên quan, chỉ cần vài người là có thể đảm bảo mơi trường sản phẩm hoạt động tốt với độ tin cậy cao.
• Thỏa mãn được các yêu cầu cho đội phát triển
Các nhà phát triển thường quen thuộc với cách thức truy cập trực tiếp vào môi trường sản phẩm để đọc và phân tích log khi có lỗi xảy ra. Tuy nhiên, kinh nghiệm
thực tế chỉ ra rằng cách làm này có thể gây ra nhiều thiệt hại hơn lợi ích mà nó mang lại, bởi bất cứ ai cũng có thể tạo ra một sửa đổi khiến máy triển khai chuyển sang trạng thái hoạt động bất thường.
Với việc sử dụng mơ hình triển khai khơng tùy biến, khơng có nhiều khác biệt giữa mơi trường sản phẩm và môi trường local (tất cả các thư viện, các yêu cầu để một dịch vụ chạy đều đã được đóng gói vào trong ảnh container), do vậy các nhà phát triển hồn tồn có thể tự tái hiện và kiểm tra lỗi trên chính máy đang sử dụng.
Ngoài ra, tất cả cấu hình máy triển khai được khai báo trong các tệp kịch bản
Ansible, được lưu và quản lý như mã nguồn trên kho quản lý mã chung mà các nhà
phát triển đều có thể truy cập. Bằng việc tích hợp EFK stack và sử dụng các công cụ giám sát với giao diện thể hiện trực quan, những thông tin trước đây cần phải truy cập trực tiếp vào máy mới xem được đều hiện hữu trên giao diện người dùng.
Thiết kế hệ thống triển khai liên tục trong luận văn thực tế đã đáp ứng gần như
tất cả yêu cầu mà bên phát triển mong muốn, đồng thời đã hạn chế được những rủi ro mà những phương pháp làm việc trước đó gây ra.
KẾT LUẬN
Các ứng dụng dựa vào đám mây là xu hướng mới nhất trong ngành công nghiệp công nghệ thông tin, giúp phát triển và triển khai phần mềm một cách nhanh chóng và hiệu quả bằng việc sử dụng các dịch vụ đám mây. Nó giúp cải thiện tốc độ làm việc cho các đội phát triển bởi giờ đây họ có thể tập trung vào việc phát triển tính năng thay vì lo lắng về cơ sở hạ tầng. Nó cũng giúp cho các cơng ty, tổ chức đưa phần mềm ra thị trường nhanh hơn do không phải dành thời gian cho các thủ tục chuẩn bị máy móc phức tạp. Các khái niệm tích hợp, chuyển giao liên tục, kiến trúc vi dịch vụ giúp tận dụng tối đa lợi ích mà đám mây mang lại. Công nghệ container, cùng với sự xuất hiện của Docker, đã cách mạng hóa cách thức đóng gói và triển khai vi dịch vụ. Bản chất nhẹ, sử dụng ít tài nguyên của container giúp việc thiết lập môi trường chạy cho ứng dụng trở nên đơn giản, nhanh chóng (giảm thời gian từ vài chục phút cho việc khởi
động máy ảo gồm toàn bộ hệ điều hành tới chỉ vài phút cho việc bật container). Sự ra đời của container, tích hợp cùng với những cơng nghệ trước đó, đã biến việc triển khai
liên tục trở thành hiện thực. Các công cụ mới cũng liên tục xuất hiện để hỗ trợ cho việc triển khai container như: các công cụ khám phá dịch vụ, các bộ khung điều phối container, các giải pháp thu thập và quản lý log hay các cách thức giám sát hệ thống. Tuy nhiên, tồn bộ những cơng cụ, nền tảng hay công nghệ nêu trên đều xuất hiện và tồn tại một cách rời rạc, chưa có sự thống nhất. Câu hỏi đặt ra hiện tại là làm thế nào để phối hợp những công nghệ này để đưa ra một luồng triển khai liên tục hiệu quả,