Pipeline de várias ramificações do Jenkins no GKE

1. Visão geral

O Jenkins é uma das soluções de integração contínua mais usadas. Ele é usado para automatizar as partes não humanas essenciais do processo de desenvolvimento de software. Ao implantar o Jenkins no Kubernetes no Google Cloud e usar o plug-in do GKE, podemos escalonar rapidamente e de forma automática os executores de build conforme a necessidade. Combinado com o Cloud Storage, podemos criar e testar um aplicativo com o mínimo de esforço.

O que você aprenderá

  • Implantar o Jenkins em um cluster do Kubernetes
  • Implante e configure o plug-in do Jenkins GKE para permitir que o Jenkins crie e destrua pods como nós executores.
  • Criar e testar um aplicativo de exemplo do SpringBoot
  • Criar e publicar um contêiner no Google Container Registry
  • Implantar o aplicativo de exemplo em um ambiente de preparo e produção do GKE

O que é necessário

  • Um projeto na nuvem do Google Cloud com o faturamento configurado. Se você não tiver uma, crie uma.

2. Etapas da configuração

Este codelab pode ser executado completamente no Google Cloud Platform sem instalação ou configuração local.

Cloud Shell

Ao longo deste codelab, vamos provisionar e gerenciar diferentes recursos e serviços de nuvem usando a linha de comando pelo Cloud Shell.

Ativar APIs

Estas são as APIs que precisamos ativar no nosso projeto:

  • API Compute Engine: cria e executa máquinas virtuais.
  • API Kubernetes Engine: cria e gerencia aplicativos baseados em contêineres.
  • API Cloud Build: plataforma de integração e entrega contínuas do Google Cloud.
  • API Service Management: permite que produtores de serviços publiquem serviços no Google Cloud Platform.
  • API Resource Manager: cria, lê e atualiza metadados para contêineres de recursos do Google Cloud.

Ative as APIs necessárias com o seguinte comando gcloud:

gcloud services enable compute.googleapis.com \
container.googleapis.com \
cloudbuild.googleapis.com \
servicemanagement.googleapis.com \
cloudresourcemanager.googleapis.com \
--project ${GOOGLE_CLOUD_PROJECT}

Criar um bucket do GCS

Vamos precisar de um bucket do GCS para fazer upload do nosso trabalho de teste. Vamos criar um bucket usando o ID do projeto no nome para garantir a exclusividade:

gsutil mb gs://${GOOGLE_CLOUD_PROJECT}-jenkins-test-bucket/ 

3. Criar clusters do Kubernetes

Criar o cluster

Em seguida, vamos criar um cluster do GKE que vai hospedar nosso sistema Jenkins, incluindo os pods que serão enviados como nós de trabalho. O escopo adicional indicado pela flag --scopes permite que o Jenkins acesse o Cloud Source Repositories e o Container Registry. No console do Cloud, execute o seguinte:

gcloud container clusters create jenkins-cd \
--machine-type n1-standard-2 --num-nodes 1 \
--zone us-east1-d \
--scopes "https://www.googleapis.com/auth/source.read_write,cloud-platform" \
--cluster-version latest

Vamos também implantar dois clusters para hospedar nossos builds de preparo e produção do aplicativo de exemplo:

gcloud container clusters create staging \
--machine-type n1-standard-2 --num-nodes 1 \
--zone us-east1-d \
--cluster-version latest
gcloud container clusters create prod \
--machine-type n1-standard-2 --num-nodes 2 \
--zone us-east1-d \
--cluster-version latest

28b45298e1e82748.png Verificar

Depois que os clusters forem criados, confirme se eles estão em execução com gcloud container clusters list

A saída precisa ter RUNNING na coluna STATUS:

NAME        LOCATION    MASTER_VERSION  MASTER_IP     MACHINE_TYPE   NODE_VERSION  NUM_NODES  STATUS
jenkins-cd  us-east1-d  1.15.9-gke.9    34.74.77.124  n1-standard-2  1.15.9-gke.9  2          RUNNING
prod        us-east1-d  1.15.9-gke.9    35.229.98.12  n1-standard-2  1.15.9-gke.9  2          RUNNING
staging     us-east1-d  1.15.9-gke.9    34.73.92.228  n1-standard-2  1.15.9-gke.9  2          RUNNING

4. Implantar o Jenkins com o Helm

Instalar o Helm

Vamos usar o Helm, um gerenciador de pacotes de aplicativos para Kubernetes, para instalar o Jenkins no nosso cluster. Para começar, faça o download do projeto que inclui os manifestos do Kubernetes que vamos usar para implantar o Jenkins:

