+50

Giám sát ứng dụng Docker với cAdvisor, Prometheus và Grafana

Cập nhật gần nhất: 15/02/2024

Chào mừng các bạn đã quay trở lại với series học Docker và CICD của mình

Ở bài trước chúng ta đã cùng nhau setup Auto deploy với CICD, giảm thiểu những thao tác thừa lặp lại, chỉ cần commit, tất cả mọi thứ còn lại như: build Docker image, test và deploy được làm hoàn toàn tự động.

Ở bài này chúng ta sẽ setup các công cụ để monitor các ứng dụng Docker trông đầy đủ, xịn xò và chuyên nghiệp nhé 🙌

Tổng quan

Một trong những công việc quan trọng khi chạy ứng dụng ở production là luôn phải theo dõi, giám sát ứng dụng của mình, theo dõi các thông tin hệ thống (Logs, CPU, RAM, disks, IO operations,...) xác định những điểm/những khoảng thời gian ảnh hưởng xấu tới hiệu suất của app mục đích là đảm bảo ứng dụng luôn hoạt động ổn định. Đây là công việc dù có hay không dùng Docker thì ta vẫn thường xuyên phải làm (nếu là người làm nhiệm vụ Deploy và maintain)

Thông thường khi mua VPS thì ta có thể xem được 1 số thông tin tổng quát về CPU, Ram, networks, có thể xem trực tiếp trên giao diện trang web quản trị của nhà cung cấp nơi ta mua VPS (bên dưới là dashboard cho VM - Virtual Machine của mình trên Azure)

Nếu muốn những thông tin cụ thể hơn thì ta cần phải vào trực tiếp server để kiểm tra. Nhưng khi số lượng ứng dụng lên nhiều, đặc biệt khi ta chạy với Docker, số lượng container nhiều lên thì thật khó để có thể kiểm tra xem từng container chiếm bao nhiêu RAM, CPU, Network ra sao,...

Và cuộc đời thật may mắn vì thế giới open source luôn cứu rỗi những linh hồn đang lang thang tìm ra những công cụ hữu ích để xử lý vấn đề này với bộ 3 cặp bài trùng: cAdvisor, PrometheusGrafana 💪💪. Bộ 3 này được dùng rất rất nhiều khi trong thế giới DevOps để monitor ứng dụng Container

Chúng ta sẽ cùng tìm hiểu theo thứ tự từng thành phần một xem chúng là gì và lợi ích chúng mang lại nhé. 😉

Thực ra tên chính xác nên gọi là monitoring chứ gọi là giám sát, theo dõi nghe nó hơi nghiêm trọng. Nói monitoring là nói tới những điều mình kể bên trên, do vậy từ giờ trong bài này mình sẽ dùng monitor/monitoring thay vì dịch ra tiếng việt nhé 😄

Setup

Clone source

Đầu tiên các bạn clone code thực hành bài này ở đây (nhánh master nhé)

Ở bài này ta sẽ chỉ quan tâm tới folder docker-monitoring nhé

Ở bài này mình vẫn lấy project NodeJS CRUD sản phẩm như các bài trước, về chức năng, hay setup Docker thì y hệt không có gì thay đổi

Test ở local

Và vẫn như thường lệ, để đảm bảo code vẫn chạy bình thường ta luôn test ở local trước khi làm những điều tiếp theo nhé.

Và project bài này cũng như các bài gần đây ta đều setup để chạy với non-root user nhé các bạn. Tập dần cách chạy ứng dụng Docker với non-root user đi nhé 😉

Bắt đầu thôi nào 🚀🚀

Ở bài này ta sẽ chạy với user 1000:1000 nhé. Đầu tiên, vẫn đứng ở folder hiện tại - docker-monitoring, ta đổi toàn bộ quyền của các files bên trong về user 1000:1000, các bạn nào đang dùng Docker Windows + Mac thì bỏ qua bước này nhé, bước này chỉ áp dụng cho Docker Linux:

sudo chown -R 1000:1000 .

