PR

Kubernetes 1.18の新機能を学び、使ってみよう

2020年5月8日(金)
須田 一輝(すだ・かずき)

はじめに

Kubernetes 1.18(以降、1.18)が2020年3月24日にリリースされました。ここではリリースノートで紹介された5つの注目機能に加えて、筆者が注目するHorizontalPodAutoscalerのspec.behaviorフィールドの追加、ノードローカルDNSキャッシュ、Pod StartupProbeを紹介し、最後にStartupProbeを試していきます。

Kubernetes 1.18注目の新機能

最初に1.18リリースノートにおける5つの注目機能について、それぞれ解説します。

Topology Manager(ベータ)

Topology Managerは、NUMA(Non-Uniform Memory Access、ヌマ)の環境において、コンテナの使用するCPUとデバイスの同一ソケット(NUMAノード)への割り当てを可能にします。Topology Manager(トポロジマネージャ)は1.18でベータに昇格し、デフォルトで使用できるようになりました。

NUMAアーキテクチャは、図1のように複数のCPUから構成されるアーキテクチャで、各ソケット(NUMAノードと呼ぶ)それぞれが自身のCPU、メモリ、PCIデバイスを持ちます。CPUは他のソケットのメモリやI/Oデバイスにアクセスできますが、自身の持つメモリやデバイスに対するアクセスと比較して性能に影響があります。

2ソケットでそれぞれ4CPU、2GPU、2NICという2つのNUMAノードを持つシステムの例
(https://kubernetes.io/blog/2020/04/01/kubernetes-1-18-feature-topoloy-manager-beta/から引用)

Kubernetesには、特定のCPUコアの専有(CPU Pinning)を実現するためのCPU ManagerとGPUやSR-IOVといった拡張デバイスの割り当てを実現するためのDevice Managerがあります。しかし、それらはリソースの割り当てを互いに独立して行っているため、NUMAアーキテクチャにおいて要求されたリソースが異なるソケットへ割り当てられ、性能に影響が出る可能性がありました。今後はTopology Managerにより、できる限り同一のNUMAノードに割り当てるといったコンテナのNUMAアウェアなリソースの割り当てが可能になります。

そのほか、1.18時点でのTopology Managerには次のような制約があります。

  1. Topology Managerが許容するNUMAノードのサイズは最大で8
  2. Kubernetesスケジューラはトポロジを認識しないため、スケジュールされたあとに実行に失敗する可能性がある
  3. Topology Managerをサポートするのは現時点でCPU ManagerとDevice Managerのみで、メモリとHugeページは考慮されない

Topology Managerの具体的な使用方法や関連するより詳しい情報は、次のドキュメントを参照してください(※すべて英文サイトです)。

Kubernetes Topology Manager Moves to Beta - Align Up!
Control Topology Management Policies on a node
Control CPU Management Policies on the Node
Device Plugins
CPU Manager(KEP)
Device Manager(KEP)
Topology Manager(KEP)

Server-side Apply(ベータ)

Server-side Apply(サーバサイドアプライ)は、kubectl applyコマンドによるKubernetesリソースの適用をこれまでクライアント(kubectl)側で実施していたのをサーバ(kube-apiserver)側で実施するようにします。Serverside Applyは1.18で2回目のベータとアナウンスされました。

おそらくKubernetesを利用する方が最も使用するコマンドであり、リソースを宣言的に定義するために使用するkubectl applyコマンドは以前から次のような問題があると言われていました。

  1. Kubernetesオブジェクトの各フィールドが誰またはどのコンポーネントによって定義および変更されたのかが分からず、手順によっては変更が失われるケースがある
  2. リソースの適用に使用されるKubernetes独自のマージアルゴリズムであるStrategic merge-patch(ストラテジック マージパッチ)がクライアント(kubectl)に実装されていたことで、ライブラリとして使用したい場合にkubectlのGoコードをインポートするか、シェルからkubectlを呼び出す必要がある
  3. Strategic merge-patchのパッチ形式が様々なバージョンのKubernetes APIサーバとの互換性を維持し続けることや一部の新機能はクライアント側に実装していくことが困難だった

Server-side Applyは、Kubernetesリソースの各フィールドが誰(人間もKubernetesコンポーネントもここでは同等)によって管理されているかを記録し、もし管理者(フィールドマネージャと呼ぶ)以外がフィールドを変更しようとするとコンフリクトとして扱い、forceオプションを使用しない限り変更されません。これにより、他の管理者が管理しているフィールドを誤って変更してしまうことを防ぎます。

1.18でServer-side Applyを試すには、kubectl applyコマンドに明示的に--server-sideオプションを指定する必要があります。このオプションは将来的にはデフォルトになるでしょう。そのほか、関連するオプションとして、フィールドの変更がコンフリクトした場合に強制的に解決する--force-conflictsオプションが追加されています。また、オブジェクトの各フィールドが誰によって定義および変更されたのかを管理するためのフィールドとして、全てのリソースに共通してmetadata.managedFieldsフィールドが追加されています。

Server-side Applyにより、これまで以上に安全に宣言的にオブジェクト管理ができるようになります。また、これまで自身で開発したツールでkubectl apply相当のことを行うのは難しかったのですが、実装がサーバ側に移ったことでGoクライアントライブラリはもちろんPythonといった他のプログラミング言語やcurlでさえも簡単に利用できるようになります。

Server-side Applyに関するより詳しい情報は、次のドキュメントを参照してください。

Kubernetes 1.18 Feature Server -side Apply Beta 2(英語)
Apply(KEP)(英語)
Kubernetes 1.14: Server -side Apply(alpha)
An example of using dynamic client of k8s.io/client-go(英語)

Ingress APIの改善(GA)

一向にGAを迎えないIngress APIに3つの大きな改善が行われました。

  1. Ingressパスのマッチ方法を指定できるpathTypeフィールドの追加
  2. どのIngressコントローラを使用するかを指定するIngressClassリソースの追加
  3. ホスト名に対するワイルドカードのサポート

(1)のpathTypeフィールドはImplementationSpecific(実装固有) 、Exact(完全一致)、Prefix(前方一致)という3つのパスタイプを指定します。ImplementationSpecificタイプがデフォルトです。

(2)のIngressClassリソースは、これまで1つのクラスタで複数のIngressコントローラを使用したい場合には、kubernetes.io/ingress.classアノテーションにIngressコントローラ名を指定していました。IngressClassリソースはそれに変わるもので、IngressClassリソースにIngressコントローラの名前や独自のパラメータを指定し、Ingress spec.ingressClassNameフィールドで使用するコントローラを指定します。なお、デフォルトで使用するIngressコントローラはIngressClassingressclass.kubernetes.io/is-default-classアノテーションの値を"true"(boolではなく文字列)に設定することで指定できます。

apiVersion: networking.k8s.io/v1beta1
kind: IngressClass
metadata:
  name: external-lb
  annotations:
    ingressclass.kubernetes.io/is-default-class: "true"
spec:
  controller: example.com/ingress-controller
  parameters:
    apiGroup: k8s.example.com/v1alpha
    kind: IngressParameters
    name: external-lb

(3)のホスト名に対するワイルドカードのサポートは*.example.comと指定することでfoo.example.comに一致するようになります。実はこれまではFQDNとの完全一致が仕様だったにも関わらず、多くのIngressコントローラでワイルドカードをサポートしていました。そのため、Ingress API自体の仕様を変更してワイルドカードをサポートするようにしたというのが正確です。

なお、これらの新しい機能を使用できるかは、使用するIngressコントローラがサポートしているか次第です。そのため、クラスタのバージョンを1.18以上にアップグレードしてもこれらの機能が使えるとは限りません。自身の利用するクラスタがどのIngressコントローラを使用しており、そのコントローラが新しい機能をサポートしているかを確認してください。マネージドKubernetesサービスを使用している場合は、パブリッククラウドが出す変更内容を確認しましょう。自身でクラスタを構築している場合は、クラスタの運用者に確認すると良いでしょう。

最後にIngressはコントローラの実装依存な部分が多く、Kubernetesのなかでは異質なリソースです。今回のパスタイプやホスト名のワイルドカードといった機能もコントローラの実装次第で仕様通りに機能するかは分かりません。今後Ingress APIのGAに向けてコンフォーマンステストの提供が予定されているため、将来的には仕様に定義されている機能については挙動が統一されていくことが期待できます。

Ingress APIに関するより詳しい情報は、次のドキュメントを参照してください。

Improvements to the Ingress API in Kubernetes 1.18(英語)
Ingress(KEP)(英語)

【TIP】アルファ、ベータ、GAってなに?

Kubernetesの機能紹介で、よく「この機能はベータです」といった記述があります。Kubernetesでは機能のステージとしてアルファ(Alpha)、ベータ(Beta)、GA(General Availability、安定版)があり、アルファから始まり、ベータを経てGAに至るという流れになっています。

アルファステージの機能は実験的なもので、ベータ昇格時に破壊的変更が入ったり、その後機能自体が削除されることがあるため、基本的に本番では利用しないほうが良いでしょう。デフォルトで無効になっているため、利用するには明示的にフィーチャーゲート(feature-gate*1)で有効にする必要があります。

ベータステージの機能はデフォルトで有効になります。十分にテストを行い、利用しても問題ないレベルと判断されると昇格します。そのあとの昇格で互換性のない変更が入る可能性もありますが、マイグレーションパスが用意されることになっています。このステージの機能を利用されたくない場合は明示的に無効化できます。

GAステージの機能はデフォルトで有効になり、無効化はできません。

今後、Kubernetesのドキュメントでアルファ、ベータ、GAの単語を見かけたら上記を思い出してみてください。より詳細な機能ステージの説明は、次のドキュメントを参照してください。

フィーチャーゲート

*1:フィーチャゲートは特定機能を有効/無効にするフラグのことで、各コンポーネントの--feature-gatesオプションで設定します。アルファ機能はデフォルトで無効になっているので、フィーチャゲートのオプションで有効化すると使用できるようになります。

kubectl alpha debug(アルファ)

kubectl alpha debugコマンドは、実行中のPodにデバッグを目的として一時的なコンテナを後から追加実行できる機能で、アルファステージで提供されました。実は1.16時点で一度アルファで紹介されていたので、1.18で2度目の紹介になります。

これまで、実行中のPodをデバッグしたいときにはkubectl execコマンドを使って対象のコンテナ内で任意のコマンドを実行していました。この方法は、デバッグ対象のコンテナがscratchイメージ(何も含まれていない空のイメージ)やDistroless イメージ(ランタイムのみを含むイメージ)をベースとしているとデバッグに必要なコマンドやそもそもシェルさえも含まれていない場合もあり、デバッグが難しいという問題がありました。デバッグ用のコンテナをサイドカーとして実行させておくということも考えられますが、全てのPodに追加しておくことはコストがかかります。

kubectl alpha debugは、実行中のPodにエフェメラルコンテナと呼ばれる一時的なコンテナ(デバッグコンテナ)を後から追加するコマンドです。これにより、デバッグに必要なコマンドをアプリケーションコンテナに含ませておく必要がなく、コンテナイメージ作成のベストプラクティスであるイメージサイズの最小化などにscratchイメージやDistrolessイメージを使用して素直に取り組むことができます。また、自身が使い慣れたデバッグ専用のコンテナイメージを用意しておくことで、サードパーティのイメージにも慣れた環境でデバッグできます。

使い方はとても簡単で、次のようにデバッグの対象となるPodとデバッグコンテナで使用するイメージを指定するだけです。この例は、デバッグ対象のPodがnginxでデバッグコンテナにbusyboxイメージを指定しています。

$ kubectl alpha debug nginx -it --image=busybox

nginx Podにbusyboxをデバッグコンテナとして追加実行する

デバッグコンテナからはアプリケーションコンテナで実行されているnginxにローカルホスト(127.0.0.1)でアクセスできます。そのほかに--targetオプションを使用すると、指定したコンテナとPIDネームスペースを共有してコンテナを実行します。これにより指定したコンテナで実行されているプロセスを参照し、シグナルの送信などができるようになります。次の例では、nginx Pod に含まれるnginxコンテナとPIDネームスペースを共有したうえでデバッグコンテナを実行します。

$ kubectl alpha debug nginx -it --image=busybox --target=nginx

ここまでで、デバッグコンテナを使用すれば、あとからサイドカーコンテナを追加するなど「デバッグ用途以外にも便利に使えそうだ」と思った方もいるかもしれません。しかし、Podに対する大きな機能追加は影響が大きくなりすぎる可能性があることから、現時点で次のような制約があります。

  1. デバッグコンテナをPodの新規作成時から設定しておくことはできない
  2. デバッグコンテナは再起動されない
  3. livenessProbereadinessProbelifecycleなどの機能が使えない
kubectl debugにより、今後Kubernetes上でアプリケーションのデバッグが格段にやりやすくなりそうですが、1.18時点ではアルファステージの機能であるため、使用するにはEphemeralContainers feature gate(フィーチャゲート)を有効にする必要があります。そのほかkubectl alpha debugに関する詳しい情報は、次のドキュメントを参照してください。

Ephemeral Containers(英語)
kubectl debug(KEP)(英語)
Ephemeral Containers(KEP)(英語)
Kubernetes 1.16: Ephemeral Containers(alpha)
Kubernetes 1.16 アルファ機能を先取り! エフェメラルコンテナ

実際にkubectl alpha debugを試してみたい方は、次のエントリが参考になります。

Kubernetes 1.18でkubectl alpha debugを使ってPodをデバッグする

Windows CSIサポート(アルファ)

1.18でWindows向けのCSIプロキシがアルファストレージで提供されました。これにより、WindowsクラスタにおいてCSIドライバが使用できるようになります。

CSI(Container Storage Interface、コンテナストレージインターフェイス)は、Kubernetesのようなコンテナオーケストレータで任意のストレージシステムでのボリュームの作成/削除やアタッチ/デタッチなどの操作を標準化するために策定された仕様です。それまでのKubernetesでは、サードベンダが新しいボリュームプラグインを追加するにはin-tree(Kubernetes本体のコード)で開発する必要があり、プラグインのリリースがKubernetesのリリースサイクルに縛られる、Kubernetes本体のセキュリティの問題を引き起こす可能性があるなどの課題がありました。KubernetesのCSIサポートにより、サードベンダはCSIに準拠したドライバをKubernetesの外で開発し提供することで、独自のリリースサイクルを取れるようになりました。今後、Kubernetes 1.21までに全てのin-treeのボリュームプラグインのCSIへの移行が予定されています。

csi-proxy.exeは、すべてのWindowsノード上で実行され、Podで実行されるCSIノードプラグインからgRPCで命令を受け取り代理として特権が必要なストレージの操作を行う(https://kubernetes.io/blog/2020/04/03/kubernetes-1-18-feature-windows-csi-support-alpha/からの引用)

このリリースでは、WindowsクラスタでCSIドライバが使用できるようになりました。KubernetesのCSIドライバはコントローラプラグインとノードプラグインの2つから成っています。コントローラプラグインはKubernetes APIや外部のストレージシステムを操作するため、Windowsクラスタでも問題なく使用できていました。一方でノードプラグインは一般に全てのノードにDaemonSetで実行され、ボリュームのフォーマットやマウント/アンマウントやフォーマットなどを行うため、ホストに直接アクセスし、特権コンテナとして実行させる必要があります。しかし、現時点でWindowsは特権コンテナの実行をサポートしていないため、ノードプラグインが機能しませんでした。そこで、Windowsノードのホスト上で直接実行され、ノードプラグインに代わってストレージの操作を実行するCSIプロキシが開発されました。これにより、CSIプロキシがホストを操作することでノードプラグインが特権コンテナとして実行される必要がなくなり、CSIドライバがWindowsクラスタで使用できるようになります。

CSIプロキシは1.18時点でアルファです。AzureとGoogle Cloud Platformのクラウドプロバイダがアルファでサポートしています。今後使用が見込まれる方は検証環境で使用し、問題があればフィードバックするなどしましょう。より詳しいCSIプロキシに関する情報は、次のドキュメントを参照してください。

Introducing Windows CSI support alpha for Kubernetes(英語)
kubernetes-csi/csi-proxy: CSI Proxy utility to enable CSI Plugins on Windows(英語)
Introduction - Kubernetes CSI Developer Documentation(英語)
Support for CSI Plugins on Windows Nodes(KEP)(英語)
KubernetesにおけるContainer Storage Interface(CSI)の概要と検証

著者
須田 一輝(すだ・かずき)
ゼットラボ株式会社/ヤフー株式会社
ヤフー株式会社所属。2015年からゼットラボ株式会社に出向し、Kubernetesを中心としたインフラ基盤の研究開発・技術支援に従事。近頃は、Kubernetesでの永続ストレージやステートフルアプリケーションの運用に関する調査・開発、技術支援を担当している。Kubernetes Meetup Tokyo、Kubernetes Community Days Tokyoの共同主催者で、Kubernetesのアクティブコントリビュータでもある。共著書に『Kubernetes実践入門』『みんなのDocker/Kubernetes』(技術評論社)、監訳書に『入門Prometheus』『Kubernetesで実践するクラウドネイティブDevOps」(オライリー・ジャパン)がある。TwitterとGitHubのアカウントはともに@superbrothers。

連載バックナンバー

Think IT会員サービス無料登録受付中

Think ITでは、より付加価値の高いコンテンツを会員サービスとして提供しています。会員登録を済ませてThink ITのWebサイトにログインすることでさまざまな限定特典を入手できるようになります。

Think IT会員サービスの概要とメリットをチェック

他にもこの記事が読まれています