Entregando VM's no VMware vCenter/vSphere com o Jenkins

Olá pessoal, depois de muito tempo estou de volta!

No meu primeiro artigo, expliquei e demonstrei como criar máquinas no vCenter/vSphere usando terraform, e que tal entregar essas máquinas virtuais dentro de um pipeline como se fosse um aplicativo?

Não é de hoje que tudo está se convergindo para Cloud Computing e de fato esse parece ser o futuro. Mas ainda temos o meio do caminho, muitas empresas utilizam parte da sua infraestrutura em datacenters, migrando e ou utilizando esse dois mundo em uma abordagem de Cloud Hibrida que acaba fazendo parte do negócio.

Bom deixando a história de lado bora colocar a mão na massa!

Nesse artigo vou utilizar o Jenkins para criar o pipeline de entrega dessas máquinas virtuais. Porque o Jenkins? Ele ainda é um dos serviços de CI/CD mais conhecidos, acredito que todo mundo que usa uma solução mais moderna, tenha pelo menos passado por ele, acho que ainda é valido conhece-lo. Existem grandes empresas que o utilizam e muito bem, com abordagens bem bacanas. o iFood é uma dessas empresas. No TDC do ano passado o pessoal demonstrou um uso de caso que inclusive inspirou esse artigo.

IaaC - Autonomia, rastreabilidade, agilidade com Terraform e Pipeline - Diego Ragazzi / Smailli Moraes

Jenkins

Para esse artigo vamos usar uma versão em container do Jenkins.

docker pull jenkins/jenkins

<>

Junto do Jenkins precisamos de instalar terraform

docker run -it -d --name jenkins -p 8080:8080 -p 50000:50000 jenkins/jenkins
docker exec -it jenkins mkdir /var/jenkins_home/extras
docker cp terraform jenkins:/var/jenkins_home/extras/
docker exec -it jenkins /var/jenkins_home/extras/terraform --version
Terraform v0.12.24

<>

Vamos pegar a senha inicial para inicializar o jenkins

docker exec -it jenkins cat /var/jenkins_home/secrets/initialAdminPassword

Abaixo segue o setup inicial do Jenkins até sua tela inicial.

Unlock Jenkins

<>

Customize Jenkins

<>

Getting Started

<>

Create First Admin User

<>

Instance Configuration

<>

Jenkins is Ready!

<>

Jenkins Dashboard

<>

JOB

Aqui a mágica acontece, vamos criar o pipeline para fazer o deploy da nossa VM.

Novo job

<>

<>

Não vou entrar no detalhe de cada parametro do pipeline, vou direto a criação do pipeline. Com calma, leia cada parametro entenda se faz sentido para o seu uso.

Selecione a opção Este build é parametrizado.

<>

Parametros

Para esse exemplo temos parametros iniciais para criar uma máquina virtual.

  • Nome da máquina
  • Quantidade de máquinas
  • Número de processadores
  • Número de memória
  • Tamanho do disco para instalação do SO. OBS: Para esse exemplo, estou usando o tamanho de 50 (50GB) por conta da customização do disco feita no kickstart da imagem.

<>

<>

<>

<>

<>

<>

Pipeline

Ainda no job, vamos configurar o projeto que ira fazer o deploy da(s) máquinas virtuais.

  • Definição: Pipeline script from SCM
  • SCM: Git
  • Repositories
  • Branches to build
  • Script Path

<>

Em destaque temos o parametro Script Path onde se encontra o arquivo Jenkinsfile, ele quem ira fazer todo o processo de deploy.

Nesse exemplo existem duas variáveis PROVIDER_USR e PROVIDER_PSW, que são as informações que o terraform irá usar no módulo provider para acessar o vSphere/vCenter.

Bom, vou tomar que você tenha um breve entendimento de segurança e entenda que estamos fazendo um exemplo e que estamos em um ambiente controlado, POR FAVOR, NÃO USE ISSO EM PRODUÇÃO estude uma forma mais segura ok?

No próprio jenkins existe uma forma de você gerenciar arquivos de credenciais e senhas. Vamos utilizar a opção de texto secreto Secret text

<>

<>

<>

<>

<>

<>

<>

<>

<>

Junto com a configuração de credencial do jenkins, no Jenkinsfile é preciso usar a seguinte função.

