LXD를 사용자 정의 실행기와 함께 사용하기
이번 예제에서는 LXD를 사용하여 빌드당 컨테이너를 생성하고, 그 후에 정리합니다.
이 예제는 각 단계에 대해 bash 스크립트를 사용합니다.
자신의 이미지를 지정할 수 있으며, 이는
CI_JOB_IMAGE로 노출됩니다.
이 예제는 단순성을 위해 ubuntu:18.04
이미지를 사용합니다.
여러 이미지를 지원하고 싶다면, 실행기를 수정해야 합니다.
이 스크립트는 다음과 같은 전제 조건이 있습니다:
구성
[[runners]]
name = "lxd-driver"
url = "https://www.gitlab.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 스크립트의 경로입니다.
기본
각 단계 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"
준비
준비 스크립트는 다음 작업을 수행합니다:
- 실행 중인 동일한 이름의 컨테이너가 있으면 삭제합니다.
- 컨테이너를 시작하고 시작할 때까지 기다립니다.
- 필수 종속성을 설치합니다.
#!/usr/bin/env bash
# /opt/lxd-driver/prepare.sh
currentDir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
source ${currentDir}/base.sh # 기본에서 변수 가져오기.
set -eo pipefail
# 오류를 포착하고 이를 시스템 오류로 표시합니다.
trap "exit $SYSTEM_FAILURE_EXIT_CODE" ERR
start_container () {
if lxc info "$CONTAINER_ID" >/dev/null 2>/dev/null ; then
echo '기존 컨테이너를 찾았습니다. 삭제합니다.'
lxc delete -f "$CONTAINER_ID"
fi
# 컨테이너 이미지는 하드코딩되어 있지만,
# `CI_JOB_IMAGE` 미리 정의된 변수를 사용할 수 있습니다.
# https://docs.gitlab.com/ee/ci/variables/predefined_variables.html
# 사용자가 이미지를 지정할 수 있도록 `CUSTOM_ENV_CI_JOB_IMAGE`에서 사용할 수 있습니다.
# 나머지 스크립트는 우분투 이미지에서 실행되고 있다고 가정하므로 수정이 필요할 수 있습니다.
lxc launch ubuntu:18.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 '10초 동안 컨테이너 시작을 기다렸습니다. 종료합니다..'
# GitLab Runner에 이것이 시스템 실패임을 알리므로,
# 재시도해야 합니다.
exit "$SYSTEM_FAILURE_EXIT_CODE"
fi
sleep 1s
done
}
install_dependencies () {
# Git LFS를 설치합니다. git은 우분투 이미지에 기본적으로 설치되어 있습니다.
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 "컨테이너 ID로 실행 중: $CONTAINER_ID"
start_container
install_dependencies
실행
이 스크립트는 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 # 기본에서 변수 가져오기.
lxc exec "$CONTAINER_ID" /bin/bash < "${1}"
if [ $? -ne 0 ]; then
# 변수 사용하여 종료하여 빌드를 GitLab CI에서 실패로 만들기.
exit $BUILD_FAILURE_EXIT_CODE
fi
정리
빌드가 완료되었으므로 컨테이너를 삭제합니다.
#!/usr/bin/env bash
# /opt/lxd-driver/cleanup.sh
currentDir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
source ${currentDir}/base.sh # 기본에서 변수 가져오기.
echo "컨테이너 $CONTAINER_ID 삭제 중"
lxc delete -f "$CONTAINER_ID"