Spot Jenkins 에이전트 — 부팅마다 git pull
Jenkins Agent 는 Spot 인스턴스로 띄웠고, 빌드가 몰릴 때만 여러 대가 필요하고 평소에는 노는 자리라, 온디맨드보다 훨씬 싼 데다 회수당해도 새 인스턴스가 떠서 이어받으면 그만입니다.
빌드에 필요한 게 미리 깔려 있어야 하니 AMI 를 만들어 두고 그걸로 띄웁니다. 배포 스크립트와 Ansible inventory 도 그 AMI 안에 같이 넣어 뒀습니다.
문제는 그 새로 뜨는 자리에서 났습니다. 새 인스턴스에 들어 있는 건 AMI 를 생성한 시점의 파일이고, 그동안 Git 쪽 배포 스크립트와 inventory 는 계속 바뀌었습니다. Spot 은 수시로 회수되고 새로 뜨니 이 격차를 만나는 빈도도 그만큼 높습니다.
AMI에 포함된 설정은 최신화가 안 됨
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
git -C /opt/app/scripts 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 은 Agent 로컬의 고정 경로에 있는 inventory 를 그대로 참조합니다.
inventory: "/opt/app/scripts/ansible/inventory/aws_ec2.yml"
경로는 고정이지만 내용은 매 부팅 때 최신화되니 Jenkinsfile 을 건드릴 필요가 없습니다.
다만 @reboot 의 git pull 과 Master 의 SSH 접속 사이에 순서를 보장하는 장치는 없습니다. pull
이 끝나기 전에 Master 가 붙어 빌드가 시작될 수 있으니, 순서가 중요한 파이프라인이라면 Agent 를
연결 가능 상태로 만드는 시점 자체를 pull 뒤로 미루는 장치가 따로 필요합니다.
AMI 재생성 주기에 설정을 안 묶는 것
AMI 를 다시 생성하지 않아도 되는 게 제일 큰데, 설정 변경은 Git push 로 끝나고 다음에 뜨는 Agent 가 알아서 반영하니 무거운 AMI 재생성 주기에 설정 최신화가 묶이지 않고, Agent 를 stateless 하게 둘 수 있는 것도 덤입니다. 언제 회수되고 언제 새로 떠도 뜰 때마다 같은 최신 상태로 수렴하니 Spot 처럼 수시로 교체되는 워크로드에 맞습니다.
@reboot 대신 5분마다 도는 cron 으로 git pull 을 걸 수도 있지만, Agent 는 뜨는 시점에만
최신이면 충분하고 그 뒤로는 설정이 안 바뀌니 @reboot 한 번이면 됩니다.
댓글 0