ElasticIP¶
ElasticIPは、外部から到達可能なIPアドレスを1つ予約するリソースです。
spec.externalNetworkで参照したExternalNetworkに紐づくAddressPoolから1つのアドレスが選ばれます。 ElasticIPで利用されるAddressPoolは、spec.advertiseModeがExternalNetworkのspec.typeと一致している必要があります。
spec.requestedIPは省略可能で、指定した場合はそのIPv4アドレスをElasticIPとして要求します。 指定するアドレスは、spec.externalNetworkで参照したExternalNetworkに紐づくAddressPoolのいずれかに含まれている必要があります。 省略した場合は、利用可能なアドレスから1つが自動的に選ばれます。
2つの使い方¶
予約したアドレスの使い方は2通りあります。
| 使い方 | 設定するもの | Podの中から見えるアドレス |
|---|---|---|
| NAT | ElasticIPAttachmentでNetworkInterfaceに関連付ける | Vpc内のアドレス。NodeがElasticIPとの間を1:1 NATで変換します |
| 直接 | PodのNICがjuneau.loutres.me/elastic-ipアノテーションか、juneau.loutres.me/networksのelasticIPでElasticIPを参照する | ElasticIPのアドレスそのもの |
1つのElasticIPを2つの使い方で同時に使うことはできません。ElasticIPAttachmentが使っているElasticIPをPodのNICから参照するとPodの作成が拒否され、NICが直接使っているElasticIPを参照するElasticIPAttachmentも拒否されます。
直接使う手順はPodのNICにElasticIPを直接持たせるにあります。
ElasticIPによる1:1 NATは、ICMPエラーメッセージが内包する元パケットのヘッダも書き換えます。Path MTU Discoveryやtracerouteがどう成立するかはElasticIPAttachmentのICMPの扱いを参照してください。直接使う場合はNATを通らないので、書き換えも起きません。
status.attachment¶
status.attachmentは、いまこのアドレスを使っているものです。kindとnameの組で、指す先はElasticIPと同じnamespaceにあります。
kind: ElasticIPAttachment:NATで使われています。nameはElasticIPAttachmentの名前ですkind: NetworkInterface:直接使われています。nameはアドレスを持っているNetworkInterfaceの名前です
何にも使われていない間は空です。
$ kubectl get elasticip
NAME EXTERNALNETWORK ADDRESS ATTACHMENTKIND ATTACHMENT PHASE ALLOCATED ATTACHED
nginx-eip ext-net 10.225.51.5 ElasticIPAttachment nginx-eip-attach Attached True True
web-eip ext-net 10.225.51.8 NetworkInterface web.eth0 Attached True True
Phase¶
- Pending:参照先ExternalNetworkとAddressPoolは解決できたが、利用可能なアドレスがまだ選ばれていない状態
- Available:アドレスは選ばれているが、何にも使われていない状態
- Attached:アドレスが選ばれ、1つのElasticIPAttachmentか、1つのNetworkInterfaceに使われている状態
- Error:依存リソースの不整合や、複数のElasticIPAttachmentからの参照などで正常に扱えない状態
ElasticIPAttachmentとNetworkInterfaceの両方から参照されたときもErrorになります。reasonはConflictで、messageに両方の名前が出ます。webhookが拒否するので普通は起きませんが、Podを作ってからそのNetworkInterfaceができるまでの間にElasticIPAttachmentを作ると、すり抜けることがあります。
この間はどちらもアドレスを使いません。NetworkInterfaceはPendingで止まり、reason WaitingForElasticIPのmessageにElasticIPAttachmentの名前が出ます。ElasticIPAttachmentもPendingで止まり、NATは設定されません。どちらかを消すと、ElasticIPは残った方に使われ、残った方もそのまま動き出します。
直接使うNetworkInterfaceの選び方¶
同じElasticIPを参照するNetworkInterfaceが、同時に2つ以上存在することがあります。終了中のPodと入れ替わりの新しいPodが並んだときや、KubeVirtのvirt-launcher Podが作り直されたときです。アドレスを持てるのはそのうち1つだけで、controllerは次の順に決めます。
status.attachmentに書かれているNetworkInterfaceは、残っている限りアドレスを持ち続けます。削除中でも手放しません- 1に当てはまらず、参照しているNetworkInterfaceのどれかが削除中なら、どれにも渡しません。消えるまで待ちます
- どちらでもなければ、一番古いNetworkInterfaceが持ちます。作成時刻が同じなら名前の順です
2で待つのは、ElasticIPが一度Errorを通るとstatus.attachmentが消えるからです。そのあとでは、削除中のNetworkInterfaceがまだアドレスを持っているかどうかをcontrollerが確かめられません。
待っている間はPHASE: Availableのままで、AttachedconditionがFalse、reasonがWaitingForHandoverになります。messageには、消えるのを待っているNetworkInterfaceの名前が出ます。
アドレスを持てなかったNetworkInterfaceはPendingで止まり、そのPodは起動しません。詳しくはNetworkInterfaceを参照してください。
削除¶
NATで使っている場合の削除は、これまでと変わりません。
直接使っているNetworkInterfaceが1つでも残っている間は、ElasticIPの削除が完了しません。finalizerがNetworkInterfaceが無くなるのを待ち、その間はアドレスの予約(AllocationClaim)もARPAdvertisementも外しません。先に予約を外すと、動いているPodのNICがまだ持っているアドレスを、別のElasticIPが取れてしまうからです。
待っている間はAllocatedconditionのreasonがWaitingForNetworkInterfacesになり、messageに残っているNetworkInterfaceの名前が並びます。そのNetworkInterfaceを持つPodを消せば、削除が進みます。
削除中のElasticIPは、新しく作られたNetworkInterfaceにアドレスを渡しません。
type=arpのExternalNetworkを使う場合¶
外部からの到達性は、経路広報ではなく、ElasticIPを使っているPodが動いているNodeがARP Replyを返すことで成立します。 controllerはeip-<namespace>-<ElasticIP名>という名前のARPAdvertisementを作り、spec.nodeNameに次のNodeを書きます。
- NATで使っている場合:ElasticIPAttachmentの
status.nodeName - 直接使っている場合:アドレスを持っているNetworkInterfaceの
spec.nodeName
Podが別のNodeへ再スケジュールされると、このNodeが変わり、ARPAdvertisementもそれに追従します。
何にも使われていない間はARPAdvertisementが削除され、そのアドレスにはどのNodeも応答しません。 PHASE: Availableのままでも外部からは到達できない、という状態になります。
応答するNodeが移ったときにgratuitous ARPを送らないため、上流のneighborキャッシュが更新されるまで通信は戻りません。詳しくはARPAdvertisementを参照してください。