はじめに
この記事では、前回の記事の続きとして、仮想マシンのLive Migration前後で変わらないIPアドレス(静的IPアドレス)を付与します。また、その静的IPアドレスを用いてアクセス制御を試してみます。
OpenShiftのOverlay Networkについて
この記事の内容を読み進める上では、OpenShift上でPod(インスタンス)達が相互に通信する為の仮想ネットワーク(Overlay Network)に関するイメージを持っておくことが重要です。KubernetesはCNI(Container Network Interface)プラグインを適用する事で、Cluster上に任意のOverlay Networkを展開することができますが、OpenShiftではver4.14から「OVN-Kubernetes CNI」をデフォルトに採用しています。
ver 4.13までデフォルトだった「OpenShift SDN CNI」は、ver4.14以降は非推奨になりました。詳細はこちらを参照ください。
Overlay NetworkとPod達の関係を絵にすると以下のようになります。
パッと見難しそうなのですが、実はとても簡単です。順を追って解説します。
同一Node内に閉じたPod間通信
これは、各Pod同士がレイヤ2(L2)で通信可能です。「OVN-Kubernetes CNI」は仮想的なL2スイッチとしてOpen vSwitch(OVS)を採用し、Podに割り当てられた仮想NIC(名称はeth0
)に振られたMACアドレスで通信します。つまり、同一ホスト内に閉じてL2レベルで通信しているということです。
Nodeを跨いだPod間通信
既にOpenShift/Kubernetes上にコンテナやVMをDeployして通信させた事のある方は、特にコンテナやVMがどのNodeの上で起動しているのかを意識していないと思いますが、しかしよく考えると変です。Nodeを跨いだ通信は一体どうやって実現しているのか?と。更に、同じLANにつながっているNodeならいざ知らず、例えばNodeが異なるAvailability Zone(AZ)に跨っている場合など、いったいPod同士はどうやってお互いのMACアドレスを宛先に通信できているのでしょうか?
その実現手段が「L2 over L3」という技術です。あるいは「トンネリング」と呼びます。ここでは詳細は割愛します(ググってみてください)が、ざっくりいうとレイヤ3(L3)の世界、つまりIPの世界において仮想的なトンネルを張り、Pod同士を物理アドレス(MACアドレス)で通信させています。
このトンネリングのプロトコルは様々なものがあります。例えば「VXLAN(仮想拡張可能LAN)」や「NVGRE(汎用ルーティングカプセル化を使用したネットワーク仮想化)」が有名です。特に、従来OpenShiftに採用されていたデフォルトのCNIプラグインである「OpenShift SDN CNI」はトンネリングプロトコルとして「VXLAN」を採用していました。「VXLAN」にはCPU使用率の上昇を招くという欠点があり(詳細はこちら)、それも踏まえて現在の「OVN-Kubernetes CNI」では「Geneve」というプロトコルが採用されています。マニアックな話ですし、L2 over L3のトンネルはOpenShiftのインストール時に自動的に作成されます。よって特にクラスター管理者が意識するものでもありません。
これによって、Node達が接続されている物理的なネットワーク(Underlay Network)を介して、Pod同士が通信されるわけですが、しかし当のPod達はそんなものは意識しません。自分たちはNode内に閉じた通信だろうが、Nodeを跨いだ通信だろうが、仮想的にPod達が参加するネットワーク、つまりOverlay Networkしか意識する事はありません。
なお、このデフォルトのOverlay Networkである「Pod Network(Cluster Networkともいう)」はPod間の通信のみならず、Kubernetes Clusterとの通信にも使われます。例えば、Podのヘルスチェックや、各種メトリクスの収集 等、いわゆる「U-Plane」のみならず「C-Plane」の通信も走っています。
Pod Networkに参加するPod達は、作成されたタイミングで自動的にCluster内でユニークなIPアドレスを振られます。ただし、Podが再作成されたり、Nodeを跨いだリスケジュールが行われる際には、IPアドレスは勝手に変わります。
これは、以前の記事でVMをLive Migrationした際にも確認できました。
Overlay Networkは追加できる
Podに複数の仮想NICを追加する事ができるCNIプラグインである「Multus CNI」を利用する事で、Podをデフォルトのネットワーク以外のOverlay Networkに参加させることができます。
また、今回は試すことはできませんが、Node(サーバ)が複数の物理NICを有しており、それぞれが異なるUnderlay Networkに接続している場合、Underlay Networkのレベルでも通信を分離することが可能です。
上の図でいう「Overlay Network 1」はデフォルトのPod Networkです。つまり、eth0
にはPod Networkから自動的にIPアドレスが付与され、仮にVM(を内包するPod)がLive Migrationした場合は、勝手にIPアドレスが変わります。しかし、任意で追加する「Overlay Network 2」に接続しているeth1
は、静的IPアドレスを振ることが可能です。これにより、VMが再作成されたりLive Migrationしても変わらない、「そのVM固有のIPアドレス」を保持させることが可能です。
というわけで、早速やっていきます。
VMを追加ネットワークに参加させよう
まずはOpenShift Cluster内に二つめのOverlay Networkを作成します。
とても簡単に作れます。
NetworkAttachmentDefinitions
の作成
追加のOverlay Networkの展開は、NetworkAttachmentDefinitions
(NAD)と呼ばれるリソースを作成する事で可能です。
今回はNameSpace: virtual-machine
に「OVN Kubernetes L2 overlay network」を作成します。
こちらのNADのテンプレを使ってoc apply -f
でサクッと作成できてしまいます。
apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
name: l2-network
namespace: virtual-machine
spec:
config: |
{
"cniVersion": "0.3.1",
"name": "virtual-machine-l2-network",
"type": "ovn-k8s-cni-overlay",
"topology":"layer2",
"netAttachDefName": "virtual-machine/l2-network"
}
詳細は後述しますが、「OVN-Kubernetes CNI」は追加ネットワークに適用できるMultiNetworkPolicy
に対応しており、そのおかげでアクセス制御も容易に実施できるのです。
VMを作成する
VMの作成については、前回の記事を参照頂き、
-
StorageClass
にocs-storagecluster-ceph-rbd-virtualization
を選択し、Live Migration可能なRWX
のPersistentVolume
(PV)をプロビジョニングできる様にする - SSHするための公開鍵を登録する
を実施しますが、加えて以下二つの作業を行います。 - 追加のNetwork Interface
eth1
を設定する -
eth1
に静的IPアドレスを設定する
つまり、これから作成するVM(名称はfedora-source
としておきます)と2つのOverlay Networkの関係はこんな感じです。
作成時に追加のNetwork Interfaceを設定する
VM作成のカスタマイズ画面にてタブ「Network interfaces」から「Add network interface」をクリックします。
インターフェース名はランダムに割り当てられますが、任意の好きなものを設定する事も可能です。
「Network」は、既に追加済みのNAD
があれば選択されている状態です。複数のNAD
があればプルダウンから選べます。
今回は必要な設定がされているので、このまま「Save」をクリックします。
これでNetwork Interfaceeth1
の追加が完了です。
eth1
に静的IPアドレスを設定する
VM作成画面のタブ「Scripts」に移動します。SSH公開鍵の登録は「Public SSH key」から行いましたが、今回は「Cloud-init」欄の「Edit」から、VM作成時に初回のみ実施する設定を行います。
「Add network data」にチェックを入れると、Network Interfaceの設定を入れられます。
対象の「Ethernet name」と付与したい「IP addreses」を入力し、「Apply」をクリックします。
これでOKです。VMの名前をfedora-source
として、「Create VirtualMachine」をクリックしてVMを作成します。
VMが起動すると、Pod Networkに接続しているeth0
には自動的にIPアドレスが振られますが、追加したOverlay Networkに接続しているeth1
には指定した静的IPアドレス192.168.100.10
が振られます。
Live Migrationしてeth1
のIPアドレスが変わらないか確認する
Live Migration前の各種情報は以下です。
- Node:
ip-10-0-64-154.ap-northeast-3.compute.internal
- IP address:
- default(=
eth0
):10.129.8.114
- nic-plum-dog-12(=
eth1
):192.168.100.10
- default(=
なお、VMの詳細情報はoc describe vmi
コマンドで確認することも可能です。Interfaces
でeth0
及びeth1
の情報を確認できます。なお「OVN-Kubernetes」はIPv6/IPv4のデュアルスタックに対応しており、実はeth1
にはIPv6アドレスも設定されますが今回は気にしません。
~ % oc describe vmi fedora-source
(中略)
Interfaces:
Info Source: domain, guest-agent
Interface Name: eth0
Ip Address: 10.129.8.114
Ip Addresses:
10.129.8.114
Mac: 02:7b:6f:00:00:2c
Name: default
Queue Count: 1
Info Source: domain, guest-agent, multus-status
Interface Name: eth1
Ip Address: 192.168.100.10
Ip Addresses:
192.168.100.10
fe80::e46:cadf:ece1:1dd0
Live Migration後の情報を見ます。
- Node:
ip-10-0-49-4.ap-northeast-3.compute.internal
- IP address:
- default(=
eth0
):10.131.4.36
- nic-plum-dog-12(=
eth1
):192.168.100.10
- default(=
eth1
のIPアドレスは変わっていません!これでVMに固有の静的IPアドレスを振れる事が確認できました。
同じ手順でもう一つのVMを作成する。
この後のMultiNetworkPolicy
を試す為に、全く同様の手順でもう一つのVM(名前はfedora-destination
、静的IPアドレスは192.168.100.20
とする)を作成してください。
2つの仮想NICが付いた2つのVM、それぞれが2つのOverlay Networkに接続している状態です。
2nd Overlay Network内でVM同士の通信状況を確認する
2つのVMはそれぞれ仮想NICeth1
が2nd Overlay Networkに接続しています。ということは通信可能ということ。
traceroute
コマンドで疎通状況を確認してみます。
前回の記事を参考にして、fedora-source
にSSH接続しておきます。traceroute
をインストールしておいてください。
[fedora@fedora-source ~]$ sudo yum install traceroute -y
fedora-destination
のIPアドレス192.168.100.20
にtraceroute
してみます。
[fedora@fedora-source ~]$ traceroute 192.168.100.20
traceroute to 192.168.100.20 (192.168.100.20), 30 hops max, 60 byte packets
1 192.168.100.20 (192.168.100.20) 3.698 ms * 3.656 ms
当然ながら1ホップで到達しました。次に、fedora-source
を踏み台サーバにしてfedora-destination
にSSHしてみます。今からやることはこんな感じ。
そのためにはfedora-source
に対して、fedora-destination
に登録しておいた公開鍵のペアである秘密鍵を転送しておく必要があるので、SCPコマンドを使ってローカルからid_rsa
を転送します。oc login
済みのターミナルでvirtctl
コマンドの中にSCPコマンドを盛り込むことができます。virtctl
コマンド、地味に便利だ...
~ % virtctl -n virtual-machine scp <path_to_sshkey> fedora@fedora-source:~/ --identity-file=<path_to_sshkey>
<path_to_sshkey>
はid_rsa
のパスです。
ファイルが転送されたっぽいですが、ちゃんと転送されたか、fedora-source
にSSHして見てみます。
~ % virtctl -n virtual-machine ssh fedora@fedora-source:~/ --identity-file=<path_to_sshkey>
ls
コマンドで確認。あとid_rsa
がオーナーのみ参照・更新できる権限かも見ておきます。
[fedora@fedora-source ~]$ ls -la | grep id_rsa
-rw-------. 1 fedora fedora 2622 May 24 16:12 id_rsa
大丈夫そうです。では、このままfedora-destination
にSSHしてみます。
[fedora@fedora-source ~]$ ssh -i id_rsa 192.168.100.20
[fedora@fedora-destination ~]$
できました!
VMを踏み台サーバにして別のVMに入る。こうした作業がOpenShiftの上で行われている事が面白いですね。つまり、OpenShift VirtualizationはVMの為の基盤としてもとても自然に動作します。
この後、MultiNetworkPolicy
を適用した状態でもう一回SSHしますので、一度exit
しておいて、踏み台サーバに戻って来ておきます。
[fedora@fedora-source ~]$ ssh -i id_rsa 192.168.100.20
Last login: Sat May 25 03:29:46 2024 from 192.168.100.10
[fedora@fedora-destination ~]$ exit
logout
Connection to 192.168.100.20 closed.
[fedora@fedora-source ~]$
MultiNetworkPolicy
を設定し、2つのVM間のアクセス制御を行う
MultiNetworkPolicy
はNetworkPolicy
と名前が似ています。後者はPod Network内における、その名の通り「ネットワークポリシー」を設定するCustom Resource
です。
NetworkPolicy
の詳細はこちらを御覧ください。
MultiNetworkPolicy
は追加ネットワークに対するネットワークポリシーを設定できるCustom Resource
です。NetworkPolicy
自体のAPIが使えますので、記法は同じです。
なお、OpenShiftのデフォルトではMultiNetworkPolicy
のAPIが使えませんので、有効化しておきます。方法はOpenShiftのドキュメントで公開されていますので、こちらを参考にして有効化しておきます。要はnetwork.operator.openshift.io
をいじるわけです。
ローカルでmultinetwork-enable-patch.yamlを作成して、
apiVersion: operator.openshift.io/v1
kind: Network
metadata:
name: cluster
spec:
useMultiNetworkPolicy: true
oc patch
してください。
oc patch network.operator.openshift.io cluster --type=merge --patch-file=multinetwork-enable-patch.yaml
これでapiVersion: k8s.cni.cncf.io/v1beta1
が使えるようになりました。
いよいよMultiNetworkPolicy
(MNP)を作ります。今回MNPを適用する2nd Overlay NetworkはNameSpace: virtual-machine
にありますので、同じNameSpace
にMNPをapplyしてます。
リソース名はmnp-ingress-vm.yaml
としました。
OVN-KuberneteとMNPの互換性についてはこちらを参照ください。
apiVersion: k8s.cni.cncf.io/v1beta1
kind: MultiNetworkPolicy
metadata:
name: mnp-ingress-vm
namespace: virtual-machine
annotations:
k8s.v1.cni.cncf.io/policy-for: virtual-machine/l2-network
# ここでMNPを適用する追加NWを指定します。
# 以下の記法はNetworkPolicyと全く同じです。
spec:
podSelector:
matchLabels:
vm.kubevirt.io/name: fedora-destination
# MNPを適用するPodを特定するkeyを指定します。今回はPod名をそのまま指定します。
policyTypes:
- Ingress
ingress:
- from:
- ipBlock:
cidr: 192.168.100.30
except: []
ports:
- protocol: TCP
port: 22
このポリシーは「fedora-destination
に対して、IPアドレス192.168.100.30
から22番ポートにのみInのアクセスを認める」というポリシーです。
さて、IPアドレス192.168.100.30
はfedora-source
のIPアドレス192.168.100.10
とは異なります。ということは、このMultiNetworkPolicy
を適用してしまうと、fedora-source
からfedora-dextination
にSSHできなくなってしまうはずです。
試してみましょう。上記のmnp-ingress-vm.yaml
をoc apply -f
してください。
再度、fedora-source
からfedora-destination
にSSHを試みます。
[fedora@fedora-source ~]$ ssh -i id_rsa 192.168.100.20
あれれ、いつまでたっても接続できません。そりゃそうです。ctrl + c
で中断します。
GUIでMNPのYAMLを修正してみます。cidr
のIPアドレスをfedora-source
のIPアドレス192.168.100.10
に変更して「保存」をクリックします。
もう一回SSHを試します。
[fedora@fedora-source ~]$ ssh -i id_rsa 192.168.100.20
Last login: Sat May 25 03:33:16 2024 from 192.168.100.10
[fedora@fedora-destination ~]$
今度はちゃんとSSHできました。
おわりに
OpenShiftの追加ネットワークを設定し、OpenShift Virtualization上で建てたVM間の疎通を確認しました。またVMに静的IPアドレスを振ってネットワークポリシーを適用したりしました。
これまでのVMの運用のあり方をOpenShift上でも遜色なく適用する事が確認できました。