コンテンツにスキップ

NetworkInterface

NetworkInterfaceは、Podに紐づく論理NICを表すリソースです。

通常はユーザーが直接作成するのではなく、PodControllerがPodのネットワーク要求に応じて自動作成します。名前は<Pod名>.<interface>です。

$ kubectl get networkinterface
NAME       NODE       SUBNET       L2NETWORK   ELASTICIP   ADDRESS          PHASE
app.eth0   worker-1   app-subnet                           10.90.0.5/24     Ready
gw.eth0    worker-2   default                              10.16.0.9/16     Ready
gw.eth1    worker-2                            gw-eip      10.225.51.6/32   Ready

spec

spec.subnetspec.l2Networkspec.elasticIPは、NICの接続先です。3つのうちちょうど1つを指定します。

spec.subnetには、このNetworkInterfaceが接続されるSubnetを指定します。

spec.l2Networkには、このNetworkInterfaceが接続されるL2Networkを指定します。

spec.elasticIPには、同じnamespaceにあるElasticIPの名前を指定します。このNICはElasticIPのアドレスをそのまま持ち、NATを通しません。どのVpcにも属しません。作成後は変更できません。

spec.addressは省略可能で、指定した場合はそのIPv4アドレスを要求します。 未指定の場合は、Juneauがspec.subnetの範囲から空いているアドレスを自動割り当てします。

spec.securityGroupsは、このNICに適用するSecurityGroupです。

spec.elasticIPを指定したNICでは、spec.addressspec.securityGroupsは空でなければなりません。アドレスはElasticIPが持っていて、NIC側で別のアドレスを選ぶことはできません。Vpcに属さないので、SecurityGroupも付けられません。アドレスの予約(AllocationClaim)もNIC側では作りません。

spec.podRefは、この論理NICがどのPodのどのインターフェースを表しているかを示します。

spec.allocationIdentityは、名前が毎回変わるPod(KubeVirtのvirt-launcher Podなど)でも同じワークロードだと分かるようにする値です。SubnetのNICでは、同じ値を持つNIC同士がアドレスの予約を共有します。spec.elasticIPのNICは何も予約しないので、ここでの意味は1つだけです。同じ値を持つ古いNICがElasticIPを持っている間でも、新しいNICがそのElasticIPを参照して作られることを許します。新しいNICは古いNICが消えるまでPendingで待ちます。

status

status.addressは、実際に割り当てられたIPv4アドレスとプレフィックス長です。 spec.elasticIPのNICでは<ElasticIPのアドレス>/32になります。ElasticIPを別のNICが持っている間は空です。

status.routesは、CNIがPodのnetwork namespaceに入れる経路です。

フィールド 意味
dst 宛先のCIDR
gw ネクストホップ
onLink trueなら、NICのアドレスの範囲外にあるgwをリンク上にあるものとして扱います。ip routeonlinkです
table 経路を入れるルートテーブルの番号。0か省略ならmainテーブルです

status.rulesは、CNIがPodのnetwork namespaceに入れるpolicy routingのルールです。

フィールド 意味
from 送信元のCIDR
table 一致したパケットが引くルートテーブルの番号
priority ルールの優先度。小さいほど先に評価されます

NICの種類ごとに、入るものは次のとおりです。

NIC status.routes status.rules
eth0 / Subnet 0.0.0.0/0 via Subnetのゲートウェイ なし
eth0 / L2Network 0.0.0.0/0 via L2Networkのstatus.gateway なし
eth0 / ElasticIP 0.0.0.0/0 via 169.254.0.1onLink: true なし
追加NIC / SubnetかL2Network なし なし
追加NIC / ElasticIP 0.0.0.0/0 via 169.254.0.1onLink: truetable: <番号> from: <ElasticIP>/32table: <番号>priority: 100

mainテーブルに入るデフォルトルートは、eth0の1本だけです。追加NICのSubnetやL2Networkに経路を入れないのは、Podのデフォルトルートを1本に保つためです。

ElasticIPの追加NICだけは、専用のテーブルにデフォルトルートを入れ、そのアドレスを送信元とするパケットをそのテーブルへ向けるルールを足します。外から追加NICのElasticIPに届いた通信の応答は送信元がElasticIPなので、ルールに一致して追加NICから出ていきます。ルールが無いと、応答がeth0から別のアドレスの経路に乗ってしまいます。

169.254.0.1は、ElasticIPを持つNICのゲートウェイです。NICは/32しか持たないので、ゲートウェイはどのアドレスの範囲にも入りません。そのためonLinkを付けます。このアドレス宛のARPには、Node側のvethでeBPFが応答します。

status:
  address: 10.225.51.6/32
  routes:
    - dst: 0.0.0.0/0
      gw: 169.254.0.1
      onLink: true
      table: 182530822
  rules:
    - from: 10.225.51.6/32
      table: 182530822
      priority: 100

ルートテーブルの番号

ElasticIPの追加NICが使うテーブルの番号は、ElasticIPのIPv4アドレスを32ビットの整数として読んだ値です。上位のオクテットから並べるので、10.225.51.610×2^24 + 225×2^16 + 51×2^8 + 6182530822になります。

番号をNIC自身のアドレスだけから決めているので、何度reconcileしても、どのNodeでも、同じElasticIPでPodを作り直しても、番号は変わりません。1つのPodの2枚のNICが同じElasticIPを持つことはwebhookが拒否するので、Podの中で番号がぶつかることもありません。

0.0.0.0から0.0.0.255までのアドレスは、Linuxが予約している0から255のテーブル番号に当たるので、このNICには使えません。

ルールの優先度は100で固定です。mainテーブルを引くルール(32766)より先に評価させるためです。1つのPodに複数のElasticIPの追加NICがあっても、ルールごとに送信元が違うので、同じ優先度で並んでいて構いません。

Phase

  • Pending:まだ割り当て待ち、または必要な依存リソース待ち
  • Allocated:IPは確保済みだが、まだNetworkEndpoint待ち
  • Ready:NetworkEndpointもそろい利用可能
  • Failed:割り当てや整合性確認に失敗

spec.elasticIPのNICでは、次の場合にPendingになります。

reason 状態
WaitingForElasticIP ElasticIPを別のNetworkInterfaceが持っている、ElasticIPAttachmentが使っている、またはElasticIPがまだどのNICにも渡していない
NetworkNotReady ElasticIPにアドレスが無い、またはExternalNetworkのstatus.networkIDがまだ0

どちらもAllocatedReadyのconditionに同じreasonが入り、messageに待っている相手の名前が出ます。

ElasticIPが存在しない、アドレスが無い、ExternalNetworkにstatus.networkIDが無い、のいずれかに当てはまる間は、PodControllerがNetworkInterface自体を作りません。kubectl get networkinterfaceにNICが出てこないときは、controllerのログのwaiting for the network of a Pod NICを見てください。

ElasticIPのアドレスを解釈できない場合は、reason InvalidElasticIPAddressFailedになります。