Criar um canal de CI/CD com o Azure Pipelines e o Kubernetes Engine

Last reviewed 2022-11-29 UTC

Neste tutorial, mostraremos como usar o Azure Pipelines, o Google Kubernetes Engine (GKE) e o Google Container Registry para criar um pipeline de integração/implantação contínuas (CI/CD) para um aplicativo da Web MVC do ASP.NET. Neste tutorial, você pode escolher entre dois aplicativos de exemplo:

  • Um aplicativo da Web ASP.NET Core que usa o .NET 6.0 e é executado no Linux
  • Um aplicativo da Web ASP.NET MVC que usa o .NET Framework 4 e é executado no Windows

O pipeline de CI/CD usa dois clusters do GKE separados, um para desenvolvimento e outro para produção, como mostra o diagrama a seguir.

Diagrama conceitual do pipeline de CI/CD mostrando como desenvolvedores e usuários finais interagem com o aplicativo

No início do pipeline, os desenvolvedores confirmam as alterações no código de exemplo. Essa ação aciona o canal para criar uma versão e implantá-la no cluster de desenvolvimento. Um gerenciador de versões pode, então, promover a versão para que ela seja implantada no cluster de produção.

Este tutorial se destina a desenvolvedores e engenheiros de DevOps. Ele pressupõe que você tenha conhecimento básico de Microsoft .NET, Azure Pipelines e GKE. Também é preciso ter acesso administrativo a uma conta do Azure DevOps.

Objetivos

  • Conectar o Google Container Registry ao Azure Pipelines para publicar imagens do Docker.
  • Preparar um aplicativo de amostra .NET para implantação no GKE.
  • Autenticar com segurança no GKE sem precisar usar a autenticação legada.
  • Usar o gerenciamento de versões do Azure Pipelines para organizar as implantações do GKE.

Custos

Neste documento, você usará os seguintes componentes faturáveis do Google Cloud:

Para gerar uma estimativa de custo baseada na projeção de uso deste tutorial, use a calculadora de preços. Novos usuários do Google Cloud podem estar qualificados para uma avaliação gratuita.

Ao concluir as tarefas descritas neste documento, é possível evitar o faturamento contínuo excluindo os recursos criados. Saiba mais em Limpeza.

Verifique a página de preços do Azure DevOps para ver as taxas aplicáveis ao uso do Azure DevOps.

Antes de começar

Geralmente, é aconselhável usar projetos separados para cargas de trabalho de desenvolvimento e produção, de modo que os papéis e permissões do gerenciamento de identidade e acesso (IAM) possam ser concedidos individualmente. Para simplificar, neste tutorial é usado um único projeto para os dois clusters do GKE, um para desenvolvimento e outro para produção.

  1. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  2. Make sure that billing is enabled for your Google Cloud project.

  3. É necessário ter uma conta Azure DevOps e ter acesso de administrador a ela. Se você ainda não tiver uma conta do Azure DevOps, inscreva-se na página inicial do Azure DevOps.

Como criar um projeto do Azure DevOps

