Como uso o Terraform e o Helm para implantar o painel Kubernetes
O Terraform pode implantar Helm Charts. É certo para você?
Quando estou trabalhando em projetos que exigem provisionamento de infraestrutura em nuvem, meu fluxo de trabalho tem dois componentes distintos: um é a orquestração da infraestrutura, que inclui o Terraform para trazer a infraestrutura (por exemplo, novos clusters EKS), e o segundo é o componente de provisionamento, que inclui scripts Ansible ou Bash para instanciar e inicializar essa infraestrutura para aceitar novas implantações (por exemplo, instalação do Cluster Autoscaler, kube-state-metrics e assim por diante).
A razão para isso é simples: muito poucas ferramentas podem cruzar e lidar tanto com a orquestração quanto com o lado do provisionamento. Quando me deparei com o provedor Helm para Terraform, queria explorar a possibilidade de usar uma ferramenta para lidar com ambos os lados: usar o Terraform para criar um novo cluster EKS e provisioná-lo com Prometheus, Loki, Grafana, Cluster Autoscaler e outros, tudo em uma implantação organizada e limpa. Mas isso não acontecerá até que eu descubra como usar isso, então abaixo está minha experiência usando Terraform e Helm para algo simples: implantar o painel Kubernetes.
O provedor Helm
O provedor Helm funciona como os outros provedores de nuvem. Você pode especificar o caminho do KUBECONFIG
ou outras credenciais, executar terraform init
e o provedor Helm será inicializado.
Implantando o painel Kubernetes
Vou usar o Minikube para este teste.
Meu arquivo main.tf
contém o seguinte:
provider "helm" {
kubernetes {
config_path = "~/.kube/config"
}
}
resource "helm_release" "my-kubernetes-dashboard" {
name = "my-kubernetes-dashboard"
repository = "https://kubernetes.github.io/dashboard/"
chart = "kubernetes-dashboard"
namespace = "default"
set {
name = "service.type"
value = "LoadBalancer"
}
set {
name = "protocolHttp"
value = "true"
}
set {
name = "service.externalPort"
value = 80
}
set {
name = "replicaCount"
value = 2
}
set {
name = "rbac.clusterReadOnlyRole"
value = "true"
}
}
No Terraform acima, estou implantando o gráfico kubernetes-dashboard
de https://kubernetes.github.io/dashboard/
no namespace default
. Também estou usando a variável set
para substituir os padrões do gráfico:
service.type
: estou mudando paraLoadBalancer
para revisar minhas alterações localmente. Lembre-se de executar ominikube tunnel
em uma janela separada, ou isso não funcionará.protocolHttp
: estou implantando a versão não segura para suprimir avisos HTTPS emlocalhost
.service.externalPort
: precisa ser 80 para não seguro.replicaCount
: estou mudando para 2 para ver se essas mudanças funcionam :)rbac.clusterReadOnlyRole
: deve sertrue
para que o Dashboard tenha as permissões corretas.
Executando nosso Terraform
Vamos começar inicializando o Terraform com terraform init
:
Initializing the backend...
Initializing provider plugins...
- Finding latest version of hashicorp/helm...
- Installing hashicorp/helm v2.2.0...
- Installed hashicorp/helm v2.2.0 (signed by HashiCorp)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
Até agora tudo bem. O Terraform inicializou com êxito o provedor Helm. E agora para terraform apply
:
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# helm_release.my-kubernetes-dashboard will be created
+ resource "helm_release" "my-kubernetes-dashboard" {
+ atomic = false
+ chart = "kubernetes-dashboard"
+ cleanup_on_fail = false
[...]
+ set {
+ name = "service.type"
+ value = "LoadBalancer"
}
}
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
helm_release.my-kubernetes-dashboard: Creating...
helm_release.my-kubernetes-dashboard: Still creating... [10s elapsed]
helm_release.my-kubernetes-dashboard: Creation complete after 14s [id=my-kubernetes-dashboard]
(Lembre-se de executar o minikube tunnel
em outra janela do terminal, caso contrário o apply
não funcionará).
Verificando nossas alterações
Vamos verificar se nossos pods estão funcionando usando kubectl get po
e kubectl get svc
:
~ kubectl get po
NAME READY STATUS RESTARTS AGE
my-kubernetes-dashboard-7bc7ccfbd9-56w56 1/1 Running 0 18m
my-kubernetes-dashboard-7bc7ccfbd9-f6jc4 1/1 Running 0 18m
~ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 20m
my-kubernetes-dashboard LoadBalancer 10.104.144.125 10.104.144.125 80:32066/TCP 19m
Nossos pods estão implantados e o balanceador de carga está funcionando. Agora verifique a IU:
Figura 2: Painel de cargas de trabalho do Kubernetes
Conclusão
Você pode encontrar os exemplos deste artigo em meu repositório Gitlab.
Com o provisionamento do Helm agora parte do Terraform, minha vida profissional é muito mais fácil. Sei que a separação entre infraestrutura e provisionamento tinha um propósito diferente: as alterações na infraestrutura geralmente eram pontuais ou não exigiam atualizações frequentes, talvez algumas vezes quando as regras de governança ou segurança da minha organização mudavam. As alterações de provisionamento, por outro lado, ocorriam com frequência, às vezes a cada versão. Portanto, fazia sentido ter Terraform (Infraestrutura) e Helm Charts (Provisionamento) em dois repositórios diferentes com duas ferramentas diferentes e dois fluxos de trabalho de revisão diferentes. Não tenho certeza se mesclá-los usando uma única ferramenta seja a melhor ideia, mas uma ferramenta a menos no conjunto de ferramentas é sempre uma grande vitória. Acho que os prós e os contras disso variam de um projeto para outro e de uma equipe para outra.