GitLab CI를 이용한 CI 구현

박재하·2024년 1월 7일
0

DevOps 기초

목록 보기
6/9

GitLab CI

CI, CD

CI란?

Continuous Integration. 지속적인 통합이라는 의미.

새로운 코드 변경 사항이 정기적+자동으로 빌드 및 테스트되어 공유 레포지토리에 통합되는 것을 의미함.
다수의 개발자들이 형상관리 툴을 관리할때 주로 사용되며, 새로운 코드의 빌드, 테스트, 병합(merge)하는 기능이 포함됨.

CD란?

Continuous Delivery 또는 Continuous Deployment. 지속적인 제공 또는 지속적인 배포라는 의미.

CI에서 빌드/테스트/병합된 코드가 배포를 함에 있어 문제가 없는지 검증한 후 배포를 수동적으로 진행하는 것이 Continuous Delivery, 배포 과정까지 자동으로 진행하는 것이 Continuous Deployment이다.

GitLab CI/CD란?

GitLab CI/CD는 애플리케이션 구축, 테스트 및 배포 프로세스를 자동화하는 GitLab의 기본 제공 기능임.

문법은 다소 다르지만 GitHub Actions와 동작 방식은 유사하다고 볼 수 있겠다(YAML 파일에 정의된 파이프라인대로 단계별 작업 실행)

스크린샷 2024-01-05 오전 12 20 49

주요 기능과 동작 방식은 위 그림과 같으며, 관련된 주요 개념은 다음과 같음.

  • 구성(Configuration) : Git 리포지토리의 루트 디레토리에 저장된 .gitlab-ci.yml이라는 YAML 파일을 사용하여 환경 설정을 할 수 있음. 빌드, 테스트 및 배포 프로세스를 설명하는 다양한 작업, 단계 및 규칙을 정의함.
  • 파이프라인(Pipeline) : 커밋이 Git 리포지토리로 푸시되거나 병합 요청이 생성되면 GitLab CI/CD가 자동으로 파이프라인을 트리거함. 파이프라인은 .gitlab-ci.yml에 정의된 대로 실행됨.
  • 작업(Jobs) : 파이프라인 내의 개별 작업 단위. 각 작업은 .gitlab-ci.yml에 정의되어 있음.
  • 단계(Stage) : 빌드, 테스트 및 배포와 같은 파이프라인의 여러 단계. 동일한 스테이지 내의 작업은 병렬로 실행되며, 스테이지는 순차적으로 실행됨. 구조화된 방식으로 파이프라인을 구성하고 시각화하는 가독성 측면에서도 도움됨.

GitLab에 리포지토리 만들기

스크린샷 2024-01-07 오후 4 55 21

GitLab 가입하고 kube-test라는 이름으로 프로젝트를 하나 만들었다.

스크린샷 2024-01-09 오후 3 03 45

로그를 잘 읽는게 참 중요한 것 같다.. 조금 삽질하다 여길 보니 비번 설정이나 토큰을 만들어야 HTTPS로 push 가능하댄다.

스크린샷 2024-01-09 오후 3 04 49

설정하고 다시 로그인, email verification까지 거치면 재접속할 수 있다.

GitLab 리포지토리 remote로 등록

스크린샷 2024-01-09 오후 3 29 33

몇 번 테스트하다보니 주소 https://gitlab.com/kube-test/kube-test.git으로 github 리포지토리처럼 remote를 등록하면 접속할 수 있겠더라.

clone을 받아오고 코드를 복붙해서 push 되지만 이미 만든 GitHub 프로젝트에 remote만 추가로 등록해서 push하는 방법으로 해보기로 했다.

git remote add gitlab https://gitlab.com/kube-test/kube-test.git
git push gitlab [브랜치명]
스크린샷 2024-01-09 오후 3 27 03

되겠다!

스크린샷 2024-01-09 오후 3 27 39

참고로 최초 등록 후 접근하면 위와 같이 계정정보를 물어본다. username에는 GitLab 가입시의 email, password에는 위에서 설정한 패스워드를 입력해주면 됨.

스크린샷 2024-01-09 오후 3 33 55

결과는 대 성 공. GitLab CI를 트리거하기 위해 아직은 develop에다 넣지 말자

GitLab CI YAML 파일 작성 준비

이제 .gitlab-ci.yml 파일을 만들어 다음 작업을 하는 job을 만들어야 한다.

  1. 트리거 조건 : develop branch에 commit/merge
  2. docker image build
  3. build된 docker image를 AWS 본인 계정 ECR에 push로 업로드

