Phát triển plugin cho Grafana: lịch sử của những cú hích lớn

Chào mọi người! Một vài tháng trước, chúng tôi đã đưa dự án nguồn mở mới vào sản xuất - plugin Grafana để giám sát kubernetes mà chúng tôi gọi là DevOpsThần đồng KubeGraf. Mã nguồn plugin có sẵn tại kho lưu trữ công cộng trên GitHub. Và trong bài viết này, chúng tôi muốn chia sẻ với bạn câu chuyện về cách chúng tôi tạo ra plugin, những công cụ chúng tôi đã sử dụng và những cạm bẫy mà chúng tôi gặp phải trong quá trình phát triển. Đi nào!

Phần 0 - giới thiệu: làm thế nào chúng ta đi đến điểm này?

Ý tưởng viết plugin riêng cho Grafan đến với chúng tôi một cách khá tình cờ. Công ty chúng tôi đã giám sát các dự án web với nhiều mức độ phức tạp khác nhau trong hơn 10 năm. Trong thời gian này, chúng tôi đã tích lũy được rất nhiều kiến ​​thức chuyên môn, các trường hợp thú vị và kinh nghiệm trong việc sử dụng các hệ thống giám sát khác nhau. Và tại một thời điểm nào đó, chúng tôi đã tự hỏi: “Có công cụ kỳ diệu nào để giám sát Kubernetes không, để như người ta nói, “đặt nó và quên nó đi”?”.. Tất nhiên, tiêu chuẩn ngành để giám sát k8 từ lâu đã là tiêu chuẩn Sự kết hợp Prometheus + Grafana. Và là giải pháp được tạo sẵn cho ngăn xếp này, có một bộ lớn các loại công cụ khác nhau: prometheus-operator, một bộ bảng thông tin kubernetes-mixin, grafana-kubernetes-app.

Plugin grafana-kubernetes-app dường như là lựa chọn thú vị nhất đối với chúng tôi, nhưng nó đã không được hỗ trợ trong hơn một năm và hơn nữa, không thể hoạt động với các phiên bản mới của node-exporter và kube-state-metrics. Và đến một lúc nào đó, chúng tôi quyết định: “Chúng ta có nên tự đưa ra quyết định của mình không?”

Những ý tưởng mà chúng tôi quyết định triển khai trong plugin của mình:

  • trực quan hóa “bản đồ ứng dụng”: trình bày thuận tiện các ứng dụng trong cụm, được nhóm theo không gian tên, triển khai...;
  • trực quan hóa các kết nối như “triển khai - dịch vụ (+ cổng)”.
  • trực quan hóa sự phân bố của các ứng dụng cụm trên các nút cụm.
  • thu thập số liệu và thông tin từ nhiều nguồn: máy chủ api Prometheus và k8s.
  • giám sát cả phần cơ sở hạ tầng (sử dụng thời gian CPU, bộ nhớ, hệ thống con đĩa, mạng) và logic ứng dụng - nhóm trạng thái sức khỏe, số lượng bản sao có sẵn, thông tin về việc vượt qua các bài kiểm tra khả năng hoạt động/sẵn sàng.

Phần 1: “Plugin Grafana” là gì?

Từ quan điểm kỹ thuật, plugin cho Grafana là bộ điều khiển góc, được lưu trữ trong thư mục dữ liệu Grafana (/var/grafana/plugin/ /dist/module.js) và có thể được tải dưới dạng mô-đun SystemJS. Ngoài ra, trong thư mục này còn có tệp plugin.json chứa tất cả thông tin meta về plugin của bạn: tên, phiên bản, loại plugin, liên kết đến kho lưu trữ/trang web/giấy phép, phần phụ thuộc, v.v.

Phát triển plugin cho Grafana: lịch sử của những cú hích lớn
mô-đun.ts

Phát triển plugin cho Grafana: lịch sử của những cú hích lớn
plugin.json

Như bạn có thể thấy trong ảnh chụp màn hình, chúng tôi đã chỉ định plugin.type = app. Bởi vì plugin cho Grafana có thể có ba loại:

