천만년만의 기술 글이다. 평소에 회사에서 사용하는 기술은 회사 내에만 적용하는 경우가 많아서 글로 적을만 한 것이 별로 없었는데, 이번 경험은 꽤 범용적이라고 생각하여 정리해본다.
GitHub Actions의 Self-hosted runner를 사용하고 있는데, 회사 내에 1대만 있어 오래 걸리는 테스트가 하나 들어가면 그 뒤가 한참 밀려버리는 문제가 있었다. 그래서 일단 2개로 늘려보자고 생각했고, 이를 다시 처음부터 세팅하기는 뭐가 있는지도 잘 모르고 여러모로 귀찮아서 이미 있던 인스턴스를 복제하여 사용하고자 했다. 새 환경이 되면 Git Repository나 Maven Repository, Gradle Cache 같은 것이 다 날아가는 것에 대한 속도 고려도 있었다.
사실은 Java 같은 것도 actions/setup-java 같은걸 사용해서 처음부터 세팅하는 것도 어렵지 않게 되어야 할 테지만 프로젝트가 많다 보니 일괄 적용은 아무래도 무리가 있다.
복제는 어렵지 않다. AMI 생성, 템플릿 생성하며 AMI 연결, 템플릿으로 인스턴스 생성, AMI 제거 순으로 하면 된다.
볼륨도 함께 다 스냅샷으로 만들어주는 기능이 제일 필요하다. '재부팅 안 함' 기능이 궁금하지만 '일관된 상태' 인지 잘 모르겠어서 그냥 기본 값으로 뒀다.
그냥 하면 된다. 스크린샷이 의미 있는지 잘 모르겠어서 넘긴다.
AMI 자체는 요금이 없는 것으로 보이지만, EBS 스냅샷은 확실히 과금이 있다.# 더 만들 거면 그때 가서 또 뜨면 되므로 그냥 삭제한다.
확실히 완전 복제는 아니고 템플릿을 이용한 신규 생성이라, 켜보면 hostname이 ip-XXX-XXX-XXX-XXX 형태로 되어 있다. hostnamectl set-hostname
으로 변경하면 된다.
이제 서비스를 등록해야 하는데, 해보면 이미 설정이 되어있다고만 나온다.
remove는 실행해보면 토큰을 받아서 지우는 형태로, 아예 등록된 Self-hosted runner에서 삭제하는 것이라 기존 인스턴스에서도 다시 등록해야 하므로 원하는 동작이 아니다.
문서를 찾아봐도 client 쪽에서만 인증 정보를 초기화하는 방법은 찾을 수 없었다. 오류 메시지가 있고, runner가 오픈소스이므로 추적해보기로 했다.
Self-hosted runner 위 메시지를 검색해보면 다음 위치를 찾을 수 있다.
actions/runner@da79ef4
/src/Runner.Listener/Configuration/ConfigurationManager.cs#L83-L86
if (IsConfigured())
{
throw new InvalidOperationException("Cannot configure the runner because it is already configured. To reconfigure the runner, run 'config.cmd remove' or './config.sh remove' first.");
}
따라가 보자.
actions/runner@da79ef4
/src/Runner.Listener/Configuration/ConfigurationManager.cs#L45-L47
public bool IsConfigured()
{
bool result = _store.IsConfigured();
actions/runner@7ffd9af
/src/Runner.Common/ConfigurationStore.cs#L168-L171
public bool IsConfigured()
{
Trace.Info("IsConfigured()");
bool configured = new FileInfo(_configFilePath).Exists;
actions/runner@7ffd9af
/src/Runner.Common/ConfigurationStore.cs#L145
_configFilePath = hostContext.GetConfigFile(WellKnownConfigFile.Runner);
actions/runner@a519f96
/src/Runner.Common/HostContext.cs#L294-L297
case WellKnownConfigFile.Runner:
path = Path.Combine(
GetDirectory(WellKnownDirectory.Root),
".runner");
actions/runner@a519f96
/src/Runner.Common/HostContext.cs#L237-L238
case WellKnownDirectory.Root:
path = new DirectoryInfo(GetDirectory(WellKnownDirectory.Bin)).Parent.FullName;
actions/runner@a519f96
/src/Runner.Common/HostContext.cs#L221-L222
case WellKnownDirectory.Bin:
path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
대충 정보는 다 나왔고 이제 어셈블리가 어디에 있는지만 알면 된다.
actions/runner@3ec20e9
/src/Misc/layoutroot/config.sh#L80
./bin/Runner.Listener configure "$@"
bin의 상위 폴더, 즉 config.sh 파일이 있는 경로에서 .runner 파일을 지워주면 되는 것이다. 진작에 ls -al
해 볼걸...
Kubernetes 안에 actions-runner-controller 설정해서 쓰고 싶다.