그러려면 우선 ECR(Amazon Elastic Container Registry)을 AWS에 만들어 둬야 한다.

ECR 리포지토리 생성

AWS에서 Elastic Container Registry를 검색해서 들어가면 Amazon ECR -> 프라이빗 레지스트리에서 새로운 리포지토리를 생성할 수 있다.

스크린샷 2024-01-09 오후 3 55 03

프라이빗으로, default 설정대로 리포지토리 이름만 kube-test로 지었다.

스크린샷 2024-01-09 오후 3 55 17

잘 생성됨.

스크린샷 2024-01-09 오후 3 55 27

리포지토리 상세 페이지로 들어가면 docker push 명령을 실행하기 위한 방법이 나온다.

스크린샷 2024-01-09 오후 4 55 20 스크린샷 2024-01-09 오후 4 56 24

AWS CLI에서 1번 명령을 입력하면 /home/cloudshell-user/.docker/config.json에서 auth값을 확인할 수 있음. 잘 된다!

IAM 생성, ECR 액세스 권한 부여

원래 로컬에 awscli를 brew install awscli로 설치하고, IAM 계정에 ECR 권한 부여하고, 액세스 키 발급받아서 하는게 맞는 것 같지만 우리는 GitLab CI로 접근할거니 권한부여/액세스키 발급만 해보자.

스크린샷 2024-01-10 오후 3 41 25

IAM -> 사용자로 가면 새로운 사용자를 생성할 수 있다. kube-test-user로 새로운 사용자를 생성하자.

스크린샷 2024-01-10 오후 3 44 02

직접 정책 연결 선택 후 AmazonEC2ContainerRegistryPowerUser 정책을 추가해준다.

생성된 IAM 사용자에 대한 액세스 키 생성

스크린샷 2024-01-10 오후 3 47 39

IAM 사용자를 생성하면 리스트에 표시된다.

스크린샷 2024-01-10 오후 3 48 02

상세페이지에 들어가면 액세스 키를 조회하고 생성할 수 있는 영역이 있음. 만들자.

스크린샷 2024-01-10 오후 3 49 16

여기서는 기타 선택해서 조건없이 만들어보자.

스크린샷 2024-01-10 오후 3 50 30

적당히 이름을 지으면

스크린샷 2024-01-10 오후 3 52 34

액세스 키비밀 액세스 키를 획득할 수 있다! 이제 이걸 이용하면 됨.

GitLab 프로젝트에 AWS IAM 관련 Variables 등록

다시 GitLab으로 돌아와서, 위에서 만든 액세스 키 등을 Variable로 등록해주자.

스크린샷 2024-01-10 오후 3 58 58

만들어둔 프로젝트 페이지에서 Settings -> CI/CD 선택

스크린샷 2024-01-10 오후 3 59 21

Variables Expend하고 Add variable 선택

스크린샷 2024-01-10 오후 4 02 31 스크린샷 2024-01-10 오후 4 03 06

AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY를 키로 Value에 AWS에서 할당받은 값을 입력해 Variable을 생성한다.

스크린샷 2024-01-10 오후 4 03 34

잘 생성됐고, 이제 .gitlab-ci.yml에서 이 변수들을 사용해 ECR push job을 만들어주면 된다.

.gitlab-ci.yml 파일 작성

대망의 YAML 파일 작성. 다음 작업을 하는 job을 만들어야 한다.

  1. 트리거 조건 : develop branch에 commit/merge
  2. docker image build
  3. build된 docker image를 AWS 본인 계정 ECR에 push로 업로드

GPT의 도움을 좀 받아봤다.

develop branch에 commit 또는 merge 할 경우 프로젝트에 있는 Dockerfile을 이용해서 docker build해서 aws ecr에 push하는 gitlab ci yaml파일을 작성해줘. buid와 push를 stage로 나누자.

stages:
  - build_and_push

variables:
  # AWS ECR 설정
  AWS_REGION: "your-aws-region"
  ECR_REPO: "your-ecr-repo"
  AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
  AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY

  # Docker 설정
  DOCKER_IMAGE_NAME: "your-docker-image-name"
  DOCKERFILE_PATH: "path/to/Dockerfile"
  CONTAINER_REGISTRY: "your-container-registry"