Các bạn có thể thắc mắc, ủa môi trường gốc tôi đâu có user nào 1000:1000 đâu, oke không sao cả 😄, 1000:1000 nó chỉ như cái mã số, ta thích gán mã số nào cũng được, chỉ khi nào bạn dùng tên, kiểu james:james thì mới cần user/group đó tồn tại.

Sau đó ta tiến hành build Docker image nhé các bạn:

docker build -t learning-docker:docker-monitoring .

Sau đó ta khởi động project lên:

docker compose up -d

Tiếp đó ta truy cập trình duyệt ở địa chỉ localhost:3000 thấy như sau là ôkê rồi nhé:

Các bạn thử Regiser account mới, login và thêm thử vài sản phẩm xem mọi thứ ổn định chưa nhé. Phần này mình để các bạn tự sướng 😄

Sau khi đã kiểm tra là app chạy ổn không lỗi lầm gì thì ta bắt đầu vào tiết mục chính của ngày hôm nay 💪💪

Chú ý: nếu khi các bạn up lên mà thấy db restart liên tục, check logs db thì thấy IllegalOperation: Attempted to create a lock file on a read-only directory: /data/db thì là folder mà ta đang mount volume vào đến container thì nó là readonly và user trong container không có quyền ghi vào đó, ta chạy command sau ở môi trường gốc:

sudo chmod 777 .docker/data/db .docker/data/redis public/images

Ở trên ta phải gán cho tất cả các folder mà các container của ta sẽ write, bởi vì nếu lỗi xảy ra với db thì cũng sẽ xảy ra với redis và images

Note cho bạn nào đang dùng Windows: các bạn xem lại phần chú ý lúc mount volume cho MongoDB mình đã nói ở bài Dockerize ứng dụng NodeJS, Mongo rồi nhé

Phân tích tài nguyên sử dụng và hiệu suất bằng cAdvisor

Chúng ta cùng đi tới thành phần đầu tiên trong bộ 3 cặp bài trùng. Và đây cũng là thành phần core cho 2 thành phần sau có thể dựa vào.

Tổng quan cAdvisor

cAdvisor (đọc là: xi-ớt-vai-dờ) là 1 dự án Open source của Google (nghe Google là biết hàng xịn rồi, không cần nói nhiều 😄), mục đích để phân tích mức độ sử dụng, hiệu năng, và rất nhiều thông số khác từ các ứng dụng Container, cung cấp cho người dùng cái nhìn tổng quan về toàn bộ các container đang chạy.

Link chi tiết các bạn có thể xem ở đây

Setup cAdvisor

Ở project của chúng ta, các bạn mở folder .docker, bên trong đó các bạn tạo cho mình 1 folder tên là monitoring để lưu cấu hình cho cAdvisor, Prometheus và Grafana nhé

Bởi vì Google đã cung cấp sẵn cho chúng ta Image của cAdvisor nên việc chạy sẽ vô cùng đơn giản 😘

Trong folder monitoring bên trên, các bạn tạo cho mình 1 file docker-compose.yml mới với nội dung như sau:

version: "3.8"
services:
  cadvisor:
    image: gcr.io/cadvisor/cadvisor:v0.38.6
    ports:
    - 8080:8080
    privileged: true
    devices:
      - /dev/kmsg
    volumes:
    - /:/rootfs:ro
    - /var/run:/var/run:ro
    - /sys:/sys:ro
    - /var/lib/docker/:/var/lib/docker:ro
    - /dev/disk/:/dev/disk:ro
    - /var/run/docker.sock:/var/run/docker.sock:ro
    - /etc/machine-id:/etc/machine-id:ro
    - /var/lib/dbus/machine-id:/var/lib/dbus/machine-id:ro

Ở trên ta map volumes một số chỗ để cAdvisor có thể đọc thông tin liên quan, tổng hợp và đưa ra các con số thống kê cho chúng ta

Tiếp theo ta khởi động cAdvisor lên nhé, vẫn ở folder monitoring các bạn chạy:

