Dapr ✕ Kubernetesのクラスタ構成を確認してみる

# はじめに

Daprはローカル環境で動作するSelf-hostedモードの他に、Kubernetesクラスタと連携して動作するKubernetesモードがあります。このKubernetesモードの動作を確認するのに良いサンプルが、Dapr公式のHello Kubernetesクイックスタートになります。
https://github.com/dapr/quickstarts/tree/master/tutorials/hello-kubernetes

本記事では、このクイックスタートの環境を動かし、デプロイされるポッドやサービスを確認することにより、KubenetesクラスタにDaprを導入したときの構成を紐解いていきたいと思います。

# 学べること

- Minikubeを使ったHello Kubernetesクイックスタートの動かし方
- KubernetesクラスタにDaprを導入するための設定方法の概要
- Daprを導入したときのKubernetesクラスタの構成

**※これまでに投稿したDaprに関する記事**

- [マイクロサービスを簡単に連携させるランタイム「Dapr」について](https://qiita.com/highitoh/items/8c1643fb5d6d7634a5f9)
- [Daprのクイックスタートでサービス呼出しのイメージを掴む](https://qiita.com/highitoh/items/7276ac138d09336dde15)

# 環境構築

DaprのHello Kubernetesクイックスタートを使って、DaprがKubernetesクラスタにどのように展開されるかを見ていきたいと思います。今回は、Kubernetes環境としてminikubeを使用します。minikubeでクイックスタートを動かすには、各Stepで以下の操作を行います。

**Step1**
下の公式サイトに書かれている方法で、minikubeをインストールします。
https://minikube.sigs.k8s.io/docs/start/
私の環境(Linux X86-64)では、下のコマンドでインストールできました。

```
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
```

また、kubectlを併せてインストールします。

```
https://kubernetes.io/ja/docs/tasks/tools/install-kubectl/
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
sudo mv ./kubectl /usr/local/bin/kubectl
```

**Step2**
Step 2の1.でRedisストレージのセットアップを行いますが、ここではKubernetes向けRedisをセットアップします。下の図の赤枠で囲ったKubernetesタブに書かれた内容に従って、環境を構築します。



なお、セットアップを実行するには、Helmをインストールする必要があります。私はHelmプロジェクト( https://helm.sh/ja/docs/intro/install/ )からバイナリリリースをインストールしました。
実際には、下のコマンドでHelm(執筆当時の最新 v3.8.2)をインストールしました。

```
curl -LO https://get.helm.sh/helm-v3.8.2-linux-amd64.tar.gz
tar -xvf helm-v3.8.2-linux-amd64.tar.gz
sudo mv linux-amd64/helm /usr/local/bin/helm
```

**Step7**
minikubeを使用している場合、typeをloadbalancerに設定しても、EXTERNAL-IPがpendingと表示され、IPが割り当てられません。minikube tunnelを利用すると、IPが割り当てられるようになります。

```
minikube tunnel
```

# KubernetesクラスタにDaprを導入する設定

KubernetesクラスタにDaprを導入するには、マニフェストにDaprのアノテーションを追加します。Hello Kubernetesでは、次のようにデプロイメントにアノテーションが追加されています。

```deploy/node.yaml(抜粋)
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "nodeapp"
        dapr.io/app-port: "3000"
```
```deploy/python.yaml(抜粋)
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "pythonapp"
```

これを見ると、Daprを組み込むためにenabledとapp-idのアノテーションを記述する必要があることが分かります。逆に言えば、これらを最低限記述すればKubernetesクラスタでDaprを動かすことができるので、ハードルとしては低いと感じます。
アノテーションは他にも種類があり、Daprが使用する通信プロトコルなどを指定できます。設定できる項目は、下のDaprのドキュメントを参照してください。
https://docs.dapr.io/reference/arguments-annotations-overview/

# 全体構成
Hello Kubernetesで構築されるKubenetesクラスタは、下の図のような構成になっています。これから、図の構成要素をコマンドを使いながら確認していきたいと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2243249/22d8ca0c-1fd6-b319-c2ee-e988ec78a5b3.png)

# アプリケーションのポッド

個々のアプリケーションに対応して生成されるポッドを確認します。大きく分けて、nodeappポッドとpythonappポッドとredisポッド群の3種類が動作していることが分かります。

```
$ kubectl get pods
NAME                         READY   STATUS    RESTARTS       AGE
nodeapp-59d545f986-8tvbd     2/2     Running   14 (89m ago)   5d
pythonapp-79b69b7494-cvsgw   2/2     Running   13 (89m ago)   5d
redis-master-0               1/1     Running   5 (92m ago)    5d4h
redis-replicas-0             1/1     Running   7 (92m ago)    5d4h
redis-replicas-1             1/1     Running   7 (92m ago)    5d4h
redis-replicas-2             1/1     Running   7 (92m ago)    5d4h
```

KubernetesのマニフェストにDaprのアノテーションを追加すると、**daprd**という名前のコンテナがポッドに追加されます。このdaprdコンテナが、アプリケーションのサイドカーとして働き、daprの機能を提供します。
実際にnodeappポッドには、アプリケーションに対応するnodeコンテナとdaprdコンテナが含まれていることが分かります。

```
$ kubectl get pod nodeapp-59d545f986-8tvbd -o jsonpath="{.spec.containers[*].name}"
node daprd
```

Daprサイドカーに対応するサービスはClusterIP=Noneとなっており、ヘッドレスサービスとして実行されています。

```
$ kubectl get svc
NAME             TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                               AGE
kubernetes       ClusterIP      10.96.0.1       <none>        443/TCP                               9d
nodeapp          LoadBalancer   10.111.176.78   <pending>     80:30684/TCP                          9d
nodeapp-dapr     ClusterIP      None            <none>        80/TCP,50001/TCP,50002/TCP,9090/TCP   9d
pythonapp-dapr   ClusterIP      None            <none>        80/TCP,50001/TCP,50002/TCP,9090/TCP   9d
redis-headless   ClusterIP      None            <none>        6379/TCP                              9d
redis-master     ClusterIP      10.98.43.62     <none>        6379/TCP                              9d
redis-replicas   ClusterIP      10.97.209.171   <none>        6379/TCP
```

daprdコンテナに対しては、下のようにIPが割り当てられています。
```
$ kubectl run -it busybox --restart=Never --rm --image=busybox sh
/ # nslookup nodeapp-dapr
Server:		10.96.0.10
Address:	10.96.0.10:53

Name:	nodeapp-dapr.default.svc.cluster.local
Address: 172.17.0.2
```

# Daprのサービス

DaprをKubernetesに導入する設定をすると、Kubernetesクラスタに以下のサービスが追加されます。
- **Dapr Operator**：Daprコンポーネントの更新を管理
- **Dapr Sidecar Injector**：ポッドにDaprサイドカーを導入するサービス
- **Dapr Placement Server**：DaprのActor機能を利用する時のマップを作成するサービス
- **Dapr Sentry**：サービス間のmTLS通信を管理するサービス
- **Dapr Dashboard**：Dapr Dashboardを提供するサービス

Hello Kubernetesの環境がデプロイされているとき、上記のサービスが動作(HEALTHY=True)していることが分かります。

```
$ dapr status -k
  NAME                   NAMESPACE    HEALTHY  STATUS   REPLICAS  VERSION  AGE  CREATED              
  dapr-sentry            dapr-system  True     Running  1         1.6.0    6d   2022-03-26 11:42.45  
  dapr-dashboard         dapr-system  True     Running  1         0.9.0    6d   2022-03-26 11:42.45  
  dapr-sidecar-injector  dapr-system  True     Running  1         1.6.0    6d   2022-03-26 11:42.45  
  dapr-placement-server  dapr-system  True     Running  1         1.6.0    6d   2022-03-26 11:42.47  
  dapr-operator          dapr-system  True     Running  1         1.6.0    6d   2022-03-26 11:42.45
```

これらのサービスは、Kubernetesクラスタの**dapr-system名前空間**においてデプロイメントまたはステートフルセットとして動作しています(Dapr Placement Serverのみステートフルセット)。

```
$ kubectl get deploy --namespace dapr-system
NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
dapr-dashboard          1/1     1            1           8d
dapr-operator           1/1     1            1           8d
dapr-sentry             1/1     1            1           8d
dapr-sidecar-injector   1/1     1            1           8d
$ kubectl get sts --namespace dapr-system
NAME                    READY   AGE
dapr-placement-server   1/1     8d
```

それぞれのサービスに対応するポッドも、併せて動作していることが分かります。
```
$ kubectl get pods --namespace dapr-system
NAME                                     READY   STATUS    RESTARTS       AGE
dapr-dashboard-5b7dd7b657-w2stl          1/1     Running   7 (72m ago)    6d10h
dapr-operator-d78cf9fc7-7z44z            1/1     Running   13 (68m ago)   6d10h
dapr-placement-server-0                  1/1     Running   7 (72m ago)    6d10h
dapr-sentry-5874cb7d67-mhvcw             1/1     Running   11 (72m ago)   6d10h
dapr-sidecar-injector-6fb45cc48c-kxp8g   1/1     Running   11 (72m ago)   6d10h
```

# おわりに

KubernetesクラスタにDaprを導入するときの設定と動作を、Hello Kubernetesのクイックスタートを題材に確認してきました。Kubernetesのマニフェストにアノテーションを追加すれば、Daprの機能が利用できるようになるので、導入のハードルとしては低いかなと思います。
Daprに関しては継続的に記事を書いていきたいと思っています。これまでに書いた記事を下に載せていますので、参考になれば嬉しいです。
- [マイクロサービスを簡単に連携させるランタイム「Dapr」について](https://qiita.com/highitoh/items/8c1643fb5d6d7634a5f9)
- [Daprのクイックスタートでサービス呼出しのイメージを掴む](https://qiita.com/highitoh/items/7276ac138d09336dde15)

# 参考リンク

- GitHub - Dapr quickstarts Hello Kubernetes
https://github.com/dapr/quickstarts/tree/master/tutorials/hello-kubernetes
- Dapr Docs - Overview of Dapr on Kubernetes
https://docs.dapr.io/operations/hosting/kubernetes/kubernetes-overview/
- Dapr Docs - Deploy Dapr on a Kubernetes cluster
https://docs.dapr.io/operations/hosting/kubernetes/kubernetes-deploy/
- Dapr Docs - Dapr sidecar (daprd) overview
https://docs.dapr.io/concepts/dapr-services/sidecar/
- Dapr Docs - Dapr arguments and annotations for daprd, CLI, and Kubernetes
https://docs.dapr.io/reference/arguments-annotations-overview/
- minikube start
https://minikube.sigs.k8s.io/docs/start/