Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

再度サンプルソースのフィードバックお願いします。 #4

Open
ryom0624 opened this issue Jun 20, 2019 · 14 comments
Open
Assignees

Comments

@ryom0624
Copy link
Contributor

@ryutah

ローリングアップデートの件ありがとうございました。
サンプルの方に strategy3 の記述して更新しているので、一旦プルリクの方はクローズさせていただきます。

続いての回答依頼をさせていただきます。
現状残り必要な部分としては、

- 現状のsampleソースにおける、sample-k8s/k8s/gkeのyamlファイルやdeploy.shの疑問点、問題点のあぶり出し
- 負荷検証とスケールに関する戦略?(HPAとかresources.requestsとかを含めた)
- 管理構成ツールの設定

このあたりかなと思っていますが、
現状の課題をあぶり出すことが現時点では一番実施したいこととなります。
自分たちの知見の中でなんとかたどり着いておりますが、
これで正しいのか、プロから見て、???な箇所の記述はないのか?
というところが気になっております。
お時間使って頂いて構いませんので
もう一度サンプルのソースをじっくりと見ていただいて、ご指摘いただくことは可能でしょうか?
もし上記以外に特に問題がなければそれはそれで一言いただきたい次第です。

一応HPAとかrequestsとかの記述もしていますが、実際の負荷を検証していない根拠のない数字なのでじっくり見ていただいた後に改めて検証方法とかのご回答の依頼をさせていただこうと思っております。

よろしくお願い致します。

@ryutah
Copy link

ryutah commented Jun 24, 2019

HPAについて

とりあえず、オートスケールできるように設定を追加してみたような感じですかねー。
この設定もとてもむずかしいので、一概に「こうしたほうがいい!」と言いづらい設定でして、実際に負荷をかけて検証が必要になってくるのかなと思います 😅

また、ご存知かもですがk8sのスケールには PodのスケールNodeのスケール があり、Podに比べてNodeの方はスケールに時間がかかってしまうため、以前お話にあったバースト系の負荷増加に対応にはさらに考慮が必要ですねー。

これは僕の個人的な意見なのですが、基本的にはk8sのスケールアウトはおまけ程度で考えておいて、最初から想定される負荷(今回で言うと分間数百アクセスでしたっけ?)が耐えられる構成にしておくのが良いかもです。。。!

deploy.shのJobの完了待ち処理

while [ true ]; do
phase=`kubectl get pods --selector="name=deploy-task" -o 'jsonpath={.items[0].status.phase}' || 'false'`
if [[ "$phase" != 'Pending' ]]; then
echo -e "\njob podがpending状態を抜けたのでループを抜けます。"
break
fi
kubectl get pods --selector=name=deploy-task -o 'jsonpath={.items[0].status.phase}'
sleep 1s
done
echo "jobがsucceededかfailedになるまで状態を取得してループします。"
# Jobの終了状態を取得します
while [ true ]; do
succeeded=`kubectl get jobs setup -o 'jsonpath={.status.succeeded}'`
failed=`kubectl get jobs setup -o 'jsonpath={.status.failed}'`
if [[ "$succeeded" == "1" ]]; then
echo -e "\njobが成功したので終了します。"
break
elif [[ "$failed" -gt "0" ]]; then
kubectl describe job setup
kubectl logs $(kubectl get pods --selector="name=deploy-task" -o 'jsonpath={.items[0].metadata.name}')
kubectl delete job setup
echo 'マイグレートに失敗!'
exit 1
fi
kubectl get pods --selector=name=deploy-task -o 'jsonpath={.items[0].status.phase}'

僕も実際にプロダクトとしては使ったことが無いのですが、1.11から kubectl wait が追加されてますので、そちらを使うともっとスッキリ書けると思います ✋

refs: https://stackoverflow.com/questions/44686568/tell-when-job-is-complete

Podのレプリカ数

replicas: 2

minReplicas: 1
maxReplicas: 5

