<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rafael Carvalhedo</title>
    <description>The latest articles on DEV Community by Rafael Carvalhedo (@rafaelcarvalhedosousa).</description>
    <link>https://dev.to/rafaelcarvalhedosousa</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F652668%2Fd73f7afd-622a-48e1-8aa8-74682f12cbdb.jpeg</url>
      <title>DEV Community: Rafael Carvalhedo</title>
      <link>https://dev.to/rafaelcarvalhedosousa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rafaelcarvalhedosousa"/>
    <language>en</language>
    <item>
      <title>Escalando sua aplicação utilizando K8S e Prometheus</title>
      <dc:creator>Rafael Carvalhedo</dc:creator>
      <pubDate>Fri, 16 Jul 2021 00:34:32 +0000</pubDate>
      <link>https://dev.to/rafaelcarvalhedosousa/escalando-sua-aplicacao-utilizando-k8s-e-prometheus-3oia</link>
      <guid>https://dev.to/rafaelcarvalhedosousa/escalando-sua-aplicacao-utilizando-k8s-e-prometheus-3oia</guid>
      <description>&lt;p&gt;Hoje em dia é comum termos a necessidade de trabalhar com várias instâncias de um serviço para atender cargas de trabalho que em determinados momentos uma única pode não ser o suficiente.&lt;/p&gt;

&lt;p&gt;O Kubernetes possui o componente HorizontalPodAutoscaler(HPA) que nos permite de forma automática controlar a quantidade de replicas do serviço baseado em métricas, ou seja permite definir o momento em que deve ser adicionado replicas ao seu "pool" de instâncias do seu serviço, evitando assim desperdício de recurso que seria o caso de um gerência estática.&lt;/p&gt;

&lt;h4&gt;
  
  
  E como podemos escalar baseado em métricas de aplicação?
&lt;/h4&gt;

&lt;p&gt;Por padrão só conseguimos utilizar o HPA com métricas de CPU ou memoria, porém com o Prometheus podemos obter métricas da aplicação que por sua vez serão enviadas para a API Kubernetes.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que iremos utilizar?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://helm.sh/docs/intro/install/"&gt;Helm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack"&gt;Prometheus Stack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kubernetes-sigs/prometheus-adapter"&gt;Prometheus Operator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Para seguir artigo será necessário ter instalado o &lt;a href="https://helm.sh/docs/intro/install/"&gt;Helm&lt;/a&gt; e o nosso cluster que sugiro utilizar opções como &lt;a href="https://kind.sigs.k8s.io/docs/user/quick-start/"&gt;Kind&lt;/a&gt;, &lt;a href="https://minikube.sigs.k8s.io/docs/start/"&gt;Minikube&lt;/a&gt; e afin.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Instalação Prometheus Stack e Adapter
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Prometheus Stack
&lt;/h3&gt;

&lt;p&gt;Este é uma coleção de documentos para configuração do seu Prometheus para o Kubernetes, além de já instalar o Grafana que também sera utilizado aqui.&lt;/p&gt;

&lt;h4&gt;
  
  
  Primeiramente vamos criar uma namespace para nossos serviços de monitoramento
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl create namespace monitoring
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  E em seguida já podemos instalar o Prometheus Stack através do Helm
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install prometheus prometheus-community/kube-prometheus-stack -n monitoring  --set grafana.service.type=NodePort --set prometheus.service.type=NodePort
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Pode ser observado que foi adicionado argumentos definindo os tipos de serviço como NodePort tendo em vista facilitar nosso acesso as interfaces fora do cluster, porém em um ambiente de produção o recomendado é utilizar &lt;a href="https://kubernetes.io/docs/concepts/services-networking/ingress/"&gt;Ingress&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Apos a execução dos comandos é esperado esse resultado ao listar nossos deployments&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~$ kubectl get deployments -n monitoring
NAME                                  READY   UP-TO-DATE   AVAILABLE   AGE
prometheus-grafana                    1/1     1            1           19h
prometheus-kube-prometheus-operator   1/1     1            1           19h
prometheus-kube-state-metrics         1/1     1            1           19h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Prometheus Adapter
&lt;/h3&gt;

&lt;p&gt;Esse é o resposável por ser conectar ao nosso Prometheus e obter as metricas coletadas pelo mesmo e envia-las para a API Metricas do Kubernetes disponibilizando o uso das mesmas no nosso &lt;a href="https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/"&gt;HPA&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Crie o arquivo &lt;code&gt;customValues.yaml&lt;/code&gt;, pois nele iremos configurar a url para nosso prometheus e configuração adicional para obter métricas requisições por segundo que iremos utilizar logo mais a frente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;prometheus:
  url: "http://prometheus-kube-prometheus-prometheus"
