InfoGrab Docs

Custom executor에서 LXD 사용하기

요약

이 예제에서는 LXD를 사용하여 빌드마다 컨테이너를 생성하고 완료 후 정리합니다. 이 예제는 각 단계에 bash 스크립트를 사용합니다. 이 스크립트에는 다음과 같은 필수 소프트웨어가 필요합니다: 각 단계인 prepare, run, cleanup은 이 스크립트를 사용하여 스크립트 전반에서 사용되는 변수를 생성합니다.

이 예제에서는 LXD를 사용하여 빌드마다 컨테이너를 생성하고 완료 후 정리합니다.

이 예제는 각 단계에 bash 스크립트를 사용합니다. 고유한 이미지를 지정할 수 있으며, 이는 CI_JOB_IMAGE로 노출됩니다. 단순성을 위해 이 예제에서는 ubuntu:22.04 이미지를 사용합니다. 여러 이미지를 지원하려면 executor를 수정해야 합니다.

이 스크립트에는 다음과 같은 필수 소프트웨어가 필요합니다:

구성#

[[runners]]
  name = "lxd-driver"
  url = "https://gitlab.example.com"
  token = "xxxxxxxxxxx"
  executor = "custom"
  builds_dir = "/builds"
  cache_dir = "/cache"
  [runners.custom]
    prepare_exec = "/opt/lxd-driver/prepare.sh" # lxd 컨테이너를 생성하고 의존성을 다운로드하는 bash 스크립트 경로.
    run_exec = "/opt/lxd-driver/run.sh" # 컨테이너 내부에서 스크립트를 실행하는 bash 스크립트 경로.
    cleanup_exec = "/opt/lxd-driver/cleanup.sh" # 컨테이너를 삭제하는 bash 스크립트 경로.

Base#

각 단계인 prepare, run, cleanup은 이 스크립트를 사용하여 스크립트 전반에서 사용되는 변수를 생성합니다.

이 스크립트는 다른 스크립트와 동일한 디렉터리, 이 경우 /opt/lxd-driver/에 위치해야 합니다.

#!/usr/bin/env bash

# /opt/lxd-driver/base.sh

CONTAINER_ID="runner-$CUSTOM_ENV_CI_RUNNER_ID-project-$CUSTOM_ENV_CI_PROJECT_ID-concurrent-$CUSTOM_ENV_CI_CONCURRENT_PROJECT_ID-$CUSTOM_ENV_CI_JOB_ID"

Prepare#

prepare 스크립트는 다음을 수행합니다:

  • 동일한 이름의 컨테이너가 실행 중이면 삭제합니다.
  • 컨테이너를 시작하고 시작될 때까지 대기합니다.
  • 필수 의존성을 설치합니다.
#!/usr/bin/env bash

# /opt/lxd-driver/prepare.sh

currentDir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
source ${currentDir}/base.sh # base에서 변수 가져오기.

set -eo pipefail

# 모든 오류를 트랩하고 시스템 오류로 표시합니다.
trap "exit $SYSTEM_FAILURE_EXIT_CODE" ERR

start_container () {
    if lxc info "$CONTAINER_ID" >/dev/null 2>/dev/null ; then
        echo 'Found old container, deleting'
        lxc delete -f "$CONTAINER_ID"
    fi

    # 컨테이너 이미지는 하드코딩되어 있지만,
    # `CI_JOB_IMAGE` 사전 정의 변수를 사용할 수 있습니다.
    # https://docs.gitlab.com/ci/variables/predefined_variables/
    # 이 변수는 `CUSTOM_ENV_CI_JOB_IMAGE` 아래에서 사용 가능하며
    # 사용자가 이미지를 지정할 수 있습니다. 나머지 스크립트는
    # ubuntu 이미지에서 실행된다고 가정하므로 수정이 필요할 수 있습니다.
    lxc launch ubuntu:22.04 "$CONTAINER_ID"

    # 컨테이너가 시작될 때까지 대기합니다. 간결성을 위해
    # systemd를 사용하여 확인합니다.
    for i in $(seq 1 10); do
        if lxc exec "$CONTAINER_ID" -- sh -c "systemctl isolate multi-user.target" >/dev/null 2>/dev/null; then
            break
        fi

        if [ "$i" == "10" ]; then
            echo 'Waited for 10 seconds to start container, exiting..'
            # GitLab Runner에 시스템 오류임을 알려
            # 재시도하도록 합니다.
            exit "$SYSTEM_FAILURE_EXIT_CODE"
        fi

        sleep 1s
    done
}

