grep

DevOps

[DevOps] GitLab 버전 업그레이드는 계속 된다.

루카스Lucas(이상배) / DevOps팀여기어때

2024년 9월 13일

원문에서 보기 ↗

안녕하세요. 여기어때컴퍼니 DevOps팀 루카스입니다. 저희 팀은 여기어때컴퍼니 Tech 조직내 개발자들의 업무 몰입을 위한 개발 환경과 체계를 만들어가는 조직으로 조직별로 상이한 개발 환경을 통합하고 운영하고 있습니다.

Photo by Pankaj Patel on Unsplash

이번에 다룰 주제는 팀에 합류하고 나서 첫 번째 작업이었던 GitLab 버전 업그레이드 과정입니다. GitLab은 소프트웨어 개발자에게 강력한 기능을 제공하는 형상 관리 플랫폼입니다. 하지만 최신 기능을 활용하고 보안 업데이트를 적용하기 위해서는 정기적으로 업그레이드를 해야 합니다. 우리 조직내 개발자들이 더욱 안전한 환경에서 신규 기능을 활용 할 수 있도록 저희팀은 GitLab을 업그레이드 하기로 결정하였습니다.

1. 사전 준비

1–1. Upgrade Path 확인

GitLab의 현재 설치된 버전과 호환성을 확인합니다. 이런 경우에는 GitLab의 공식 문서에서 지원되는 업그레이드 경로를 확인하는 것이 좋습니다. https://gitlab-com.gitlab.io/support/toolbox/upgrade-path/ 이 URL에서 현재 사용 버전, OS, 업그레이드 대상 버전 등을 선택하면 어떤 버전의 순서로 업그레이드를 해야하는지 알려 줍니다. 버전 변경에 대한 큰 변동사항에 대해서도 미리 경고해 줍니다.

여기어때에서는 GitLab 15.1.6을 사용하고 있었으며, 16.9.4 버전으로 업그레이드를 진행하였습니다.

15.1.6에서 16.9.4로 Upgrade Path는 다음과 같습니다.

15.1.6 → 15.4.6 → 15.11.13 → 16.1.6 → 16.3.7 → 16.7.7 → 16.9.1

Upgrade Path의 경고 마지막 부분에 Expiring Access Token 부분이 있었습니다. Gitlab PAT 관련 문서를 통해 추가로 확인해 보았습니다. https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html

Never Expire로 발급된 Personal Access Token은 모두 GitLab 16.0으로 업그레이드한 날짜로부터 1년 후에 만료 되도록 강제로 변경 됩니다. CI/CD Pipeline 자동화를 위해서 사용되는 토큰인 경우, 만료시 장애를 일으킬 수 있는 원인이 되기 때문에 사전 작업을 진행합니다.

  1. 기존 버전의 Personal Access Token의 만료일이 Never인 Token을 리스트업합니다.
$ curl -s --header "PRIVATE-TOKEN: ${your_access_token}" "https://${gitlab url}/api/v4/personal_access_tokens" | jq '.[] | {id, expires_at}'

결과 샘플은 다음과 같습니다.

{
  "id": 154,
  "name": "GITLAB-PAT",
  "expires_at": "2025-06-25"
}

your_access_token 은 admin 권한을 갖는 계정의 Personal Access Token을 발급하여 Rest API를 호출하여, 사용 중인 전체 Token의 만료일을 나열합니다. expires_at 의 value가 null 인 경우, 만료일이 Never로 설정된 Token들입니다. 추후 업그레이드 작업 완료 후 만료일 값을 변경해야 하기에 작업이 끝나기 전까지 잘 보관합니다.

1–2. 백업

데이터 손실을 방지하기 위해 기존 GitLab의 데이터베이스 백업을 수행합니다. 우리는 AWS 환경을 사용하기 때문에 기존에 사용하던 GitLab 15.1.6 버전의 인스턴스와 GitLab Runner는 AMI를 생성하여, 백업 및 테스트를 진행합니다. AMI 생성 및 AMI를 이용한 인스턴스 시작 순서는 다음과 같습니다.

1)AMI가 있는지 확인 → 2)있다면 등록 해제 → 3)새로운 AMI 생성 → 4)새로운 AMI를 사용하여 EC2 인스턴스 시작

위 순서대로 백업을 계획하였으며, 실제 작업한 과정은 예시와 함께 더욱 상세하게 과정을 설명하겠습니다.

  1. AMI가 있는지 확인
REGION='리전'
INSTANCE_ID='{현재 사용중인 인스턴스 id}'
AMI_NAME_TARGET='생성할AMI이름'
TYPE='{Instance type}'
KEY_PAIR='{현재 사용중인 key}'
aws ec2 describe-images \
    --region $REGION \
    --filters "Name=name,Values=$AMI_NAME_TARGET" \
    >$JSON_AMI
  1. 있다면 등록 해제
AMI_ID_TARGET=$(jq -r '.Images[0].ImageId' $JSON_AMI)
if [ $AMI_ID_TARGET != "null" ]
then
   aws ec2 deregister-image --region $REGION --image-id $AMI_ID_TARGET
fi
  1. 새로운 AMI 생성
aws ec2 create-image \
    --region $REGION \
    --instance-id $INSTANCE_ID \
    --name "$AMI_NAME_TARGET" \
    --no-reboot \
    >$JSON_AMI
  1. 새로운 AMI를 이용하여 EC2 인스턴스 시작
AMI_ID_TARGET=$(jq -r '.ImageId' $JSON_AMI)
aws ec2 run-instances \
    --region $REGION \
    --image-id $AMI_ID_TARGET \
    --count 1 \
    --instance-type $TYPE \
    --key-name $KEYPAIR

→ On-Premise 서버를 이용하고 있는 경우, 다음 백업/복구 절차에 따르시면 됩니다.

Gitlab Backup

https://docs.gitlab.com/ee/administration/backup_restore/backup_gitlab.html

Gitlab Restore

https://docs.gitlab.com/ee/administration/backup_restore/restore_gitlab.html

2. GitLab 패키지 업데이트

2–1. 패키지 저장소 업데이트

yum은 rpm 설치를 위해 개발된 패키지 매니저입니다. yum을 사용하면, rpm 설치 시 발생하는 의존성 문제를 해결할 수 있습니다. 아래 명령어 실행을 통해서 모든 패키지 및 해당 종속 항목을 업데이트 할 수 있습니다.

$ sudo yum update

3. GitLab 업그레이드

3–1. 업그레이드 명령 실행

  1. 15.1.6에서 15.4.6으로 업그레이드
$ yum install gitlab-ee-15.4.6 -y
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
amzn2-core                                                                                                                                                                                 | 3.6 kB  00:00:00
gitlab_gitlab-ee/x86_64/signature                                                                                                                                                          |  862 B  00:00:00
gitlab_gitlab-ee/x86_64/signature                                                                                                                                                          | 1.0 kB  00:00:00 !!!
gitlab_gitlab-ee-source/signature                                                                                                                                                          |  862 B  00:00:00
gitlab_gitlab-ee-source/signature                                                                                                                                                          |  951 B  00:00:00 !!!
...
gitlab Reconfigured!
Restarting previously running GitLab services
ok: run: alertmanager: (pid 21470) 0s
ok: run: gitaly: (pid 2811) 10171s
ok: run: gitlab-exporter: (pid 21468) 0s
ok: run: gitlab-kas: (pid 21449) 1s
ok: run: gitlab-workhorse: (pid 21459) 1s
ok: run: grafana: (pid 21483) 1s
ok: run: logrotate: (pid 21494) 0s
ok: run: nginx: (pid 21500) 1s
ok: run: node-exporter: (pid 21508) 0s
ok: run: postgres-exporter: (pid 21515) 0s
ok: run: postgresql: (pid 21344) 102s
ok: run: prometheus: (pid 21526) 1s
ok: run: puma: (pid 21538) 0s
ok: run: redis: (pid 2823) 10174s
ok: run: redis-exporter: (pid 21544) 0s
ok: run: sidekiq: (pid 21546) 0s
     _______ __  __          __
    / ____(_) /_/ /   ____ _/ /_
   / / __/ / __/ /   / __ `/ __ \
  / /_/ / / /_/ /___/ /_/ / /_/ /
  \____/_/\__/_____/\__,_/_.___/
Upgrade complete! If your GitLab server is misbehaving try running
  sudo gitlab-ctl restart
before anything else.
If you need to roll back to the previous version you can use the database
backup made during the upgrade (scroll up for the filename).
  Verifying  : gitlab-ee-15.4.6-ee.0.el7.x86_64                                                                                                                                                               1/2
  Verifying  : gitlab-ee-15.1.6-ee.0.el7.x86_64                                                                                                                                                               2/2
Updated:
  gitlab-ee.x86_64 0:15.4.6-ee.0.el7
Complete!

이 명령어는 설치된 GitLab 버전을 15.4.6으로 업데이트합니다. gitlab-ee는 GitLab Enterprise Edition을 의미합니다. 만약 Community Edition을 사용 중이라면 gitlab-ce를 사용해야 합니다.

  1. 15.4.6에서 15.11.13으로 업그레이드
$ yum install gitlab-ee-15.11.13 -y

그리고, 다음과 같은 메시지가 보이면 PostgreSQL을 업그레이드 해줍니다.

Checking if a newer PostgreSQL version is available and attempting automatic upgrade to it: NOT OK
Error ensuring PostgreSQL is updated. Please check the logs

GitLab 16부터는 PostgreSQL이 최소 13버전이어야 합니다.

$ gitlab-ctl pg-upgrade --timeout=1d
Checking for an omnibus managed postgresql: OK
Checking if postgresql['version'] is set: OK
Checking if we already upgraded: NOT OK
Checking for a newer version of PostgreSQL to install
Upgrading PostgreSQL to 13.11
...
Toggling services:ok: run: alertmanager: (pid 27359) 1s
ok: run: gitaly: (pid 27369) 0s
ok: run: gitlab-exporter: (pid 27387) 1s
ok: run: gitlab-kas: (pid 27389) 0s
ok: run: grafana: (pid 27391) 0s
ok: run: logrotate: (pid 27398) 0s
ok: run: node-exporter: (pid 27406) 0s
ok: run: postgres-exporter: (pid 27410) 0s
ok: run: prometheus: (pid 27429) 0s
ok: run: redis-exporter: (pid 27441) 0s
ok: run: sidekiq: (pid 27449) 0s
Toggling services: OK
==== Upgrade has completed ====

PostgreSQL 버전 업그레이드 후에 PostgreSQL, Redis 재시작합니다.

$ gitlab-ctl restart redis
ok: run: redis: (pid 27573) 0s
$gitlab-ctl restart postgresql
ok: run: postgresql: (pid 27555) 1s
$ gitlab-ctl reconfigure
  1. 15.11.13 에서 16.3.7로 업그레이드
$ yum install gitlab-ee-16.3.7 -y

업그레이드 수행 중 다음과 같은 경고 문구가 나옵니다.

Warnings:
The version of the running redis service is different than what is installed.
Please restart redis to start the new version.
sudo gitlab-ctl restart redis

Redis 버전이 자동으로 업그레이드 되어, 서비스를 재시작 시킵니다.

$ gitlab-ctl restart redis
  1. 이후 버전 업그레이드를 진행합니다.
$ yum install gitlab-ee-16.7.7 -y
$ yum install gitlab-ee-16.9.1 -y

3–2. 데이터베이스 마이그레이션

$ sudo gitlab-ctl reconfigure

이 명령어들은 GitLab의 데이터베이스 마이그레이션을 실행합니다.

3–3. GitLab 시작

$ sudo gitlab-ctl start

GitLab을 재시작하여 새 버전으로 전환합니다.

3–4. Personal Access Token 만료일 이슈를 해결

기존에 만료일이 Never로 설정된 Token은 업그레이드 후 다시 설정 합니다.

$ gitlab-rails runner 'PersonalAccessToken.active.where(name: "GITLAB-PAT").update_all(expires_at: "10.year.from_now")'

위의 명령어는 GitLab 16.0 이상으로 업그레이드 한 다음 GitLab 인스턴스 내에서 실행합니다. 여기어때에서는 GitLab 16.0 업그레이드 한 다음에 10년후로 설정 시, REST API로 확인 결과 expires_at의 value가 null로 표기되는 것을 확인하였습니다.

$ curl -s --header "PRIVATE-TOKEN: ${your_access_token}" "https://${gitlab_url}/api/v4/personal_access_tokens?user_id=154" | jq '.[] | {id, name, expires_at}'
{
  "id": 154,
  "name": "GITLAB-PAT",
  "expires_at": null
}

4. 테스트 및 확인

4–1. GitLab 접속 확인

업그레이드가 완료된 후, 브라우저를 통해 새 버전의 Gitlab에 접속합니다. 로그인, 프로젝트 접근, 기본적인 CI/CD 파이프라인 등 주요 기능들이 정상적으로 작동하는지 점검합니다. 모든 기능이 예상대로 동작하는지 확인하는 것이 중요합니다.

4–2. 백업 복원 확인

업그레이드 후, 데이터 손실 방지를 위해 백업 복원 절차를 테스트합니다. 필요할 경우, 백업 파일을 사용하여 이전 데이터를 복원할 수 있는지 확인합니다. 복원 과정에서 문제가 발생하지 않도록 미리 테스트를 진행해 보는 것이 좋습니다.

4–3. 첫 번째 이슈 대응

업그레이드 후 모든 Gitlab CI가 실패함.

CI 진행 후 EKS Manifest에 Tag를 업데이트 하는 과정에서 GitLab Runner에서 GitLab으로 SSH로 연결하여 Clone, Push 과정이 진행됩니다.

GitLab Runner → GitLab으로 SSH Port 오픈

4–4. 두 번째 이슈 대응

Runner에서 Docker Pull Rate 초과함.

429 Too Many Requests - Server message: toomanyrequests: You have reached your pull rate limit. You may increase the limit by authenticating and upgrading: https://www.docker.com/increase-rate-limit  

GitLab Runner를 신규 인스턴스로 구축하여 Cache된 Image가 없는 상태인데, EKS에서 Base Image를 Public Registry인 Docker hub에서 Pull하게 됩니다. 그런데 이 때, 개발팀과 테스트 시간이 겹치면서 다수의 Image를 동시에 Pull하게 되면서 발생하였습니다.

기존 보유 Docker 계정으로 인증키를 발급받아 적용합니다.

$ vi /etc/gitlab-runner/config.toml

environment = ["DOCKER_AUTH_CONFIG={\"auths\":{\"index.docker.io/v1\":{\"auth\":\"{도커인증키}\"}}}"]

마무리

GitLab 버전을 정기적으로 업그레이드하여 최신 기능을 사용할 수 있도록하면서 동시에 보안적인 측면의 안정성도 강화함으로써 개발 생산성을 일정 수준 이상으로 유지하는 일은 반드시 필요합니다. 이번 글에서는 GitLab 15.1.6 버전을 16.9.4 버전으로 업그레이드하는 과정을 설명하였습니다. 업그레이드 과정에서 예상치 못한 문제가 발생한 경우 GitLab 공식 문서나 커뮤니티 포럼에서 해결 방법을 찾을 수 있었습니다. 제 경험이 여러분께 도움이 되었길 바라며 마치겠습니다.