Spot Jenkins 에이전트 — 부팅마다 git pull

CI·CD2분조회

Jenkins Agent 를 Spot 인스턴스로 돌리면 비용은 싸지만 문제가 하나 있습니다. Spot 은 회수되면 새 인스턴스로 다시 뜹니다. 새로 뜬 인스턴스는 AMI 를 생성한 시점의 설정을 그대로 갖고 있습니다. 그동안 배포 스크립트나 Ansible inventory 가 바뀌었으면, 새 Agent 는 옛날 것으로 빌드하게 됩니다.

AMI에 포함된 설정은 최신화가 안 됨

Agent 의 배포 스크립트와 inventory 를 AMI 에 넣어두면, AMI 를 생성한 그 시점의 커밋으로 고정됩니다. 새 Spot 이 뜰 때마다 그 커밋이 그대로 올라오니, Git 의 최신 커밋과 실제 Agent 가 쓰는 버전이 계속 벌어집니다. AMI 를 새로 생성해야 따라잡히는데 이건 무거운 작업이라 자주 하기 어렵습니다.

설정을 Git 에 두고, 인스턴스가 뜰 때마다 최신을 당겨오게 하면 이 문제가 없어집니다.

@reboot에 건 git pull

시스템 전체 crontab(/etc/crontab)에 @reboot 을 겁니다. 이건 AMI 에 포함되므로 새 인스턴스에서도 그대로 동작합니다.

@reboot root /opt/app/update-agent-scripts.sh

/etc/crontab 은 사용자 계정 칸이 있는 시스템 crontab 이라 명령 앞에 실행 계정(root)을 적어야 합니다. 이걸 빠뜨리면 그 줄이 통째로 무시됩니다. @reboot 은 부팅 때 한 번 실행됩니다. Spot 이 새로 뜨는 것 = 부팅이니, 새 인스턴스가 시작될 때마다 이 스크립트가 돕니다.

스크립트는 설정 저장소를 최신화합니다.

#!/bin/bash
cd /opt/app/infra-repo && git -C agent-config pull origin main

저장소는 AMI 생성 단계에서 미리 git clone 해둡니다. 그러면 새 인스턴스는 처음 clone 을 받는 게 아니라 git pull 로 차이만 당겨오면 됩니다. 빠르고, 네트워크 문제에도 덜 취약합니다.

재부팅부터 빌드까지의 흐름

Spot VM 새로 시작 (ASG + Launch Template)
    → AMI에 든 /etc/crontab 의 @reboot 실행
    → update-agent-scripts.sh 실행
    → git pull origin main (스크립트·inventory 최신화)
    → Jenkins Master 가 SSH 로 Agent 연결
    → 빌드 시작

빌드가 시작되는 시점엔 이미 최신 설정이 올라와 있습니다. Jenkinsfile 은 그 로컬 고정 경로의 inventory 를 참조합니다.

inventory: "/opt/app/scripts/ansible/inventory/aws_ec2.yml"

경로는 고정이지만 내용은 매 부팅 때 최신화되니, Jenkinsfile 을 건드릴 필요가 없습니다.

이 방식을 택한 이유

  • AMI 를 다시 생성하지 않아도 됩니다. 설정 변경은 Git push 로 끝나고, 다음에 뜨는 Agent 가 자동으로 반영합니다.
  • Agent 가 상태를 안 들고 있습니다. 언제 회수되고 언제 새로 떠도, 뜰 때마다 같은 최신 상태로 수렴합니다. Spot 처럼 수시로 교체되는 워크로드에 맞습니다.

@reboot 대신 부팅 후 주기적 git pull(cron 5분) 을 걸 수도 있지만, Agent 는 뜨는 시점에만 최신이면 충분하고 그 뒤로는 설정이 안 바뀌므로 @reboot 한 번이 맞습니다.

  1. 불러오는 중