Use o Azure DevOps para gerenciar o código-fonte, executar compilações e testes e orquestrar a implantação no GKE. Para começar, crie um projeto na sua conta do Azure DevOps.

  1. Acesse a página inicial do Azure DevOps (https://dev.azure.com/YOUR_AZURE_DEVOPS_ACCOUNT_NAME).
  2. Clique em New project.
  3. Insira um nome de projeto, como CloudDemo.
  4. Defina Visibility como Private e clique em Create.
  5. Depois de criar o projeto, clique em Repos no menu à esquerda.
  6. Clique em Import para bifurcar o repositório dotnet-docs-samples do GitHub e defina os seguintes valores:
    • Tipo de repositório: Git
    • URL do clone: https://github.com/GoogleCloudPlatform/dotnet-docs-samples.git
  7. Clique em Importar.

    Quando o processo de importação estiver concluído, você verá o código-fonte do repositório dotnet-docs-samples.

Como conectar o Azure Pipelines ao Google Container Registry

Antes de configurar a integração contínua para o aplicativo CloudDemo, é preciso conectar o Azure Pipelines ao Container Registry. Essa conexão permite que o Azure Pipelines publique imagens de contêiner no Container Registry.

Configurar uma conta de serviço para publicar imagens

Crie uma conta de serviço do Google Cloud no seu projeto:

  1. Abra o console do Google Cloud.

  2. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

  3. Para economizar tempo ao digitar suas opções de ID do projeto e zona do Compute Engine, defina os valores de configuração padrão executando os comandos a seguir:

    gcloud config set project PROJECT_ID
    gcloud config set compute/zone us-central1-a
    

    Substitua PROJECT_ID pelo ID do projeto de destino.

  4. Ative a API Container Registry no projeto:

    gcloud services enable containerregistry.googleapis.com
    
  5. Crie uma conta de serviço que o Azure Pipelines usa para publicar imagens do Docker:

    gcloud iam service-accounts create azure-pipelines-publisher \
        --display-name="Azure Pipelines Publisher"
    
  6. Conceda o papel de IAM do Storage Admin (roles/storage.admin) à conta de serviço para permitir que o Azure Pipelines seja enviado ao Container Registry:

    AZURE_PIPELINES_PUBLISHER=azure-pipelines-publisher@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com
    
    gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \
        --member serviceAccount:$AZURE_PIPELINES_PUBLISHER \
        --role roles/storage.admin
    
  7. Gere uma chave de conta de serviço:

    gcloud iam service-accounts keys create azure-pipelines-publisher.json \
        --iam-account $AZURE_PIPELINES_PUBLISHER
    
    tr -d '\n' < azure-pipelines-publisher.json > azure-pipelines-publisher-oneline.json
    
  8. Veja o conteúdo do arquivo de chave da conta de serviço:

    echo $(<azure-pipelines-publisher-oneline.json)
    

    Você precisa da chave da conta de serviço em uma das etapas a seguir.

Como criar uma conexão de serviço para o Google Container Registry

No Azure Pipelines, crie uma nova conexão de serviço para o Container Registry:

  1. No menu do Azure DevOps, selecione Configurações do projeto e, em seguida, selecione Pipelines > Conexões do serviço.
  2. Clique em Criar conexão de serviço.
  3. Na lista, selecione Registro do Docker e clique em Avançar.
  4. Na caixa de diálogo, insira valores para os seguintes campos:
    • Tipo de registro: Outros
    • Docker Registry: https://gcr.io/PROJECT_ID, substituindo PROJECT_ID pelo nome do projeto (por exemplo, https://gcr.io/azure-pipelines-test-project-12345).
    • ID do Docker: _json_key
    • Senha: cole o conteúdo de azure-pipelines-publisher-oneline.json.
    • Nome da conexão de serviço: gcr-tutorial
  5. Clique em Salvar para criar a conexão.

Como compilar continuamente

Agora, use o Azure Pipelines para configurar a integração contínua. Para cada confirmação enviada para o repositório Git, o Azure Pipelines cria o código e empacota os artefatos de build em um contêiner do Docker. Em seguida, o contêiner é publicado no Container Registry.

O repositório já contém o seguinte Dockerfile:

.NET/Linux

#
# Copyright 2020 Google LLC
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#

FROM mcr.microsoft.com/dotnet/aspnet:6.0
EXPOSE 8080

#------------------------------------------------------------------------------
# Copy publishing artifacts.
#------------------------------------------------------------------------------

WORKDIR /app
COPY CloudDemo.MvcCore/bin/Release/net6.0/publish/ /app/

ENV ASPNETCORE_URLS=http://0.0.0.0:8080

#------------------------------------------------------------------------------
# Run application in Kestrel.
#------------------------------------------------------------------------------

ENTRYPOINT ["dotnet", "CloudDemo.MvcCore.dll"]

.NET Framework/Windows

#
# Copyright 2020 Google LLC
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#

FROM mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
EXPOSE 80
SHELL ["powershell", "-command"]

#------------------------------------------------------------------------------
# Add LogMonitor so that IIS and Windows logs are emitted to STDOUT and can be
# picked up by Docker/Kubernetes.
#
# See https://github.com/microsoft/windows-container-tools/wiki/Authoring-a-Config-File
# for details.
#------------------------------------------------------------------------------

ADD https://github.com/microsoft/windows-container-tools/releases/download/v1.1/LogMonitor.exe LogMonitor/
ADD LogMonitorConfig.json LogMonitor/

#------------------------------------------------------------------------------
# Copy publishing artifacts to webroot.
#------------------------------------------------------------------------------

ADD CloudDemo.Mvc/bin/Release/PublishOutput/ c:/inetpub/wwwroot/

#------------------------------------------------------------------------------
# Configure IIS using the helper functions from deployment.ps1.
#------------------------------------------------------------------------------

ADD deployment.ps1 /
RUN . /deployment.ps1; \
	Install-Iis; \
	Register-WebApplication -AppName "CloudDemo"; \
	Remove-Item /deployment.ps1

#------------------------------------------------------------------------------
# Run IIS, wrapped by LogMonitor.
#------------------------------------------------------------------------------

ENTRYPOINT ["C:\\LogMonitor\\LogMonitor.exe", "C:\\ServiceMonitor.exe", "w3svc"]

Agora, crie um novo pipeline que use a sintaxe YAML:

  1. Usando o Visual Studio ou um cliente git de linha de comando, clone seu novo repositório Git e confira a ramificação main.
  2. Na raiz do repositório, crie um arquivo chamado azure-pipelines.yml.
  3. Copie o seguinte código no arquivo:

    .NET/Linux

    resources:
    - repo: self
      fetchDepth: 1
    pool:
      vmImage: ubuntu-20.04
    trigger:
    - main
    variables:
      TargetFramework: 'net6.0'
      BuildConfiguration: 'Release'
      DockerImageName: 'PROJECT_ID/clouddemo'
    steps:
    - task: DotNetCoreCLI@2
      displayName: Publish
      inputs:
        projects: 'applications/clouddemo/netcore/CloudDemo.MvcCore.sln'
        publishWebProjects: false
        command: publish
        arguments: '--configuration $(BuildConfiguration) --framework=$(TargetFramework)'
        zipAfterPublish: false
        modifyOutputPath: false
    - task: CmdLine@1
      displayName: 'Lock image version in deployment.yaml'
      inputs:
        filename: /bin/bash
        arguments: '-c "awk ''{gsub(\"CLOUDDEMO_IMAGE\", \"gcr.io/$(DockerImageName):$(Build.BuildId)\", $0); print}'' applications/clouddemo/netcore/deployment.yaml > $(build.artifactstagingdirectory)/deployment.yaml"'
    - task: PublishBuildArtifacts@1
      displayName: 'Publish Artifact'
      inputs:
        PathtoPublish: '$(build.artifactstagingdirectory)'
    - task: Docker@2
      displayName: 'Login to Container Registry'
      inputs:
        command: login
        containerRegistry: 'gcr-tutorial'
    - task: Docker@2
      displayName: 'Build and push image'
      inputs:
        Dockerfile: 'applications/clouddemo/netcore/Dockerfile'
        command: buildAndPush
        repository: '$(DockerImageName)'

    .NET Framework/Windows

    resources:
    - repo: self
      fetchDepth: 1
    pool:
      vmImage: windows-2019     # Matches WINDOWS_LTSC in GKE
      demands:
      - msbuild
      - visualstudio
    trigger:
    - master
    variables:
      Solution: 'applications/clouddemo/net4/CloudDemo.Mvc.sln'
      BuildPlatform: 'Any CPU'
      BuildConfiguration: 'Release'
      DockerImageName: 'PROJECT_ID/clouddemo'
    steps:
    - task: NuGetCommand@2
      displayName: 'NuGet restore'
      inputs:
        restoreSolution: '$(Solution)'
    - task: VSBuild@1
      displayName: 'Build solution'
      inputs:
        solution: '$(Solution)'
        msbuildArgs: '/p:DeployOnBuild=true /p:PublishProfile=FolderProfile'
        platform: '$(BuildPlatform)'
        configuration: '$(BuildConfiguration)'
    - task: PowerShell@2
      displayName: 'Lock image version in deployment.yaml'
      inputs:
        targetType: 'inline'
        script: '(Get-Content applications\clouddemo\net4\deployment.yaml) -replace "CLOUDDEMO_IMAGE","gcr.io/$(DockerImageName):$(Build.BuildId)" | Out-File -Encoding ASCII $(build.artifactstagingdirectory)\deployment.yaml'
    - task: PublishBuildArtifacts@1
      displayName: 'Publish Artifact'
      inputs:
        PathtoPublish: '$(build.artifactstagingdirectory)'
    - task: Docker@2
      displayName: 'Login to Container Registry'
      inputs:
        command: login
        containerRegistry: 'gcr-tutorial'
    - task: Docker@2
      displayName: 'Build and push image'
      inputs:
        Dockerfile: 'applications/clouddemo/net4/Dockerfile'
        command: buildAndPush
        repository: '$(DockerImageName)'

    Substitua PROJECT_ID pelo nome do projeto e salve o arquivo.

  4. Confirme as alterações e envie-as para o Azure Pipelines.

    Visual Studio

    1. Abra o Team Explorer e clique no ícone Home.
    2. Clique em Changes.
    3. Insira uma mensagem de confirmação como Add pipeline definition.
    4. Clique em Confirmar tudo e enviar por push.

    Linha de comando

    1. Organize todos os arquivos modificados:

      git add -A
      
    2. Confirme as alterações no repositório local:

      git commit -m "Add pipeline definition"
      
    3. Envie as alterações para o Azure DevOps:

      git push
      
  5. No menu do Azure DevOps, selecione Pipelines e clique em Criar pipeline.

  6. Selecione Azure Repos Git.

  7. Selecione seu Repositório.

  8. Na página Revise o YAML do pipeline, clique em Executar.

    Uma nova versão é acionada. Pode levar cerca de seis minutos para que a compilação seja concluída.

  9. Para verificar se a imagem foi publicada no Container Registry, alterne para o projeto no Console do Google Cloud, selecione Container Registry > Imagens e, em seguida, Clique em CloudDemo.

    Uma única imagem e a tag desta imagem são exibidas. A tag corresponde ao ID numérico da compilação executada no Azure Pipelines.

Como implantar continuamente

Agora que o Azure Pipelines está compilando automaticamente seu código e publicando imagens do Docker para cada commit, retorne sua atenção para a implantação.

Ao contrário de alguns outros sistemas de integração contínua, o Azure Pipelines distingue entre criação e implantação e fornece um conjunto especializado de ferramentas chamado Gerenciamento de versões para todas as tarefas relacionadas à implantação.

O Gerenciamento de versões do Azure Pipelines é criado com base nestes conceitos:

  • Uma versão se refere a um conjunto de artefatos que compõem uma versão específica do app e que geralmente é o resultado de um processo de compilação.
  • Implantação refere-se ao processo de escolher uma versão e implantá-la em um ambiente específico.
  • Uma implantação executa um conjunto de tarefas, que podem ser agrupadas em jobs.
  • Os estágios permitem segmentar seu pipeline e podem ser usados para orquestrar implantações em vários ambientes, por exemplo, ambientes de desenvolvimento e teste.

O principal artefato produzido pelo processo de compilação da CloudDemo é a imagem do Docker. No entanto, como a imagem do Docker é publicada no Container Registry, ela está fora do escopo dos Pipelines do Azure. A imagem, portanto, não serve bem como a definição de uma versão.

Para implantar no Kubernetes, você também precisa de um manifesto, que se assemelha a uma lista de materiais. O manifesto não apenas define os recursos que o Kubernetes tem de criar e gerenciar, mas também especifica a versão exata da imagem do Docker a ser utilizada. O manifesto do Kubernetes é adequado para servir como o artefato que define a versão no gerenciamento de versões do Azure Pipelines.

Configurar a implantação do Kubernetes

Para executar a CloudDemo no Kubernetes, você precisa dos recursos a seguir:

  • Uma implantação que defina um único pod que executa a imagem do Docker produzida pela compilação.
  • Um serviço NodePort que torne o pod acessível a um balanceador de carga.
  • Uma entrada que exponha o aplicativo à Internet pública usando um balanceador de carga HTTP(S) do Cloud.

O repositório já contém o seguinte manifesto do Kubernetes que define esses recursos:

.NET/Linux

#
# Copyright 2020 Google LLC
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#

apiVersion: v1
kind: Service
metadata:
  name: clouddemo-netcore
spec:
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
    name: http
  selector:
    app: clouddemo-netcore
  type: NodePort

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: clouddemo-netcore
spec:
  defaultBackend:
    service:
      name: clouddemo-netcore
      port:
        number: 80

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: clouddemo-netcore
spec:
  replicas: 2
  selector:
    matchLabels:
      app: clouddemo-netcore
  template:
    metadata:
      labels:
        app: clouddemo-netcore
    spec:
      containers:
      - name: clouddemo-netcore
        image: CLOUDDEMO_IMAGE
        ports:
          - containerPort: 8080
        livenessProbe:      # Used by deployment controller
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5
        readinessProbe:     # Used by Ingress/GCLB
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 3
          periodSeconds: 5
        resources:
          limits:
            memory: 1024Mi
          requests:
            memory: 256Mi

.NET Framework/Windows

#
# Copyright 2020 Google LLC
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#

apiVersion: v1
kind: Service
metadata:
  name: clouddemo-net4
  annotations:
    cloud.google.com/neg: '{"ingress": false}' # Disable NEG

spec:
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
    name: http
  selector:
    app: clouddemo-net4
  type: NodePort

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: clouddemo-net4
spec:
  defaultBackend:
    service:
      name: clouddemo-net4
      port:
        number: 80

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: clouddemo-net4
spec:
  replicas: 2
  selector:
    matchLabels:
      app: clouddemo-net4
  template:
    metadata:
      labels:
        app: clouddemo-net4
    spec:
      nodeSelector:
        kubernetes.io/os: windows
      containers:
      - name: clouddemo-net4
        image: CLOUDDEMO_IMAGE
        ports:
          - containerPort: 80
        livenessProbe:      # Used by deployment controller
          httpGet:
            path: /health
            port: 80
          initialDelaySeconds: 120
          periodSeconds: 5
        readinessProbe:     # Used by Ingress/GCLB
          httpGet:
            path: /health
            port: 80
          initialDelaySeconds: 10
          periodSeconds: 5
        resources:
          limits:
            memory: 1024Mi
          requests:
            memory: 256Mi

Configurar os ambientes de desenvolvimento e produção

Antes de retornar ao gerenciamento de versões do Azure Pipelines, você precisa criar os clusters do GKE.

Criar clusters do GKE

  1. Volte para a instância do Cloud Shell.

  2. Ative a API GKE no projeto:

    gcloud services enable container.googleapis.com
  3. Crie o cluster de desenvolvimento usando o comando a seguir. Observe que esse processo pode levar alguns minutos para ser concluído:

    .NET/Linux

    gcloud container clusters create azure-pipelines-cicd-dev --enable-ip-alias
    

    .NET Framework/Windows

    gcloud container clusters create azure-pipelines-cicd-dev --enable-ip-alias
    
    gcloud container node-pools create azure-pipelines-cicd-dev-win \
        --cluster=azure-pipelines-cicd-dev \
        --image-type=WINDOWS_LTSC \
        --no-enable-autoupgrade \
        --machine-type=n1-standard-2
    
  4. Crie o cluster de produção usando o comando a seguir. Observe que esse processo pode levar alguns minutos para ser concluído:

    .NET/Linux

    gcloud container clusters create azure-pipelines-cicd-prod --enable-ip-alias
    

    .NET Framework/Windows

    gcloud container clusters create azure-pipelines-cicd-prod --enable-ip-alias
    
    gcloud container node-pools create azure-pipelines-cicd-prod-win \
        --cluster=azure-pipelines-cicd-prod \
        --image-type=WINDOWS_LTSC \
        --no-enable-autoupgrade \
        --machine-type=n1-standard-2
    

Conectar o Azure Pipelines ao cluster de desenvolvimento

Assim como o Azure Pipelines pode ser usado para se conectar a um registro do Docker externo, como o Container Registry, ele também oferece suporte à integração de clusters Kubernetes externos.

É possível autenticar no Container Registry usando uma conta de serviço do Google Cloud, mas o uso de contas de serviço do Google Cloud não é compatível com o Azure Pipelines para autenticação com o GKE. Em vez disso, você precisa usar uma conta de serviço do Kubernetes.

Para conectar o Azure Pipelines ao seu cluster de desenvolvimento, é preciso primeiro criar uma conta de serviço do Kubernetes.

  1. No Cloud Shell, conecte-se ao cluster de desenvolvimento:

    gcloud container clusters get-credentials azure-pipelines-cicd-dev
  2. Crie uma conta de serviço do Kubernetes para o Azure Pipelines:

    kubectl create serviceaccount azure-pipelines-deploy
  3. Crie um secret do Kubernetes contendo uma credencial de token para o Azure Pipelines:

    kubectl create secret generic azure-pipelines-deploy-token --type=kubernetes.io/service-account-token --dry-run -o yaml \
      | kubectl annotate --local -o yaml -f - kubernetes.io/service-account.name=azure-pipelines-deploy \
      | kubectl apply -f -
    
  4. Atribua o papel cluster-admin à conta de serviço criando uma vinculação de papel de cluster:

    kubectl create clusterrolebinding azure-pipelines-deploy --clusterrole=cluster-admin --serviceaccount=default:azure-pipelines-deploy
  5. Determine o endereço IP do cluster:

    gcloud container clusters describe azure-pipelines-cicd-dev --format=value\(endpoint\)
    

    Você precisará desse endereço daqui a pouco.

  6. No menu do Azure DevOps, selecione Project settings e, em seguida, Pipelines > Service connections.

  7. Clique em New service connection.

  8. Selecione Kubernetes e clique em Avançar.

  9. Defina as configurações a seguir.

    • Método de autenticação: Conta de serviço.
    • URL do servidor: https://PRIMARY_IP. Substitua PRIMARY_IP pelo endereço IP que você determinou anteriormente.
    • Secret: o Secret do Kubernetes que você criou anteriormente. Para receber o Secret, execute o seguinte comando, copie o Secret e, em seguida, copie-o na página do Azure.
      kubectl get secret azure-pipelines-deploy-token -o yaml
    • Nome da conexão de serviço: azure-pipelines-cicd-dev.
  10. Clique em Save.

Conectar o Azure Pipelines ao cluster de produção

Para conectar o Azure Pipelines ao seu cluster de produção, siga a mesma abordagem.

  1. No Cloud Shell, conecte-se ao cluster de produção:

    gcloud container clusters get-credentials azure-pipelines-cicd-prod
  2. Crie uma conta de serviço do Kubernetes para o Azure Pipelines:

    kubectl create serviceaccount azure-pipelines-deploy
  3. Atribua o papel cluster-admin à conta de serviço criando uma vinculação de papel de cluster:

    kubectl create clusterrolebinding azure-pipelines-deploy --clusterrole=cluster-admin --serviceaccount=default:azure-pipelines-deploy
  4. Determine o endereço IP do cluster:

    gcloud container clusters describe azure-pipelines-cicd-prod --format=value\(endpoint\)
    

    Você precisará desse endereço daqui a pouco.

  5. No menu do Azure DevOps, selecione Project settings e, em seguida, Pipelines > Service connections.

  6. Clique em New service connection.

  7. Selecione Kubernetes e clique em Avançar.

  8. Defina as configurações a seguir:

    • Método de autenticação: Conta de serviço.
    • URL do servidor: https://PRIMARY_IP. Substitua PRIMARY_IP pelo endereço IP que você determinou anteriormente.
    • Secret: execute o seguinte comando no Cloud Shell e copie a saída:
      kubectl get secret $(kubectl get serviceaccounts azure-pipelines-deploy -o custom-columns=":secrets[0].name") -o yaml
    • Nome da conexão de serviço: azure-pipelines-cicd-prod.
  9. Clique em Save.

Configurar o pipeline de lançamento

Depois de configurar a infraestrutura do GKE, você retorna ao Azure Pipelines para automatizar a implantação, o que inclui estas tarefas:

  • Implantação no ambiente de desenvolvimento
  • Solicitação de aprovação manual antes de iniciar uma implantação no ambiente de produção
  • Implantação no ambiente de produção

Criar uma definição de versão

Como primeiro passo, crie uma nova definição de versão.

  1. No menu do Azure DevOps, selecione Pipelines > Releases.
  2. Clique em New pipeline.
  3. Na lista de modelos, selecione Job vazio.
  4. Quando for necessário inserir um nome para o estágio, digite Development.
  5. Na parte superior da tela, nomeie a versão CloudDemo-KubernetesEngine.
  6. No diagrama de pipeline, ao lado de Artifacts, clique em Add.
  7. Selecione Build e adicione as seguintes configurações:

    • Tipo de origem: Build
    • Origem (pipeline de build): selecione a definição da compilação. Haverá apenas uma opção
    • Versão padrão: Latest
    • Alias de origem: manifest
  8. Clique em Adicionar.

  9. Na caixa Artifact, clique em Continuous deployment trigger (ícone de raio) para adicionar um gatilho de implantação.

  10. Em Continuous deployment trigger, defina a chave como Enabled.

  11. Clique em Save.

  12. Insira um comentário, se quiser, e confirme clicando em OK.

    O pipeline será assim:

    Captura de tela do pipeline atualizado no Azure Pipelines

Implantar no cluster de desenvolvimento

Depois de criar a definição de versão, você pode configurar a implantação no cluster de desenvolvimento do GKE.

  1. No menu, alterne para a guia Tasks.
  2. Clique em Job do agente e defina as seguintes configurações:

    • Pool de agentes: Azure Pipelines
    • Especificação do agente: ubuntu-18.04
  3. Ao lado de Agent job, clique em Add a task to agent job para adicionar uma etapa à fase.

  4. Selecione a tarefa Deploy to Kubernetes e clique em Add.

  5. Clique na tarefa recém-adicionada e defina as seguintes configurações:

    • Nome de exibição: Deploy
    • Ação: implantação
    • Conexão de serviço Kubernetes: azure-pipelines-cicd-dev
    • Namespace: default
    • Estratégia: nenhuma
    • Manifestos: manifest/drop/deployment.yaml
  6. Clique em Save.

  7. Insira um comentário se quiser e clique em OK para confirmar.

Implantar no cluster de produção

Por fim, configure a implantação no cluster de produção do GKE.

  1. No menu, passe para a guia Pipeline.
  2. Na caixa Stages, select Add > New stage.
  3. Na lista de modelos, selecione Job vazio.
  4. Quando for necessário inserir um nome para o estágio, digite Production.
  5. Clique no ícone de raio, referente ao cenário recém-criado.
  6. Defina as configurações a seguir:

    • Select trigger: After stage
    • Stages: Dev
    • Pre-deployment approvals: (ativada)
    • Approvers: selecione seu próprio nome de usuário

    O pipeline agora fica assim:

    Captura de tela do pipeline atualizado no Azure Pipelines

  7. Alterne para a guia Tasks.

  8. Mantenha o mouse sobre a guia Tasks e clique em Tasks > Production.

  9. Clique em Job do agente e defina as seguintes configurações:

    • Pool de agentes: Azure Pipelines
    • Especificação do agente: ubuntu-18.04
  10. Clique em Add a task to agent job para adicionar uma etapa à fase.

  11. Selecione a tarefa Deploy to Kubernetes e clique em Add.

  12. Clique na tarefa recém-adicionada e defina as seguintes configurações:

    • Nome de exibição: Deploy
    • Ação: implantação
    • Conexão de serviço Kubernetes: azure-pipelines-cicd-prod
    • Namespace: default
    • Estratégia: nenhuma
    • Manifestos: manifest/drop/deployment.yaml
  13. Clique em Save.

  14. Insira um comentário se quiser e clique em OK para confirmar.

Executar o pipeline

Agora que você configurou o pipeline inteiro, é possível testá-lo executando uma alteração no código-fonte:

  1. No computador local, abra o arquivo Index.cshtml no repositório Git que você clonou anteriormente:

    .NET/Linux

    O arquivo está localizado em applications\clouddemo\netcore\CloudDemo.MvcCore\Views\Home\

    .NET Framework/Windows

    O arquivo está localizado em applications\clouddemo\net4\CloudDemo.Mvc\Views\Home\.

  2. Na linha 26, altere o valor de ViewBag.Title de Home Page para This app runs on GKE.

  3. Confirme as alterações e envie-as para o Azure Pipelines.

    Visual Studio

    1. Abra o Team Explorer e clique no ícone Home.
    2. Clique em Changes.
    3. Insira uma mensagem de confirmação como Change site title.
    4. Clique em Confirmar tudo e enviar por push.

    Linha de comando

    1. Organize todos os arquivos modificados:

      git add -A
      
    2. Confirme as alterações no repositório local:

      git commit -m "Change site title"
      
    3. Envie as alterações para o Azure Pipelines:

      git push
      
  4. No menu do Azure DevOps, selecione Pipelines. Um build é acionada.

  5. Após a conclusão do build, selecione Pipelines > Releases. Um processo de versão será iniciado.

  6. Clique em Release-1 para abrir a página de detalhes e aguarde até que o status do estágio Development mude para Succeeded.

  7. No Console do Google Cloud, selecione Kubernetes Engine > Serviços e entrada > Entrada.

  8. Localize o serviço Ingress para o cluster azure-pipelines-cicd-dev e aguarde até que o status dele mude para Ok. Isso pode levar alguns minutos.

  9. Abra o link na coluna Front-ends da mesma linha. Talvez você veja um erro no início porque o balanceador de carga leva alguns minutos para ficar disponível. Quando estiver pronto, você verá que o CloudDemo foi implantado e está usando o título personalizado.

  10. No Azure Pipelines, clique no botão Approve abaixo do cenário Prod, para promover a implantação no ambiente de produção.

    Se você não encontrar o botão, talvez seja necessário aprovar ou rejeitar uma versão anterior.

  11. Insira um comentário, se quiser, e clique em Approve para confirmar.

  12. Aguarde o status do ambiente Prod passar para Succeeded. Pode ser necessário atualizar manualmente a página no navegador.

  13. No Console do Google Cloud, atualize a página Serviços e entrada.

  14. Localize o serviço Ingress para o cluster azure-pipelines-cicd-prod e aguarde que o status dele mude para Ok. Isso pode levar alguns minutos.

  15. Abra o link na coluna Front-ends da mesma linha. Novamente, talvez você veja um erro no início porque o balanceador de carga leva alguns minutos para ficar disponível. Quando estiver pronto, você verá o aplicativo CloudDemo com o título personalizado novamente, desta vez em execução no cluster de produção.

Limpeza

Para evitar custos adicionais depois de concluir este tutorial, exclua as entidades criadas.

Excluir o projeto do Azure Pipelines

Para excluir o projeto do Azure Pipelines, consulte a documentação de serviços do Azure DevOps. A exclusão do projeto do Azure Pipelines faz com que todas as alterações no código-fonte sejam perdidas.

Excluir os projetos e o desenvolvimento do Google Cloud

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

A seguir