환경 - Kubernetes 리소스

Azure DevOps Services | Azure DevOps Server 2022 | Azure DevOps Server 2020

Kubernetes 리소스 뷰에는 리소스에 매핑된 네임스페이스 내의 개체 상태 표시됩니다. 리소스 뷰는 Kubernetes 개체에서 파이프라인으로 다시 추적한 다음 커밋으로 다시 추적할 수 있도록 파이프라인 추적 가능성도 오버레이합니다.

Kubernetes 리소스를 사용하여 배포 환경에서 Kubernetes 클러스터를 대상으로 지정합니다. 파이프라인을 사용하여 AKS(Azure Kubernetes Service) 및 다른 클라우드 공급자의 클러스터에 배포합니다.

공용 또는 프라이빗 클러스터에서 Kubernetes 리소스를 사용할 수 있습니다. 리소스 작동 방식에 대한 자세한 내용은 YAML의 리소스 및 리소스를 사용한 보안을 참조하세요.

개요

환경 내에서 Kubernetes 리소스 뷰를 사용할 경우 다음과 같은 이점을 참조하세요.

  • 파이프라인 추적성 - 배포에 사용되는 Kubernetes 매니페스트 태스크리소스 뷰에서 파이프라인 추적 가능성을 표시하는 주석을 더 추가합니다. 파이프라인 추적 기능은 네임스페이스 내의 개체에 대한 업데이트를 담당하는 원래 Azure DevOps 조직, 프로젝트 및 파이프라인을 식별하는 데 도움이 됩니다.

    Pipeline traceability

  • 리소스 상태 진단 - 워크로드 상태 새 배포에서 도입된 실수 또는 회귀를 신속하게 디버깅하는 데 유용할 수 있습니다. 예를 들어 ImagePullBackOff 오류가 발생하는 구성되지 않은 imagePullSecrets의 경우 Pod 상태 정보는 문제의 근본 원인을 식별하는 데 도움이 될 수 있습니다.

    ImagePullBackOff

  • 검토 - 앱 검토는 Git 리포지토리의 모든 끌어오기 요청을 환경의 동적 Kubernetes 리소스에 배포하여 작동합니다. 검토자는 해당 변경 내용이 대상 분기에 병합되고 프로덕션에 배포되기 전에 다른 종속 서비스의 모양과 작동 방식을 확인할 수 있습니다.

Azure Kubernetes Service 사용

AKS(Azure Kubernetes Service)를 사용하는 경우 ServiceAccount는 선택한 클러스터 및 네임스페이스에서 만들어집니다. Kubernetes RBAC 사용 클러스터의 경우 RoleBinding은 생성된 서비스 계정의 범위를 선택한 네임스페이스로 제한하기 위해 생성됩니다. Kubernetes RBAC 사용 안 함 클러스터의 경우 만든 ServiceAccount에는 클러스터 전체 권한(네임스페이스 간)이 있습니다.

AKS Kubernetes 리소스 추가

  1. 환경 세부 정보 페이지에서 리소스 추가를 선택하고 Kubernetes를 선택합니다.

  2. 공급자 드롭다운에서 Azure Kubernetes Service를 선택합니다.

  3. Azure 구독, 클러스터 및 네임스페이스(신규/기존)를 선택합니다.

  4. 유효성 검사를 선택하고 만들기를 선택하여 Kubernetes 리소스를 만듭니다.

  5. 사용자 환경에 대한 클러스터가 표시되는지 확인합니다. 클러스터에 코드를 아직 배포하지 않은 경우 "배포되지 않음" 텍스트가 표시됩니다.

    Add a Kubernetes cluster.

기존 서비스 계정 사용

Azure Kubernetes Service는 사용자 환경 내의 Kubernetes 리소스를 네임스페이스에 매핑합니다.

환경 외부에서 Kubernetes 서비스 연결을 설정하는 방법에 대한 자세한 내용은 서비스 연결의 Kubernetes 서비스 연결 섹션을 참조하세요.

일반 공급자(기존 서비스 계정)를 사용하여 Kubernetes 리소스를 AKS가 아닌 클러스터의 네임스페이스에 매핑합니다.