bảng điều khiển: loại plugin phổ biến nhất - đó là bảng điều khiển để trực quan hóa bất kỳ số liệu nào, được sử dụng để xây dựng các trang tổng quan khác nhau.
nguồn dữ liệu: trình kết nối plugin với một số nguồn dữ liệu (ví dụ: Prometheus-datasource, ClickHouse-datasource, ElasticSearch-datasource).
ứng dụng: Một plugin cho phép bạn xây dựng ứng dụng giao diện người dùng của riêng mình bên trong Grafana, tạo các trang html của riêng bạn và truy cập thủ công vào nguồn dữ liệu để trực quan hóa nhiều dữ liệu khác nhau. Ngoài ra, các loại plugin khác (nguồn dữ liệu, bảng điều khiển) và các trang tổng quan khác nhau có thể được sử dụng làm phần phụ thuộc.

Phát triển plugin cho Grafana: lịch sử của những cú hích lớn
Ví dụ phụ thuộc plugin với type=app.

Bạn có thể sử dụng cả JavaScript và TypeScript làm ngôn ngữ lập trình (chúng tôi đã chọn nó). Chuẩn bị cho bất kỳ loại plugin hello-world nào bạn có thể tìm bằng liên kết: kho lưu trữ này chứa một số lượng lớn gói khởi động (thậm chí còn có một ví dụ thử nghiệm về plugin trong React) với các trình tạo được cài đặt sẵn và định cấu hình.

Phần 2: chuẩn bị môi trường địa phương

Để làm việc với plugin, đương nhiên chúng ta cần một cụm kubernetes với tất cả các công cụ được cài đặt sẵn: prometheus, node-exporter, kube-state-metrics, grafana. Môi trường phải được thiết lập nhanh chóng, dễ dàng và tự nhiên, đồng thời để đảm bảo tải lại nhanh, thư mục dữ liệu Grafana phải được gắn trực tiếp từ máy của nhà phát triển.

Theo chúng tôi, cách thuận tiện nhất để làm việc cục bộ với kubernetes là minikube. Bước tiếp theo là cài đặt tổ hợp Prometheus + Grafana bằng toán tử prometheus. TRONG bài viết này Quá trình cài đặt prometheus-operator trên minikube được mô tả chi tiết. Để kích hoạt tính bền bỉ, bạn phải đặt tham số kiên trì: đúng trong tệp Charts/grafana/values.yaml, thêm PV và PVC của riêng bạn và chỉ định chúng trong tham số Persence.beingClaim

Kịch bản khởi chạy minikube cuối cùng của chúng tôi trông như thế này:

minikube start --kubernetes-version=v1.13.4 --memory=4096 --bootstrapper=kubeadm --extra-config=scheduler.address=0.0.0.0 --extra-config=controller-manager.address=0.0.0.0
minikube mount 
/home/sergeisporyshev/Projects/Grafana:/var/grafana --gid=472 --uid=472 --9p-version=9p2000.L

Phần 3: Phát triển thực tế

Mô hình đối tượng

Để chuẩn bị triển khai plugin, chúng tôi đã quyết định mô tả tất cả các thực thể Kubernetes cơ bản mà chúng tôi sẽ làm việc dưới dạng các lớp TypeScript: pod, triển khai, daemonset, statefulset, job, cronjob, service, node, namespace. Mỗi lớp này kế thừa từ lớp BaseModel chung, lớp này mô tả hàm tạo, hàm hủy, các phương thức cập nhật và chuyển đổi chế độ hiển thị. Mỗi lớp mô tả các mối quan hệ lồng nhau với các thực thể khác, ví dụ: danh sách các nhóm cho một thực thể thuộc loại triển khai.

import {Pod} from "./pod";
import {Service} from "./service";
import {BaseModel} from './traits/baseModel';

export class Deployment extends BaseModel{
   pods: Array<Pod>;
   services: Array<Service>;

   constructor(data: any){
       super(data);
       this.pods = [];
       this.services = [];
   }
}

Với sự trợ giúp của getters và setters, chúng ta có thể hiển thị hoặc đặt các số liệu thực thể mà chúng ta cần ở dạng thuận tiện và dễ đọc. Ví dụ: đầu ra được định dạng của các nút cpu có thể phân bổ:

get cpuAllocatableFormatted(){
   let cpu = this.data.status.allocatable.cpu;
   if(cpu.indexOf('m') > -1){
       cpu = parseInt(cpu)/1000;
   }
   return cpu;
}

