InfoGrab DocsInfoGrab Docs

Ruby 업그레이드 가이드라인

요약

GitLab은 성능·보안 업데이트와 새 Ruby API의 이점을 얻기 위해 최신 Ruby MRI 릴리스로 GitLab을 운영하려고 합니다. Ruby 버전을 변경하기 전에 이 문서를 처음부터 끝까지 꼼꼼히 읽고 어떤 변경이 필요한지 큰 그림을 파악합니다.

GitLab은 성능·보안 업데이트와 새 Ruby API의 이점을 얻기 위해 최신 Ruby MRI 릴리스로 GitLab을 운영하려고 합니다. GitLab 전반의 Ruby를 업그레이드할 때는 다음을 만족하는 방식으로 진행해야 합니다.

  • 기여자에게 미치는 지장이 가장 적습니다.
  • GitLab.com 가용성에 맞춰 최적화합니다.
  • GitLab의 모든 구성 요소에서 Ruby 버전을 동일하게 유지합니다.

Ruby 버전을 변경하기 전에 이 문서를 처음부터 끝까지 꼼꼼히 읽고 어떤 변경이 필요한지 큰 그림을 파악합니다. Ruby 업그레이드는 매번 이전과 조금씩 다르므로, 문서에 적힌 단계의 순서와 필요성은 상황에 맞게 판단합니다.

Ruby 업그레이드 범위#

Ruby를 업그레이드할 때 가장 먼저 고려할 것은 범위입니다. 일반적으로 Ruby 업데이트가 필요할 수 있는 영역은 다음과 같습니다.

  • 메인 GitLab Rails 리포지터리.
  • 부수적인 Ruby 시스템 리포지터리.
  • 이러한 리포지터리의 시스템이 사용하는 서드파티 라이브러리.
  • 이러한 리포지터리의 시스템이 사용하는 GitLab 라이브러리.

이 모두를 항상 손대야 하는 것은 아닙니다. 예를 들어 패치 수준의 Ruby 업데이트라면 서드파티 gem까지 업데이트해야 할 가능성은 낮습니다.

패치, 마이너, 메이저 업그레이드#

범위를 판단할 때는 Ruby 버전 수준이 중요합니다. 예를 들어 패치 릴리스는 보통 보안 수정이나 버그 수정에 한정되므로, GitLab을 Ruby 2.7.2에서 2.7.4로 올리는 것보다 Ruby 2.x에서 3.x로 올리는 편이 더 어렵고 위험합니다. 업그레이드를 준비할 때 이 점을 염두에 두고 그에 맞춰 계획합니다.

향후 업그레이드의 범위를 가늠하는 데는 다음 업그레이드에 들어간 작업량을 참고합니다.

영향을 받는 대상 및 타깃#

업그레이드 전에 Ruby 업그레이드의 영향을 받는 순서대로 모든 대상과 타깃을 고려합니다.

  1. 개발자. GitLab과 관련 프로젝트에는 사내외의 기여자가 많습니다. .ruby-version 같은 파일을 변경하면 그 파일을 해석하는 도구를 쓰는 모든 사람이 영향을 받습니다. 개발자는 변경이 머지된 리포지터리를 가져오는 즉시 영향을 받습니다.
  2. GitLab CI/CD. GitLab은 코드 통합과 테스트에 CI/CD를 크게 활용합니다. CI/CD job은 .ruby-version 같은 파일을 해석하지 않습니다. 대신 .gitlab-ci.yml에 정의된, job 이 실행되는 Docker 컨테이너에 설치된 Ruby를 사용합니다. 이러한 job에서 사용하는 컨테이너 이미지는 gitlab-build-images 리포지터리에서 관리합니다. 이미지 업데이트를 머지하면 이미지가 빌드되는 즉시 CI/CD job 이 영향을 받습니다.
  3. GitLab.com. GitLab.com은 Cloud Native GitLab(CNG)의 Docker 이미지를 사용하는 맞춤 Helm 차트로 배포됩니다. CI/CD와 마찬가지로 이 환경에서 .ruby-version은 의미가 없습니다. 대신 Ruby를 업그레이드하려면 해당 Docker 이미지를 수정해야 합니다. GitLab.com은 다음 배포 시점에 영향을 받습니다.
  4. GitLab Self-Managed. Omnibus로 GitLab을 설치하는 고객은 위의 어느 것도 사용하지 않습니다. 대신 Ruby 버전은 Omnibus의 Ruby 소프트웨어 번들이 정의합니다. GitLab Self-Managed 고객은 이 변경이 포함된 릴리스로 업그레이드하는 즉시 영향을 받습니다.

Ruby 업그레이드 접근 방식#

Ruby 업그레이드의 모든 단계에서 시점을 정확히 잡는 것이 중요합니다. 일반적인 지침은 다음과 같습니다.

  • 프로덕션 동작이 바뀔 가능성이 낮은 소규모 업그레이드에서는 리포지터리와 프로덕션 사이의 버전 격차를 최소로 유지합니다. 이해관계자와 조율해 모든 변경을 (하루나 이틀 안에) 가깝게 머지해 격차가 벌어지지 않게 합니다. 이때는 개발자 도구와 환경을 먼저 업그레이드하고 프로덕션을 나중에 올리는 순서가 적절합니다.
  • 변경 규모가 크면 새 Ruby로 프로덕션에 나가는 위험이 큽니다. 이 경우 새 Ruby 버전과의 알려진 비호환을 모두 해결한 상태를 먼저 만든 다음, 프로덕션 엔지니어와 함께 GitLab 프로덕션 플릿의 일부에 새 Ruby를 배포합니다. 이때는 프로덕션을 먼저 업데이트하고 개발자 도구와 환경을 나중에 올리는 순서가 적절합니다. 이렇게 하면 프로덕션에서 치명적인 회귀가 발생했을 때 롤백하기 쉽습니다.

어느 쪽이든 과거 경험상 다음 접근 방식이 효과적이었으며, 일부 단계는 마이너·메이저 업그레이드에서만 필요할 수 있습니다. 앞서 설명한 것처럼 일부 단계는 병렬로 진행하거나 순서를 바꿀 수 있습니다.

에픽 생성#

이 작업을 에픽으로 추적하면 진행 상황을 파악하는 데 유용합니다. 규모가 큰 업그레이드라면 이해관계자가 최종 전환 시점을 알 수 있도록 에픽 설명에 일정을 포함합니다. 업그레이드의 성능 기준을 확인할 수 있도록 지정된 성능 테스트 템플릿도 함께 넣습니다.

개별 리포지터리의 변경은 이 에픽 아래 별도 이슈로 나눕니다.

업그레이드 의사 전달#

특히 기능을 도입하거나 지원 중단하는 업그레이드라면 업그레이드가 예정되어 있음을 가급적 일정과 함께 일찍 알립니다. 개발자가 변경 사항을 미리 익힐 수 있도록 중요하거나 눈여겨볼 만한 변경에 대한 링크를 제공합니다.

GitLab 팀원은 관련 Slack 채널(최소한 #backend와 #development)과 Engineering Week In Review(EWIR)에 의사를 알립니다. 공지에는 업그레이드 에픽 링크를 포함합니다.

CI/CD 및 개발 환경에 새 Ruby 추가#

새 Ruby로 Ruby gem과 GitLab Rails 애플리케이션을 빌드하고 실행하려면, 먼저 CI/CD와 개발자 환경에 새 Ruby 버전이 포함되도록 준비해야 합니다. 이 단계에서는 아직 기본 Ruby로 만들지 않고 선택 항목으로 둡니다. 이렇게 하면 일정 기간 동안 구 버전과 새 버전의 Ruby를 모두 지원해 전환이 매끄러워집니다.

변경이 필요한 곳은 두 군데입니다.

  1. GitLab Build Images. 러너와 그 밖의 Docker 기반 프리프로덕션 환경에서 사용하는 Docker 이미지입니다. 필요한 변경의 종류는 범위에 따라 다릅니다.
    • 패치 수준 업데이트에서는 RUBY_VERSION의 패치 수준만 올리면 충분합니다. 같은 마이너 릴리스를 기준으로 빌드하는 모든 프로젝트는 새 패치 릴리스를 자동으로 내려받습니다.
    • 메이저·마이너 업데이트에서는 업그레이드 과정에서 기존 이미지와 나란히 사용할 수 있는 새 Docker 이미지 세트를 만듭니다. 중요: /patches 디렉터리의 Ruby 패치 파일을 업그레이드 대상 Ruby 버전에 맞는 새 폴더로 모두 복사해야 하며, 그러지 않으면 패치가 적용되지 않습니다.
  2. GitLab Development Kit(GDK). 개발자가 선택할 수 있는 항목으로 새 Ruby를 추가하도록 GDK를 업데이트합니다. 보통은 .tool-versions에 추가하기만 하면 되며, 이렇게 하면 asdf 사용자가 혜택을 받습니다. 그 밖의 사용자는 직접 설치해야 합니다 (예시).

버전 업그레이드 규모가 크다면 Quality Engineering과 함께 테스트 계획을 세우는 것을 검토합니다.

서드파티 gem 업데이트#

패치 릴리스에서는 이 작업이 필요할 가능성이 낮지만, 마이너·메이저 릴리스에서는 gem 이 Ruby를 특정 버전으로 고정한 탓에 호환성이 깨지거나 Bundler 의존성 문제가 생길 수 있습니다. 이를 확인하는 좋은 방법은 gitlab-org/gitlab에 머지 리퀘스트를 만들어 무엇이 깨지는지 보는 것입니다.

GitLab gem 및 관련 시스템 업데이트#

GitLab 이 직접 관리하는 gem 이나 Ruby 애플리케이션에는 .ruby-version, .tool-versions, .gitlab-ci.yml 같은 빌드 설정이 들어 있으므로 이 작업은 대체로 필요합니다. GitLab Rails 애플리케이션이 새 Ruby에서 동작하기 위해 이러한 리포지터리를 반드시 업데이트해야 하는 것은 아니지만, 모든 리포지터리에서 Ruby 버전을 같은 단계로 유지하는 것이 바람직합니다. 마이너·메이저 업그레이드에서는 새 Ruby를 사용하는 CI/CD job을 이러한 리포지터리에 추가합니다. 빌드 매트릭스 정의를 사용하면 효율적으로 처리할 수 있습니다.

업데이트할 리포지터리 결정#

Ruby를 업그레이드할 때는 ruby/gems 그룹의 리포지터리 업데이트도 함께 검토합니다. 참고로 과거에 이들 프로젝트 일부의 Ruby를 업데이트한 머지 리퀘스트 목록은 다음과 같습니다.

이 가운데 어떤 리포지터리를 메인 GitLab 애플리케이션과 함께 반드시 업데이트해야 하는지는 다음을 기준으로 판단합니다.

  • Ruby 버전 범위.
  • 해당 서비스나 라이브러리가 GitLab 전체 동작에서 맡는 역할.

영향을 받을 수 있는 리포지터리 전체는 GitLab 프로젝트 목록을 참고합니다. 버전 업그레이드 규모가 작다면, 필수적이지 않거나 새 Ruby 버전에서 메인 애플리케이션 테스트 스위트가 회귀를 잡아낼 것이 확실한 라이브러리는 업데이트를 미뤄도 무방합니다.

Note

이 변경을 GitLab 애플리케이션 업데이트보다 먼저 머지해도 되는지는 해당 코드 오너와 상의합니다. 필요한 승인은 미리 받아 두되, 모든 준비가 끝날 때까지 머지는 미루는 편이 좋을 수 있습니다.

GitLab 애플리케이션 머지 리퀘스트 준비#

의존성을 업데이트하고 새 gem 버전을 릴리스했다면, gem 및 관련 시스템과 마찬가지로 메인 Rails 애플리케이션에도 필요한 변경을 적용할 수 있습니다. 여기에 더해 설치·업데이트 안내 문서의 버전 표기도 변경 사항에 맞춰 갱신합니다(예시).

Note

이 머지 리퀘스트의 시점에는 특히 주의해야 합니다. 머지되는 순간 모든 GitLab 기여자가 영향을 받고 변경 사항이 배포되기 때문입니다. 다른 모든 준비가 끝날 때까지 이 MR을 열어 두어야 하지만, 리드 타임을 줄이기 위해 승인은 미리 받아 두면 좋습니다.

개발자에게 업그레이드 시간 제공(유예 기간)#

새 Ruby를 선택 항목으로 제공하고 모든 머지 리퀘스트가 준비되었거나 머지되었다면, 개발자가 자신의 컴퓨터에 새 Ruby를 설치할 수 있도록 최소 1주일의 유예 기간을 두어야 합니다. GDK와 asdf 사용자는 gdk update로 자동으로 설치됩니다.

이 기간은 이번 업그레이드가 GitLab.com에 미칠 위험을 평가하기에 좋은 시점입니다. 메이저 버전 업그레이드처럼 위험이 큰 Ruby 업그레이드는 변경 관리 요청을 통해 인프라 팀과 변경 사항을 조율할 것을 권장합니다. 모두가 변경을 계획하고 준비할 시간을 갖도록 이 이슈는 일찍 만듭니다.

기본 Ruby로 설정#

알려진 버전 호환성 문제가 더 이상 없고 유예 기간이 지났다면, 영향을 받는 모든 리포지터리와 개발자 도구를 업데이트해 새 Ruby를 기본값으로 설정합니다.

이 시점에 GitLab Compose Kit(GCK)도 업데이트합니다. 이는 GitLab을 docker-compose로 실행하려는 사용자를 위한 대체 개발 환경입니다. 이 프로젝트는 러너와 같은 Docker 이미지를 사용하므로 해당 리포지터리의 변경과 보조를 맞춰야 합니다. 이 변경은 마이너·메이저 버전이 바뀔 때만 필요합니다 (예시).

앞서 말한 것처럼 Ruby 업그레이드가 SaaS 가용성에 미칠 영향이 불확실하다면, 단계적 롤아웃으로 프로덕션에서 문제없이 동작하는 것을 확인할 때까지 이 단계를 건너뛰는 것이 안전합니다. 이 경우 다음 단계를 먼저 진행하고, 검증 기간이 지난 뒤에 새 Ruby를 기본값으로 승격합니다.

CNG, Omnibus, Self-compiled 업데이트 및 GitLab MR 머지#

마지막 단계는 프로덕션에서 새 Ruby를 사용하는 것입니다. 이를 위해서는 Omnibus와 프로덕션 Docker 이미지가 새 버전을 쓰도록 업데이트해야 합니다.

프로덕션에서 새 Ruby를 사용하려면 다음 프로젝트를 업데이트합니다.

GitLab Helm Chart 같은 차트도 어떤 형태로든 Ruby를 사용한다면, 예를 들어 테스트 실행에 사용한다면 함께 업데이트해야 합니다(이 예시 참고). 다만 반드시 필요한 것은 아닐 수 있습니다.

변경 관리 요청을 제출했다면 인프라 엔지니어와 롤아웃을 조율합니다. 규모가 큰 업그레이드에서는 롤아웃 계획에 릴리스 매니저를 참여시킵니다.

보안 패치를 위한 패치 릴리스 및 백포트 생성#

업그레이드가 패치 릴리스였고 중요한 보안 수정이 포함되어 있다면, self-managed 고객에게 GitLab 패치 릴리스로 배포해야 합니다. 진행 방법은 릴리스 매니저에게 문의합니다.

Ruby 업그레이드 도구#

업그레이드 과정을 수월하게 해 주는 도구가 몇 가지 있습니다.

Deprecation Logger#

GitLab은 Ruby와 Rails의 지원 중단 경고를 전용 로그 파일 log/deprecation_json.log에도 기록하며(GitLab 로그 파일 위치는 GitLab 개발자를 위한 로깅 가이드 참고), 이는 테스트로 충분히 다루지 못한 코드를 찾는 단서가 됩니다.

GitLab.com의 경우 GitLab 팀원은 Kibana (https://log.gprd.gitlab.net/goto/f7cebf1ff05038d901ba2c45925c7e01)에서 이 로그 이벤트를 확인할 수 있습니다.

권장 사항#

업그레이드 과정에서는 다음 사항을 권장합니다.

  • 가능한 한 많은 변경을 앞당겨 처리합니다. 특히 마이너·메이저 릴리스에서는 애플리케이션 코드가 깨지거나 바뀔 가능성이 큽니다. 하위 호환이 유지되는 변경은 메인 브랜치에 머지해 Ruby 버전 업그레이드보다 먼저 독립적으로 릴리스합니다. 이렇게 하면 작은 단위로 움직이면서 프로덕션 환경의 피드백을 일찍 받을 수 있습니다.
  • 규모가 큰 업데이트에는 실험용 브랜치를 만듭니다. GitLab은 장기간 유지되는 토픽 브랜치를 대체로 피하지만, 피드백과 실험 목적으로는 새 Ruby로 실행할 때 CI/CD의 피드백을 꾸준히 받을 수 있는 브랜치가 유용합니다. 이 MR에서 볼 수 있듯이, 어떤 문제가 생길지 처음 가늠할 때 도움이 됩니다. 이러한 실험용 브랜치는 머지할 목적이 아니며, 필요한 변경을 모두 나누어 독립적으로 머지한 뒤 닫으면 됩니다.
  • 마일스톤 릴리스에 앞서 문제를 고칠 시간을 충분히 확보합니다. GitLab은 빠르게 움직입니다. Ruby 업그레이드에는 많은 MR을 보내고 리뷰받아야 하므로, 모든 변경은 릴리스일보다 최소 1주일 앞서 머지합니다. 그러면 문제가 생겼을 때 대응할 여유가 생깁니다. 판단이 서지 않는다면 속도보다 가용성을 우선하므로 업그레이드를 다음 달로 미루는 편이 낫습니다.

Ruby 업그레이드 가이드라인

GitLab v19.4
원문 보기

요약

GitLab은 성능·보안 업데이트와 새 Ruby API의 이점을 얻기 위해 최신 Ruby MRI 릴리스로 GitLab을 운영하려고 합니다. Ruby 버전을 변경하기 전에 이 문서를 처음부터 끝까지 꼼꼼히 읽고 어떤 변경이 필요한지 큰 그림을 파악합니다.

GitLab은 성능·보안 업데이트와 새 Ruby API의 이점을 얻기 위해 최신 Ruby MRI 릴리스로 GitLab을 운영하려고 합니다. GitLab 전반의 Ruby를 업그레이드할 때는 다음을 만족하는 방식으로 진행해야 합니다.

  • 기여자에게 미치는 지장이 가장 적습니다.
  • GitLab.com 가용성에 맞춰 최적화합니다.
  • GitLab의 모든 구성 요소에서 Ruby 버전을 동일하게 유지합니다.

Ruby 버전을 변경하기 전에 이 문서를 처음부터 끝까지 꼼꼼히 읽고 어떤 변경이 필요한지 큰 그림을 파악합니다. Ruby 업그레이드는 매번 이전과 조금씩 다르므로, 문서에 적힌 단계의 순서와 필요성은 상황에 맞게 판단합니다.

Ruby 업그레이드 범위#

Ruby를 업그레이드할 때 가장 먼저 고려할 것은 범위입니다. 일반적으로 Ruby 업데이트가 필요할 수 있는 영역은 다음과 같습니다.

  • 메인 GitLab Rails 리포지터리.
  • 부수적인 Ruby 시스템 리포지터리.
  • 이러한 리포지터리의 시스템이 사용하는 서드파티 라이브러리.
  • 이러한 리포지터리의 시스템이 사용하는 GitLab 라이브러리.

이 모두를 항상 손대야 하는 것은 아닙니다. 예를 들어 패치 수준의 Ruby 업데이트라면 서드파티 gem까지 업데이트해야 할 가능성은 낮습니다.

패치, 마이너, 메이저 업그레이드#

범위를 판단할 때는 Ruby 버전 수준이 중요합니다. 예를 들어 패치 릴리스는 보통 보안 수정이나 버그 수정에 한정되므로, GitLab을 Ruby 2.7.2에서 2.7.4로 올리는 것보다 Ruby 2.x에서 3.x로 올리는 편이 더 어렵고 위험합니다. 업그레이드를 준비할 때 이 점을 염두에 두고 그에 맞춰 계획합니다.

향후 업그레이드의 범위를 가늠하는 데는 다음 업그레이드에 들어간 작업량을 참고합니다.

영향을 받는 대상 및 타깃#

업그레이드 전에 Ruby 업그레이드의 영향을 받는 순서대로 모든 대상과 타깃을 고려합니다.

  1. 개발자. GitLab과 관련 프로젝트에는 사내외의 기여자가 많습니다. .ruby-version 같은 파일을 변경하면 그 파일을 해석하는 도구를 쓰는 모든 사람이 영향을 받습니다. 개발자는 변경이 머지된 리포지터리를 가져오는 즉시 영향을 받습니다.
  2. GitLab CI/CD. GitLab은 코드 통합과 테스트에 CI/CD를 크게 활용합니다. CI/CD job은 .ruby-version 같은 파일을 해석하지 않습니다. 대신 .gitlab-ci.yml에 정의된, job 이 실행되는 Docker 컨테이너에 설치된 Ruby를 사용합니다. 이러한 job에서 사용하는 컨테이너 이미지는 gitlab-build-images 리포지터리에서 관리합니다. 이미지 업데이트를 머지하면 이미지가 빌드되는 즉시 CI/CD job 이 영향을 받습니다.
  3. GitLab.com. GitLab.com은 Cloud Native GitLab(CNG)의 Docker 이미지를 사용하는 맞춤 Helm 차트로 배포됩니다. CI/CD와 마찬가지로 이 환경에서 .ruby-version은 의미가 없습니다. 대신 Ruby를 업그레이드하려면 해당 Docker 이미지를 수정해야 합니다. GitLab.com은 다음 배포 시점에 영향을 받습니다.
  4. GitLab Self-Managed. Omnibus로 GitLab을 설치하는 고객은 위의 어느 것도 사용하지 않습니다. 대신 Ruby 버전은 Omnibus의 Ruby 소프트웨어 번들이 정의합니다. GitLab Self-Managed 고객은 이 변경이 포함된 릴리스로 업그레이드하는 즉시 영향을 받습니다.

Ruby 업그레이드 접근 방식#

Ruby 업그레이드의 모든 단계에서 시점을 정확히 잡는 것이 중요합니다. 일반적인 지침은 다음과 같습니다.

  • 프로덕션 동작이 바뀔 가능성이 낮은 소규모 업그레이드에서는 리포지터리와 프로덕션 사이의 버전 격차를 최소로 유지합니다. 이해관계자와 조율해 모든 변경을 (하루나 이틀 안에) 가깝게 머지해 격차가 벌어지지 않게 합니다. 이때는 개발자 도구와 환경을 먼저 업그레이드하고 프로덕션을 나중에 올리는 순서가 적절합니다.
  • 변경 규모가 크면 새 Ruby로 프로덕션에 나가는 위험이 큽니다. 이 경우 새 Ruby 버전과의 알려진 비호환을 모두 해결한 상태를 먼저 만든 다음, 프로덕션 엔지니어와 함께 GitLab 프로덕션 플릿의 일부에 새 Ruby를 배포합니다. 이때는 프로덕션을 먼저 업데이트하고 개발자 도구와 환경을 나중에 올리는 순서가 적절합니다. 이렇게 하면 프로덕션에서 치명적인 회귀가 발생했을 때 롤백하기 쉽습니다.

어느 쪽이든 과거 경험상 다음 접근 방식이 효과적이었으며, 일부 단계는 마이너·메이저 업그레이드에서만 필요할 수 있습니다. 앞서 설명한 것처럼 일부 단계는 병렬로 진행하거나 순서를 바꿀 수 있습니다.

에픽 생성#

이 작업을 에픽으로 추적하면 진행 상황을 파악하는 데 유용합니다. 규모가 큰 업그레이드라면 이해관계자가 최종 전환 시점을 알 수 있도록 에픽 설명에 일정을 포함합니다. 업그레이드의 성능 기준을 확인할 수 있도록 지정된 성능 테스트 템플릿도 함께 넣습니다.

개별 리포지터리의 변경은 이 에픽 아래 별도 이슈로 나눕니다.

업그레이드 의사 전달#

특히 기능을 도입하거나 지원 중단하는 업그레이드라면 업그레이드가 예정되어 있음을 가급적 일정과 함께 일찍 알립니다. 개발자가 변경 사항을 미리 익힐 수 있도록 중요하거나 눈여겨볼 만한 변경에 대한 링크를 제공합니다.

GitLab 팀원은 관련 Slack 채널(최소한 #backend와 #development)과 Engineering Week In Review(EWIR)에 의사를 알립니다. 공지에는 업그레이드 에픽 링크를 포함합니다.

CI/CD 및 개발 환경에 새 Ruby 추가#

새 Ruby로 Ruby gem과 GitLab Rails 애플리케이션을 빌드하고 실행하려면, 먼저 CI/CD와 개발자 환경에 새 Ruby 버전이 포함되도록 준비해야 합니다. 이 단계에서는 아직 기본 Ruby로 만들지 않고 선택 항목으로 둡니다. 이렇게 하면 일정 기간 동안 구 버전과 새 버전의 Ruby를 모두 지원해 전환이 매끄러워집니다.

변경이 필요한 곳은 두 군데입니다.

  1. GitLab Build Images. 러너와 그 밖의 Docker 기반 프리프로덕션 환경에서 사용하는 Docker 이미지입니다. 필요한 변경의 종류는 범위에 따라 다릅니다.
    • 패치 수준 업데이트에서는 RUBY_VERSION의 패치 수준만 올리면 충분합니다. 같은 마이너 릴리스를 기준으로 빌드하는 모든 프로젝트는 새 패치 릴리스를 자동으로 내려받습니다.
    • 메이저·마이너 업데이트에서는 업그레이드 과정에서 기존 이미지와 나란히 사용할 수 있는 새 Docker 이미지 세트를 만듭니다. 중요: /patches 디렉터리의 Ruby 패치 파일을 업그레이드 대상 Ruby 버전에 맞는 새 폴더로 모두 복사해야 하며, 그러지 않으면 패치가 적용되지 않습니다.
  2. GitLab Development Kit(GDK). 개발자가 선택할 수 있는 항목으로 새 Ruby를 추가하도록 GDK를 업데이트합니다. 보통은 .tool-versions에 추가하기만 하면 되며, 이렇게 하면 asdf 사용자가 혜택을 받습니다. 그 밖의 사용자는 직접 설치해야 합니다 (예시).

버전 업그레이드 규모가 크다면 Quality Engineering과 함께 테스트 계획을 세우는 것을 검토합니다.

서드파티 gem 업데이트#

패치 릴리스에서는 이 작업이 필요할 가능성이 낮지만, 마이너·메이저 릴리스에서는 gem 이 Ruby를 특정 버전으로 고정한 탓에 호환성이 깨지거나 Bundler 의존성 문제가 생길 수 있습니다. 이를 확인하는 좋은 방법은 gitlab-org/gitlab에 머지 리퀘스트를 만들어 무엇이 깨지는지 보는 것입니다.

GitLab gem 및 관련 시스템 업데이트#

GitLab 이 직접 관리하는 gem 이나 Ruby 애플리케이션에는 .ruby-version, .tool-versions, .gitlab-ci.yml 같은 빌드 설정이 들어 있으므로 이 작업은 대체로 필요합니다. GitLab Rails 애플리케이션이 새 Ruby에서 동작하기 위해 이러한 리포지터리를 반드시 업데이트해야 하는 것은 아니지만, 모든 리포지터리에서 Ruby 버전을 같은 단계로 유지하는 것이 바람직합니다. 마이너·메이저 업그레이드에서는 새 Ruby를 사용하는 CI/CD job을 이러한 리포지터리에 추가합니다. 빌드 매트릭스 정의를 사용하면 효율적으로 처리할 수 있습니다.

업데이트할 리포지터리 결정#

Ruby를 업그레이드할 때는 ruby/gems 그룹의 리포지터리 업데이트도 함께 검토합니다. 참고로 과거에 이들 프로젝트 일부의 Ruby를 업데이트한 머지 리퀘스트 목록은 다음과 같습니다.

이 가운데 어떤 리포지터리를 메인 GitLab 애플리케이션과 함께 반드시 업데이트해야 하는지는 다음을 기준으로 판단합니다.

  • Ruby 버전 범위.
  • 해당 서비스나 라이브러리가 GitLab 전체 동작에서 맡는 역할.

영향을 받을 수 있는 리포지터리 전체는 GitLab 프로젝트 목록을 참고합니다. 버전 업그레이드 규모가 작다면, 필수적이지 않거나 새 Ruby 버전에서 메인 애플리케이션 테스트 스위트가 회귀를 잡아낼 것이 확실한 라이브러리는 업데이트를 미뤄도 무방합니다.

Note

이 변경을 GitLab 애플리케이션 업데이트보다 먼저 머지해도 되는지는 해당 코드 오너와 상의합니다. 필요한 승인은 미리 받아 두되, 모든 준비가 끝날 때까지 머지는 미루는 편이 좋을 수 있습니다.

GitLab 애플리케이션 머지 리퀘스트 준비#

의존성을 업데이트하고 새 gem 버전을 릴리스했다면, gem 및 관련 시스템과 마찬가지로 메인 Rails 애플리케이션에도 필요한 변경을 적용할 수 있습니다. 여기에 더해 설치·업데이트 안내 문서의 버전 표기도 변경 사항에 맞춰 갱신합니다(예시).

Note

이 머지 리퀘스트의 시점에는 특히 주의해야 합니다. 머지되는 순간 모든 GitLab 기여자가 영향을 받고 변경 사항이 배포되기 때문입니다. 다른 모든 준비가 끝날 때까지 이 MR을 열어 두어야 하지만, 리드 타임을 줄이기 위해 승인은 미리 받아 두면 좋습니다.

개발자에게 업그레이드 시간 제공(유예 기간)#

새 Ruby를 선택 항목으로 제공하고 모든 머지 리퀘스트가 준비되었거나 머지되었다면, 개발자가 자신의 컴퓨터에 새 Ruby를 설치할 수 있도록 최소 1주일의 유예 기간을 두어야 합니다. GDK와 asdf 사용자는 gdk update로 자동으로 설치됩니다.

이 기간은 이번 업그레이드가 GitLab.com에 미칠 위험을 평가하기에 좋은 시점입니다. 메이저 버전 업그레이드처럼 위험이 큰 Ruby 업그레이드는 변경 관리 요청을 통해 인프라 팀과 변경 사항을 조율할 것을 권장합니다. 모두가 변경을 계획하고 준비할 시간을 갖도록 이 이슈는 일찍 만듭니다.

기본 Ruby로 설정#

알려진 버전 호환성 문제가 더 이상 없고 유예 기간이 지났다면, 영향을 받는 모든 리포지터리와 개발자 도구를 업데이트해 새 Ruby를 기본값으로 설정합니다.

이 시점에 GitLab Compose Kit(GCK)도 업데이트합니다. 이는 GitLab을 docker-compose로 실행하려는 사용자를 위한 대체 개발 환경입니다. 이 프로젝트는 러너와 같은 Docker 이미지를 사용하므로 해당 리포지터리의 변경과 보조를 맞춰야 합니다. 이 변경은 마이너·메이저 버전이 바뀔 때만 필요합니다 (예시).

앞서 말한 것처럼 Ruby 업그레이드가 SaaS 가용성에 미칠 영향이 불확실하다면, 단계적 롤아웃으로 프로덕션에서 문제없이 동작하는 것을 확인할 때까지 이 단계를 건너뛰는 것이 안전합니다. 이 경우 다음 단계를 먼저 진행하고, 검증 기간이 지난 뒤에 새 Ruby를 기본값으로 승격합니다.

CNG, Omnibus, Self-compiled 업데이트 및 GitLab MR 머지#

마지막 단계는 프로덕션에서 새 Ruby를 사용하는 것입니다. 이를 위해서는 Omnibus와 프로덕션 Docker 이미지가 새 버전을 쓰도록 업데이트해야 합니다.

프로덕션에서 새 Ruby를 사용하려면 다음 프로젝트를 업데이트합니다.

GitLab Helm Chart 같은 차트도 어떤 형태로든 Ruby를 사용한다면, 예를 들어 테스트 실행에 사용한다면 함께 업데이트해야 합니다(이 예시 참고). 다만 반드시 필요한 것은 아닐 수 있습니다.

변경 관리 요청을 제출했다면 인프라 엔지니어와 롤아웃을 조율합니다. 규모가 큰 업그레이드에서는 롤아웃 계획에 릴리스 매니저를 참여시킵니다.

보안 패치를 위한 패치 릴리스 및 백포트 생성#

업그레이드가 패치 릴리스였고 중요한 보안 수정이 포함되어 있다면, self-managed 고객에게 GitLab 패치 릴리스로 배포해야 합니다. 진행 방법은 릴리스 매니저에게 문의합니다.

Ruby 업그레이드 도구#

업그레이드 과정을 수월하게 해 주는 도구가 몇 가지 있습니다.

Deprecation Logger#

GitLab은 Ruby와 Rails의 지원 중단 경고를 전용 로그 파일 log/deprecation_json.log에도 기록하며(GitLab 로그 파일 위치는 GitLab 개발자를 위한 로깅 가이드 참고), 이는 테스트로 충분히 다루지 못한 코드를 찾는 단서가 됩니다.

GitLab.com의 경우 GitLab 팀원은 Kibana (https://log.gprd.gitlab.net/goto/f7cebf1ff05038d901ba2c45925c7e01)에서 이 로그 이벤트를 확인할 수 있습니다.

권장 사항#

업그레이드 과정에서는 다음 사항을 권장합니다.

  • 가능한 한 많은 변경을 앞당겨 처리합니다. 특히 마이너·메이저 릴리스에서는 애플리케이션 코드가 깨지거나 바뀔 가능성이 큽니다. 하위 호환이 유지되는 변경은 메인 브랜치에 머지해 Ruby 버전 업그레이드보다 먼저 독립적으로 릴리스합니다. 이렇게 하면 작은 단위로 움직이면서 프로덕션 환경의 피드백을 일찍 받을 수 있습니다.
  • 규모가 큰 업데이트에는 실험용 브랜치를 만듭니다. GitLab은 장기간 유지되는 토픽 브랜치를 대체로 피하지만, 피드백과 실험 목적으로는 새 Ruby로 실행할 때 CI/CD의 피드백을 꾸준히 받을 수 있는 브랜치가 유용합니다. 이 MR에서 볼 수 있듯이, 어떤 문제가 생길지 처음 가늠할 때 도움이 됩니다. 이러한 실험용 브랜치는 머지할 목적이 아니며, 필요한 변경을 모두 나누어 독립적으로 머지한 뒤 닫으면 됩니다.
  • 마일스톤 릴리스에 앞서 문제를 고칠 시간을 충분히 확보합니다. GitLab은 빠르게 움직입니다. Ruby 업그레이드에는 많은 MR을 보내고 리뷰받아야 하므로, 모든 변경은 릴리스일보다 최소 1주일 앞서 머지합니다. 그러면 문제가 생겼을 때 대응할 여유가 생깁니다. 판단이 서지 않는다면 속도보다 가용성을 우선하므로 업그레이드를 다음 달로 미루는 편이 낫습니다.