Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions .github/workflows/gpu-runner-overlay2-smoke.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
name: GPU Runner overlay2 smoke test

on:
workflow_dispatch:
inputs:
image:
description: Container image used for the pull and GPU test
required: true
default: ghcr.io/deepmodeling/abacus-cuda:latest
type: string
pull_request:
paths:
- '.github/workflows/gpu-runner-overlay2-smoke.yml'

permissions:
contents: read

concurrency:
group: gpu-runner-overlay2-smoke
cancel-in-progress: false

jobs:
gpu-runner-smoke:
name: Validate overlay2, image pull, and GPU
runs-on:
- self-hosted
- gpu
- linux-x64
timeout-minutes: 30
env:
TEST_IMAGE: ${{ inputs.image }}

steps:
- name: Verify Docker storage driver
shell: bash
run: |
set -euo pipefail

driver="$(docker info --format '{{.Driver}}')"
docker_root="$(docker info --format '{{.DockerRootDir}}')"
driver_status="$(docker info --format '{{json .DriverStatus}}')"

echo "Docker storage driver: ${driver}"
echo "Docker root: ${docker_root}"
echo "Driver status: ${driver_status}"

{
echo "## GPU Runner smoke test"
echo
echo "- Runner: \`${RUNNER_NAME}\`"
echo "- Docker driver: \`${driver}\`"
echo "- Docker root: \`${docker_root}\`"
echo "- Test image: \`${TEST_IMAGE}\`"
} >> "${GITHUB_STEP_SUMMARY}"

if [[ "${driver}" != "overlay2" ]]; then
echo "Expected Docker storage driver overlay2, got ${driver}." >&2
exit 1
fi

- name: Pull test image and measure cold-pull time
id: cold_pull
shell: bash
run: |
set -euo pipefail

started_at="$(date +%s)"
docker pull "${TEST_IMAGE}"
finished_at="$(date +%s)"
pull_seconds="$((finished_at - started_at))"

image_size_bytes="$(docker image inspect "${TEST_IMAGE}" --format '{{.Size}}')"
image_size_gib="$(awk -v bytes="${image_size_bytes}" 'BEGIN { printf "%.2f", bytes / 1024 / 1024 / 1024 }')"

echo "seconds=${pull_seconds}" >> "${GITHUB_OUTPUT}"
echo "size_gib=${image_size_gib}" >> "${GITHUB_OUTPUT}"

{
echo "- Cold pull: \`${pull_seconds}s\`"
echo "- Image size: \`${image_size_gib} GiB\`"
} >> "${GITHUB_STEP_SUMMARY}"

- name: Validate warm-cache pull
id: warm_pull
shell: bash
run: |
set -euo pipefail

started_at="$(date +%s)"
docker pull "${TEST_IMAGE}"
finished_at="$(date +%s)"
pull_seconds="$((finished_at - started_at))"

echo "seconds=${pull_seconds}" >> "${GITHUB_OUTPUT}"
echo "- Warm pull: \`${pull_seconds}s\`" >> "${GITHUB_STEP_SUMMARY}"

- name: Run GPU smoke test inside the image
shell: bash
run: |
set -euo pipefail

docker run --rm --gpus all "${TEST_IMAGE}" nvidia-smi
echo "- GPU container test: **passed**" >> "${GITHUB_STEP_SUMMARY}"

- name: Report Docker disk usage
if: always()
shell: bash
run: |
docker system df || true
df -h /runner/_work || true

{
echo
echo "### Timings"
echo
echo "| Check | Result |"
echo "|---|---:|"
echo "| Cold pull | ${{ steps.cold_pull.outputs.seconds || 'failed' }}s |"
echo "| Warm pull | ${{ steps.warm_pull.outputs.seconds || 'failed' }}s |"
echo "| Image size | ${{ steps.cold_pull.outputs.size_gib || 'unknown' }} GiB |"
} >> "${GITHUB_STEP_SUMMARY}"
60 changes: 60 additions & 0 deletions docs/community/cicd/overlay2-runner-sample.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# CPU GitHub Actions Runner sample for ACK/ECI.
apiVersion: v1
kind: ConfigMap
metadata:
name: docker-daemon-cpu-overlay2
namespace: actions-runner-system
data:
daemon.json: |
{
"storage-driver": "overlay2",
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
---
apiVersion: actions.summerwind.dev/v1alpha1
kind: RunnerDeployment
metadata:
name: cpu-runner
namespace: actions-runner-system
spec:
template:
metadata:
annotations:
k8s.aliyun.com/eci-auto-imc: "true"
k8s.aliyun.com/imc-perfect-match: "true"
k8s.aliyun.com/eci-extra-ephemeral-storage: "120Gi"
k8s.aliyun.com/eci-schedule-strategy: VSwitchOrdered
k8s.aliyun.com/eci-use-specs: ecs.c6.2xlarge
spec:
organization: deepmodeling
labels:
- cpu
- self-hosted
- linux-x64
ephemeral: true
image: summerwind/actions-runner@sha256:ac52790f2737b2ef1be90a6708280cf2f0b2cf838f421ee7cce42d7511951976
imagePullPolicy: IfNotPresent
dockerEnabled: true
dockerVolumeMounts:
- name: docker-config
mountPath: /etc/docker/daemon.json
subPath: daemon.json
- name: docker-storage
mountPath: /var/lib/docker
volumes:
- name: docker-config
configMap:
name: docker-daemon-cpu-overlay2
- name: docker-storage
emptyDir: {}
nodeSelector:
type: virtual-kubelet
tolerations:
- key: virtual-kubelet.io/provider
operator: Equal
value: alibabacloud
effect: NoSchedule
Loading