GitHub Actions에서 마이그레이션

Tier: Free, Premium, Ultimate Offering: GitLab.com, Self-Managed, GitLab Dedicated

GitHub Actions에서 GitLab CI/CD로 마이그레이션하면 GitHub Actions의 워크플로우를 반영하고 향상시킬 수 있습니다.

주요 유사성과 차이점

GitHub Actions과 GitLab CI/CD는 둘 다 코드 빌드, 테스트, 배포를 자동화하기 위한 파이프라인을 생성하는 데 사용됩니다. 둘 다 다음과 같은 유사성을 가지고 있습니다:

  • CI/CD 기능은 프로젝트 리포지터리에 저장된 코드에 직접 액세스할 수 있습니다.
  • YAML로 작성된 파이프라인 구성은 프로젝트 리포지터리에 저장됩니다.
  • 파이프라인은 구성 가능하며 다양한 단계에서 실행될 수 있습니다.
  • 각 Job은 다른 컨테이너 이미지를 사용할 수 있습니다.

또한 둘 간에 중요한 차이점이 있습니다:

  • GitHub은 3rd-party 액션을 다운로드할 수 있는 마켓플레이스를 보유하고 있으며, 이는 추가 지원 또는 라이선스가 필요할 수 있습니다.
  • Self-Managed GitLab 인스턴스는 수평 및 수직 확장을 지원하지만, GitHub Enterprise Server는 수직 확장만 지원합니다.
  • GitLab은 모든 기능을 직접 유지 및 지원하며, 일부 3rd-party 통합은 템플릿을 통해 접근할 수 있습니다.
  • GitLab은 내장 컨테이너 레지스트리를 제공합니다.
  • GitLab은 원활한 Kubernetes 배포 지원을 제공합니다.
  • GitLab은 세분화된 보안 정책을 제공합니다.

기능 및 개념 비교

많은 GitHub 기능 및 개념은 같은 기능을 제공하는 GitLab과 동등한 대안이 있습니다.

구성 파일

GitHub Actions는 workflow YAML 파일을 사용하여 구성할 수 있습니다. 반면 GitLab CI/CD는 기본적으로 .gitlab-ci.yml YAML 파일을 사용합니다.

예를 들어, GitHub Actions의 workflow 파일에서:

on: [push]
jobs:
  hello:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Hello World"

GitLab CI/CD의 .gitlab-ci.yml 파일의 해당 부분은 다음과 같을 것입니다:

stages:
  - hello

hello:
  stage: hello
  script:
    - echo "Hello World"

GitHub Actions 워크플로우 구문

GitHub Actions 구성은 특정 키워드를 사용하여 workflow YAML 파일에서 정의됩니다. GitLab CI/CD도 YAML 키워드를 사용하여 유사한 기능을 가지고 있습니다.

GitHub GitLab 설명
env variables env는 워크플로우, job 또는 단계에서 정의된 변수를 정의합니다. GitLab은 CI/CD 변수를 전역 또는 job 수준에서 정의하기 위해 variables를 사용합니다. 변수는 UI에서도 추가할 수 있습니다.
jobs stages jobs는 워크플로우에서 실행되는 모든 작업을 그룹화합니다. GitLab은 stages를 사용하여 작업을 그룹화합니다.
on 해당 없음 on은 워크플로우가 트리거되는 시점을 정의합니다. GitLab은 SCM(버전 관리 시스템)과 긴밀하게 통합되어 있으므로 트리거에 대한 SCM 폴링 옵션이 필요하지 않지만 필요한 경우 job당 구성할 수 있습니다.
run 해당 없음 job에서 실행할 명령을 정의합니다. GitLab은 script 키워드 아래의 YAML 배열을 사용하여 실행할 각 명령에 대해 하나의 항목을 사용합니다.
runs-on tags runs-on은 job이 실행되어야 하는 GitHub 러너를 정의합니다. GitLab은 tags를 사용하여 러너를 선택합니다.
steps script steps는 job에서 실행되는 모든 단계를 그룹화합니다. GitLab은 script를 사용하여 job에서 실행되는 모든 명령을 그룹화합니다.
uses include usesstep에 추가할 GitHub Action을 정의합니다. GitLab은 job에 다른 파일의 구성을 추가하기 위해 include를 사용합니다.

공통 구성

이 섹션에서는 GitHub Actions에서 GitLab CI/CD로 일반적으로 사용되는 CI/CD 구성에 대해 알아봅니다.