こんな感じで、Deploymentで指定しているレプリカ数をHPAで指定している最低レプリカ数が違う風に設定てしたことが無いので、どんな挙動をするかイメージ湧いて無いんですけど、こんな感じで設定するとデプロイ直後は2Pod立ち上がって、その後場合によってはPod1までダウンスケールする感じなんです?? 🤔

Deploymentで指定しているレプリカ数を下回らないようにPodがスケジュールされるとので、1Podまでダウンスケールせずに実質2Podが最低Pod数になるのかな?と思ったんですが、HPA設定のほうが優先されるんですかね?

Containerのresourceについて

どういうふうに計測して割当を行ったのかわからないので、もしかしたらこれが適正って可能性もあるのですが全体的に割当量が少ない気がしましたー 🙌

知ってるかもですが、 resources.requests だけ指定して resources.limits を指定しない場合、 requests.requests の値がlimitとして扱われるため、この設定だと結構CPU使用率かつかつ何じゃないかなーと。

Cloud SQL Proxy

resources:
requests:
cpu: 50m

Deprecateになっているリポジトリなので本当に参考値なのですが、↓のhelmチャートだとデフォルトのリソース割り当てが

Parameter Description Default
resources CPU/Memory resource requests/limit Memory: 100/150Mi, CPU: 100/150m

https://github.com/helm/charts/tree/master/stable/gcloud-sqlproxy

となってますので、とりあえず同じ程度か、DBアクセスが多い場合は少し多めにlimitを取っても良いかもです 👍

nginx, rails

sample-k8s/k8s/gke/web.yaml

Lines 119 to 121 in d09b58a

resources:
requests:
cpu: 100m

sample-k8s/k8s/gke/web.yaml

Lines 142 to 144 in d09b58a

resources:
requests:
cpu: 50m

メインの処理をやらせるコンテナなので、もう少し割り当てて挙げて良いような気がするんですけど、大丈夫です?? 🤔
使用率などの計測方法は

  • resources指定無し� && Pod数1で固定してデプロイしてみて適当に負荷をかけてみて、どの程度リソース使ってるかを確認する
  • コンテナを単体で実行してみて負荷をかけ、 docekr stats などを使って使用率を見る

などがあると思います!

各コンテナのpreStopについて

Cloud SQL Proxy

lifecycle:

sample-k8s/k8s/gke/web.yaml

Lines 129 to 132 in d09b58a

lifecycle:
preStop:
exec:
command: ["sh", "-c", "sleep 25; /usr/sbin/nginx -s quit"]

sample-k8s/k8s/gke/web.yaml

Lines 157 to 160 in d09b58a

lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 25; kill -QUIT `(cat tmp/pids/puma.pid)`"]

停止シグナル送ってるだけなら、わざわざpreStopを定義してあげる必要は無いような?
preStop自体は、コンテナ終了時に特別にやらせたいような処理を記述するところなので、消しちゃっても特に問題ないんじゃないですかねー。

@KeiichiHonma
Copy link

@ryutah

これは僕の個人的な意見なのですが、基本的にはk8sのスケールアウトはおまけ程度で考えておいて

ここもう少し聞きたいと思いました。
トップゲートさんは運用で他社様の大規模運用のお手伝いしているとお聞きしましたが、
高負荷の対策としてどういった方法で現実的には対応しているのでしょうか?

@KeiichiHonma
Copy link

@ryutah

現状のsampleソースにおける、sample-k8s/k8s/gkeのyamlファイルやdeploy.shの疑問点、問題点のあぶり出し

ここの部分をまずは重要視しておりますが、
あまりご回答もらえていない認識です。

負荷系の回答がメインとなっており、状況を聞きたいと思っています。

負荷系は今後実行していく予定ではあるのですが、
まずは現在設定しているyamlファイル等の設定ファイルが正しく記述されているのか?
足りない設定はどこかないのか?などをまずは知りたいです

@ryom0624
Copy link
Contributor Author

@ryutah
ありがとうございます!

この設定もとてもむずかしいので、一概に「こうしたほうがいい!」と言いづらい設定でして、実際に負荷をかけて検証が必要になってくるのかなと思います 😅

