์๋
ํ์ธ์ ์ฌ๋ฌ๋ถ! ๋ช ๋ฌ ์ , ์ฐ๋ฆฌ๋ ์๋ก์ด ์คํ ์์ค ํ๋ก์ ํธ์ธ Kubernetes ๋ชจ๋ํฐ๋ง์ฉ Grafana ํ๋ฌ๊ทธ์ธ์ ํ๋ก๋์
์ ์ถ์ํ์ต๋๋ค.
ํํธ 0 - ์ ๋ฌธ: ์ด๋ป๊ฒ ์ด ์ง์ ์ ๋๋ฌํ๋์?
Grafan์ฉ ํ๋ฌ๊ทธ์ธ์ ์์ฒด์ ์ผ๋ก ์์ฑํ๋ ค๋ ์์ด๋์ด๋ ์ฐ์ฐํ ๋ ์ค๋ฅธ ๊ฒ์ ๋๋ค. ์ฐ๋ฆฌ ํ์ฌ๋ 10๋ ๋๊ฒ ๋ค์ํ ์์ค์ ๋ณต์ก์ฑ์ ์ง๋ ์น ํ๋ก์ ํธ๋ฅผ ๋ชจ๋ํฐ๋งํด ์์ต๋๋ค. ๊ทธ ๋์ ์ฐ๋ฆฌ๋ ๋ค์ํ ๋ชจ๋ํฐ๋ง ์์คํ ์ ํ์ฉํ๋ฉด์ ๋ง์ ์ ๋ฌธ์ง์๊ณผ ํฅ๋ฏธ๋ก์ด ์ฌ๋ก, ๊ฒฝํ์ ์ถ์ ํด์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด๋ ์์ ์์ ์ฐ๋ฆฌ๋ ์ค์ค๋ก์๊ฒ ์ด๋ ๊ฒ ๋ฌผ์์ต๋๋ค. "Kubernetes๋ฅผ ๋ชจ๋ํฐ๋งํ์ฌ "์ค์ ํ๊ณ ์์ด๋ฒ๋ฆฌ๋๋ก" ํ๋ ๋ง๋ฒ์ ๋๊ตฌ๊ฐ ์์ต๋๊น?". ๋ฌผ๋ก k8s ๋ชจ๋ํฐ๋ง์ ์ํ ์ ๊ณ ํ์ค์ ์ค๋ซ๋์ ํ๋ก๋ฉํ ์ฐ์ค + ๊ทธ๋ผํ๋ ์กฐํฉ. ๊ทธ๋ฆฌ๊ณ ์ด ์คํ์ ์ํ ๊ธฐ์ฑ ์๋ฃจ์ ์ผ๋ก prometheus-operator, kubernetes-mixin ๋์๋ณด๋ ์ธํธ, grafana-kubernetes-app ๋ฑ ๋ค์ํ ์ข ๋ฅ์ ๋๊ตฌ ์ธํธ๊ฐ ์์ต๋๋ค.
grafana-kubernetes-app ํ๋ฌ๊ทธ์ธ์ ์ฐ๋ฆฌ์๊ฒ ๊ฐ์ฅ ํฅ๋ฏธ๋ก์ด ์ต์ ์ธ ๊ฒ ๊ฐ์์ง๋ง XNUMX๋ ๋๊ฒ ์ง์๋์ง ์์์ผ๋ฉฐ ๊ฒ๋ค๊ฐ ์ ๋ฒ์ ์ node-exporter ๋ฐ kube-state-metrics์๋ ์๋ํ ์ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด๋ ์๊ฐ ์ฐ๋ฆฌ๋ โ์ฐ๋ฆฌ ์ค์ค๋ก ๊ฒฐ์ ์ ๋ด๋ ค์ผ ํ์ง ์์๊น?โ๋ผ๊ณ ๊ฒฐ์ ํ์ต๋๋ค.
ํ๋ฌ๊ทธ์ธ์ ๊ตฌํํ๊ธฐ๋ก ๊ฒฐ์ ํ ์์ด๋์ด๋ ๋ฌด์์ ๋๊น?
- "์ ํ๋ฆฌ์ผ์ด์ ๋งต" ์๊ฐํ: ํด๋ฌ์คํฐ ๋ด ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ค์์คํ์ด์ค, ๋ฐฐํฌ๋ณ๋ก ๊ทธ๋ฃนํํ์ฌ ํธ๋ฆฌํ๊ฒ ํ์ํฉ๋๋ค.
- "๋ฐฐํฌ - ์๋น์ค(+ํฌํธ)"์ ๊ฐ์ ์ฐ๊ฒฐ ์๊ฐํ.
- ํด๋ฌ์คํฐ ๋ ธ๋ ์ ์ฒด์ ํด๋ฌ์คํฐ ์ ํ๋ฆฌ์ผ์ด์ ๋ฐฐํฌ๋ฅผ ์๊ฐํํฉ๋๋ค.
- Prometheus ๋ฐ k8s API ์๋ฒ์ ๊ฐ์ ์ฌ๋ฌ ์์ค์์ ์ธก์ ํญ๋ชฉ ๋ฐ ์ ๋ณด๋ฅผ ์์งํฉ๋๋ค.
- ์ธํ๋ผ ๋ถ๋ถ(CPU ์๊ฐ, ๋ฉ๋ชจ๋ฆฌ, ๋์คํฌ ํ์ ์์คํ , ๋คํธ์ํฌ ์ฌ์ฉ)๊ณผ ์ ํ๋ฆฌ์ผ์ด์ ๋ก์ง(์ํ ํฌ๋, ์ฌ์ฉ ๊ฐ๋ฅํ ๋ณต์ ๋ณธ ์, ํ์ฑ/์ค๋น ํ ์คํธ ํต๊ณผ์ ๋ํ ์ ๋ณด)์ ๋ชจ๋ ๋ชจ๋ํฐ๋งํฉ๋๋ค.
ํํธ 1: "Grafana ํ๋ฌ๊ทธ์ธ"์ด๋ ๋ฌด์์ ๋๊น?
๊ธฐ์ ์ ์ธ ๊ด์ ์์ Grafana์ฉ ํ๋ฌ๊ทธ์ธ์ Grafana ๋ฐ์ดํฐ ๋๋ ํฐ๋ฆฌ(/var/grafana/ํ๋ฌ๊ทธ์ธ/ /dist/module.js) SystemJS ๋ชจ๋๋ก ๋ก๋๋ ์ ์์ต๋๋ค. ๋ํ ์ด ๋๋ ํฐ๋ฆฌ์๋ ํ๋ฌ๊ทธ์ธ์ ๋ํ ๋ชจ๋ ๋ฉํ ์ ๋ณด(์ด๋ฆ, ๋ฒ์ , ํ๋ฌ๊ทธ์ธ ์ ํ, ์ ์ฅ์/์ฌ์ดํธ/๋ผ์ด์ผ์ค ๋งํฌ, ์ข ์์ฑ ๋ฑ)๊ฐ ํฌํจ๋plugin.json ํ์ผ์ด ์์ด์ผ ํฉ๋๋ค.
module.ts
ํ๋ฌ๊ทธ์ธ.json
์คํฌ๋ฆฐ์ท์์ ๋ณผ ์ ์๋ฏ์ด ์ฐ๋ฆฌ๋plugin.type = app์ ์ง์ ํ์ต๋๋ค. Grafana์ฉ ํ๋ฌ๊ทธ์ธ์ ์ธ ๊ฐ์ง ์ ํ์ด ์์ ์ ์์ต๋๋ค.
ํจ๋: ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ์ ํ์ ํ๋ฌ๊ทธ์ธ - ๋ค์ํ ๋์๋ณด๋๋ฅผ ๊ตฌ์ถํ๋ ๋ฐ ์ฌ์ฉ๋๋ ์ธก์ ํญ๋ชฉ์ ์๊ฐํํ๋ ํจ๋์
๋๋ค.
๋ฐ์ดํฐ ์์ค: ์ผ๋ถ ๋ฐ์ดํฐ ์์ค(์: Prometheus-datasource, ClickHouse-datasource, ElasticSearch-datasource)์ ๋ํ ํ๋ฌ๊ทธ์ธ ์ปค๋ฅํฐ์
๋๋ค.
์ฑ: Grafana ๋ด์์ ์์ ๋ง์ ํ๋ฐํธ์๋ ์ ํ๋ฆฌ์ผ์ด์
์ ๊ตฌ์ถํ๊ณ , ์์ ๋ง์ HTML ํ์ด์ง๋ฅผ ๋ง๋ค๊ณ , ๋ฐ์ดํฐ ์์ค์ ์๋์ผ๋ก ์ก์ธ์คํ์ฌ ๋ค์ํ ๋ฐ์ดํฐ๋ฅผ ์๊ฐํํ ์ ์๋ ํ๋ฌ๊ทธ์ธ์
๋๋ค. ๋ํ, ๋ค๋ฅธ ์ ํ(๋ฐ์ดํฐ์์ค, ํจ๋)์ ํ๋ฌ๊ทธ์ธ๊ณผ ๋ค์ํ ๋์๋ณด๋๋ฅผ ์ข
์์ฑ์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
type=app์ธ ํ๋ฌ๊ทธ์ธ ์ข
์์ฑ์ ์.
ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ก JavaScript์ TypeScript๋ฅผ ๋ชจ๋ ์ฌ์ฉํ ์ ์์ต๋๋ค(์ ํฌ๋ ์ด๋ฅผ ์ ํํ์ต๋๋ค). ๊ฐ๋ฅํ ๋ชจ๋ ์ ํ์ hello-world ํ๋ฌ๊ทธ์ธ์ ์ํ ์ค๋น
2๋ถ: ๋ก์ปฌ ํ๊ฒฝ ์ค๋น
ํ๋ฌ๊ทธ์ธ ์์ ์ ์ํด์๋ ๋น์ฐํ prometheus, node-exporter, kube-state-metrics, grafana ๋ฑ ๋ชจ๋ ์ฌ์ ์ค์น๋ ๋๊ตฌ๊ฐ ํฌํจ๋ kubernetes ํด๋ฌ์คํฐ๊ฐ ํ์ํฉ๋๋ค. ํ๊ฒฝ์ ๋น ๋ฅด๊ณ ์ฝ๊ณ ์์ฐ์ค๋ฝ๊ฒ ์ค์ ๋์ด์ผ ํ๋ฉฐ, ํซ ๋ฆฌ๋ก๋๋ฅผ ๋ณด์ฅํ๋ ค๋ฉด Grafana ๋ฐ์ดํฐ ๋๋ ํฐ๋ฆฌ๋ฅผ ๊ฐ๋ฐ์ ์ปดํจํฐ์์ ์ง์ ๋ง์ดํธํด์ผ ํฉ๋๋ค.
์ฐ๋ฆฌ ์๊ฐ์ ์ฟ ๋ฒ๋คํฐ์ค๋ฅผ ๋ก์ปฌ์์ ์์
ํ๋ ๊ฐ์ฅ ํธ๋ฆฌํ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ต์ข 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, ๋ฐฐํฌ, daemonset, statefulset, job, cronjob, ์๋น์ค, ๋ ธ๋, ๋ค์์คํ์ด์ค)์ผ๋ก ์ค๋ช ํ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค. ์ด๋ฌํ ๊ฐ ํด๋์ค๋ ์์ฑ์, ์๋ฉธ์, ๊ฐ์์ฑ์ ์ ๋ฐ์ดํธํ๊ณ ์ ํํ๊ธฐ ์ํ ๋ฉ์๋๋ฅผ ์ค๋ช ํ๋ ๊ณตํต BaseModel ํด๋์ค์์ ์์๋ฉ๋๋ค. ๊ฐ ํด๋์ค๋ ๋ค๋ฅธ ์ํฐํฐ์์ ์ค์ฒฉ ๊ด๊ณ(์: ๋ฐฐํฌ ์ ํ ์ํฐํฐ์ ๋ํ 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 = [];
}
}
getter ๋ฐ setter์ ๋์์ผ๋ก ํ์ํ ์ํฐํฐ ๋ฉํธ๋ฆญ์ ํธ๋ฆฌํ๊ณ ์ฝ๊ธฐ ์ฌ์ด ํ์์ผ๋ก ํ์ํ๊ฑฐ๋ ์ค์ ํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ํ ๋น ๊ฐ๋ฅํ CPU ๋ ธ๋์ ํ์ํ๋ ์ถ๋ ฅ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
get cpuAllocatableFormatted(){
let cpu = this.data.status.allocatable.cpu;
if(cpu.indexOf('m') > -1){
cpu = parseInt(cpu)/1000;
}
return cpu;
}
ํ์ด์ง
๋ชจ๋ ํ๋ฌ๊ทธ์ธ ํ์ด์ง ๋ชฉ๋ก์ ์ฒ์์ ์ข ์์ฑ ์น์ ์ pluing.json์ ์ค๋ช ๋์ด ์์ต๋๋ค.
๊ฐ ํ์ด์ง์ ๋ธ๋ก์๋ ํ์ด์ง ์ด๋ฆ์ ํ์ํด์ผ ํฉ๋๋ค(์ด ํ์ด์ง์ ์ก์ธ์คํ ์ ์๋ ์ฌ๋ฌ๊ทธ๋ก ๋ณํ๋ฉ๋๋ค). ์ด ํ์ด์ง์ ์์
์ ๋ด๋นํ๋ ๊ตฌ์ฑ ์์์ ์ด๋ฆ(๊ตฌ์ฑ ์์ ๋ชฉ๋ก์ module.ts๋ก ๋ด๋ณด๋ด์ง๋๋ค) ์ด ํ์ด์ง ์์
์ด ๊ฐ๋ฅํ ์ฌ์ฉ์ ์ญํ ๊ณผ ์ฌ์ด๋๋ฐ์ ๋ํ ํ์ ์ค์ ์ ๋ํ๋
๋๋ค.
ํ์ด์ง ์์ ์ ๋ด๋นํ๋ ๊ตฌ์ฑ ์์์์ templateUrl์ ์ค์ ํ๊ณ ์ฌ๊ธฐ์ ๋งํฌ์ ์ด ํฌํจ๋ html ํ์ผ ๊ฒฝ๋ก๋ฅผ ์ ๋ฌํด์ผ ํฉ๋๋ค. ์ปจํธ๋กค๋ฌ ๋ด๋ถ์์๋ ์ข ์์ฑ ์ฃผ์ ์ ํตํด ์ต๋ 2๊ฐ์ ์ค์ํ ๊ฐ๋ ์๋น์ค์ ์ก์ธ์คํ ์ ์์ต๋๋ค.
- backendSrv - Grafana API ์๋ฒ์์ ์ํธ ์์ฉ์ ์ ๊ณตํ๋ ์๋น์ค์ ๋๋ค.
- datasourceSrv - Grafana์ ์ค์น๋ ๋ชจ๋ ๋ฐ์ดํฐ ์์ค์์ ๋ก์ปฌ ์ํธ ์์ฉ์ ์ ๊ณตํ๋ ์๋น์ค(์: .getAll() ๋ฉ์๋) - ์ค์น๋ ๋ชจ๋ ๋ฐ์ดํฐ ์์ค ๋ชฉ๋ก์ ๋ฐํํฉ๋๋ค. ) - ํน์ ๋ฐ์ดํฐ ์์ค์ ์ธ์คํด์ค ๊ฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค.
ํํธ 4: ๋ฐ์ดํฐ ์์ค
Grafana์ ๊ด์ ์์ ๋ณด๋ฉด datasource๋ ๋ค๋ฅธ ๋ชจ๋ ํ๋ฌ๊ทธ์ธ๊ณผ ์์ ํ ๋์ผํ ํ๋ฌ๊ทธ์ธ์ ๋๋ค. ์์ฒด ์ง์ ์ module.js๊ฐ ์๊ณ ๋ฉํ ์ ๋ณด๊ฐ ์๋ ํ์ผ์ธplugin.json์ด ์์ต๋๋ค. type = app์ธ ํ๋ฌ๊ทธ์ธ์ ๊ฐ๋ฐํ ๋ ๊ธฐ์กด ๋ฐ์ดํฐ ์์ค(์: prometheus-datasource)์ ์์ฒด ๋ฐ์ดํฐ ์์ค(dist/datasource/*)์ ์ง์ ์ ์ฅํ๊ฑฐ๋ ์ข ์์ฑ์ผ๋ก ์ค์นํ ์ ์๋ ์์ฒด ๋ฐ์ดํฐ ์์ค์ ์ํธ ์์ฉํ ์ ์์ต๋๋ค. ์ฐ๋ฆฌ์ ๊ฒฝ์ฐ ๋ฐ์ดํฐ ์์ค๋ ํ๋ฌ๊ทธ์ธ ์ฝ๋์ ํจ๊ป ์ ๊ณต๋ฉ๋๋ค. ๋ํ ๋ฐ์ดํฐ ์์ค ์ธ์คํด์ค ๊ตฌ์ฑ ํ์ด์ง์ ์ฌ์ฉ๋ config.html ํ ํ๋ฆฟ๊ณผ ConfigCtrl ์ปจํธ๋กค๋ฌ์ ๋ฐ์ดํฐ ์์ค์ ๋ก์ง์ ๊ตฌํํ๋ ๋ฐ์ดํฐ ์์ค ์ปจํธ๋กค๋ฌ๊ฐ ํ์ํฉ๋๋ค.
KubeGraf ํ๋ฌ๊ทธ์ธ์์ ์ฌ์ฉ์ ์ธํฐํ์ด์ค ๊ด์ ์์ ๋ฐ์ดํฐ ์์ค๋ ๋ค์ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ kubernetes ํด๋ฌ์คํฐ์ ์ธ์คํด์ค์
๋๋ค(์์ค ์ฝ๋ ์ฌ์ฉ ๊ฐ๋ฅ).
- k8s API ์๋ฒ์์ ๋ฐ์ดํฐ ์์ง(๋ค์์คํ์ด์ค, ๋ฐฐํฌ ๋ชฉ๋ก ๊ฐ์ ธ์ค๊ธฐ...)
- prometheus-datasource(๊ฐ ํน์ ํด๋ฌ์คํฐ์ ํ๋ฌ๊ทธ์ธ ์ค์ ์์ ์ ํ๋จ)์ ๋ํ ์์ฒญ์ ํ๋ก์ํ๊ณ ์ ์ ํ์ด์ง์ ๋์๋ณด๋ ๋ชจ๋์์ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๋๋ก ์๋ต ํ์์ ์ง์ ํฉ๋๋ค.
- ์ ์ ํ๋ฌ๊ทธ์ธ ํ์ด์ง์์ ๋ฐ์ดํฐ ์ ๋ฐ์ดํธ(์ค์ ๋ ์๋ก๊ณ ์นจ ๋น๋ ์ฌ์ฉ)
- grafana-dashboards์์ ํ ํ๋ฆฟ ์ํธ๋ฅผ ์์ฑํ๊ธฐ ์ํ ์ฟผ๋ฆฌ ์ฒ๋ฆฌ(metriFindQuery() ๋ฉ์๋)
- ์ต์ข 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"};
})
}
์ฐ๋ฆฌ ์๊ฐ์ ๋ ๋ค๋ฅธ ํฅ๋ฏธ๋ก์ด ์ ์ ๋ฐ์ดํฐ ์์ค์ ๋ํ ์ธ์ฆ ๋ฐ ๊ถํ ๋ถ์ฌ ๋ฉ์ปค๋์ฆ์ ๊ตฌํ์ ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ๊ธฐ๋ณธ ์ ๊ณต Grafana ๊ตฌ์ฑ ์์ datasourceHttpSettings๋ฅผ ์ฌ์ฉํ์ฌ ์ต์ข ๋ฐ์ดํฐ ์์ค์ ๋ํ ์ก์ธ์ค๋ฅผ ๊ตฌ์ฑํ ์ ์์ต๋๋ค. ์ด ๊ตฌ์ฑ ์์๋ฅผ ์ฌ์ฉํ๋ฉด URL ๋ฐ ๊ธฐ๋ณธ ์ธ์ฆ/๊ถํ ์ค์ (login-password ๋๋ client-cert/client-key)์ ์ง์ ํ์ฌ http ๋ฐ์ดํฐ ์์ค์ ๋ํ ์ก์ธ์ค๋ฅผ ๊ตฌ์ฑํ ์ ์์ต๋๋ค. ๋ฒ ์ด๋ฌ ํ ํฐ(k8s์ ์ฌ์ค์ ํ์ค)์ ์ฌ์ฉํ์ฌ ์ก์ธ์ค๋ฅผ ๊ตฌ์ฑํ๋ ๊ธฐ๋ฅ์ ๊ตฌํํ๊ธฐ ์ํด ์ฝ๊ฐ์ ์กฐ์ ์ด ํ์ํ์ต๋๋ค.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๋ฉด ๋ด์ฅ๋ Grafana "ํ๋ฌ๊ทธ์ธ ๊ฒฝ๋ก" ๋ฉ์ปค๋์ฆ์ ์ฌ์ฉํ ์ ์์ต๋๋ค(์์ธํ ๋ด์ฉ์ ๋ค์์ ์ฐธ์กฐํ์ธ์).
Authorization: Bearer ํค๋๊ฐ ์๋ /api/v8/namespaces.
๋น์ฐํ k8s API ์๋ฒ๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ์ฝ๊ธฐ ์ ์ฉ ์ก์ธ์ค ๊ถํ์ด ์๋ ์ฌ์ฉ์๊ฐ ํ์ํ๋ฉฐ ์์ฑ์ ์ํ ๋งค๋ํ์คํธ๋ ๋ค์์์ ์ฐพ์ ์ ์์ต๋๋ค.
ํํธ 5: ์ถ์
์์ ๋ง์ Grafana ํ๋ฌ๊ทธ์ธ์ ์์ฑํ๊ณ ๋๋ฉด ์์ฐ์ค๋ฝ๊ฒ ์ด๋ฅผ ๊ณต๊ฐ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๊ฒ ๋ง๋ค๊ณ ์ถ์ ๊ฒ์
๋๋ค. Grafana์์๋ ์ฌ๊ธฐ์์ ์ฌ์ฉํ ์ ์๋ ํ๋ฌ๊ทธ์ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์
๋๋ค.
๊ณต์ ์คํ ์ด์์ ํ๋ฌ๊ทธ์ธ์ ์ฌ์ฉํ๋ ค๋ฉด ๋ค์์์ PR์ ์์ฑํด์ผ ํฉ๋๋ค.
์ฌ๊ธฐ์ version์ ํ๋ฌ๊ทธ์ธ ๋ฒ์ ์ด๊ณ , url์ ์ ์ฅ์์ ๋ํ ๋งํฌ์ด๋ฉฐ, commit์ ํ๋ฌ๊ทธ์ธ์ ํน์ ๋ฒ์ ์ ์ฌ์ฉํ ์ ์๋ ์ปค๋ฐ์ ํด์์
๋๋ค.
์ถ๋ ฅ์์ ๋ค์๊ณผ ๊ฐ์ ๋ฉ์ง ๊ทธ๋ฆผ์ ๋ณผ ์ ์์ต๋๋ค.
์ด์ ๋ํ ๋ฐ์ดํฐ๋ Readme.md, Changelog.md ๋ฐ ํ๋ฌ๊ทธ์ธ ์ค๋ช
๊ณผ ํจ๊ป ํ๋ฌ๊ทธ์ธ.json ํ์ผ์์ ์๋์ผ๋ก ๊ฐ์ ธ์ต๋๋ค.
6๋ถ: ๊ฒฐ๋ก ๋์
์ฐ๋ฆฌ๋ ์ถ์ ํ์๋ ํ๋ฌ๊ทธ์ธ ๊ฐ๋ฐ์ ์ค๋จํ์ง ์์์ต๋๋ค. ์ด์ ์ฐ๋ฆฌ๋ ํด๋ฌ์คํฐ ๋ ธ๋์ ๋ฆฌ์์ค ์ฌ์ฉ์ ์ฌ๋ฐ๋ฅด๊ฒ ๋ชจ๋ํฐ๋งํ๊ณ , UX๋ฅผ ๊ฐ์ ํ๊ธฐ ์ํ ์๋ก์ด ๊ธฐ๋ฅ์ ๋์ ํ๊ณ , ํด๋ผ์ด์ธํธ์ GitHub ์ฌ์ฉ์ ๋ชจ๋๋ก๋ถํฐ ํ๋ฌ๊ทธ์ธ์ ์ค์นํ ํ ๋ฐ์ ๋ง์ ์์ ํผ๋๋ฐฑ์ ์์งํ๊ธฐ ์ํด ๋ ธ๋ ฅํ๊ณ ์์ต๋๋ค. ๊ทํ์ ๋ฌธ์ ๋ ๋์ด์ค๊ธฐ ์์ฒญ์ ๋ณด๋ด์ฃผ์๋ฉด ๋งค์ฐ ๊ธฐ์ ๊ฒ์ ๋๋ค :)
์ด ๊ธฐ์ฌ๊ฐ Grafana์ ๊ฐ์ ํ๋ฅญํ ๋๊ตฌ๋ฅผ ์ดํดํ๊ณ ์๋ง๋ ์์ ๋ง์ ํ๋ฌ๊ทธ์ธ์ ์์ฑํ๋ ๋ฐ ๋์์ด ๋๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
๊ฐ์ฌํฉ๋๋ค!)
์ถ์ฒ : habr.com