LegalOn Technologies Engineering Blog

LegalOn Technologies 開発チームによるブログです。

GitHub Codespacesの導入

こんにちは、LegalOn TechnologiesのLegalForce開発部のSRE 伊藤です。

私たちのチームでは、LegalForceの安定稼働と同様に、開発者がより楽に開発・運用できるような基盤を提供することをミッションにさまざまな改善活動を行なっています。

今回はGitHub CodespacesをLegalForceのバックエンドの開発に導入した話をご紹介します。

GitHub Codespacesとは

GitHubが提供しているクラウド開発環境で、通常十数秒で起動し、すぐ開発環境が手に入ります。

削除や再作成も手軽に行え、CPU/Memoryなどのスペックの変更も容易です。

デフォルトのエディタはVS Codeですが、その他のIDEでもリモート開発機能を通じて扱うことが可能です。

https://github.co.jp/features/codespaces

LegalForceの開発における課題

当時のバックエンドの開発環境は、開発者のローカルで複数のDockerコンテナ(Hanamiアプリケーション、nginx、mysql、redis、sidekiq)を動かす構成になっていました。

これを見直すきっかけとなったのは、2021年末〜2022年始に、リーダー陣が集まり今後のLegalForceのアーキテクチャや開発スタイルの方向性を話す会が開催されたことでした。

その中で当時のバックエンドの開発環境において、

  • ローカルの環境でコンテナ動かすのが重い
  • 開発チームにジョインしたその日のうちにコードを読み、手元でステップ実行できる状態にしたい
    • しかしソフトウェアのインストールや設定などが面倒である
      • Ruby、Docker、Docker Compose、direnv、aws-vaultなど

などの課題が上がりました。

また同時期に、自分達のチームが行っているDeveloper Surveyでも同様の課題感を抱えている開発者がいると分かりました。

※Developer Survey

LegalForce開発部内で独自に行っている開発者向けのサーベイ。開発環境やCI/CD、モニタリングなどの現在の開発・運用における開発者の体験を計測し、改善に活かす目的で半年に一回程度のペースで行っている。

解決策

技術選定

上記を受けて、この問題の解決のオーナーシップが自分達のチームに割り当てられました。

社内でも既に他の部門がGCP上のインスタンス上でリモート開発している事例を知り、LegalForce開発部でも同じような環境を整備することでこの問題を一定解決できるのではと考えました。

そして、選択肢に上がった以下のものを調査・検証することになりました。

これらからツールを選定するにあたり、主に以下が論点となりました。

  • 使い勝手
  • コスト
  • セキュリティ
  • 機能・将来性

まず、使い勝手のところではDeveloper SurveyからVS Codeを使っている開発者が2/3程度を占めると分かっていたので相性の良いプラットフォームとしてGitHub Codespacesが第一候補に上がりました。

他の選択肢もSSHで接続できたり、GitPodやCoderはかなりVS Code風なブラウザエディタを使うことできますが、やはりワンクリックでVS Code Desktopと接続し起動できるGitHub Codespacesの使い勝手は良さそうだと感じました。

※現在GitPodはβではありますがVS Code DesktopやJetBrains Gatewayなど各種IDEとの連携ができるようです。

コスト面では金額の他に、開発者・SREの運用面でのコストを鑑みて、自分たちでインスタンスを立てるAmazon EC2や、kubernetesクラスタなど自前のインフラにホストする必要があるCoderは選択肢から消えました。

ここまでで、第一候補GitHub Codespaces、第二候補GitPodというところまで絞り込み、両者は金額面でほぼ同じ、セキュリティも方法は違えど第三者とのネットワーク、コンピューティング環境の分離レベルは実用レベルであると調査からわかりました。

最終的な判断としては、使い勝手のところでVS Codeとの相性の良さや、(当時まだβでしたが)GitHub Copilotとの連携などプラットフォームとしての将来性を考慮しGitHub Codespacesを選択することにしました。

開発環境の構築において工夫した点

GItHub Codespacesでローカルと同様の開発環境を提供するために課題となったのが、内部で使っているAPIへのアクセスです。

LegalForce構成図

上の構成図に表されるように、LegalForceの主な機能は自然言語処理や検索などのAPIを組み合わせて実現されており、Webバックエンドから利用されます。

本番環境や検証環境においては、これらのAPIVPCの外部からはアクセスできない構成となっています。

開発環境ではVPC外からのアクセス用のロードバランサーをオフィスのIPアドレスを制限する形で用意しており、VPN接続や出社をすることで開発ができていました。

従来と同じような環境を提供するためには、GitHub Codespacesの機能によって起動したリモートの環境 (以下 codespace と呼びます) からそれらのAPIへアクセスする必要がありました。

公式ドキュメントによるとプライベートネットワークへの接続について、GitHub CLI 拡張機能を使用するかVPNを使用するかのどちらかが推奨されていますが、VPN製品のCLIをcodespaceのイメージにインストールしておき、それを使ってVPN接続することで対応しました。