build_and_push:
  stage: build_and_push
  script:
    - echo "Building Docker image..."
    - docker build -t $DOCKER_IMAGE_NAME -f $DOCKERFILE_PATH .
    - echo "Logging in to the container registry..."
    - echo "$AWS_SECRET_ACCESS_KEY" | docker login -u "$AWS_ACCESS_KEY_ID" --password-stdin $CONTAINER_REGISTRY
    - echo "Tagging Docker image..."
    - docker tag $DOCKER_IMAGE_NAME $CONTAINER_REGISTRY/$ECR_REPO/$DOCKER_IMAGE_NAME
    - echo "Pushing Docker image to ECR..."
    - docker push $CONTAINER_REGISTRY/$ECR_REPO/$DOCKER_IMAGE_NAME
  only:
    - develop

역시 최고! 우리 프로젝트에 맞게 적당히 수정해준다.

스크린샷 2024-01-10 오후 4 20 29

처음 만들때 대체 왜 시드니로 만들었는지 모르겠지만,, 시드니니까 리전(AWS_REGION)은 ap-southeast-2
ECR_REPO는 ECR에서 지은 이름 kube-test
CONTAINER_REGISTRY에는 만들어둔 ECR URI값 461338739533.dkr.ecr.ap-southeast-2.amazonaws.com/kube-test

도커 파일 경로는 현재 폴더에 Dockerfile이면 생략해도 되니까 빼자.
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY도 프로젝트 세팅에서 variables로 넣어줘서 따로 선언을 안해도 됨.

최종 완성된 코드는 다음과 같다.

stages:
  - build_and_push

variables:
  # Docker 설정
  DOCKER_HOST: tcp://docker:2375
  DOCKER_DRIVER: overlay2
  DOCKER_TLS_CERTDIR: ''

  # Docker 이미지 설정
  DOCKER_IMAGE_NAME: kube-test
  DOCKER_REGISTRY: 461338739533.dkr.ecr.ap-southeast-2.amazonaws.com

build_and_push:
  stage: build_and_push
  image: docker:latest
  services:
    - docker:19-dind
  before_script:
    - echo "Logging in to the container registry..."
    - apk add --no-cache curl jq python3 py3-pip
    - python3 -m venv venv
    - chmod +x ./venv/bin/activate
    - . ./venv/bin/activate
    - pip install awscli --no-build-isolation
    - aws ecr get-login-password | docker login --username AWS --password-stdin $DOCKER_REGISTRY
    - aws --version
    - docker info
    - docker --version
  script:
    - echo "Building Docker image..."
    - docker build -t $DOCKER_IMAGE_NAME .
    - echo "Tagging Docker image..."
    - docker tag $DOCKER_IMAGE_NAME $DOCKER_REGISTRY/$DOCKER_IMAGE_NAME:$CI_PIPELINE_IID
    - echo "Pushing Docker image to ECR..."
    - docker push $DOCKER_REGISTRY/$DOCKER_IMAGE_NAME:$CI_PIPELINE_IID
  only:
    - develop

이제 develop branch로 push해주면 끝!

git switch develop
git reset [gitlab-ci 작성한 브랜치]
git push gitlab develop

트러블 슈팅 1: 이미지 미설정

스크린샷 2024-01-10 오후 4 32 17

develop push는 잘 됐는데

스크린샷 2024-01-10 오후 4 32 51

job에서 에러 뜸

스크린샷 2024-01-10 오후 4 30 00

들어가서 로그 보니 docker 커맨드가 미설치. 도커 이미지를 따로 지정해줘야 했다. 위 최종 코드에는 반영되어 있지만 image:속성으로 지정해줄 수 있음.

docker:dind도 서비스로 지정해줘야 한다고 함.

build_and_push:
  stage: build_and_push
  image: docker:latest
  services:
    - docker:19-dind
  ...

이렇게

트러블 슈팅 2: awscli 설치 오류

스크린샷 2024-01-11 오전 11 18 24

학습메모 3 등을 참고하면 pip를 통해 awscli를 설치해 사용하는데, 여기서 에러가 떴다.

여기저기 자료조사도 하고 시행착오를 많이 겪은 끝에, 위 그림에서 나와있는 것 처럼 venv로 가상환경을 activate을 한 후 pip를 사용하되, --no-build-isolation옵션을 줘야한다고 한다.

학습메모 4 참고.


build_and_push:
  ...
  before_script:
    - echo "Logging in to the container registry..."
    - apk add --no-cache curl jq python3 py3-pip
    - python3 -m venv venv
    - chmod +x ./venv/bin/activate
    - . ./venv/bin/activate
    - pip install awscli --no-build-isolation

이렇게

트러블 슈팅 3: aws 로그인 오류

스크린샷 2024-01-11 오전 11 26 43

