kt cloud가 상용 배포판이 아닌 Community OpenStack을 코어로 채택하면서, 코드부터 빌드·패치·검증·배포까지 전체 워크플로를 직접 소유해야 하는 상황에서 Zuul.CI 기반 Gating System을 구축한 사례다. Upstream 릴리스를 계속 반영하면서 자체 패치도 유지해야 하니 "여기서 발생하는 모든 변화를 어떻게 검증할 것인가"가 핵심 질문이 됐다. 결론은 검증 자산을 복사하지 말고 참조하라는 것이다.
핵심 포인트- Community 버전을 직접 쓰면 벤더가 하던 딜리버리·패치·책임을 대신할 파트너가 사라진다. 설치가 아니라 공급망 자체를 만들고 운영하는 일이 된다.
- Downstream 코드에서 Upstream의 기존 Job이 실패하면 기능 추가가 아니라 기존 기능의 회귀 신호이자 내재화 방향에 어긋난다는 뜻으로 봤다.
- Upstream Job을 복사해 오면 테스트 코드도 계속 바뀌기 때문에 복사하는 순간부터 어긋난다. Zuul.CI는 Job이 정의된 저장소를 등록·선언해 참조하는 모델이라 이 문제를 피한다.
- Job 상속으로 Upstream의 테스트 환경 구성·테스트 코드·수행 절차를 그대로 쓰되 검증 대상 코드만 Downstream으로 교체한다.
- Job을 실행할 Resource Provider로 다시 OpenStack을 써서 OpenStack으로 OpenStack을 검증하는 구조이고, 둘 다 Kubernetes 위에서 돈다.
상세 정리- 배경: 플랫폼이 성장하면서 이미지 자체 빌드, Helm Chart 수정·패키징, 드라이버 버그 패치, 신규 기능 개발 같은 자체 변경이 코드·이미지·차트 전반에 누적돼 Upstream과 Downstream 요소가 혼재하게 됐다.
- 정리 방향: Community OpenStack을 Upstream으로 삼고 kt cloud PLATFORM 설계에 맞춰 동작하는 자체 Downstream을 KTC OpenStack으로 내재화한다. Code에서 Image, Chart까지 전 체인을 지속적으로 돌아가는 파이프라인으로 만드는 일이다.
- 개발 원칙 셋: Upstream을 그대로 쓰는 것을 기본으로 하고, Upstream에 없으면서 꼭 필요한 기능이나 주요 버그 수정에 한정해 Downstream에서 자체 구현하며, 자체 구현분은 가능한 한 Upstream에 지속 기여한다.
- 용어 정리: Gating System은 변경 사항이 메인 브랜치에 병합되기 전 정의된 파이프라인과 Job으로 검증을 통과시키는 체계이고, Zuul.CI는 OpenInfra 재단이 실제로 이 용도로 쓰는 오픈소스다. Netflix의 게이트웨이 프레임워크 Zuul과는 다른 프로젝트라고 명시한다.
- Upstream 흐름: 개발자가 코드 리뷰 시스템 Gerrit에 코드를 올리면 Zuul.CI가 미리 정의된 파이프라인을 따라 Job을 실행해 변경을 검증한다.
- 도구 선택 근거: 테스트 실행 자체는 GitHub Actions나 Jenkins로도 가능하지만 문제의 본질이 끊임없이 변하는 Upstream의 검증 자산을 그대로 따라가는 것이었다. Zuul.CI의 참조 구조가 다른 도구와의 결정적 차이였다.
- 시스템 두 축: 게이팅 로직과 파이프라인을 관리하는 컨트롤 플레인인 Zuul.CI Cluster, 그리고 Job을 실제로 수행할 인프라 자원을 제공하는 Resource Provider로 구성된다.
- Resource Provider를 OpenStack으로 둔 이유는 Job 실행에 VM을 유연하게 프로비저닝할 IaaS가 필요한데 그 역할을 가장 잘하는 플랫폼이 이미 OpenStack이고, nested virtualization 같은 테스트 환경까지 그대로 재현할 수 있어서다.
- Job 상속 예시: ktc-neutron용 Job을 선언하면서 parent로 Upstream의 neutron-tempest-plugin-ovn-2025-1을 상속하고, required-projects에서 devstack과 requirements는 stable/2025.1로 고정한 뒤 검증 대상만 kt-cloud-stack/ktc-neutron으로 교체한다.
- devstack_plugins 변수의 neutron 항목도 ktc-neutron 저장소 URL로 바꿔, 테스트가 Downstream 코드 위에서 돌게 만든다.
- 파이프라인 등록: 선언한 Job을 ktc-neutron 프로젝트의 check 파이프라인 jobs 목록에 추가하는 것으로 연결이 끝난다.
- 실제 수행 내용: VM 1대(8코어 8GB)를 OpenStack Provider에서 KVM nested virt로 프로비저닝하고, Downstream ktc-neutron 코드를 체크아웃해 DevStack으로 OVN·Neutron·Nova·Keystone 등을 설치한 뒤, Upstream이 정의한 Tempest 케이스를 실행하고 로그와 결과를 수집한다.
- 작성량의 의미: 팀이 쓴 것은 수백 줄의 테스트 로직이 아니라 어떤 Upstream Job을 상속하고 어떤 코드로 동작시킬지를 선언하는 몇 줄뿐이다. 환경 구성과 검증 절차는 Upstream Job에 위임한다.
- 얻은 교훈: 복제해 둔 테스트 코드는 당장은 편하지만 Upstream이 바뀔 때마다 뒤처져 부채가 된다. 참조하고 상속하면 Upstream 변화가 자연스럽게 흘러들어와 애쓰지 않아도 최신 기준이 유지된다.
- 여기에 "Upstream Job은 반드시 통과한다"는 규칙 하나를 더하면 자기 코드가 기존 기능을 망가뜨리는 순간을 가장 빠르게 잡아낼 수 있다.
- 다음 계획: 적용 범위는 코드 검증을 넘어 실제 VM에 kt cloud PLATFORM 아키텍처대로 클러스터까지 자동 구성해 검증하는 데까지, 검증 범위는 Upstream Job을 넘어 자체 Job 설계까지 넓힐 예정이라고 밝힌다.
왜 읽나거대한 오픈소스를 포크해 자체 배포판으로 운영하는 팀이 Upstream 회귀를 어떻게 상시로 잡아낼지, CI 도구 선택의 기준을 무엇으로 둘지 판단할 때 참고가 된다.