AWS 対応した GitHub Enterprise v2 へスムーズに移行した話

技術部 id:sora_h です。今回は v2 より AWS 上での運用に対応した GitHub Enterprise を、オフィスにある既存の環境から AWS へスムーズに移行した話について説明します。

GitHub Enterprise v2

GitHub Enterprise (以下 GHE) とは、github.com を自前の環境で運用できるアプライアンスです。クックパッドでは主に GHE 上で開発を行っています。

従来まで GHE の実行環境として VMware vSphere, VirtualBox 上の実行しかサポートされていませんでしたが、11 月にリリースされたアップデート v2 より、AWS での実行がサポートされました。

クックパッドでは全面的に AWS を利用していますが、いままで GHE を AWS 上で動作させる事はできませんでした。そのため、オフィス内に ESXi 用物理マシンを用意・メンテナンスしていましたが、 GHE の物理ホストのメンテナンスコストが高い事が問題でした。

2014 年 10 月頃に GitHub 社から AWS サポートが追加された GHE v2 のベータテストに招待されました。それを機会に、AWS への移行を前提に検証・バグ報告・移行を行いました。

ESXi 時代の構成

まずは移行前の環境について説明します。

f:id:sora_h:20150113101440p:plain

前述の通り、GHE はオフィス内に設置された VMware ESXi マシンの上で稼動させていました。

しかし、このままだと AWS 側からの SSH や HTTPS でのアクセス、および GHE からも AWS 側のリソースへアクセスする事ができません。そのため、ESXi 上に Linux の VM を別途立て、そこから AWS 側サーバーへ SSH トンネルを掘る事で対応していました。

具体的には、ssh_config(5) の RemoteForward を利用して AWS 側サーバーの特定ポートを GHE の 443, 22/tcp ポートへ転送するようにしました。同様に、GHE がアクセスする必要のある LDAP サーバー、SMTP サーバー等は LocalForward で転送し、それぞれ GHE に設定しました。

AWS 側サーバーからの git clone で利用する ssh ホストおよびポートの指定は、鍵と一緒に配布される ssh_config で Host ... および HostName を利用して、RemoteForward しているポートを利用するように設定していました。尚、配布には puppet を利用しています。

また、開発者がオフィス外のネットワークから SSH access を利用する際には、AWS 内の remote forwarded port へ接続するように、 ssh_config の ProxyCommand を利用する設定ファイルを提供していました。

外部からの HTTPS でのアクセスは、GHE の 443 に対応するポートに reverse proxy しつつ、外部ネットワークの場合は HTTP 認証をかける Apache を稼動させたサーバーを用意し、外部から GHE の FQDN を DNS で引いた時はこのサーバーの IP アドレスが返るようになっていました (この https reverse proxy は以降 github-proxy と呼称します)

以上が移行元の環境でした。

一つ、GHE 導入当時になく、現在利用できる設備として存在するのが、AWS VPC との拠点間 VPN がオフィスとの間で確立された事です。移行に際して、SSH トンネルから拠点間 VPN ベースへの切り替えも行う事になりました。

移行の要件

まずは業務に支障を出さずに移行を行う事が求められました。

また、このタイミングで GHE 導入以来利用してきた FQDN を変更する事になりました。FQDN がそのままであれば、前述の RemoteForward の ssh_config だけ対応して DNS を切り替えるだけで移行が完了します。 ですが、FQDN を変更するため、旧 URL そのままでの git clone, http access もリダイレクト等で対応し、スムーズに移行できる事が追加の要件になりました。

移行の手順

移行は下記の手順で行う事にしました。

  1. メンテナンスウィンドウを決め、事前に社内へアナウンスを流して周知する
  2. 当日、出社して時間になったら旧 GHE をメンテナンスモードに入れる
  3. 旧 GHE の ghe-backup を行う
  4. 完了次第、新 GHE に ghe-restore する
  5. proxy で旧 GHE の FQDN を新 GHE の FQDNにリダイレクトさせる設定に切り替える
  6. 旧 GHE の DNS を旧 GHE 自体から github-proxy に切り替えて、TTL を待つ
  7. 新 GHE のメンテモードを外す

下準備

バックアップ

バックアップでは従来より公式ツールである github/backup-utils を利用していました。 元々バックアップは ESXi 上の別仮想マシンで実行していましたが、バックアップ先をまず AWS へ移行し、インターネット経由でのバックアップに切り替えました。この時の経路は VPC との拠点間 VPN を利用しています。

移行までの間、自動バックアップ完了後に AWS 上に立ててある GHE のインスタンスへリストアするように設定し、なるべく最新のデータがつねに新 GHE へ同期されるようにしました。

github-proxy の新 FQDN 対応

github-proxy は今迄、ただリクエストを remote port forward された HTTPS ポートへリバースプロキシし、必要に応じて BASIC 認証を要求するというサーバーでした。