まさにHPA / resources.requests(limits) に関しては負荷をかけながら実際に見ていくしか適切な値は得られないと思ったので、現状はとりあえずの意味のない数値となっています。
今後また回答依頼として検証方法などお伺いします。
検証前の初期値として適切でなければrequestsとlimitに関してはもう少し高めでとりあえずの設定はしておきます。

replicasとminReplicasは特に考えずだったので、普通はminより下に設定しないということであればそうします!
一応ですが、自分の手元ではminReplicasが優先されて1になってたと思います!


1.11から kubectl wait が追加されてますので、そちらを使うともっとスッキリ書けると思います

ありがとうございます!知らなかったので確認してみます!


停止シグナル送ってるだけなら、わざわざpreStopを定義してあげる必要は無いような?
preStop自体は、コンテナ終了時に特別にやらせたいような処理を記述するところなので、消しちゃっても特に問題ないんじゃないですかねー。

https://qiita.com/superbrothers/items/3ac78daba3560ea406b2

停止シグナルというよりsleepが大事(25秒は長すぎるのは承知です)だと思ってまして、、、
少し古いqiitaの記事ではありますが、ローリングアップデートの際にpodがterminatedになったタイミングでserviceがエンドポイントの削除するタイミングとpodが停止するタイミングが非同期なのでsleepしないと一部リクエストにエラーが生じると思われるのですが、、、
アップデート時のダウンタイムはなくしたいのでネットや書籍でも調べていたらこういう処理になりました。

ですが、先日maxSurgeとかアップデート戦略をお伺いする前の設定そのままだったので、仰っていただいた通りに設定できていればこちらは不要でもダウンタイムゼロが実現できるという認識でよろしいですかね??:smile:

@ryutah
Copy link

ryutah commented Jun 25, 2019

@KeiichiHonma

ここもう少し聞きたいと思いました。
トップゲートさんは運用で他社様の大規模運用のお手伝いしているとお聞きしましたが、
高負荷の対策としてどういった方法で現実的には対応しているのでしょうか?

特別なことと言えるかわかりませんが、TGではWebでの開発はGAEを主に利用してます ✋
GKEを使う場合も、クライアントからのリクエストを受けるWebフロントの部分はGAEにして、GKEでやるのはGAEでは処理しきれない重い処理や非同期で実行しても良い処理をやらせる感じにしますねー。

その他、なるべくマネージドでスケール可能なサービスを使ってインフラの構築や運用をしないような構成を意識します。
DBサーバで行ったら、Cloud SQLよりもDatastoreやFirestoreなどをなるべく利用するという感じですね!


現状のsampleソースにおける、sample-k8s/k8s/gkeのyamlファイルやdeploy.shの疑問点、問題点のあぶり出し

ここの部分をまずは重要視しておりますが、
あまりご回答もらえていない認識です。

設定ファイルなどの確認をした上で気になったことを回答しているのでこれやってるイメージだったんですけど、イメージされてた回答とちょっと違いましたかね??

結局設定ファイルとスクリプトしか見てないため、 「どういう判断でそうしたのか」みたいな文脈があまりわかっておらず、課題になってそうなところを勝手に想像してるのが原因かもですね 🤔

ちょっと手間かもしれませんが、 各設定ファイルとかスクリプトの中に あえてそうしている 、のか よくわからないけどとりあえずこうしてる なのかわかるようにコメントをつけてもらえたりするともう少しいい感じの回答ができるかもです! 🙏 🙏

@ryutah
Copy link

ryutah commented Jun 25, 2019

まさにHPA / resources.requests(limits) に関しては負荷をかけながら実際に見ていくしか適切な値は得られないと思ったので、現状はとりあえずの意味のない数値となっています。
今後また回答依頼として検証方法などお伺いします。
検証前の初期値として適切でなければrequestsとlimitに関してはもう少し高めでとりあえずの設定はしておきます。

今の設定だと1CPU割り当てられてるノードの場合で最大5つのPod立ち上がる計算になりますからねー。ちょっと厳しそう!

参考程度ですが、僕は1Podで1CPUの割当するくらいからスタートすることが多いので、そのあたりを基準に割当考えてもいいかもですー ✋


replicasとminReplicasは特に考えずだったので、普通はminより下に設定しないということであればそうします!
一応ですが、自分の手元ではminReplicasが優先されて1になってたと思います!

あーそうんなんですね!これは地味に知らなかったです!
ちょっと僕がやったこと無い設定なので、普通はどっち?と言われるとちょっと答えにつまりますね 😅
どこかのサイトとかを参考に設定した感じなら、参考にしたものを教えていただいてもいいです??


停止シグナルというよりsleepが大事(25秒は長すぎるのは承知です)だと思ってまして、、、

あーーー、なるほどなるほどGraceful Shutdown用ですね!理解しておらずごめんなさい 💦

そうですね!確かにアップデート時のエラーを極力減らすように考えると、今やってる感じでpreStopでsleep箚せといた方が良さそうです!
おっしゃっている通り25秒は長い気がしますので、これは可能なら要調整ってところですかねー。

@ryutah
Copy link

ryutah commented Jun 25, 2019

@ryom0624 あ、ちなみにCloud SQL Proxyの方はSIGTERMでのGraceful Shutdownに対応してますので、そいつはpreStopのsleep いらないかもですねー
GoogleCloudPlatform/cloud-sql-proxy#206

@ryom0624
Copy link
Contributor Author

@ryutah

参考程度ですが、僕は1Podで1CPUの割当するくらいからスタートすることが多いので、そのあたりを基準に割当考えてもいいかもですー ✋

ありがとうございます!そうします!


普通はどっち?と言われるとちょっと答えにつまりますね 😅
どこかのサイトとかを参考に設定した感じなら、参考にしたものを教えていただいてもいいです??

そうなんですねー。
HPAだけの設定を書籍で確認しただけでreplicas関連の説明はなかったです:cry:


おっしゃっている通り25秒は長い気がしますので、これは可能なら要調整ってところですかねー。
Cloud SQL Proxyの方はSIGTERMでのGraceful Shutdownに対応してますので、そいつはpreStopのsleep いらないかもですねー

そうします!ありがとうございます!

@KeiichiHonma
Copy link

@ryutah

特別なことと言えるかわかりませんが、TGではWebでの開発はGAEを主に利用してます

そうなのですね。。。。
最近その方が良いのかなと思っていたところでしたのでここらへんぜひ詳細しりたいです。

・GAEをTGでチョイスしている理由を知りたいです。

・弊社はrubyで組んでいるのですが、App Engine フレキシブルで構築してく必要があるのかなと思っております
App Engine フレキシブルだとそんなにメリット享受できませんよーとかありますでしょか?

・そもそもブランドサイト等はGAE向きかなとも思っておりますが、ご意見ほしく

設定ファイルなどの確認をした上で気になったことを回答しているのでこれやってるイメージだったんですけど、イメージされてた回答とちょっと違いましたかね??

村上からも同じような質問ありましたが、あらためて
設定ファイルを見て、ここ致命的、みたいな回答をもらっていないと思っております。
つまり、言い換えると、特段おかしな箇所ありませんでしたよ、という、70点とれてるのでは?の所感回答がほしい、というのが正直なところです。

よくわからないけどとりあえずこうしてる

これ入れてみます!

@ryom0624
Copy link
Contributor Author

@ryutah

月末駆け込みすみません、
以下の点で少し質問です!

参考程度ですが、僕は1Podで1CPUの割当するくらいからスタートすることが多いので、そのあたりを基準に割当考えてもいいかもですー ✋

こちらやってみたのですが、
元々のノードのスペックが1CPUでやっていたので、GKEだと割当可能なものが940mとなっていました。
他のpod(kube-system側)と合わせると1300mCPUとか必要になってきてしまいノードのスペックについてどれがいいのだろうかと疑問が出てきました。:worried:

これも最初の段階ではスペックあげて2CPUとかにして負荷検証とかのフェーズで調整していく。みたいな認識であっていますでしょうか?

@ryutah
Copy link