install_dependencies () {
    # Git LFS를 설치합니다. git은 ubuntu 이미지에 사전 설치되어 있습니다.
    lxc exec "$CONTAINER_ID" -- sh -c 'curl -s "https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh" | sudo bash'
    lxc exec "$CONTAINER_ID" -- sh -c "apt-get install -y git-lfs"

    # 캐시/아티팩트를 위해 gitlab-runner 바이너리를 설치합니다.
    lxc exec "$CONTAINER_ID" -- sh -c 'curl -L --output /usr/local/bin/gitlab-runner "https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64"'
    lxc exec "$CONTAINER_ID" -- sh -c "chmod +x /usr/local/bin/gitlab-runner"
}

echo "Running in $CONTAINER_ID"

start_container

install_dependencies

Run#

GitLab Runner가 생성한 스크립트의 내용을 STDIN을 통해 컨테이너에 전송하여 스크립트를 실행합니다.

#!/usr/bin/env bash

# /opt/lxd-driver/run.sh

currentDir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
source ${currentDir}/base.sh # base에서 변수 가져오기.

lxc exec "$CONTAINER_ID" /bin/bash < "${1}"
if [ $? -ne 0 ]; then
    # 변수를 사용하여 종료하면 GitLab
    # CI에서 빌드가 실패로 표시됩니다.
    exit $BUILD_FAILURE_EXIT_CODE
fi

Cleanup#

빌드가 완료되었으므로 컨테이너를 삭제합니다.

#!/usr/bin/env bash

# /opt/lxd-driver/cleanup.sh

currentDir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
source ${currentDir}/base.sh # base에서 변수 가져오기.

echo "Deleting container $CONTAINER_ID"

lxc delete -f "$CONTAINER_ID"

Custom executor에서 LXD 사용하기

Tier: Free, Premium, Ultimate
Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
원문 보기
요약

이 예제에서는 LXD를 사용하여 빌드마다 컨테이너를 생성하고 완료 후 정리합니다. 이 예제는 각 단계에 bash 스크립트를 사용합니다. 이 스크립트에는 다음과 같은 필수 소프트웨어가 필요합니다: 각 단계인 prepare, run, cleanup은 이 스크립트를 사용하여 스크립트 전반에서 사용되는 변수를 생성합니다.

이 예제에서는 LXD를 사용하여 빌드마다 컨테이너를 생성하고 완료 후 정리합니다.

이 예제는 각 단계에 bash 스크립트를 사용합니다. 고유한 이미지를 지정할 수 있으며, 이는 CI_JOB_IMAGE로 노출됩니다. 단순성을 위해 이 예제에서는 ubuntu:22.04 이미지를 사용합니다. 여러 이미지를 지원하려면 executor를 수정해야 합니다.

이 스크립트에는 다음과 같은 필수 소프트웨어가 필요합니다:

구성#

[[runners]]
  name = "lxd-driver"
  url = "https://gitlab.example.com"
  token = "xxxxxxxxxxx"
  executor = "custom"
  builds_dir = "/builds"
  cache_dir = "/cache"
  [runners.custom]
    prepare_exec = "/opt/lxd-driver/prepare.sh" # lxd 컨테이너를 생성하고 의존성을 다운로드하는 bash 스크립트 경로.
    run_exec = "/opt/lxd-driver/run.sh" # 컨테이너 내부에서 스크립트를 실행하는 bash 스크립트 경로.
    cleanup_exec = "/opt/lxd-driver/cleanup.sh" # 컨테이너를 삭제하는 bash 스크립트 경로.

Base#

각 단계인 prepare, run, cleanup은 이 스크립트를 사용하여 스크립트 전반에서 사용되는 변수를 생성합니다.

이 스크립트는 다른 스크립트와 동일한 디렉터리, 이 경우 /opt/lxd-driver/에 위치해야 합니다.

#!/usr/bin/env bash

