Implantar um app .NET no Google Kubernetes Engine usando um fluxo de trabalho do GitHub Actions


Neste tutorial, descrevemos como usar um fluxo de trabalho do GitHub Actions para implantar um aplicativo da Web ASP.NET Model-View-Controller (MVC) que usa o .NET no Google Kubernetes Engine (GKE).

Este tutorial é destinado a desenvolvedores e engenheiros de DevOps que têm conhecimento básico de Microsoft .NET, GitHub Actions e GKE. Também é necessária uma conta do GitHub para executar este tutorial.

Objetivos

Implante um aplicativo da Web ASP.NET Core que usa o .NET 6.0 e é executado no Linux no Google Kubernetes Engine.

O diagrama a seguir mostra o fluxo de trabalho das Ações do GitHub para implantar um aplicativo da Web MVC ASP.NET no Google Kubernetes Engine (GKE).

Diagrama conceitual do fluxo de trabalho do GitHub Actions

Neste tutorial, mostramos como concluir as seguintes tarefas para alcançar seu objetivo:

  • Crie um repositório do GitHub
  • Configurar a autenticação
  • Implantar um cluster do GKE e um repositório do Artifact Registry
  • Criar um fluxo de trabalho do GitHub Actions

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.

Antes de começar

  1. Faça login na sua conta do Google Cloud. Se você começou a usar o Google Cloud agora, crie uma conta para avaliar o desempenho de nossos produtos em situações reais. Clientes novos também recebem US$ 300 em créditos para executar, testar e implantar cargas de trabalho.
  2. 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

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

  4. Ative as APIs Artifact Registry and Google Kubernetes Engine.

    Ative as APIs

  5. 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

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

  7. Ative as APIs Artifact Registry and Google Kubernetes Engine.

    Ative as APIs

Crie um repositório do GitHub

Crie uma bifurcação do repositório dotnet-docs-samples na sua conta do GitHub. Essa etapa é necessária porque estamos criando com Ações do GitHub.

  1. Acesse o repositório do GitHub dotnet-docs-samples.
  2. Clique em Bifurcar.
  3. Na página Criar uma nova bifurcação, defina o seguinte:

    • Proprietário: sua conta do GitHub
    • Nome do repositório - dotnet-docs-samples
  4. Clique em Criar bifurcação.

Configurar a autenticação

Prepare seu projeto do Google Cloud para que as Ações do GitHub possam autenticar e acessar recursos no projeto do Google Cloud.

Criar um pool e um provedor de federação de identidade de carga de trabalho

Para permitir que as Ações do GitHub autentiquem o Google Cloud e implantem no GKE, use a federação de identidade da carga de trabalho. Ao usar a federação de identidade da carga de trabalho, você evita a necessidade de armazenar e gerenciar chaves de conta de serviço para a carga de trabalho do Actions do GitHub.

O uso da federação de identidade da carga de trabalho exige um provedor e um pool de identidades de carga de trabalho. Recomendamos que você use um projeto dedicado para gerenciar pools e provedores de identidade da carga de trabalho. Neste tutorial, para simplificar, crie o pool e o provedor no mesmo projeto do cluster do GKE:

  1. Abra o console do Google Cloud.

  2. No Console do Google Cloud, ative o Cloud Shell.

    Ativar o Cloud Shell

    Na parte inferior do Console do Google Cloud, uma sessão do Cloud Shell é iniciada e exibe um prompt de linha de comando. O Cloud Shell é um ambiente shell com a CLI do Google Cloud já instalada e com valores já definidos para o projeto atual. A inicialização da sessão pode levar alguns segundos.

  3. Crie um novo pool de identidades de carga de trabalho:

    gcloud iam workload-identity-pools create github-actions \
        --location="global" \
        --description="GitHub Actions tutorial" \
        --display-name="GitHub Actions"
    
  4. Adicione ações do GitHub como um provedor de pool de identidade de carga de trabalho:

    gcloud iam workload-identity-pools providers create-oidc github-actions-oidc \
        --location="global" \
        --workload-identity-pool=github-actions \
        --issuer-uri="https://token.actions.githubusercontent.com/" \
        --attribute-mapping="google.subject=assertion.sub"
    

