PLAIDのインターンを振り返って ~ 開発環境の改善がもたらす新機能リリースの効率化 ~

自己紹介

はじめまして、エンジニアインターンの渋谷です。Twitterはしぶちゃり@sivchariという名前でやってます。僕は2021年6月から2022年3月までの期間PLAIDでエンジニアとしてインターンをしていました。PLAIDのサービスである、KARTEは複数のプラグインを導入することで様々な機能を利用することができます。そのため各機能ごとにチームが存在しており、僕はその中の1つであるQualtDataで働いていました。

この記事では、PLAIDのインターンを通じて特に大きく改善できた開発環境周りの話と、インターンを通じて感じたPLAIDに対しての感想と自身の考え方の変化について書いていきます。

PLAIDのインターンを知ったきっかけ

僕がインターンとしてPLAIDに入社したのは前述の通り6月です。そこまでに僕は複数の就業型インターンを経験していましたが、どこか成長を感じなくなっており大学4年生の1年間でいかにエンジニアとしてより良くなれるかについて考えていました。
僕がその時に感じていた課題は2つありました。
1つは根本的なエンジニアとしてのスキルです。ひと口にエンジニアのスキルといっても十人十色、感じるものは様々にあると思います。この時に僕が感じていたスキルは例えば以下のようなものです。

  • コーディングスキル
  • コーディングスピード
  • ソフトウェアアーキテクチャ設計

2つ目は、エンジニアとして自身の関わる事業ドメインを最大化するための動き方です。
しかし、当初はインターンが全て終わったタイミングだったことと、大学4年生からインターンとして働かせていただける企業は無さそうだなという所感があり、個人開発をしながら、行きたいと思えばその時にインターンを探そうという感じでした。
ちょうどそのようなことを考えていたときに友人であり、既にPLAIDでエンジニアインターンをしていたとさくんの誘いがあり、扱っている事業の面白さと事業フェーズにとても興味が湧き、働くことになりました。この誘いがなければ、確実に今よりはスキルがなかったので、本当に恵まれていたなと思います。

配属チーム

ogp.png

僕が働いていたQualtDataというチームでは、ノーコードで外部のサービスとデータ連携を行ったり、ワークフローを管理することができるジョブフローや、これらの機能により一元化されたデータを用いてスプレッドシートやダッシュボードを作成し、データを可視化できる機能などをサービスとして提供しています。

8d406a2-768.png

上記の内容からもわかるようにqualtdataでは様々な機能を提供しているため、機能ごとにさらにチームが存在する体制でした。僕はこの中でスプレッドシート機能を提供するシートチームで働いていました。
QualtDataではVue.js, TypeScript, GCP, mongoなどにより構成されており、アーキテクチャはStoreパターンをベースとした設計となっています。ここでStoreパターンと呼ぶ設計はコンポーネント指向のUI開発時に起きがちな密結合・複雑化問題をStoreパターンで解決するで詳しく述べられています。

開発環境に対する悩み

タスクに取り組むうちにQualtDataのアーキテクチャや実装には徐々に慣れていくこともでき大きく躓くことはありませんでしたが、開発環境(コンテナ開発環境)とCircleCIによるCI/CDパイプラインにおいて改善したいという気持ちが湧いていきました。

まず前者の開発環境についての悩みです。QualtDataでは開発環境としてDockerを用いたコンテナ開発環境を用いています。Dockerは新しく開発に参加したメンバーの環境をコードとして管理でき、メンバー間の環境差分をなくすことができるなど確かなメリットが存在します。しかし、QualtDataはサービス規模の大きさもあり、開発環境を構築するだけでもかなりの時間がかかっていました。実際に僕やその後入ってきたインターン生が環境構築のために1日半近く時間を要しているという事実もあります。
またupstreamに追従したりコードレビューのサイクルにおいて一度自分の手元で確認したい場合、仮にライブラリの追加や更新があったときに依存周りの解決がうまく行かずにエラーが出ているケースなどもありました。エラーを解決するために一度依存周りをクリアして再度インストールする必要もあったため、これによりまた開発環境を構築するのと同等の時間が必要になるという悪循環も起こりました。そのため、僕はupstreamへの追従をする際にも大丈夫かなと少し心配になったりしていました。
加えてKARTEをDockerで立ち上げるためには多くのメモリとボリュームが必要なため、ある程度のスペックがあるPCで、Dockerに多くのメモリなどを割り当てる必要があるというマシンスペックが求められるという問題もありました。