docker compose up -d

Sau đó ta mở trình duyệt, truy cập ở địa chỉ localhost:8080 sẽ thấy giao diện như sau:

Ở đó ta thấy vô vàn các thông tin hữu ích: danh sách các container, CPU/RAM/Disk... ở trên môi trường gốc:

Ở trang chủ các bạn click vào Docker containers sẽ hiện ra danh sách chi tiết các container đang được chạy trên máy gốc của chúng ta, các bạn có thể xem chi tiết thống kê về từng container, các bạn tha hồ tự vọc vạch nha, có rất nhiều thứ hay ho đấy ;

Screenshot 2024-02-15 at 11.58.10 PM.png

Chú ý là cAdvisor thống kê tất tần tật các container trên máy gốc của chúng ta, không chỉ mỗi project NodeJS ở bài này đâu nhé

Đến đây ta đã setup thành công cAdvisor để có một trang giao diện monitoring trông cũng đầy đủ và nhiều thông tin quan trọng, nom cũng ra gì phết ấy nhỉ 😂😂

Mặc dù ở trên ta đã thấy có 1 số thông tin tổng quát nhưng cAdvisor thực tế còn cung cấp rất nhiều thông tin chi tiết về các container đang chạy: IO operations, network, uptime, ... nhưng chúng không có ở trên trang giao diện quản lý kia. Mà cAdvisor để người dùng tuỳ chọn nếu có yêu cầu cụ thể. Các thông số khác mà cAdvisor cung cấp các ban có thể xem ở đây

Và để truy cập sâu hơn về thông tin các ứng dụng container ta cùng đi tới phần tiếp nhé

Prometheus

Tổng quan

Prometheus (đọc là: Pròm-mí-thi-ợt-s) là bộ toolkit để monitor system và thông báo (alert) dựa trên các thông số của hệ thống.

Prometheus có khá nhiều tính năng hay ho: dữ liệu tổ chức đa chiều, timeseries, có chức năng thông báo qua mail, sms,... Prometheus tích hợp được với rất nhiều thứ khác, không chỉ cAdvisor

Việc dùng cAdvisor và Prometheus cho phép ta có cái nhìn sâu hơn, chi tiết hơn về thông số của các ứng dụng Docker. cAdvisor đóng vai trò như người lấy thông tin, Prometheus là người nhận trách nhiệm lấy thông tin đó, tổ chức sao cho hợp lý và trả về cho người dùng.

Setup

Và vì Prometheus cũng cung cấp sẵn image nên việc chạy sẽ vô cùng đơn giản (cứ nghe đơn giản là thích rồi 😘😘)

Vẫn ở folder monitoring, các bạn tạo cho mình 1 file tên là prometheus.yml, với nội dung như sau:

scrape_configs:
- job_name: cadvisor
  scrape_interval: 5s
  static_configs:
  - targets:
    - cadvisor:8080

File này là file cấu hình cho Prometheus, ở trên ta có scrape_configs (scrape dịch ra là cạo, ý là liên tục "cạo" ra thông tin 😄, nghe chuối nhỉ).

Trong config ta có 1 job tên là cadvisor, ta có scrape_interval: 5s ý là cứ 5 giây thì "cạo" ra thông tin từ cAvisor 1 lần. Tiếp theo ta có static_configtargetscadvisor:8080 ý là "đây cạo thông tin từ ông cAvisor đang chạy ở địa chỉ cadvisor:8080".

Nhớ là phần địa chỉ cadvisor:8080 chính là tên service cadvisor ta viết ở docker-compose.yml nhé.

Cổng 8080 là cổng mặc định được cadvisor expose ra rồi nhé

Tiếp đó, vẫn ở folder .docker/monitoring, ta thêm vào docker-compose.yml với nội dung như sau:

