การพัฒนาปลั๊กอินสำหรับ Grafana: ประวัติความเป็นมาของภาพใหญ่

สวัสดีทุกคน! ไม่กี่เดือนที่ผ่านมา เราได้เปิดตัวโปรเจกต์โอเพนซอร์สใหม่ของเรา ซึ่งเป็นปลั๊กอิน Grafana สำหรับการตรวจสอบ Kubernetes สู่การผลิตจริง DevOpsProdigy KubeGrafซอร์สโค้ดปลั๊กอินมีอยู่ใน ที่เก็บข้อมูลสาธารณะบน GitHubในบทความนี้ เราอยากแบ่งปันเรื่องราวเกี่ยวกับวิธีการสร้างปลั๊กอิน เครื่องมือที่เราใช้ และปัญหาที่เราพบเจอระหว่างการพัฒนา มาเริ่มกันเลย!

ตอนที่ 0 - บทนำ: เราเดินทางมาถึงจุดนี้ได้อย่างไร?

ไอเดียการเขียนปลั๊กอินสำหรับ Grafana ของเราเองเกิดขึ้นโดยบังเอิญ บริษัทของเราได้ติดตามโครงการเว็บที่มีความซับซ้อนหลากหลายมานานกว่า 10 ปี ในช่วงเวลานี้ เราได้สั่งสมความเชี่ยวชาญ กรณีศึกษาที่น่าสนใจ และประสบการณ์การใช้งานระบบติดตามที่หลากหลาย มีอยู่ช่วงหนึ่งที่เราสงสัยว่า "มีเครื่องมือวิเศษสำหรับติดตาม Kubernetes ที่คุณสามารถ 'ตั้งค่าแล้วลืมมันไปได้เลย' อย่างที่ใครๆ พูดกัน" แน่นอนว่าชุด Prometheus + Grafana เป็นมาตรฐานอุตสาหกรรมสำหรับการติดตาม K8S มาอย่างยาวนาน มีเครื่องมือสำเร็จรูปมากมายสำหรับสแต็กนี้ ซึ่งรวมถึง prometheus-operator, kubernetes-mixin dashboard suite และ grafana-kubernetes-app

ปลั๊กอิน grafana-kubernetes-app ดูเหมือนจะเป็นตัวเลือกที่น่าสนใจที่สุดสำหรับเรา แต่มันไม่ได้รับการสนับสนุนมานานกว่าหนึ่งปีแล้ว และยิ่งไปกว่านั้น มันยังไม่สามารถใช้งานได้กับ node-exporter และ kube-state-metrics เวอร์ชันใหม่ ๆ อีกด้วย ถึงจุดหนึ่ง เราจึงตัดสินใจว่า "ทำไมไม่สร้างโซลูชันของเราเองล่ะ?"

เราตัดสินใจนำไอเดียใดมาใช้ในปลั๊กอินของเรา?

  • การแสดงภาพแผนที่แอปพลิเคชัน: การแสดงแอปพลิเคชันในคลัสเตอร์อย่างสะดวก โดยจัดกลุ่มตามเนมสเปซ การปรับใช้งาน ฯลฯ
  • การแสดงภาพการเชื่อมต่อประเภท "การปรับใช้ - บริการ (+ พอร์ต)"
  • การแสดงภาพการกระจายของแอปพลิเคชันคลัสเตอร์ในโหนดคลัสเตอร์
  • การรวบรวมเมตริกและข้อมูลจากหลายแหล่ง: เซิร์ฟเวอร์ Prometheus และ K8S API
  • การตรวจสอบทั้งโครงสร้างพื้นฐาน (การใช้เวลา CPU, หน่วยความจำ, ระบบย่อยของดิสก์, เครือข่าย) และตรรกะของแอปพลิเคชัน สถานะความสมบูรณ์ของพ็อด จำนวนแบบจำลองที่มีอยู่ และข้อมูลเกี่ยวกับความคืบหน้าของการทดสอบความพร้อมใช้งาน

ตอนที่ 1: ปลั๊กอิน Grafana คืออะไร?