次に後者のCI/CDのパイプラインについてです。おそらくこの問題はある程度の規模の開発をしている方には経験があるかと思います。QualtDataではコンテナイメージを作成するためにCloud Buildを使用しており、ステップを全て完了するために20分ほど掛かっていました。その中には後述するstargzのためのコンテナイメージを作成するというステップもあり短くできそうな課題が残っていました。

開発環境を改善したい!!

上記の問題を解決することで、最低限このようなメリットが生まれると考えました。

  • ビジネスを最大化するための機能実装やバグ修正に集中することができる
  • upstreamへの追従等を行うときに依存周りでこけることが無くなる
  • コンテナイメージ作成の時間が短くなるため、より短いイテレーションで新しいコンテナイメージを提供できる
  • 新しくPLAIDで働く人がすぐに開発に参加できる
  • マシンスペックが今ほど要求されなくなる

そこでメンターの方と開発環境の改善を行いたいことを話しました。すると既にKubernetesを開発環境として用いるプロジェクトが動いていることを教えていただき、シート機能と並行して開発環境を改善するプロジェクトも行うことになりました。

開発環境としてKubernetesを利用する(GKE)

前述の内容をKubernetesを開発環境として用いることでクリアしようとしていました。
PLAIDではGoogleとの提携もあり、社内システムの多くがGCP基盤の上で開発されています。QualtDataも同様にproduction, developerがGKE上で運用されています。このような背景もあり、開発環境もGKEを用いてセッティングする方針となっています。
確かにKubernetesを開発環境とすることでコンテナを開発環境として用いた時の問題点は達成されたといえます。しかし今のままでは開発した内容を変更するたびにデプロイして確認するという開発者の体験を損ねてしまう状態です。そのためリアルタイムで反映させることで開発体験も維持する仕組みが必要でした。
解決策としてTiltというKubernetesの開発をサポートするライブラリを使用しています。
Tiltはソースコードやマニフェストの変更を監視しており、変更があった際に差分をリアルタイムで反映させる機能を持っています。これにより抱えていた開発体験を維持するという目標も達成されました。
またTiltを用いることで、立ち上げ対象のサービス名が書かれているymlを1行いじるだけで立ち上げにコントロールが簡単にできるというメリットも生まれました。

developImages:
  - myApp1
  # - MyApp2 #このサービスは立ち上げない
  - myApp3

ここまでは既に整備されていた環境であったため、自分の既に身についていたKubernetesの知識を引き出しながら触ってみることで理解できました。そしてこの状態で残っていた課題にはこのようなことがありました。
まず、Kubernetesの開発環境はstargzのコンテナイメージを用いているため、セットアップで置き換えるためのスクリプトファイルが黒魔術になっていたことです。そして前述の通りstargzのコンテナイメージ生成のためにCloudBuildの時間が伸びていたため、stargzと同等の速さでコンテナが立ち上がるライブラリや機能があれば剥がしたいという課題です。
次にwebpackを用いてフロントを開発しているチームで、Tiltの設定が不足しておりフロントの変更をサーバー側が変更を検知できていない、ファイルが大きく同期に時間がかかることで一見反映されてないように感じてしまうといった課題です。
この課題を発見したときに開発体験の向上をしたいという自身のモチベーションともマッチし取り組ませていただきました。

stargzからGKEのイメージストリーミング機能に変更する

まずstargzを剥がすタスクに取り組みました。stargzを導入した当初はおそらく存在していなかった、GKEの新機能であるイメージストリーミングを用いるという方針を取りました。
イメージストリーミング機能とはコンテナイメージ全体がダウンロードされるのを待たずにワークロードを初期化することができる機能です。そのため初期化時間を大幅に短くできるため、Podの起動を高速化する他、大きなコンテナイメージをpullするときにレイテンシを短縮することが可能となります。
仕組みとしては、GKEは本来各ノードにコンテナイメージ全体をダウンロードしルートファイルシステムとして用いますが、ルートファイルシステムとしてリモートファイルシステムを使ういます。こうすることで実際に必要なイメージ部分のみを提供することが可能となります。
より詳しい内容や実際に手を動かすことができるページがこちらです。サンプルではKubernetesのチュートリアル等でも用いられるguestbookのイメージを用いて比較しています。
標準機能では24秒ほどimageのpullに時間を要していますが、イメージストリーミングを用いることでimage pullに1.5秒しかかからないという結果が出ています。
GKEを使っていることからもイメージストリーミングが使えるため、まず検証としてイメージストリーミング対応のクラスターを作成し実際に立ち上がるまでの速度を検証することにしました。
PLAIDではterraformで管理しているため、新たにイメージストリーミング対応のノードプールを作成し、検証しました。

