20231228 Azure DevOps를 활용하여 AKS에 Modern App 배포하기

20231228 Azure DevOps를 활용하여 AKS에 Modern App 배포하기

 

 

 

 

 

1. Azure  DevOps에 Backlog 등록하기

Azure DevOps에 다음 Backlog를 등록한다.

Epic

Issue

Task

Description

Azure DevOps를 활용하여 AKS에
Modern App 배포

로컬 환경 작업

소스 준비하기

Spring Boot 샘플 소스를 로컬로 git clone 한다.
https://github.com/zer0big/gs-spring-boot-aks  를 fork하여 자신의 리포지토리 상에서 git clone 한다.

App Build 및 검증하기

Maven Build 후 애플리케이션의 동작을 검증한다.

Docker Build 및 검증하기

검증된 애플리케이션을 doker build 후 생성된 이미지에 대하여 동작을 검증한다.

이미지 ACR로 푸시하기

검증된 이미지를 ACR로 태그/푸시한다.
# 전제조건 : 먼저 ACR 배포하기 Task 수행 완료한다.

Azure Resource 작업

AKS 클러스터 배포하기

Modern App이 배포 될 대상 AKS 클러스터를 생성한다.

ACR 배포하기

Containerized App을 관리할 Container Repository를 생성한다.

AKS-ACR 통합하기

AKS의 Pod에서 ACR의 이미지를 Pull 할 수 있도록 Attatch 한다.

Azure DevOps 작업

Modern App 샘플 준비하기

Containerized된 Spring Boot 샘플 소스를 Azure Repos에 Import 한다.
https://github.com/zer0big/gs-spring-boot-aks

서비스 커넥션 구성하기

Azure Resource가 위치하는 Azure 구독에 대해 ACR, AKS 등의 서비스 커넥션을 생성 및 구성한다.

CI 파이프라인 구성하기

CI 파이프라인을 생성 및 구성한다.

CD 파이프라인 구성하기

CD 파이프라인을 생성 및 구성한다.

CI/CD 검증하기

소스 변경을 수행하여 구성한 CI/CD 파이프라인이 정상적으로 동작하는지 검증한다.

 

 

1,1  프로젝트 생성하기

먼저 Azure DevOps에서 프로젝트를 생성한다.

  • Project name : DeployContApp2AKS

  • Visibility : 기본값

 

1.2 Backlog 등록하기

 

Boards > Backlogs를 클릭하고 Work Item 타입을 Epic으로 선택 후 + New Work Item을 클릭한다.

 

Epic 란에 "Azure DevOps를 활용하여 AKS에 Modern App 배포" 라고 입력 후 Add to top을 클릭한다.

 

Backlog는 Work items나 Boards 화면을 통해서도 등록 가능하다. 여기서는 Scrum 프로세스의 취지를 살려 플래닝 하여 도출한 Backlog에 대하여 각각 Epic, Issue, Tasks 순서로 등록하는 것을 기준으로 한다.

 

생성한 Epic의 좌측에 를 클릭하면 Issue 등록 창으로 전환하게 된다.

 

 

위에서 정의한 Backlog 중 첫 번째 Issue를 입력하고 Save & Close를 클릭한다.

 

이제 화면은 다음과 같은 모습이 된다.

 

생성한 Issue의 좌측에 +를 클릭하면 Task 등록 창으로 전환하게 된다.

위에서 정의한 Backlog 중 "로컬 환경 작업" Issue의 첫 Task명을 입력하고 Description을 입력한 후 Save & Close를 클릭한다.

 

현재 순서대로 Backlog를 등록하면 Epic과 Issue 등록 화면 각각의 우측 하단에 다음과 같이 Work(일감)에 대한 링크가 구성된다.

 

이제 화면은 다음과 같은 모습이 된다.

생성한 Issue (로컬 환경 작업)의 좌측에 + 를 클릭하여 반복 과정을 통해 추가 Task를 등록한다.

등록 후 화면은 다음과 같다.

다시 생성한 Epic의 좌측에 + 를 클릭 후 위 과정을 반복하여 정의했던 Backlog (Issue 및 Task)를 등록한다.

