지금까지 진행했던 실습들을 정리해보면,
Kubernetes 환경에서는 모든 설정 정보를 매니페스트 파일(ex .yaml)로 정의해왔다.
이번 포스팅에선 앞선 실습에서 YAML 파일로 생성했던 모든 설정을 코드로 관리하여
CI/CD를 구현하려고 한다.
구현하기에 앞서 CI/CD라는 개념을 정리해보자.
현재 인프라를 관리하고 운영하는 데 있어 가장 많이 접하는 단어는 아마 IaC, CD/CD일 것이다.
CI(Continuous Integration)/CD(Continuous Delivery 혹은 Deployment)는 말 그대로
'지속적인 통합/지속적인 배포' 를 의미한다.
그럼 무엇을 통합하고 무엇을 배포한다는 뜻일까?
아래 그림은 CI/CD를 설명할 때 가장 쉽게 볼 수 있는 그림이다.
그림을 살펴보면,
소스코드 작성, 빌드, 테스트 -> 릴리즈, 배포, 운영, 모니터링 과정이 계속해서 이루어진다.
애플리케이션을 개발하고 운영하는 단계에서 소스코드는 계속해서 추가, 수정, 통합, 배포될 것이다.
이럴 때마다 위의 단계를 수작업으로 거쳐야 한다면 아마 많은 인적 자원과 시간이 필요할 것이다.
CI/CD는 이러한 애플리케이션 개발 단계를 자동화함으로써 짧은 주기로, 그리고 지속적으로 사용자에게
서비스를 제공할 수 있다.
좀 더 자세하게 알아보자.
먼저, CI는 지속적 통합이다.
여기서 지속적 통합은 새롭게 변경된 코드가 정기적으로 빌드, 테스트 되고 공유 레포지토리(대표적으로 Git)에 통합되는 것을 의미한다.
애플리케이션 운영 단계에서 새로운 기능이 추가된다면 아마 commit을 통해 Git 레포지토리에 업데이트될 것이다.
만약 다수의 개발자가 한 팀을 이룬다면 이 레포지토리엔 수많은 commit이 쌓이게 되고,
그럴 때마다 누군가가 코드를 빌드하고, 테스트하고, 통합한다면 굉장히 번거로운 작업이 될 것이다.
이러한 상황에서, 자동화된 Build&Test는 메인 소스코드의 충돌 등을 방어하는 데 큰 도움을 준다.
또한 이 자동화 작업은 MSA(Micro Service Architecture) 환경에서도 큰 이점이 있다.
MSA는 보통 모놀리식 방식과 비교되는데,
모놀리식은 여러 서비스, 기능이 모여 하나의 애플리케이션을 이루는 구성이라면
MSA는 작은 기능 별로 서비스를 잘게 쪼개어 개발하는 형태를 의미한다.
MSA의 대표적인 예로 AWS 서비스를 예로 들 수 있다.
MSA는 보통 애자일한 방법론이 적용되기 때문에 기능 추가가 빈번하게 발생하게 된다.
작은 micro service들 간의 긴밀한 동작 테스트도 중요해지는데 이러한 상황에서
CI를 적용하면 기능 충돌 방지 등의 이점을 확보할 수 있다.
CD와 관련된 내용은 아래 실습을 진행하면서 자세하게 살펴보도록 하자.실습을 진행하기에 앞서 전체 흐름을 파악할 수 있도록 간소화 된 파이프라인을 구축해보자.먼저 애플리케이션 소스 코드를 수정하고 CodeCommit 서비스에서 제공하는 레포지토리에 push(1) 하면,파이프라인이 자동으로 동작(2)한다.그럼 애플리케이션 빌드(3)를 실시하게 되고 컨테이너 이미지를 생성하여 ECR에 이미지를 푸시(4)한다.마지막으로 이 ECR의 컨테이너 이미지를 EKS에 자동으로 배포(5)되는 것이 CI/CD의 목표이다.
CI/CD에 필요한 리소스 생성
CI/CD 환경을 구성하기 위해 먼저 필요한 리소스를 생성한다.
여기엔 Region 설정부터 CodeCommit Repository, S3 등의 리소스를 포함한다.
Parameters:
# 실행 대상 리전
Region:
Type: String
Default: "us-west-2"
Description: Which region do you want to exeute pipeline.
...
...
yaml 파일을 통해 CloudFormation 스택을 생성해준다.
EKS 클러스터 액세스 권한에 CodeBuild의 IAM 역할 추가
이제 EKS 클러스터 액세스 권한에 CodeBuild의 IAM 역할을 추가한다.
이번에 구축할 파이프라인에서는 CodePipeline의 CodeBuild 프로젝트 안에서 EKS 클러스터에 매니페스트를 적용한다.
그러려면 CodeBuild가 kubectl 명령을 사용하여 설정할 수 있도록 kubectl 명령어의 인증 정보를 생성해야 한다.
인증 정보 설정은 아래와 같다.
$ eksctl create iamidentitymapping \
> --region us-west-2 \
> --username codebuild \
> --group system:masters \
> --cluster eks-work-cluster \
> --arn [CodeBuild가 사용하는 IAM 역할의 ARN]
ARN 값은 앞서 생성한 스택의 [출력] 탭에서 확인할 수 있다.
위 명령어를 입력하면 아래와 같은 결과값을 얻을 수 있다.
EKS 인증은 IAM과 통합되어 있다.
즉 CodeBuild가 사용하는 iam 역할의 ARN을 EKS 클러스터에 추가하는 형태이다.
2021-09-07 23:24:29 [ℹ] eksctl version 0.61.0
2021-09-07 23:24:29 [ℹ] using region us-west-2
2021-09-07 23:24:31 [ℹ] adding identity "ARN 값" to auth ConfigMap
예제 소스 코드를 AWS CodeCommit에 푸시하도록 설정
그 다음으로 예제 소스 코드를 AWS CodeCommit에 푸시하도록 설정하는 과정이다.
먼저 로컬 환경에 클론한 예제 애플리케이션 코드 전체를 CodeCommit에 생성한 Repository에 푸시한다.
방법은 다음과 같다.
1. CodeCommit용 깃 인증 정보를 생성한다.
-> CodeCommit에 Repository를 푸시하기 위해선 전용 깃 인증 정보가 필요하기 때문이다.
IAM 서비스에서 [사용자 추가] 후 [AWSCodeCommitPowerUser] 정책을 연결해준다.
사용자 생성 후 '.csv 다운로드' 를 클릭하여 '액세스 키 ID'와 '비밀 액세스 키' 정보를 저장한다.
사용자가 생성되면 [보안 자격 증명] 탭에서 Git 자격 증명을 생성해준다.
이 또한 '자격 증명 다운로드'를 클릭하여 파일을 저장해준다.
이 값들은 나중에 예제 소스 코드를 CodeCommit repository에 푸시할 때 사용할 사용자 이름, 패스워스이다.
2. 예제 소스 코드 repository 내부 git 설정을 CodeCommit 용으로 변경한다.
예제 소스 파일의 루트 디렉토리(k8s-aws-book) 내부에서 다음 명령어를 통해 리포지토리 푸시 대상을
생성한 CodeCommit Repository로 변경한다.
URL 값은 eks-book-sample-ap-slack의 'YourCodeCommitRepositoryUrl' 항목에서 확인할 수 있다.
mzmz01:~/environment/k8s-aws-book (master) $ git remote rename origin upstream
mzmz01:~/environment/k8s-aws-book (master) $ git remote add origin <CodeCommitRepositoryUrl값>
애플리케이션 수정
이제 테스트를 위해 애플리케이션을 조금 수정해보자.
이번 실습에선 '전국 관광지 명소 정보'의 모든 지역 앞에 "*"를 붙이기로 한다.
아래는 현재 애플리케이션에서 표시되는 정보이다.
소스코드의 경로는 아래와 같다.
mzmz01:~/environment/k8s-aws-book/backend-app/src/main/java/k8sbook/sampleapp/presentation/dto (master) $ pwd
/home/ec2-user/environment/k8s-aws-book/backend-app/src/main/java/k8sbook/sampleapp/presentation/dto
RegionDto.java 파일에서 this.regionName 부분을 아래와 같이 수정해준다.
이렇게 수정하면 모든 지역의 이름 앞에 "*"을 붙게 된다.
mzmz01:~/environment/k8s-aws-book/backend-app/src/main/java/k8sbook/sampleapp/presentation/dto (master) $ cat RegionDto.java | grep this.regionName
this.regionName = "*" + region.getRegionName();
this.regionName = regionName;
수정이 끝난 후엔 애플리케이션 버전 번호를 변경한다.
build.gradle 파일을 변경해야 하고 경로는 아래와 같다.
mzmz01:~/environment/k8s-aws-book/backend-app (master) $ pwd
/home/ec2-user/environment/k8s-aws-book/backend-app
기존 1.0.0 버전을 1.0.1로 변경한다.
mzmz01:~/environment/k8s-aws-book/backend-app (master) $ cat build.gradle | grep "version = '1.0.1'"
version = '1.0.1'
매니페스트 수정
이제 ECR의 URI와 버전 번호를 업데이트하도록 매니페스트 파일을 수정해야 한다.
앞서 설계했던 파이프라인은 아래 과정을 거친다.
1. 애플리케이션 빌드
2. 도커 이미지를 생성하고 ECR에 푸시
3. EKS 클러스터에 매니페스트 적용
4. 새로운 도커 이미지를 ECR에 풀하여 애플리케이션 배포
이를 구현하기 위해 cicd 하위 경로의 kustomization.yaml 파일을 수정한다.
기존 파일의 내용은 아래와 같다.
mzmz01:~/environment/k8s-aws-book/cicd/kustomization/prod (master) $ cat kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../base # 기반이 되는 매니페스트 장소
images:
- name: backend-app-image # 여기는 바꾸지 않음
newTag: x.x.x # 애플리케이션 버전 번호
newName: <Your_registry_URI> # ECR 레지스트리 UR
이제 .images.newTag와 .images.newName의 값을 수정해준다.
images:
- name: backend-app-image # 여기는 바꾸지 않음
newTag: 1.0.1 # 애플리케이션 버전 번호
newName: <ecr의 k8sbook/backend-app URI 값> # ECR 레지스트리 URI
CodeCommit에 푸시
수정이 끝났다면 이제 Repository에 푸시하는 과정만 남았다.
변경 내용을 커밋하고 CodeCommit Repository에 푸시한다.
# 인증 정보를 물어보면 CodeCommit용 깃 인증 정보를 입력해주면 된다.
mzmz01:~/environment/k8s-aws-book (master) $ git add *
mzmz01:~/environment/k8s-aws-book (master) $ git commit -m "Test Commit"
mzmz01:~/environment/k8s-aws-book (master) $ git push origin master
자동으로 EKS에 배포되는 것을 확인하기
CodeCommit에 푸시된 것을 트리거로 하여 CodePipeline이 자동으로 실행되고,
EKS 클러스터에 최신 애플리케이션이 배포된다.
실습 도중 아래와 같은 에러가 발생할 수 있다.
에러가 발생하면 CodeBuild로 가서 상세 설명을 확인해보자.
아래 내용을 보면 docker 빌드 중에 에러가 발생한 것 같다.
지금까지 build/libs 경로의 backend-app-1.0.0.jar 파일을 사용했는데 VERSION_NO와 관련된 에러인 걸 보니
애플리케이션 버전은 1.0.1로 변경했지만 JAR 파일은 1.0.0 버전으로 돼있어서 오류가 난 것 같다.
아래와 같이 1.0.0을 1.0.1로 변경한 후 CodePipeline으로 돌아와서 재시도를 클릭해보자.
mzmz01:~/environment/k8s-aws-book/backend-app/build/libs (master) $ mv backend-app-1.0.0.jar backend-app-1.0.1.jar
다행히 오류가 발생하지 않고 다음 작업으로 넘어갔다.
변경된 애플리케이션 확인
앞서 살펴보았던 파이프라인대로 작업이 완료됐고, 변경된 애플리케이션이 EKS에 자동 배포됐을 것이다.
먼저 pod를 살펴보면 새롭게 생성된 것을 확인할 수 있다.
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
backend-app-f4db645b8-8ggs4 1/1 Running 0 8m58s
backend-app-f4db645b8-d4vx6 1/1 Running 0 5m7s
pod의 Image 정보를 확인해보자.
1.0.0에서 1.0.1로 변경된 것을 확인한다.
$ kubectl describe pod | grep Image:
Image: 371156277055.dkr.ecr.us-west-2.amazonaws.com/k8sbook/backend-app:1.0.1
Image: 371156277055.dkr.ecr.us-west-2.amazonaws.com/k8sbook/backend-app:1.0.1
이제 Frontend URL에 다시 접속해보면 모든 지역 앞에 "*"가 붙은 것을 확인할 수 있다.
이것으로 AWS CodePipeline을 사용한 EKS CI/CD 구현을 마치도록 한다.
'CICD' 카테고리의 다른 글
CI/CD with Jenkins&ArgoCD (0) | 2022.05.03 |
---|---|
Argo CD (0) | 2021.10.13 |