resource "google_container_node_pool" "image_streaming_pool" {
  provider = google-beta

  name               = "image-streaming"
  location           = "asia-east1"
  cluster            = google_container_cluster.development.name
  initial_node_count = 2
  node_locations = ["asia-east1-a",
    "asia-east1-b",
  "asia-east1-c", ]

  node_config {
    # We should use COS_CONTAINERD. Image stereaming feature is only supported this image type.
    image_type      = "COS_CONTAINERD"
    machine_type    = "e2-standard-8"
    service_account = "kubernetes@evaluation-karte-io-systems.iam.gserviceaccount.com"
    disk_size_gb    = 100
    disk_type       = "pd-standard"
    labels          = {}
    local_ssd_count = 0
    metadata = {
      "disable-legacy-endpoints" = "true"
    }
    tags = []
    oauth_scopes = [
      "https://www.googleapis.com/auth/devstorage.read_only",
      "https://www.googleapis.com/auth/logging.write",
      "https://www.googleapis.com/auth/monitoring",
    ]
    shielded_instance_config {
      enable_integrity_monitoring = true
      enable_secure_boot          = false
    }
    workload_metadata_config {
      mode = "GKE_METADATA"
    }
    # gcfs config is for the Google Container Filesystem (GCFS)
    # gcfs config mus be enabled in order to use image streaming
    # FYI
    # https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/container_cluster
    # https://cloud.google.com/kubernetes-engine/docs/how-to/image-streaming
    gcfs_config {
      enabled = true
    }
  }

  management {
    auto_repair  = true
    auto_upgrade = true
  }

  autoscaling {
    min_node_count = 1
    max_node_count = 20
  }
}

その後、実際にQualtDataで使用している通常のコンテナイメージを用いて速度検証をしたところ、Runningまでに22秒掛かっていましたが、イメージストリーミングでは9秒で立ち上がりました。

スクリーンショット2022-03-3115.15.49.png

このことからstargzと同等のパフォーマンスを担保できると判断し、stargzを剥がすという決断をとりました。剥がしたことによる副次的なメリットとしてCIoud Buildでのstargz対応のコンテナイメージを作成するステップが全てなくなったことで、Cloud Buildで対応前は15分から長くて20分ほどかかっていたタスクが、今ではほとんどが50秒以内に完了するようになりました。

スクリーンショット2022-03-3114.28.47.png

iOSの画像.jpg

webpack周りの問題

次にwebpack周りの問題です。現状webpackによりビルドされたファイル群をTiltにより同期していましたが、この部分は同期対象とせずローカルに対してリクエストすることでTiltの管理から外すという方針を取りました。また現状webpackを使ったいたため、変更を反映した際にリロードしないと変更部分が更新されないという状態だったため、webpack-dev-serverのホットリロードも同時に使う方針でいきました。
実装する上で気にしたこととしては、既存のローカル環境でコンテナを立ち上げ開発している人との差分を生まずに対応させることです。
最終的にscriptによる実行がメインとなるため、ここでは導入背景とドキュメントを正しく残すことを意識しました。この経験を経て不具合を解決しながらも、ただのドキュメントではなく、ドキュメントの背景を伝えるissueを残すという経験を積むことができました。

スクリーンショット2022-03-3115.17.14.png

当初の目標と現在の自分

PLAIDに入社する前に感じていた課題は以下のようなものでしたが

1つは根本的なエンジニアとしてのスキルです。ひと口にエンジニアのスキルといっても十人十色、感じるものは様々にあると思います。この時に僕が感じていたスキルは例えば以下のようなものです。

- コーディングスキル
- コーディングスピード
- ソフトウェアアーキテクチャ設計