git clone https://github.com/GoogleCloudPlatform/continuous-deployment-on-kubernetes.git ~/continuous-deployment-on-kubernetes

Mude o diretório de trabalho atual para o diretório do projeto:

cd ~/continuous-deployment-on-kubernetes/

Crie uma vinculação de papel do cluster para conceder a você mesmo permissões de administrador do cluster:

kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=$(gcloud config get-value account)

Conecte-se ao cluster do Jenkins recebendo as credenciais dele:

gcloud container clusters get-credentials jenkins-cd --zone us-east1-d --project ${GOOGLE_CLOUD_PROJECT}

Faça o download do binário do Helm no console do Cloud:

wget https://storage.googleapis.com/kubernetes-helm/helm-v2.14.1-linux-amd64.tar.gz

Descompacte o arquivo e copie o arquivo helm incluído para o diretório de trabalho atual:

tar zxfv helm-v2.14.1-linux-amd64.tar.gz && \
cp linux-amd64/helm .

O Tiller é o lado do servidor do Helm que é executado no cluster do Kubernetes. Vamos criar uma conta de serviço chamada tiller:

kubectl create serviceaccount tiller \
--namespace kube-system

e vincule-o à função de cluster cluster-admin para que ele possa fazer mudanças:

kubectl create clusterrolebinding tiller-admin-binding \
--clusterrole=cluster-admin \
--serviceaccount=kube-system:tiller

Agora podemos inicializar o Helm e atualizar o repositório:

./helm init --service-account=tiller && \
./helm repo update

28b45298e1e82748.png Verificar

Confirme se o Helm está pronto para uso com ./helm version. Isso vai retornar os números de versão do cliente e do servidor:

Client: &version.Version{SemVer:"v2.14.1", GitCommit:"5270352a09c7e8b6e8c9593002a73535276507c0", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.14.1", GitCommit:"5270352a09c7e8b6e8c9593002a73535276507c0", GitTreeState:"clean"}

Instalar o Jenkins

Agora que o Helm está instalado no nosso cluster, podemos instalar o Jenkins:

./helm install stable/jenkins -n cd \
-f jenkins/values.yaml \
--version 1.2.2 --wait

28b45298e1e82748.png Verificar

Vamos verificar os pods:

kubectl get pods

A saída precisa mostrar o pod do Jenkins com o status "RUNNING":

NAME                          READY     STATUS    RESTARTS   AGE
cd-jenkins-7c786475dd-vbhg4   1/1       Running   0          1m

Confirme se o serviço do Jenkins foi criado corretamente:

kubectl get svc

A resposta será semelhante a esta:

NAME               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)     AGE
cd-jenkins         ClusterIP   10.35.241.170   <none>        8080/TCP    2m27s
cd-jenkins-agent   ClusterIP   10.35.250.57    <none>        50000/TCP   2m27s
kubernetes         ClusterIP   10.35.240.1     <none>        443/TCP     75m

A instalação do Jenkins vai usar o plug-in do Kubernetes para criar agentes de criador. Eles serão iniciados automaticamente pelo mestre do Jenkins conforme necessário. Quando o trabalho for concluído, eles serão finalizados de maneira automática, e os respectivos recursos serão adicionados novamente ao pool de recursos do cluster.

Conectar ao Jenkins

O Jenkins está sendo executado no cluster, mas para acessar a interface, vamos configurar o encaminhamento de portas no Cloud Shell:

export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/component=jenkins-master" -l "app.kubernetes.io/instance=cd" -o jsonpath="{.items[0].metadata.name}") &&
kubectl port-forward $POD_NAME 8080:8080 >> /dev/null &

Uma senha de administrador foi gerada durante a instalação. Vamos recuperá-lo:

printf $(kubectl get secret cd-jenkins -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode);echo

Na parte de cima do Cloud Shell, clique no ícone de visualização da Web 7ddf5a65fd556dd6.png e selecione "Visualizar na porta 8080".

1d614c831a621cff.png

Uma tela de login do Jenkins vai aparecer. Nela, insira o admin para nome de usuário e a senha retornada na etapa anterior:

9cba23e856cbc84f.png

Ao clicar em Fazer login, você será direcionado à página principal do Jenkins.

9261f3e914829137.png

5. Instalar e configurar o plug-in do GKE

O plug-in do Google Kubernetes Engine permite publicar implantações criadas no Jenkins em nossos clusters do Kubernetes executados no GKE. É necessário fazer algumas configurações com as permissões do IAM no seu projeto. Vamos implantar essa configuração usando o Terraform.