AKS가 아닌 Kubernetes 리소스 추가

  1. 환경 세부 정보 페이지에서 리소스 추가를 선택하고 Kubernetes를 선택합니다.

  2. 공급자에 대한 제네릭 공급자(기존 서비스 계정)를 선택합니다.

  3. 클러스터 이름 및 네임스페이스 값을 추가합니다.

  4. 서버 URL을 추가합니다. 다음 명령을 사용하여 URL을 가져올 수 있습니다.

    kubectl config view --minify -o 'jsonpath={.clusters[0].cluster.server}'
    
  5. 비밀 개체를 가져옵니다.

    Kubernetes 1.22 이상

    계정 이름으로 대체 service-account-name 합니다.

    kubectl get secret -n <namespace>  -o jsonpath='{.items[?(@.metadata.annotations.kubernetes\.io/service-account\.name==\"service-account-name\")]}'
    

    아무 것도 가져오지 않으면 ServiceAccount에 대한 수명이 긴 API 토큰 수동 만들기를 참조 하세요.

    Kubernetes 1.22 이하:

    1. 서비스 계정 비밀 이름 찾기
    kubectl get serviceAccounts <service-account-name> -n <namespace> -o 'jsonpath={.secrets[*].name}'
    
    1. 이 명령에서 이전 명령의 값으로 바꾸기 <service-account-secret-name>
    kubectl get secret <service-account-secret-name> -n <namespace> -o json
    
  6. 이전 단계의 출력을 사용하여 비밀 개체를 가져옵니다.

    kubectl get secret <service-account-secret-name> -n <namespace> -o json
    
  7. JSON 양식에서 가져온 Secret 개체를 복사하여 비밀 필드에 붙여넣습니다.

  8. 유효성 검사를 선택하고 만들기를 선택하여 Kubernetes 리소스를 만듭니다.

파이프라인에서 Kubernetes 리소스 참조

Azure Kubernetes Service를 사용하고 YAML 파이프라인을 빌드하는 경우 파이프라인을 구성하는 가장 쉬운 방법은 템플릿을 사용하는 것입니다. 리포지토리에 커넥트 다음 두 Kubernetes Service 옵션 중 하나를 선택합니다.

템플릿을 사용하면 YAML 코드를 처음부터 작성하거나 명시적 역할 바인딩을 수동으로 만들 필요 없이 검토 앱을 설정할 수 있습니다.

Kubernetes template options.

검토 앱 설정

다음 예제에서는 첫 번째 배포 작업이 비 PR 분기에 대해 실행되고 환경에서 일반 Kubernetes 리소스에 대해 배포를 수행합니다. 두 번째 작업은 PR 분기에 대해서만 실행되며 요청 시 생성된 Review App 리소스(Kubernetes 클러스터 내의 네임스페이스)에 대해 배포됩니다. 리소스는 환경의 리소스 목록 보기에서 "검토"로 레이블이 지정됩니다. 파이프라인에서 사용할 변수를 정의합니다. Azure Kubernetes Services에 배포 템플릿을 사용하는 경우 이러한 변수가 정의됩니다.

# Build and push image to Azure Container Registry; Deploy to Azure Kubernetes Service
trigger:
- main

resources:
- repo: self

variables:

  # Container registry service connection established during pipeline creation
  dockerRegistryServiceConnection: '12345' # Docker service connection identifier
  envName: 'myEnv' # name of your environment
  imageRepository: 'name-of-image-repository' # name of image repository
  containerRegistry: 'mycontainer.azurecr.io' # path to container registry
  dockerfilePath: '**/Dockerfile'
  tag: '$(Build.BuildId)'
  imagePullSecret: 'my-app-secret' # image pull secret

  # Agent VM image name
  vmImageName: 'ubuntu-latest'

  # Name of the new namespace being created to deploy the PR changes.
  k8sNamespaceForPR: 'review-app-$(System.PullRequest.PullRequestId)'

