환경 - Kubernetes 리소스
Azure DevOps Services | Azure DevOps Server 2022 | Azure DevOps Server 2020
Kubernetes 리소스 뷰는 리소스에 매핑된 네임스페이스 내의 개체 상태를 보여 줍니다. 리소스 뷰는 Kubernetes 개체에서 파이프라인으로 다시 추적한 다음 커밋으로 다시 추적할 수 있도록 파이프라인 추적 가능성도 오버레이합니다.
Kubernetes 리소스를 사용하여 배포 환경에서 Kubernetes 클러스터를 대상으로 지정합니다. 파이프라인을 사용하여 AKS(Azure Kubernetes Service) 및 다른 클라우드 공급자의 클러스터에 배포합니다.
공용 또는 프라이빗 클러스터에서 Kubernetes 리소스를 사용할 수 있습니다. 리소스 작동 방식에 대한 자세한 내용은 YAML의 리소스 및 리소스를 사용한 보안을 참조하세요.
참고 항목
프라이빗 AKS 클러스터를 사용하는 경우 API 서버 엔드포인트가 공용 IP 주소를 통해 노출되지 않으므로 클러스터의 가상 네트워크에 연결되어 있는지 확인합니다.
Azure Pipelines는 클러스터의 가상 네트워크에 액세스할 수 있는 VNET 내에서 자체 호스팅 에이전트를 설정하는 것이 좋습니다. 자세한 내용은 프라이빗 클러스터에 연결하는 옵션을 참조하세요.
개요
환경 내에서 Kubernetes 리소스 뷰를 사용할 경우 다음과 같은 이점을 참조하세요.
파이프라인 추적성 - 배포에 사용되는 Kubernetes 매니페스트 태스크는 리소스 뷰에서 파이프라인 추적 가능성을 표시하는 주석을 더 추가합니다. 파이프라인 추적 기능은 네임스페이스 내의 개체에 대한 업데이트를 담당하는 원래 Azure DevOps 조직, 프로젝트 및 파이프라인을 식별하는 데 도움이 됩니다.
리소스 상태 진단 - 워크로드 상태는 새 배포에서 도입된 실수 또는 회귀를 신속하게 디버깅하는 데 유용할 수 있습니다. 예를 들어 ImagePullBackOff 오류가 발생하는 구성 되지 않은 imagePullSecrets 의 경우 Pod 상태 정보는 문제의 근본 원인을 식별하는 데 도움이 될 수 있습니다.
앱 검토 - 앱 검토는 Git 리포지토리의 모든 끌어오기 요청을 환경의 동적 Kubernetes 리소스에 배포하여 작동합니다. 검토자는 해당 변경 내용이 대상 분기에 병합되고 프로덕션에 배포되기 전에 다른 종속 서비스의 모양과 작동 방식을 확인할 수 있습니다.
Azure Kubernetes Service 사용
AKS(Azure Kubernetes Service)를 사용하는 경우 ServiceAccount는 선택한 클러스터 및 네임스페이스에서 만들어집니다. Kubernetes RBAC 사용 클러스터의 경우 RoleBinding은 생성된 서비스 계정의 범위를 선택한 네임스페이스로 제한하기 위해 생성됩니다. Kubernetes RBAC 사용 안 함 클러스터의 경우 만든 ServiceAccount에는 클러스터 전체 권한(네임스페이스 간)이 있습니다.
AKS Kubernetes 리소스 추가
환경 세부 정보 페이지에서 리소스 추가를 선택하고 Kubernetes를 선택합니다.
공급자 드롭다운에서 Azure Kubernetes Service를 선택합니다.
Azure 구독, 클러스터 및 네임스페이스(신규/기존)를 선택합니다.
유효성 검사를 선택하고 만들기를 선택하여 Kubernetes 리소스를 만듭니다.
사용자 환경에 대한 클러스터가 표시되는지 확인합니다. 클러스터에 코드를 아직 배포하지 않은 경우 "배포되지 않음" 텍스트가 표시됩니다.
기존 서비스 계정 사용
Azure Kubernetes Service는 사용자 환경 내의 Kubernetes 리소스를 네임스페이스에 매핑합니다.
환경 외부에서 Kubernetes 서비스 연결을 설정하는 방법에 대한 자세한 내용은 서비스 연결의 Kubernetes 서비스 연결 섹션을 참조하세요.
팁
일반 공급자(기존 서비스 계정)를 사용하여 Kubernetes 리소스를 AKS가 아닌 클러스터의 네임스페이스에 매핑합니다.
AKS가 아닌 Kubernetes 리소스 추가
환경 세부 정보 페이지에서 리소스 추가를 선택하고 Kubernetes를 선택합니다.
공급자에 대한 제네릭 공급자(기존 서비스 계정)를 선택합니다.
클러스터 이름 및 네임스페이스 값을 추가합니다.
서버 URL을 추가합니다. 다음 명령을 사용하여 URL을 가져올 수 있습니다.
kubectl config view --minify -o 'jsonpath={.clusters[0].cluster.server}'
비밀 개체를 가져옵니다.
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 이하:
- 서비스 계정 비밀 이름 찾기
kubectl get serviceAccounts <service-account-name> -n <namespace> -o 'jsonpath={.secrets[*].name}'
- 이 명령에서 이전 명령의 값으로 바꾸기
<service-account-secret-name>
kubectl get secret <service-account-secret-name> -n <namespace> -o json
이전 단계의 출력을 사용하여 비밀 개체를 가져옵니다.
kubectl get secret <service-account-secret-name> -n <namespace> -o json
JSON 양식에서 가져온 Secret 개체를 복사하여 비밀 필드에 붙여넣습니다.
유효성 검사를 선택하고 만들기를 선택하여 Kubernetes 리소스를 만듭니다.
파이프라인에서 Kubernetes 리소스 참조
Azure Kubernetes Service를 사용하고 YAML 파이프라인을 빌드하는 경우 파이프라인을 구성하는 가장 쉬운 방법은 템플릿을 사용하는 것입니다. 리포지토리에 연결하고 다음 두 Kubernetes 서비스 옵션 중 하나를 선택합니다.
- Azure Kubernetes Services 템플릿에 배포
- Kubernetes에 배포 - Azure DevSpaces를 사용하여 앱 검토
템플릿을 사용하면 YAML 코드를 처음부터 작성하거나 명시적 역할 바인딩을 수동으로 만들 필요 없이 검토 앱을 설정할 수 있습니다.
검토 앱 설정
다음 예제에서는 첫 번째 배포 작업이 비 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 환경 리소스를 지원하는 서비스 연결을 "클러스터 관리자 자격 증명 사용"으로 수정해야 합니다. 그렇지 않으면 앱 네임스페이스 검토에 대한 기본 서비스 계정에 대한 역할 바인딩을 만들어야 합니다.