Primeiro, baixe o projeto de plug-in do GKE:

git clone https://github.com/jenkinsci/google-kubernetes-engine-plugin.git ~/google-kubernetes-engine-plugin

Configuração automatizada de permissões do IAM

Mude o diretório de trabalho atual para o diretório rbac do projeto do GKE que clonamos antes:

cd ~/google-kubernetes-engine-plugin/docs/rbac/

gcp-sa-setup.tf é um arquivo de configuração do Terraform que cria um papel personalizado do IAM do GCP com permissões restritas e uma conta de serviço do GCP para conceder esse papel. O arquivo exige valores para as variáveis de projeto, região e nome da conta de serviço. Fornecemos esses valores declarando primeiro as seguintes variáveis de ambiente:

export TF_VAR_project=${GOOGLE_CLOUD_PROJECT}
export TF_VAR_region=us-east1-d
export TF_VAR_sa_name=kaniko-role

Inicialize o Terraform, gere um plano e aplique-o:

terraform init
terraform plan -out /tmp/tf.plan
terraform apply /tmp/tf.plan && rm /tmp/tf.plan

A conta de serviço precisa de permissões de administrador de armazenamento para salvar no bucket do Cloud Storage:

gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
--member serviceAccount:kaniko-role@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com \
--role 'roles/storage.admin'

Ele também vai precisar de permissões de contêiner para os estágios de implantação do pipeline:

gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} --member \
serviceAccount:kaniko-role@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com --role 'roles/container.developer'

Agora podemos usar o Helm para configurar permissões de cluster para o plug-in do GKE usando o implantador de robôs do gke. Mude o diretório de trabalho para o diretório do Helm do projeto do GKE:

cd ~/google-kubernetes-engine-plugin/docs/helm/

e instale usando o gráfico do Helm fornecido:

export TARGET_NAMESPACE=kube-system && \
envsubst < gke-robot-deployer/values.yaml | helm install ./gke-robot-deployer --name gke-robot-deployer -f -

6. Configurar o Jenkins

Chaves da conta de serviço

Para que a conta de serviço funcione corretamente, precisamos gerar um arquivo de chave privada e adicioná-lo como um secret do Kubernetes. Primeiro, gere o arquivo com o seguinte comando gcloud:

gcloud iam service-accounts keys create /tmp/kaniko-secret.json --iam-account kaniko-role@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com

Vamos criar uma chave secreta no armazenamento de Secrets do Kubernetes com esse arquivo:

kubectl create secret generic jenkins-int-samples-kaniko-secret --from-file=/tmp/kaniko-secret.json 

Faça o download do arquivo JSON para o disco local acessando o item "Fazer o download do arquivo" no menu de três pontos do Cloud Shell:

c40378e72013b843.png

Insira o caminho do arquivo /tmp/kaniko-secret.json e clique em "Fazer o download".

De volta à página do Jenkins, no painel à esquerda, clique em Credenciais e depois em Sistema.

6c140f7e6bb82f8.png

3b874912cdc8019b.png

Na seção da página chamada Sistema,clique em "Credenciais globais" e em "Adicionar credenciais" à esquerda:

4350c0e68561119b.png

3d3526551cdae8b.png

No menu suspenso "Tipo", selecione Conta de serviço do Google da chave privada. Insira "kaniko-role" como o nome, faça upload da chave JSON criada nas etapas anteriores e clique em "OK".

b0502213408e730e.png

Variáveis de ambiente

Há algumas variáveis de ambiente que precisamos definir no Jenkins antes de criar o pipeline de várias ramificações. São eles:

  • JENK_INT_IT_ZONE: a zona do cluster do Kubernetes. No nosso caso, us-east1-d
  • JENK_INT_IT_PROJECT_ID: refere-se ao ID do projeto do GCP que hospeda esta instância do Jenkins.
  • JENK_INT_IT_STAGING: o nome do cluster de teste. Para fins de demonstração, é staging.
  • JENK_INT_IT_PROD: nome do nosso cluster "prod". Para fins de demonstração, é prod
  • JENK_INT_IT_BUCKET: o bucket do Cloud Storage criado na etapa anterior
  • JENK_INT_IT_CRED_ID: refere-se às credenciais criadas usando o JSON na etapa anterior. O valor precisa corresponder ao nome que atribuímos a ele, kaniko-role.

Para adicionar esses itens, acesse Manage Jenkins:

d54f279190a07878.png

Em seguida, Configure System:

ce79d218b2799640.png

