GitLabの導入(Backlog + GitHub からの移行)

いま、社内に GitLab を導入中です。数ヶ月かけて、これまで利用していた Backlog と GitHub を、GitLab に置きかえていく予定です。

Backlog は課金額がユーザ数に依存しません。そこで、いろいろな人が関わる課題管理には Backlog を利用しています。過去の履歴を見ると、2013年から 5年以上もお世話になっています。現在のアクティブユーザー数は120名ほど。

一方 Backlog の Gitリポジトリ機能はそれほど魅力的ではないため、コード管理には GitHub を利用しています。しかし GitHub はユーザ毎にお金がかかるため、コードを書く人に限定して使っています。現在のアクティブユーザー数は50名ほど。

目次

開発の流れ

当社の開発の流れは、だいたい次のようになっています。

  1. 誰かが「○○をやりたい」と提案する。誰が何を提案してもいい。要点をまとめて Backlog に proposal(提案)として登録する。
  2. やるか、やらないか、優先度はどうするか、を毎朝のミーティングで決める。
  3. やることになった案件は planning(企画)フェーズに移行し、ディレクター、デザイナー、エンジニアなど案件毎に適切な人が仕様を決める。
  4. planningフェーズの仕様をレビューして問題がなければ、dev フェーズに移行させる。課題の優先度は毎朝の会議で決める。
  5. 優先度高の課題の中から好きなものを、手が空いたエンジニアが自分で取っていく。
  6. 開発が終わったら、提案者やディレクターがテストする。問題がなければリリース待ちとなる。
  7. リリースする。「街コンジャパン」の場合、少ない日で 1件、多い日で 10件くらいのリリースをする。ただし、売上が一番多いのが土日祝であるため、休みの前日のリリースはなるべく避ける。

    提案から仕様を作るフェーズまでが Backlog で、開発が GitHub で、開発が終わるとまた Backlog に戻ってくる。これで仕事は充分に回っているのですが、開発の全ライフサイクルにまたがった、全プロダクト横断での進捗状況の見通しが悪い状態でした。

課題

  1. 全プロダクトを横断した状況の把握がしにくい
    Backlog でも FindIssueAllOver という全プロダクト(プロジェクト)横断の検索機能がありますが、おまけ程度の存在で、あまり実用的ではありません。エンジニアやディレクターが豊富にいるわけではないので、プロダクトにかかわらず、少しでも優先度の高い案件を先にやりたいという時の機動性はあまり提供してくれません。

  2. 開発の全ライフサイクルを横断して状況が把握しにくい
    Backlog と GitHub に情報がわかれていて、相互に簡単に行き来できないため、提案、企画、開発、テスト、リリースと、ライフサイクル全体を一望しにくいという欠点がありました。それぞれの開発担当者は、同時に数個程度の案件を頭にいれておけば良いので問題になりませんが、リーダーやマネージャが数十個、数百個単位で管理する場合、ライフサイクル横断性の悪さは非効率につながります。

  3. 工数のトラッキング手法が確立されていない
    これは Backlog や GitHub の問題ではありませんが、GitLab の工数トラッキング機能は魅力的に見えました。毎月月初に、経理に工数を報告しているのですが、過去3年近くにわたって、Excelファイルを各メンバーが作成して提出しています。正確性に欠ける上に、開発者にはあまり評判がよくありません。

  4. GitHub はユーザ数とコストが比例する
    たいした出費ではないものの、ユーザ数とコストが比例するので、本当に必要なユーザのみに限定しがちになります。

導入

GitLab の EC2 へのインストール

インストール先は AWS にしました。インフラチームが用意してくれました。当社のインフラチームは、AWS が大好きです。というか、基本的に特に理由がなければ AWS を使うようにしています。

GitHubリポジトリのインポート

影響の少なそうなリポジトリから、手作業で一つずつ、インポートしていきました。現時点で 82リポジトリなので、なんとかなります。Gitのリポジトリも Issue も、全自動でインポートしてくれます。