ryutah commented Jun 28, 2019

@KeiichiHonma

・GAEをTGでチョイスしている理由を知りたいです。

運用、開発の楽さとスケーラビリティの高く、コストが優れている点ですね!
基本的に、デフォルトの設定値で運用しても問題なく動作してくれますし、SSL証明書もマネージドで更新してくれるため、システムを稼働させるために考えなければならないことが大きく減ります。

また、ゼロスケールしますので開発環境やステージング環境などを分けている場合でも余計な費用がかからずに済むなどもメリット大きいですね ✋


・弊社はrubyで組んでいるのですが、App Engine フレキシブルで構築してく必要があるのかなと思っております

App Engine フレキシブルだとそんなにメリット享受できませんよーとかありますでしょか?

そうですねー、、、Standard Environmentに比べるとちょっと見劣りするなー点が多いですね
特に、スケーラビリティとコストに関してはどうしてもSEには勝てなくなってしまうかなーと。

その分、コンテナでシステムを構築できる汎用性の高さが強みでもありますし、ローカルストレージやCPU割当などもSEより自由に設定可能、VPCの設定が可能であることなどSEには無いメリットも存在するため、一概にはSEのほうが良いとは言い切れないと思います!

また、SSL証明書の自動更新などはFlexible Environmentでもやってくれますので、どちらにしろ運用や環境構築はかなり楽になるとは思いますー。


・そもそもブランドサイト等はGAE向きかなとも思っておりますが、ご意見ほしく

リプレイスではなく新規開発なら間違いなくGAEを選んでたかなーという感じですねー。

GAEは運用や開発が楽ではありますが、特有の制限事項も結構ありますので、最悪アプリケーションの機能自体に手を入れなければならないという可能性がなくも無い点が少し悩ましいポイントですねー。

バッチ処理や非同期処理などをやりたい場合は、専用のやり方を覚える必要がありますし、単純に「今動いているのをそっくりそのまま移行したい」という場合は少し選択をためらうプラットフォームでもあるりますねー。

ただ、GAEに載せられたときのメリットはかなりでかいですので、検証してみる価値はあるかと思います!


村上からも同じような質問ありましたが、あらためて
設定ファイルを見て、ここ致命的、みたいな回答をもらっていないと思っております。
つまり、言い換えると、特段おかしな箇所ありませんでしたよ、という、70点とれてるのでは?の所感回答がほしい、というのが正直なところです。

あーーなるほど!了解です!
今、設定などあらためて見直してますので、また後ほどこのあたりはご報告します!!

@ryutah
Copy link

ryutah commented Jun 28, 2019

@ryom0624

元々のノードのスペックが1CPUでやっていたので、GKEだと割当可能なものが940mとなっていました。
他のpod(kube-system側)と合わせると1300mCPUとか必要になってきてしまいノードのスペックについてどれがいいのだろうかと疑問が出てきました。😟

ごめんなさい、、、僕の返信見直しましたが、requestsとlimitsをごちゃまぜにして回答しているような感じですし、その後の説明もちょっといろいろ説明が足りてない感じがあるので、ちょっと説明し直します。。。 🙏 🙏

resources.requestsとresources.limits

resources.requests

概要

  • コンテナの実行に最低限必要なリソースの割当
  • requests未指定でlimitsが設定されている場合はlimitの値がrequestsの値として扱われる

適切な割当数の調査方法

  • Pod起動後に軽く負荷(通常考えられるトラフィック数を数分ほど流す)をかけて、その間のリソース使用状況を kubectl top や各種モニタリングツールを使って調査する
    • 通常稼働しているときにどの程度リソースを消費するのか知るため

Pod起動時に、ノードに必要なリソースが足りない場合の挙動

  • requests未設定
    • CrashLoopBackOffになり、Podの停止・再起動が繰り返し行われる
  • requests設定
    • Pending状態となり、ノードのリソースに空きができるまで起動が待機される

設定すべきかどうか

設定推奨。
ノードのスペックやノード数を決定するための目安になる。

resources.limits

