1
/
5

3週間のインターンで kube fork を劇的に改善した話

こんにちは 👋
3週間、DX Squad でインターンしていた大森です。

インターン中いろいろな課題を解決したのでまとめブログを書きます✍️

目次

  1. DX Squad とは
  2. インターンの目標
  3. kube fork に与えた変更
  4. 大きな変更点
    1. fork 時に service 名 を自動で解決する
    2. remote fork 時にすべてのservice を forkする
    3. fork 時に任意のコマンドを実行できるようになった
  5. 達成された体験
  6. まとめ

DX Squad とは

社内の技術基盤や制度を整えることで社内のエンジニアの生産性を向上させることに責務を持つ Developer eXperience squad

詳しくは DX Squad のリーダの大坪さんの投稿をご覧ください!


インターンの目標

3週間のインターンで kube という社内ツールの改善に取り組みました。
kube とは、kubectl のラッパーのことで、社内で広く使われています。



kube には様々な機能があるのですが、今回は kube fork という機能をもっと使いやすくすることを目標にインターンを行いました。

kube fork

マイクロサービスの開発では、様々な言語で書かれたアプリケーションが相互に通信を行っています。そのうちの一部を変更したいと思った時、docker-compose などを用いて関係するサービスをすべて手元で実行するのは現実的ではありません。

そこで、DX Squad では fork とremote fork というコマンドを実装しています。


詳しくはぜひリンク先を見てほしいのですが、ざっくりまとめると以下のような感じです。

  1. モノリシックなアプリケーションの開発は手元で完結していたのでやりやすかった
  2. マイクロサービスの開発は関連するアプリケーションについても知る必要があって大変
  3. クラスタにデプロイして変更を確かめようとすると他の人に迷惑をかけるかもしれない
  4. Istio と Telepresence を使うことで 自分専用のクラスタを持っているような開発体験を得られる

ここからは具体的に forkfork remote を使うと何ができるのかについて説明します。

fork の機能

  1. `kube sandbox fork` を実行
  2. server を起動するコマンドを実行

上記の手順を実行すると、自分のリクエストは自分専用の開発環境に下図のようにルーティングされるようになります。

この状態で、開発環境にブラウザからアクセスすることで実際のリクエストを使ってマイクロサービスの開発をすることができます。

このようにして、開発者一人ひとりが自分専用のクラスタを持っているような開発体験を実現しています。

fork がやっていること

kube sandbox fork は以下のような操作をしています。

  1. Service を Apply する
  2. Telepresence を Apply する
  3. 特定のヘッダが付いた通信は 2. でApply された Telepresence にルーティングされるように Virtual Service で設定する

上記の流れのように、トラップした通信を Telepresence を用いて手元のマシンに転送しています。

remote fork の機能

  1. `kube sandbox fork remote <branch-name>` を実行
  2. ブラウザから開発環境にアクセス

remote fork は fork と異なり、手元で開発環境を起動する必要がありません。指定した branch の HEAD の状態の Docker Image がデプロイされることになります。この機能の一番の利点は、docker build を待ちさえすれば手元に開発環境がなくても開発を行うことができることです。また、他にも実際のクラスタでアプリケーションが動作するので環境差異がなくなることも利点として挙げられます。

remote fork がやっていること

kube sandbox fork remote は以下のような操作をしています。

  1. Serviceを Apply する
  2. 自分の指定したバージョンの Tagがついた Deployment を Apply する
  3. 特定のヘッダが付いた通信は 2. でApply された Deployment にルーティングされるように, VirtualService で設定する

remote fork は、Kubernetes クラスタに対して Service とVirtualService をApplyして、特定のヘッダが付いた通信をトラップするところまでは同じなのですが、トラップした通信は Kubernetes 上に Apply した Deployment にルーティングされます。
この機能を使うことで、自分の手元に環境を構築することなく開発が行えるようになります。

kube fork に加えた変更

ここまで fork, remote fork の良さを語ってきましたが、実際にはオプションを付けたり、色々考える必要がある状態でした。

これから、インターンで変更したと大きな変更点について説明します。

インターンで変更した点
1. fork 時のデフォルトのプロトコルを指定できるようになった
2. 複数の service を fork できるようになった
3. service を自動で解決するようになった
4. fork remote ですべての service を fork するようになった
5. ログがみやすくなった
6. fork したときに任意のシェルを使えるようになった
7. fork したあとに自動でコマンドを実行できるようになった
8. fork したアプリケーションも newrelic で簡単に計測できるようになった
9. fork remote --grpc してもコマンドが終了しなくなった

変更点の中でも、体験が大きく変わった部分については詳しく説明します。

