Skip to main content
Views 9

생성형 AI 도구를 활용하여 작성 및 편집된 노트입니다.

Grafana GitHub OAuth 연동으로 사내 로그인 깔끔하게 정리하기

Summary

이 노트는 아래 출처를 AI로 재구성한 것입니다. 원문 방문을 권장합니다.

원문 출처: https://velog.io/@xgro/OAuth-GitHub-Grafana

GitLab CI/CD로 AWS ECR·EKS 배포 자동화 구축하는 실전 가이드

Spring Boot 애플리케이션을 GitLab CI/CD로 자동 빌드하고, AWS ECR에 이미지를 푸시한 뒤, EKS에까지 자동 배포되게 만들면 더 이상 서버에 접속해서 git pull 하고, jar 돌리고, 컨테이너 재시작하는 수고를 하지 않아도 됩니다.

여기서는 GitLab에서 .gitlab-ci.yml 하나로

  1. Maven 빌드로 JAR 생성,

  2. Docker 이미지 빌드 후 ECR 푸시,

  3. GitLab Agent를 통한 EKS 배포
    이 세 단계를 순서대로 구성하는 전체 흐름을 처음부터 끝까지 정리합니다.

중간에 나오는 코드와 명령어만 잘 따라가면, GitLab에서 파이프라인 한 번 돌려서 "코드 푸시 → 도커 이미지 생성 → 쿠버네티스 배포"까지 한 번에 자동화할 수 있습니다.

GitLab CI/CD 준비: Runner와 .gitlab-ci.yml 기본 세팅

GitLab에서 CI/CD를 쓰려면 가장 먼저 확인해야 할 것이 Runner입니다.

프로젝트의 Settings > CI/CD 메뉴로 들어가면 Runner 설정 영역이 보이는데, 여기에서 사용할 Runner가 등록되어 있어야 파이프라인이 실제로 실행됩니다.

Runner는 로컬 머신이든, 서버든 어디든 설치가 가능하고, 설치 후에는 GitLab의 그룹 또는 프로젝트 단위로 Runner를 등록합니다.

Runner가 준비되면, 이제 파이프라인 정의를 위한 .gitlab-ci.yml 파일이 필요합니다.

이 파일은 반드시 레포지토리 최상단 경로에 하나 있어야 합니다.

GitLab의 CI/CD > Editor 메뉴에 들어가면 기본 템플릿으로 .gitlab-ci.yml을 자동 생성해 주기도 하고, 만약 이 파일의 위치를 바꾸고 싶다면 Settings > CI/CD > General pipelines에서 경로를 수정할 수 있습니다.

.gitlab-ci.yml 하나에 앞으로 사용할 모든 단계, 예를 들어 package, docker_build, deploy 같은 스테이지와 각 Job의 스크립트를 순서대로 정의하게 됩니다.

Maven으로 Spring Boot JAR 빌드: package 스테이지 만들기

Spring Boot 애플리케이션이라면, 배포 전에 보통 jar 파일을 먼저 빌드하게 됩니다.

이 글의 예시는 Maven 기반이기 때문에 Maven으로 빌드하는 방식만 다룹니다. Gradle 프로젝트라면 image, script 부분만 Gradle 명령어에 맞게 바꿔 쓰면 됩니다.

기본적인 .gitlab-ci.yml의 첫 버전은 다음 흐름을 가집니다.

먼저 스테이지를 선언합니다.

stages:
  - package

이제 package Job을 정의합니다.

package:
  image: adoptopenjdk/maven-openjdk11
  stage: package
  script:
    - 'mvn -B package --file pom.xml'
  artifacts:
    paths:
      - target/*.jar
  only:
    variables:
      - $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

여기서 image는 빌드를 실행할 도커 환경입니다.

script에는 Maven 빌드 명령을 적고, 빌드 결과인 target/*.jarartifacts에 등록해 두면 다음 스테이지에서 이 파일을 그대로 사용할 수 있습니다.

only 조건을 통해 "기본 브랜치에 커밋될 때만 이 Job을 실행"하도록 제한합니다.

이렇게 해 두면, 실험용 브랜치에서는 불필요한 CI 비용이 발생하지 않고, 실제 배포 라인에서만 파이프라인이 돌아가게 됩니다.

Docker 이미지 빌드 후 AWS ECR에 푸시하기

이제 package 스테이지에서 생성한 JAR 파일을 기반으로 Docker 이미지를 만들고, AWS ECR에 푸시하는 단계가 필요합니다.

기본 도커 레지스트리를 쓴다면 GitLab에서 제공하는 로그인 방식
docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
를 그대로 활용하면 되지만, 여기서는 AWS ECR을 사용하는 흐름에 집중합니다.

먼저, 레포지토리 최상단에 Dockerfile이 있어야 합니다.

예를 들어, 이런 구조의 Dockerfile을 사용할 수 있습니다.

FROM adoptopenjdk:11-jre-openj9
ADD /target/[파일명].jar [파일명].jar
ADD [설정파일경로].yml application.yml
ENV JAVA_OPTS=""
ENTRYPOINT ["java","-jar","-Duser.timezone=Asia/Seoul","/[파일명].jar","--spring.profiles.active=default"]
EXPOSE 8281

빌드 시점에 target 폴더에 JAR가 있으므로, 이를 컨테이너 안으로 복사해 실행하는 방식입니다.

AWS ECR에 접근하기 위해서는 IAM에서 Access Key를 하나 발급 받아야 합니다.

IAM > Access Management > Users > Security Credentials에서 Access Key를 생성하고, GitLab의 Settings > CI/CD > VariablesAWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY라는 이름으로 저장합니다.

이 값들은 반드시 Masked 옵션을 켜서 로그에 그대로 노출되지 않도록 하고, 필요에 따라 Protected 여부를 조정합니다. 예를 들어 feature 브랜치에서도 테스트용으로 CI를 돌려야 한다면 Protected는 끄는 편이 편합니다.

이제 .gitlab-ci.yml에 Docker 빌드와 ECR 푸시 스테이지를 추가합니다.

variables:
  DOCKER_REGISTRY: 000000000000.dkr.ecr.ap-northeast-2.amazonaws.com
  AWS_DEFAULT_REGION: ap-northeast-2
  APP_NAME: [app-name]
  DOCKER_HOST: tcp://docker:2375
  DOCKER_DRIVER: overlay2
  DOCKER_TLS_CERTDIR: ""

DOCKER_REGISTRY는 ECR 주소, AWS_DEFAULT_REGION은 ECR 리전, APP_NAME은 레지스트리에서 사용할 이미지 이름입니다.

DOCKER_HOST, DOCKER_DRIVER, DOCKER_TLS_CERTDIR는 GitLab에서 Docker-in-Docker(dind)를 사용할 때 기본적으로 필요한 설정입니다.

이 값을 빼먹으면 "Cannot connect to the Docker daemon at tcp://docker:2375" 같은 오류를 만나게 됩니다.

Docker 빌드 Job은 다음과 같은 형태가 됩니다.

stages:
  - package
  - build

docker_build:
  image: docker:latest
  stage: build
  services:
    - docker:19-dind
  before_script:
    - apk add --no-cache curl jq python3 py3-pip
    - pip install awscli
    - aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $DOCKER_REGISTRY
  script:
    - docker build -t $DOCKER_REGISTRY/$APP_NAME:$CI_PIPELINE_IID -t $DOCKER_REGISTRY/$APP_NAME:latest .
    - docker push $DOCKER_REGISTRY/$APP_NAME:$CI_PIPELINE_IID
    - docker push $DOCKER_REGISTRY/$APP_NAME:latest
  only:
    variables:
      - $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

servicesdocker:19-dind는 "파이프라인 안에서 다시 도커를 돌릴 수 있게 해 주는 서비스 컨테이너"입니다.

before_script에서는 awscli 설치 후 aws ecr get-login-password를 이용해 ECR에 로그인합니다.

script에서는 Docker 이미지를 두 개의 태그로 빌드합니다.

$CI_PIPELINE_IID 태그는 파이프라인마다 유니크한 버전 이미지용이고, latest 태그는 항상 최신 버전을 가리키게 됩니다.

그 후 두 태그 모두 ECR로 푸시해 두면, 버전별 롤백이 필요할 때도 유용하게 활용할 수 있습니다.

GitLab Agent로 EKS 클러스터와 연동하기

이제 실제 배포 대상인 EKS(Elastic Kubernetes Service)에 접근해야 합니다.

예전에는 GitLab에서 Kubernetes 클러스터를 Token 기반으로 연동하는 방법도 있었지만, 현재는 GitLab Agent를 사용하는 방식이 주로 권장됩니다.

EKS 클러스터와 kubectl, aws-cli 등은 미리 준비되어 있다고 가정하고, GitLab Agent를 통한 연결 과정을 정리해 보겠습니다.

핵심 단계는 세 가지입니다.

먼저, GitLab 레포지토리 안에 Agent 설정 파일을 만들어야 합니다.

구조는 다음과 같습니다.

.gitlab/agents/<agent-name>/config.yaml

config.yaml 안에는 어떤 프로젝트의 매니페스트를 기준으로 GitOps를 할지 정의합니다.

예시는 아래처럼 작성할 수 있습니다.

gitops:
  manifest_projects:
    - id: [조직명]/[그룹명]/[프로젝트명]
      default_namespace: aiden-vas

default_namespace는 선택 사항이지만, EKS에서 주로 사용할 네임스페이스를 여기서 지정해 두면 뒤에서 편해집니다.

다음으로, GitLab에 Kubernetes 클러스터를 등록합니다.

프로젝트의 Infrastructure > Kubernetes clusters 메뉴로 이동해 Connect cluster를 선택하고, 방금 만든 agent-name을 입력한 뒤 create agentRegister를 순서대로 눌러줍니다.

등록이 완료되면, GitLab이 자동으로 Helm 설치 명령어와 함께 Access Token이 포함된 설치 커맨드를 보여줍니다.

이 명령어를 복사해 두었다가, 실제 EKS 클러스터에 접속해 실행하면 됩니다.

Helm이 클러스터에 설치되어 있어야 하고, 그 다음 이 명령어를 실행하면 gitlab-agent 네임스페이스 아래에 Agent Pod가 떠 있는 것을 확인할 수 있습니다.

kubectl get po -n gitlab-agent 명령으로 Pod가 정상 실행 중인지 확인해 보세요.

이 과정을 마치면, GitLab에서 EKS 클러스터로 안전하게 명령을 전달할 준비가 끝난 것입니다.

GitLab CI/CD에서 EKS로 배포하는 deploy 스테이지 구성

이제 마지막 단계인 배포 스테이지를 .gitlab-ci.yml에 추가해 봅니다.

목표는 GitLab 파이프라인에서 kubectl을 사용해 EKS에 배포 YAML을 적용하는 것입니다.

먼저, 배포에 필요한 변수들을 정의합니다.

variables:
  DOCKER_REGISTRY: 000000000000.dkr.ecr.ap-northeast-2.amazonaws.com
  AWS_DEFAULT_REGION: ap-northeast-2
  APP_NAME: [app-name]
  DOCKER_HOST: tcp://docker:2375
  DOCKER_DRIVER: overlay2
  DOCKER_TLS_CERTDIR: ""
  EKS_CONTEXT_PATH: [조직]/[그룹]/[프로젝트명]:[agent명]
  EKS_DEFAULT_NAMESPACE: aiden-vas
  EKS_DEPLOYMENT_YAML_PATH: [deploy yaml 파일 경로]

cache:
  paths:
    - .m2/repository

EKS_CONTEXT_PATH는 GitLab Agent의 config.yaml이 있는 프로젝트 경로와 Agent 이름을 합친 값입니다.

이 값이 있어야 kubectl config use-context로 올바른 클러스터에 연결할 수 있습니다.

EKS_DEFAULT_NAMESPACE는 EKS에서 사용할 기본 네임스페이스, EKS_DEPLOYMENT_YAML_PATH는 레포지토리 안에 배포용 Kubernetes 매니페스트가 있는 위치입니다.

스테이지는 deploy를 추가해 세 단계로 구성합니다.

stages:
  - package
  - build
  - deploy

이제 배포 Job을 정의합니다.

deploy:
  image:
    name: bitnami/kubectl:latest
    entrypoint: ['']
  stage: deploy
  script:
    - kubectl config get-contexts
    - kubectl config use-context $EKS_CONTEXT_PATH
    - kubectl get pods -n $EKS_DEFAULT_NAMESPACE
    - kubectl delete -f $EKS_DEPLOYMENT_YAML_PATH
    - kubectl apply -f $EKS_DEPLOYMENT_YAML_PATH
    # - kubectl rollout restart deployment -n $EKS_DEFAULT_NAMESPACE admin-mgmt-deploy
  only:
    variables:
      - $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

image로는 kubectl이 포함된 컨테이너를 사용합니다.

entrypoint를 빈 배열로 설정하는 이유는, 도커 이미지 기본 엔트리포인트 대신 우리가 작성한 script를 그대로 실행하기 위함입니다.

kubectl config use-context $EKS_CONTEXT_PATH는 앞에서 등록한 GitLab Agent를 기반으로 클러스터 접속 정보를 가져와 현재 컨텍스트로 설정합니다.

바로 다음에 kubectl get pods -n $EKS_DEFAULT_NAMESPACE를 실행해 실제로 잘 연결되었는지 확인하는 용도로 한 번 출력해 볼 수 있습니다.

실제 배포는 kubectl delete -fkubectl apply -f 두 단계로 처리합니다.

먼저 기존 리소스를 삭제한 후, 같은 YAML을 다시 적용함으로써 새 이미지가 반영된 Pod를 띄우는 방식입니다.

만약 삭제–생성 방식 대신 무중단에 가까운 롤링 업데이트를 하고 싶다면, deleteapply 대신 주석 처리된 kubectl rollout restart 같은 방식을 쓸 수도 있습니다.

이 경우에는 Deployment에서 사용하는 이미지 태그를 예를 들어 $DOCKER_REGISTRY/$APP_NAME:latest처럼 항상 최신 이미지를 바라보도록 설정해 두면, YAML을 수정하지 않고도 롤링 재시작만으로 업데이트가 가능합니다.

배포에 필요한 Deployment/Service 등의 상세 YAML은 팀마다 구조가 다르기 때문에 이 글에서는 생략했지만, 핵심은 "ECR에서 최신 이미지를 가져와서" Pod를 띄우도록 설정하는 것입니다.

GitLab–ECR–EKS CI/CD 파이프라인 완성 후 확인 포인트

여기까지 설정을 마치고 나면, 기본 브랜치에 커밋을 푸시했을 때 GitLab의 파이프라인 화면에서 package → docker_build → deploy 세 단계가 순서대로 실행되는 것을 볼 수 있습니다.

package 단계가 성공하면 Maven 빌드가 정상이라는 뜻이고, docker_build 단계가 성공하면 ECR에 이미지가 잘 푸시된 것입니다.

마지막 deploy까지 초록색으로 끝난다면, 이제는 GitLab에서 "Run pipeline" 버튼 한 번으로 배포까지 끝나는 CI/CD 파이프라인이 완성된 셈입니다.

실제로는 종종 다음 부분에서 에러가 나기 쉽습니다.

도커 데몬 연결 문제, AWS 인증 실패, EKS 컨텍스트 설정 오류 같은 것들인데, 대부분은 변수 값 오타나 IAM 권한, 또는 DOCKER_HOST와 같은 환경 변수 누락에서 시작됩니다.

에러 로그를 한 줄씩 읽어 보면서 해당 스테이지의 before_scriptscript를 점검하면 해결되는 경우가 많습니다.

시사점: GitLab으로 시작하는 현실적인 DevOps 자동화

이 구성을 한 번 끝까지 구축해 보면, "GitLab 레포지토리에 코드만 푸시했을 뿐인데 EKS까지 자동으로 배포가 된다"는 경험을 하게 됩니다.

이를 통해 팀에서 자연스럽게 코드 리뷰–머지–배포까지의 흐름을 하나의 파이프라인으로 엮을 수 있고, 사람 손을 타는 반복 작업을 줄여 배포 빈도를 높일 수 있습니다.

핵심은 세 가지입니다.

GitLab Runner와 .gitlab-ci.yml로 빌드와 배포 절차를 코드로 정의하고, AWS ECR을 이미지 저장소로 사용하며, GitLab Agent를 통해 EKS와 안전하게 연결하는 것입니다.

처음에는 변수 이름, 권한, YAML 경로 하나하나가 번거롭게 느껴질 수 있지만, 한 번 제대로 세팅해 두면 이후에는 "코드를 바꾸고, 커밋하고, 머지하는 것"만으로 서비스가 자동 업데이트 됩니다.

새 프로젝트를 시작할 때부터 이런 CI/CD 파이프라인을 함께 설계해 두면, 나중에 트래픽이 늘고 서비스가 복잡해질수록 "그때 미리 해 두길 잘했다"는 생각이 들 것입니다.

출처 및 참고 : Gitlab에서 CI/CD하기 (ECR / EKS 연동)

Grafana GitHub OAuth 연동으로 사내 로그인 깔끔하게 정리하기

이 노트는 요약·비평·학습 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.