모든 Backlog가 등록된 후의 최종 화면은 다음과 같다.

 

 

참고로 Boards 화면에서 전시되는 모습은 다음과 같다.

 

 

 

2. Backlog 구현하기

 

이제 첫 번째 Issue를 Doing으로 이동 후 Backlog(또는 일감)를 구현해 나간다. 각 일감마다 처리 완료 후 Done으로 업데이트 한다.

 

현재 일감의 진행 상태를 나타내는 컬럼 중 "Doing" "Done"  사이에 "Reviewed"를 새로 생성하는 것이 좋다. 

일감을 완료한 사람이 바로 Done으로 이동시키는 것이 아니라 Reviewed로 이동시키고 일감을 할당/요청한 사람이 완료 조건을 검토 후 Done으로 이동 또는 반려하는 프로세스 구성이 권장되는 관행이다.

하지만 본 튜토리얼에서는 간결성을 위해 본인이 일감 종료 시 마다 바로 일감을 Done 하는 것으로 한다.

 

일감에 대한 작업자 할당(assign)은 Issue 단위 또는 Task 단위로 가능하다. 하나의 Issue에 대하여 여러명이 함께 처리하게 되는 경우Task를 각각에게 할당할 수 있다는 의미이다. 여기서는 Issue 단위에만 작업자를 할당하는 기준으로 진행한다.

  • Task 레벨 assign

 

  • Issue 레벨 assign

 

 

 

2.1 소스 준비하기

일감을 처리하가 위해서는 로컬 작업 환경에 다음의 전제 조건이 충족되어야 한다.

 

먼저 https://github.com/zer0big/gs-spring-boot-aks.git  로부터 Fork를 수행하여 자신의 리포지토리를 기준으로 작업을 진행한다.

 

자신의 리포지토리 우측 상단의 Code를 클릭하여 복제할 HTTPS 주소를 복사한다.

 

git clone 하여 샘플 소스를 다운 받고 소스 디렉토리로 이동한다.

VS Code가 설치 된 경우 code 명령을 수행하여 소스 코드 내용을 살펴본다.

git clone https://github.com/zer0big/gs-spring-boot-aks.git cd gs-spring-boot-aks code .

 

 

2.2 App 빌드 및 검증하기

별도의 bash 창에서 mvn clean package 명령으로 컴파일을 수행하고 컴파일 한다. 참고로 clean 옵션은 maven build 시 생성된 모든 것들을 삭제한다.

mvn clean package -DskipTests

 

appmod-demo# mvn clean package -DskipTests WARNING: An illegal reflective access operation has occurred WARNING: Illegal reflective access by com.google.inject.internal.cglib.core.$ReflectUtils$1 (file:/usr/share/maven/lib/guice.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) WARNING: Please consider reporting this to the maintainers of com.google.inject.internal.cglib.core.$ReflectUtils$1 WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations WARNING: All illegal access operations will be denied in a future release [INFO] Scanning for projects... [INFO] [INFO] -------------< org.springframework:gs-spring-boot-docker >-------------- [INFO] Building Spring Boot Docker 0.1.0 [INFO] --------------------------------[ jar ]--------------------------------- [INFO] [INFO] --- maven-clean-plugin:3.1.0:clean (default-clean) @ gs-spring-boot-docker --- [INFO] [INFO] --- maven-resources-plugin:3.1.0:resources (default-resources) @ gs-spring-boot-docker --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] Copying 1 resource [INFO] Copying 0 resource [INFO] [INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ gs-spring-boot-docker --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 1 source file to /mnt/c/Users/youngdae.kim/gs-spring-boot-aks/target/classes [INFO] [INFO] --- maven-resources-plugin:3.1.0:testResources (default-testResources) @ gs-spring-boot-docker --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] skip non existing resourceDirectory /mnt/c/Users/youngdae.kim/gs-spring-boot-aks/src/test/resources [INFO] [INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ gs-spring-boot-docker --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 1 source file to /mnt/c/Users/youngdae.kim/gs-spring-boot-aks/target/test-classes [INFO] [INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ gs-spring-boot-docker --- [INFO] Tests are skipped. [INFO] [INFO] --- maven-jar-plugin:3.2.0:jar (default-jar) @ gs-spring-boot-docker --- [INFO] Building jar: /mnt/c/Users/youngdae.kim/gs-spring-boot-aks/target/gs-spring-boot-docker-0.1.0.jar [INFO] [INFO] --- spring-boot-maven-plugin:2.3.0.RELEASE:repackage (repackage) @ gs-spring-boot-docker --- [INFO] Replacing main artifact with repackaged archive [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 3.557 s [INFO] Finished at: 2022-04-19T15:00:31+09:00 [INFO] ------------------------------------------------------------------------ appmod-demo#

 

