Đăng vào

Thiết lập GitHub ARC runner để chạy job trong container

Giới thiệu

Trong chuổi các bài viết liên quan đến Kubernetes, mình có giới thiệu đến việc triển khai GitHub ARC trên Kubernetes để tạo Self-hosted runner có thể tự đông scale (mở rộng) dựa theo số lượng job cần chạy.

Self-hosted runner chính là các runner do chính người dùng cung cấp, dùng để thực hiện các tác vụ CI/CD bên cạnh các runner do GitHub cung cấp và người dùng phải trả tiền theo tài nguyên sử dụng.

Tuy nhiên do bản thân runner đang chạy ở dạng container nên nếu workflow của bạn có chạy dạng container job sẽ dẫn tới vấn đề cần thiết lập docker trong một container (DinD).

Bài viết này sẽ hướng dẫn cách cấu hình để cho phép làm được điều đó

Runner image

Đầu tiên, mình sẽ hướng dẫn cách tạo docker image dành cho runner, trong Dockerfile của nó sẽ chứa những cấu hình, công cụ cần thiết để khi container chạy có thể phục vụ được các tác vụ CI/CD.

Nếu như đọc kỹ vào helm chart gha-runner-scale-set thì mặc định, pod runner sẽ sử dụng image ghcr.io/actions/actions-runner:latest

Dưới đây là dockerfile của pod runner

# Source: https://github.com/dotnet/dotnet-docker
FROM mcr.microsoft.com/dotnet/runtime-deps:8.0-jammy as build

ARG TARGETOS
ARG TARGETARCH
ARG RUNNER_VERSION
ARG RUNNER_CONTAINER_HOOKS_VERSION=0.6.1
ARG DOCKER_VERSION=27.3.1
ARG BUILDX_VERSION=0.18.0

RUN apt update -y && apt install curl unzip -y

WORKDIR /actions-runner
RUN export RUNNER_ARCH=${TARGETARCH} \
    && if [ "$RUNNER_ARCH" = "amd64" ]; then export RUNNER_ARCH=x64 ; fi \
    && curl -f -L -o runner.tar.gz https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-${TARGETOS}-${RUNNER_ARCH}-${RUNNER_VERSION}.tar.gz \
    && tar xzf ./runner.tar.gz \
    && rm runner.tar.gz

RUN curl -f -L -o runner-container-hooks.zip https://github.com/actions/runner-container-hooks/releases/download/v${RUNNER_CONTAINER_HOOKS_VERSION}/actions-runner-hooks-k8s-${RUNNER_CONTAINER_HOOKS_VERSION}.zip \
    && unzip ./runner-container-hooks.zip -d ./k8s \
    && rm runner-container-hooks.zip

RUN export RUNNER_ARCH=${TARGETARCH} \
    && if [ "$RUNNER_ARCH" = "amd64" ]; then export DOCKER_ARCH=x86_64 ; fi \
    && if [ "$RUNNER_ARCH" = "arm64" ]; then export DOCKER_ARCH=aarch64 ; fi \
    && curl -fLo docker.tgz https://download.docker.com/${TARGETOS}/static/stable/${DOCKER_ARCH}/docker-${DOCKER_VERSION}.tgz \
    && tar zxvf docker.tgz \
    && rm -rf docker.tgz \
    && mkdir -p /usr/local/lib/docker/cli-plugins \
    && curl -fLo /usr/local/lib/docker/cli-plugins/docker-buildx \
        "https://github.com/docker/buildx/releases/download/v${BUILDX_VERSION}/buildx-v${BUILDX_VERSION}.linux-${TARGETARCH}" \
    && chmod +x /usr/local/lib/docker/cli-plugins/docker-buildx

FROM mcr.microsoft.com/dotnet/runtime-deps:8.0-jammy

ENV DEBIAN_FRONTEND=noninteractive
ENV RUNNER_MANUALLY_TRAP_SIG=1
ENV ACTIONS_RUNNER_PRINT_LOG_TO_STDOUT=1
ENV ImageOS=ubuntu22