trang

Danh sách tất cả các trang plugin của chúng tôi được mô tả ban đầu trong pluing.json trong phần phụ thuộc:

Phát triển plugin cho Grafana: lịch sử của những cú hích lớn

Trong khối cho mỗi trang, chúng ta phải chỉ ra TÊN TRANG (sau đó nó sẽ được chuyển đổi thành một phần mở rộng để trang này có thể truy cập được); tên của thành phần chịu trách nhiệm vận hành trang này (danh sách các thành phần được xuất sang module.ts); cho biết vai trò của người dùng làm việc với trang này có sẵn và cài đặt điều hướng cho thanh bên.

Trong thành phần chịu trách nhiệm về hoạt động của trang, chúng ta phải đặt templateUrl, chuyển đến đó đường dẫn đến tệp html có đánh dấu. Bên trong bộ điều khiển, thông qua việc nội xạ phụ thuộc, chúng ta có thể truy cập tối đa 2 dịch vụ góc quan trọng:

  • backendSrv - một dịch vụ cung cấp khả năng tương tác với máy chủ API Grafana;
  • datasourceSrv - một dịch vụ cung cấp tương tác cục bộ với tất cả các nguồn dữ liệu được cài đặt trong Grafana của bạn (ví dụ: phương thức .getAll() - trả về danh sách tất cả các nguồn dữ liệu đã cài đặt; .get( ) - trả về một đối tượng thể hiện của một nguồn dữ liệu cụ thể.

Phát triển plugin cho Grafana: lịch sử của những cú hích lớn

Phát triển plugin cho Grafana: lịch sử của những cú hích lớn

Phát triển plugin cho Grafana: lịch sử của những cú hích lớn

Phần 4: nguồn dữ liệu

Theo quan điểm của Grafana, nguồn dữ liệu hoàn toàn giống với tất cả các plugin khác: nó có điểm vào module.js riêng, có một tệp có thông tin meta plugin.json. Khi phát triển plugin với type = app, chúng tôi có thể tương tác với cả nguồn dữ liệu hiện có (ví dụ: prometheus-datasource) và nguồn dữ liệu của riêng chúng tôi, chúng tôi có thể lưu trữ trực tiếp trong thư mục plugin (dist/datasource/*) hoặc cài đặt dưới dạng phụ thuộc. Trong trường hợp của chúng tôi, nguồn dữ liệu đi kèm với mã plugin. Cũng cần phải có mẫu config.html và bộ điều khiển ConfigCtrl, sẽ được sử dụng cho trang cấu hình phiên bản nguồn dữ liệu và bộ điều khiển Datasource, thực hiện logic của nguồn dữ liệu của bạn.

Trong plugin KubeGraf, từ quan điểm giao diện người dùng, nguồn dữ liệu là một phiên bản của cụm kubernetes triển khai các khả năng sau (mã nguồn có sẵn по ссылке):

  • thu thập dữ liệu từ máy chủ api của k8s (lấy danh sách các không gian tên, triển khai ...)
  • gửi yêu cầu ủy quyền tới prometheus-datasource (được chọn trong cài đặt plugin cho từng cụm cụ thể) và định dạng phản hồi để sử dụng dữ liệu cả trong trang tĩnh và trong trang tổng quan.
  • cập nhật dữ liệu trên các trang plugin tĩnh (với tốc độ làm mới đã đặt).
  • xử lý các truy vấn để tạo một trang mẫu trong bảng điều khiển grafana (phương thức metriFindQuery())

Phát triển plugin cho Grafana: lịch sử của những cú hích lớn

Phát triển plugin cho Grafana: lịch sử của những cú hích lớn

Phát triển plugin cho Grafana: lịch sử của những cú hích lớn

  • kiểm tra kết nối với cụm k8s cuối cùng.
testDatasource(){
   let url = '/api/v1/namespaces';
   let _url = this.url;
   if(this.accessViaToken)
       _url += '/__proxy';
   _url += url;
   return this.backendSrv.datasourceRequest({
       url: _url,
       method: "GET",
       headers: {"Content-Type": 'application/json'}
   })
       .then(response => {
           if (response.status === 200) {
               return {status: "success", message: "Data source is OK", title: "Success"};
           }else{
               return {status: "error", message: "Data source is not OK", title: "Error"};
           }
       }, error => {
           return {status: "error", message: "Data source is not OK", title: "Error"};
       })
}

Theo chúng tôi, một điểm thú vị riêng là việc triển khai cơ chế xác thực và ủy quyền cho nguồn dữ liệu. Thông thường, chúng ta có thể sử dụng datasourceHttpSettings thành phần Grafana tích hợp sẵn để định cấu hình quyền truy cập vào nguồn dữ liệu cuối cùng. Bằng cách sử dụng thành phần này, chúng tôi có thể định cấu hình quyền truy cập vào nguồn dữ liệu http bằng cách chỉ định url và cài đặt xác thực/ủy quyền cơ bản: mật khẩu đăng nhập hoặc client-cert/client-key. Để triển khai khả năng định cấu hình quyền truy cập bằng mã thông báo mang (tiêu chuẩn thực tế cho k8), chúng tôi đã phải thực hiện một chút điều chỉnh.

Để giải quyết vấn đề này, bạn có thể sử dụng cơ chế “Lộ trình plugin” tích hợp sẵn của Grafana (chi tiết tại trang tài liệu chính thức). Trong cài đặt nguồn dữ liệu của chúng tôi, chúng tôi có thể khai báo một bộ quy tắc định tuyến sẽ được máy chủ proxy grafana xử lý. Ví dụ: đối với mỗi điểm cuối riêng lẻ, có thể đặt tiêu đề hoặc url với khả năng tạo khuôn mẫu, dữ liệu có thể được lấy từ các trường jsonData và safeJsonData (để lưu trữ mật khẩu hoặc mã thông báo ở dạng mã hóa). Trong ví dụ của chúng tôi, các truy vấn như /__proxy/api/v1/không gian tên sẽ được ủy quyền cho url của biểu mẫu
/api/v8/namespaces với tiêu đề Authorization: Bearer.

Phát triển plugin cho Grafana: lịch sử của những cú hích lớn

Phát triển plugin cho Grafana: lịch sử của những cú hích lớn

Đương nhiên, để làm việc với máy chủ api k8s, chúng tôi cần một người dùng có quyền truy cập chỉ đọc, các bảng kê khai để tạo mà bạn cũng có thể tìm thấy trong mã nguồn plugin.

Phần 5: phát hành

Phát triển plugin cho Grafana: lịch sử của những cú hích lớn

Sau khi bạn đã viết plugin Grafana của riêng mình, tất nhiên bạn sẽ muốn công khai nó. Trong Grafana, đây là thư viện plugin có sẵn tại đây grafana.com/grafana/plugins

Để plugin của bạn có sẵn trên cửa hàng chính thức, bạn cần thực hiện PR trong kho lưu trữ nàybằng cách thêm nội dung như thế này vào tệp repo.json:

Phát triển plugin cho Grafana: lịch sử của những cú hích lớn

trong đó phiên bản là phiên bản plugin của bạn, url là liên kết đến kho lưu trữ và cam kết là hàm băm của cam kết mà phiên bản cụ thể của plugin sẽ có sẵn.

Và ở đầu ra bạn sẽ thấy một bức tranh tuyệt vời như:

Phát triển plugin cho Grafana: lịch sử của những cú hích lớn

Dữ liệu cho nó sẽ được tự động lấy từ tệp Readme.md, Changelog.md và plugin.json cùng với mô tả plugin.

Phần 6: thay cho kết luận

Chúng tôi đã không ngừng phát triển plugin của mình sau khi phát hành. Và hiện tại, chúng tôi đang nỗ lực giám sát chính xác việc sử dụng tài nguyên của các nút cụm, giới thiệu các tính năng mới để cải thiện UX, đồng thời thu được một lượng lớn phản hồi nhận được sau khi cài đặt plugin bởi cả khách hàng của chúng tôi và từ mọi người trên GitHub (nếu bạn rời khỏi vấn đề của bạn hoặc yêu cầu kéo, tôi sẽ rất vui :)

Chúng tôi hy vọng rằng bài viết này sẽ giúp bạn hiểu về một công cụ tuyệt vời như Grafana và có thể viết plugin của riêng bạn.

Cảm ơn bạn!)

Nguồn: www.habr.com

Thêm một lời nhận xét