Crie uma conta de serviço

  1. No Cloud Shell, crie uma conta de serviço que as Ações do GitHub possam usar para publicar imagens do Docker e implantá-las no GKE:

    SERVICE_ACCOUNT=$(gcloud iam service-accounts create github-actions-workflow \
      --display-name "GitHub Actions workflow" \
      --format "value(email)")
    
  2. Conceda o papel de gravador do Artifact Registry (roles/artifactregistry.writer) à conta de serviço para permitir que as ações do GitHub foram enviadas para o Artifact Registry:

    gcloud projects add-iam-policy-binding $(gcloud config get-value core/project) \
      --member serviceAccount:$SERVICE_ACCOUNT \
      --role roles/artifactregistry.writer
    
  3. Conceda o papel de desenvolvedor do Google Kubernetes Engine (roles/container.developer) à conta de serviço para permitir que as ações do GitHub sejam enviadas para o Artifact Registry:

    gcloud projects add-iam-policy-binding $(gcloud config get-value core/project) \
      --member serviceAccount:$SERVICE_ACCOUNT \
      --role roles/container.developer
    

Permitir que o fluxo de trabalho do GitHub Actions use a conta de serviço

Permita que o fluxo de trabalho do Actions do GitHub represente e use a conta de serviço:

  1. Inicialize uma variável de ambiente que contenha o assunto usado pelo fluxo de trabalho do GitHub Actions. Um assunto é semelhante a um nome de usuário que identifica exclusivamente o repositório e o branch do GitHub:

    SUBJECT=repo:OWNER/dotnet-docs-samples:ref:refs/heads/main
    

    Substitua OWNER pelo nome de usuário do GitHub.

  2. Conceda ao titular a permissão para personificar a conta de serviço:

    PROJECT_NUMBER=$(gcloud projects describe $(gcloud config get-value core/project) --format='value(projectNumber)')
    
    gcloud iam service-accounts add-iam-policy-binding $SERVICE_ACCOUNT \
      --role=roles/iam.workloadIdentityUser \
      --member="principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/github-actions/subject/$SUBJECT"
    

Implantar um cluster do GKE e um repositório do Artifact Registry

  1. Crie um repositório para imagens do Docker:

    gcloud artifacts repositories create clouddemo \
      --repository-format=docker \
      --location=us-central1
    
  2. Permita que a conta de serviço padrão do Compute Engine acesse o repositório:

    gcloud projects add-iam-policy-binding $(gcloud config get-value core/project) \
      --member=serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com \
      --role=roles/artifactregistry.reader
    
  3. Crie o cluster:

    gcloud container clusters create clouddemo-linux \
      --enable-ip-alias \
      --zone us-central1-a
    

    Esse comando pode levar alguns minutos para ser concluído.

  4. Consiga o nome e o número do projeto do cluster:

    echo "Project ID: $(gcloud config get-value core/project)"
    echo "Project Number: $(gcloud projects describe $(gcloud config get-value core/project) --format=value\(projectNumber\))"
    

    Você precisará desses valores mais tarde.

Criar um fluxo de trabalho do GitHub Actions

Agora você pode usar as Ações do GitHub para configurar a integração contínua. Para cada confirmação enviada ao repositório Git, um fluxo de trabalho do GitHub Actions cria o código e empacota os artefatos de versão em um contêiner do Docker. O contêiner é publicado no Artifact Registry.

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

#
# 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"]

O repositório também contém um manifesto do Kubernetes:

#
# 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

Crie um fluxo de trabalho do Ações do GitHub que faça o seguinte:

  • Autentique-se no Google Cloud usando a federação de identidade da carga de trabalho e a conta de serviço criada anteriormente.
  • Crie uma imagem do Docker e a implante no Artifact Registry.
  • Implantar a imagem do Docker no GKE.

