Kubernetes, Istioの環境構築（Linux, kind, istioctl使用、helm 不使用）

この記事は[2019新卒 エンジニア Advent Calendar 2019](https://qiita.com/advent-calendar/2019/2019-graduates)の11日目の記事です。

普段業務でkubernetesやistioに触れる機会が多いので、復習も兼ねて環境構築の一例を紹介したいと思います。

（登場するIPアドレスは一時的なものなのでアクセスしても何もありません。。。）

# 予備知識
## kubernetesとは

宣言的に管理できるコンテナオーケストレーションツールです。

yamlという形式で（ある必要はないですが）**「nginxのイメージを使ったコンテナを3台立ち上げる」**と書いておけば3台立ち上げてくれて、立てたコンテナに負荷分散する形でサービスを公開したり、ヘルスチェックしてリスタートしたりと、コンテナアプリケーションをデプロイする上で必要な機能が揃っています。

kubernetesは通常複数の**Node**から構成され、Nodeというのはコンテナのホストとなるマシンのことで物理マシンだったりVMだったりします。

Node上には複数のコンテナが展開することになるのですが、このコンテナの1まとまりを**Pod**と呼びます。

Podの中のコンテナは互いにファイルシステムやIPアドレスを共有するという特徴があり、1つのPodが複数のNodeに跨ってdeployされることはありません。


## istioとは

**サービスメッシュ**を実現するためのツールです。これをkubernetes内で動かすことで、各コンテナごとに専用のプロキシがついて全ての通信がそのプロキシを経由するようになるため、可観測性が上がり、リトライしたりサーキットブレーカーを導入したりといったことがやりやすくなります。

istioはkubernetes上ではPodの中に専用のプロキシとして動作するコンテナが入る形になるため、**1つのPodにアプリケーション用のコンテナとプロキシ用のコンテナが入ることになります。**

# 本題
## 環境構築
環境構築は面倒なのでconohaでVPSを借ります。1時間1円程度で汚れない環境が手に入ると思うと安いですね。**自宅のネットの上り下りが1Mbps**なことを考慮しても賢い選択肢だと思います。

OS: Ubuntu 18.04.2 LTS
Docker: 19.03.1

### kind(kubernetes)

今回はdocker環境でk8sを動かせるkind（kubernetes in docker）を使っていきます。実際のkubernetesを使えればそれでいいのですが、テストで使うにはわざわざ感があるので、kindを使います。

簡易的なk8sを実現するツールは、k3sやminikubeなど他の選択肢もあるのですが、今回はkindを使っていきます。

quick-startを頼りにinstallします。公式のコンポーネントのテストにも使われています。
https://kind.sigs.k8s.io/docs/user/quick-start/

```console
curl -Lo ./kind https://github.com/kubernetes-sigs/kind/releases/download/v0.6.1/kind-$(uname)-amd64
chmod +x ./kind
mv ./kind /usr/local/bin/kind
```

kindはマルチノードを作ることができるので、折角なので利用しましょう。

```yaml:config.yml
kind: Cluster
apiVersion: kind.sigs.k8s.io/v1alpha3
nodes:
- role: control-plane
- role: worker
- role: worker
```

そして適用しましょう。

```console
kind create cluster --config config.yml
```

### kubectl
kubectlというコマンドラインツールもinstallしましょう。
[公式](https://kubernetes.io/ja/docs/tasks/tools/install-kubectl/#linux%e3%81%b8kubectl%e3%82%92%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab%e3%81%99%e3%82%8b)

```console
curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl
chmod +x ./kubectl
mv ./kubectl /usr/local/bin/kubectl
```

うまく行けばnodeの情報が取れると思います。

```console
root@150-95-200-74:~# kubectl get node
NAME                 STATUS   ROLES    AGE    VERSION
kind-control-plane   Ready    master   117s   v1.16.3
kind-worker          Ready    <none>   75s    v1.16.3
kind-worker2         Ready    <none>   75s    v1.16.3
```

マルチノードなclusterを作成することができました。

### istio

次にistioを入れます。istioは1.3までは`helm`というkubernetesのパッケージマネージャ的なやつを使って入れることができましたが、最近リリースされた1.4ではhelmは使えなくなりました。代わりに`istioctl`というクライアントツールを利用します。（やっていることは大量のyamlファイルをいい感じに適用してくれるだけです）

こちらをもとに入れていきます。
https://istio.io/docs/setup/getting-started/

```console
curl -L https://istio.io/downloadIstio | sh -
cd istio-1.4.1
mv bin/istioctl /usr/local/bin
# pathを通せれば何でもいいです

istioctl manifest apply --set profile=demo
```

これでistioの主要なコンポーネントがinstallされたので機能を使うことができるようになります。

```console
root@150-95-200-74:~# kubectl get pod -A
NAMESPACE      NAME                                         READY   STATUS    RESTARTS   AGE
istio-system   grafana-6b65874977-j8htn                     1/1     Running   0          5m11s
istio-system   istio-citadel-86d9c5dc-6fwrh                 1/1     Running   0          5m12s
istio-system   istio-egressgateway-7cb7fdff55-hmskf         1/1     Running   0          5m13s
istio-system   istio-galley-6ff4cbc457-rvm7s                1/1     Running   0          5m12s
istio-system   istio-ingressgateway-68884574c5-9skg7        1/1     Running   0          5m14s
istio-system   istio-pilot-5646cc96d4-nc49t                 1/1     Running   0          5m12s
istio-system   istio-policy-7c76fb7fdb-kfvg9                1/1     Running   3          5m14s
istio-system   istio-sidecar-injector-5464f6dff-7t4bt       1/1     Running   0          5m12s
istio-system   istio-telemetry-557d4bf784-n7xf8             1/1     Running   3          5m13s
istio-system   istio-tracing-c66d67cd9-ckxqd                1/1     Running   0          5m14s
istio-system   kiali-8559969566-nf4th                       1/1     Running   0          5m12s
istio-system   prometheus-66c5887c86-kf9rw                  1/1     Running   0          5m12s
kube-system    coredns-5644d7b6d9-8wpjp                     1/1     Running   0          10m
kube-system    coredns-5644d7b6d9-fhw2n                     1/1     Running   0          10m
kube-system    etcd-kind-control-plane                      1/1     Running   0          10m
kube-system    kindnet-jx4qc                                1/1     Running   0          10m
kube-system    kindnet-v2bch                                1/1     Running   0          10m
kube-system    kindnet-x2v8c                                1/1     Running   0          10m
kube-system    kube-apiserver-kind-control-plane            1/1     Running   0          9m52s
kube-system    kube-controller-manager-kind-control-plane   1/1     Running   0          9m53s
kube-system    kube-proxy-2dgzx                             1/1     Running   0          10m
kube-system    kube-proxy-gw9ld                             1/1     Running   0          10m
kube-system    kube-proxy-hdtw9                             1/1     Running   0          10m
kube-system    kube-scheduler-kind-control-plane            1/1     Running   0          10m
root@150-95-200-74:~#
```

まだ何のアプリケーションも動かしていないのに凄いコンポーネントの量ですね:sweat:

## istioのサンプルアプリケーションを動かしてみる

空っぽだとつまらないので、サンプルアプリケーションを動かしてみましょう。
https://istio.io/docs/examples/bookinfo/#deploying-the-application

```console
kubectl label namespace default istio-injection=enabled
# defaultというnamespaceにラベルを付けて、全てのpodに自動的にistioのプロキシを追加するようにするコマンド。こういう形でdefaultのnamespaceを普通は汚したくない笑

# istio-1.4.1配下にsamplesディレクトリがある
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml

# gatewayとvirtual serviceというリソースの追加。
kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
```

`Gateway`はLoad Balancerに対して特定のリクエストを取得するための設定です。hostがhogehogeで、portが80番はこのGatewayで受け付けるといった感じです。

`VirtualService`は、Gatewayと合わせて利用することで、L7の情報を利用してルーティングの設定を行うことができ、今回は先程設定したGatewayを通ったリクエストのうち特定のpathに合致するものをproductpageというserviceに送る設定となっています。

VirtualServiceを利用してheaderを追加したり、削除したりも出来るので触る機会が多いリソースです。

## 実際にアクセス！

さて、これでbookinfoというアプリケーションがkubernetes上で動いています。実際にブラウザからアクセスしてみましょう。

もし今動かしている環境が`AKS`や`GKE`などのマネージドサービスを利用している場合はistioのLoad BalancerのIPにアクセスできますが、今回はそうではないので、リクエストを振り分けるPodにport-forwardを経由してアクセスします。（詳しく知りたい方はkubernetesのServiceのLoadBalancer typeを調べてみてください）

```console
kubectl port-forward -n istio-system istio-ingressgateway-68884574c5-9skg7 80:80 --address 0.0.0.0
```

`istio-ingressgateway-68884574c5-9skg7`というのはPod名で取得するためには`kubectl get pod -n istio-system`などを実行してください。

`addressオプション`を使用してlocalhost以外でもアクセスできるようにしているので、今動かしているhostの`IPアドレス/productpage`にブラウザからアクセスしてみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121571/9894620f-8db3-5593-42eb-f76c47fa23fb.png)

おめでとうございます。こんなページが表示されれば実際にアクセスすることが出来ています。

ほんとにアクセス出来ているの？という懐疑心旺盛な方のためにistioのvisualizeツール的な存在である`kiali`を使って見てみましょう。

本来であれば`istioctl dashboard kiali`というコマンドを叩けばport-forwardされてブラウザが開くのですが、何分sshしている身ですので、localhostで見れても仕方がないのでもう一度先程のようなコマンドを叩きます。

```console
kubectl port-forward -n istio-system kiali-8559969566-nf4th  --address 0.0.0.0 80:20001
```

kialiはコンテナが20001番で公開しているのでそれに合わせるために上記のような形になります。Pod名はランダムで変わるので取得し直してください。

`IPアドレス/kiali`でアクセスして、最初のログイン画面はadmin,adminで突破しましょう。

そして以下のようなマイクロサービスっぽい画面が出てきたら成功です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121571/716657c9-1553-6e69-197d-bc3edaee3880.png)

どういうリクエストが成功しているかが分かりやすくていいですね。左上のnamespaceの設定をistioとdefaultの両方をチェックしておくと画像のようになります。

## 今後

今回紹介した環境構築はわりと楽な部類だと思います。MacやWindowsに入れるとなると諸所異なるところが出るので難しいとは思いますが。VPSを使うときれいな環境でrootでドカドカ作業できるので結構おすすめです。

次の記事では今回作った環境を用いてistioの様々な機能を試して行きたいと思います。例えば、Retry, fault injectionなどがあります。