จากมุมมองทางเทคนิค ปลั๊กอินสำหรับ Grafana เป็นตัวควบคุมเชิงมุมที่เก็บไว้ในไดเร็กทอรีข้อมูลของ Grafana (/var/grafana/plugins/ /dist/โมดูล.js) และสามารถโหลดเป็นโมดูล SystemJS ได้ ไดเรกทอรีนี้ควรมีไฟล์ plugin.json ด้วย ซึ่งประกอบด้วยข้อมูลเมตาทั้งหมดเกี่ยวกับปลั๊กอินของคุณ ได้แก่ ชื่อ เวอร์ชัน ประเภทปลั๊กอิน ลิงก์ที่เก็บ/เว็บไซต์/ใบอนุญาต การอ้างอิง และอื่นๆ

การพัฒนาปลั๊กอินสำหรับ Grafana: ประวัติความเป็นมาของภาพใหญ่
โมดูล.ts

การพัฒนาปลั๊กอินสำหรับ Grafana: ประวัติความเป็นมาของภาพใหญ่
Plugin.json

อย่างที่คุณเห็นในภาพหน้าจอ เราได้ระบุ plugin.type = app ไว้แล้ว เนื่องจากปลั๊กอินสำหรับ Grafana มีสามประเภท:

แผง:ปลั๊กอินประเภทที่พบมากที่สุด - เป็นแผงสำหรับแสดงข้อมูลเมตริกบางอย่าง และใช้ในการสร้างแดชบอร์ดต่างๆ
แหล่งข้อมูล:ตัวเชื่อมต่อปลั๊กอินไปยังแหล่งข้อมูลใดๆ (เช่น Prometheus-datasource, ClickHouse-datasource, ElasticSearch-datasource)
app:ปลั๊กอินที่ช่วยให้คุณสร้างแอปพลิเคชันส่วนหน้าของคุณเองภายใน Grafana สร้างหน้า HTML ของคุณเอง และเข้าถึงแหล่งข้อมูลด้วยตนเองเพื่อแสดงข้อมูลต่างๆ ปลั๊กอินประเภทอื่นๆ (แหล่งข้อมูล, แผงควบคุม) และแดชบอร์ดต่างๆ สามารถใช้เป็น dependencies ได้เช่นกัน

การพัฒนาปลั๊กอินสำหรับ Grafana: ประวัติความเป็นมาของภาพใหญ่
ตัวอย่างการพึ่งพาปลั๊กอินที่มีประเภท = app.

คุณสามารถใช้ JavaScript หรือ TypeScript เป็นภาษาโปรแกรมได้ (เราเลือก TypeScript) คุณสามารถสร้างเทมเพลตสำหรับปลั๊กอิน hello-world ทุกประเภทได้ ค้นหาโดยลิงค์:ที่เก็บข้อมูลนี้ประกอบด้วยแพ็คเริ่มต้นจำนวนมาก (ยังมีตัวอย่างทดลองของปลั๊กอิน React ด้วย) โดยมีตัวสร้างที่ติดตั้งและกำหนดค่าไว้ล่วงหน้า

ส่วนที่ 2: การเตรียมสภาพแวดล้อมในท้องถิ่น

ในการใช้งานปลั๊กอิน เราจำเป็นต้องมีคลัสเตอร์ Kubernetes พร้อมเครื่องมือทั้งหมดที่ติดตั้งไว้ล่วงหน้า ได้แก่ Prometheus, Node-Exporter, Kube-State-Metrics และ Grafana สภาพแวดล้อมควรตั้งค่าได้อย่างรวดเร็ว ง่ายดาย และปราศจากความยุ่งยาก และเพื่อให้มั่นใจว่าสามารถโหลดซ้ำได้ทันที ไดเรกทอรีข้อมูล Grafana ควรถูกเมาท์โดยตรงจากเครื่องของนักพัฒนา

ในความคิดของเรา วิธีที่สะดวกที่สุดในการทำงานในเครื่องด้วย Kubernetes คือ มินิคุเบะขั้นตอนถัดไปคือการติดตั้งชุด Prometheus + Grafana โดยใช้ prometheus-operator บทความนี้ ขั้นตอนการติดตั้ง prometheus-operator บน minikube มีรายละเอียดอธิบายไว้ หากต้องการเปิดใช้งานการคงอยู่ คุณต้องตั้งค่าพารามิเตอร์ ความคงอยู่: จริง ในไฟล์ charts/grafana/values.yaml ให้เพิ่ม PV และ PVC ของคุณเอง และระบุไว้ในพารามิเตอร์ persistence.existingClaim

