Desenvolvimento de plugins para Grafana: a história dos cones completos

Olá pessoal! Há alguns meses, lançamos nosso novo projeto de código aberto, o plugin Grafana para monitorar kubernetes, chamado DevOpsProdigy KubeGraf, em produção . O código fonte do plug-in está disponível no repositório público no GitHub . E neste artigo, queremos compartilhar com você uma história sobre como criamos o plug-in, quais ferramentas usamos e quais armadilhas encontramos durante o processo de desenvolvimento. Vamos lá!

Parte 0 - introdutória: como chegamos a isso?


A idéia de escrever nosso próprio plugin para o Grafan nasceu por acaso. Nossa empresa monitora projetos web de vários níveis de complexidade há mais de 10 anos. Durante esse período, adquirimos muita experiência, casos interessantes e experiência no uso de vários sistemas de monitoramento. E, em algum momento, nos perguntamos: “Existe uma ferramenta mágica para monitorar o Kubernetes, de modo que, como se costuma dizer,“ defina e esqueça ””? E como soluções prontas para essa pilha, há um grande conjunto de vários tipos de ferramentas: prometheus-operator, conjunto de painéis kubernetes-mixin, grafana-kubernetes-app.

O plugin grafana-kubernetes-app parecia ser a opção mais interessante para nós, mas não é suportado há mais de um ano e, além disso, não sabe como trabalhar com novas versões das métricas de exportador de nó e de estado do kube. E, em algum momento, decidimos: "Mas não tomamos nossa própria decisão?"

Que ideias decidimos implementar em nosso plugin:

  • visualização do "mapa de aplicativos": apresentação conveniente de aplicativos no cluster, agrupados por namespace, implantação ...;
  • visualização de conexões no formato "implantação - serviço (+ portas)".
  • visualização da distribuição de aplicativos de cluster por acenos de cluster.
  • coletando métricas e informações de várias fontes: Prometheus e k8s api server.
  • monitoramento da parte da infraestrutura (uso de tempo do processador, memória, subsistema de disco, rede) e lógica do aplicativo - pods de status de integridade, número de réplicas disponíveis, informações sobre a passagem de amostras de prontidão / prontidão.

Parte 1: O que é o Grafana Plugin?


Do ponto de vista técnico, o plug-in do Grafana é um controlador angular, armazenado no diretório de dados do Grafana ( /var/grafana/plugins/<your_plugin_name>/dist/module.js ) e pode ser carregado como um módulo SystemJS. Também neste diretório deve haver um arquivo plugin.json contendo todas as metainformações sobre o seu plug-in: nome, versão, tipo de plug-in, links para o repositório / site / licença, dependências e assim por diante.


module.ts


plugin.json

Como você pode ver na captura de tela, especificamos plugin.type = app. Para plugins para Grafana pode ser de três tipos:

painel : o tipo mais comum de plug-in - é um painel para visualizar qualquer métrica, é usado para criar vários painéis.
fonte de dados : conector de plug-in para qualquer fonte de dados (por exemplo, fonte de dados Prometheus, fonte de dados ClickHouse, fonte de dados ElasticSearch).
app : um plug-in que permite criar seu próprio aplicativo front-end dentro do Grafana, criar suas próprias páginas html e acessar manualmente a fonte de dados para visualizar vários dados. Além disso, plugins de outros tipos (fonte de dados, painel) e vários painéis podem ser usados ​​como dependências.


Um exemplo de dependências de plug-in com type = app .

Como linguagem de programação, você pode usar JavaScript e TypeScript (optamos por isso). Você pode encontrar os espaços em branco para plug-ins hello-world de qualquer tipo aqui : neste repositório, há um grande número de pacotes iniciais (há até um exemplo experimental de um plug-in no React) com construtores pré-instalados e configurados.

Parte 2: preparando seu ambiente local


Para trabalhar no plug-in, precisamos naturalmente de um cluster do kubernetes com todas as ferramentas pré-instaladas: prometheus, exportador de nós, métricas do estado do cubo, grafana. O ambiente deve ser configurado de maneira rápida, fácil e natural e, para fornecer dados de recarga a quente, o diretório Grafana deve ser montado diretamente da máquina do desenvolvedor.

A maneira mais conveniente, em nossa opinião, de trabalhar localmente com o kubernetes é o minikube . O próximo passo é estabelecer o pacote Prometheus + Grafana usando o operador prometheus. Este artigo detalha o processo de instalação do prometheus-operator no minikube. Para ativar a persistência, você deve configurar o parâmetro persistence: true no arquivo charts / grafana / values.yaml, adicione seu próprio PV e PVC e especifique-os no parâmetro persistence.existingClaim

O script final de lançamento do minikube é assim:

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 

Parte 3: desenvolvimento em si


Modelo de objeto

Na preparação para a implementação do plug-in, decidimos descrever todas as entidades básicas do Kubernetes com as quais trabalharemos como classes TypeScript: pod, implantação, daemonset, statefulset, job, cronjob, serviço, nó e namespace. Cada uma dessas classes herda da classe BaseModel comum, que descreve os métodos construtor, destruidor, para atualizar e alternar a visibilidade. Cada uma das classes descreve relacionamentos aninhados com outras entidades, por exemplo, uma lista de pods para uma entidade do tipo implantação.

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

Usando getters e setters, podemos exibir ou definir as métricas de entidades que precisamos de uma maneira conveniente e legível. Por exemplo, a saída formatada da CPU alocável concorda:

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