stages:
- stage: Build
  displayName: Build stage
  jobs:
  - job: Build
    displayName: Build
    pool:
      vmImage: $(vmImageName)
    steps:
    - task: Docker@2
      displayName: Build and push an image to container registry
      inputs:
        command: buildAndPush
        repository: $(imageRepository)
        dockerfile: $(dockerfilePath)
        containerRegistry: $(dockerRegistryServiceConnection)
        tags: |
          $(tag)

    - upload: manifests
      artifact: manifests

- stage: Production
  displayName: Deploy stage
  dependsOn: Build

  jobs:
  - deployment: Production
    condition: and(succeeded(), not(startsWith(variables['Build.SourceBranch'], 'refs/pull/')))
    displayName: Production
    pool:
      vmImage: $(vmImageName)
    environment: 
      name: $(envName).$(resourceName)
      resourceType: Kubernetes 
    strategy:
      runOnce:
        deploy:
          steps:
          - task: KubernetesManifest@0
            displayName: Create imagePullSecret
            inputs:
              action: createSecret
              secretName: $(imagePullSecret)
              dockerRegistryEndpoint: $(dockerRegistryServiceConnection)

          - task: KubernetesManifest@0
            displayName: Deploy to Kubernetes cluster
            inputs:
              action: deploy
              manifests: |
                $(Pipeline.Workspace)/manifests/deployment.yml
                $(Pipeline.Workspace)/manifests/service.yml
              imagePullSecrets: |
                $(imagePullSecret)
              containers: |
                $(containerRegistry)/$(imageRepository):$(tag)

  - deployment: DeployPullRequest
    displayName: Deploy Pull request
    condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/pull/'))
    pool:
      vmImage: $(vmImageName)

    environment: 
      name: $(envName).$(resourceName)
      resourceType: Kubernetes
    strategy:
      runOnce:
        deploy:
          steps:
          - reviewApp: default

          - task: Kubernetes@1
            displayName: 'Create a new namespace for the pull request'
            inputs:
              command: apply
              useConfigurationFile: true
              inline: '{ "kind": "Namespace", "apiVersion": "v1", "metadata": { "name": "$(k8sNamespaceForPR)" }}'

          - task: KubernetesManifest@0
            displayName: Create imagePullSecret
            inputs:
              action: createSecret
              secretName: $(imagePullSecret)
              namespace: $(k8sNamespaceForPR)
              dockerRegistryEndpoint: $(dockerRegistryServiceConnection)

          - task: KubernetesManifest@0
            displayName: Deploy to the new namespace in the Kubernetes cluster
            inputs:
              action: deploy
              namespace: $(k8sNamespaceForPR)
              manifests: |
                $(Pipeline.Workspace)/manifests/deployment.yml
                $(Pipeline.Workspace)/manifests/service.yml
              imagePullSecrets: |
                $(imagePullSecret)
              containers: |
                $(containerRegistry)/$(imageRepository):$(tag)

          - task: Kubernetes@1
            name: get
            displayName: 'Get services in the new namespace'
            continueOnError: true
            inputs:
              command: get
              namespace: $(k8sNamespaceForPR)
              arguments: svc
              outputFormat: jsonpath='http://{.items[0].status.loadBalancer.ingress[0].ip}:{.items[0].spec.ports[0].port}'

          # Getting the IP of the deployed service and writing it to a variable for posting comment
          - script: |
              url="$(get.KubectlOutput)"
              message="Your review app has been deployed"
              if [ ! -z "$url" -a "$url" != "http://:" ]
              then
                message="${message} and is available at $url.<br><br>[Learn More](https://aka.ms/testwithreviewapps) about how to test and provide feedback for the app."
              fi
              echo "##vso[task.setvariable variable=GITHUB_COMMENT]$message"

기존 파이프라인에서 이 작업을 사용하려면 일반 Kubernetes 환경 리소스를 지원하는 서비스 연결을 "클러스터 관리자 자격 증명 사용"으로 수정해야 합니다. 그렇지 않으면 앱 네임스페이스 검토에 대한 기본 서비스 계정에 대한 역할 바인딩을 만들어야 합니다.

다음 단계