target 디렉토리 생성을 확인하고 해당 디렉토리로 이동하여 gs-spring-boot-docker-0.1.0.jar 파일 생성을 확인한다.

cd target ls -rlth

 

appmod-demo# appmod-demo# ls -rlht total 44K -rwxrwxrwx 1 zerobig zerobig 131 Apr 19 14:53 Dockerfile -rwxrwxrwx 1 zerobig zerobig 378 Apr 19 14:53 README.md -rwxrwxrwx 1 zerobig zerobig 1.1K Apr 19 14:53 azure-pipelines.yml -rwxrwxrwx 1 zerobig zerobig 771 Apr 19 14:53 build.gradle drwxrwxrwx 1 zerobig zerobig 4.0K Apr 19 14:53 gradle -rwxrwxrwx 1 zerobig zerobig 5.9K Apr 19 14:53 gradlew -rwxrwxrwx 1 zerobig zerobig 3.0K Apr 19 14:53 gradlew.bat drwxrwxrwx 1 zerobig zerobig 4.0K Apr 19 14:53 k8s -rwxrwxrwx 1 zerobig zerobig 11K Apr 19 14:53 mvnw -rwxrwxrwx 1 zerobig zerobig 6.7K Apr 19 14:53 mvnw.cmd -rwxrwxrwx 1 zerobig zerobig 1.6K Apr 19 14:53 pom.xml drwxrwxrwx 1 zerobig zerobig 4.0K Apr 19 14:53 src drwxrwxrwx 1 zerobig zerobig 4.0K Apr 19 2022 target appmod-demo# appmod-demo# cd target/ appmod-demo# ls -rlht total 16M drwxrwxrwx 1 zerobig zerobig 4.0K Apr 19 15:00 generated-sources drwxrwxrwx 1 zerobig zerobig 4.0K Apr 19 15:00 maven-status drwxrwxrwx 1 zerobig zerobig 4.0K Apr 19 15:00 classes drwxrwxrwx 1 zerobig zerobig 4.0K Apr 19 15:00 generated-test-sources drwxrwxrwx 1 zerobig zerobig 4.0K Apr 19 15:00 test-classes drwxrwxrwx 1 zerobig zerobig 4.0K Apr 19 15:00 maven-archiver -rwxrwxrwx 1 zerobig zerobig 2.9K Apr 19 15:00 gs-spring-boot-docker-0.1.0.jar.original -rwxrwxrwx 1 zerobig zerobig 16M Apr 19 15:00 gs-spring-boot-docker-0.1.0.jar appmod-demo#

 

java -jar 명령을 통해 로컬에서 샘플 소스의 유효성을 검증한다.

java -jar gs-spring-boot-docker-0.1.0.jar

 