version: "3.8"
services:
  cadvisor:
    image: gcr.io/cadvisor/cadvisor:v0.38.6
    ports:
    - 8080:8080
    privileged: true
    devices:
      - /dev/kmsg
    volumes:
    - /:/rootfs:ro
    - /var/run:/var/run:ro
    - /sys:/sys:ro
    - /var/lib/docker/:/var/lib/docker:ro
    - /dev/disk/:/dev/disk:ro
    - /var/run/docker.sock:/var/run/docker.sock:ro
    - /etc/machine-id:/etc/machine-id:ro
    - /var/lib/dbus/machine-id:/var/lib/dbus/machine-id:ro

  prometheus:
    image: prom/prometheus:v2.49.1
    ports:
    - 9090:9090
    command:
    - --config.file=/etc/prometheus/prometheus.yml
    volumes:
    - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
    depends_on:
    - cadvisor

Cuối cùng ta khởi động lại phần monitoring nhé:

docker compose down
docker compose up -d

Sau đó ta mở trình duyệt ở địa chỉ localhost:9090 sẽ thấy giao diện của Prometheus nhé:

Screenshot 2024-02-16 at 12.12.25 AM.png

Ta click chọn tab Graph,  sau đó bấm icon hình quả địa cầu để show list của tất cả các metrics mà ta có thể xem:

Screenshot 2024-02-16 at 2.48.21 PM.png

Ta sẽ thấy có ti tỉ loại thông số rất là chi tiết, đầu tiên ta thử chọn container_memory_usage_bytes, đây là thông số sử dụng RAM của từng container theo bytes, ta chọn tiếp interval 5m/10m/30m... (5 phút/10 phút/.... tuỳ ta chọn) sau đó bấm Execute, ta sẽ thấy đồ thị hiện ra dạng như sau:

Screenshot 2024-02-16 at 3.03.21 PM.png

Ta có thể truy vấn thông số của chỉ 1 container nào đó, ở ô text box các bạn gõ như sau sẽ thấy nó autocomplete hiện ra tất cả các thuộc tính mà ta có thể truy vấn, nó list luôn cả danh sách container cho ta luôn:

Screenshot 2024-02-16 at 2.54.48 PM.png

Khi bấm Execute thì giờ đồ thị sẽ chỉ show thông số của riêng container đó:

Screenshot 2024-02-16 at 3.00.09 PM.png

Ngoài ra còn có rất nhiều thông số khác ở ô select box, các bạn tuỳ chọn thoải mái tự sướng nhé 😉

Ở trên giao diện ta còn thấy có 1 số tab như Alerts (gửi thông báo, ví dụ khi CPU tăng lên 50% chẳng hạn, các bạn xem chi tiết Alert Manager), hay Status để xem thông tin về cấu hình Prometheus, phiên bản đang sử dụng....

Đến đây ta đã hoàn thành việc setup Prometheus, bằng việc kết hợp sử dụng cAdvisor ta có 2 công cụ để monitor ứng dụng Container rất hữu ích.

Có thể các bạn thấy rằng Prometheus nhiều thông số thật đấy, nhưng nom hơi phức tạp và không realtime, cứ phải bấm Execute. Thì ta cùng đến với phần tiếp theo đó là dùng Grafana để hiển thị (visualize) dữ liệu từ Prometheus cực chất nhé 😉

Grafana

Tổng quan

Grafana (đọc là: grơ-pha-nà) là một platform chuyên về data-visualization để phân tích dữ liệu trên giao diện Web. Grafana tích hợp được với rất nhiều thứ: MySQL, MongoDB, .... và cả Prometheus.

Sử dụng Grafana cho phép chúng ta tạo ra những trang Dashboard cực kì đẹp mắt, đầy đủ và trông rất chuyên nghiệp.

Ở bài này ta sẽ setup để Grafana lấy những thông tin mà bên Prometheus scrape được từ cAdvisor và hiển thị trên Dashboard của Grafana nhé

Setup

Grafana cung cấp cho chúng ta Docker image nên việc chạy sẽ cực kì đơn giản.

Vẫn ở folder ./docker/monitoring các bạn thêm vào docker-compose.yml 1 service mới tên là grafana với nội dung như sau:

...
grafana:
    image: grafana/grafana:10.3.3
    ports:
    - 4000:3000
    volumes:
    - ./data:/var/lib/grafana
    restart: always
    depends_on:
    - prometheus

Tiếp đó, vẫn ở folder monitoring, ta tạo 1 folder tên là data, mục đích dùng để lưu lại những Dashboard mà tí nữa ta sẽ tạo.

Cuối cùng, vẫn ở folder monitoring, ta chạy command sau để khởi động lại nhé:

docker-compose down
docker-compose up -d

Ngay sau khi các service được chạy lên thành công, ta mở trình duyệt ở địa chỉ localhost:4000 để truy cập Grafana, và sẽ thấy như sau:

Screenshot 2024-02-16 at 3.09.34 PM.png

Woaaaa, nom đẹp quá nhỉ 😍😍

Sau đó các bạn login với username+password mặc định đều là admin.

Sau khi login xong ta sẽ được điều hướng vào trang chủ nom rất đẹp như sau:

Screenshot 2024-02-16 at 3.10.30 PM.png

Sau đó các bạn click vào ô màu đỏ như trong hình để thêm Data Sources - thứ mà từ đó Grafana sẽ lấy data về để hiển thị

Tiếp đó các bạn chọn Prometheus:

Screenshot 2024-02-16 at 3.11.35 PM.png

Ở màn hình setup kết nối tới Prometheus, các bạn chỉ cần quan tâm tới mục HTTP như hình dưới, nhớ điền giống như mình nhé (http://prometheus:9090):

Screenshot 2024-02-16 at 3.13.13 PM.png

Sau đó ta kéo xuống dưới cùng bấm Save & Test, thấy in ra như sau là oke rồi nhé.

Screenshot 2024-02-16 at 3.13.28 PM.png

Sau đó ta quay lại trang chủ, chọn Create your first dashboard:

Chọn Add Visualization:

Screenshot 2024-02-16 at 3.14.25 PM.png

Tiếp đó ta chọn thông số container_network_transmit_bytes_total để xem thông tin về lưu lượng network traffic mà container của chúng ta trao đổi nhé, ta chọn Last 15 minutes để đồ thị hiển thị rõ ràng hơn cuối cùng ta bấm Run queries:

Screenshot 2024-02-16 at 3.23.32 PM.png

Ngay lập tức sau khi ta select thông số thì ta sẽ thấy đồ thị được in ra 💪💪. Sau đó ta bấm Apply, vậy là Dashboard của ta đã có 1 Panel với 1 thông số, nom như sau:

Screenshot 2024-02-16 at 3.27.50 PM.png

Sau đó ta chọn interval để nó tự fetch lại data update đồ thị, rồi bấm Save và nhập vào tên của dashboard rồi lưu lại nha:

Screenshot 2024-02-16 at 3.28.21 PM.png

Sau khi lưu xong thì dashboard của ta sẽ được hiển thị ngay trên trang chủ như sau:

Screenshot 2024-02-16 at 3.28.35 PM.png

Ều, nhưng mà nom cái đồ thị nghèo nàn nhỉ 🤣🤣.

Muốn có dashboard đẹp đẹp như lúc đầu show hàng thì chả nhẽ cứ ngồi lọ mọ thêm từng Panel à? Biết thông số nào mà thêm vào đây??? 🤔🤔

Thì Grafana có 1 thư viện các dashboard được build sẵn khổng lồ, ti tỉ dashboard, ta tha hồ chọn, những người khác đã tốn công build sẵn cho chúng ta dùng rồi 😉

Các bạn truy cập vào trang thư viện Dashboard của Grafana ở đây, rồi lọc Dashboard với data source là Prometheus, ta sẽ thấy có rất nhiều Dashboard build sẵn dành cho Prometheus.

Screenshot 2024-02-16 at 3.44.34 PM.png

Hìu vẫn chả biết chọn cái nào?? 😭😭

Thì mình có dùng 1 Dashboard với ID là 193 mình thấy nom cũng ổn, ta cùng import Dashboard này nhé.

Ta quay lại Grafana ở local, ở thanh Sidebar bên trái click chọn Dashboard:

Screenshot 2024-02-16 at 3.45.14 PM.png

Ở màn hình tiếp theo bấm ở đây và chọn Import:

Screenshot 2024-02-16 at 3.45.35 PM.png

Tiếp đó các bạn nhập ID dashboard 193 mà ta muốn cài vào, bấm Load, ở ô Select chọn Prometheus, rồi bấm Import là xong:

Screenshot 2024-02-16 at 3.45.44 PM.png

Sau đó chọn data source là Prometheus:

Screenshot 2024-02-16 at 3.45.52 PM.png

Và ta sẽ thấy Dashboard hiển thị như sau:

Screenshot 2024-02-16 at 3.46.17 PM.png

Sau đó ta nhớ bấm Save để lưu lại dashboard nha.

Vậy là chúng ta đã hoàn thành việc setup monitoring với Grafana rồi đó, Dashboard nom cũng ra gì phết ấy chứ nhỉ 😂😂

Các bạn có thể chọn time range ví dụ như mình là 5m thì đồ thị sẽ hiển thị rõ ràng hơn

Note

Thường theo cảm nhận bản thân thì mình thấy Grafana là đủ, 2 WebUI của cAdvisor và Prometheus mình khá ít dùng tới. Thứ nữa là 2 WebUI đó lại không có authentication. Đúng là Prometheus có support basic Auth, nhưng còn cAdvisor setup authentication khá là chuối. Mà chạy ở production không lẽ mình lại để vậy, mở public cho người ngoài xem 😂

Vậy nên nếu ta không thực sự dùng tới 2 web UI của cAdvisor và Prometheus thì ta bỏ map port ở docker-compose đi nhé các bạn, thì bên ngoài sẽ không truy cập vào được:

...

  cadvisor:
    image: gcr.io/cadvisor/cadvisor:v0.47.2
    # ports: ---> ở đây
    # - 8080:8080
    privileged: true
    devices:
      - /dev/kmsg
    volumes:
    - /:/rootfs:ro
    - /var/run:/var/run:ro
    - /sys:/sys:ro
    - /var/lib/docker/:/var/lib/docker:ro
    - /dev/disk/:/dev/disk:ro
    - /var/run/docker.sock:/var/run/docker.sock:ro
    - /etc/machine-id:/etc/machine-id:ro
    - /var/lib/dbus/machine-id:/var/lib/dbus/machine-id:ro

  prometheus:
    image: prom/prometheus:v2.49.1
    # ports: --> ở đây
    # - 9090:9090
    command:
    - --config.file=/etc/prometheus/prometheus.yml
    volumes:
    - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
    depends_on:
    - cadvisor
    
...

Ta chỉ cần map port của Grafana thôi là đủ vì ta chỉ sử dụng Grafana là chủ yếu.

Thứ nữa là vì những thông số thông kê từ cAdvisor là cho toàn bộ tất cả các container đang được chạy trên máy của chúng ta. Vì thế khi chạy thật mình nghĩ các bạn nên đặt cấu hình của chúng ra 1 nơi nào đó riêng. Ở bài này mình để chung cả vào project NodeJS để lát còn commit lên Gitlab được 😄

Đóng máy

Qua bài này ta đã biết được cách setup các công cụ để monitor ứng dụng Container sử dụng bộ 3 quân bài trùng cAdvisor, Prometheus và Grafana, từ đó tạo ra những Dashboard để monitor rất đẹp và trực quan.

Việc monitor system ở production là điều luôn luôn phải làm, và làm thường xuyên do vậy với sự trợ giúp đắc lực của những tool bên trên thì ta sẽ tiết kiệm được nhiều thời gian trong việc dựng Dashboard và có được những thôn tin hữu ích chi tiết về hệ thống của chúng ta.

Cám ơn các bạn đã theo dõi, hẹn gặp lại các bạn vào những bài sau ^^


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí