Red Hat OpenShift 仮想化におけるLocalnet UDNの例

CUDN Localnetネットワークを使用して、 OpenShift の仮想化VMを IBM Cloud VPC のサブネットに接続し、VLANを基盤とし、ネームスペースが分離されたトラフィックを実現します。

このチュートリアルでは、 IBM Cloud 上の Red Hat OpenShift on IBM Cloud において、Virtual Private Cloud(VPC)サブネット、Cluster User-Defined Networks(CUDN)、localnet、およびネームスペースを使用して、3層アプリケーションのサンプルを作成する方法について説明します。 この例では、仮想ローカルエリアネットワーク(VLAN)を基盤とするローカルネットネットワークを使用して、 Red Hat OpenShift Virtualization上で実行される仮想サーバーをVPCサブネットに直接接続する方法を示しています。 ネットワークの種類に関する詳細については、 『 vSphere® 』の管理者向けドキュメントにある「 Red Hat OpenShift の Open Virtual Network(OVN)ネットワーク 」を参照してください。

概要

この例では、Web層、データベース層、アプリケーション層ごとに別々のネットワークセグメントを持つ3層アプリケーションをデプロイします。 各ティアでは、専用のVPCサブネットと、一意のVLAN IDを持つローカルネットCUDNが使用されます。 Web層とデータベース層は1つのネームスペース(green )に配置され、アプリケーション層は別のネームスペース(red )に配置されています。これは、ネームスペースに基づく分離を実証するためのものです。

ネットワーク、ネームスペース、および仮想サーバーの詳細

次の表は、ネットワーク構成の例をまとめたものです。

Localnet CUDN、ネームスペース、および仮想サーバーの構成例
Localnet CUDN 名前空間 VLAN ID VPC サブネット 仮想サーバー
vlan20-prod green 20 198.18.0.0/24 plant-web00, plant-web01
vlan21-db green 21 198.18.1.0/24 plant-db00, plant-db01
vlan22-app red 22 198.18.2.0/24 plant-app00, plant-app01

最終的な構成の図

Localnet による 3 層アプリケーションの構成
Localnet による 3 層アプリケーションの構成

このガイドにある各コードブロックは、ファイルにコピーして、 oc apply -f <file-name>.yml で実行することができます。 PDFやWord形式では、一部のコードブロックがページをまたぐ場合があり、また、長い行が改行される場合があります。

このガイドでは、 IBM Cloud のCLIコマンドにおいて、「 ibmcloud 」の略語として「 ic 」を使用しています。 シェルで alias ic=ibmcloud を定義するか、以下のコマンドにおいて ic を ibmcloud に置き換えてください。

開始前に

以下の項目がすべて整っていることを確認してください:

  • VPCおよび Red Hat OpenShift リソースを管理する権限を持つ IBM Cloud アカウント。
  • IBM Cloud のCLIがインストールされました。
  • 「 container-service 」および「 vpc-infrastructure 」プラグインがインストールされました。

container-service プラグインは、このガイドでクラスタにVLAN仮想ネットワークインターフェイス(VNI)をアタッチするために使用される ic ks コマンドを提供します。 vpc-infrastructure プラグインは、このガイドでVPCサブネット、仮想ネットワークインターフェイス(VNI)、およびその他のインフラストラクチャを作成するために使用される ic is コマンドを提供します。

必要なCLIプラグインをインストールする必要がある場合は、以下のコマンドを実行してください。

ibmcloud plugin install container-service
ibmcloud plugin install vpc-infrastructure

ネットワークの前提条件を確認する

Red Hat OpenShift on IBM Cloud をご利用の場合は、作業を開始する前に、 Red Hat OpenShift on IBM Cloud の「OVN UDN/CUDN ネットワークの前提条件 」をご確認ください。 Red Hat OpenShift Virtualization Service には、デフォルトでこれらの前提条件が含まれています。

グリーンティア用の名前空間とCUDN Localnetセカンダリネットワークの作成

Localnet ネットワークは、 Layer 2 のプライマリネットワーク、 Layer 2 のセカンダリネットワーク、および同じネームスペース内の他の Localnet ネットワークと共存することができます。 各ローカルネットには、 VLAN ID が必要です。 現在、VLAN 1つにつき1つのサブネットしか使用できません。

このVLANでは、ワーカー間で Layer 2 ドメインは作成されません。 VLANは、VPC内ではなく、各ワーカーノード内で使用されます。

green ネームスペース、および vlan20-prod と vlan21-db のネットワークを作成します。 oc apply -f step1.yml を実行して、マニフェストを適用します。

