TelepresenceとKubernetesを使って迅速な開発を行う

# Telepresence

## Telepresenceとは
Telepresenceは [CNCF(Cloud Native Computing Foundation)](https://www.cncf.io)の[Sandboxプロジェクト](https://www.cncf.io/sandbox-projects/)の 1 つです。
Kubernetesからローカルへのリクエスト、ローカルからKubernetesへのリクエストをプロキシしてくれるツールです。
これだけだと意味がわからないので、具体的なユースケースを見ていきましょう。

## ローカルのコンテナとKubernetes上のコンテナを入れ替える


### マイクロサービスを開発する際の課題
マイクロサービス化が促進されればされるほど、ローカルで環境構築するのが困難になってきます。
docker-composeを使えばある程度緩和されますが、それでも本番環境とは構成が違ってきますし、ローカルのリソースを食います。
そこでTelepresenceを使って一連のマイクロサービスをKubernetes上に置き、**開発対象のサービスだけ**ローカルに置くことを考えます。
例として、サービスA、サービスBを想定します。
<img width="972" alt="スクリーンショット 2019-07-05 11.00.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14124/51741d2b-231f-d8ee-eeb9-f9b1a90d62cb.png">

例えばサービスAの機能だけを修正したい場合、Telepresenceを使えば、ローカルのコンテナとKubernetes上のコンテナを置き替えることができます。

つまり
ブラウザからアクセス→サービスA(**k8s上のコンテナ**)→サービスB(k8s上のコンテナ)→DB
<img width="972" alt="スクリーンショット 2019-07-05 11.00.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14124/51741d2b-231f-d8ee-eeb9-f9b1a90d62cb.png">

を
ブラウザからアクセス→サービスA(**ローカル上のコンテナ**)→サービスB(k8s上のコンテナ)→DB
<img width="962" alt="スクリーンショット 2019-07-05 11.20.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14124/9a6e7a59-149d-09d7-4681-ea38da5f6747.png">


にできます。
これにより、ローカルでサービスBの環境を構築しなくてもよくなります。

コマンドは以下です。

```bash
$ telepresence --swap-deployment {サービスAのDeployment名} --docker-run --rm -it {サービスAのDocker Image名}
```

**ローカルのvolumeをマウントしてコンテナを動かしたい場合は以下のようにします。こうするとソースを変更してもイメージを再作成しなくてもよいので迅速な開発が可能になります。**

```bash
$ telepresence --swap-deployment {サービスAのDeployment名} --docker-run --rm -v /Users/akira/work/service_a:/var/app/current -p 3000:3000 {サービスAのDocker Image名}
```

上の図は簡略化された図ですが、正確には以下のようにTelepresence ProxyとTelepresence Clientが通信を仲介してくれています。
<img width="980" alt="スクリーンショット 2019-07-07 14.30.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14124/65b39b37-6e5b-9f45-77b9-e47b39e1d30f.png">


## Kubernetesからローカルのportへリクエストを流す

ローカルでコンテナを動かさなくても、ローカルのportへリクエストを流すことができます。

#### 新しいDeploymentを作成し、そこへのリクエストをローカルのportに流す
(ただし、Kubernetes上のserviceへは名前解決ができないためアクセスできない…。)

```bash
$ telepresence --new-deployment {新しいDeployment名} --expose 3000 --run bundle exec rails s
```

新しいDeployment名を`service-c`にした場合:
<img width="976" alt="スクリーンショット 2019-07-07 14.49.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14124/e17cc711-61f0-24b9-17ad-8f0c6206826d.png">




#### 既存のDeploymentを置き換え、そこへのリクエストをローカルのportに流す
(ただし、Kubernetes上のserviceへは名前解決ができないためアクセスできない…。)

```bash
$ telepresence --swap-deployment {サービスBのDeployment名} --expose 3000 --run bundle exec rails s
```

<img width="957" alt="スクリーンショット 2019-07-07 14.51.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14124/8cfb3e98-d720-b46c-2c7e-a4ba883a219a.png">


## Kubernetesクラスタ内のサービスにアクセスする

Telepresenceを使うとKubernetesクラスタ内のサービスに簡単にアクセスすることができます。
たとえば、KubernetesのサービスBのServiceに対してローカルからリクエストを投げることができます。

```bash
$ telepresence --run curl http://service-b:3000/users/hoge
```
<img width="957" alt="スクリーンショット 2019-07-07 14.51.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14124/f8f86e49-bd3f-9fc6-02f8-21c8d839ad25.png">

`--run`移行のコマンドは、Kubernetesのコンテナ内で実行されるため、curlの他にも様々なことができます。


KubernetesのServiceはクラスタ外からアクセスできるようになっているとは限らないので、そういった場合にこういう方法はデバッグする際に便利です。


# 参考
- [Telepresence で EKS 上の k8s クラスタをデバッグする](https://qiita.com/yuzumikan15/items/5e5949f3058535f5e5ec#telepresence-%E3%82%92%E4%BD%BF%E3%81%86)
- [Telepresence で Microservices on Kubernetes の開発環境構築](https://qiita.com/os1ma/items/dfbc1420f1d58957a060)
- [マイクロサービスのTelepresenceを使ったローカル開発環境の話](https://tech.mercari.com/entry/2019/05/28/090000)