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. No console do Google Cloud, na página do seletor de projetos, selecione ou crie um projeto do Google Cloud.

    Acessar o seletor de projetos

  2. Verifique se a cobrança está ativada para o seu projeto do Google Cloud.

  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. No Console do Google Cloud, ative o Cloud Shell.

    Ativar o 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. No Console do Google Cloud, acesse a página Gerenciar recursos.

    Acessar "Gerenciar recursos"

  2. Na lista de projetos, selecione o projeto que você quer excluir e clique em Excluir .
  3. Na caixa de diálogo, digite o ID do projeto e clique em Encerrar para excluí-lo.

A seguir