Páginas

Uma lista de todas as páginas do nosso plug-in é descrita inicialmente em pluing.json na seção de dependência:



No bloco de cada página, devemos indicar o TÍTULO DA PÁGINA (será então convertido em slug, pelo qual esta página estará disponível); nome do componente responsável pela operação desta página (a lista de componentes é exportada para module.ts); especificando a função do usuário para quem o acesso a esta página está disponível e configurações de navegação para a barra lateral

No componente responsável pela operação da página, devemos instalar o templateUrl, passando lá o caminho para o arquivo html com marcação. Dentro do controlador, através da injeção de dependência, podemos acessar até 2 serviços angulares importantes:

  • backendSrv - um serviço que fornece interação com o grafana api-server;
  • datasourceSrv - um serviço que fornece interação local com todas as fontes de dados instaladas no seu Grafana (por exemplo, o método .getAll () - retorna uma lista de todas as fontes de dados instaladas'ov; .get (<name>) - retorna um objeto de instância de uma fonte de dados específica.







Parte 4: fonte de dados


Do ponto de vista do Grafana, a fonte de dados é exatamente o mesmo plug-in que todos os outros: possui seu próprio ponto de entrada module.js, existe um arquivo com a meta-informação plugin.json. Ao desenvolver um plug-in com type = app, podemos interagir com a fonte de dados existente (por exemplo, prometheus-datasource) e também com a nossa, que podemos armazenar diretamente no diretório do plugin (dist / datasource / *) ou definir como uma dependência. No nosso caso, a fonte de dados vem com o código do plugin. Também é necessário ter o modelo config.html e o controlador ConfigCtrl que serão usados ​​para a página de configuração da instância da fonte de dados e o controlador da fonte de dados, que implementa a lógica da fonte de dados.

No plug-in KubeGraf, do ponto de vista da interface do usuário, a fonte de dados é uma instância do cluster kubernetes na qual os seguintes recursos são implementados (o código-fonte está disponível por referência ):

  • coleta de dados do k8s api-server (obtendo uma lista do namespace'ov, deployment'ov ...)
  • solicitações de proxy em fonte de dados prometheus (que é selecionada nas configurações do plug-in para cada cluster específico) e formatação de respostas para o uso de dados em páginas estáticas e painéis.
  • atualização de dados em páginas estáticas do plug-in (com a taxa de atualização definida).
  • Processando Solicitações para Gerar uma Lista de Modelos em Grafana-Dashboards (Método .metriFindQuery ())







  • teste a conexão com o cluster k8s final.


 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"}; }) } 

Um ponto interessante separado, em nossa opinião, é a implementação do mecanismo de autenticação e autorização para a fonte de dados. Como regra, pronto para configurar o acesso à fonte de dados final, podemos usar o componente Grafana interno - datasourceHttpSettings. Usando esse componente, podemos configurar o acesso à fonte de dados http, especificando as configurações básicas de autenticação e autorização de URL e URL: senha de login ou certificado de cliente / chave de cliente. Para perceber a capacidade de configurar o acesso usando um token de portador (de fato o padrão para k8s), tive que fazer um pouco de "produto químico".

Para resolver esse problema, você pode usar o mecanismo “Rotas de plug-in” incorporado da Grafana (mais na página da documentação oficial ). Nas configurações de nossa fonte de dados, podemos declarar um conjunto de regras de roteamento que serão processadas pelo servidor proxy grafana. Por exemplo, para cada terminal individual, existe a possibilidade de afixar cabeçalhos ou URLs com a capacidade de modelar, dados para os quais podem ser obtidos os campos jsonData e secureJsonData (para armazenar senhas ou tokens no formato criptografado). Em nosso exemplo, solicitações do formulário / __ proxy / api / v1 / namespaces serão enviadas por proxy para o URL do formulário
<your_k8s_api_url> / api / v1 / namespaces com o cabeçalho Authorization: Bearer.





Naturalmente, para trabalhar com o servidor api do k8s, precisamos de um usuário com acesso somente leitura, o manifesto para a criação que você também pode encontrar no código-fonte do plug-in .

Parte 5: liberação




Depois de escrever seu próprio plugin para o Grafana, você naturalmente desejará colocá-lo em domínio público. Grafana é uma biblioteca de plugins disponível em grafana.com/grafana/plugins

Para que seu plug-in esteja disponível na loja oficial, você precisa fazer PR neste repositório adicionando o seguinte conteúdo ao arquivo repo.json:



onde version é a versão do seu plugin, url é um link para o repositório e commit é um hash do commit, pelo qual uma versão específica do plugin estará disponível.

E na saída, você verá uma imagem maravilhosa do formulário:



Os dados serão coletados automaticamente do arquivo Leiame.md, Changelog.md e plugin.json com a descrição do plugin.

Parte 6: em vez de conclusões


Não paramos de desenvolver nosso plugin após o lançamento. E agora estamos trabalhando no monitoramento correto do uso dos recursos dos nós do cluster, na introdução de novos recursos para aumentar o UX, além de obter uma grande quantidade de feedback recebido após a instalação do plug-in pelos nossos clientes e do ishui no github (se você deixar seu problema ou solicitação de pull, eu Ficarei muito feliz :-)).

Esperamos que este artigo o ajude a entender uma ferramenta tão boa como o Grafana e, possivelmente, escrever seu próprio plugin.

Obrigado!)

Source: https://habr.com/ru/post/pt474500/


All Articles