Para criar o fluxo de trabalho do GitHub Actions, faça o seguinte:

  1. No GitHub, acesse a bifurcação do repositório dotnet-docs-samples.
  2. Clique em Adicionar arquivo > Criar novo arquivo.
  3. No campo de texto Name your file, digite o seguinte nome:

    .github/workflows/deploy-gke.yaml
    
  4. Copie o seguinte código no arquivo:

    name: Build and Deploy to GKE
    
    on:
      push:
        branches:
          - main
    
    env:
      PROJECT_ID: PROJECT_ID
      PROJECT_NUMBER: PROJECT_NUMBER
    
      CLUSTER: clouddemo-linux
      CLUSTER_ZONE: us-central1-a
    
      REPOSITORY: clouddemo
      REPOSITORY_REGION: us-central1
    
      IMAGE: clouddemo
    
    jobs:
      build:
        runs-on: ubuntu-latest
        permissions:
          id-token: write
          contents: read
    
        steps:
        - name: Checkout
          uses: actions/checkout@v3
    
        #
        # Authenticate to Google Cloud using workload identity federation
        #
        - id: 'auth'
          name: 'Obtain access token by using workload identity federation'
          uses: 'google-github-actions/auth@v0'
          with:
            create_credentials_file: true
            token_format: access_token
            workload_identity_provider: projects/${{ env.PROJECT_NUMBER }}/locations/global/workloadIdentityPools/github-actions/providers/github-actions-oidc
            service_account: github-actions-workflow@${{ env.PROJECT_ID }}.iam.gserviceaccount.com
    
        - name: Connect to Artifact Registry
          run: |-
            echo ${{ steps.auth.outputs.access_token }} | docker login -u oauth2accesstoken --password-stdin https://${{ env.REPOSITORY_REGION }}-docker.pkg.dev
    
        - name: Connect to GKE
          uses: google-github-actions/get-gke-credentials@v0
          with:
            cluster_name: ${{ env.CLUSTER }}
            location: ${{ env.CLUSTER_ZONE }}
    
        #
        # Build the .NET code
        #
        - name: Build solution
          run: |-
            dotnet publish applications/clouddemo/netcore/CloudDemo.MvcCore.sln \
                --configuration Release \
                --framework net6.0
    
        #
        # Build the Docker image and push it to Artifact Registry
        #
        - name: Create image tag
          run: echo "IMAGE_TAG=${{ env.REPOSITORY_REGION }}-docker.pkg.dev/${{ env.PROJECT_ID }}/${{ env.REPOSITORY }}/${{ env.IMAGE }}:$GITHUB_SHA" >> $GITHUB_ENV
    
        - name: Lock image version in deployment.yaml
          run: sed -i 's|CLOUDDEMO_IMAGE|${{ env.IMAGE_TAG }}|g' applications/clouddemo/netcore/deployment.yaml
    
        - name: Build Docker image
          run: docker build --tag "${{ env.IMAGE_TAG }}" applications/clouddemo/netcore
    
        - name: Publish Docker image to Google Artifact Registry
          run: docker push "${{ env.IMAGE_TAG }}"
    
        #
        # Deploy to GKE
        #
        - name: Deploy to GKE
          run: kubectl apply -f applications/clouddemo/netcore/deployment.yaml
        

    Substitua os seguintes valores:

    • PROJECT_ID: o ID do projeto que contém o cluster do GKE.
    • PROJECT_NUMBER: o número do projeto que contém o cluster do GKE.
  5. Na seção Commit new file, insira uma mensagem de confirmação, por exemplo, Add workflow e clique em Commit new file.

  6. No menu, clique em Ações e aguarde a conclusão do fluxo de trabalho.

    O fluxo de trabalho pode levar vários minutos para ser concluído.

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

    Acesse "Serviços e Entrada"

  8. Acesse a guia Ingress.

  9. Localize o serviço Entrada para o cluster clouddemo e aguarde até que o status dele mude para OK. Isso pode levar alguns minutos.

  10. Abra o link na coluna Front-ends da mesma linha. O balanceador de carga leva alguns minutos para ficar disponível. Portanto, o aplicativo CloudDemo pode não ser carregado inicialmente. Quando o balanceador de carga estiver pronto, você verá o aplicativo CloudDemo com o título personalizado, desta vez em execução no cluster de produção.

Limpeza

Depois de concluir o tutorial, você pode limpar os recursos que criou para que eles parem de usar a cota e gerar cobranças. Nas seções a seguir, descrevemos como excluir ou desativar esses recursos.

Excluir o repositório do GitHub

Para excluir o repositório do GitHub, consulte Como excluir um repositório. A exclusão do repositório faz com que todas as alterações no código-fonte sejam perdidas.

Excluir o projeto

O jeito mais fácil de evitar cobranças é excluindo o projeto que você criou para este tutorial.

    Exclua um projeto do Google Cloud:

    gcloud projects delete PROJECT_ID

A seguir