สคริปต์เปิดตัว minikube สุดท้ายของเรามีลักษณะดังนี้:

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

ส่วนที่ 3: การพัฒนาโดยตรง

แบบจำลองวัตถุ

ในการเตรียมการสำหรับการนำปลั๊กอินไปใช้งานจริง เราได้ตัดสินใจกำหนดเอนทิตี Kubernetes พื้นฐานทั้งหมดที่เราจะใช้งานเป็นคลาส TypeScript ได้แก่ pod, deployment, daemonset, statefulset, job, cronjob, service, node และ namespace คลาสเหล่านี้แต่ละคลาสสืบทอดมาจากคลาส BaseModel ทั่วไป ซึ่งกำหนด constructor, destructor และเมธอดสำหรับการอัปเดตและสลับการมองเห็น นอกจากนี้ แต่ละคลาสยังกำหนดความสัมพันธ์แบบซ้อนกับเอนทิตีอื่นๆ เช่น รายการ pod สำหรับเอนทิตีการปรับใช้

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 = [];
   }
}

การใช้ getters และ setters ช่วยให้เราสามารถแสดงหรือตั้งค่าเมตริกเอนทิตีที่ต้องการในรูปแบบที่สะดวกและอ่านง่าย ตัวอย่างเช่น ผลลัพธ์ที่จัดรูปแบบของโหนด CPU ที่สามารถจัดสรรได้:

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

หน้า

รายการของหน้าทั้งหมดของปลั๊กอินของเราได้รับการอธิบายไว้ในเบื้องต้นใน pluing.json ในส่วนการอ้างอิง:

การพัฒนาปลั๊กอินสำหรับ Grafana: ประวัติความเป็นมาของภาพใหญ่

ในบล็อกสำหรับแต่ละหน้า เราต้องระบุชื่อหน้า (ซึ่งจะถูกแปลงเป็นสลักที่สามารถเข้าถึงหน้านี้ได้) ชื่อของส่วนประกอบที่รับผิดชอบในการทำงานของหน้านี้ (รายการส่วนประกอบจะถูกส่งออกไปยัง module.ts) ข้อบ่งชี้บทบาทของผู้ใช้ที่สามารถทำงานกับหน้านี้ได้ และการตั้งค่าการนำทางสำหรับแถบด้านข้าง