# /opt/lxd-driver/base.sh

CONTAINER_ID="runner-$CUSTOM_ENV_CI_RUNNER_ID-project-$CUSTOM_ENV_CI_PROJECT_ID-concurrent-$CUSTOM_ENV_CI_CONCURRENT_PROJECT_ID-$CUSTOM_ENV_CI_JOB_ID"

Prepare#

prepare 스크립트는 다음을 수행합니다:

  • 동일한 이름의 컨테이너가 실행 중이면 삭제합니다.
  • 컨테이너를 시작하고 시작될 때까지 대기합니다.
  • 필수 의존성을 설치합니다.
#!/usr/bin/env bash

# /opt/lxd-driver/prepare.sh

currentDir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
source ${currentDir}/base.sh # base에서 변수 가져오기.

set -eo pipefail

# 모든 오류를 트랩하고 시스템 오류로 표시합니다.
trap "exit $SYSTEM_FAILURE_EXIT_CODE" ERR

start_container () {
    if lxc info "$CONTAINER_ID" >/dev/null 2>/dev/null ; then
        echo 'Found old container, deleting'
        lxc delete -f "$CONTAINER_ID"
    fi

    # 컨테이너 이미지는 하드코딩되어 있지만,
    # `CI_JOB_IMAGE` 사전 정의 변수를 사용할 수 있습니다.
    # https://docs.gitlab.com/ci/variables/predefined_variables/
    # 이 변수는 `CUSTOM_ENV_CI_JOB_IMAGE` 아래에서 사용 가능하며
    # 사용자가 이미지를 지정할 수 있습니다. 나머지 스크립트는
    # ubuntu 이미지에서 실행된다고 가정하므로 수정이 필요할 수 있습니다.
    lxc launch ubuntu:22.04 "$CONTAINER_ID"

    # 컨테이너가 시작될 때까지 대기합니다. 간결성을 위해
    # systemd를 사용하여 확인합니다.
    for i in $(seq 1 10); do
        if lxc exec "$CONTAINER_ID" -- sh -c "systemctl isolate multi-user.target" >/dev/null 2>/dev/null; then
            break
        fi

        if [ "$i" == "10" ]; then
            echo 'Waited for 10 seconds to start container, exiting..'
            # GitLab Runner에 시스템 오류임을 알려
            # 재시도하도록 합니다.
            exit "$SYSTEM_FAILURE_EXIT_CODE"
        fi

        sleep 1s
    done
}

install_dependencies () {
    # Git LFS를 설치합니다. git은 ubuntu 이미지에 사전 설치되어 있습니다.
    lxc exec "$CONTAINER_ID" -- sh -c 'curl -s "https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh" | sudo bash'
    lxc exec "$CONTAINER_ID" -- sh -c "apt-get install -y git-lfs"

    # 캐시/아티팩트를 위해 gitlab-runner 바이너리를 설치합니다.
    lxc exec "$CONTAINER_ID" -- sh -c 'curl -L --output /usr/local/bin/gitlab-runner "https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64"'
    lxc exec "$CONTAINER_ID" -- sh -c "chmod +x /usr/local/bin/gitlab-runner"
}

echo "Running in $CONTAINER_ID"

start_container

install_dependencies

Run#

GitLab Runner가 생성한 스크립트의 내용을 STDIN을 통해 컨테이너에 전송하여 스크립트를 실행합니다.

#!/usr/bin/env bash

# /opt/lxd-driver/run.sh

currentDir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
source ${currentDir}/base.sh # base에서 변수 가져오기.

lxc exec "$CONTAINER_ID" /bin/bash < "${1}"
if [ $? -ne 0 ]; then
    # 변수를 사용하여 종료하면 GitLab
    # CI에서 빌드가 실패로 표시됩니다.
    exit $BUILD_FAILURE_EXIT_CODE
fi

Cleanup#

빌드가 완료되었으므로 컨테이너를 삭제합니다.

#!/usr/bin/env bash

# /opt/lxd-driver/cleanup.sh

currentDir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
source ${currentDir}/base.sh # base에서 변수 가져오기.

echo "Deleting container $CONTAINER_ID"

lxc delete -f "$CONTAINER_ID"