体験が大きく変わった点
3. service を自動で解決するようになった
4. fork remote ですべての service を fork するようになった
7. fork したあとに自動でコマンドを実行できるようになった

インターンで変更した点

1. fork 時のデフォルトのプロトコルを指定できるようになった

Wantedly では アプリケーション間の通信に gRPC を採用している事が多いです。しかし、移行中などの理由で gRPC と HTTP の両方で通信を受け付けているアプリケーションが多いです。片方のプロトコルにしか実装されていない機能などもあり、どちらのプロトコルで fork するべきかわからないという問題がありました。これは、.kuberc に HTTP or gRPC を記入することでデフォルトのプロトコルをリポジトリごとに決められるようにして解決しました。

$ kube sandbox fork --grpc # before
$ kube sandbox fork # after

2. 複数の service を fork できるようになった

Wantedly では基本的に 1つのNamespace にHTTP用の Service と gRPC用の Service の2つがありますが、HTTPに 2つの Service が存在している アプリケーションがありました。既存のインターフェイスでは複数の service を指定できなかったので、どちらか一方を選ぶ必要がありました。kube fork のインターフェイスとして複数の Service を受け入れるようにして解決しました。

$ kube sandbox fork --service-name some-service-internal # 
$ kube sandbox fork --service-name some-service-nodeport # Must choose one of these

$ kube sandbox fork \
--service-name some-service-internal \
--service-name some-service-nodeport # After

3. service を自動で解決するようになった

これまで --service-name を用いて service を指定してきましたが、すべてのアプリケーションの service を探したり覚えたりするのは面倒です。詳しくは後の変更点2 で記載しますが、自動で service を解決できるようにしました。

$ kube sandbox fork --service-name some-service-internal # Before
$ kube sandbox fork $ After

4. fork remote ですべての service を fork するようになった

fork remote でも --service-name を指定する必要がありました。詳しくは後の変更点2 で記載しますが、必要な service をすべて fork remote できるようにしました。

$ kube sandbox fork remote --service-name some-service-internal # Before
$ kube sandbox fork remote # After

5. ログがみやすくなった

fork remote 時はコンソールにログが表示されるのですが、ライブラリの問題でログが重複していた問題がありました。stern に変えることでこの問題は解決しました。

6. fork したときに任意のシェルを使えるようになった

fork 時は telepresence を用いてローカルに通信をルーティングしています。telepresence を起動したときにログインシェルを起動せず、環境変数などが足りなくなる問題がありました。

この問題は telepresence --run $SHELL をするようにして対処しました。

7. fork したあとに自動でコマンドを実行できるようになった

fork した後、起動するためのコマンドを毎回入力するのが手間だという声があったので、コマンドを実行できるようにしました。詳しくは変更点3 で説明します。

8. fork したアプリケーションも newrelic で簡単に計測できるようになった

Wantedly では newrelic を用いてアプリケーションの性能比較を行っています。newrelicの課金体系はホスト毎なので、コストカットのために特定のラベルがついた Deployment のみ 計測するようになっています。

ここで、 fork remote 時に newrelic 用の Deployment を特定するのが大変でした。

これには、--newrelic というオプションをつけると newrelic 用のDeploymentが使用されるようにしました。

$ kube sandbox fork remote --deployment-name some-deployment-newrelic # before
$ kube sandbox fork remote --newrelic # After

9. fork remote --grpc してもコマンドが終了しなくなった

fork--grpc オプションでアプリケーションのプロトコルの指定ができます。しかし、remote fork はすべての service を fork するようになったので remote fork にはこのオプションはありません。それを知らずに --grpc をつけて実行するとコマンドが終了してしまい、開発者体験が悪くなっていました。

これは仕様なので問題ではないのですが、開発者にわかりやすく伝わるようにメッセージを出力するようにしました。

$ kube sandbox fork remote --grpc # Before
unknown flag: --grpc

$ kube-go sb fork remote --grpc # After
`remote` will resolve service automatically
You don't have to add `--grpc` option

変更点1: service を自動で解決するようになった

WHY

fork を行うときは以下の様にコマンドを実行します。

$ kube sandbox fork --service-name some-app-http --namespace some-app
$ kube sandbox fork --service-name some-app-grpc --grpc -namespace some-app

Wantedly では アプリケーション間の通信に gRPC を採用している事が多いです。しかし、まだ移行中なので gRPC と HTTP の両方のservice プロトコル別に service が立っています。
ここで、開発者はこのアプリケーションはどちらのプロトコルで、どの service を用いて通信を行っているかを特定する必要があります。

WHAT