GitHub Action 워크플로우는 새 커밋을 푸시하는 등의 이벤트가 발생할 때 트리거되는 자동화된 CI/CD 작업을 생성합니다. GitHub Action 워크플로우는 .github/workflows 디렉터리에 정의된 YAML 파일입니다. GitLab과 동등한 것은 루트 디렉터리에 위치한 .gitlab-ci.yml 구성 파일입니다.

Jobs

Jobs는 특정 결과를 달성하기 위해 순차적으로 실행되는 명령 세트입니다. 예를 들어, 이 GitHub Actions workflow는 컨테이너를 빌드한 다음 프로덕션으로 배포합니다. deploy job은 build job에 종속되어 순차적으로 실행됩니다:

on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    container: golang:alpine
    steps:
      - run: apk update
      - run: go build -o bin/hello
      - uses: actions/upload-artifact@v3
        with:
          name: hello
          path: bin/hello
          retention-days: 7
  deploy:
    if: contains( github.ref, 'staging')
    runs-on: ubuntu-latest
    container: golang:alpine
    steps:
      - uses: actions/download-artifact@v3
        with:
          name: hello
      - run: echo "Deploying to Staging"
      - run: scp bin/hello remoteuser@remotehost:/remote/directory

해당 예시에서:

  • golang:alpine 컨테이너 이미지를 사용합니다.
  • 빌드된 실행 가능 파일을 artifact로 저장합니다.
  • staging로 배포를 실행하는 두 번째 job을 실행합니다. 이에는 다음이 포함됩니다:
    • 실행되기 전에 build 작업이 성공해야 합니다.
    • 커밋 대상 브랜치가 staging이어야 합니다.
    • 빌드 실행 파일 artifact를 사용합니다.

해당 GitLab CI/CD .gitlab-ci.yml 파일은 다음과 같을 것입니다:

default:
  image: golang:alpine

stages:
  - build
  - deploy

build-job:
  stage: build
  script:
    - apk update
    - go build -o bin/hello
  artifacts:
    paths:
      - bin/hello
    expire_in: 1 week

deploy-job:
  stage: deploy
  script:
    - echo "Deploying to Staging"
    - scp bin/hello remoteuser@remotehost:/remote/directory
  rules:
    - if: $CI_COMMIT_BRANCH == 'staging'
병렬

GitHub 및 GitLab에서 기본적으로 Jobs는 병렬로 실행됩니다.

예를 들어, GitHub Actions workflow 파일에서:

on: [push]
jobs:
  python-version:
    runs-on: ubuntu-latest
    container: python:latest
    steps:
      - run: python --version
  java-version:
    if: contains( github.ref, 'staging')
    runs-on: ubuntu-latest
    container: openjdk:latest
    steps:
      - run: java -version

해당 예시는 파이썬 job과 Java job을 병렬로 실행하며 각각 다른 컨테이너 이미지를 사용합니다. Java job은 staging 브랜치가 변경된 경우에만 실행됩니다.

해당 GitLab CI/CD .gitlab-ci.yml 파일은 다음과 같을 것입니다:

python-version:
  image: python:latest
  script:
    - python --version

java-version:
  image: openjdk:latest
  rules:
    - if: $CI_COMMIT_BRANCH == 'staging'
  script:
    - java -version

이 경우 병렬로 실행하려면 추가 구성이 필요하지 않습니다. 기본적으로 Jobs는 병렬로 실행되며 각각의 runner에서 실행되지만, 상황에 따라 모든 job에 충분한 runner가 있는 경우에만 적용됩니다. Java job은 staging 브랜치가 변경될 때만 실행되도록 설정되어 있습니다.

행렬

GitLab 및 GitHub 모두 단일 파이프라인에서 여러 번 작업을 병렬로 실행하고 각 작업 인스턴스마다 다른 변수 값을 사용하여 행렬을 사용할 수 있습니다.

예를 들어, GitHub Actions의workflow 파일에서:

on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: echo "$PLATFORM에 대한 $ARCH 빌드"
    strategy:
      matrix:
        platform: [linux, mac, windows]
        arch: [x64, x86]
  test:
    runs-on: ubuntu-latest
    steps:
      - run: echo "$PLATFORM에 대한 $ARCH 테스트"
    strategy:
      matrix:
        platform: [linux, mac, windows]
        arch: [x64, x86]
  deploy:
    runs-on: ubuntu-latest
    steps:
      - run: echo "$PLATFORM에 대한 $ARCH 배포"
    strategy:
      matrix:
        platform: [linux, mac, windows]
        arch: [x64, x86]

동등한 GitLab CI/CD .gitlab-ci.yml 파일은 다음과 같습니다:

stages:
  - build
  - test
  - deploy

