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

Este tutorial descreve 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 Framework no Google Kubernetes Engine (GKE).

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

Objetivos

Implantar um aplicativo da Web ASP.NET MVC que usa o .NET Framework 4 e é executado no Windows em Google Kubernetes Engine.

O diagrama a seguir mostra o GitHub Actions, fluxo de trabalho para implantar um aplicativo da Web ASP.NET MVC 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, use a calculadora de preços.

Novos Google Cloud usuários podem estar qualificados para um teste sem custo financeiro.

Ao concluir as tarefas descritas neste documento, é possível evitar o faturamento contínuo excluindo os recursos criados. Para mais informações, consulte Liberar espaço.

Antes de começar

  1. Faça login na sua Google Cloud conta do. Se você começou a usar o Google Cloud, crie uma conta para avaliar o desempenho dos 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. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. Enable the Artifact Registry and Google Kubernetes Engine APIs.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

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

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  6. Verify that billing is enabled for your Google Cloud project.

  7. Enable the Artifact Registry and Google Kubernetes Engine APIs.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

Crie um repositório do GitHub

Crie um fork do repositório dotnet-docs-samples na sua conta do GitHub. Essa etapa é necessária porque estamos criando com o GitHub Actions.

  1. Acesse o dotnet-docs-samples repositório do GitHub.
  2. Clique em Fork.
  3. Na página Criar um novo fork, defina o seguinte:

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

Configurar a autenticação

Prepare seu Google Cloud projeto para que o GitHub Actions possa autenticar e acessar recursos nele. Google Cloud

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

Para permitir que o GitHub Actions autentique Google Cloud e implante no GKE, use a federação de identidade da carga de trabalho. Ao usar a federação de identidade da carga de trabalho, é possível evitar a necessidade de armazenar e gerenciar chaves de conta de serviço para a carga de trabalho do GitHub Actions.

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

  1. Abra o Google Cloud console.

  2. No Google Cloud console, ative o Cloud Shell.

    Ativar o Cloud Shell

    Na parte inferior do Google Cloud console, uma sessão do Cloud Shell é iniciada e exibe um prompt de linha de comando. O Cloud Shell é um ambiente shell com a Google Cloud CLI 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 Identidade da carga de trabalho:

    gcloud iam workload-identity-pools create github-actions \
        --location="global" \
        --description="GitHub Actions tutorial" \
        --display-name="GitHub Actions"
    
  4. Adicione o GitHub Actions como um provedor de pool de Identidade da 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" \
        --attribute-condition="assertion.repository_owner=='ORGANIZATION'"
    

    Substitua ORGANIZATION pelo nome da sua organização do GitHub.

Criar uma conta de serviço

  1. No Cloud Shell, crie uma conta de serviço que o GitHub Actions possa usar para publicar imagens do Docker e implantar 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 enviem 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 enviem 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 GitHub Actions 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 a ramificação do GitHub:

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

    Substitua OWNER pelo nome de usuário do GitHub.

  2. Conceda permissão ao assunto para representar 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-windows \
      --enable-ip-alias \
      --zone us-central1-a
    
    gcloud container node-pools create clouddemo-windows-pool \
      --cluster=clouddemo-windows \
      --image-type=WINDOWS_LTSC_CONTAINERD \
      --no-enable-autoupgrade \
      --machine-type=n1-standard-2 \
      --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, use o GitHub Actions para configurar a integração contínua. Para cada confirmação enviada para o repositório Git, um fluxo de trabalho do GitHub Actions cria o código e empacota os artefatos de build em um contêiner do Docker. Em seguida, 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/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"]

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

Crie um fluxo de trabalho do GitHub Actions que faça o seguinte:

  • Autentique o Google Cloud usando a federação de identidade da carga de trabalho e a conta de serviço que você criou anteriormente.
  • Crie uma imagem Docker e implante-a no Artifact Registry.
  • Implante a imagem Docker no GKE.

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

  1. No GitHub, acesse seu fork do dotnet-docs-samples repositório.
  2. Clique em Adicionar arquivo > Criar novo arquivo.
  3. No campo de texto Nomeie seu arquivo, insira 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-windows
      CLUSTER_ZONE: us-central1-a
    
      REPOSITORY: clouddemo
      REPOSITORY_REGION: us-central1
    
      IMAGE: clouddemo
    
    jobs:
      build:
        runs-on: windows-2019  # Matches WINDOWS_LTSC in GKE
        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: Setup MSBuild
          uses: microsoft/setup-msbuild@v1
    
        - name: Setup NuGet
          uses: NuGet/setup-nuget@v1
    
        - name: Restore NuGet packages
          run: nuget restore applications/clouddemo/net4/CloudDemo.Mvc.sln
    
        - name: Build solution
          run: msbuild /t:Rebuild /p:Configuration=Release /p:DeployOnBuild=true /p:PublishProfile=FolderProfile /nologo applications/clouddemo/net4/CloudDemo.Mvc.sln
    
        #
        # 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 }}:$env:GITHUB_SHA" >> $env:GITHUB_ENV
    
        - name: Lock image version in deployment.yaml
          shell: pwsh
          run: (Get-Content applications\clouddemo\net4\deployment.yaml) -replace "CLOUDDEMO_IMAGE","${{ env.IMAGE_TAG }}" | Out-File -Encoding ASCII applications\clouddemo\net4\deployment.yaml
    
        - name: Build Docker image
          run: docker build --tag "${{ env.IMAGE_TAG }}" applications/clouddemo/net4
    
        - 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/net4/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 Fazer commit do novo arquivo, insira uma mensagem de commit, por exemplo, Add workflow e clique em Fazer commit do novo arquivo.

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

    O fluxo de trabalho pode levar alguns minutos para ser concluído.

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

    Acesse "Serviços e Entrada"

  8. Acesse a guia Entrada.

  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, então o app CloudDemo pode não carregar no início. Quando o balanceador de carga estiver pronto, você verá o app CloudDemo com o título personalizado, desta vez em execução no cluster de produção.

Liberar espaço

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

    Excluir um Google Cloud projeto do:

    gcloud projects delete PROJECT_ID

A seguir