理由としては、codespace内でコマンドを実行する方がcodespace起動時に自動でVPN接続を確立することができ(後述)、毎回ローカルでGitHub CLIコマンドを実行するよりも手間が少なくなると判断したからです。

VPN接続に必要な認証情報はCodespaces secretsにあらかじめ登録しておくことで、codespace内では環境変数経由でCLIに値を渡し使用しています。

ここで一点ハマったポイントとしては、デフォルトのVPN設定ではcodespaceと外側の通信の全てがVPNトンネルに流れしまいローカルとcodespaceの通信が途切れてしまうことでした。

これに対しては自然言語処理や検索のAPIへ向かう通信のみVPNトンネルに流れるようにcodepspace内のルーティングテーブルを起動時に設定することで対応しました。

ルーティングのイメージ図

泥臭く ip route コマンドを使ってルーティングの設定を書いているのですが、これをスクリプト化し、codespaceの作成・起動時に自動的にVPN接続・ルーティングの設定ができる仕組みになっています。

codespaceの作成・起動時にスクリプトを流す仕組みは、postCreateCommandとpostStartCommandを利用していて、それぞれ、codespaceが作成された時に実行されるコマンド、codespaceが起動する時に実行されるコマンドです。

ここではpostCreateCommandでAWS CLIの名前付きプロファイルの設定、postStartCommandではVPN接続とルーティングの設定を行なっています。

それぞれのスクリプトの中身は以下の通りです。

  • postCreateCommand.sh

    #!/bin/bash
    
    ls ${HOME}/.aws >/dev/null 2>&1 || mkdir ${HOME}/.aws
    cat <<EOS > ${HOME}/.aws/config
    [profile lf-dev]
    sso_start_url = <AWS SSOのログイン画面のURL>
    sso_region = ap-northeast-1
    sso_account_id = <AWSアカウントID>
    sso_role_name = ${AWS_SSO_ROLE_NAME}
    region = ap-northeast-1
    output = json
    EOS
    
  • postStartCommand.sh

    #!/bin/bash
    
    # LF_OFFICE_VPN_USERNAME, LF_OFFICE_VPN_PASSWORDはあらかじめCodespaces secretsに登録しておく
    # vpn.confでは set-routes = 0 と設定し、VPN接続時にデフォルトで設定されるルーティングを無効にしてある
    nohup bash -c "sudo --preserve-env=LF_OFFICE_VPN_USERNAME,LF_OFFICE_VPN_PASSWORD /usr/bin/openfortivpn --username \\"${LF_OFFICE_VPN_USERNAME}\\" --password \\"${LF_OFFICE_VPN_PASSWORD}\\" -c .devcontainer/vpn.conf &"
    
    # connection確立まで待つ
    sleep 10
    
    for ip in $(dig <ロードバランサーのドメイン> A +short)
    do
        sudo ip route add "${ip}"/32 via "$(ip addr show ppp0 | grep -oP '(?<=inet\\s)\\d+(\\.\\d+){3}')" dev ppp0
    done
    

最終的なGitHub Codespacesを使った開発環境の構成は以下の通りになりました。

開発環境の構成図

結果

GitHub Codespacesを導入したことでバックエンドの開発環境が十数秒で準備できるようになり、ローカルが重くなる問題も解決しました。

仕組み上仕方ない部分ではありますが、codespaceとローカルとのレイテンシはある程度存在したり、codespaceの起動が若干面倒に感じたりする部分はあるものの、元々の課題の解決以外にも以下の点でメリットを感じており、総合的にデメリットを上回ると思っています。

  • ソースコードやデータ、AWSの認証情報などをローカルに保存することなく開発ができる
  • マシンスペックを柔軟に変更できる
  • 気軽に環境を0から再作成できる
  • インターネットに接続さえしていればローカルのマシンのスペック関係なく快適に開発ができる
  • 作業場所のネットワーク帯域が狭くてもcodespaceはクラウド上にあるのでパッケージのインストール等が高速に行える

今後

さらにGitHub Codespacesの機能を駆使すると、従来のローカルの環境でできなかった様々なことができるようになると考えています。

例えば、現状バックエンドとフロントエンドのリポジトリが分かれており、これらを組み合わせて動かすには複数のリポジトリの対象のブランチを引っ張ってきてローカルで同時に起動する、またはステージング環境にデプロイする必要があるなど手間がかかっています。

これに対し、codespace上で起動しているアプリケーションのポートを公開(認証付き)する機能を利用することで、バックエンドエンジニアとフロントエンジニアが並行で開発を進めながら手軽に結合して動作確認ができるなど、当初の課題を超えてさらに楽に素早く開発ができるようになると考えています。

まとめ

今回はGitHub Codespacesをバックエンドの開発環境に導入した話をお届けしました。

LegalOn TechnologiesのSREチームでは、プロダクトの信頼性を担保する活動や開発者が楽に開発・運用できるような基盤を整備する活動を通じて顧客により大きな価値を届けられるようこれからも改善を続けていきます。

もし興味があれば下記の募集要項をご覧ください!

ぜひ私たちと一緒に、法とテクノロジーの力で、安心して前進できる社会を創っていきましょう。