インポート時に GitLab側にユーザが存在すると、GitHub のユーザと GitLab のユーザを紐付けてくれます。そこで、50ユーザほどを手作業で作りました。これで移行した後も快適に使えるはずです。しかしここにワナが潜んでいました。

Google Account で OAuth

当社はメールやスケジュールは G Suite を利用しているので、Googleアカウントでログインできるものは、可能な限り Googleアカウントにしています。GitLab も、当然 Googleログインしたくなります。

ところが、OAuth でログインしようとすると、既に登録済みの既存のアカウントと衝突してエラーになります。これは GitLab のバグや機能不足ではなく、「メアドが同じだからといって同じユーザであるとみなしてはいけない」というセキュリティポリシーから来ているようです。

仕方が無いので、PostgreSQL に直接アクセスして、usersテーブルのメアドを一時的に .example.com 付きに変えて待避し、利用者に OAuth でログインしてもらい、identitiesテーブルの user_id を付け替えるという方法で、既存アカウントと Googleアカウントを紐付けました。

Kubernetes で CI

リポジトリが無事に移行できたので、次は CI です。当初は、GitHub で利用していた CircleCI をそのまま使うつもりでした。しかし、CircleCI は GitLab に対応していなかったのでした。

残念に思ったものの、調べてみると GitLab の CI は、かなり強力であることがわかりました。Circle CI よりも良い感じです。しかも Kubernetes(以下 k8s)に対応している。もう、心は決まりました。使ったことのない GKE で動かそう、と。これでソース、課題管理が AWS で CI が GCP になりました。(なお、当社のプロダクトの一つは、一年くらい前から GKE で動いています)

GitLab の CI は、Runner と呼ばれるサーバ上で実行されます。GitLabサーバが、Runnerと通信して、Runner が Dockerコンテナを立ち上げて CI します。この Runner は、ローカルの PC を登録してもいいし、EC2インスタンスを登録してもいいし、k8sクラスタを登録してもいい。k8sで動かすのが、一番難易度が高くて格好良さそうです。

しかし k8s上の Runner には、バグや制約がいくつかあったのです。そしてそれはドキュメントのどこにも書かれておらず、GitLab社の issue tracker を漁って初めてわかることでした。

その1. コンテナ間の通信がホスト名でできない

以下のように書いておけば、アプリケーションからは mysql という名前のホスト名で通信できる、というのが GitLab CI の仕様です。

[code] services:
– mysql:5.7
[/code]

しかし k8s Runner では、ホスト名に 127.0.0.1 を指定しないと通信できませんでした。
https://gitlab.com/gitlab-org/gitlab-runner/issues/2229

その2. ファイルがキャッシュできない

以下のように書いておけば、ダウンロードしたライブラリがキャッシュされて、ビルドが短縮されるはずでした。

[code] cache:
paths:
– vendor/bundle
– node_modules
[/code]

しかし k8s runner では動的にノード数が変わるため、キャッシュがサポートされていません。代わりに、S3 にファイルを待避するなどの仕掛けを自分で組み込む必要があります。

今回は、Dockerイメージに gem もインストールして container registry に置いておくことで、とりあえず回避しました。gem のバージョンアップ毎に少しずつ CI が遅くなりますが、数ヶ月は耐えることでしょう。。。

CI の時間

実は GitLab CI に移行してから、CI の時間が長くなりました。k8sのノードの vCPU数を増やしても、効果は無いようでした。CI の時間は開発効率に直接の影響を与えるので、ここは何とかしたいところですが、まだ試行錯誤中です。Circle CI って、優秀だったのですね。

GitHub + Circle CI: 8分
GitLab + k8s: 12分
GitLab + k8s with CircleCI MySQL image: 10分

創業7年を経過したリンクバルは、毎期増収増益中です。リンクバルでは、会社と共に成長していきたいエンジニアを大募集中です。あなたも一緒に、リンクバルの DevOps環境を進化させてみませんか?

リンクバル 採用情報
https://hrmos.co/pages/linkbal