
AI가 시키는 대로 GitLab Runner를 EKS에 배치했다가, CI 환경이 망가져서 전부 다시 만든 이야기
요약
GitLab CI/CD 환경에서 VPC 내 리소스 접근을 위해 EKS에 Runner를 배치했다가, 운영 효율성과 순환 참조 문제로 인해 EC2 기반 Runner로 재구축한 사례를 다룹니다. AI의 조언을 맹목적으로 따르기보다 운영 환경의 특성을 고려한 아키텍처 설계의 중요성을 강조합니다.
핵심 포인트
- VPC 내부 리소스 접근을 위한 Self-hosted Runner 구축 경험
- EKS 기반 Runner 운영 시 EKS 파괴/재생성 시 발생하는 관리 이슈
- AI 제안의 기술적 타당성과 실제 운영 환경 간의 괴리 주의
- 비용 절감을 위한 인프라 On/Off 전략에 따른 Runner 배치 결정

개요
GitLab CI/CD에서 VPC 내의 리소스(Vault 등)에 액세스하기 위해, 처음에는 EKS 위에 self-hosted Runner를 구축했으나, 운영 요건과의 불일치로 인해 EC2 기반의 Runner로 재구축한 구성 변경 기록입니다.
왜 EKS로는 안 되었는지에 대한 아키텍처의 함정과 구체적인 Terraform 구현 예시, 그리고 그로부터 얻은 설계의 교훈을 공유합니다.
대상 독자
- GitLab CI/CD를 사용 중이며, Shared Runner의 한계에 부딪힌 분
- EKS를 사용 중이며, Runner를 어디에 배치할지 고민 중인 분
- AI가 말하는 대로 그대로 구현했다가 되돌아온 경험이 있는 분 (동지입니다)
배경
Test 환경을 구축해 나가는 과정에서, Vault(시크릿 관리 도구)나 RDS 등 VPC 내부에만 존재하는 리소스에 CI에서 접근하고 싶은 상황이 발생했습니다.
그런데 GitLab의 Shared Runner는 VPC 외부에 있기 때문에, 애초에 VPC 내부로 도달할 수 없다는 것을 알게 되었습니다.
GitLab Shared Runner (VPC 외)
→ Vault (VPC 내) ← 도달할 수 없음!
"어떡하지"라고 생각하며 AI에게 물어보니, "self-hosted Runner를 EKS에 배치하면 됩니다"라는 답변을 들었습니다. 공식 문서도 확인해 보니 EKS에 Runner를 배치하는 절차가 제대로 적혀 있어서, "과연, 이걸로 되겠네!"라고 생각하며 진행했습니다.
문서 자체는 틀리지 않았습니다. 문제는 다른 곳에 있었습니다.
했던 일 ①: EKS에 Runner를 배치하는 구현 (나중에 전부 다시 함)
AI의 조언대로, EKS 내부에 GitLab Runner를 Helm으로 배포하는 구현을 진행했습니다.
보안도 제대로 고려하며(고려했다고 믿으며) 구현했습니다.
고안한 포인트:
- Runner 토큰은 Vault → ESO → K8s Secret을 경유하여 주입 (Terraform state에 포함하지 않음)
privileged: false로 컨테이너의 특권 승격(Privilege Escalation) 방지- node_selector를 사용하여 system 노드에 전용 배치
[runners.kubernetes]
namespace = "{{.Release.Namespace}}"
image = "alpine:3.20"
...
CI 태그도 설정하여 모든 작업(Job)이 self-hosted runner에서 동작하도록 했습니다.
default:
tags:
- self-hosted
...
"좋아, 이제 VPC 내의 리소스에도 도달할 수 있어!"라고 생각하며 리뷰를 올렸습니다.
막혔던 포인트
리뷰에서 "순환 참조(Circular Dependency)가 발생한다"는 말을 들었다
리뷰 코멘트를 확인해 보니, 다음과 같은 지적이 있었습니다.
처음에는 "복구 절차를 문서에 적어두면 될까"라고 생각했지만, 코멘트를 읽으며 깊이 생각해보니 더 근본적인 문제가 있다는 것을 깨달았습니다.
애초에 Test 환경은 EKS를 중지하거나 파괴하는 운영 방식으로 갈 예정이었다
비용 절감을 위해, Test 환경은 필요할 때만 EKS를 기동하고, 사용하지 않을 때는 중지하거나 destroy 하는 운영 방식을 상정하고 있었습니다.
EKS 내부에 Runner를 두면, EKS를 중지할 때마다 Runner도 사라지게 됩니다. 그때마다 매번 수동으로 셋업을 해야 합니다. 이것은 도저히 운영할 수 없는 방식입니다...
문서로 해결할 수 있는 문제가 아니라, 아키텍처의 문제였습니다.
했던 일 ②: EC2 Runner로 다시 만들기
리뷰에서 순환 참조 문제를 지적받고, "그럼 어떻게 해야 하지?"라고 생각했습니다. EKS 외부에 두면 된다면, EC2에도 Runner를 세울 수 있을까? 하고 찾아보니 가능하다는 것을 알게 되어 EC2로 전환하기로 했습니다.
EC2 Runner (VPC 내, EKS와는 독립적으로 상주)
→ Vault (VPC 내) ← 도달 가능!
→ EKS가 destroy 되어도 Runner는 살아있음 ← 해결!
...
EC2 인스턴스 설정
resource "aws_instance" "gitlab_runner" {
ami = var.ami_id # Amazon Linux 2023 (AMI를 고정하여 의도하지 않은 업데이트 방지)
instance_type = var.instance_type
...
SG는 outbound만 개방
SSH는 SSM Session Manager로 대체할 수 있으므로, inbound는 완전히 폐쇄했습니다.
resource "aws_security_group" "gitlab_runner" {
name = "${local.name_prefix}-fw-gitlab-runner"
description = "GitLab Runner EC2: HTTPS outbound only"
...
IAM은 최소 권한으로
Runner 토큰을 SSM Parameter Store에서 가져오기만 하면 되므로, 권한은 이것만으로 제한했습니다.
# SSM Session Manager (SSH 불필요 액세스)
resource "aws_iam_role_policy_attachment" "gitlab_runner_ssm" {
role = aws_iam_role.gitlab_runner.name
...
user_data로 셋업 자동화
EC2가 기동될 때, SSM에서 Runner 토큰을 가져와 자동으로 등록하도록 설정했습니다.
#!/bin/bash
set -euo pipefail
# Docker 설치
...
첫 셋업만큼은 수동 작업이 필요
Runner가 존재하지 않는 상태에서는 CI를 통해 apply할 수 없으므로, 처음 한 번은 로컬에서 실행해야 했습니다.
# 1. CMK의 alias를 확인한다 (terraform apply 후에 확인 가능)
terraform output runner_token_kms_key_alias
# → alias/aidd-infra-test-gitlab-runner-token
...
--key-id를 잊으면 AWS managed key로 암호화되어 CloudTrail을 통한 추적이 불가능해지므로 주의해야 합니다. terraform output으로 key alias를 확인한 뒤 등록하도록 했습니다.
리뷰에서 "t3.micro는 부족할지도 모른다"는 말을 들었지만 무시했다가 막혔다
리뷰 코멘트에서 다음과 같은 지적도 있었습니다.
Terraform 작업은 비교적 메모리를 많이 소비하므로, 제한이 없으면 system 노드의 리소스를 예상치 못하게 모두 써버릴 가능성이 있음
이 시점에서는 실제로 잘 돌아가고 있었기에 "괜찮겠지"라고 생각하며 뒤로 미뤄두었습니다.
그 후, 제대로 막혔습니다. Terraform이 무거워져서 t3.micro로는 프로세스가 다운되기 시작했고, 결국 t3.small로 변경하게 되었습니다. 리뷰에서 말해줬을 때 바로 수정했어야 했습니다. 반성합니다.
요약
| EKS Runner (폐기) | EC2 Runner (채택) |
|---|---|
| EKS destroy의 영향 | 매일 사라짐 😇 |
| ... |
한 일: EKS에 GitLab Runner를 두려고 시도함 → 리뷰를 통해 EC2로 변경함
근본 원인: AI가 틀린 것이 아니라, 내가 "Vault에 연결하고 싶다"라는 목적만 보고 있었고, 환경의 전제 조건을 제대로 전달하지 못했다는 점. 그리고 스스로도 전체를 조망하며 생각하지 못했다는 점.
전달한 질문: "VPC 내의 리소스에 CI에서 접근하려면?"
부족했던 정보: "EKS를 중지하거나 파괴하는 운용을 해나갈 환경"
↓ 만약 처음부터 이렇게 물었다면
...
이것은 Claude 자체에도 똑같이 적용되는 이야기인데, Claude는 매번 컨텍스트가 리셋됩니다. "지난번에 이렇게 말했으니 알고 있겠지"는 통하지 않습니다. 매번 제대로 전제 조건을 전달해야 합니다.
이를 위해 .claude/CLAUDE.md에 프로젝트의 전제 조건을 정리해 두면, 매번 읽어 들일 수 있어 조금 더 수월해질 것이라고 생각합니다. 전부 다 적을 수는 없더라도, 환경 구성이나 운용 전제 등 요점만이라도 말이죠.
결국 AI와 잘 지내기 위해서는, 자신이 환경과 영향 범위를 제대로 파악하고 있는 것이 가장 중요하다는 것을 뼈저리게 느꼈습니다. AI는 올바르게 대답해 주지만, 올바른 질문을 하는 것은 자신의 몫이네요💪
끝까지 읽어주셔서 감사합니다!
참고
- GitLab Runner Helm chart 설치 절차
- GitLab Runner Helm chart values.yaml 레퍼런스 (Reference)
- GitLab Runner 새로운 토큰 등록 방식 (glrt- 접두사)
- AWS SSM Session Manager
- AWS SSM Parameter Store
- Terraform aws_instance 리소스
- External Secrets Operator 문서
집필자 소개 / 회사 정보
집필자
higu
BREXA SOLVIA SES
배정처: 주식회사 Scalar
최근에는 인프라를 공부하고 있습니다. Terraform을 다루기 시작한 지 얼마 되지 않아 매일 무언가에 막히곤 합니다... (웃음)
회사 정보
Scalar, Inc는 "데이터 매니지먼트(Data Management)의 미래를 만든다"를 내걸고, 데이터베이스 미들웨어의 연구 개발 및 판매를 수행하는 일본 기반의 글로벌 스타트업 기업입니다!
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기