概要

  • 各コンテナが利用可能な最大のリソース数
  • 未指定時は制限なく利用可能

適切な割当数の調査方法

  • SLOなどで規定されているリクエストrateを目安に負荷をかけ、その間のリソース使用状況を kubectl top や各種モニタリングツールを使って調査する
    • SLO+αの負荷をかけると良さげ

設定すべきかどうか

特に必要性を感じなければ不要。
同じクラスタに複数のシステムが乗っている場合など、他システムが利用するリソースを圧迫しないように制限をかけることが多い。
limitを設定するときは(個人的には)CPU使用率の合計が1CPUになるように設定して負荷をかけながら調整していく


という感じです。。。!

改めて質問にお答えすると、requestsの適切な割当数が不明なようなら、とりあえず未設定の状態で構築してみて負荷をかけ、どの程度リソースを使っているのか確認してみると良いです!(なのでとりあえず1CPUのノードでOKかと)

リソース使用量の検証のために負荷をかける際は、オートスケールをオフ(HPAの設定を外す)に、ノード数とレプリカ数も1にしてから計測したほうがやりやすいと思います 🙌

@ryutah
Copy link

ryutah commented Jun 28, 2019

全体を再度確認しましたー!

致命的な問題や不足している設定は無いと思いますので、後はデプロイ -> 検証を繰り返して細かいパラメータの調整をしていく方向にすすめていくほうが良いのかなーと ✋

また、再確認していて気になった細かい点も書いて置きます。。!


sample-k8s/k8s/gke/web.yaml

Lines 107 to 110 in d09b58a

- name: ssl-certs
mountPath: /etc/ssl/certs
- name: cloudsql
mountPath: /cloudsql

この設定はもう不要になったと思ったんですが、どこかのサンプルに書いてました??

refs


spec:
rules:
- host: ssl-testing.work
http:
paths:
- path: /*
backend:
serviceName: webserver-service
servicePort: 80

バックエンドサービスが一つだけなら、

spec:
    tls:
      - secretName: "[SECRET_NAME]"
    backend:
        serviceName: "[SERVICE_NAME]"
        servicePort: "[SERVICE_PORT]"

みたいにするかな?と思いましたー。(複数のサービスにルーティングする想定ならこの方式で合ってます)


resources:
requests:
cpu: 5m

僕はJobでresourcesを指定したことがないのでちょっと気になりました。軽く調べましたが、Jobにresourcesを指定しているサンプルとかどうするのが良いかと紹介しているようなサイトも見つからず。

別に指定するのが悪いということではなく、あまりやる人いないかも?と思っただけです!

@ryom0624
Copy link
Contributor Author

ryom0624 commented Jul 1, 2019

@ryutah
ご返事遅くなり、申し訳ございません!

致命的な問題や不足している設定は無いと思いますので、後はデプロイ -> 検証を繰り返して細かいパラメータの調整をしていく方向にすすめていくほうが良いのかなーと

ありがとうございます:smile:


resourcesの解説ありがとうございます!助かります。。。

改めて質問にお答えすると、requestsの適切な割当数が不明なようなら、とりあえず未設定の状態で構築してみて負荷をかけ、どの程度リソースを使っているのか確認してみると良いです!(なのでとりあえず1CPUのノードでOKかと)
リソース使用量の検証のために負荷をかける際は、オートスケールをオフ(HPAの設定を外す)に、ノード数とレプリカ数も1にしてから計測したほうがやりやすいと思います

また負荷検証の方法をご教示いただく際のご依頼のときに設定しておきます!
現状とりあえずの値で適当につけたままにします。


この設定はもう不要になったと思ったんですが、どこかのサンプルに書いてました??

どこかの設定を見て書いたんですが、情報が古かったですね、、、ありがとうございます。


ingressのここの部分ですか!知らなかったです。。

https://kubernetes.io/docs/concepts/services-networking/ingress/#single-service-ingress


確かGKEのデフォルトnamesepaceのresourcesが0.1でノードがパンパンになって入らなくなっちゃったときに適当につけた値だったかもしれません。。。消しておきます!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants