ご利用の前に

kubernetesは、ワーカーノードのエラーが発生したとしても、正常に或いは部分的に機能を実行できるようにフォールトトレラント(fault tolerant)システムでデザインされています。kubernetesのマスターノードは、仮想機械のようなインフラのステータスを周期的にワーカーノードから受信し、或る理由によって問題が発生した場合には、それを復旧するように動作します。しかし、全ての場合を解決するのには限界があり、ノードの維持管理のために開発者が特定のワーカーノード上に運用中であったpodのグレースフルなシャットダウン(gracefully shutting down)のための介入が必要になることがあります。

この文書では、kubernetesのクラスターのReady状態であるノード数をサーバの返却や維持管理のための中断などで意図的に縮小させようとする際、縮小の対象になるノードで駆動中のアプリケーションを別のノードにドレーン(drain)させる過程について説明します。

kubernetesに対する誤解

kubernetesに対するよくある誤解
十分なリソースがあれば、kubernetesは問題のあるノードの全podを別のノードにリスケジューリングするはずなので、ワーカーノードに発生する可能性のある問題について心配する必要がない。なお、必要の際に、Cluster Autoscalerが新しいワーカーノードを追加するはずなので、アプリケーション及びクラスターに対する運用は問題なく継続することができる。

上述の内容は、kubernetesの運用に対するよくある誤解の1つです。kubernetesのマスターノードのkube-controller-managerは、特定のワーカーノードのコンディションの問題を検知したとしても、Podのeviction条件が満たされた場合に、リスケジューリングを行います。

動作中のワーカーノードを強制で再起動する場合には、上述した条件が満たされていない場合、一定時間の間そのワーカーノードにスケジュールされたPodの停止(downtime)を引き起こすことになります。特定のワーカーノードの再起動の前にkubectl drainのコマンドを利用し、駆動中だったPodを別のワーカーノードにevictionするグレースフルなシャットダウン(gracefully shutting down pods) 過程を通じて安定的にサービスを運用することができます。

ワーカーノードの状況を確認する

kubernetesのマスターノードは、周期的にインフラの状況を周期的にワーカーノードから受信します。ノードの状況と詳細情報は、次のコマンドを通じて確認することができます。詳しい内容は、[公式文書]をご参照ください。

$ kubectl --kubeconfig=$KUBE_CONFIG describe node $NODENAME

ノードのコンディションは、JSONオブジェクトで返されます。次は、正常なノードのコンディションを示すレスポンス例です。

"conditions": [
  {
    "type": "Ready",
    "status": "True",
    "reason": "KubeletReady",
    "message": "kubelet is posting ready status",
    "lastHeartbeatTime": "2019-06-05T18:38:35Z",
    "lastTransitionTime": "2019-06-05T11:41:27Z"
  }
]

ノードのコンディションのうち、Readyタイプのステータスがマスターノードのkube-controller-managerに因数として渡されるpod-eviction-timeoutより更に長く、Unknown又はFalseで維持される場合、ノード上に全てのPodはノードコントローラによって削除されるようにスケジュールされます。

NAVERクラウドプラットフォームのkubernetesサービスでは、pod-eviction-timeoutに5分を設定値として使います。

kubectl drainコマンドを利用してワーカーノードからPodをevictionする

ノードに対するカーネルのアップデート及びインフラの維持管理などの作業に取り掛かる前に、kubectl drainのようなコマンドを利用し、当該ノードからPodを安全にevictionすることができます。安全なevictionは、Podのコンテナーをグレースフルにシャットダウン(gracefully terminate)するようにします。

Note: kubectl drainのコマンドは、ノード内で削除できない特定のシステムPodを無視します。詳しい内容は、 [kubectl drain] ガイドをご参照ください。

kubectl drainのコマンドに成功した場合、それは全てのPodが安全に特定のワーカーノードからevictionされていることを意味します。その後、仮想機械を停止、再起動或いは返却してからノードを中断する方が安全です。

① Podをevictionしようとするノードを確認します。クラスター内の全てのワーカーノードを照会するためには、次のコマンドを利用します。

$ kubectl --kubeconfig=$KUBE_CONFIG get nodes

② 照会したノード名のうち、Podをドレーン(drain)する対象のワーカーノード名を入力します。子の動作は、ノードにスケジュールができないように表示しつつ、対象のワーカーノード上にある全てのPodをグレースフルにシャットダウンします。

$ kubectl --kubeconfig=$KUBE_CONFIG drain $NODENAME

上記のコマンドは、対象のワーカーノードのPodが以下のように属する場合は動作しません。

  • PodがemptyDirを使ってlocal dataを保存する場合 emptyDirを利用してlocal dataを保存するPodが当該ワーカーノードにある場合、このPodを削除する際、当該データも削除されるため実行されません。当該Podが削除されても問題がない場合には、--delete-local-dataフラグをdrainコマンドに追加して実行します。
  • 当該ワーカーノードにデーモンセット(daemonset)が駆動されている場合 デーモンセットに属するPodが当該ワーカーノードに駆動されている場合、kubectl drainコマンドが実行されません。デーモンセットのコントローラは、ノードの unschedulable状態があったとしても、それを無視してそのノードにPodをスケジュールして配置することができます。デーモンセットに属するPodがある場合には、--ignore-daemonsetsフラグを追加して当該Podをevictionの対象から除外することができます。

  • kubernetesのコントローラで管理されないPodが駆動されている場合 kubernetesでは、Deployment、Statefulset、DaemonSet、ReplicaSet、Jobのようなコントローラが管理していないPodが当該ワーカーノード上にある場合、kubectl drainコマンドは、それを保護するために動作しません。kubectl drainコマンドを--forceオプションを通じて実行する場合、このようなPodはクラスターから削除され、リスケジューリングされません。

コマンド例

$ kubectl --kubeconfig=$KUBE_CONFIG drain $NODENAME --delete-local-data --ignore-daemonsets

③ エラーを返すことなく、kubectl drainコマンドに成功した場合、仮想機械を再起動したりPodの削除などのようなクラスターの維持管理作業を実行することができます。維持管理作業の後は、当該ワーカーノードに再度Podがスケジュールされるように次のコマンドを利用します。当該ワーカーノードを返却しようとする場合には、以下のコマンドを実行する必要がありません。

$ kubectl --kubeconfig=$KUBE_CONFIG uncordon $NODENAME

に対する検索結果は~件です。 ""

    に対する検索結果がありません。 ""

    処理中...