Oracle Container Engine for Kubernetes (OKE) にサービスメッシュIstioを導入してみた

- OKEのセットアップとCloud Shellを利用したアクセス
- Istioのインストール
- bookinfoアプリのデプロイ

# はじめに
マイクロサービスアーキテクチャで実装されたシステムでは、従来のモノシリックなシステムでは発生しなかった課題に対処する機能の実装が必要となります。例えば、特定のサービスの障害が広域の障害へ発展することを防止するためのリクエストを制御する仕組みや、サービス間の通信可否の制御やサービスへの不正なアクセスを防止するためのサービス間通信の保護の仕組み、複雑なマイクロサービスを監視しサービス間の問題を分析するための仕組み、未然に障害への対処をテストするための仕組み等であり、これらを全てアプリケーションで実装することは多大な労力を有します。

そこで、マイクロサービス固有の問題をアプリケーションに依存しないかたちで解決しようとしたネットワークモデルがサービスメッシュであり、サービス間のトラフィック制御やセキュリティ、可観測性の確保といったマイクロサービスを展開するために必要となる基本機能を提供する仕組みです。

IstioはGoogle, IBM, Lyft 社によって開発され、2017年にオープンソース化されたサービスメッシュであり、Kubernetesなどのプラットフォームにインストールして使用することができます。また、Istioは高機能なサービスメッシュで、トラフィックルーティングとルール設定により、サービス間のトラフィックと API 呼び出しのフローを制御可能な「トラフィック管理」、mTLSを利用したサービス間の相互認証をはじめとしたポリシーや暗号化等の「セキュリティ機能」、サービスの視覚化や複数サービスに跨った処理を追跡・分析可能な分散トレーシングおよびOSSの監視ソリューションとの連携といった「観測可能性」をシステムに提供します。

本記事では、Oracle Cloud Infrastructure (OCI) で提供されるKubernetes基盤であるOracle Container Engine for Kubernetes (OKE) にIstioをインストールし、マイクロサービスアーキテクチャで実装されたbookinfoアプリケーションをデプロイする手順を紹介します。次回以降で、Oracle Cloud Observability and Management PlatformのサービスであるApplication Performance Monitoring (OCI APM) を利用した分散トレーシングの実装、LoggingとLogging Analyticsを利用したIstioのログ分析方法をご紹介します。

# 検証環境 
- Kubernetes: 1.22.5
- Istio: 1.13.3

なお、本記事の検証は管理者ユーザー (Administrators Groupに属したユーザー) で実施しています。
dministrators Groupに属したユーザーで実施する場合は、下記のドキュメントに従って必要なポリシーを設定する必要があります。

[Container Engine for Kubernetes (OKE)　クラスタの作成とデプロイメントのためのポリシー構成](https://docs.oracle.com/ja-jp/iaas/Content/ContEng/Concepts/contengpolicyconfig.htm)


# Kubernetesクラスタのセットアップ
OKEのクイック作成ウィザードを利用することで、手軽に短時間でKubernetesクラスタを構築することが出来ます。
OCIサービスコンソールの左上のメニューの**開発者サービス**より、**Kubernetesクラスタ**を選択し、OKEの管理画面でKubernetesクラスタを作成するコンパートメントを選択し、**クラスタの作成**ボタンを押します。

![Fig1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/831381/d2e3283d-901c-7da9-eaa6-c4da18a1b010.png)
![Fig2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/831381/662c7399-bd90-ba12-8793-81e2b66990b3.png)

既存のVCNにKubernetesクラスタを作成する場合は*カスタム作成*を選択しますが、今回は手軽に検証環境を作成するためにVCN等のネットワーク・リソースを新規作成する**クイック作成**よりKubernetesクラスタを作成します。**クイック作成**を選択し、**ワークフローの起動**ボタンを押します。

![Fig3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/831381/6a9cbdc2-1655-ab6c-ee55-98bbb9ed908e.png)


下記の様に各項目を入力し **次**ボタンを押します。

---
* 名前: 任意の名前　Istio_OKE
* コンパートメントの選択: 任意のコンパートメント名　 /dev
* Kubernetesバージョン: v1.22.5
* Kubernetes APIのエンドポイント: パブリック・エンドポイント
* Kubernetesワーカー・ノード: プライベート・ワーカー
* シェイプ：VM.Standard.E4.Flex (リソース量は任意, 1 OCPU / 16 GB RAMで構築)
* ノード数 : 任意 (1ノード)

---

![Fig4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/831381/caf20fb4-3c72-c7df-df68-916dc9386b80.png)
![Fig5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/831381/482d07b5-1240-00cf-aee1-a2e6e7dc83c7.png)

各設定項目を確認して、**クラスタの作成**ボタンを押すと各ネットワーク・リソースが自動作成され、Kubernetesクラスタの作成が開始されます。

5分から10分程度でクラスタがアクティブになり、これだけでKubernetesを利用する準備完了です。

![Fig6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/831381/3ada5ffb-0246-9d55-d5ca-26f4eb8e5e73.png)

# Cloud Shellを利用したKubernetesクラスタへのアクセス
画面右上にあるターミナルアイコン (?) をクリックして、Cloud Shellを起動します。

![Fig7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/831381/3eed5e69-2d45-565d-e863-f8619310f2c1.png)


Cloud Shellの画面は右上のアイコンを操作することでブラウザいっぱいに最大化することや最小化することも出来るので、OCIのサービス・コンソール操作を行いながらコマンドラインの操作を行うことができ、生産性を向上させることができます。
また、ocicliやkubectlも予めインストールされているため、Kubernetesクラスタを作ったらすぐにPodsを構築してアプリケーションを稼働させることが出来ます。それでは、kubectlの初期設定を行いKubernetesクラスタへのアクセスを確認したいと思います。

![Fig8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/831381/5d4e6689-9096-7d0f-9e7d-95703d8f5674.png)


作成されたKubernetesクラスタの詳細画面より、**クラスタへのアクセス**ボタンを押します。そうするとクラスタへのアクセス方式を選択できるので、*Cloud Shellアクセス*を選択し、接続設定に必要なコマンドをコピーしてCloud Shellで実行します。

![Fig9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/831381/744f4aae-774d-1007-d4f1-a0b562544368.png)


```shell
$ oci ce cluster create-kubeconfig --cluster-id ocid1.cluster.oc1.ap-tokyo-1.aaaaaa(略)7dsqhq --file $HOME/.kube/config --region ap-tokyo-1 --token-version 2.0.0  --kube-endpoint PUBLIC_ENDPOINT

Existing Kubeconfig file found at ~/.kube/config and new config merged into it
```
これだけで接続設定が完了です。
早速Kubernetesクラスタにアクセスしてkubectlのバージョンと比較してみましょう。(1バージョン差のみサポート)

```shell
$ kubectl version

Client Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.5", GitCommit:"5c99e2ac2ff9a3c549d9ca665e7bc05a3e18f07e", GitTreeState:"clean", BuildDate:"2021-12-16T08:38:33Z", GoVersion:"go1.16.12", Compiler:"gc", Platform:"linux/amd64"}

Server Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.5", GitCommit:"c999fea1e6dbf111d64000dfaaff45edaa4c34d2", GitTreeState:"clean", BuildDate:"2022-01-11T12:16:14Z", GoVersion:"go1.16.12 BoringCrypto", Compiler:"gc", Platform:"linux/amd64"}

$ 
```
これでKubernetesクラスタを利用する準備が完了です。

# Istioのインストール

KubernetesクラスタにIstioをインストールしていきましょう。
Githubからダウンロードし展開します、環境変数を設定しprecheckを実施します。

```shell
$ curl -L https://istio.io/downloadIstio | sh -

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   101  100   101    0     0    301      0 --:--:-- --:--:-- --:--:--   300
100  4926  100  4926    0     0   7945      0 --:--:-- --:--:-- --:--:--  7945

Downloading istio-1.13.3 from https://github.com/istio/istio/releases/download/1.13.3/istio-1.13.3-linux-amd64.tar.gz ...

Istio 1.13.3 Download Complete!

Istio has been successfully downloaded into the istio-1.13.3 folder on your system.

Next Steps:
See https://istio.io/latest/docs/setup/install/ to add Istio to your Kubernetes cluster.

To configure the istioctl client tool for your workstation,
add the /home/xxxxx/istio-1.13.3/bin directory to your environment path variable with:
         export PATH="$PATH:/home/xxxxx/istio-1.13.3/bin"

Begin the Istio pre-installation check by running:
         istioctl x precheck 

Need more information? Visit https://istio.io/latest/docs/setup/install/ 

$ cd istio-1.13.3
$ export PATH=$PWD/bin:$PATH
$ istioctl x precheck

✔ No issues found when checking the cluster. Istio is safe to install or upgrade!
  To get started, check out https://istio.io/latest/docs/setup/getting-started/
```

次にIstioをKubernetesクラスタにインストールしましょう。
なお、この後の操作は全てistio-1.13.3ディレクイトリ下で実施しています。

```shell
$ istioctl install

This will install the Istio 1.13.3 default profile with ["Istio core" "Istiod" "Ingress gateways"] components into the cluster. Proceed? (y/N) y
✔ Istio core installed                                                                                                                                                                                     
✔ Istiod installed                                                                                                                                                                                         
✔ Ingress gateways installed                                                                                                                                                                               
✔ Installation complete                                                                                                                                                                                    Making this installation the default for injection and validation.

Thank you for installing Istio 1.13.  Please take a few minutes to tell us about your install/upgrade experience!  https://forms.gle/pzWZpAvMVBecaQ9h9

$ 
```

以上でIstioのインストール完了です。

# bookinfoアプリケーションのデプロイ

それでは、マイクロサービスアーキテクチャで実装されたbookinfoアプリケーションをデプロイしてみましょう。
bookinfoアプリケーションは下記のようにProductpageサービス、Detailsサービス、Reviewサービス、Ratingサービスで構成されており、それぞれ異なる言語で開発されたサービスが各々のPodsで稼働します。

![Fig12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/831381/586aa9d3-cffd-3796-4543-aad810f68a6b.jpeg)
*出典: https://docs.oracle.com/ja-jp/iaas/Content/ContEng/Tasks/contengistio-intro-topic.htm#managing_traffic*

bookinfoアプリケーションがデプロイされる名前空間defaultにIstioがSidecarが構成 (Inject) されるようにistio-injection=enabledを使用してアプリケーションをホストするネームスペースにラベルを付けます。

```shell
$ kubectl label namespace default istio-injection=enabled

namespace/default labeled
```

Bookinfoアプリケーションをデプロイします。

```shell
$ kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml

service/details created
serviceaccount/bookinfo-details created
deployment.apps/details-v1 created
service/ratings created
serviceaccount/bookinfo-ratings created
deployment.apps/ratings-v1 created
service/reviews created
serviceaccount/bookinfo-reviews created
deployment.apps/reviews-v1 created
deployment.apps/reviews-v2 created
deployment.apps/reviews-v3 created
service/productpage created
serviceaccount/bookinfo-productpage created
deployment.apps/productpage-v1 created
```

稼働しているServiceとPodを確認してみます。

```shell
$ kubectl get services

NAME          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
details       ClusterIP   10.96.217.157   <none>        9080/TCP   2m18s
kubernetes    ClusterIP   10.96.0.1       <none>        443/TCP    137m
productpage   ClusterIP   10.96.94.190    <none>        9080/TCP   2m18s
ratings       ClusterIP   10.96.22.233    <none>        9080/TCP   2m18s
reviews       ClusterIP   10.96.169.232   <none>        9080/TCP   2m18s

$ kubectl get pods

NAME                              READY   STATUS    RESTARTS   AGE
details-v1-79f774bdb9-xg8nq       2/2     Running   0          2m32s
productpage-v1-6b746f74dc-bmb8k   2/2     Running   0          2m31s
ratings-v1-b6994bb9-b4xcg         2/2     Running   0          2m32s
reviews-v1-545db77b95-qw7dm       2/2     Running   0          2m32s
reviews-v2-7bf8c9648f-ws2rd       2/2     Running   0          2m32s
reviews-v3-84779c7bbc-mmfn6       2/2     Running   0          2m32s
```

IstioのEnvoyがSidecarでInjectされているため、2/2と表示され1つのPodに2つのコンテナが稼働していることが確認できました。
rating Pod内からcurlコマンドを送信して、bookinfoアプリケーションが正常に実行されていることを確認します。

```shell
$ kubectl exec "$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -sS productpage:9080/productpage | grep -o "<title>.*</title>"

<title>Simple Bookstore App</title>
```
外部からアクセス出来るように、IstioのIngress Gatewayを作成します。
Ingress Gatewayを作成するとOCI Load Blancerのパブリック・ロードバランサが自動的に作成されます。Ingress Gatewayを作成後、割り当てられているパブリックIPを確認します。

```shell
$ kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml

gateway.networking.istio.io/bookinfo-gateway created
virtualservice.networking.istio.io/bookinfo created

$ kubectl get svc istio-ingressgateway -n istio-system

NAME                   TYPE           CLUSTER-IP     EXTERNAL-IP       PORT(S)                                      AGE
istio-ingressgateway   LoadBalancer   10.96.65.136   XX.XX.XX.XX   15021:30356/TCP,80:30996/TCP,443:32405/TCP   49m
```

Ingress Gatewayに割り当てられたパブリックIP経由でbookinfoアプリケーションにアクセス出来ることを確認します。

```shell
$ curl -s "http://XX.XX.XX.XX:80/productpage" | grep -o "<title>.*</title>"

<title>Simple Bookstore App</title>
```
無事にアクセスできました。
最後にブラウザからもURL (http://XX.XX.XX.XX:80/productpage) を指定してアクセスしでみます。

![Fig15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/831381/6885ec31-671f-e099-bb8a-5a8fec1bd7c9.png)


こちらも上記のような画面が確認できればOKです。なお、ブラウザを更新することでBook Reviewの星のアイコンが変化することがわかると思います。これは、reviewsサービスには3つのバージョンがあり、アクセスする度にいずれかにルーティングされるように設定されているからです。


# 最後に
OKEとCloud Shellを利用することでKubernetesクラスタを構築し、サービスメッシュとしてIstioを導入、マイクロサービスアーキテクチャで実装されたアプリケーションをデプロイするまでの作業を数十分で実施することが出来ました。
Application Performance Monitoring (APM) を利用した分散トレースの実装に[続く](https://qiita.com/orakurara/items/e3d0954eb83a21fe1d7b)。。。

# 参考情報
[Oracle Cloud Infrastructureドキュメント　例: OKEへのIstioサービス メッシュのインストール](https://docs.oracle.com/ja-jp/iaas/Content/ContEng/Tasks/contengistio-intro-topic.htm#managing_traffic)

[OCIチュートリアル　Oracle Container Engine for Kubernetes(OKE)でサンプルマイクロサービスアプリケーションをデプロイしてオブザバビリティツールを利用してみよう](https://oracle-japan.github.io/ocitutorials/cloud-native/oke-for-advances/)

[Istio Documentation　Ingress Gateway](https://istio.io/latest/docs/tasks/traffic-management/ingress/ingress-control/#determining-the-ingress-ip-and-ports)

[Istio / Bookinfo Application](https://istio.io/latest/docs/examples/bookinfo/)