wantedly にはそれぞれのマイクロサービスがどのような internal url を持つかを集めた yaml があり、そのyaml をもとに service を特定する仕組みを実装しました。
また、.kuberc という設定ファイルに デフォルトのプロトコルを書けるようにしたことで grpc
かどうかを特定する仕組みも実装しました。

この2つの変更が行われたことで、開発者はどのリポジトリでも同じコマンドを入力するだけで fork
を行うことができる
ようになりました。

$ kube sandbox fork --service-name some-service # before
$ kube sandbox fork # after

変更点2: fork remote ですべての service を fork するようになった

WHY

remote fork を行うときは以下のようにコマンドを実行します。

$ kube sandbox fork remote --service-name HTTP

$ kube sandbox fork remote --service-name GRPC

ここで問題になるのは 前述したように service 名の特定が難しいことだけでなく、どのように通信を行うかを開発者に考えさせる点です。先述したようにWantedlyのアプリケーションは http と grpc の両方を使って通信を行う場合があります。

- Service 名 
- HTTP
- GRPC

上記の様にservice が2つあるアプリケーションに対し、下記のようにremote fork を行った場合選ばなかった方の通信は取りこぼすことになります。

$ kube sandbox fork remote --service-name HTTP 

WHAT

下図のように、必要なだけService と Deployment を作成しすべての通信を fork するようにしました。

結果的に、開発者はどのリポジトリでも同じコマンドを入力するだけで remote fork を行うことができるようになりました。

$ kube sandbox fork remote --service-name some-service # Before (1)
$ kube sandbox fork remote --service-name some-service-grpc # Before (2)

$ kube sandbox fork remote # After

変更点3: fork したあとに自動でコマンドを実行できるようになった

WHY

前述したとおり、fork を行うと手元にクラスタから通信が流れてくるようになります。
しかし、アプリケーションが自動で立ち上がったりはしないので開発者はコマンドを入力してアプリケーションを起動する必要があります。

  1. kube sandbox fork して待つ
  2. 立ち上がってきたシェルのなかで yarn start などアプリケーションの起動を行う

ここで、開発者は一つのアプリケーションを触り続けるわけではない ので、それぞれ異なる起動方法を調べる必要があるという問題が発生します。

以下にアプリケーションの開発に必要なコマンドを例として示します。

  • アプリケーションA
    • 開発する前: bash script/bootstap
    • 開発する時: yarn start
  • アプリケーションB
    • 開発する前: make setup
    • 開発する時: grapi server
  • アプリケーションC
    • 開発する前: bash script/bootstap
    • 開発する時: yarn ssr:watch && yarn start

頻繁に違うアプリケーションの開発を行う時、READMEを見て環境を整えて... というのはだいぶ手間になってきます。

WHAT

kube には .kuberc という設定ファイルを読み込む機能があります。
そこに適切なコマンドを書いておくことで、fork 時に必要なコマンドが自動的に実行される仕組みを導入しました。

fork:
install:
steps:
- run: bash script/bootstrap
start:
http:
steps:
- run: yarn start &
- run: yarn ssr:watch
grpc:
steps:
- run: yarn start
env:
- GRPC=true

この仕組みを導入することで、コマンドを入力して待つだけでアプリケーションが動いている状態にすることができました。

# Before
$ kube sandbox fork
︙ #起動するまで待つ
$ yarn start &
$ yarn ssr:watch

# After
$ kube sandbox fork

達成された体験

もともとの fork のインターフェイスでは、service 名を指定する必要があったり、そもそもどのように通信がルーティングされるかというKubernetesに関する知識が必要でした。

今回の改善で、開発者は fork するだけでアプリケーション開発を始められるようになりました。また、fork はアプリケーション開発を始める前に必要なプロセスを省略してくれるので、開発者は変更したいコード自体に集中することができます。

言い換えるとこれは、Kubernetesに関する知識がなくても、アプリケーションに関する知識がなくても開発が行えるようになったと言えます。

今回加えたいくつかの変更で、DX Squad が目指す 未来の開発体験 に一歩近づいたんじゃないかなと思っています!

まとめ

実は、先述した体験は理想的なアプリケーションでしか達成できていません。
未来の開発体験を実現するにはまだまだ解決すべき課題はありますが、この三週間で少しは先に進められたと思っています!

リモートでインターンをしてたこともあり、メンターの大坪さんにはとても助けていただきました。
また、リモートランチを一緒になった社員の方々、関わってくださった方々にはとても感謝しています!
3週間ありがとうございました!

Wantedly, Inc.では一緒に働く仲間を募集しています
17 いいね!
17 いいね!
同じタグの記事
今週のランキング