.parallel-hidden-job:
  parallel:
    matrix:
      - PLATFORM: [linux, mac, windows]
        ARCH: [x64, x86]

build-job:
  extends: .parallel-hidden-job
  stage: build
  script:
    - echo "$PLATFORM에 대한 $ARCH 빌드"

test-job:
  extends: .parallel-hidden-job
  stage: test
  script:
    - echo "$PLATFORM에 대한 $ARCH 테스트"

deploy-job:
  extends: .parallel-hidden-job
  stage: deploy
  script:
    - echo "$PLATFORM에 대한 $ARCH 배포"

트리거

GitHub Actions는 워크플로우에 대한 트리거를 추가해야 합니다. GitLab은 Git과 긴밀하게 통합되어 있으므로 트리거에 대한 SCM 폴링 옵션이 필요하지 않지만 필요한 경우 작업 당으로 구성할 수 있습니다.

샘플 GitHub Actions 구성:

on:
  push:
    branches:
      - main

동등한 GitLab CI/CD 구성은 다음과 같습니다:

rules:
  - if: '$CI_COMMIT_BRANCH == main'

파이프라인은 또한 크론 구문을 사용하여 예약할 수도 있습니다.

컨테이너 이미지

GitLab을 사용하면 image 키워드를 사용하여 별도로 격리된 Docker 컨테이너에서 CI/CD 작업을 실행할 수 있습니다.

예를 들어, GitHub Actions의workflow 파일에서:

jobs:
  update:
    runs-on: ubuntu-latest
    container: alpine:latest
    steps:
      - run: apk update

이 예에서 apk update 명령은 alpine:latest 컨테이너에서 실행됩니다.

동등한 GitLab CI/CD .gitlab-ci.yml 파일은 다음과 같습니다:

update-job:
  image: alpine:latest
  script:
    - apk update

GitLab은 모든 프로젝트에 대해 컨테이너 레지스트리를 제공하며, 컨테이너 이미지를 빌드하고 GitLab CI/CD 파이프라인에서 직접 저장할 수 있습니다.

예를 들어:

stages:
  - build

build-image:
  stage: build
  variables:
    IMAGE: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG:$CI_COMMIT_SHA
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    - docker build -t $IMAGE .
    - docker push $IMAGE

변수

GitLab에서 우리는 런타임에 variables 키워드를 사용하여 다른 CI/CD 변수를 정의합니다. 파이프라인에서 구성 데이터를 재사용해야 하는 경우 변수를 정의할 수 있습니다. 변수를 전역적으로 또는 작업 당으로 정의할 수 있습니다.

예를 들어, GitHub Actions의workflow 파일에서:

env:
  NAME: "fern"

jobs:
  english:
    runs-on: ubuntu-latest
    env:
      Greeting: "hello"
    steps:
      - run: echo "$GREETING $NAME"
  spanish:
    runs-on: ubuntu-latest
    env:
      Greeting: "hola"
    steps:
      - run: echo "$GREETING $NAME"

이 예에서 변수는 작업에 대해 다른 출력을 제공합니다.

동등한 GitLab CI/CD .gitlab-ci.yml 파일은 다음과 같습니다:

default:
  image: ubuntu-latest

variables:
  NAME: "fern"

english:
  variables:
    GREETING: "hello"
  script:
    - echo "$GREETING $NAME"

spanish:
  variables:
    GREETING: "hola"
  script:
    - echo "$GREETING $NAME"

변수는 GitLab UI를 통해 설정할 수도 있으며, 여기서 보호하거나 가리기할 수 있습니다. 가려진 변수는 작업 로그에 숨겨지며 보호된 변수는 보호된 브랜치나 태그에 대한 파이프라인에서만 액세스할 수 있습니다.

예를 들어, GitHub Actions의workflow 파일에서:

jobs:
  login:
    runs-on: ubuntu-latest
    env:
      AWS_ACCESS_KEY: ${{ secrets.AWS_ACCESS_KEY }}
    steps:
      - run: my-login-script.sh "$AWS_ACCESS_KEY"

만약 AWS_ACCESS_KEY 변수가 GitLab 프로젝트 설정에 정의된 경우, 동등한 GitLab CI/CD .gitlab-ci.yml 파일은 다음과 같습니다:

login:
  script:
    - my-login-script.sh $AWS_ACCESS_KEY

또한, GitHub ActionsGitLab CI/CD는 파이프라인 및 리포지터리에 관련된 데이터를 포함하는 내장 변수를 제공합니다.

조건부