2つ目は、エンジニアとして自身の関わる事業ドメインを最大化するための動き方です。
しかし、当初はインターンが全て終わったタイミングだったことと、大学4年生からインターンとして働かせていただける企業は無さそうだなという所感があり、個人開発をしながら、行きたいと思えばその時にインターンを探そうという感じでした。
ちょうどそのようなことを考えていたときに友人であり、既にPLAIDでエンジニアインターンをしていた[とさくん](https://twitter.com/tosa_now)の誘いがあり、扱っている事業の面白さと事業フェーズにとても興味が湧き、働くことになりました。この誘いがなければ、確実に今よりはスキルがなかったので、本当に恵まれていたなと思います。

現在の自分と比較してみます。コーディングスキルについては、前提としてまだまだでありながら、入社前の僕と比較して確実に良くなったと思います。これは複雑なビジネス背景をいかにシンプルに置き換えたり、追加するかを意識していたことで達成できたことだと思うので、今後も精進します。伸びたかもと感じた経験は、メンターの方とお話し、達成目標から逆算して問題を紐解くissueを背景を踏まえて残すということを聞いたところからだなと感じます。僕はこのお話を聞いた後から今考えていることと、ゴールから逆算し、問題を小さく切り出す癖をつけるよう意識しました。切り出してしまえば、あとは目標にそって足りない技術的な知見を足してコードを書いていくだけなので、以前に比べて無駄な行動がなく実装ができる感覚を持つことができるようになりました。このやり方は僕個人にもとてもマッチしていたため今後もより自身に合わせながらスキルを高めたいと思います。
コーディングスピードについては上記の理由から多少は向上したと思います。ただし、まだ必要な知見の引き出しが足りないなと後から振り返り感じるタスクも多かったため多くの経験という刺激をさらに感じながらあげていきたいです。
アーキテクチャ設計に関してはこの入社期間でかなり考え方に変化が起きました。入社前はレイヤードアーキテクチャやクリーンアーキテクチャというものが設計の際に一番良いものだという狭い考え方をしていました。その理由としてもただテストがしやすくなる、DIで抽象化!といったような技術的解決のアプローチのみでしか捉えていませんでした。しかしPLAIDに誘ってくれた友人とオフィスの芝生でエリックエバンスの本を輪読したことやプロダクトのアーキテクチャをみることでとてもいい方向に思考が変化しました。もっとも変化した点としては、当初ベストであると考えていたアーキテクチャは事業ドメインをどう扱うかというアプローチの1つであるベターな設計で、各事業のフェーズや企業文化により事業を雄弁に語らせるアーキテクチャは様々であるという風に考えるようになったことです。ソフトウェアのアーキテクチャ設計は自身の携わったプロダクトや経験したアーキテクチャ、ひいては感性により捉え方が変化すると考えるため深くは言及しませんがKARTEというサービスの構成が僕自身のプラスになったことは間違いないと断言できます。

次にエンジニアとして自身の関わる事業ドメインを最大化する動き方ですが、こちらも今の僕なりに答えを出せたと思います。入社前の僕は技術に精通しビジネスとの架け橋となるような存在になりたいと考えていました。しかし、PLAIDで働く社員やインターンの方はそもそもこの考え方を前提として働いていました。僕のなりたい理想像はエンジニア、ビジネス問わず達成されていたということです。他の開発環境を見るといかにこの環境が貴重なものであるかについても気づくことができました。事実PLAIDで働くエンジニアとビジネスの方々の差分をみた時にいかに自身の職業のドメインを確保しているかということでした。
より詳細に書くとすれば、自身の職業のスキルを用いてベターな解決案を提示するということです。このことからビジネスに対して最大化する提案のためには自身の技術的な引き出しをいかに増やすかが大事であるか理解することができ、引き出しの多さや柔軟性が課題を解決することがでできることも実感できました。今の僕にとってこの経験を実感できたことはとても恵まれていることでありながら、このようなことを感じられるPLAIDのインターン文化の素晴らしさも味わうことができました。

インターンを終えて

e767b3f5-fdce-4a38-b737-fa43075a87bc.avif

PLAIDのインターンを終え、僕はもう一年学生でいたかったなと率直に思いました。それほど自分のやりたいこととプロダクトが抱えている課題を解決できる場所が限られているからです。
もし少しでもPLAIDという環境に興味を持ったならば、ぜひインターンに応募することをおすすめします。
採用ページはこちらです。またはwantedlyのこちらでも応募できます。