埋め込みレジストリミラー

バージョンゲート

埋め込みレジストリミラーは、2024年1月のリリースから実験的な機能として利用可能です:v1.26.13+k3s1、v1.27.10+k3s1、v1.28.6+k3s1、v1.29.1+k3s1

K3sは、Kubernetesクラスター内のノード間でコンテナイメージをピアツーピアで共有できる、ステートレスな分散OCIレジストリミラーであるSpegelを埋め込んでいます。 分散レジストリミラーはデフォルトでは無効になっています。

分散OCIレジストリミラーの有効化

埋め込みレジストリミラーを有効にするには、サーバーノードを--embedded-registryフラグを付けて起動するか、設定ファイルにembedded-registry: trueを追加する必要があります。 このオプションを有効にすると、クラスター内のすべてのノードで埋め込みミラーが使用可能になります。

クラスター全体で有効にすると、すべてのノードはポート6443でローカルOCIレジストリをホストし、ポート5001でピアツーピアネットワークを介して利用可能なイメージのリストを公開します。 任意のノードのcontainerdイメージストアにあるイメージは、外部レジストリにアクセスせずに他のクラスターのメンバーによってプルされることができます。 エアギャップイメージtarファイルを介してインポートされたイメージは、Kubeletのガベージコレクションによって削除されないようにcontainerdに固定されます。

ピアツーピアポートは、K3sサービスの環境変数K3S_P2P_PORTを設定することで5001から変更できます。ポートはすべてのノードで同じ値に設定する必要があります。 ポートの変更はサポートされておらず、推奨されません。

要件

埋め込みレジストリミラーが有効になっている場合、すべてのノードは内部IPアドレスを介して、TCPポート5001および6443で相互に接続できる必要があります。 ノードが相互に接続できない場合、分散レジストリが最初に試され、その後他のエンドポイントにフォールバックするため、イメージのプルに時間がかかることがあります。

レジストリミラーリングの有効化

レジストリのミラーリングを有効にすると、ノードは他のノードからそのレジストリのイメージをプルし、そのレジストリのイメージを他のノードと共有できます。 一部のノードでレジストリのミラーリングが有効になっているが、他のノードでは有効になっていない場合、レジストリが有効になっているノードのみがそのレジストリからイメージを交換します。

上流のコンテナレジストリからのイメージのミラーリングを有効にするには、ノードはそのレジストリのregistries.yamlmirrorsセクションにエントリを持っている必要があります。 レジストリにはエンドポイントをリストする必要はなく、存在するだけで十分です。 例えば、docker.ioおよびregistry.k8s.ioからのイメージの分散ミラーリングを有効にするには、すべてのクラスターのノードで以下の内容でregistries.yamlを設定します:

mirrors:
  docker.io:
  registry.k8s.io:

レジストリミラーのエンドポイントも通常通り追加できます。 以下の設定では、イメージのプルは最初に埋め込みミラーを試し、その後mirror.example.com、最後にdocker.ioを試みます:

mirrors:
  docker.io:
    endpoint:
      - https://mirror.example.com

プライベートレジストリを直接使用する場合、上流レジストリのミラーとしてではなく、パブリックレジストリと同様にミラーリングを有効にできます - ミラーセクションにリストすることで:

mirrors:
  mirror.example.com:
バージョンゲート

ワイルドカードサポートは、2024年3月のリリースから利用可能です:v1.26.15+k3s1、v1.27.12+k3s1、v1.28.8+k3s1、v1.29.3+k3s1

"*"ワイルドカードミラーエントリを使用して、すべてのレジストリの分散ミラーリングを有効にできます。アスタリスクは必ず引用符で囲む必要があります:

mirrors:
  "*":

ノードでミラーリングが有効になっているレジストリがない場合、そのノードは分散レジストリに一切参加しません。

registries.yamlファイルの構造に関する詳細は、プライベートレジストリの設定を参照してください。

デフォルトエンドポイントのフォールバック

デフォルトでは、containerdはミラーエンドポイントが設定されているレジストリからプルする際にデフォルトエンドポイントにフォールバックします。これを無効にし、 設定されたミラーおよび/または埋め込みミラーからのみイメージをプルしたい場合は、プライベートレジストリ設定のデフォルトエンドポイントのフォールバックセクションを参照してください。

--disable-default-endpointオプションを使用していて、特定のレジストリから直接プルを許可し、他のレジストリからは許可しない場合は、エンドポイントを明示的に指定してイメージプルがそのレジストリ自体にフォールバックするようにできます:

mirrors:
  docker.io:           # デフォルトエンドポイントなし、ノードで利用できない場合はプルに失敗
  registry.k8s.io:     # デフォルトエンドポイントなし、ノードで利用できない場合はプルに失敗
  mirror.example.com:  # 明示的なデフォルトエンドポイント、ノードで利用できない場合は上流からプル可能
    endpoint:
      - https://mirror.example.com

最新タグ

コンテナイメージにタグが指定されていない場合、暗黙のデフォルトタグはlatestです。このタグは頻繁に更新され、最新バージョンのイメージを指します。このタグはプルされるタイミングによって異なるリビジョンのイメージを指すため、分散レジストリは他のノードからlatestタグをプルしません。これにより、containerdは一貫したビューを確保するために上流レジストリまたはレジストリミラーにアクセスすることを強制されます。

これは、コンテナイメージにlatestタグを使用する際にKubernetesが観察する特別なimagePullPolicyのデフォルト設定と一致します。

latestタグのミラーリングは、K3sサービスの環境変数K3S_P2P_ENABLE_LATEST=trueを設定することで有効にできます。上記の理由から、これはサポートされておらず、推奨されません。

セキュリティ

認証

埋め込みミラーのレジストリAPIへのアクセスには、クラスターのクライアント証明書認証局によって署名された有効なクライアント証明書が必要です。

分散ハッシュテーブルのピアツーピアネットワークへのアクセスには、サーバーノードによって制御される事前共有キーが必要です。 ノードは、事前共有キーとクラスター証明書認証局によって署名された証明書の両方を使用して相互に認証します。

潜在的な懸念

分散レジストリはピアツーピアの原則に基づいて構築されており、すべてのクラスターメンバー間で同等の特権と信頼を前提としています。 これがクラスターのセキュリティポリシーに一致しない場合、埋め込み分散レジストリを有効にすべきではありません。

埋め込みレジストリは、ノードが通常アクセスできないイメージを利用可能にする場合があります。 例えば、一部のイメージがKubernetesイメージプルシークレットやregistries.yamlの資格情報を介して認証が必要なレジストリ、プロジェクト、リポジトリからプルされる場合、分散レジストリは他のノードがこれらのイメージを資格情報なしで共有できるようにします。

あるノードのcontainerdイメージストアにイメージをプッシュする権限を持つユーザーは、他のクラスターノードのイメージを「毒する」ことができるかもしれません。他のノードはそのノードが広告するタグを信頼し、上流レジストリを確認せずに使用します。 イメージの整合性が重要な場合は、タグの代わりにイメージダイジェストを使用するべきです。ダイジェストはこの方法で毒されることはありません。

エアギャップまたは手動でロードされたイメージの共有

イメージの共有は、ソースレジストリに基づいて制御されます。 エアギャップtarボールを介して直接containerdにロードされたイメージ、またはctrコマンドラインツールを使用してcontainerdのイメージストアに直接ロードされたイメージは、ミラーリングが有効になっているレジストリとしてタグ付けされている場合、ノード間で共有されます。

イメージが実際に存在する必要はなく、到達可能である必要もありません。 例えば、架空の上流レジストリとしてイメージをタグ付けし、そのイメージをcontainerdのイメージストアにインポートすることができます。 そのレジストリがregistries.yamlにリストされている限り、すべてのクラスターメンバーからそのイメージをプルすることができます。

イメージのプッシュ

埋め込みレジストリは読み取り専用であり、docker pushや他の一般的なOCIレジストリと対話するツールを使用して直接プッシュすることはできません。

イメージは、ctr -n k8s.io image pullを実行してイメージをプルするか、docker saveで作成されたイメージアーカイブをctr -n k8s.io image importコマンドを使用してロードすることで、手動で埋め込みレジストリで利用可能にできます。 ctrを使用してイメージを管理する際には、kubeletに表示されるようにするためにk8s.io名前空間を指定する必要があることに注意してください。