Kiến thức

Logging System cho k8s với Loki

Loki là hệ thống thu thập và tra cứu log tập trung được thiết kế từ Prometheus, có tính sẵn sàng cao (high-available) và có khả năng scale tốt. Loki được thiết kế để dễ dàng vận hành và hiệu quả về chi phí.

So sánh với các hệ thống log khác, Loki có một vài điểm khác:

  • Không index fulltext log.
  • Lưu trữ với thuật toán nén, không có cấu trúc log, chỉ index metadata.
  • Loki dễ dàng vận hành và chỉ cần resource nhỏ là có thể chạy.
  • Index và group các luồng log stream dựa vào các nhãn giống nhau.
  • Đặc biệt rất phù hợp với lưu trữ log của các Pod chạy trong Kubernetes.

Hệ thống logging của Loki gồm 3 thành phần chính:

  • Promtail là agent, có trách nhiệm đi thu gom log và gửi về cho Loki.
  • Loki là thành phần chính, có trách nhiệm lưu trữ log và xử lý các câu query.
  • Grafana là công cụ query và hiển thị log.

Loki có thể hiểu là kho lưu trữ dữ liệu được tối ưu hóa để lưu log một cách hiệu quả nhằm giúp công việc tra cứu nhanh hơn các hệ thống log thông thường.

Để có thể tăng tốc độ tra cứu loki không chỉ lưu lại các dòng log thông thường mà đánh chỉ mục các log dựa trên các metadata. Ví dụ như sau:

Labels: __name__ = logs app = graphite cluster = us-central1 color = b container_name = graphite filename = /var/log/pods/metrictank_graphite-og hosted_metrics = 1 instance = graphite-1-large-mdb68b5c-jh769 job = metrictank/graphite namespace = metrictank org = 1 plan = large pod_template_hash = 5f9db68b5c stream = stderr

Loki cần các agent chạy độc lập để đẩy log về lưu trữ. Có thể tham khảo một vài các công cụ thu thập log khác như Fluent Bit, Fluentd, Logstash..

Đa phần các công cụ sẽ có một vài điểm chung trong kiến trúc. Trong bài giới thiệu này chúng tôi sẽ nói cụ thể hơn về promtail. 3 tính năng chính của promtail là:

  • Tìm kiếm các targets (container, app, pod …)
  • Gán nhãn và trích xuất metadata của các log stream.
  • Đẩy các dòng log và nhãn về cho Loki thông qua HTTP API.

Trong các hệ thống sử dụng k8s Promtail sẽ được chạy dưới dạng các Daemonset trên mỗi node và gửi trả log về cho Loki dưới dạng HTTP API. Promtail có thể theo dõi log từ hai nguồn: local log files và systemd log.

Chuyên gia chia sẻ  Hướng dẫn cài đặt và đăng ký tài khoản Airpay

Scraping log (tìm kiếm các log)

Promtail tìm vị trí của các tệp log và trích xuất nhãn từ chúng thông qua phần scrape_configs trong YAML cấu hình. Cú pháp giống hệt với những gì Prometheus sử dụng.

scrape_configs chứa một hoặc nhiều phần được thực thi cho từng mục tiêu (VD cho từng container trong mỗi pod chạy trên một node):

scrape_configs: – job_name: local static_configs: – … – job_name: kubernetes kubernetes_sd_config: – …

Nếu có nhiều hơn một scrape_configs với một mục tiêu (cùng một container), sẽ nhận được các dòng log trùng lặp vì log sẽ được gửi theo các luồng khác nhau có thể trả ra các label khác nhau.

Kubernetes Discovery

Promtail có thể sử dụng API Kubernetes để khám phá các pod làm mục tiêu, nhưng nó chỉ có thể đọc các tệp log từ các pod đang chạy trên cùng một node với Promtail đang chạy trên đó. Promtail tìm kiếm nhãn __host__ trên mỗi mục tiêu và xác thực rằng nó được đặt thành cùng tên máy chủ như của Promtail.

relabel_configs: – source_labels: [‘__meta_kubernetes_pod_node_name’] target_label: ‘__host__’

Kubernetes config

Cấu hình này cho phép lấy các metadata của kubernetes thông qua REST API và các dữ liệu này được đồng bộ với cluster

Một vài các config để lấy các metadata thường dùng như:

Đối với Node: __meta_kubernetes_node_name: tên của node __meta_kubernetes_node_address_<address_type>: The first address for each node address type, if it exists. Service: __meta_kubernetes_namespace: tên namespace của service __meta_kubernetes_service_cluster_ip: cluster_ip của service __meta_kubernetes_service_name: tên của service pod __meta_kubernetes_pod_name: tên của pod __meta_kubernetes_pod_container_name: tên container ingress: __meta_kubernetes_ingress_name: tên của ingress __meta_kubernetes_ingress_path

Lưu trữ

Grafana Loki cần lưu trữ hai loại dữ liệu khác nhau: chunkindex.

Loki nhận log trong các luồng riêng biệt, trong đó mỗi luồng được xác định duy nhất bằng ID đối tượng và bộ label của nó.

Khi các log từ một luồng đến, chúng được nén thành chunk và được lưu trong chunk store.

Index sẽ lưu trữ bộ label của từng luồng và liên kết chúng với các chunk riêng lẻ.

Table Manager

Hai tác dụng chính

  • Thay đổi schema_config: mỗi table được giới hạn với một phiên bản và schema, do đó ta có thể thay đổi schema theo thời gian, và với mỗi khoảng thời gian khác nhau có thể dùng các version schema khác nhau
  • Retention: tự động xóa các table khi chúng expire
Chuyên gia chia sẻ  Làm cách nào để xác định giá trị rủi ro thị trường của công ty chứng khoán?

Các backend được Loki hỗ trợ để lưu trữ index bao gồm

  • Single Store (boltdb-shipper)
  • Amazon DynamoDB
  • Google Bigtable
  • Apache Cassandra
  • BoltDB (thường dùng local)

Các backend được Loki hỗ trợ để lưu trữ chunk bao gồm

  • Amazon DynamoDB
  • Google Bigtable
  • Apache Cassandra
  • Amazon S3
  • Google Cloud Storage
  • Filesystem (thường dùng local)
  • Baidu Object Storage

Retention

Thao tác retention là thao tác xóa các table cũ, đã expire và không còn cần thiết, để giữ cho chunk store và index store của Loki không bị đầy lên theo thời gian, giảm hiệu quả store/query và tốn chi phí lưu trữ.

Thao tác này được quản lý bởi Table Manager (theo mặc định sẽ không được bật lên do tính chất xóa file cũ).

Có thể kích hoạt tính năng này trong configuration và đặt retention_period > 0:

table_manager: retention_deletes_enabled: true retention_period: 336h

Table Manager sẽ thực hiện xóa toàn bộ bảng có dữ liệu timestamp vượt quá retention_period tính tới thời điểm chạy. Thiết kế này cho phép thực hiện các thao tác xóa nhanh, kiểm soát bởi thời gian tồn tại của bảng.

Table Manager sẽ tính toán giữ cho các bảng cuối cùng tồn tại bằng công thức sau:

number_of_tables_to_keep = floor(retention_period / table_period) + 1

LogQL: Log query language

LogQL có thể hiểu đơn giản giống như PromQL sử dụng khi truy vấn với Prometheus

Có hai loại truy vấn LogQL: Log query và metric query

  • Log query: trả về nội dung của các dòng nhật ký.
  • Metric query: để tính toán giá trị dựa trên kết quả truy vấn.

Sử dụng docker-compose tạo một stack các service bao gồm: grafana, loki, promtail

Config loki

Tạo file loki-config.yml

auth_enabled: false chunk_store_config: max_look_back_period: 0s compactor: shared_store: filesystem working_directory: /data/loki/boltdb-shipper-compactor ingester: chunk_block_size: 262144 chunk_idle_period: 3m chunk_retain_period: 1m lifecycler: ring: kvstore: store: inmemory replication_factor: 1 max_transfer_retries: 0 limits_config: enforce_metric_name: false reject_old_samples: false reject_old_samples_max_age: 4320h max_entries_limit_per_query: 5000 schema_config: configs: – from: “2020-10-24” index: period: 24h prefix: index_ object_store: filesystem schema: v11 store: boltdb-shipper server: http_listen_port: 3100 storage_config: boltdb_shipper: active_index_directory: /data/loki/boltdb-shipper-active cache_location: /data/loki/boltdb-shipper-cache cache_ttl: 24h shared_store: filesystem filesystem: directory: /data/loki/chunks table_manager: retention_deletes_enabled: true retention_period: 168h

Một vài cài đặt cần lưu ý

  • ingester cấu hình để đẩy ra file chunk vd thời gian giữ file, dung lượng file tối đa
  • schema_config khai báo sử dụng phương pháp lưu index dùng boltdb-shipper và lưu chunk dùng filesystem
  • http_listen_port loki chạy HTTP API ở cổng 3100 lưu ý khi add vào Grafana sẽ cần endpoint này
  • storage_config khai báo thư mục lưu index và chunk
  • table_manager bật tính năng retention với thời gian lưu file chunk cũ
Chuyên gia chia sẻ  Initial nghĩa là gì: Định nghĩa, Ví dụ

Config promtail

Tạo file promtail-config.yml

server: http_listen_address: 0.0.0.0 http_listen_port: 9080 positions: filename: /tmp/positions.yaml clients: – url: http://localhost:3100/loki/api/v1/push scrape_configs: – job_name: kubernetes-pods-name pipeline_stages: – docker: {} kubernetes_sd_configs: – role: pod relabel_configs: – source_labels: [__meta_kubernetes_namespace] action: drop regex: auth|cert-manager – source_labels: – __meta_kubernetes_pod_label_name target_label: __service__ – source_labels: – __meta_kubernetes_pod_node_name target_label: __host__ – action: replace source_labels: – __meta_kubernetes_namespace target_label: namespace – action: labelmap regex: __meta_kubernetes_pod_label_(.+) – action: replace source_labels: – __meta_kubernetes_pod_name target_label: pod – action: replace source_labels: – __meta_kubernetes_pod_container_name target_label: container – replacement: /var/log/pods/*$1/*.log separator: / source_labels: – __meta_kubernetes_pod_uid – __meta_kubernetes_pod_container_name target_label: __path__

Mô tả một vài các stages trong pipeline được sử dụng

  • parsing stage
    • docker: Trích xuất dữ liệu bằng cách phân tích log bằng định dạng Docker tiêu chuẩn.
    • action.replace: thay thế các label gốc bằng label tự tạo. Khai báo source_labels và target_label
  • filtering stage
    • action.drop: bỏ đi các log phù hợp với regex phía dưới (regex: auth|cert-manager)

Tạo các service

docker-compose up -d

version: “3.3” networks: monitor: driver: bridge services: grafana: restart: always image: grafana/grafana:latest container_name: grafana ports: – “3000:3000” volumes: – $PWD/grafana:/var/lib/grafana networks: – monitor loki: image: grafana/loki:2.1.0 container_name: loki restart: unless-stopped ports: – 3100:3100 command: -config.file=/etc/loki/local-config.yaml volumes: – ./loki-config.yaml:/etc/loki/local-config.yaml networks: – monitor promtail: image: grafana/promtail:latest container_name: promtail restart: unless-stopped volumes: – /var/lib/docker/containers:/var/lib/docker/containers – ./promtail-config.yml:/etc/promtail/promtail-config.yml command: -config.file=/etc/promtail/promtail-config.yml networks: – monitor

Thêm datasource loki vào grafana

Truy cập localhost:3000 mặc định admin/admin

Click Save & test => Explore

Tra cứu log với loki

VD Query log theo tên của namespace và tên pod, thường dùng khi muốn xem chi tiết log của 1 pod đang có lỗi

VD khi muốn lọc các kết quả có chứa chữ “endpointslice”, thường dùng khi muốn filter các entries của 1 log stream theo 1 keyword cụ thể (vd xem các log DEBUG, WARNING hoặc ERROR)

Metric queries:

VD khi muốn đếm các dòng log của từng pod, thường dùng nếu muốn tìm xem pod nào đang có khả năng gặp lỗi. Pod gặp lỗi thường sẽ bắn ra nhiều log hơn các pod khác.

Đánh giá bài viết post

Phạm Văn Sỹ

Tôi là Phạm Văn Sỹ chuyên gia uy tín trong lĩnh vực kinh tế và kinh doanh là sinh viên của trường Đại học Ngoại Thương. Với kiến thức sâu rộng sau 12 năm ở bên ngoài thương trường thị trường tôi mong muốn chia sẻ các kiến thức chuyên sâu hữu ích dành cho mọi người.

Related Articles

Back to top button