---
apiVersion: v1
kind: Namespace
metadata:
  name: green
---
apiVersion: k8s.ovn.org/v1
kind: ClusterUserDefinedNetwork
metadata:
  name: "vlan20-prod"
spec:
  namespaceSelector:
    matchExpressions:
    - key: kubernetes.io/metadata.name
      operator: In
      values:
      - "green"
  network:
    topology: Localnet
    localnet:
      role: "Secondary"
      physicalNetworkName: "vpc-vlans"
      ipam:
        mode: Disabled
      vlan:
        mode: Access
        access:
          id: 20
---
apiVersion: k8s.ovn.org/v1
kind: ClusterUserDefinedNetwork
metadata:
  name: "vlan21-db"
spec:
  namespaceSelector:
    matchExpressions:
    - key: kubernetes.io/metadata.name
      operator: In
      values:
      - "green"
  network:
    topology: Localnet
    localnet:
      role: "Secondary"
      physicalNetworkName: "vpc-vlans"
      ipam:
        mode: Disabled
      vlan:
        mode: Access
        access:
          id: 21

以下の点に留意してください:

  • Localnet の設定でサブネットが定義されていません。
  • VLAN 1 は使用しないでください。
  • VLANは2~500の範囲で設定してください。 現在、VLAN 501 ~ 4094 は利用が制限されています。

red ティア用に、別のネームスペースと CUDN Localnet セカンダリネットワークを作成する

「 red 」ネームスペースと「 vlan22-app 」ネットワークを作成します。 oc apply -f step2.yml を実行して、マニフェストを適用します。

---
apiVersion: v1
kind: Namespace
metadata:
  name: red
---
apiVersion: k8s.ovn.org/v1
kind: ClusterUserDefinedNetwork
metadata:
  name: "vlan22-app"
spec:
  namespaceSelector:
    matchExpressions:
    - key: kubernetes.io/metadata.name
      operator: In
      values:
      - "red"
  network:
    topology: Localnet
    localnet:
      role: "Secondary"
      physicalNetworkName: "vpc-vlans"
      ipam:
        mode: Disabled
      vlan:
        mode: Access
        access:
          id: 22

アカウントでの予約済みIPアドレスおよびVNIの作成

この手順では、各サブネットに予約済みIPアドレスを作成し、その予約済みIPアドレスを使用してVNIを作成した後、各仮想ネットワークインターフェースに MAC address を割り当てます(VNI )。

以下の点に留意してください:

  • この手順では、 VLAN ID は接続されていません。
  • この手順で使用するセキュリティグループを必ず確認してください。 ic is sgs を実行して、利用可能なセキュリティグループの一覧を表示します。
  • この手順は一括で実行できます。
  • ホストあたり256個のVNIが上限です。 フェイルオーバーや他のホストからの移行に備え、使用率を85%未満に抑えてください。

各サブネットに予約済みIPアドレスを作成する

まず、仮想サーバー用に各サブネットで予約済みIPアドレスを作成します:

ic is subnet-reserved-ip-create zone1-vm-prod --address 198.18.0.20 --name zone1-web00 --auto-delete false
ic is subnet-reserved-ip-create zone1-vm-db --address 198.18.1.20 --name zone1-db00 --auto-delete false
ic is subnet-reserved-ip-create zone1-vm-app --address 198.18.2.20 --name zone1-app00 --auto-delete false

予約済みIPアドレスを使用したVNIの作成

それでは、前の手順で予約したIP名を使用して、VNIを作成します:

ic is virtual-network-interface-create --name zone1-web00 --allow-ip-spoofing false --auto-delete false --protocol-state-filtering-mode disabled --enable-infrastructure-nat true --subnet zone1-vm-prod --vpc my-vpc --rip zone1-web00 --sgs handclap-roundworm-clique-eccentric --resource-group-name Default
ic is virtual-network-interface-create --name zone1-db00 --allow-ip-spoofing false --auto-delete false --protocol-state-filtering-mode disabled --enable-infrastructure-nat true --subnet zone1-vm-db --vpc my-vpc --rip zone1-db00 --sgs handclap-roundworm-clique-eccentric --resource-group-name Default
ic is virtual-network-interface-create --name zone1-app00 --allow-ip-spoofing false --auto-delete false --protocol-state-filtering-mode disabled --enable-infrastructure-nat true --subnet zone1-vm-app --vpc my-vpc --rip zone1-app00 --sgs handclap-roundworm-clique-eccentric --resource-group-name Default

VLAN VNI をクラスタに割り当てる

前の手順で作成した各VNIのIDを取得し、 IBM Cloud の container-service プラグインを使用して、そのVNIをクラスタに接続します。 クラスタ ID が必要です。これは、 ic ks cluster ls を実行することで取得できます。

以下の点に留意してください:

  • ワーカーがVNIの割り当て量を超過している場合、関連する操作は失敗します。
  • VNIは、クラスター( floating とも呼ばれる)または特定のワーカーに割り当てることができます。

VNI IDを調べてください。

ic is vni zone1-web00 | awk '$1 ~ /^ID/ {print $NF}'
ic is vni zone1-db00 | awk '$1 ~ /^ID/ {print $NF}'
ic is vni zone1-app00 | awk '$1 ~ /^ID/ {print $NF}'

各VNIを、対応するVLAN IDを持つクラスターに割り当ててください。 クラスター ID および VNI ID を、ご自身の環境の値に置き換えてください。

ic ks vni attach baremetal -c <CLUSTER_ID> --vni <VNI_ID_web00> --vlan 20
ic ks vni attach baremetal -c <CLUSTER_ID> --vni <VNI_ID_db00>  --vlan 21
ic ks vni attach baremetal -c <CLUSTER_ID> --vni <VNI_ID_app00> --vlan 22

ネームスペースへの仮想サーバーの追加

以下のマニフェストは、1つの仮想サーバーを作成するための、 YAML の最小限のサンプルです。 このマニフェストは、名前空間やネットワークごとに更新することができます。 作成した各 VNI に対して、 MAC address が必要です。 ic is vnis を実行して一覧を表示し、 DHCP が正しく動作するように、テンプレートの「 macAddress 」フィールドを更新してください。

以下のコマンドを使用して、各 VNI の MAC address を確認してください。

ic is vni zone1-web00 | awk '/^Mac Address/ {print $NF}'
ic is vni zone1-db00  | awk '/^Mac Address/ {print $NF}'
ic is vni zone1-app00 | awk '/^Mac Address/ {print $NF}'

VNI ごとの出力例。 価値観が異なります:

02:00:01:00:98:A0
02:00:02:00:98:A5
02:00:02:00:98:AA

マニフェストを適用する前に、以下の点に留意してください:

  • 各マニフェストのパスワードを更新してください。
  • ログインするには、「 ssh_authorized_keys 」フィールドに実際のSSH公開鍵を入力する必要があります。
  • パスワードを使用したSSHは利用できません。
  • すべての「 macAddress 」という値を、前のコマンドで調べた該当するVNIの MACアドレスに置き換えてください。 「 macAddress 」は、 DHCP が期待通りのIPアドレスを割り当てるように、VNIと一致している必要があります。

oc apply -f <file-name>.yml を使用して、以下のマニフェストをそれぞれ適用してください。 以下のリンクから、各マニフェストに直接移動できます。

green ネームスペース内の仮想サーバー plant-web00 ( vlan20-prod

# Bare YAML to stand up a Red Hat OpenShift on IBM Cloud virtual machine
---
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: "plant-web00"
  namespace: "green"
  annotations:
    description: "example vm plant-web00"
  labels:
    app: "plant-web00-green-server"
    kubevirt.io/dynamic-credentials-support: 'true'
    vm.kubevirt.io/template: "centos-stream9-server-small"
    vm.kubevirt.io/template.namespace: openshift
    vm.kubevirt.io/template.revision: '1'
    vm.kubevirt.io/template.version: v0.34.0
spec:
  dataVolumeTemplates:
    - apiVersion: cdi.kubevirt.io/v1beta1
      kind: DataVolume
      metadata:
        creationTimestamp: null
        name: "plant-web00-green-server"
      spec:
        sourceRef:
          kind: DataSource
          name: "centos-stream9"
          namespace: openshift-virtualization-os-images
        storage:
          resources:
            requests:
              storage: 30Gi
  runStrategy: RerunOnFailure
  template:
    metadata:
      annotations:
        vm.kubevirt.io/flavor: "small"
        vm.kubevirt.io/os: "centos-stream9"
        vm.kubevirt.io/workload: "server"
      labels:
        kubevirt.io/domain: example
        kubevirt.io/size: "small"
    spec:
      domain:
        cpu:
          cores: 1
          sockets: 1
          threads: 1
        devices:
          disks:
            - disk:
                bus: virtio
              name: rootdisk
            - disk:
                bus: virtio
              name: cloudinitdisk
          interfaces:
            - model: virtio
              name: default
              state: up
              bridge: {}
              macAddress: 02:00:01:00:98:A0 # <- replace with the MAC of VNI zone1-web00
          networkInterfaceMultiqueue: true
          rng: {}
        memory:
          guest: "2Gi"
      hostname: "plant-web00"
      networks:
        - name: default
          multus:
            networkName: vlan20-prod
      terminationGracePeriodSeconds: 180
      volumes:
        - dataVolume:
            name: "plant-web00-green-server"
          name: rootdisk
        - cloudInitNoCloud:
            userData: |-
              #cloud-config
              user: admin
              password: "aRandomPassword9292"
              ssh_authorized_keys:
                 - "ssh-ed25519 AAAA....BBBB....CCCCC.....DDDD put-your-key-here@example.local"
              chpasswd: { expire: False }
              runcmd:
                - [ dnf, install, -y, epel-release ]
                - [ dnf, install, -y, iperf3, nmap-ncat, darkhttpd ]
          name: cloudinitdisk

green ネームスペース内の仮想サーバー plant-db00 ( vlan21-db

---
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: "plant-db00"
  namespace: "green"
  annotations:
    description: "example vm plant-db00"
  labels:
    app: "plant-db00-green-server"
    kubevirt.io/dynamic-credentials-support: 'true'
    vm.kubevirt.io/template: "centos-stream9-server-small"
    vm.kubevirt.io/template.namespace: openshift
    vm.kubevirt.io/template.revision: '1'
    vm.kubevirt.io/template.version: v0.34.0
spec:
  dataVolumeTemplates:
    - apiVersion: cdi.kubevirt.io/v1beta1
      kind: DataVolume
      metadata:
        creationTimestamp: null
        name: "plant-db00-green-server"
      spec:
        sourceRef:
          kind: DataSource
          name: "centos-stream9"
          namespace: openshift-virtualization-os-images
        storage:
          resources:
            requests:
              storage: 30Gi
  runStrategy: RerunOnFailure
  template:
    metadata:
      annotations:
        vm.kubevirt.io/flavor: "small"
        vm.kubevirt.io/os: "centos-stream9"
        vm.kubevirt.io/workload: "server"
      labels:
        kubevirt.io/domain: example
        kubevirt.io/size: "small"
    spec:
      domain:
        cpu:
          cores: 1
          sockets: 1
          threads: 1
        devices:
          disks:
            - disk:
                bus: virtio
              name: rootdisk
            - disk:
                bus: virtio
              name: cloudinitdisk
          interfaces:
            - model: virtio
              name: default
              state: up
              bridge: {}
              macAddress: 02:00:01:00:98:A5 # <- replace with the MAC of VNI zone1-db00
          networkInterfaceMultiqueue: true
          rng: {}
        memory:
          guest: "2Gi"
      hostname: "plant-db00"
      networks:
        - name: default
          multus:
            networkName: vlan21-db
      terminationGracePeriodSeconds: 180
      volumes:
        - dataVolume:
            name: "plant-db00-green-server"
          name: rootdisk
        - cloudInitNoCloud:
            userData: |-
              #cloud-config
              user: admin
              password: "aRandomPassword9292"
              ssh_authorized_keys:
                 - "ssh-ed25519 AAAA....BBBB....CCCCC.....DDDD put-your-key-here@example.local"
              chpasswd: { expire: False }
              runcmd:
                - [ dnf, install, -y, epel-release ]
                - [ dnf, install, -y, iperf3, nmap-ncat, darkhttpd ]
          name: cloudinitdisk

red ネームスペース内の仮想サーバー plant-app00 ( vlan22-app

---
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: "plant-app00"
  namespace: "red"
  annotations:
    description: "example vm plant-app00"
  labels:
    app: "plant-app00-red-server"
    kubevirt.io/dynamic-credentials-support: 'true'
    vm.kubevirt.io/template: "centos-stream9-server-small"
    vm.kubevirt.io/template.namespace: openshift
    vm.kubevirt.io/template.revision: '1'
    vm.kubevirt.io/template.version: v0.34.0
spec:
  dataVolumeTemplates:
    - apiVersion: cdi.kubevirt.io/v1beta1
      kind: DataVolume
      metadata:
        creationTimestamp: null
        name: "plant-app00-red-server"
      spec:
        sourceRef:
          kind: DataSource
          name: "centos-stream9"
          namespace: openshift-virtualization-os-images
        storage:
          resources:
            requests:
              storage: 30Gi
  runStrategy: RerunOnFailure
  template:
    metadata:
      annotations:
        vm.kubevirt.io/flavor: "small"
        vm.kubevirt.io/os: "centos-stream9"
        vm.kubevirt.io/workload: "server"
      labels:
        kubevirt.io/domain: example
        kubevirt.io/size: "small"
    spec:
      domain:
        cpu:
          cores: 1
          sockets: 1
          threads: 1
        devices:
          disks:
            - disk:
                bus: virtio
              name: rootdisk
            - disk:
                bus: virtio
              name: cloudinitdisk
          interfaces:
            - model: virtio
              name: default
              state: up
              bridge: {}
              macAddress: 02:00:01:00:98:AA # <- replace with the MAC of VNI zone1-app00
          networkInterfaceMultiqueue: true
          rng: {}
        memory:
          guest: "2Gi"
      hostname: "plant-app00"
      networks:
        - name: default
          multus:
            networkName: vlan22-app
      terminationGracePeriodSeconds: 180
      volumes:
        - dataVolume:
            name: "plant-app00-red-server"
          name: rootdisk
        - cloudInitNoCloud:
            userData: |-
              #cloud-config
              user: admin
              password: "aRandomPassword9292"
              ssh_authorized_keys:
                 - "ssh-ed25519 AAAA....BBBB....CCCCC.....DDDD put-your-key-here@example.local"
              chpasswd: { expire: False }
              runcmd:
                - [ dnf, install, -y, epel-release ]
                - [ dnf, install, -y, iperf3, nmap-ncat, darkhttpd ]
          name: cloudinitdisk

ネットワーク設定のテスト

IBM これらのテストを行う際は、クラスターと同じVPC内の Linux® ジャンプホストを使用することを推奨します。 ジャンプホストから、仮想サーバーの設定で指定した公開鍵を使用して、各仮想サーバーにSSHで接続します。

SSHエージェント転送を設定するか、ジャンプホスト上にホストされている新しい鍵を使用してください。 秘密鍵をシステム間でコピーしないでください。

1つのターミナルセッションから、SSHを使用してWeb層の仮想サーバーに接続します:

ssh admin@198.18.0.20

別のターミナルセッションから、SSH を使用してデータベース層の仮想サーバーに接続します:

ssh admin@198.18.1.20

別のターミナルセッションから、SSH を使用してアプリケーション層の仮想サーバーに接続します:

ssh admin@198.18.2.20

テスト (Tests)

ネットワークの設定を確認するために、以下のテストを実行してください。

  1. 各仮想サーバー上で、簡易版の HTTP サーバーを起動します。

    • 198.18.0.20 から、 darkhttpd /usr/share/doc/bash --daemon を実行してください。
    • 198.18.1.20 から、 darkhttpd /usr/share/doc/bash --daemon を実行してください。
    • 198.18.2.20 から、 darkhttpd /usr/share/doc/bash --daemon を実行してください。
  2. 198.18.0.20 から、 curl -v http://198.18.1.20:8080 を実行してください。

  3. 198.18.1.20 から、 curl -v http://198.18.0.20:8080 を実行してください。

  4. jump仮想サーバーから、 curl -v http://198.18.2.20:8080 を実行してください。

  5. 198.18.1.20 から、 iperf3 サーバーを起動します: iperf3 -s -p 9090。

  6. 198.18.0.20 から、 green ネームスペース内の iperf3 サーバーに接続します: iperf3 -c 198.18.1.20 -p 9090。

  7. 198.18.1.20 から 198.18.0.20 へ、およびその逆方向へ ping を実行します。

  8. 198.18.2.20 およびジャンプ仮想サーバーの IP アドレスを使用して、前述のタスクを再実行してください。

マルチネットワークポリシーを適用し、テストを再実行する

vlan20-prod ネットワークに対して、 TCP のポート8080のみを許可するマルチネットワークポリシーを適用します。 以下のマニフェストを「 my-policy.yml 」という名前のファイルとして保存してください。 その後、 oc apply -f my-policy.yml を実行して適用してください。

---
apiVersion: k8s.ovn.org/v1alpha1
kind: MultiNetworkPolicy
metadata:
  name: allow-8080-tcp
  namespace: green
  annotations:
    k8s.v1.cni.cncf.io/policy-for: vlan20-prod
spec:
  podSelector: {}
  ingress:
    - ports:
        - protocol: TCP
          port: 8080
  egress:
    - ports:
        - protocol: TCP
          port: 8080
  policyTypes:
    - Ingress
    - Egress

vlan20-prod 上の plant-web00 に対して、 テスト を再実行してください。 TCP ポート8080は依然として機能していますが、 ping やポート9090での iperf3 テストなど、その他のトラフィックは、そのネットワーク接続では機能しなくなりました。

oc delete -f my-policy.yml を実行して、ポリシーを削除し、接続を復元してください。 テストは再び成功しました。