withCredentials([string(credentialsId: 'PROVIDER_USR', variable: 'PROVIDER_USR'), string(credentialsId: 'PROVIDER_PSW', variable: 'PROVIDER_PSW')])

Essa função cria uma mascara aos caracteres no log do JOB em execução.

<>

Eis a mágica! :^D

pipeline {
	agent {
        any {}
	}
	stages {
		stage ('Inicializando o Terraform') {
			steps {
				script {
                    withCredentials([string(credentialsId: 'PROVIDER_USR', variable: 'PROVIDER_USR'), string(credentialsId: 'PROVIDER_PSW', variable: 'PROVIDER_PSW')]) {
                        sh "export TF_VAR_provider_user=${env.PROVIDER_USR} \
                        && export TF_VAR_provider_password=${env.PROVIDER_PSW} \
                        && export TF_VAR_name_new_vm=${env.NAME_NEW_VM} \
                        && export TF_VAR_vm_count=${env.VM_COUNT} \
                        && export TF_VAR_num_cpus=${env.NUM_CPUS} \
                        && export TF_VAR_num_mem=${env.NUM_MEM} \
                        && export TF_VAR_size_disk=${env.SIZE_DISK} \
                        && /var/jenkins_home/extras/terraform init \
    					&& /var/jenkins_home/extras/terraform plan -out deploy.tfplan"
                    }
				}
			}
		}
        stage ('Construindo Maquina Virtual') {
            steps {
                script {
                   if ("${env.TF_STATE}" == "APPLY") {
                        timeout(time: 3, unit: "MINUTES") {
                            input(id: 'chooseOptions', message: 'Criar a maquina virtual?', ok: 'Confirmar')
                            script {
                                sh '/var/jenkins_home/extras/terraform apply deploy.tfplan'
                            }
                        }
                    }
                }
            }
        }
        stage ('Destruindo Maquina Virtual') {
            steps {
                script {
                   if ("${env.TF_STATE}" == "DESTROY") {
                        timeout(time: 3, unit: "MINUTES") {
                            input(id: 'chooseOptions', message: 'Destruir a maquina virtual?', ok: 'Confirmar')
                            script {
                                withCredentials([string(credentialsId: 'PROVIDER_USR', variable: 'PROVIDER_USR'), string(credentialsId: 'PROVIDER_PSW', variable: 'PROVIDER_PSW')]) {
                                    sh "export TF_VAR_provider_user=${env.PROVIDER_USR} \
                                    && export TF_VAR_provider_password=${env.PROVIDER_PSW} \
                                    && export TF_VAR_name_new_vm=${env.NAME_NEW_VM} \
                                    && export TF_VAR_vm_count=${env.VM_COUNT} \
                                    && export TF_VAR_num_cpus=${env.NUM_CPUS} \
                                    && export TF_VAR_num_mem=${env.NUM_MEM} \
                                    && export TF_VAR_size_disk=${env.SIZE_DISK} \
                					&& /var/jenkins_home/extras/terraform destroy -auto-approve"
                                }
                            }
                        }
                    }
                }
            }
        }
	}
	post {
        success {
          slackSend (
              color: '#088A29',
              message: ":white_check_mark: SUCCESSFUL: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})")
        }

        failure {
          slackSend (
              color: '#DF0101',
              message: ":rotating_light: FAILED: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})")
        }
    }
}

Construindo e ou Destruindo sua VM

Depois de realizar todas as configurações, vamos criar e ou destruir nossas máquinas virtuais.

No projeto, vamos contruir APPLY com parametros.

<>

Confirme a criação ou destruição do ambiente.

<>

<>

Você também pode destruir(remover) as máquinas executando novamente o projeto selecionando o DESTROY

<>

Uma perfumaria que pode ser feita é o alerta no slack :D

<>

Demo

<

Conclusão

A alguns anos atrás acredito que para a maioria dos Sysadmin’s(Ops), SRE’s, DevOps Engineer, não importa o nome do cargo, criar um fluxo (pipeline) de entrega de infraestrutura seria inimaginavel. Esse foi uma pequena desmonstração do que pode ser feito, uma forte recomendação é ler a documentação do módulo vSphere do terraform e conhecer outras configurações que podem ser aplicadas na sua infraestrutura.

Projeto: https://github.com/fabianoflorentino/terraform-deploy-vm

comments powered by Disqus