This page contains information related to upcoming products, features, and functionality. It is important to note that the information presented is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. The development, release, and timing of any products, features, or functionality may be subject to change or delay and remain at the sole discretion of GitLab Inc.
Status Authors Coach DRIs Owning Stage Created
ongoing @igorwwwwwwwwwwwwwwwwwwww @ggillies @andrewn @marin @fzimmer 2023-07-31

Runway: GitLab을 위한 PaaS

요약

Runway는 GitLab을 위한 내부적인 플랫폼으로, 팀이 서비스를 신속하고 안전하게 배포하고 실행할 수 있도록 하는 것을 목표로 합니다.

동기

이 섹션은 명시적으로 동기, 목표 및 비목표를 나열하는 데 사용됩니다. 이 설계도 내에서 계획에 대한 더 넓은 GitLab 커뮤니티에서의 관심을 보여주는 이슈에 대한 링크를 선택적으로 제공할 수 있습니다. 경쟁 제품 및 서비스에 대한 문서의 링크도 권장됩니다.

이 계획에 대한 근본적인 동기는 서비스 통합 설계도에서 다뤘습니다. 이 설계도는 해당 제안에서 제시된 전략적 요구 사항의 구체화로 간주될 수 있습니다.

목표

  • 인프라 관리, 확장, 모니터링에 대해 과도한 걱정 없이 서비스를 배포하려는 개발 팀.
  • 상태가 없으므로 자동으로 확장하여 수요를 충족시킬 수 있는 위성 서비스에 중점을 둡니다.
  • 기존 GitLab 기능 및 도구와 통합하여 간소화된 경험을 제공하는 데 초점을 두고 있습니다.

비목표

  • GitLab 모놀리스 호스팅: 모놀리스는 매우 특수한 요구 사항을 가진 복잡한 응용 프로그램이며, 이에 따라 충족되지 않습니다. 모놀리스의 배포는 납품팀이 소유하며, 이를 위해 Cells 등 해당 공간을 대상으로 한 다른 도구 및 이니셔티브가 있습니다.
  • 임의의 GCP 자원: 일부 일반적으로 사용되는 GCP 자원을 지원할 수 있지만, 지원할 자원을 선택적으로 처리할 것입니다. 더 큰 유연성이 필요한 경우 GitLab Sandbox 프로젝트를 요청할 수 있습니다.
  • 임의의 Kubernetes 자원: 관리 플랫폼으로서 기반이 되는 배치 메카니즘을 너무 많이 노출시키지 않는 것을 목표로 합니다. 이로써 지원할 자원을 잘 지원하고 공급업체를 변경할 유연성을 제공합니다. 특수 요구 사항이 있는 경우, 고유의 Kubernetes 클러스터를 얻는 것이 더 나은 옵션일 수 있습니다.

제안

Runway는 서비스를 Docker 이미지로 패키지화하여 프로덕션 환경으로 배포하는 수단입니다. 이를 위해 GitLab CI/CD 및 기타 GitLab 제품 기능을 활용합니다.

설계 및 구현 세부 정보

Runway의 설계는 개별 컴포넌트를 서로 변경하고 대체할 수 있는 방식으로 분리되도록 하였습니다.

아키텍처

Runway 아키텍처

다이어그램 원본

초기 아키텍처 토론

프로비저너

프로비저너는 나머지 시스템에서 필요한 서비스 계정 및 최소한의 리소스를 생성하는 특권 있는 코드입니다.

이 프로세스는 “테스트 공간을 만들어 주세요”라는 요청을 수신하고 해당 공간에 필요한 최소한의 인프라를 생성합니다. 더 이상 필요하지 않은 경우 해제하는 것도 담당합니다.

  • 현재 Terraform을 기반으로 하고 있습니다.
  • Terraform은 프로비저너 프로젝트에서 CI를 통해 실행됩니다.
  • 우리는 Terraform 상태를 GitLab Terraform 상태 백엔드에 저장합니다.

조정자

조정자는 시스템의 핵심 역할을 합니다. 원하는 세계의 보기를 만들고(서비스 정의 및 현재 버전에 기초하여) 실제 상태에서의 차이를 찾은 후 해당 차이를 적용하는 것이 이의 책임입니다.

