Google Cloudとコンテナの継続的なセキュリティ
本文の内容は、2020年1月23日にSysdigのCarlos Arillaが投稿したブログ(https://sysdig.com/blog/kubernetes-pod-evicted/)を元に日本語に翻訳・再構成した内容となっております。
通常、ポッドのevictedとスケジューリングの問題は、計画の不足が原因で発生するKubernetesのリミットとリクエストの副作用です。
初心者は、リミットはオプションであり、実行するものの障害に過ぎないと考える傾向があります。リミットを設定できないのに、なぜリミットを設定する必要があるのですか?最終的にはすべてのCPUが必要になる場合があります。
この考え方では、Kubernetesは今のような状況になれなかったでしょう。幸いなことに、Kubernetes開発者はこれを念頭に置いており、クォータメカニズムはリソースの誤用を避けるように設計されています。
アプリケーションのポッドを作成するときに、内部のすべてのコンテナのCPUとメモリのリクエストとリミットを設定できます。
これらの値を適切に設定することは、アプリリソースの管理方法をKubernetesに指示する方法です。 Kubernetesは、すべてのポッドにそのリミットとリクエストに基づいてスコアを付与し、公正使用規則に準拠していないポッドをクラスターからキックする準備ができています。
リクエストの設定とは、コンテナが通常の操作で実行する必要があるリソースの数を宣言することです。
リミットを設定すると、使用できるメモリまたはCPUの量が宣言されます。
Kubernetesのコンテナには2つの異なるクォータがあります。
resources: requests: cpu: 100m memory: 128Mi limits: cpu: 500m
memory: 768Mi
この記事で説明したように、どちらもCPUとメモリでさまざまな意味で使用できます。
Guaranteed:すべてのコンテナにリクエストとリミットがあるポッドで、同じでなければなりません
Burstable:コンテナの1つに少なくとも1つのCPUまたはメモリリクエストがある「保証されていない」ポッド
Best effort:リクエストやリミットのないポッド
この投稿で見るように、ポッドのQoSタイプは、リソースを割り当てて再利用するときに重要です。
クラスターポッドの割り当ては、リクエスト(CPUとメモリ)に基づいています。 ポッドがノード内の使用可能なCPUまたはメモリよりも大きい(リクエストを要求する)場合、ポッドはそのノードで実行できません。 ポッドを実行するのに十分なリソースがクラスターノードにない場合、ポッドは十分なリソースがあるまでスケジュールがペンディングのままになります。
あまりにも多くのリソースを要求すると、ポッドのスケジュール設定が難しくなります。 さらに、リクエストがリソースの通常の使用よりも多い場合、リクエストされ使用されていないリソースを他のポッドに割り当てることはできず、クラスターの運用容量が減少します。 クラスター管理者はおそらくあなたに知らせてくれるでしょう。
ポッドの割り当てを待機しており、スケジューラがポッドを実行するのに十分なリソースを持つノードを見つけられない場合、十分なリソースがあるまで「ペンディング」フェーズのままになります。
NAME READY STATUS RESTARTS AGE
frontend 0/2 Pending 0 10s
「kubectl describe pod」コマンドは、問題に関する情報を提供します。
Events: Type Reason Age From Message ---- ------ ---- ---- -------
Warning FailedScheduling 44s (x2 over 44s) default-scheduler 0/4 nodes are available: 4 Insufficient memory.
ポッドのデプロイメントに必要なリソースが、見た目と異なる場合があることに注意してください。 割り当てに使用されるポッドの有効なリクエストは、次の2つの値のうち最も高い値です。
たとえば、この定義のポッドがある場合:
apiVersion: v1 kind: Pod ... containers: - name: myapp-container image: busybox:1.28 resources: requests: cpu: 100m memory: 128Mi limits: cpu: 500m memory: 768Mi - name: myapp2-container image: busybox:1.28 resources: requests: cpu: 100m memory: 128Mi limits: cpu: 500m memory: 768Mi ... initContainers: - name: init-myservice image: busybox:1.28 command: ['sh', '-c', 'sleep 3'] resources: requests: cpu: 300m
memory: 750Mi
アプリケーションを実行するコンテナの合計は、200ミリコアのCPUと256 MBのリクエストです。 ただし、ポッドのスケジュールに使用される有効なポッドリクエスト、および占有としてマークされたリソースの量は、initコンテナごとに要求される300mおよび750MBになります。
クラスター内の割り当て可能なリソースの明確な視点を持つことにより、クラスター管理者は現在および予想されるワークロードに応じてニーズをより適切に計画できます。リクエストされたリソースを実際に使用しているポッドを正確に把握することは、ノードごとのクラスター占有率とアプリケーション密度を最大化するための貴重なツールになります。
Sysdig MonitorのダッシュボードにKubernetes → Resource usage → Kubernetes cluster and node capacityにメトリクスがあります。
Kubernetesクラスター内のノードでメモリまたはディスクが不足すると、圧力がかかっていることを示すフラグがアクティブになります。これにより、ノード内の新しい割り当てがブロックされ、evictionプロセスが開始されます。
ヒント:この情報は、Sysdigモニターダッシュボードで見つけることができます。
その瞬間、kubeletはリソースの再利用を開始し、リソースの使用量が再びevictionのしきい値を下回るまで、コンテナを強制終了し、ポッドをフェイルとして宣言します。
まず、kubeletは、無効なポッドとそのコンテナを削除してから、未使用のイメージを削除することにより、ノードリソース、特にディスクを解放しようとします。これだけでは不十分な場合、kubeletは次の順序でエンドユーザーポッドの削除を開始します。
ポッドの1つがメモリ使用によってevictedされると、次のようなメッセージが表示されます。
NAME READY STATUS RESTARTS AGE frontend 0/2 Evicted 0 10s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 12m default-scheduler Successfully assigned test/frontend to gke-lab-kube-gke-default-pool-02126501-qcbb Normal Pulling 12m kubelet, gke-lab-kube-gke-default-pool-02126501-qcbb pulling image "nginx" Normal Pulled 12m kubelet, gke-lab-kube-gke-default-pool-02126501-qcbb Successfully pulled image "nginx" Normal Created 12m kubelet, gke-lab-kube-gke-default-pool-02126501-qcbb Created container Normal Started 12m kubelet, gke-lab-kube-gke-default-pool-02126501-qcbb Started container Warning Evicted 4m8s kubelet, gke-lab-kube-gke-default-pool-02126501-qcbb The node was low on resource: memory. Container db was using 1557408Ki, which exceeds its request of 200Mi. Warning ExceededGracePeriod 3m58s kubelet, gke-lab-kube-gke-default-pool-02126501-qcbb Container runtime did not kill the pod within specified grace period.
Normal Killing 3m27s kubelet, gke-lab-kube-gke-default-pool-02126501-qcbb Killing container with id docker://db:Need to kill Pod
evictionの場合、保証されたポッドは安全であるはずです。 ポッドでリクエストとリミットを設定していない場合、これはそうする非常に良い理由です。 これらの値を適切に設定すると、予期しない停止から保護できます。
これには特別な例外があります。一部のシステムサービスが予約されている量よりも多くのリソースを必要とし、保証されたポッドしかない場合、kubeletは圧力がなくなるまでリソースの使用順にそれらのポッドを排除します。
クラスター内のさまざまなアプリケーションを共存させるには、リクエストとリミットを適切に構成することが重要です。これらのリミットを理解することで、コールローテーションをより良くすることができます。
このことから学ぶべき教訓は次のとおりです。
sysdigモニターのような優れたモニタリングシステムは、ポッドの削除およびペンディングのポッドを確実に回避するのに役立ちます。試されたい方は、https://sysdig.jp/ 内の無料お試しをクリックすると14日間のトライアルライセンスが発行されます。
Sysdig Secureも試されたい方は、http://www.scsk.jp/sp/sysdig/index.htmlからお問い合わせいただければと存じます。