rules:
  custom:
  - seriesQuery: '{container!="POD",namespace!="",pod!=""}'
    resources:
      template: &amp;lt;&amp;lt;.Resource&amp;gt;&amp;gt;
    name:
      matches: "^(.*)_seconds_count"
      as: "${1}_per_second"
    metricsQuery: (sum(rate(&amp;lt;&amp;lt;.Series&amp;gt;&amp;gt;{&amp;lt;&amp;lt;.LabelMatchers&amp;gt;&amp;gt;}[1m])) by (&amp;lt;&amp;lt;.GroupBy&amp;gt;&amp;gt;))

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;_A url do prometheus definida é baseada no &lt;a href="https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/"&gt;DNS interno do serviço&lt;/a&gt; visto que o mesmo foi também na namespace monitoring _&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm install prometheus-adapter prometheus-community/prometheus-adapter -n monitoring -f customValues.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Instalando nossa aplicação no cluster
&lt;/h3&gt;

&lt;p&gt;Para este exemplo utilizei de uma aplicação SpringBoot+Kotlin que está disponível em &lt;a href="https://github.com/rafaelcarvalhedo/spring-auto-scaling-k8/tree/master"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Toda a especificação do chart dessa aplicação se encontra em /chart, que segue a seguinte estrutura:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chart/  
├── Chart.yaml
├── templates
│&amp;nbsp;&amp;nbsp; ├── deployment.yaml
│&amp;nbsp;&amp;nbsp; ├── _helpers.tpl
│&amp;nbsp;&amp;nbsp; ├── hpa.yaml
│&amp;nbsp;&amp;nbsp; ├── ingress.yaml
│&amp;nbsp;&amp;nbsp; ├── NOTES.txt
│&amp;nbsp;&amp;nbsp; ├── serviceaccount.yaml
│&amp;nbsp;&amp;nbsp; ├── servicemonitor.yaml
│&amp;nbsp;&amp;nbsp; └── service.yaml
└── values.yaml

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dentre os yaml's acima o &lt;code&gt;servicemonitor.yaml&lt;/code&gt; é responsável por definir a captura de metricas do serviço, que no nosso caso é no path &lt;code&gt;/actuator/prometheus&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Gerando imagem aplicação
&lt;/h4&gt;

&lt;p&gt;Para gerar a imagem da aplicação iremos usar o seguinte comando gradle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gradle bootBuildImage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Após isso já teremos disponível em docker local a imagem &lt;code&gt;spring-auto-scaling:0.0.1&lt;/code&gt;, feito isso poderemos agora intalar nosso chart no cluster.&lt;/p&gt;

&lt;h4&gt;
  
  
  Instalando via Helm
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm install article chart/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Verificando estado atual do HPA
&lt;/h3&gt;

&lt;p&gt;Podemos fazer isso com kubectl:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~$ kubectl get hpa 
NAME                          REFERENCE                                TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
article-spring-auto-scaling   Deployment/article-spring-auto-scaling   418m/1    1         5         1          65m

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A Coluna TARGETS representa a métrica alvo, onde temos 418m(O K8's utiliza 'm' para unidades fracionarias da métrica que nesse caso seria 0,4/1) de 1 como media entre as quantidade de replicas que também se encontra em 1. A carga atual se deve ao fato de termos o Prometheus obtendo as métricas do nosso serviço através do ServiceMonitor.&lt;/p&gt;

&lt;h3&gt;
  
  
  Incrementando carga
&lt;/h3&gt;

&lt;p&gt;Iremos executar um pod com busybox para fazer chamadas á nossa aplicação em loop, irá tentar gerando uma carga de 10 requisições por segundo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl run -i --tty load-generator --rm --image=busybox --restart=Never -- /bin/sh -c "while sleep 0.1; do wget -q -O- http://article-spring-auto-scaling/users/latest; done"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Devemos levar em conta o tempo de resposta da aplicação, pois as chamadas são sequencias e não paralelas, porém já é o suficiente para vermos funcionar.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Eventos HPA
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl describe hpa  article-spring-auto-scaling
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nsdkfXyC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hxb7tcm015s0mace4m9q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nsdkfXyC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hxb7tcm015s0mace4m9q.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como podemos para que para tentar atingir a media máxima de 1 req/s enviou eventos para aumentar o numero replicas para nosso deployment e chegou ao número de 4 replicas sendo 5 o número máximo de replicas permitidas.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Uma excelente boa prática é definição de valores limites, pois não queremos que um serviço escale infinitamente dentro nosso cluster.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Podemos ver que o escalonamento de automático de aplicações é grande aliado, juntamente com a possibilidade de usar métricas customizadas que podem estar bem alinhadas a necessidade do negócio.As configurações e definições de escalonamento também devem ser constantemente monitoradas e refinidas, pois os requisitos sempre mudam e afinal não existe bala de prata.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>braziliandevs</category>
    </item>
  </channel>
</rss>
