Dapr Tutorials - Hello World Kubernetes をやってみた
Dapr入門 です。
今回は、前回構築したアプリケーションをminikubeにデプロイします。
環境
WSL2 Ubuntu 22.04
minikube 1.32.0
dapr 1.12.0
Helm v3
構成
公式より拝借しました。
手順としては2種類あるようで、dapr コマンドで一括ドカーンと作るパターンと kubectl で粛々と作っていくパターンがあるようです。
では、dapr コマンドで作るパターンから始めていきます。
Using Dapr Multi-app run with Dapr dev mode deployment
Prerequisites
使用するソースコードを git からクローンします。
$ git clone https://github.com/dapr/quickstarts.git
$ cd quickstarts/tutorials/hello-kubernetes
minikube は起動させておきます。(私は忘れてdaprインストールできなくてうんうんしてました笑)
$ minikube start
Step 1 - Setup Dapr dev mode on your Kubernetes cluster
minikube に Dapr をデプロイします。
$ dapr init -k --dev
⌛ Making the jump to hyperspace...
ℹ️ Note: To install Dapr using Helm, see here: https://docs.dapr.io/getting-started/install-dapr-kubernetes/#install-with-helm-advanced
ℹ️ Container images will be pulled from Docker Hub
✅ Deploying the Dapr control plane with latest version to your cluster...
✅ Deploying the Dapr dashboard with latest version to your cluster...
✅ Deploying the Dapr Redis with latest version to your cluster...
✅ Deploying the Dapr Zipkin with latest version to your cluster...
ℹ️ Applying "statestore" component to Kubernetes "default" namespace.
ℹ️ Applying "pubsub" component to Kubernetes "default" namespace.
ℹ️ Applying "appconfig" zipkin configuration to Kubernetes "default" namespace.
✅ Success! Dapr has been installed to namespace dapr-system. To verify, run `dapr status -k' in your terminal. To get started, go here: https://aka.ms/dapr-getting-started
Step 2 - Run the Multi-app run template to deploy both the Node.js and Python apps
Node.js と Python アプリの両方を実行します。
$ dapr run -k -f dapr.yaml
ℹ️ This is a preview feature and subject to change in future releases.
ℹ️ Validating config and starting app "nodeapp"
ℹ️ Deploying app "nodeapp" to Kubernetes
ℹ️ Deploying service YAML "/home/user/GitHub/dapr/quickstarts/tutorials/hello-kubernetes/node/.dapr/deploy/service.yaml" to Kubernetes
ℹ️ Deploying deployment YAML "/home/user/GitHub/dapr/quickstarts/tutorials/hello-kubernetes/node/.dapr/deploy/deployment.yaml" to Kubernetes
ℹ️ Streaming logs for containers in pod "nodeapp-6998f8844b-xhczb"
ℹ️ Writing log files to directory : /home/user/GitHub/dapr/quickstarts/tutorials/hello-kubernetes/node/.dapr/logs
ℹ️ Validating config and starting app "pythonapp"
ℹ️ Deploying app "pythonapp" to Kubernetes
ℹ️ Deploying deployment YAML "/home/user/GitHub/dapr/quickstarts/tutorials/hello-kubernetes/python/.dapr/deploy/deployment.yaml" to Kubernetes
== APP - nodeapp == Node App listening on port 3000!
ℹ️ Streaming logs for containers in pod "pythonapp-56675c86ff-q9vqq"
ℹ️ Writing log files to directory : /home/user/GitHub/dapr/quickstarts/tutorials/hello-kubernetes/python/.dapr/logs
ℹ️ Starting to monitor Kubernetes pods for deletion.
== APP - nodeapp == Got a new order! Order ID: 3
== APP - nodeapp == Successfully persisted state for Order ID: 3
== APP - nodeapp == Got a new order! Order ID: 4
== APP - nodeapp == Successfully persisted state for Order ID: 4
アプリを終了する場合は以下のコマンドか、Ctrl+C で止めます。
(止まるのに少し時間がかかります)
$ dapr stop -k -f dapr.yaml
Using the kubectl CLI
上記は、dapr コマンドで一括にデプロイする方法でした。
ここからはいつも通り kubectl を使ったやり方で、デプロイをしていきます。
Step 1 - Setup Dapr on your Kubernetes cluster
$ dapr init --kubernetes --wait
⌛ Making the jump to hyperspace...
ℹ️ Note: To install Dapr using Helm, see here: https://docs.dapr.io/getting-started/install-dapr-kubernetes/#install-with-helm-advanced
ℹ️ Container images will be pulled from Docker Hub
✅ Deploying the Dapr control plane with latest version to your cluster...
✅ Deploying the Dapr dashboard with latest version to your cluster...
✅ Success! Dapr has been installed to namespace dapr-system. To verify, run `dapr status -k' in your terminal. To get started, go here: https://aka.ms/dapr-getting-started
dapr のコントロールブレーンが完全にデプロイされているかは、以下のコマンドで確認できます。
全て Running になっていればOK。
$ dapr status -k
NAME NAMESPACE HEALTHY STATUS REPLICAS VERSION AGE CREATED
dapr-dashboard dapr-system True Running 1 0.14.0 5m 2023-11-30 10:52.38
dapr-sidecar-injector dapr-system True Running 1 1.12.2 5m 2023-11-30 10:52.27
dapr-operator dapr-system True Running 1 1.12.2 5m 2023-11-30 10:52.27
dapr-sentry dapr-system True Running 1 1.12.2 5m 2023-11-30 10:52.27
dapr-placement-server dapr-system True Running 1 1.12.2 5m 2023-11-30 10:52.27
Step 2 - Create and configure a state store
状態ストアは Redis、CosmosDB、DynamoDB、Cassandra などいろいろ使えるようです。
ここではRedisを使います。
- まずは Redis を minikibe にインストールします。helmを使います。
https://docs.dapr.io/getting-started/tutorials/configure-state-pubsub/#step-1-create-a-redis-store
$ helm repo add bitnami https://charts.bitnami.com/bitnami
"bitnami" has been added to your repositories
$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "argo" chart repository
...Successfully got an update from the "bitnami" chart repository
Update Complete. ⎈Happy Helming!⎈
$ helm install redis bitnami/redis --set image.tag=6.2
NAME: redis
LAST DEPLOYED: Thu Nov 30 11:02:30 2023
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: redis
CHART VERSION: 18.4.0
APP VERSION: 7.2.3
** Please be patient while the chart is being deployed **
Redis® can be accessed on the following DNS names from within your cluster:
redis-master.default.svc.cluster.local for read/write operations (port 6379)
redis-replicas.default.svc.cluster.local for read-only operations (port 6379)
To get your password run:
export REDIS_PASSWORD=$(kubectl get secret --namespace default redis -o jsonpath="{.data.redis-password}" | base64 -d)
To connect to your Redis® server:
1. Run a Redis® pod that you can use as a client:
kubectl run --namespace default redis-client --restart='Never' --env REDIS_PASSWORD=$REDIS_PASSWORD --image docker.io/bitnami/redis:6.2 --command -- sleep infinity
Use the following command to attach to the pod:
kubectl exec --tty -i redis-client \
--namespace default -- bash
2. Connect using the Redis® CLI:
REDISCLI_AUTH="$REDIS_PASSWORD" redis-cli -h redis-master
REDISCLI_AUTH="$REDIS_PASSWORD" redis-cli -h redis-replicas
To connect to your database from outside the cluster execute the following commands:
kubectl port-forward --namespace default svc/redis-master 6379:6379 &
REDISCLI_AUTH="$REDIS_PASSWORD" redis-cli -h 127.0.0.1 -p 6379
WARNING: Rolling tag detected (bitnami/redis:6.2), please note that it is strongly recommended to avoid using rolling tags in a production environment.
+info https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/
Redis のコンテナが起動したか確認します。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
redis-master-0 1/1 Running 0 19s
redis-replicas-0 1/1 Running 0 19s
redis-replicas-1 1/1 Running 0 19s
redis-replicas-2 1/1 Running 0 18s
- ディレクトリのファイルにキーを追加します。
These settings will work out of the box if you use
helm install bitnami/redis
.
とあるので、今回はそのままで動くようです。
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: statestore
spec:
type: state.redis
version: v1
metadata:
# These settings will work out of the box if you use `helm install
# bitnami/redis`. If you have your own setup, replace
# `redis-master:6379` with your own Redis master address, and the
# Redis password with your own Secret's name. For more information,
# see https://docs.dapr.io/operations/components/component-secrets .
- name: redisHost
value: redis-master:6379
- name: redisPassword
secretKeyRef:
name: redis
key: redis-password
auth:
secretStore: kubernetes
The secret,
redis
, is created automatically
シークレットは redis
という名前で自動作成してくれるようなので、そのままにします。
- ファイルを適用します。
$ kubectl apply -f ./deploy/redis.yaml
component.dapr.io/statestore configured
Step 3 - Deploy the Node.js app with the Dapr sidecar
Dapr サイドカーを使用して Node.js アプリをデプロイします。
$ kubectl apply -f ./deploy/node.yaml
service/nodeapp created
deployment.apps/nodeapp created
デプロイが完了したかどうか確認します。
$ kubectl rollout status deploy/nodeapp
deployment "nodeapp" successfully rolled out
よさそう。
このタイミングで自動的に dapr サイドカーも一緒にデプロイされているようです。
ちょっと見てみます。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nodeapp-6b65576f5-br4h4 2/2 Running 0 2m12s
redis-master-0 1/1 Running 0 19m
redis-replicas-0 1/1 Running 0 19m
redis-replicas-1 1/1 Running 0 19m
redis-replicas-2 1/1 Running 0 18m
$ kubectl describe pod nodeapp-6b65576f5-br4h4
### 省略
Containers:
node:
Container ID: docker://d9a6035ef5391daabe7709cb43212c8dbb7a207dd87a9478b2da88bd92590da4
Image: ghcr.io/dapr/samples/hello-k8s-node:latest
Image ID: docker-pullable://ghcr.io/dapr/samples/hello-k8s-node@sha256:0f51eef9148fc5f7cada346af20667216e3e6cbde372fa197524cd2946f83ebb
Port: 3000/TCP
Host Port: 0/TCP
State: Running
Started: Thu, 30 Nov 2023 11:20:17 +0900
Ready: True
Restart Count: 0
Environment:
APP_PORT: 3000
DAPR_HTTP_PORT: 3500
DAPR_GRPC_PORT: 50001
APP_PROTOCOL: http
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-pzjrw (ro)
daprd:
Container ID: docker://efbcd6ef558c2dc8d6dc58470dd6af8e0b377c0a87b6917ae5ca7dde33ac2aa8
Image: docker.io/daprio/daprd:1.12.2
Image ID: docker-pullable://daprio/daprd@sha256:c9117a6131c3df620fef01a423dcb141b3c3202bf7f15a6eca7c347ae436f525
Ports: 3500/TCP, 50001/TCP, 50002/TCP, 9090/TCP
Host Ports: 0/TCP, 0/TCP, 0/TCP, 0/TCP
### 省略
おーいますねぇ daprd コンテナ。
仕組みとしては annotations をつけるだけで良いみたいです。
annotations:
dapr.io/enabled: "true"
dapr.io/app-id: "nodeapp"
dapr.io/app-port: "3000"
dapr.io/enable-api-logging: "true"
Node.js アプリが起動したので、8080をポートフォワードしてサービスを利用できるようにします。
$ kubectl port-forward service/nodeapp 8080:80
Forwarding from 127.0.0.1:8080 -> 3000
Forwarding from [::1]:8080 -> 3000
Step 4 - Verify Service
ポートフォワードしたサービスを以下のコマンドで確認します。
$ curl http://localhost:8080/ports
{"DAPR_HTTP_PORT":"3500","DAPR_GRPC_PORT":"50001"}
Node.js アプリに注文のリクエストを投げます。
$ curl --request POST --data "@sample.json" --header Content-Type:application/json http://localhost:8080/neworder
注文が永続化されたことを確認します。
$ curl http://localhost:8080/order
{"orderId":"42"}
うまくいきました。
Step 5 - Deploy the Python app with the Dapr sidecar
次はPythonアプリをデプロイします。
Python アプリは localhost:3500 に Postを1秒ごとに投げる子です。
3500 は dapr のデフォルト HTTPポートなので、 dapr runtime は受け流して nodepp に流す、ということをしてるらしいです。
url 的には v1.0/invoke/nodeapp/method/neworder
に展開されるみたいですけど、アプリが複数あったらどこに行くかわからないのでは?と思いきや、HTTPヘッダでちゃんと宛先のアプリが指定されてました。
response = requests.post(dapr_url, json=message, timeout=5, headers = {"dapr-app-id": "nodeapp"} )
というわけで、デプロイします。
$ kubectl apply -f ./deploy/python.yaml
deployment.apps/pythonapp created
デプロイも確認して。
$ kubectl rollout status deploy/pythonapp
deployment "pythonapp" successfully rolled out
Step 6 - Observe messages
Node.js のアプリの監視ログを確認します。
うまくいくとこのようなログが出るとか。
$ kubectl logs --selector=app=node -c node --tail=-1
Node App listening on port 3000!
DAPR_HTTP_PORT: 3500
DAPR_GRPC_PORT: 50001
Got a new order! Order ID: 42
Successfully persisted state for Order ID: 42
Got a new order! Order ID: 2
Successfully persisted state for Order ID: 2
Got a new order! Order ID: 3
Successfully persisted state for Order ID: 3
Got a new order! Order ID: 4
Successfully persisted state for Order ID: 4
Step 7 - Observe API call logs
API 呼び出しログも見てみます。
まずはNode.js 側から。
$ kubectl logs --selector=app=node -c daprd --tail=-1
###
time="2023-11-30T06:57:20.841375634Z" level=info msg="HTTP API Called" app_id=nodeapp instance=nodeapp-6b65576f5-79zp5 method="POST /v1.0/state/statestore" scope=dapr.runtime.http-info type=log useragent="node-fetch/1.0 (+https://github.com/bitinn/node-fetch)" ver=1.12.2
time="2023-11-30T06:57:21.848303956Z" level=info msg="HTTP API Called" app_id=nodeapp instance=nodeapp-6b65576f5-79zp5 method="POST /v1.0/state/statestore" scope=dapr.runtime.http-info type=log useragent="node-fetch/1.0 (+https://github.com/bitinn/node-fetch)" ver=1.12.2
healthz のリクエストばっかりで見つけるのつらいですがいました。
次は Python 側。
$ kubectl logs --selector=app=python -c daprd --tail=-1
###
time="2023-11-30T07:00:19.975003722Z" level=info msg="HTTP API Called" app_id=pythonapp instance=pythonapp-974db9877-7xwkt method="POST /neworder" scope=dapr.runtime.http-info type=log useragent=python-requests/2.31.0 ver=1.12.2
time="2023-11-30T07:00:20.980843313Z" level=info msg="HTTP API Called" app_id=pythonapp instance=pythonapp-974db9877-7xwkt method="POST /neworder" scope=dapr.runtime.http-info type=log useragent=python-requests/2.31.0 ver=1.12.2
Step 8 - Confirm successful persistence
Node.js の order エンドポイントを呼び出して、最新の注文を取得します。
$ curl http://localhost:8080/order
{"orderId":469}
増えてるのでよし👌
Step 9 - Cleanup
最後にお掃除です。
$ kubectl delete -f deploy/
service "nodeapp" deleted
deployment.apps "nodeapp" deleted
deployment.apps "pythonapp" deleted
component.dapr.io "statestore" deleted
おわりに
なんかstoreの設定の更新がうまくいかなくて、時間を溶かしたりしましたが、結果少しは慣れてきたのでよしとします😉
次はPub/Subのチュートリアルかな。
それでは。
Discussion