새 버전의 서비스를 배포하는 것은 조정자를 호출하는 문제입니다.

이 프로세스는 서비스 개발자로부터 아티팩트(예: Docker 이미지)를 수신하고 실행 환경으로 가져오는 것을 책임집니다. 이에는 롤아웃 전략, 롤백, 카나리 배포, 다중 환경 프로모션, 실패한 배포에 대한 진단 도구가 포함됩니다. 이러한 기능 중 일부는 런타임에도 위임될 수 있습니다. 또한, 기존 코드 베이스를 배포에 연결하는 표준 방법이 있어야 합니다.

  • 현재 Terraform을 기반으로 하고 있습니다.
  • Terraform은 서비스 프로젝트의 다운스트림 파이프라인으로부터 트리거된 배포 프로젝트에서 CI를 통해 실행됩니다.
  • 우리는 Terraform 상태를 배포 프로젝트의 GitLab Terraform 상태 백엔드에 저장합니다.

조정자와의 사용자 대면 통합은 서비스 프로젝트에서 CI 구성에 포함되는 ci-tasks/service-project/runway.yml에서 버전이 잠겨있는 CI 작업을 통해 중재됩니다.

런타임

런타임은 실제로 서비스 워크로드를 스케줄링하고 실행하는 것을 책임집니다. 조정자는 런타임을 대상으로 합니다. 런타임은 일정 수준의 테넌트 분리를 제공하는 자동 확장 컴퓨팅 자원을 제공합니다. 선택적으로 작업 부하가 도달할 수 있는 엔드포인트를 노출할 수도 있습니다. 이 엔드포인트에는 DNS 이름이 있고 TLS로 암호화될 것입니다.

  • 현재 Cloud Run을 기반으로 합니다.
  • 보다 더 큰 유연성이 필요한 경우, Knative가 가능한 마이그레이션 대상입니다.

서비스는 HTTP 포트를 노출해야 하며, 상태가 없어야 합니다(인스턴스의 자동 확장 허용). 기타 실행 모델(예: 예약된 작업)도 향후 지원될 수 있습니다.

Runtime에서 사용하는 이미지

Runway에 의해 배포된 이미지들은 서비스를 책임지는 팀에 의해 빌드됩니다. 이들은 이미지를 원하는 방식으로 빌드할 수 있으며, 서비스 프로젝트의 GitLab 컨테이너 레지스트리에 유지할 수 있습니다. Runway 배포 프로세스의 일환으로, 해당 이미지는 Cloud Run에서 사용되기 전에 GCP Artifact Registry로 미러링됩니다. 여기에는 두 가지 이유가 있습니다.

  1. Cloud Run은 GCP Artifact Registry에서만 이미지를 사용할 수 있습니다.
  2. 이는 미래에 이미지 태그가(실수로) 변경된 경우, Runway 내에서 실행 중인 이미지에 영향을 미치지 않는다는 것을 의미합니다.

GCP 프로젝트 레이아웃

Runway는 현재 세 개의 환경(dev, staging, production)을 기반으로 하는 공유 GCP 프로젝트를 사용합니다. 이 GCP 프로젝트는 다음과 같습니다.

  • Dev: runway-dev-527768b3 (IT에 의해 관리됨 HackyStack)
  • Staging: gitlab-runway-staging (신뢰성에 의해 관리됨)
  • Production: gitlab-runway-production (신뢰성에 의해 관리됨)

Runway에서 사용하는 문서 및 스키마

Runway가 작동하려면 사용 중인 두 개의 JSON/YAML 문서가 있습니다.

  1. Runway 인벤토리 모델. 현재 Runway에 입점된 서비스 프로젝트를 다룹니다. 여기에 위치합니다. 문서를 유효성 검사하는 데 사용되는 스키마는 여기에 있습니다. 이 문서 스키마의 변경에 대한 역호환성 보장은 없습니다. 이는 Runway 팀 내부에서만 사용되며, 실제로 Runway 서비스를 협의/비협의하는 데 사용되는 단일 문서만 있습니다.

  2. Runway 서비스 모델. 이는 Runway 사용자가 서비스를 배포하기 위해 Runway에 필요한 구성을 전달하는 데 사용됩니다. 이는 사용자의 서비스 프로젝트 내에 있는 .runway/runway.yml에 위치합니다. 예시는 여기에 있습니다. 문서를 유효성 검사하는 데 사용되는 스키마는 여기에 있습니다. 모델에 계속해서 개선 및 변경을 하겠지만, 동일한 kind/apiVersion 내에서의 변경은 모두 역호환성이 있어야 합니다. 파괴적인 변경을 하려면, 새로운 apiVersion의 스키마가 출시될 것입니다. 전반적인 목표는 Kubernetes 모델 API 변경을 복사하는 것입니다.