appmod-demo# java -jar gs-spring-boot-docker-0.1.0.jar . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.3.0.RELEASE) 2022-04-19 15:03:21.292 INFO 586 --- [ main] hello.Application : Starting Application v0.1.0 on youngdae_kim with PID 586 (/mnt/c/Users/youngdae.kim/gs-spring-boot-aks/target/gs-spring-boot-docker-0.1.0.jar started by zerobig in /mnt/c/Users/youngdae.kim/gs-spring-boot-aks/target) 2022-04-19 15:03:21.298 INFO 586 --- [ main] hello.Application : No active profile set, falling back to default profiles: default 2022-04-19 15:03:25.029 INFO 586 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http) 2022-04-19 15:03:25.058 INFO 586 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2022-04-19 15:03:25.058 INFO 586 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.35] 2022-04-19 15:03:25.300 INFO 586 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2022-04-19 15:03:25.300 INFO 586 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 3826 ms 2022-04-19 15:03:25.937 INFO 586 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor' 2022-04-19 15:03:26.547 INFO 586 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '' 2022-04-19 15:03:26.574 INFO 586 --- [ main] hello.Application : Started Application in 6.957 seconds (JVM running for 7.842)

 

별도의 Windows 터미널 탭을 띄워서 다음 명령을 실행한다.

start http://localhost:8080

 

팝업 된 웹 브라우저에서 실행 결과를 확인한다.

 

결과 확인 후 Ctrl + C를 눌러 실행된 자바 프로세스를 종료한다.

다음 명령을 시행하여 gs-spring-boot-aks 디렉토리로 이동한다.

cd ..

 

2.3 Docker Build 및 검증하기

Azure Container Registry 생성

다음 명령을 수행하여 ACR을 생성하고 결과를 확인한다.

# AZ Login az login # 변수 선언 //ACR_NAME은 각자 고유한 이름으로 할당 ACR_NAME=zerobigacrdemo RESOURCE_GROUP=RG-Demo4TDG-CICD REGION_NAME=koreacentral # Resource Group 생성 az group create \ --resource-group $RESOURCE_GROUP \ --location $REGION_NAME # ACR 생성 az acr create \ --resource-group $RESOURCE_GROUP \ --location $REGION_NAME \ --name $ACR_NAME \ --sku Standard # 생성 결과 확인 az acr list -o table

 

Docker Build

다시 gs-spring-boot-aks 디렉토리로 이동하여 샘플 소스 내 준비된 Dockerfile 내용을 검토한다.

