こんにちは、インフラ部の id:sue445 です。
前回に引き続きGitLabのGCP移行について紹介します。
前編の記事はこちらになります
今回の目次
- 今回の目次
- やったこと2: 実際にGCPに構築した
- GitLab構築に関係するリポジトリの構成
- 全体の構成図
- 3rd party製のDockerイメージから公式のDockerイメージに移行した
- Docker Swarmは継続利用
- GitLabを複数ゾーンで動かすための準備だけした
- Cloud IAPとTunneling SSH Connectionsを利用したgitアクセス
- GitLab CIの環境にGKE Standardを採用
- PlantUMLとgitpandaをGitLab CI用のGKEクラスタに設置
- GKE Standardのクラスタに複数のNode Poolを設定する
- 外向けのエンドポイントに対して外形監視を仕込む
- オンプレミスのサーバにGitLab Runnerを設置
- GCP外からGitLabのAPIをたたくための口を作った
- やったこと3: 本番のデータを移行する検証
- やったこと4: 移行の段取り
- 最後に
やったこと2: 実際にGCPに構築した
オンプレミス環境からクラウド環境への移行に関してAWSが「7つのR」というものを提唱しています。
これまでに書いた内容から分かるようにアーキテクチャを1から作り直したので、今回のGCP移行はこの7つのRに当てはめると「リプラットフォーム (Replatform)」や「リファクタリング (Refactor)」に近いと思います。
早い話、移行前後でだいたい全部変わりました。
GitLab構築に関係するリポジトリの構成
基本的に社内の開発ではGitLabでリポジトリを作っていますが、GitLabの構築やデプロイに必要なものをGitLabに置くとGitLabがダウンしている時にデプロイ作業などができなくなるため、GitLabの構築に必要なものは全てGitHubのprivateリポジトリに置いています。
だいたい下記の3リポジトリで構成しています。
gcp-gitlab-terraform
GCPプロジェクト全体の構築で利用するTerraformのリポジトリです。
https://github.com/sue445/terraform-gcp-template *1をベースにTerraformリポジトリを作成しています。
だいたいこれくらいの規模感です
# tfファイルの数 $ find . -name "*.tf" | wc -l 113 # tfファイル内のresourceの数 $ ag "resource" --stats-only 180 matches 76 files contained matches 124 files searched 129683 bytes searched 0.004361 seconds
gcp-gitlab-playbook
GitLab本体のVPCに設置しているGCE VM(GitLabのAPと踏み台サーバ)の構築に利用しているAnsible Playbookのリポジトリです。
Cloud IAPごしにAnsibleを流すやり方は下記エントリが参考になりました
GitLab本体のデプロイもAnsibleで行っています。
デプロイ用にcapistrano辺りを導入しようかと思ったのですが、IAP経由で cap deploy
できるか自信がなかったのでデプロイに必要なファイル一式をAnsibleで転送してgcloud compute ssh VM_NAME --tunnel-through-iap -- sudo /path/to/repo/deploy.sh
のような感じでVM内でデプロイスクリプトを実行しています。
gcp-gitlab-helm
GitLab CIの実行環境(GKEクラスタ)にデプロイするためのHelmやkustomizeのリポジトリです。
備考
言うまでもないと思いますが全てGitHub Actionsから実行できるようにしています。
GitHubのリポジトリは権限の関係でインフラ部以外は見れないのですが、他の人にサンプルコードとして見せたいような時に不便なので別途GitLabにミラーリングするようにしています。
ピクシブではFree(無料版)のGitLabを利用しているのですが、他のリポジトリからGitLabにミラーリングする機能は有料*2でPremium以上のプラン *3 でないと利用できません。
そのため、このためだけのプラン変更は見送り自作スクリプトでGitHubからGitLabにミラーリングしています。
全体の構成図
だいぶ端折ってはいますがだいたいこういう構成になっています。
webservice (GitLab本体)
ここのwebserviceってネーミングは正直迷ったんですが、Helm chartだとwebserviceって名前になっていたのでそれにならいました。*4
GitLab CI
ただこの図だけだと端折りすぎてよく分からないと思うので採用した技術などにフォーカスをあてて詳しく紹介したいと思います。
3rd party製のDockerイメージから公式のDockerイメージに移行した
2019年の移行の時 には1からGitLabの docker-compose.yml
を作成するスキルがなかったので、docker-compose.yml
が提供されている https://github.com/sameersbn/docker-gitlab (3rd party製のdockerイメージ)を利用していました。
しかし3年ほど運用してきて下記のような不満点も出てきました。
- GitLabの最新版に対しては積極的に更新されているが、古いマイナーバージョンに対してはパッチがあたらない
- GitLabだと2つ古いマイナーバージョンまではセキュリティパッチが提供されるが、sameersbn/docker-gitlabだとそれを適用できないことがある
- 最近はちょっと古いバージョンもパッチバージョンがリリースされている模様
- GitLabの全ての設定を利用できない
- メジャーな設定に関してはだいたいサポートされているのですが、あまり使われない設定に関しては自分でPRを投げる必要があります
- 実際に何回かPRを投げています https://github.com/sameersbn/docker-gitlab/pulls?q=is%3Apr+author%3Asue445+is%3Aclosed
しかし3年経った今では1からGitLabの docker-compose.yml
を書ききるスキルがついたので、この機会に公式のDockerイメージに移行しました。
公式のDockerイメージは https://gitlab.com/gitlab-org/omnibus-gitlab の設定ファイルがそのまま使えるのですがomnibus-gitlabの設定ファイルはRubyなので柔軟な設定を書けてよかったです。*5
Docker Swarmは継続利用
前編にも書いたようにアーキテクチャ選定時にKubernetesが利用できないことが分かっていて、GitLabの特性上複数のVMでの冗長構成もとりづらいためDocker Swarmを引き続き採用しています。
GitLabを複数ゾーンで動かすための準備だけした
「複数のVMでの冗長構成をとりづらい」とは書いたものの方法がないわけではありません。
前編の「懸念1. NFSを使わずにボリュームの冗長構成をとるのが難しい」で書いたようにGCEの マルチライターモード を使うことで1つの永続ディスクを複数のゾーンのVMから書き込みモードでアタッチすることが可能になります。
ちゃんとベンチとる必要はありますが、カタログスペック上はCloud Filestore(GCPのマネージドNFS)よりも速そうです。(余談ですがFilestore(GCPのNFS)とFirestore(GCPのKVS)って字面が似すぎてくっそ紛らわしいですね...)
しかし一番の問題として執筆時点でマルチライターモードが東京リージョンでサポートされていません。
そのため、いつの日にか東京リージョンで対応することを信じてそれ以外の条件(N2マシンタイプ、SSDタイプのリージョン永続ディスクを利用)は揃えています。
現時点でGitLab APの冗長構成が取れないとはいってもゾーン障害には備える必要があります。
そのためGitLabのAPサーバと踏み台サーバは複数のゾーンで作成だけはしています。通常の運用では片側のゾーンのみ起動して(もう片方のゾーンはコールドスタンバイ状態で停止)、ゾーン障害発生時にもう片方のゾーンに切り替えられるようにはしています。
やりたかった構成
現在の構成
Regional PD SSDを複数のVMでマルチライターモードでアタッチできないので片側のAPのみにアタッチしています。
Cloud IAPとTunneling SSH Connectionsを利用したgitアクセス
前述の通りCloud IAPのTunneling SSH Connectionsを使うことでGCEのVMがsshのポートをインターネットに開放していないなくてもIAMロールの権限でsshすることができます。*6
また、3rd party製ではありますが https://github.com/adohkan/git-remote-https-iap を使うことにより、Cloud IAPで保護されたhttpsのGitLabのエンドポイントに対してもgitアクセスできそうです。
PoC環境で試したところCloud IAPごしでのsshのエンドポイントに対するgitコマンドとCloud IAP設定済のhttpsのエンドポイントに対するgitコマンドが両方とも問題なかったのでGCP版GitLabでも採用しています。
Tunneling SSH Connectionsを利用したgitアクセス
実際に新GitLabで採用した構成は下記になります。
Tunneling SSH ConnectionsでVMにログインした場合、Google Workspace(以降、GWSと呼称)のアカウントベースのユーザ名でsshログインされますが、そのユーザにはデフォルトで全員にsudo権限が付与されます。
しかしピクシブではインフラ部以外には基本的にsudo権限を付与していないため、踏み台サーバであっても全社員にsudo権限があるのはあまり好ましくありませんでした。
調べた結果、GCEのVMで OS Login を有効化してさらに
- Compute OS 管理者ログイン(
roles/compute.osAdminLogin
): sudo権限がある - Compute OS ログイン (
roles/compute.osLogin
): sudo権限が無い
のようなIAMロールを使い分けることにより、踏み台サーバ内でインフラ部のGoogleグループのみにsudo権限を付与するということが実現できました。
またGitLabはgitユーザでのgitアクセスを想定しているため、踏み台サーバでの認証をGWSアカウントにして、GitLabのAPサーバへのアクセスはgitユーザになるように下記のような ~/.ssh/config
をGitLab利用者に配布するようにしました。
Host bastion.example.com # ユーザ毎に変わる設定 # NOTE: GWSアカウントがdareka@pixiv.co.jpであればdareka_pixiv_co_jpを書く User dareka_pixiv_co_jp # ユーザ毎に基本的に変えない共通設定 HostName gitlab-webservice-production-bastion-a ProxyCommand gcloud compute start-iap-tunnel %h %p --listen-on-stdin --zone asia-northeast1-a --project gitlab-project ForwardAgent yes Port 22 IdentityFile ~/.ssh/google_compute_engine Host gitlab.example.com # ユーザ毎に変わる設定 IdentityFile ~/.ssh/id_ed25519 # ユーザ毎に基本的に変えない共通設定 HostName ap.example.com # NOTE: ap.example.comは踏み台サーバ内からのみアクセス可能なGitLab APの内部IPのDNS User git ProxyCommand ssh -W %h:%p bastion.example.com ForwardAgent yes Port 22
この設定ファイルを利用することで利用者側ではCloud IAPをあまり意識せずにいつものgitコマンドがそのまま使えます
注意点として、Tunneling SSH ConnectionsはVM内のsshdが22番ポートで動いていることが前提になっているようです。 *7
ピクシブ社内で作成するサーバはセキュリティのため全てsshdのポートを22番ポートから変えています。 そのためGitLabでも変えようとしたのですが、sshdのポートを変えたらTunneling SSH Connectionsでの接続ができなくなったのでここだけやむなく22番ポートを使っています。
Cloud IAPで保護されたhttpsに対するgitアクセス
git-remote-https-iapを利用すると下記のような経路でgitアクセスされます。
1点注意点として、GitLabでのログインをSAMLにしているとPersonal Access Tokenを使わないとcloneできないのがちょっとしたハマりポイントでした。
参考情報
- https://gitlab.com/gitlab-org/gitlab/-/issues/29249
- https://docs.gitlab.com/ee/gitlab-basics/start-using-git.html#clone-using-a-token
おまけ:Jenkinsやデプロイサーバからのgitアクセス
前述の2種類のCloud IAPを利用したgitアクセスは両方ともGWSアカウントによる認証を行っています。
しかし社内にはJenkinsやデプロイサーバのようにGWSアカウントに紐付かないUNIXユーザでgitアクセスしている社内システムもあります。
そのようなケースのみCloud IAPを経由せずに直接gitアクセスできるようにしています。
Jenkinsで例えると下記のような感じです。
踏み台サーバではFirewallでデータセンターのWANからのみsshができるようにしています。
オンプレミスのサーバからのssh接続では下記のような ~/.ssh/config
を利用しています。
Host bastion.example.com # ユーザ毎に変わる設定 # TODO: 予め踏み台サーバにユーザ作成が必要 User deploy IdentityFile ~/.ssh/id_ed25519 # ユーザ毎に基本的に変えない共通設定 ForwardAgent yes Port 22 Host gitlab.example.com # ユーザ毎に変わる設定 # GitLabに登録してる公開鍵に対応した秘密鍵のパスを書く IdentityFile ~/.ssh/id_ed25519 # ユーザ毎に基本的に変えない共通設定 HostName ap.example.com User git ProxyCommand ssh -W %h:%p bastion.example.com ForwardAgent yes Port 22
データセンターとGCPの間は現状はインターネットを通っていますが、将来的にはCloud Interconnectを導入して専用線接続したいところです。(Jenkins用にサービスアカウントを発行していないのもそれを見越したのが理由)
GCP移行時にCloud Interconnectも同時に導入するのはちょっと厳しかったので今回のGCP移行のスコープからは外しました。
GitLab CIの環境にGKE Standardを採用
GKEといえば自分でノードを管理するGKE Standardとノードの管理もGCPにお任せにするGKE Autopilotがあります。
GitLab CIのジョブでdocker buildを行うにはDocker in Docker(DinD)を行う必要があります。
https://docs.gitlab.com/ee/ci/docker/using_docker_build.html
そのためにはGKEのノードでprivilegedを有効にする必要がありますが、GKE Autopilotはノードがマネージドな関係でprivilegedを有効にすることができないためGitLab CIの環境ではGKE Standardを採用しています。
docker buildを行いたいジョブはGKE Standardにしてdocker buildを行わないジョブはGKE Autopilotにするという構成もありえますが、クラスタを2つ管理するコストを考えるとあまり現実的ではありません。
もしこれがAWSであればEKS on FargateではなくEKS on EC2のような構成が必要だと思います。
PlantUMLとgitpandaをGitLab CI用のGKEクラスタに設置
旧GitLabではPlantUMLと gitpanda を利用していたので新GitLabでもこれらを利用するための各エンドポイントを作成する必要がありました。
gitpandaについては過去に書いた記事をご参照ください。
PlantUMLとgitpandaはどちらもDockerイメージで配布されていてかつGitLab本体とは切り離されたシステムだったのでCloud Runで動かしたかったのですが、下記のような理由でGitLab CI用のGKEクラスタに相乗りさせています。
- PlantUML: PlantUMLのDockerイメージはDocker Hubで配布されているのだが、Cloud RunではGCPのContainer RegistryかArtifact RegistryにあるDockerイメージしか使えないためNG
- DockerHubにあるDockerイメージをArtifact Registryにミラーリングするのも手間
- gitpanda: 実は僕がメンテしてるOSSなのでこのためだけにArtifact Registry対応したのだが、よくよく考えたらGitLabのAPIを叩く関係でCI用のクラスタ内で動かした方が都合がよかった
- GitLabのエンドポイントはCloud IAPで保護されていて外部から簡単にAPIを叩けないようにしているのだが、GitLab CI用のクラスタであれば前述の限定公開ゾーンによりCloud IAPを迂回してAPIを実行できる
この手のツールをGitLab CI用のクラスタに相乗りするのも若干気持ち悪さがあるのですが、クラスタを増やすとその分管理コストも増えるので相乗りさせています。(両方ともほとんどリソースを食わないのでクラスタ内のリソースも圧迫してない)
GKE Standardのクラスタに複数のNode Poolを設定する
GCEで作れるVMには下記の種類があります
- Regular VM
- 定価で使えるがPreemptible VMやSpot VMと違い予告なしで停止しないいわゆる普通のVM
- AWS EC2でいうところのオンデマンドインスタンスと同じ
- Preemptible VM
- https://cloud.google.com/compute/docs/instances/preemptible?hl=ja
- 安い代わりに24時間経つと停止されるVM
- AWS EC2でいうところのスポットインスタンスに近い
- Spot VM
- https://cloud.google.com/spot-vms?hl=ja
- Preemptible VMの後継。Preemptible VMと違い24時間の制限はない
GKEのNode PoolでSpot VMやPreemptible VMを利用した場合、VMが停止してもGKEが自動で新しいVMを作成してくれます。
CI用途であれば基本的にSpot VMだけでよいです。
しかしPlantUMLやgitpandaをSpot VMのNodeに載せてNodeがシャットダウンした時に、稀にpodが削除されないことがあり新旧Nodeで1つずつのPodが存在する事象が発生していました。
旧Nodeはシャットダウン済なので当然アクセスできないのですが、GKE上はなぜか完全に消えてくれずエラーのステータスでPodが残っていて謎でした。
このような事象が発生した場合、IngressはエラーになっているPodにしかリクエストをふらないのでダウンタイムが発生していました。
このようなPodが残っていた場合に定期的に強制削除するスクリプトは既にあったのですが、スクリプトで消すまでの間にダウンタイムが発生すると嫌なのでPlantUMLやgitpandaなどのPodはRegular VMのNodeに載せるようにしました。
余談ですがこの構成にした後にterminated-pod-gc-threshold*8のことを知ったのでもしかしたらこっちの方が良かったかもしれないです。
また別件ですが、AWSのEC2のスポットインスタンスでは在庫が枯渇していた時に起動できなくなるので、スポットフリートなどで複数のインスタンスタイプやAvailability Zoneを混在させることが定番になっています。
GCEのSpot VMでも同じ問題を踏む可能性があったので念の為N1とE2の複数のマシンタイプのNode Poolを混在させることでSpot VMの在庫切れのリスクを可能な限り回避しています。(もちろんNodeも複数のzoneで動かすようにしています)
そんなこんなでGitLab CI用のGKEクラスタのNode Poolは下記のような構成になっています。
外向けのエンドポイントに対して外形監視を仕込む
外向けのエンドポイントを全てCloud IAPやCloud Armorなどで制限をかけることで大変セキュアな構成になります。
しかしセキュアにしすぎた反面、外形監視がやりづらくなるという側面もあります。
色々考えた結果、 ヘルスチェック用のホスト( healthcheck.example.com
)を作成し、GitLabが提供しているヘルスチェック用のエンドポイント *9 である/-/liveness
のみnginxで通すようにしました。
# /etc/nginx/sites-enabled/gitlab_healthcheck.conf server { listen 0.0.0.0:80; server_name healthcheck.example.com; # (略) location /-/liveness { # (略) } }
そしてこのエンドポイントをDatadogのSynthetic Monitoringで監視するようにしました。
このエンドポイントは下記のようなレスポンスなので仮にDatadog以外からアクセスされても問題ありません。
$ curl -s https://healthcheck.example.com/-/liveness {"status":"ok"}
オンプレミスのサーバにGitLab Runnerを設置
GCP移行前のGitLabではオンプレミスのサーバにデプロイするためにイントラ環境内にGitLab Runnerを設置していました。(構成図だとintra runnerに該当)
移行後もこのintra runnerは必要だったので接続先の設定のみ変えて続投させています。
GCP外からGitLabのAPIをたたくための口を作った
GitLabのエンドポイントはCloud IAPが挟まっているため基本的には外部からAPIを叩けません。
これにより仮にアクセストークンなどが流出してもAPI経由でリポジトリの内容などが漏洩しなくて安全ではあるのですが、それはそれで不便ではあります。
そのためCloud IAPを設定してるエンドポイントとは別に gitlab-api.example.com
のようなエンドポイントを作成し、このエンドポイントに対してCloud ArmorでオンプレミスのサーバやVPNのIPアドレスのみを許可する設定を入れています。
やったこと3: 本番のデータを移行する検証
GitLabのデータを素朴に移行するには
- 旧環境でバックアップを作成
- バックアップファイルを旧環境から新環境に転送
- バックアップファイルを新環境でリストア
の3ステップを踏めばいいです。
ここでネックになっていたのがバックアップ作成のための所要時間とファイルサイズです。
ピクシブのGitLabでは毎朝バックアップ作成のcronが実行されるのですが、バックアップの作成だけでも1日3〜4時間くらいかかります。作成されたtarファイルのサイズは1つ辺り約240GBあります。
データ移行時には不整合を起こさないために旧環境を止める必要があるのですが、素朴にやるとバックアップファイルの作成と転送だけで丸1日潰れかねません。
そのためメンテ時間を長引かせないために事前に色々と検証を行ったりメンテ時のデータ転送を減らすためのための様々な工夫を行いました。
下記のような準備や対策をしておくことで、当日のデータ転送の時間を1時間程度に抑えることができました。(当日の作業に関しては後編で詳しく書きます)
データ移行の手間を減らすためにいくつかのデータを前もってGCP移行しておく
地味ですがこれが効きました。
GitLabではバックアップの1つのtarファイルの中にさらに個別にファイルやディレクトリが格納されています。
バックアップファイルの中で容量を喰っていたのがGitLab上からアップロードされたファイルが格納されるuploads.tar.gz(16GB)とgitリポジトリが格納されているrepositoriesディレクトリ(240GB)でした。
サイズとバックアップ作成時間の関係でバックアップファイルには含めていないのですが、GitLab CIのログやArtifactsが格納されているディレクトリも540GBとそれなりにボリュームがありました。
repositories以外はGitLabではローカルに保存しなくてもGCSやS3などのオブジェクトストレージに置くことができます。
移行後はGCSを使う予定だったので、これらを先にGCSに移行しておくことでデータ移行の手間を減らすことができます。
具体的には下記のように旧本番環境のGitLab APから新本番環境のGCSを参照させるようにし、メンテ時のデータ転送の手間をなくしました。
既存のファイルのオブジェクトストレージへの移行は下記を参考に実施しました。
本番のバックアップを実際にGCPに持っていっての検証
バックアップファイルで一番容量を喰っていたのがgitリポジトリのデータだったので、gitリポジトリと前述のGCS移行したファイルを除いた状態でバックアップを作成しGCPに転送するようにします。
gitリポジトリを除いたバックアップファイルは数十GBだったのでメンテ時に移行できそうなサイズでした。
本番のgitリポジトリだけを差分でGCPに移行できるようにするための検証
gitリポジトリはとにかくでかいのでrsyncのように差分転送をすることでメンテ時のデータ転送を減らすことを考えました。
しかしここでもファイル転送に苦戦しました。
セキュリティのため新環境のAPはプライベートサブネットにあったため、旧環境から新環境にrsyncするためには下記のように踏み台サーバを経由する必要がありました。
数ファイルならこれでも問題なかったのですが、gitリポジトリ内にはだいたい30万ファイルありました。
踏み台サーバでトラフィックが詰まって十分な転送速度が出なかったのと、rsyncコマンドがファイル転送に1コアしか使わない仕様のため、rsyncの初回転送がいつまで終わりませんでした。(一晩経っても全然進んでいなくて諦めたと思います...)
色々調べた結果、Cloud SDKの gsutil rsync コマンドがマルチコアでファイル転送を行ってくれることが分かったので、gsutil rsync
コマンドを利用してGCS経由でgitリポジトリを差分転送するようにしました。
GitLabの旧APサーバはCPUを36コア積んでいたため36並列でファイル転送ができました。(実際に gsutil rsync
も36プロセス起動していたのも確認)
この構成をとることにより初回転送が2〜3時間で完了しました。
初回転送完了後は1日1回程度コマンドを実行して差分を転送していました。
細かいですが、稼働中のGitLab APで全力でgsutil rsync
を行うとGitLabの動作に影響を与える可能性があったので https://cloud.google.com/storage/docs/gsutil/addlhelp/GlobalCommandLineOptions を参考に ionice -c 2
をつけることで ディスクへの負荷を抑えつつ転送を行っていました。
やったこと4: 移行の段取り
前述のデータ転送以外にもGitLab移行のために細かい段取りや調整を行っていました。
複数あったGWS組織を1つの組織に統一
前提として、Cloud IAPを利用するには OAuth同意画面 を作成する必要があります。
OAuth同意画面のスコープの ユーザの種類 に内部(同じGWS組織の人のみ認証できる)と外部(gmailやGWSのアカウントを持っている人全員が認証できる)*10の2種類があります。
外部にするためには動画キャプチャを添えてGoogleの審査を通す必要があるので、社内システムであれば基本的に内部でいいと思います。
しかしピクシブでは歴史的経緯でメインで使ってる社員用のGWS組織(メインGWS組織と呼称)とそれ以外の業者委託用のサブのGWS組織(サブGWS組織と呼称)が存在していたためこのOAuth同意画面が移行のネックになっていました。
そしてなんやかんやあって現在ではこのサブGWS組織は非推奨になって現在では業務携形態問わずメインGWS組織を利用するようになっています。
しかし昔からおられる業務委託などの人たちに関してはサブGWS組織を使っているケースがあったので、コーポレート基盤部の人たちと協力してサブGWS組織の人たちを全員メインGWS組織に移行しました。
GitLabのAdminコンソールからはemailアドレスでの検索ができないので、GitLabの rails console
から下記のようなワンライナーで抽出しました。
puts User.where("email LIKE ?", "%@sub-gws.example.com").reject(&:blocked?).map { |u| [u.username, u.email].join(",") }.join("\n")
このワンライナーでは特定のメールアドレスに後方一致&ブロックされていない(GitLab上は退職処理が行われていない)ユーザのみを抽出しています。
このワンライナーで抽出した結果30〜40アカウントくらい見つかり、テストアカウントや退場処理漏れなどを除いた実際の移行対象者は10人くらいいました。
LDAPのメールアドレスのpixiv.comをpixiv.co.jpに移行
移行前の旧GitLabではLDAPによる認証を提供していました。
歴史的経緯により pixiv.co.jp
よりも前に pixiv.com
が使われていて、その関係でLDAPでも一部 pixiv.com
が残ったままになっており、そのためにGitLab上でも pixiv.com
が残っていました。
前述の通りGitLab移行で認証をOneLogin SAMLに切り替える予定だったのですがOneLoginでは pixiv.co.jp
で管理しています。
もしこの状態で pixiv.com
ユーザが新GitLabにログインすると pixiv.co.jp
で新しくアカウントが作成され、 pixiv.com
と pixiv.co.jp
で2つアカウントが存在するという面倒な状態になります。
LDAP認証でないStandard認証のユーザの場合管理画面でメールアドレスを変更できるのですが、LDAP認証だと直接メールアドレスの変更ができません。(LDAPの管理画面からメールアドレスの変更はできるのだが、対象ユーザがGitLabにログインしなおしてくれないとデータが反映されない仕様)
対象者がたくさんいたので個々人で何かしら対応してもらうにしてもなるべくその手間は減らしてあげた方が全社レベルで見ると工数が削減できますしトラブルも少なくなります。
そのため、 LDAPの管理画面から pixiv.com
を pixiv.co.jp
に一斉変更しつつ、対象の人たちにGitLabから一度ログアウトしてログインしなおしてもらうようにアナウンスをしました。(対象者は数十人いたと思います)
オープンβテスト
前述の通りGitLabの移行によりgitアクセス周りの仕組みが大きく変わるので移行直後にgit cloneができないなどの相談が社内から大量にくることが予想されました。
別件でGitLabの本番データをリストアした検証環境を作っていたので、この環境をオープンβと称して全社員に開放しました。
これによりGitLabを実際に移行する前に社内のエンジニアに利用してもらいフィードバックをもらうことができました。
移行をする日を決めてアナウンス
8月下旬くらいにはGitLabの新本番環境は完成して、あとはメンテを入れて実際に移行をするだけとなりました。
移行日を決めるために下記のようなことを考慮しました
- ピクシブの夏インターンと期間とかぶっていないこと
- 夏インターンは5〜8日間と短いです。インターン生は数十人いてそれぞれインターンのスケジュールも異なっていました。インターンの期間中にGitLabの移行を行うとインターン生のセットアップの二度手間になります。そうするとインターン生の作業時間が短くなり開発体験が悪くなるため、それを避けるために夏インターンとかぶらないようにしました
- 月初は入場者対応で忙しいので入場者対応が落ち着いた月の中旬で行う
- 移行作業はGitLabが完全に使えなくなるので業務時間中の移行作業は行わない。かつ、移行作業自体も時間がかかるので休日に行う
- 移行前後にサービスの大きなリリースが控えていないこと
- 移行直前に大きなリリースがあると、もしそれが原因でバグが起きた時にGitLabが使えないのは困る
- 移行直後は各エンジニアが開発環境の再セットアップをしたり、移行の影響でアプリがデプロイできない可能性もある
- 大安吉日(重要)
- カレンダーで大安の日を調査
この辺を諸々考慮した結果、10/16(日)の大安吉日にGitLab移行を行うことを決め、移行日の約1ヶ月前に全社にアナウンスを行いました。
最後に
いかがでしたでしょうか?
次回は実際の移行作業と移行後の所感について書こうと思います。
後編も前編と中編と同じくらいのボリュームです。お楽しみに!
*1:https://sue445.hatenablog.com/entry/2021/12/30/205629
*2:https://docs.gitlab.com/ee/user/project/repository/mirror/pull.html
*3:https://about.gitlab.com/pricing/
*4:https://docs.gitlab.com/charts/charts/gitlab/webservice/
*5:https://gitlab.com/gitlab-org/omnibus-gitlab/-/blob/master/files/gitlab-config-template/gitlab.rb.template
*6:https://cloud.google.com/iap/docs/using-tcp-forwarding?hl=ja にあるように厳密には35.235.240.0/20からの接続のみ許可している必要はあります
*7:https://cloud.google.com/compute/docs/troubleshooting/troubleshooting-ssh?hl=ja#failed_to_connect_to_backend
*8:https://kubernetes.io/ja/docs/concepts/workloads/pods/pod-lifecycle/#pod-garbage-collection
*9:https://docs.gitlab.com/ee/user/admin_area/monitoring/health_check.html
*10:あくまで認証するための権限なので、認証後に認可されるかどうかはロードバランサーの設定やアプリケーション側の実装に委ねられる