이제 설치는 잘 됐는데, credentials이 안잡혀서 로그인이 안된다고 한다. variables 등록하면 되는거아님?

이것저것 찾아보니(학습메모 5) variable 등록 시 protected branch가 아니면 기본적으로 variable을 사용하지 않는다고 한다. 무조건 사용해주도록 하려면 protected 옵션을 꺼줘야 함. expanded 옵션은 당장 쓸 일은 없어보이지만 일단 체크해줌.

또한 마찬가지로 리전 설정 없이 Default로 Region을 지정하는 AWS_DEFAULT_REGION 환경변수도 있어서 ap-southeast-2로 설정해줬다.

스크린샷 2024-01-11 오전 11 28 34

최종적으로 project variables 설정은 위와 같이 변경됨. (기존엔 프로젝트 그룹의 variables로 설정했었는데, 프로젝트의 variables로 바꿈. 지금은 프로젝트 하나라 큰 의미 없는듯)

트러블 슈팅 4: nest not found

스크린샷 2024-01-11 오전 11 03 53

빌드 환경에 nest cli가 설치되어 있지 않아 발생한 문제로 보였다.

@nestjs/cli를 글로벌로 사용하고 있었는데, dev 의존성에 추가해서 npm install을 하고 npm run build를 실행해주도록 Dockerfile을 변경했다.

npm install @nestjs/cli
FROM node:20-alpine AS builder

WORKDIR /app

# npm install 추가
COPY . /app
RUN cd /app && \
    npm install && \ 
    npm run build

FROM node:20-alpine AS app

WORKDIR /app

USER node

COPY --chown=node:node --from=builder /app/dist /app/dist
COPY --chown=node:node --from=builder /app/node_modules /app/node_modules

RUN cd /app

EXPOSE 3000

CMD ["node", "dist/main"]

트러블 슈팅 5: docker tag 오류

스크린샷 2024-01-11 오전 11 16 11

이번엔 뭐가 문젠가.. 하다가 로컬에서 직접 테스트를 해보는 과정에서

스크린샷 2024-01-11 오전 11 37 37

태그를 리포지토리명까지로 해야 하는데 [URI]/kube-test/kube-test:[버전] 이런식으로 이미지명과 리포지토리명을 둘 다 지정해서 생긴 문제였다.

[URI]/kube-test:[버전]으로 변경해서 해결.

드디어 완성

스크린샷 2024-01-11 오전 11 40 37

엄청난 시행착오 끝에 성공한 .gitlab-ci.yml은, 다시 한 번 옮겨보면 다음과 같다.

stages:
  - build_and_push

variables:
  # Docker 설정
  DOCKER_HOST: tcp://docker:2375
  DOCKER_DRIVER: overlay2
  DOCKER_TLS_CERTDIR: ''

  # Docker 이미지 설정
  DOCKER_IMAGE_NAME: kube-test
  DOCKER_REGISTRY: 461338739533.dkr.ecr.ap-southeast-2.amazonaws.com

build_and_push:
  stage: build_and_push
  image: docker:latest
  services:
    - docker:19-dind
  before_script:
    - echo "Logging in to the container registry..."
    - apk add --no-cache curl jq python3 py3-pip
    - python3 -m venv venv
    - chmod +x ./venv/bin/activate
    - . ./venv/bin/activate
    - pip install awscli --no-build-isolation
    - aws ecr get-login-password | docker login --username AWS --password-stdin $DOCKER_REGISTRY
    - aws --version
    - docker info
    - docker --version
  script:
    - echo "Building Docker image..."
    - docker build -t $DOCKER_IMAGE_NAME .
    - echo "Tagging Docker image..."
    - docker tag $DOCKER_IMAGE_NAME $DOCKER_REGISTRY/$DOCKER_IMAGE_NAME:$CI_PIPELINE_IID
    - echo "Pushing Docker image to ECR..."
    - docker push $DOCKER_REGISTRY/$DOCKER_IMAGE_NAME:$CI_PIPELINE_IID
  only:
    - develop
스크린샷 2024-01-11 오전 11 42 02 스크린샷 2024-01-11 오전 11 41 55

성공성공

스크린샷 2024-01-11 오전 11 42 50

성공! ECR에 잘 들어가죠?

학습메모

  1. gitlab push
  2. AWS CLI 설치 & 등록 방법
  3. AWS ECR push 방법
  4. gitlab ci에서 awscli 설치 오류 해결
  5. gitlab ci with AWS
profile
해커 출신 개발자

0개의 댓글