移行に際し、まず最初はリクエストに合わせて旧ドメインは旧 GHE、新ドメインは新 GHE へリバースプロキシするように設定しました。 移行後に利用する旧ドメインのリクエストを新ドメインへリダイレクトする設定の準備も行いました。

移行後は社内からもリダイレクト用に、旧ドメインのレコードを github-proxy へ向ける計画のため、SSH (port 22) へのトラフィックを新 GHE へ転送する stone も起動しました。stone についてはアクセスを社内 (VPN 経由) に security group で制限しました。

既存のサーバーや一部の開発者向け ssh_config への対応

前述のように既存のサーバーと一部の開発者に配布している ssh_config は、GHE を特定サーバー上の remote port forward された port を参照するように設定されています。また、ssh_config を持ったサーバーは大量に存在するため、移行後、git remote の url を変更するか新設定を反映させるまでアクセスするたびにエラーというのは避けたいという要件がありました。

そのため、新 GHE + 新 FQDN の ssh_config は移行前に追加しておき、いままでの ssh_config もそのまま利用できるよう、移行後は remote port forward していたポートを新 GHE の port 22 へトラフィックを転送する stone に置き換えました。その後、旧ホストの設定を削除し、新 GHE 設定の Host に旧 GHE の FQDN も追加しました。

このような手順をあらかじめ踏む事により、FQDN 変更によるエラーを最小限に留める事ができました。API を利用していた箇所についてはリダイレクトに対応できず、手動で URL を変更するまで動作しないといったケースがありましたが、開発者からの HTTPS アクセスやサーバ上の git clone/pull についてはエラーなく移行と FQDN 変更を達成しました。

移行後

git remote URL の切り替えを促す

FQDN を変更したため、git remote の設定を新ドメインに変更してもらう必要がありました。以下の ssh_config を利用すると楽ですよ、と社内ブログで周知したりしました。

Host 旧ドメイン
  Hostname 新ドメイン
  PermitLocalCommand yes
  LocalCommand bash -c 'for remote in $(git remote -v|grep "@旧ドメイン"|cut -f 1|sort|uniq); do url=$(git config remote.${remote}.url | sed -e "s/@旧ドメイン/@新ドメイン/"); echo "warn: set-url ${remote} ${url}" >/dev/stderr; git remote set-url ${remote} ${url}; done'

ssh_config の LocalCommand を利用して、旧ドメインの名前で接続を試みた時に git remote set-url を勝手に呼んでくれます。

まとめ

f:id:sora_h:20150113091602j:plain

本記事では、どのようにクックパッドが GitHub Enterprise v2 + AWS に移行しつつ、GHE の動作 FQDN を最小限のエラーで変更したかを解説しました。

(なお、写真は GitHub からベータテスト協力の gift として頂いた Octocat Figurine です (かわいい)。Thank you <3)

/* */ @import "/css/theme/report/report.css"; /* */ /* */ body{ background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527163350.png'); background-repeat: repeat-x; background-color:transparent; background-attachment: scroll; background-position: left top;} /* */ body{ border-top: 3px solid orange; color: #3c3c3c; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; line-height: 1.8; font-size: 16px; } a { text-decoration: underline; color: #693e1c; } a:hover { color: #80400e; text-decoration: underline; } .entry-title a{ color: rgb(176, 108, 28); cursor: auto; display: inline; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; font-size: 30px; font-weight: bold; height: auto; line-height: 40.5px; text-decoration: underline solid rgb(176, 108, 28); width: auto; line-height: 1.35; } .date a { color: #9b8b6c; font-size: 14px; text-decoration: none; font-weight: normal; } .urllist-title-link { font-size: 14px; } /* Recent Entries */ .recent-entries a{ color: #693e1c; } .recent-entries a:visited { color: #4d2200; text-decoration: none; } .hatena-module-recent-entries li { padding-bottom: 8px; border-bottom-width: 0px; } /*Widget*/ .hatena-module-body li { list-style-type: circle; } .hatena-module-body a{ text-decoration: none; } .hatena-module-body a:hover{ text-decoration: underline; } /* Widget name */ .hatena-module-title, .hatena-module-title a{ color: #b06c1c; margin-top: 20px; margin-bottom: 7px; } /* work frame*/ #container { width: 970px; text-align: center; margin: 0 auto; background: transparent; padding: 0 30px; } #wrapper { float: left; overflow: hidden; width: 660px; } #box2 { width: 240px; float: right; font-size: 14px; word-wrap: break-word; } /*#blog-title-inner{*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-position: left 0px;*/ /*}*/ /*.header-image-only #blog-title-inner {*/ /*background-repeat: no-repeat;*/ /*position: relative;*/ /*height: 200px;*/ /*display: none;*/ /*}*/ /*#blog-title {*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527172848.png');*/ /*background-repeat: no-repeat;*/ /*background-position: left 0px;*/ /*}*/