Runway 사용자가 Runway를 통해 GitLab CI를 통해 배포를 자동화하기 위해 사용하는 GitLab CI 템플릿도 있습니다. 사용자들은 CI 템플릿과 사용 중인 Runway 버전이 최신 상태인지 확인하기 위해 Renovate bot과 같은 도구를 사용하는 것이 좋습니다. Runway 팀은, 보안 문제가 식별될 때를 제외하고는, 출시된 모든 Runway 버전을 지원할 것입니다. 이런 경우, Runway 사용자들은 문제에 대한 수정이 포함된 Runway 버전으로 가능한 한 빨리 업데이트할 것으로 예상됩니다 (통보를 받은 후).

비밀 관리

비밀 관리를 위해, 기존 HashiCorp Vault 설정과 통합하기를 목표로 합니다. 우리는 Runtime이 가장 잘 통합되는 비밀 리포지터리로부터 Vault에서 비밀을 동기화할 것입니다. Cloud Run의 경우 Google Secret Manager를 사용할 것이며, Kubernetes의 경우 외부 비밀을 Kubernetes Secret 객체로 동기화하기 위해 external-secrets를 사용할 것입니다.

다음의 고수준 다이어그램은 Vault 내에서 비밀을 Runway을 통해 사용하기 위해 제안된 설정을 보여줍니다. 일반적인 개념은 최상위 네임스페이스인 /runway가 Vault에 생성되며, 다음과 같은 역할 및 정책이 있을 것입니다.

  • Runway 팀 구성원은 해당 네임스페이스에 대한 완전한 권한을 갖습니다.
  • CI에서 실행 중인 Runway 프로비저너가 dev, staging, production과 같은 환경에 있는 새 서비스 네임스페이스를 runway/env/$environment/service에서 생성/수정/삭제할 수 있습니다. 필요한 환경은 현재 dev, staging 및 production입니다.
  • Runway 조정자 서비스 계정 및 GitLab 팀 구성원은 배포를 위해 비밀을 읽기 위해 runway/env/$environment/service/$runway_service_id에 대한 읽기 권한이 필요합니다.
  • Runway 조정자는 Cloud Run에서의 원본 비밀을 Vault 내에서 Google Secrets Manager로 미러링할 것입니다.

Runway Vault Architecture

다이어그램 소스

Runway 컴포넌트 간의 신원 관리, 인증, 승인

Runway의 목표는 다음과 같이 Runway 컴포넌트 내에서 장기적인 비밀이나 토큰에 의존하지 않는 것입니다.

서비스 프로젝트에서 Runway 배포 프로젝트로

이는 GitLab 하류 파이프라인 트리거에 의해 처리됩니다. 따라서 모든 권한은 GitLab 자체에서 처리됩니다(그리고 GitLab의 API 호출은 새로운 CI_JOB_TOKEN을 사용합니다). 배포 프로젝트와 서비스 프로젝트 간의 API 호출에서 CI_JOB_TOKEN 허용 디렉터리이 사용됩니다(예: 서비스 프로젝트의 환경을 업데이트).

배포 프로젝트에서 GCP Cloud로

배포 프로젝트의 GitLab CI 파이프라인은 Runway 서비스에 대한 클라우드 리소스를 제공하고 변경하기 위해 GCP와 대화합니다. 이는 제한된 권한을 갖도록 GCP 서비스 계정으로 인증되도록 Runway 프로비저너에서 수행됩니다.

조정자에서 GCP Cloud로