Vai aparecer uma seção chamada Propriedades globais. Ao marcar a caixa Variáveis de ambiente, um botão Adicionar vai aparecer. Clique nele para adicionar as variáveis acima como pares de chave-valor:

81aa222a2b17b2cc.png

Clique no botão Salvar na parte de baixo da página para aplicar as mudanças.

7. Configurar um pipeline

No Jenkins, clique em "Novo item":

8d1270ce4d7b6a8a.png

Insira "jenkins-integration-sample" como nome, selecione "Multibranch Pipeline" como tipo de projeto e clique em OK:

eb071ecfbb4d775b.png

Vamos redirecionar você para a página de configuração do pipeline. Em Origens de ramificação, insira https://github.com/GoogleCloudPlatform/jenkins-integration-samples.git como o Repositório do projeto. Em Configuração da compilação, insira "gke/Jenkinsfile" como o Caminho do script.

5135bd6b0374508c.png

Clique em Salvar para aplicar essas configurações. Ao salvar, o Jenkins vai iniciar uma verificação do repositório e um build subsequente para cada ramificação. À medida que o processo avança, você vê os pods sendo criados, executados e destruídos na página "Cargas de trabalho do Kubernetes".

Quando os builds forem concluídos, você vai encontrar dois itens na página "Cargas de trabalho do Kubernetes" chamados "jenkins-integration-samples-gke", cada um correspondendo ao cluster de produção ou de teste. O status vai mostrar OK:

bdec6b1753d1ba07.png

Usando o seguinte comando gcloud, vamos ver que enviamos uma imagem de contêiner para o Google Container Registry correspondente ao nosso pipeline:

gcloud container images list

Para ver a carga de trabalho no navegador, receba as credenciais do cluster de produção:

gcloud container clusters get-credentials prod --zone us-east1-d --project ${GOOGLE_CLOUD_PROJECT}

Execute o seguinte para configurar um encaminhamento de portas da porta 8081 do shell para a porta 8080 da sua carga de trabalho:

export POD_NAME=$(kubectl get pods -o jsonpath="{.items[0].metadata.name}") &&
kubectl port-forward $POD_NAME 8081:8080 >> /dev/null &

Na parte de cima do Cloud Shell, clique no ícone "Visualização da Web" e selecione "Visualizar na porta 8081".

1b19b5b56f1bae7.png

e80e995e71763bb2.png

8. Limpeza

Você aprendeu a implantar um Jenkins e um pipeline multibranch de amostra no Kubernetes. Agora é hora de liberar espaço do nosso projeto de todos os recursos que criamos.

Excluir o projeto

Se preferir, exclua todo o projeto. No Console do GCP, acesse a página Cloud Resource Manager:

Na lista de projetos, selecione o projeto em que estamos trabalhando e clique em Excluir. Você precisará digitar o ID do projeto. Depois de fazer isso, clique em Desligar.

Outra opção é excluir todo o projeto diretamente no Cloud Shell com gcloud:

gcloud projects delete $GOOGLE_CLOUD_PROJECT

Se você preferir excluir os diferentes componentes faturáveis um por um, siga para a próxima seção.

Cluster do Kubernetes

Exclua todo o cluster do Kubernetes com o gcloud:

gcloud container clusters delete jenkins-cd --zone=us-east1-d

Buckets de armazenamento

Remova todos os arquivos enviados e exclua nosso bucket com o gsutil:

gsutil rm -r gs://${GOOGLE_CLOUD_PROJECT}-jenkins-test-bucket

Imagens do Google Container Registry

Vamos excluir as imagens do Google Container Registry usando os resumos de imagem. Primeiro, recupere os resumos com o seguinte comando:

gcloud container images list-tags gcr.io/${GOOGLE_CLOUD_PROJECT}/jenkins-integration-samples-gke --format="value(digest)"

Em seguida, para cada resumo retornado:

gcloud container images delete gcr.io/${GOOGLE_CLOUD_PROJECT}/jenkins-integration-samples-gke@sha256:<DIGEST>

9. Parabéns!

Uhu! Você conseguiu! Você aprendeu a implantar o Jenkins no GKE e a despachar jobs para clusters do Kubernetes.

O que aprendemos

  • Implantamos um cluster do Kubernetes e usamos o Helm para instalar o Jenkins.
  • Instalamos e configuramos o plug-in do GKE para permitir que o Jenkins implante artefatos de build em clusters do Kubernetes.
  • Configuramos o Jenkins para criar um pipeline de várias ramificações que envia trabalho para clusters do GKE.