こんにちは Dapr Advent Calendar 17日目です。今日はもともと分散トレーシングの話を書くつもりだったのですが、その前に環境でトラブってしまったので、その辺りの経緯や対策などを書きたいと思います。
TL;DR
「私はminikubeをメモリ割り当て2GBで動かそうとしていました」
- Daprの環境が壊れた時は、
dapr unintall -k
minikube stop
Dockerの再起動minikube start
dapr init -k
という手順で復旧できる - minikubeはデフォルトで2CPU、2GBのメモリで環境を作るが、Javaアプリケーションを5〜6つくらい作成するだけでメモリが足りなくなる
minikube start
の--cpus
と--memory
オプションで、割り当てるリソースを指定ができる- ただし既に作成したminikubeはリソース割り当てを変更できないため、一度
minikube delete
してから再作成する必要がある
- ただし既に作成したminikubeはリソース割り当てを変更できないため、一度
docker container stats
でDockerのリソース状況を確認できるeval $(minikube docker-env)
とdocker container stats
でminikubeのリソース状況を確認できる
問題の経緯
問題が起きる前
数日前ですが、このAdvent Calendarの連載を書くために、ローカル環境のminikubeに色々とアプリケーションをデプロイしたり何だりしていたら、急にkubectlコマンドの反応が極端に遅くなったことがありました。その時はMacのCPU使用率が200%になっていて、2CPUを使いきって遅くなっていたため、「podが無限ループでもしたかなぁ?」などと思い、とりあえず kubectl delete -f k8s
で順番にpodを削除しようとしました。
ただpodの削除も途中で止まったので minikube stop
コマンドでk8sごと停止させ、改めて minikube start
コマンドで起動して、残ったpodなどを削除などしてから作業を続けていました。
その後は特に問題なくminikubeを使うことができたので、まぁそんなこともあるのかなと思い、あまり気にしていませんでした。
なぜかpodを4つ以上起動できない!
昨晩、またブログを書くためにminikube上にアプリケーションをデプロイしていたら、3つか4つ以上のアプリケーションをデプロイしたところで、なぜか「アプリケーションのpodのうち1つがランダムにERRORになる」という問題が起きました。kubectl describe pod
で詳細を見ると、Liveness ProbeとReadiness Probeが500エラーを返しているようです。
何かDapr関連のポートが被って通信エラーが起きているのか、サンプルのアプリケーションに問題があるのか、複数のServiceを起動しているのが問題なのか、などいくつか仮説を立て、とりあえず問題切り分けのためにHello WorldアプリケーションをServiceなしで5つほど起動してみたところ、1つは必ず同じエラーが起きるようになっていました。
Daprをダウングレードしてみようとしたものの
いま仕事でAmazon EKS上でDaprを使ってもっとたくさんのアプリケーションを運用しているので、ポートが被って通信エラーが起きるというのも、ちょっと考えにくい話です。ただ、いま運用はDapr 1.4系を使っているのですが、このブログはDapr 1.5を使って書いているので、1.5の問題かも知れないと思い、一度バージョンを落とそうと思いました。
dapr uninstall -k dapr install -k --runtime-version 1.4.4
これでバージョンがどうなったかなと思い、dapr status -k
コマンドを実行したところ、何かおかしい。
NAME NAMESPACE HEALTHY STATUS REPLICAS VERSION AGE CREATED dapr-placement-server dapr-system False Waiting (ContainerCreating) 1 1.5.1 5d 2021-12-11 21:08.30 dapr-sidecar-injector dapr-system False Waiting (ContainerCreating) 2 1.5.1 5d 2021-12-11 21:08.30 dapr-operator dapr-system False Terminated 2 1.5.1 5d 2021-12-11 21:08.30 dapr-dashboard dapr-system False Terminated 2 0.9.0 5d 2021-12-11 21:08.30 dapr-sentry dapr-system False Waiting (ContainerCreating) 2 1.4.4 7s 2021-12-16 23:15.34
1.4.4のコンテナを作れていないだけでなく、1.5.1のコンテナもまだ残っている、、というか作成途中で止まっていて、まともに動いていません。どうやらminikube上のDapr環境が壊れているようです。おそらく、冒頭に書いたCPU使用率が上がった時に、環境の一部が壊れてしまったのでしょう。
環境の再構築
これはもうDaprのバージョンの問題ではなく、Dapr環境が壊れているせいだと確信したので、環境を再構築することにしました。
dapr uninstall -k minikube stop
この後、Docker Desktopを再起動して、また環境を構築しました。
minikube start dapr init -k
そしてまたHello Worldアプリケーションを5つほどデプロイすると、今度は5つともきちんと起動できたので、問題解決。無事にトラブルシューティングが完了しました。さすが俺!
またCPU使用率が200%になる問題が発生
環境が治ったので、とりあえず全アプリケーションをデプロイすることにしました。
kubectl apply -f k8s
そして起動するのを待っていると、、、またkubectlの反応がなくなり、CPU使用率が200%になる問題が起きました。えぇぇ、なんで。。。
Javaエンジニアの経験と勘から、これはリソースが足りていなくてメモリ不足になってフルGCでも起きているのかなと思い、とりあえずDockerのリソース状況を確認することにしました。
docker container stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS cbe04e02f2d1 minikube 202.36% 1.894GiB / 1.94GiB 97.60% 691kB / 2.11MB 102GB / 168MB 1100
いやー、もう完全に足りてないですね。メモリの割り当て2GBを完全に使いきっています。そりゃ中のアプリケーションもフルGCを頻発するでしょうよ。そもそもメモリ2GBでminikubeを運用しようとするなんて無茶、誰がしたんだよ。。。まぁ僕なんですが。
そんなわけで、環境をすべて作り直すことにしました。
環境の再構築
そんなわけで、ここから環境の再構築手順を説明します。このブログを読んで手を動かしていた人は、この手順に従って環境を作り直してください。
minikubeの削除
minikubeはstartする際の引数でCPU数やメモリ割り当て量を変えることできるのですが、既に作成してあるminikubeに対して変更することはできないため、まずminikubeそのものを削除する必要があります。
次のコマンドで削除します。
minikube stop minikube delete
これでDaprのコンテナや、作成したイメージなどもすべて削除されます。
minikubeとDapr環境の再構築
続いて環境の再構築です。次のコマンドで構築します。
minikube start --cpus=4 --memory=4096
環境が構築できたら、念のためリソース状況を確認します。
docker container stats
メモリのLIMITが4GiBになっていることを確認してください。
続いて、Dapr環境の構築です。
dapr init -k
環境が構築できたら、念のためpodが正常に動いていることを確認します。
dapr status -k
5つのpodのHEALTYがTRUEになっていて、STATUSがRunningになっていればOKです。
イメージの再作成
これまでのブログで作ってきたアプリケーションのイメージは、minikubeをdeleteした際に一緒に削除されてしまったので、すべて作り直す必要があります。
eval $(minikube docker-env) cd (GitHubのディレクトリパス)/dapr-advent-2021 ./mvnw spring-boot:build-image
これですべてのアプリケーションのイメージが再作成されます。
ちなみに最後に親モジュールのイメージも作ろうとしてmavenビルドがエラーになりますが、その時点で子モジュールのイメージはすべて作成されているためヨシとします。
アプリケーションのデプロイ
イメージの作成が完了したら、アプリケーションをまとめてデプロイしてしまいましょう。
kubectl apply -f k8s
デプロイする順番など気にせず、一気にデプロイしても特に問題などは起きません。
念のため kubectl get pods
コマンドで、起動に成功していることを確認しておきましょう。
NAME READY STATUS RESTARTS AGE hello-app-fb644cd5d-j2z7b 2/2 Running 0 1m invoke-app-745b5f4bf6-2hf6l 2/2 Running 0 1m postgresql-deploy-658df4946-lm6gp 1/1 Running 0 1m publish-app-5b4c66c9-mhj67 2/2 Running 0 1m rabbitmq-5d474484f5-rhjzd 1/1 Running 0 1m state-app-849f6d6944-2mtr5 2/2 Running 0 1m subscribe-app-cdc58446-n82px 2/2 Running 0 1m
問題ありませんね。
minikubeのリソース確認
最後に、minikubeのリソースを確認しておきましょう。
新しいコンソールを開いて、docker container stats
コマンドを実行します。
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 079bf48016ec minikube 53.21% 2.339GiB / 4GiB 58.48% 1.56GB / 250MB 106MB / 9.87GB 1062
メモリは4GiB中、2.3GiBほど使っているようです。そりゃ2GBしか割り当ててなければ、メモリが足りなくて止まっちゃいますよね、、、
なお、minikube内部のpodごとのリソース状況は、次のコマンドで確認できます。
eval $(minikube docker-env) docker container stats
次のような結果が出るはずです。
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS bb2650777c7a k8s_daprd_state-app-849f6d6944-2mtr5_default_fa0cc253-ddab-4026-9328-fc3a29d2151e_0 0.14% 15.75MiB / 7.773GiB 0.20% 1.59MB / 1.51MB 0B / 0B 11 e51e7d17a744 k8s_daprd_publish-app-5b4c66c9-mhj67_default_9f1de14f-0498-4f12-ab17-931771d7f0b3_0 0.21% 15.68MiB / 7.773GiB 0.20% 1.59MB / 1.51MB 0B / 0B 12 b9c2c68edd1b k8s_daprd_hello-app-fb644cd5d-j2z7b_default_114f279b-313b-4763-b779-3a1128986b9e_0 0.09% 15.74MiB / 7.773GiB 0.20% 1.59MB / 1.5MB 8.19kB / 0B 12 3d7590c40e30 k8s_daprd_invoke-app-745b5f4bf6-2hf6l_default_852d6fd1-582d-44ea-b06f-cbaa95a7af2b_0 0.08% 15.69MiB / 7.773GiB 0.20% 1.59MB / 1.51MB 0B / 0B 12 52769d846edb k8s_subscribe_subscribe-app-cdc58446-n82px_default_b0d3ebfa-8a4f-4dec-ad6e-4296c9dfaa74_0 0.12% 172.4MiB / 7.773GiB 2.17% 1.59MB / 1.52MB 0B / 1.29MB 32 5daf791beb83 k8s_state_state-app-849f6d6944-2mtr5_default_fa0cc253-ddab-4026-9328-fc3a29d2151e_0 0.14% 164.7MiB / 7.773GiB 2.07% 1.59MB / 1.51MB 16.4kB / 1.32MB 32 9c162e211125 k8s_publish_publish-app-5b4c66c9-mhj67_default_9f1de14f-0498-4f12-ab17-931771d7f0b3_0 0.12% 180.6MiB / 7.773GiB 2.27% 1.59MB / 1.51MB 8.19kB / 1.3MB 32 4652afb3deef k8s_postgresql_postgresql-deploy-658df4946-lm6gp_default_f080e2f5-f9ec-41f3-a8b3-752b59445d8b_0 0.00% 52.89MiB / 7.773GiB 0.66% 12.5kB / 12kB 32.7MB / 55MB 12 39ba4e76702f k8s_POD_subscribe-app-cdc58446-n82px_default_b0d3ebfa-8a4f-4dec-ad6e-4296c9dfaa74_0 0.00% 212KiB / 7.773GiB 0.00% 1.59MB / 1.52MB 0B / 0B 1 6b06c40a04b6 k8s_POD_state-app-849f6d6944-2mtr5_default_fa0cc253-ddab-4026-9328-fc3a29d2151e_0 0.00% 208KiB / 7.773GiB 0.00% 1.59MB / 1.51MB 0B / 0B 1 2f3b07bc26e6 k8s_rabbitmq_rabbitmq-5d474484f5-rhjzd_default_f39f8fcd-47af-420a-aebd-d4dbf4385d8d_0 0.25% 126.4MiB / 7.773GiB 1.59% 2.5kB / 354B 33.8MB / 819kB 33 b2bc5b2bcd5c k8s_POD_publish-app-5b4c66c9-mhj67_default_9f1de14f-0498-4f12-ab17-931771d7f0b3_0 0.00% 208KiB / 7.773GiB 0.00% 1.59MB / 1.51MB 0B / 0B 1 78778711254e k8s_POD_rabbitmq-5d474484f5-rhjzd_default_f39f8fcd-47af-420a-aebd-d4dbf4385d8d_0 0.00% 208KiB / 7.773GiB 0.00% 2.5kB / 354B 0B / 0B 1 90754eca8f01 k8s_hello_hello-app-fb644cd5d-j2z7b_default_114f279b-313b-4763-b779-3a1128986b9e_0 0.20% 194.5MiB / 7.773GiB 2.44% 1.59MB / 1.5MB 0B / 1.56MB 32 0ccbd01ea780 k8s_POD_postgresql-deploy-658df4946-lm6gp_default_f080e2f5-f9ec-41f3-a8b3-752b59445d8b_0 0.00% 204KiB / 7.773GiB 0.00% 12.5kB / 12kB 0B / 0B 1 986d6f27779d k8s_invoke_invoke-app-745b5f4bf6-2hf6l_default_852d6fd1-582d-44ea-b06f-cbaa95a7af2b_0 0.11% 179.7MiB / 7.773GiB 2.26% 1.59MB / 1.51MB 143kB / 1.64MB 32 0361dd7cf5bb k8s_POD_hello-app-fb644cd5d-j2z7b_default_114f279b-313b-4763-b779-3a1128986b9e_0 0.00% 208KiB / 7.773GiB 0.00% 1.59MB / 1.5MB 0B / 0B 1 1f374ad3ef7c k8s_POD_invoke-app-745b5f4bf6-2hf6l_default_852d6fd1-582d-44ea-b06f-cbaa95a7af2b_0 0.00% 204KiB / 7.773GiB 0.00% 1.59MB / 1.51MB 0B / 0B 1 6d1ef557c15a k8s_dapr-placement-server_dapr-placement-server-0_dapr-system_677cb5fd-ae57-41eb-918c-58d42e6c7652_0 0.33% 7.207MiB / 7.773GiB 0.09% 6.06MB / 6.09MB 0B / 0B 11 23acf6a45fe2 k8s_dapr-operator_dapr-operator-5b4b68b5c5-mptxp_dapr-system_c9d399ef-c82c-4781-9ae4-624a6933abc5_0 0.17% 18.25MiB / 7.773GiB 0.23% 27.1MB / 14.1MB 0B / 0B 13 9ff28f354a81 k8s_dapr-sidecar-injector_dapr-sidecar-injector-6f749dbf87-9vn96_dapr-system_0ab8e63d-8073-411c-9c87-d9abd03083b7_0 0.11% 8.184MiB / 7.773GiB 0.10% 1.55MB / 1.37MB 0B / 0B 12 116fb67e12ec k8s_dapr-sentry_dapr-sentry-c6b746cdf-hp2n9_dapr-system_e30b08ca-9060-4853-8c26-a37351e41c26_0 0.06% 7.883MiB / 7.773GiB 0.10% 1.53MB / 1.39MB 0B / 0B 14 9ef9efefb9c2 k8s_dapr-dashboard_dapr-dashboard-57b4db56fc-pr62l_dapr-system_4ba3a32e-afe9-4c7e-a8c2-ba2ac4745da9_0 0.00% 5.734MiB / 7.773GiB 0.07% 2.89kB / 0B 0B / 0B 8 9bc3f4edc295 k8s_POD_dapr-placement-server-0_dapr-system_677cb5fd-ae57-41eb-918c-58d42e6c7652_0 0.00% 200KiB / 7.773GiB 0.00% 6.06MB / 6.09MB 0B / 0B 1 db607d3df442 k8s_POD_dapr-sidecar-injector-6f749dbf87-9vn96_dapr-system_0ab8e63d-8073-411c-9c87-d9abd03083b7_0 0.00% 204KiB / 7.773GiB 0.00% 1.55MB / 1.37MB 0B / 0B 1 2f2426091427 k8s_POD_dapr-operator-5b4b68b5c5-mptxp_dapr-system_c9d399ef-c82c-4781-9ae4-624a6933abc5_0 0.00% 208KiB / 7.773GiB 0.00% 27.1MB / 14.1MB 0B / 0B 1 351e4b9d4e76 k8s_POD_dapr-sentry-c6b746cdf-hp2n9_dapr-system_e30b08ca-9060-4853-8c26-a37351e41c26_0 0.00% 204KiB / 7.773GiB 0.00% 1.53MB / 1.39MB 0B / 0B 1 292b25653234 k8s_POD_dapr-dashboard-57b4db56fc-pr62l_dapr-system_4ba3a32e-afe9-4c7e-a8c2-ba2ac4745da9_0 0.00% 204KiB / 7.773GiB 0.00% 2.89kB / 0B 0B / 0B 1 da405d04f18f k8s_storage-provisioner_storage-provisioner_kube-system_3526d87b-7f1f-4e57-a5c4-6a9f054e7ec2_1 0.05% 9.297MiB / 7.773GiB 0.12% 0B / 0B 0B / 0B 8 4d7fe3d17eb4 k8s_coredns_coredns-558bd4d5db-t4gxq_kube-system_ec6ebffa-abce-45b9-9978-b3349311791f_0 0.36% 11.11MiB / 170MiB 6.53% 2.23MB / 719kB 0B / 0B 12 7e4d83af4783 k8s_kube-proxy_kube-proxy-tmzwt_kube-system_29295269-e286-48b4-84e0-eb2583132419_0 0.02% 12.56MiB / 7.773GiB 0.16% 0B / 0B 0B / 16.4kB 10 52cab24b1823 k8s_POD_coredns-558bd4d5db-t4gxq_kube-system_ec6ebffa-abce-45b9-9978-b3349311791f_0 0.00% 204KiB / 7.773GiB 0.00% 2.23MB / 719kB 0B / 0B 1 1ec5d319864e k8s_POD_kube-proxy-tmzwt_kube-system_29295269-e286-48b4-84e0-eb2583132419_0 0.00% 280KiB / 7.773GiB 0.00% 0B / 0B 0B / 0B 1 23e447125876 k8s_POD_storage-provisioner_kube-system_3526d87b-7f1f-4e57-a5c4-6a9f054e7ec2_0 0.00% 148KiB / 7.773GiB 0.00% 0B / 0B 0B / 0B 1 d0b6da913375 k8s_etcd_etcd-minikube_kube-system_be5cbc7ffcadbd4ffc776526843ee514_0 1.65% 39.15MiB / 7.773GiB 0.49% 0B / 0B 0B / 235MB 19 094635d3e682 k8s_kube-apiserver_kube-apiserver-minikube_kube-system_cefbe66f503bf010430ec3521cf31be8_0 3.95% 314.8MiB / 7.773GiB 3.96% 0B / 0B 0B / 0B 12 4c8cac060a66 k8s_kube-scheduler_kube-scheduler-minikube_kube-system_a2acd1bccd50fd7790183537181f658e_0 0.20% 16.75MiB / 7.773GiB 0.21% 0B / 0B 0B / 0B 11 a638324aa7b6 k8s_kube-controller-manager_kube-controller-manager-minikube_kube-system_a5754fbaabd2854e0e0cdce8400679ea_0 1.61% 48.86MiB / 7.773GiB 0.61% 0B / 0B 0B / 0B 10 a21fdf45e9ab k8s_POD_etcd-minikube_kube-system_be5cbc7ffcadbd4ffc776526843ee514_0 0.00% 144KiB / 7.773GiB 0.00% 0B / 0B 0B / 0B 1 4983ebfc71a4 k8s_POD_kube-scheduler-minikube_kube-system_a2acd1bccd50fd7790183537181f658e_0 0.00% 144KiB / 7.773GiB 0.00% 0B / 0B 0B / 0B 1 ffa6824f6939 k8s_POD_kube-controller-manager-minikube_kube-system_a5754fbaabd2854e0e0cdce8400679ea_0 0.00% 140KiB / 7.773GiB 0.00% 0B / 0B 0B / 0B 1 6e78a62d73d0 k8s_POD_kube-apiserver-minikube_kube-system_cefbe66f503bf010430ec3521cf31be8_0 0.00% 140KiB / 7.773GiB 0.00% 0B / 0B 0B / 0B 1 19977ecb1ab2 k8s_daprd_subscribe-app-cdc58446-n82px_default_b0d3ebfa-8a4f-4dec-ad6e-4296c9dfaa74_0 0.21% 15.47MiB / 7.773GiB 0.19% 1.59MB / 1.52MB 0B / 0B 12
何やよく分かりませんけど、わりとたくさんpodが動いてるんですね(今さら)
JVM系のpodは、たとえばこんな感じです。
90754eca8f01 k8s_hello_hello-app-fb644cd5d-j2z7b_default_114f279b-313b-4763-b779-3a1128986b9e_0 0.20% 194.5MiB / 7.773GiB 2.44% 1.59MB / 1.5MB 0B / 1.56MB 32
アプリケーション1つで200MiBほどメモリを使うのですから、そりゃ5つも6つも立ち上げれば2GBでは足りませんね。
そんなわけで、無事に環境を作り直すことができました。
ドキュメントはちゃんと読もうね
ちなみにDaprのminikube環境構築のドキュメントを見ると、、、
minikube startのコマンドは、このようになっています。
minikube start --cpus=4 --memory=4096
ドキュメントで、メモリ4GiBにしろって書いてあるんですから、それをきちんと守れって話ですよね・・・。
いや、別にオプションなしで実行しても問題ないんだったら、それに越したことはないのかなって、、、(言い訳)
まとめ
ということで今回のまとめです。
- Daprの環境が壊れた時は、
dapr unintall -k
minikube stop
Dockerの再起動minikube start
dapr init -k
という手順で復旧できる - minikubeはデフォルトで2CPU、2GBのメモリで環境を作るが、Javaアプリケーションを5〜6つくらい作成するだけでメモリが足りなくなる
minikube start
の--cpus
と--memory
オプションで、割り当てるリソースを指定ができる- ただし既に作成したminikubeはリソース割り当てを変更できないため、一度
minikube delete
してから再作成する必要がある
- ただし既に作成したminikubeはリソース割り当てを変更できないため、一度
docker container stats
でDockerのリソース状況を確認できるeval $(minikube docker-env)
とdocker container stats
でminikubeのリソース状況を確認できる
いやぁ、こういうことを経験して、使いこなしレベルって上がっていくもんですよね!
それでは、また明日!