(terraform을 감싸고 있는 runwayctl을 감싸고 있는)조정자는 배포 프로젝트의 GitLab CI 내에서 실행됩니다. 이는 각 Runway 서비스를 위해 특정 서비스 계정을 사용하며, 해당 작업을 위해 GCP API를 탐지할 수 있도록 특정 권한을 가집니다. 이 인증은 위에서 설명한 대로 GitLab CI에서 처리됩니다.

옵저버빌리티

옵저버빌리티는 별도의 청사진에서 다룰 예정입니다.

대안적 해결책

미관리된 GCP 프로젝트

관리되지 않는 플랫폼을 구축하는 대신 팀에게 GCP 프로젝트를 제공하고 그들에게 맡길 수 있습니다. 실제로, 우리는 몇 가지 서비스에 대해 이를 수행했습니다. 이는 우수한 격리 및 유연성을 제공하지만, 다음과 같은 몇 가지 문제가 있습니다.

  • 인프라스트럭처-코드 누락: 기존 구조가 없으면 팀은 UI를 통해 클라우드 리소스를 Terraform이나 유사한 IaC 도구를 사용하지 않고 만들어야 할 수도 있습니다. 이것은 변경을 감사하고 여러 환경에서 인프라를 재구성하기가 매우 어렵게 만듭니다.
  • 잡데기: 합리적이고 안전한 기본값이 없으면 모든 서비스는 서비스를 배포하기 위한 자체적인 접근 방식을 개발해야 합니다. 이는 누구에게나 이 서비스에 기여하는 것이 매우 어렵게 만듭니다.
  • 비확장 가능 설계: 임의의 VM을 만들 수 있으므로 수평 확장에 대한 생각 없이 한 대의 기계에 서비스를 공존시키는 것이 매력적일 수 있습니다.

관리되지 않는 Kubernetes 클러스터 또는 네임스페이스

사용자 정의 플랫폼을 구축하는 대신, Kubernetes가 플랫폼이라고 결정하고, 팀이 자체 클러스터 또는 공유 클러스터의 자체 네임스페이스를 가질 수 있도록 할 수 있습니다.

이 접근 방식에는 몇 가지 도전 과제가 있습니다:

  • GKE의 기본 비용: 관리 비용은 월별 $70입니다. 여러 환경에서 많은 서비스를 가지려고 하면서 그 중 일부는 트래픽 양이 적을 수 있으므로, 각 서비스마다 별도의 클러스터를 갖는 것은 비용 효율적이지 않습니다. 이는 우리가 공유 클러스터를 사용하고 싶은 것으로 추정됩니다.
  • 개발자 친화성: Kubernetes는 인기를 끌고 있지만, 가장 개발자 친화적인 인터페이스는 아닙니다. 이해해야 할 개념과 추상화가 많습니다. 더 좁은 인터페이스인 “이 컨테이너를 배포하고 포트를 제공해주세요”는 유연성이 적지만 진입 장벽이 훨씬 낮습니다.

Runway가 더 이러한 방향으로 더 발전할 수도 있습니다.

서비스 당 GCP 프로젝트

GCP 프로젝트는 리소스 격리와 비용 할당을 위한 매우 견고한 기반을 제공합니다. 이러한 모델을 활용하는 것이 이상적일 것입니다. 그러나 공유 리소스의 부재는 서비스 당 상당한 기본 비용을 유발합니다.

GKE를 사용하려면, 서비스 당 클러스터 관리 비용이 월별 $70이므로, 마이크로서비스의 경우에는 이는 비용 효율적이지 않을 가능성이 높습니다.

고려할 대안은 GKE 없이 Kubernetes를 실행하는 것입니다. 그러면 Kubernetes 배포를 직접 관리하고, GKE와의 차이를 계속 파악해야 합니다.

또 다른 고려할 대안은 마이크로서비스에는 Cloud Run을 사용하고 큰 서비스에는 GKE를 사용하는 것입니다. 그러나 이 경우 Cloud Run과의 호환성을 유지하고, 기능 면에서 가장 저수준의 것으로 한정될 가능성이 있습니다.

하이브리드 방식도 가능합니다(예: Runway 서비스에 자체 프로젝트 제공), 그러나 공유 리소스가 있는 한, 리소스 당 권한 제어를 구현해야 합니다.