새 파이프라인을 시작할 때, GitLab은 파이프라인 구성을 확인하여 해당 파이프라인에서 실행해야 할 작업을 결정합니다. rules 키워드를 사용하여 변수의 상태나 파이프라인 유형과 같은 조건에 따라 작업을 구성할 수 있습니다.

예를 들어, GitHub Actions의workflow 파일에서:

jobs:
  deploy_staging:
    if: contains( github.ref, 'staging')
    runs-on: ubuntu-latest
    steps:
      - run: echo "스테이징 서버로 배포"

동등한 GitLab CI/CD .gitlab-ci.yml 파일은 다음과 같습니다:

deploy_staging:
  stage: deploy
  script:
    - echo "스테이징 서버로 배포"
  rules:
    - if: '$CI_COMMIT_BRANCH == staging'

러너

러너는 작업을 실행하는 서비스입니다. GitLab.com을 사용하는 경우 Self-Managed형 러너를 프로비저닝하지 않고도 인스턴스 러너 플리트를 사용하여 작업을 실행할 수 있습니다.

러너에 대한 몇 가지 핵심 세부 정보는 다음과 같습니다:

  • 러너를 인스턴스 전체, 그룹 또는 단일 프로젝트에 대해 공유하도록 구성할 수 있습니다.
  • 보다 정교한 제어를 위해 tags 키워드를 사용하고 특정 작업과 관련된 러너를 연결할 수 있습니다. 예를 들어, 더 강력하거나 특정 하드웨어가 필요한 작업을 위해 태그를 사용할 수 있습니다.
  • GitLab은 러너에 대한 자동 확장을 제공합니다. 필요할 때만 러너를 프로비저닝하고 필요하지 않은 경우에는 축소합니다.

예를 들어, GitHub Actions의workflow 파일에서:

linux_job:
  runs-on: ubuntu-latest
  steps:
    - run: echo "안녕, $USER"

windows_job:
  runs-on: windows-latest
  steps:
    - run: echo "안녕, %USERNAME%"

동등한 GitLab CI/CD .gitlab-ci.yml 파일은 다음과 같습니다:

linux_job:
  stage: build
  tags:
    - linux-runners
  script:
    - echo "안녕, $USER"

windows_job:
  stage: build
  tags:
    - windows-runners
  script:
    - echo "안녕, %USERNAME%"

아티팩트

GitLab에서는 어떤 작업이 완료될 때 저장할 아티팩트 세트를 정의하기 위해 artifacts 키워드를 사용할 수 있습니다. 아티팩트는 이후 작업에서 사용할 수 있는 파일입니다.

예를 들어, GitHub Actions의 workflow 파일에서:

on: [push]
jobs:
  generate_cat:
    steps:
      - run: touch cat.txt
      - run: echo "meow" > cat.txt
      - uses: actions/upload-artifact@v3
        with:
          name: cat
          path: cat.txt
          retention-days: 7
  use_cat:
    needs: [generate_cat]
    steps:
      - uses: actions/download-artifact@v3
        with:
          name: cat
      - run: cat cat.txt

동등한 GitLab CI/CD .gitlab-ci.yml 파일은 다음과 같을 것입니다:

stage:
  - generate
  - use

generate_cat:
  stage: generate
  script:
    - touch cat.txt
    - echo "meow" > cat.txt
  artifacts:
    paths:
      - cat.txt
    expire_in: 1 week

use_cat:
  stage: use
  script:
    - cat cat.txt

캐싱

작업이 하나 이상의 파일을 다운로드하고 나중에 빠른 액세스를 위해 저장할 때 캐시가 생성됩니다. 동일한 캐시를 사용하는 후속 작업은 파일을 다시 다운로드할 필요가 없으므로 실행이 더 빨리 완료됩니다. 캐시는 러너에 저장되며 분산 캐시가 활성화된 경우 S3에 업로드됩니다.

예를 들어, GitHub Actions의 workflow 파일에서:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - run: echo "This job uses a cache."
    - uses: actions/cache@v3
      with:
        path: binaries/
        key: binaries-cache-$CI_COMMIT_REF_SLUG

동등한 GitLab CI/CD .gitlab-ci.yml 파일은 다음과 같을 것입니다:

cache-job:
  script:
    - echo "This job uses a cache."
  cache:
    key: binaries-cache-$CI_COMMIT_REF_SLUG
    paths:
      - binaries/

템플릿

GitHub에서 액션이 자주 반복되어야 하는 복잡한 작업 세트이며 CI/CD 파이프라인을 재정의하지 않고 재사용하도록 저장하는 것이라면, GitLab에서는 include 키워드가 해당 작업의 동등물이며 GitLab에 내장된 템플릿 파일을 포함하여 다른 파일에서 CI/CD 파이프라인을 추가할 수 있습니다.