# 'gpg-agent' and 'software-properties-common' are needed for the 'add-apt-repository' command that follows
RUN apt update -y \
    && apt install -y --no-install-recommends sudo lsb-release gpg-agent software-properties-common curl jq unzip \
    && rm -rf /var/lib/apt/lists/*

# Configure git-core/ppa based on guidance here:  https://git-scm.com/download/linux
RUN add-apt-repository ppa:git-core/ppa \
    && apt update -y \
    && apt install -y git \
    && rm -rf /var/lib/apt/lists/*

RUN adduser --disabled-password --gecos "" --uid 1001 runner \
    && groupadd docker --gid 123 \
    && usermod -aG sudo runner \
    && usermod -aG docker runner \
    && echo "%sudo   ALL=(ALL:ALL) NOPASSWD:ALL" > /etc/sudoers \
    && echo "Defaults env_keep += \"DEBIAN_FRONTEND\"" >> /etc/sudoers

WORKDIR /home/runner

COPY --chown=runner:docker --from=build /actions-runner .
COPY --from=build /usr/local/lib/docker/cli-plugins/docker-buildx /usr/local/lib/docker/cli-plugins/docker-buildx

RUN install -o root -g root -m 755 docker/* /usr/bin/ && rm -rf docker

USER runner

Trên thực tế thì, khi chúng ta sử dụng GitHub Actions, sẽ có rất nhiều trường hợp cần chạy container job và đòi hỏi runner phải có Docker daemon hay Docker host. Khi runner của chúng ta triển khai bằng ARC trên Kubernetes, bản thân nó đang chạy ở dạng container (Pod), việc cài đặt Docker engine trên một container người ta hay gọi là Docker in Docker (DinD)

Với image ở trên chúng ta chỉ mới có docker client, để runner có thể chạy được container job chúng ta thấy trên chart gha-runner-scale-set có một thiết lập containerMode.type=dind trong values.yaml, theo như giải thích thì với cấu hình này, runner chạy với 2 container, trong đó 1 container là docker.io/docker:dind đóng vài trò là docker host. Còn container còn lại, sử dụng image ghcr.io/actions/actions-runner và nó sử dụng DOCKER_HOST lấy từ container docker:dind.

...
template:
  spec:
    initContainers:
    - name: init-dind-externals
      image: ghcr.io/actions/actions-runner:latest
      command: ["cp", "-r", "-v", "/home/runner/externals/.", "/home/runner/tmpDir/"]
      volumeMounts:
        - name: dind-externals
          mountPath: /home/runner/tmpDir
    containers:
    - name: runner
      image: ghcr.io/actions/actions-runner:latest
      command: ["/home/runner/run.sh"]
      env:
        - name: DOCKER_HOST
          value: unix:///var/run/docker.sock
      volumeMounts:
        - name: work
          mountPath: /home/runner/_work
        - name: dind-sock
          mountPath: /var/run
    - name: dind
      image: docker:dind
      args:
        - dockerd
        - --host=unix:///var/run/docker.sock
        - --group=$(DOCKER_GROUP_GID)
      env:
        - name: DOCKER_GROUP_GID
          value: "123"
      securityContext:
        privileged: true
      volumeMounts:
        - name: work
          mountPath: /home/runner/_work
        - name: dind-sock
          mountPath: /var/run
        - name: dind-externals
          mountPath: /home/runner/externals
    volumes:
    - name: work
      emptyDir: {}
    - name: dind-sock
      emptyDir: {}
    - name: dind-externals
      emptyDir: {}
...

Như vậy, đây là cách chính thống để giải quyết DinD cho GitHub ARC.

Ở các bài viết tiếp theo, mình sẽ giới thiệu 1 cách nữa để thiết lập docker trên runner.

Chúc thành công,

ANH NGUYỄN

Hiện tại mình đang tìm kiếm công việc mới với nhiều thử thách để chinh phục.

Mọi thông tin có thể gửi về me@nvtienanh.info.