ในคอมโพเนนต์ที่รับผิดชอบการทำงานของเพจ เราต้องตั้งค่า templateUrl โดยส่งพาธไปยังไฟล์ HTML ที่มีมาร์กอัป ภายในตัวควบคุม เราสามารถเข้าถึงบริการ Angular ที่สำคัญสองบริการได้ผ่านการฉีดการอ้างอิง:

  • backendSrv เป็นบริการที่ให้การโต้ตอบกับเซิร์ฟเวอร์ Grafana API
  • datasourceSrv เป็นบริการที่ให้การโต้ตอบภายในเครื่องกับแหล่งข้อมูลทั้งหมดที่ติดตั้งใน Grafana ของคุณ (ตัวอย่างเช่น วิธี .getAll() จะส่งคืนรายการแหล่งข้อมูลที่ติดตั้งทั้งหมด; .get( ) — ส่งคืนวัตถุอินสแตนซ์ของแหล่งข้อมูลที่ระบุ

การพัฒนาปลั๊กอินสำหรับ Grafana: ประวัติความเป็นมาของภาพใหญ่

การพัฒนาปลั๊กอินสำหรับ Grafana: ประวัติความเป็นมาของภาพใหญ่

การพัฒนาปลั๊กอินสำหรับ Grafana: ประวัติความเป็นมาของภาพใหญ่

ส่วนที่ 4: แหล่งข้อมูล

จากมุมมองของ Grafana แหล่งข้อมูลก็คือปลั๊กอินเช่นเดียวกับปลั๊กอินอื่นๆ ทั่วไป คือมีจุดเข้าใช้งานของตัวเองคือ module.js และไฟล์ plugin.json ที่มีเมตาดาต้า เมื่อพัฒนาปลั๊กอินที่มีประเภท = app เราสามารถโต้ตอบกับแหล่งข้อมูลที่มีอยู่ (เช่น prometheus-datasource) หรือแหล่งข้อมูลของเราเอง ซึ่งเราสามารถจัดเก็บโดยตรงในไดเรกทอรีปลั๊กอิน (dist/datasource/*) หรือติดตั้งเป็น dependency ก็ได้ ในกรณีของเรา แหล่งข้อมูลจะรวมอยู่กับโค้ดปลั๊กอิน นอกจากนี้ สิ่งที่จำเป็นต้องมีคือเทมเพลต config.html และตัวควบคุม ConfigCtrl ซึ่งจะใช้สำหรับหน้าการกำหนดค่าอินสแตนซ์ของแหล่งข้อมูล และตัวควบคุมแหล่งข้อมูล ซึ่งจะนำตรรกะไปใช้กับแหล่งข้อมูลของคุณ

ในปลั๊กอิน KubeGraf จากมุมมองของอินเทอร์เฟซผู้ใช้ แหล่งข้อมูลคืออินสแตนซ์ของคลัสเตอร์ Kubernetes ที่ใช้ความสามารถต่อไปนี้ (มีโค้ดต้นฉบับ) ลิงค์):

  • การดึงข้อมูลจากเซิร์ฟเวอร์ api ของ k8s (รับรายชื่อเนมสเปซ การปรับใช้ ฯลฯ)
  • การร้องขอพร็อกซีไปยัง prometheus-datasource (ซึ่งเลือกไว้ในการตั้งค่าปลั๊กอินสำหรับแต่ละคลัสเตอร์เฉพาะ) และการจัดรูปแบบการตอบกลับเพื่อใช้ข้อมูลในทั้งหน้าคงที่และแดชบอร์ด
  • การอัปเดตข้อมูลบนหน้าคงที่ของปลั๊กอิน (ด้วยอัตราการรีเฟรชที่กำหนด)
  • การประมวลผลแบบสอบถามเพื่อสร้างแผ่นเทมเพลตใน grafana-dashboards (วิธี .metriFindQuery())

การพัฒนาปลั๊กอินสำหรับ Grafana: ประวัติความเป็นมาของภาพใหญ่

การพัฒนาปลั๊กอินสำหรับ Grafana: ประวัติความเป็นมาของภาพใหญ่

การพัฒนาปลั๊กอินสำหรับ Grafana: ประวัติความเป็นมาของภาพใหญ่

  • ทดสอบการเชื่อมต่อกับคลัสเตอร์ k8s สุดท้าย
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"};
       })
}

ในความเห็นของเรา สิ่งที่น่าสนใจเป็นพิเศษอย่างหนึ่งคือการใช้งานกลไกการตรวจสอบสิทธิ์และการอนุญาตสำหรับแหล่งข้อมูล โดยทั่วไปแล้ว เราสามารถใช้ส่วนประกอบ datasourceHttpSettings ในตัวของ Grafana เพื่อกำหนดค่าการเข้าถึงแหล่งข้อมูลขั้นสุดท้ายได้ทันที ด้วยส่วนประกอบนี้ เราสามารถกำหนดค่าการเข้าถึงแหล่งข้อมูล HTTP ได้โดยการระบุ URL และการตั้งค่าการตรวจสอบสิทธิ์/การอนุญาตพื้นฐาน ได้แก่ ล็อกอิน/รหัสผ่าน หรือ client-cert/client-key การใช้งานความสามารถในการกำหนดค่าการเข้าถึงโดยใช้โทเค็นผู้ถือ (มาตรฐานโดยพฤตินัยสำหรับ k8s) จำเป็นต้องมีการปรับแต่งเล็กน้อย

เพื่อแก้ไขปัญหานี้ คุณสามารถใช้กลไก "Plugin Routes" ในตัวของ Grafana ได้ (รายละเอียดเพิ่มเติมเกี่ยวกับ หน้าเอกสารอย่างเป็นทางการ) ในการตั้งค่าแหล่งข้อมูลของเรา เราสามารถประกาศชุดกฎการกำหนดเส้นทางที่จะถูกประมวลผลโดยเซิร์ฟเวอร์พร็อกซี grafana ตัวอย่างเช่น สำหรับแต่ละจุดสิ้นสุด จะมีตัวเลือกในการตั้งค่าส่วนหัวหรือ URL พร้อมการรองรับเทมเพลต ซึ่งข้อมูลสามารถนำมาจากฟิลด์ jsonData และ secureJsonData (สำหรับการจัดเก็บรหัสผ่านหรือโทเค็นในรูปแบบที่เข้ารหัส) ในตัวอย่างของเรา คำขอของแบบฟอร์ม /__proxy/api/v1/เนมสเปซ จะถูกพร็อกซีไปยัง URL ประเภทต่อไปนี้
/api/v1/namespaces ที่มีการอนุญาต: ชุดส่วนหัวของ Bearer

การพัฒนาปลั๊กอินสำหรับ Grafana: ประวัติความเป็นมาของภาพใหญ่

การพัฒนาปลั๊กอินสำหรับ Grafana: ประวัติความเป็นมาของภาพใหญ่

โดยธรรมชาติแล้ว ในการทำงานกับเซิร์ฟเวอร์ API ของ K8S เราจำเป็นต้องมีผู้ใช้ที่มีสิทธิ์เข้าถึงแบบอ่านอย่างเดียว ซึ่งคุณสามารถดูรายการสำหรับการสร้างได้ใน ซอร์สโค้ดปลั๊กอิน.

ส่วนที่ 5: การปล่อยตัว

การพัฒนาปลั๊กอินสำหรับ Grafana: ประวัติความเป็นมาของภาพใหญ่

เมื่อคุณเขียนปลั๊กอิน Grafana ของตัวเองแล้ว คุณคงอยากจะทำให้มันเป็นโอเพนซอร์สอยู่แล้ว ใน Grafana นี่คือไลบรารีปลั๊กอิน พร้อมใช้งานที่ grafana.com/grafana/ปลั๊กอิน

เพื่อให้ปลั๊กอินของคุณพร้อมใช้งานในร้านค้าอย่างเป็นทางการ คุณต้องสร้าง PR ใน พื้นที่เก็บข้อมูลนี้เพิ่มเนื้อหาเช่นนี้ลงในไฟล์ repo.json:

การพัฒนาปลั๊กอินสำหรับ Grafana: ประวัติความเป็นมาของภาพใหญ่

โดยที่ version คือเวอร์ชันของปลั๊กอินของคุณ url คือลิงก์ไปยังที่เก็บข้อมูล และ commit คือแฮชของการ commit ที่จะทำให้เวอร์ชันเฉพาะของปลั๊กอินพร้อมใช้งาน

และเมื่อแสดงผลออกมาจะเห็นภาพที่สวยงามดังนี้:

การพัฒนาปลั๊กอินสำหรับ Grafana: ประวัติความเป็นมาของภาพใหญ่

ข้อมูลจะถูกดึงโดยอัตโนมัติจากไฟล์ Readme.md, Changelog.md และไฟล์ plugin.json พร้อมคำอธิบายปลั๊กอิน

ตอนที่ 6: แทนข้อสรุป

เรายังคงพัฒนาปลั๊กอินของเราอย่างต่อเนื่องนับตั้งแต่เปิดตัว ขณะนี้เรากำลังดำเนินการตรวจสอบการใช้งานทรัพยากรโหนดคลัสเตอร์อย่างเหมาะสม การนำฟีเจอร์ใหม่ๆ มาใช้เพื่อปรับปรุงประสบการณ์ผู้ใช้ และพิจารณาความคิดเห็นจำนวนมากที่เราได้รับจากทั้งลูกค้าและผู้ใช้บน GitHub หลังจากติดตั้งปลั๊กอิน (หากคุณทิ้งปัญหาหรือคำขอ Pull Request ไว้ ผมจะยินดีเป็นอย่างยิ่ง :))

เราหวังว่าบทความนี้จะช่วยให้คุณเข้าใจเครื่องมืออันยอดเยี่ยมอย่าง Grafana และอาจช่วยให้คุณเขียนปลั๊กอินของคุณเองได้

ขอบคุณ!)

ที่มา: will.com

ซื้อโฮสติ้งที่เชื่อถือได้สำหรับไซต์ที่มีการป้องกัน DDoS เซิร์ฟเวอร์ VPS VDS 🔥 ซื้อบริการเว็บโฮสติ้งที่เชื่อถือได้ พร้อมระบบป้องกัน DDoS และเซิร์ฟเวอร์ VPS/VDS | ProHoster