GitHub Actions 구성 예시:

- uses: hashicorp/setup-terraform@v2.0.3

동등한 GitLab CI/CD 구성은 다음과 같을 것입니다:

include:
  - template: Terraform.gitlab-ci.yml

이 예시에서 setup-terraform GitHub action과 Terraform.gitlab-ci.yml GitLab 템플릿은 정확히 일치하지 않습니다. 이 두 예시는 복잡한 구성이 어떻게 재사용될 수 있는지 보여주기 위한 것입니다.

보안 스캔 기능

GitLab은 보안 스캐너를 제공하여 SLDC의 모든 부분에서 취약점을 탐지합니다. 이러한 기능을 GitLab CI/CD 파이프라인에 추가하여 사용할 수 있습니다.

예를 들어, 파이프라인에 SAST 스캐닝을 추가하려면 다음을 .gitlab-ci.yml에 추가하세요:

include:
  - template: Jobs/SAST.gitlab-ci.yml

보안 스캐너의 CI/CD 변수를 사용하여 보안 스캐너의 동작을 사용자 정의할 수 있습니다.

시크릿 관리

“시크릿”으로 자주 언급되는 특권 정보는 CI/CD 워크플로에 필요한 민감한 정보나 자격 증명입니다. 시크릿을 사용하여 보호된 리소스를 잠금 해제하거나 도구, 애플리케이션, 컨테이너, 클라우드 네이티브 환경의 민감한 정보를 공유할 수 있습니다.

GitLab에서 시크릿 관리를 위해 지원되는 외부 서비스의 통합 중 하나를 사용할 수 있습니다. 이러한 서비스는 GitLab 프로젝트 외부에서 시크릿을 안전하게 저장하지만 해당 서비스의 구독이 필요합니다:

또한 GitLab은 OIDC를 지원하여 OIDC를 지원하는 다른 타사 서비스에 대해 OIDC 인증을 지원합니다.

또한 CI/CD 변수에 시크릿을 저장하여 작업에서 자격 증명을 사용할 수 있습니다. 그러나 평문으로 저장된 시크릿은 우연한 노출에 취약합니다. 일부 위험을 완화하는 마스킹보호 변수에 민감한 정보를 항상 저장해야 합니다.

또한 프로젝트, 그룹 또는 인스턴스 설정에서만 시크릿을 변수로 저장해야 하며, .gitlab-ci.yml 파일에 시크릿을 저장해서는 안됩니다. 민감한 정보를 저장해야 하는 경우를 위해서는 프로젝트, 그룹 또는 인스턴스 설정을 사용해야 합니다.

CI/CD 변수의 안전성을 향상시키기 위해 보안 가이드라인을 검토하세요.

마이그레이션 계획 수립 및 수행

다음의 권장 단계 디렉터리은 이러한 마이그레이션을 빠르게 완료할 수 있는 조직을 관찰한 후 작성되었습니다.

마이그레이션 계획 수립

마이그레이션을 시작하기 전에 마이그레이션을 준비하기 위한 마이그레이션 계획을 작성해야 합니다.

전제조건

어떠한 마이그레이션 작업을 수행하기 전에 먼저 다음을 수행해야 합니다:

  1. GitLab을 알아보세요.
  2. GitLab을 설정하고 구성하세요.
  3. GitLab 인스턴스를 테스트하세요.
    • 러너(runner)가 사용 가능한지 확인하세요, 공유된 GitLab.com 러너를 사용하거나 새 러너를 설치할 수 있습니다.

마이그레이션 단계

  1. GitHub에서 GitLab으로 프로젝트 마이그레이션:
  2. 각 프로젝트에 .gitlab-ci.yml을 만드세요.
  3. GitHub Actions 작업을 GitLab CI/CD 작업으로 마이그레이션하고 해당 결과를 Merge Request에서 직접보기 위해 구성하세요.
  4. 클라우드 배포 템플릿, 환경, GitLab 쿠버네티스 에이전트를 사용하여 배포 작업을 마이그레이션하세요.
  5. 다른 프로젝트 간에 재사용할 수 있는 CI/CD 구성이 있는지 확인한 후 CI/CD 템플릿을 만들고 공유하세요.
  6. GitLab CI/CD 파이프라인을 더 빠르고 효율적으로 만드는 방법을 배우기 위해 파이프라인 효율성 문서를 확인하세요.

추가 리소스

여기에 대답되지 않은 질문이 있을 경우, GitLab 커뮤니티 포럼이 큰 도움이 될 것입니다.