FROM openjdk:8-jdk-alpine EXPOSE 8080 ARG JAR_FILE=target/*.jar ADD ${JAR_FILE} app.jar ENTRYPOINT ["java","-jar","/app.jar"]

 

docker build 명령을 수행하여 docker images를 생성한다.

docker build -t appmod-demo4tdg-cicd . docker images

 

appmod-demo# docker build -t appmod-demo4tdg-cicd "docker build" requires exactly 1 argument. See 'docker build --help'. Usage: docker build [OPTIONS] PATH | URL | - Build an image from a Dockerfile appmod-demo# appmod-demo# appmod-demo# docker build -t appmod-demo4tdg-cicd . [+] Building 16.1s (8/8) FINISHED => [internal] load build definition from Dockerfile 0.1s => => transferring dockerfile: 176B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load metadata for docker.io/library/openjdk:8-jdk-alpine 15.7s => [auth] library/openjdk:pull token for registry-1.docker.io 0.0s => [internal] load build context 0.2s => => transferring context: 16.47MB 0.2s => CACHED [1/2] FROM docker.io/library/openjdk:8-jdk-alpine@sha256:94792824df2df33402f201713f932b58cb9de94a0cd524164a0f 0.0s => [2/2] ADD target/*.jar app.jar 0.1s => exporting to image 0.1s => => exporting layers 0.1s => => writing image sha256:6f8522b00ab4dd75e013983d972f5dd84cfab2d32bc085d0109e304eaea2178f 0.0s => => naming to docker.io/library/appmod-demo4tdg-cicd                                                                        0.0s Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them appmod-demo# appmod-demo# docker images REPOSITORY TAG IMAGE ID CREATED SIZE appmod-demo4tdg-cicd                latest 6f8522b00ab4 32 seconds ago 121MB eerkunt/terraform-compliance latest 51f9a525daa5 3 weeks ago 349MB appmod-demo#

 

docker run 명령을 수행하여 로컬에서 동작 유효성을 검증한다.

appmod-demo# docker run -d -p 8888:8080 appmod-demo4tdg-cicd 72f76c1112c0a1a4b4e52a051d6dcf5cf542d34ffea7c52580b6ccd1ad0e2be7 appmod-demo#

 

로컬 브라우저를 통해 결과를 검증한다.(전시되는 메시지 내용을 상이할 수 있다.)

 

2.4 이미지 ACR로 푸시하기

Docker Tag

docker tag, push 명령을 수행하여 생성한 ACR에 images를 Push한다.

az acr login -n $ACR_NAME docker tag appmod-demo4tdg-cicd $ACR_NAME.azurecr.io/appmod-demo4tdg-cicd docker push $ACR_NAME.azurecr.io/appmod-demo4tdg-cicd

 

appmod-demo# docker tag appmod-demo4tdg-cicd zeroacrdemo.azurecr.io/appmod-demo4tdg-cicd appmod-demo# appmod-demo# docker images REPOSITORY TAG IMAGE ID CREATED SIZE appmod-demo4tdg-cicd                          latest 6f8522b00ab4 23 minutes ago 121MB zeroacrdemo.azurecr.io/appmod-demo4tdg-cicd   latest 6f8522b00ab4 23 minutes ago 121MB eerkunt/terraform-compliance latest 51f9a525daa5 3 weeks ago 349MB appmod-demo# appmod-demo# docker push zeroacrdemo.azurecr.io/appmod-demo4tdg-cicd Using default tag: latest The push refers to repository [zeroacrdemo.azurecr.io/appmod-demo4tdg-cicd] ebc99b57ef7e: Preparing ceaf9e1ebef5: Preparing 9b9b7f3d56a0: Preparing f1b5933fe4b5: Preparing unauthorized: authentication required, visit https://aka.ms/acr/authorization for more information. appmod-demo#

 

인증/인가 에러가 발생한다. az acr login 명령을 수행하여 인증을 득하고 다시 명령을 수행한다.

az acr login -n zeroacrdemo docker push zeroacrdemo.azurecr.io/appmod-demo4tdg-cicd

 

appmod-demo# az acr login -n $ACR_NAME Login Succeeded appmod-demo# docker push zeroacrdemo.azurecr.io/appmod-demo4tdg-cicd Using default tag: latest The push refers to repository [zeroacrdemo.azurecr.io/appmod-demo4tdg-cicd] ebc99b57ef7e: Pushed ceaf9e1ebef5: Pushed 9b9b7f3d56a0: Pushed f1b5933fe4b5: Pushed latest: digest: sha256:2aca8d1526c48874d3eb61bae6ec758d1a5fc8fa9babd195def9fc3180fe17fb size: 1159 appmod-demo#

 

Azure 포털의 리포지토리로 이동하여 결과를 확인한다. 

이제 "로컬 환경 작업" Issue는 Done으로 이동시키고 "Azure Resource 작업"을 Doing으로 이동시키고 자신에게 Issue를  할당한다.

참고로 ACR 배포하기 Task는 이미 처리 되었으므로 Done 처리 되었다.

 

2.5 AKS 클러스터 배포하기

다음 명령을 수행하여 AKS를 생성한다.

# 변수 선언 //AKS_NAME은 각자 고유한 이름으로 할당 AKS_CLUSTER_NAME=zerobigaksdemo RESOURCE_GROUP=RG-Demo4TDG-CICD REGION_NAME=koreacentral VNET_NAME=aks-vnet SUBNET_NAME=aks-subnet # VNET 생성 az network vnet create \ --resource-group $RESOURCE_GROUP \ --location $REGION_NAME \ --name $VNET_NAME \ --address-prefixes 10.0.0.0/8 \ --subnet-name $SUBNET_NAME \ --subnet-prefixes 10.240.0.0/16 # SUBNET 생성 SUBNET_ID=$(az network vnet subnet show \ --resource-group $RESOURCE_GROUP \ --vnet-name $VNET_NAME \ --name $SUBNET_NAME \ --query id -o tsv) # AKS 생성 (약 3분 소요) az aks create \ --resource-group $RESOURCE_GROUP \ --name $AKS_CLUSTER_NAME \ --vm-set-type VirtualMachineScaleSets \ --node-count 2 \ --load-balancer-sku standard \ --location $REGION_NAME \ --network-plugin azure \ --vnet-subnet-id $SUBNET_ID \ --service-cidr 10.2.0.0/24 \ --dns-service-ip 10.2.0.10 \ --docker-bridge-address 172.17.0.1/16 \ --enable-managed-identity \ --generate-ssh-keys # AKS 자격증명 획득 az aks get-credentials \ --resource-group $RESOURCE_GROUP \ --name $AKS_CLUSTER_NAME # AKS 노드 정보 확인 kubectl get node

 

appmod-demo# kubectl get node NAME STATUS ROLES AGE VERSION aks-nodepool1-18801987-vmss000000 Ready agent 75s v1.22.6 aks-nodepool1-18801987-vmss000001 Ready agent 69s v1.22.6

 

 

2.6 AKS-ACR 통합하기

다음 명령을 수행하여 AKS-ACR을 통합한다.

# ACR - AKS 통합 az aks update -n $AKS_CLUSTER_NAME -g $RESOURCE_GROUP --attach-acr $ACR_NAME

 

appmod-demo# az aks update -n $AKS_CLUSTER_NAME -g $RESOURCE_GROUP --attach-acr $ACR_NAME AAD role propagation done[############################################] 100.0000%{ "aadProfile": null, "addonProfiles": null, "agentPoolProfiles": [ { "availabilityZones": null, "count": 2, <중략> "tags": null, "type": "Microsoft.ContainerService/ManagedClusters", "windowsProfile": { "adminPassword": null, "adminUsername": "azureuser", "enableCsiProxy": true, "licenseType": null } } appmod-demo#

 

이제 "로컬 환경 작업" Issue는 Done으로 이동시키고 "Azure Resource 작업"을 Doing으로 이동시키고 자신에게 Issue를  할당한다.

 

2.7 Modern App 샘플 준비하기

Repos 화면으로 이동하여 Import를 클릭한다.

자신의 git 리포지토리의 git clone URL을 복사하여 붙여 넣고 Import를 클릭한다.

 

성공하면 다음의 메시지가 전시된다.

 

성공적으로 Import한 결과는 다음과 같다.

복제한 리포지토리 내 k8s - deploy-svc.yaml 파일을 열어 각자의 상황에 맞게 이미지 관련 정보 업데이트 후 커밋을 시행한다.

 

2.8 서비스 커넥션 구성하기

AKS, ACR 등에 대한 서비스 커넥션을 구성하기 위해서는 해당 Azure 리소스에 대하여 적절한 권한이 부여되어야 한다. 본 튜토리얼에서는 이미 권한이 할당되어 있는 것으로 간주한다.

관련한 자세한 내용은 서비스 커넥션 관리 를 참조한다.

 

좌측 하단의 Project Settings > Pipelines > Service Connections 를 선택하고 다음 Create  service connection을 클릭한다.

 

docker 라고 키워드를 입력하여 검새 결과 중 Docker Registry를 선택하고 Next를 클릭한다.

 

다음의 순서에 따라 구성하고 Save를 클릭 한다.

  • Registry type : Azure Container Registry 선택

  • Subscription : 해당 구독 선택

  • Azure container registry : 생성 ACR 선택

  • Service connection name : SvcConn4Acr 입력

  • Grant access permission to all pipeliness 선택

 

 

우측 상단의 New service connection을 선택한다.

kuber라고 키워드를 입력하여 검새 결과 중 Kubernetes를 선택하고 Next를 클릭한다.

다음의 순서에 따라 구성하고 Save를 클릭 한다.

  • Registry type : Azure Container Registry 선택

  • Subscription : 해당 구독 선택

  • Azure container registry : 생성 ACR 선택

  • Service connection name : SvcConn4Acr 입력

  • Grant access permission to all pipeliness 선택

 

 

구성이 모두 완료된 결과는 다음과 같다.

 

2.9 CI 파이프라인 구성하기

Pipelines > Pipelines에서 Create pipeline을 선택한다.

Connect 탭 화면에서 Azure Repos Git를 선택한다.

 

Select 탭 화면에서 2023_TDG_AKS_CICD_Demo를 선택한다. 

기본 구성해 둔 azure-pipelines.yml 이 자동으로 로딩 된다.

만약 자동으로 로딩이 되지 않으면 기본 제공되는 파일 내용을 삭제 하고 다음 내용을 복사하여 붙여 넣는다.

# Maven # Build your Java project and run tests with Apache Maven. # Add steps that analyze code, save build artifacts, deploy, and more: # https://docs.microsoft.com/azure/devops/pipelines/languages/java trigger: - main steps: - task: Maven@3 displayName: 'Maven Build' - task: Docker@2 displayName: 'Docker Build' inputs: containerRegistry: 'SvcConn4Acr' repository: 'appmod-demo4btc' command: 'buildAndPush' Dockerfile: 'Dockerfile' tags: | $(Build.BuildId) latest - task: Docker@2 displayName: 'Docker Push' inputs: containerRegistry: 'SvcConn4Acr' repository: 'appmod-demo4btc' command: 'buildAndPush' Dockerfile: 'Dockerfile' tags: | $(Build.BuildId) latest - task: Bash@3 displayName: 'Tag Update' inputs: targetType: 'inline' script: 'sed -i "s/latest/$(Build.BuildId)/g" k8s/deploy-svc.yaml' - task: PublishBuildArtifacts@1 displayName: 'Build Artifact Publish' inputs: PathtoPublish: 'k8s/deploy-svc.yaml' ArtifactName: 'drop' publishLocation: 'Container'

 

서비스 커넥션 정보 및 리포지토리 정보를 각자 상황에 맞게 선택/입력 및 업데이트 하고 Save  한다.

 

Azure 파이프라인 관련 상세 내용 : Azure CI/CD Pipeline 구축 가이드 참조

 

CI 파이프라인 설명

Trigger 

main 브랜치의 코드 변경이 감지되면 CI 파이프라인이 트리거 된다.

trigger: - main

Maven 빌드 

Maven을 통해 애플리케이션을 빌드 한다.

steps: - task: Maven@3 displayName: 'Maven Build'

 

Docker 빌드, 태그 및 푸시 

Maven 빌드의 결과물로(war 또는 jar) Docker 이미지를 빌드, 태그하여 ACR로 푸시를 수행한다.

- task: Docker@2 displayName: 'Docker Build' inputs: containerRegistry: 'SvcConn4Acr' repository: 'appmod-demo4btc' command: 'buildAndPush' Dockerfile: 'Dockerfile' tags: | $(Build.BuildId) latest - task: Docker@2 displayName: 'Docker Push' inputs: containerRegistry: 'SvcConn4Acr' repository: 'appmod-demo4btc' command: 'buildAndPush' Dockerfile: 'Dockerfile' tags: | $(Build.BuildId) latest

 

YAML 파일 태그 정보 업데이트 

Kubernetes 배포를 위한 YAML 파일 내 이미지 태그를 최신 빌드 번호로 업데이트 한다.

- task: Bash@3 displayName: 'Tag Update' inputs: targetType: 'inline' script: 'sed -i "s/latest/$(Build.BuildId)/g" k8s/deploy-svc.yaml'

 

빌드 Artifact 게시

빌드 산출물인 YAML 파일을 drop 디렉토리에 위치 시킨다.

- task: PublishBuildArtifacts@1 displayName: 'Build Artifact Publish' inputs: PathtoPublish: 'k8s/deploy-svc.yaml' ArtifactName: 'drop' publishLocation: 'Container'

 

 

소스의 k8s/deploy-svc.yaml로 이동하여 Edit을 선택하고 image 정보 부분을 각자의 상황에 맞게 수정 후 Commit을 클릭한다.

apiVersion: apps/v1 kind: Deployment metadata: name: zerobigaksdemo spec: replicas: 1 selector: matchLabels: app: zero-aks-app template: metadata: labels: app: zero-aks-app spec: containers: - name: zero-aks-demo image: zeroacrdemo.azurecr.io/appmod-demo4btc:latest //자신의 ACR 정보로 업데이트 한다. ports: - containerPort: 8080 --- apiVersion: v1 kind: Service metadata: name: zero-aks-app spec: ports: - name: http-port port: 80 targetPort: 8080 selector: app: zero-aks-app type: LoadBalancer

 

우측 상단의 Save and run을 클릭한다.

 

Commit 메시지를 입력하고 Commit을 클릭한다.

 

 

CI 파이프라인을 최초 실행하는 경우에는 다음과 같이 리소스 접근에 대한 퍼미션 Confirm을 요구할수도 있다.

 

Permit을 클릭하여 파이프라인을 실행한다.

 

 

 

파이프라인 실행결과를 확인하고 정상이면 1 artifact를 클릭하여 빌드 결과물을 확인한다.

 

deploy-svc.yaml 파일에 Image 정보를 확인하여, ACR에 푸시된 최근 이미지 정보가 맞는지 확인한다.

 

더불어 Azure 포털의 ACR 리포지토리로 이동하여 빌드 이미지의 푸시 여부를 확인한다.

 

2.10 CD 파이프라인 구성하기

Pipelines > Releases에서 New pipeline을 선택한다.

 

Kubernetes 키워드를 입력 후 결과 중 Deploy to a Kubernetes cluster를 선택하여 Apply 한다.

 

Stage 이름을 입력하고 (ex) DEV) 우측 상단에 X를 클릭하여 창을 닫는다.

 

파이프라인 이름을 적당한 이름으로 변경하고 Pipelines 탭의 Add an artifact 을 선택한다.

Source (build pipeline)에서 소스 CI 파이프라인을 선택 후 Add를 클릭한다.

 

Stage 이름 아래  1job, 1task를 클릭한다.

 

kubectl 잡을 선택한다.

 

 

다음의 순서에 따라 구성을 진행한다.

  • Kubernetes service connection : 앞서 구성한 해당 서비스 커넥션을 선택한다.

  • Namespace : default 를 선택한다.

  • Command : apply를 선택한다.

  • Use Configuration files : 체크박스를 선택한다.

  • Configuration file : ... 버튼을 클릭하여 deploy-svc.yaml 파일의 위치를 찾아 선택한다.

 

선택 및 입력한 내용을 Save 하고 Create a release를 클릭한다.

 

파이프라인 실행 결과를 확인한다.

 

 

AKS의 Services and ingresses 블레이드에서 External IP를 확인하여 파이프라인의 배포 결과를 브라우저에서 확인한다.

 

 

2.11 CI/CD 검증하기

CI/CD를 검증하기 위해서는 각각 트리거 설정이 필요하다.

CI의 경우에는 이미 main 브랜치에 대하여 설정이 되어있다.

 

CD에 대한 트리거 설정을 위해 Pipelines > Releases에서 우측 상단 Edit을 선택한다.

 

Artifacts에서 다음 1번을 선택 후 Continuous deployment trigger를 Enabled 신킨 후 우측 상단에 X를 클릭하여 창을 닫는다.

 

우측 상단에 Save 를 선택하여 설정을 저장한다.

 

이제 Repos > Files 화면에서 src/main/java/hello/Application.java 파일에서 메시지를 변경하고 Commit을 수행한다.

  • 기존 : Hello, You are ...

  • 변경 :  Hi, You are ...

 

Pipeline 으로 이동하면 CI 파이프라인이 트리거 되어 실행되는 것을 확인할 수 있다.

 

CI 파이프라인이 정상적으로 종료되면, 바로 CD 파이프라인이 트리거 되어 실행되는 것을 확인할 수 있다.

 

CD 파이프라인이 성공적으로 종료되면 브라우저를 새로고침하여 실행 및 배포 결과를 확인한다.

 

이로서 CI/CD 파아프라인이 정상적으로 구성된 것을 확인할 수 있다.

 

 

3. Backlog 완료하기

 

Boards > Boards로 이동하여 Azure DevOps 작업 Issue를 Done으로 이동하고 모든 Backlog를 완료한다.