Red Hat OpenShift 虛擬化技術的Localnet UDN範例
透過 CUDN Localnet 網路,將 OpenShift 虛擬化虛擬機器 (VM) 連接到 IBM Cloud VPC 子網,以實現基於 VLAN 且命名空間隔離的流量傳輸。
本教學將示範如何在 IBM Cloud 上的 Red Hat OpenShift on IBM Cloud 中,利用虛擬私有雲(VPC)子網、叢集使用者自訂網路(CUDN)、localnet 以及命名空間,建立一個三層式應用程式的範例。 此範例示範如何透過基於虛擬區域網路(VLAN)的 localnet 網路,將在 Red Hat OpenShift 虛擬化環境上運行的虛擬伺服器直接連接到 VPC 子網。 有關網路類型的更多資訊,請參閱《 Red Hat OpenShift 中的 Open Virtual Network(OVN)網路》一文(適用於 vSphere® 管理員 )。
概觀
此範例部署了一個三層式應用程式,其中 Web 層、資料庫層和應用程式層各自位於不同的網路區段中。 每個層級皆使用專用的 VPC 子網,以及具有唯一 VLAN ID 的 localnet CUDN。 Web 層與資料庫層被放置於同一個命名空間(green )中,而應用程式層則被放置於另一個獨立的命名空間(red )中,藉此展示基於命名空間的隔離機制。
網路、命名空間及虛擬伺服器的詳細資訊
下表概述了此範例網路佈局。
| 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 |
最終設置示意圖
本指南中的每個程式碼區塊均可複製到檔案中,並透過 oc apply -f
本指南在 IBM Cloud 的 CLI 指令中,將 ic 作為 ibmcloud 的簡寫。 請在您的命令列介面中設定 alias ic=ibmcloud ,或在後續指令中將 ic 替換為 ibmcloud 。
開始之前
請確保您已備妥以下項目:
- 一個具備管理 VPC 和 Red Hat OpenShift 資源權限的 IBM Cloud 帳戶。
- IBM Cloud CLI 已安裝。
- 已安裝「
container-service」和「vpc-infrastructure」外掛程式。
container-service 外掛程式提供了 ic ks 指令,本指南即利用這些指令將 VLAN 虛擬網路介面 (VNI) 綁定至叢集。 vpc-infrastructure 外掛程式提供了 ic is 中的指令,本指南即利用這些指令來建立 VPC 子網、虛擬網路介面 (VNI) 及其他基礎架構。
若需安裝所需的 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 虛擬化服務預設已包含這些先決條件。
為綠色層建立命名空間及 CUDN Localnet 次級網路
Localnet 網路可在同一個命名空間中,與 Layer 2 主網路、Layer 2 次要網路,以及其他 Localnet 網路共存。 每個區域網路都需要一個 VLAN ID。 目前,每個 VLAN 僅能使用一個子網。
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。 - 請使用 2 至 500 之間的 VLAN 範圍。 VLAN 501 至 4094 目前受到限制。
為紅色層級建立另一個命名空間及 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
在您的 VPC 帳戶中建立保留 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 識別碼。
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
將虛擬伺服器新增至命名空間
以下 manifests 是一個 YAML 的基本範例,用於建立一個虛擬伺服器。 您可以針對每個命名空間和網路更新此清單。 您需要為每個已建立的 VNI 建立對應的 MAC address。 執行 ic is vnis 來列出這些項目,並更新範本中的 macAddress 欄位,以確保 DHCP 能正常運作。
請使用以下指令,找出每個 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必須與 VNI 相符,才能讓DHCP指派預期的 IP 位址。
請使用 oc apply -f
- 位於
green命名空間中的虛擬伺服器plant-web00,位於vlan20-prod - 位於
green命名空間中的虛擬伺服器plant-db00,位於vlan21-db - 位於
red命名空間中的虛擬伺服器plant-app00,位於vlan22-app
位於 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 代理轉發,或使用一個託管於中繼主機上的新金鑰。 請勿在不同系統之間複製您的私鑰。
在一個終端機工作階段中,使用 SSH 連線至 Web 層虛擬伺服器:
ssh admin@198.18.0.20
在另一個終端機工作階段中,使用 SSH 連線至資料庫層的虛擬伺服器:
ssh admin@198.18.1.20
在另一個終端機工作階段中,使用 SSH 連線至應用程式層的虛擬伺服器:
ssh admin@198.18.2.20
測試
執行以下測試以驗證網路設定。
-
在每台虛擬伺服器上啟動一個簡單的 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。
- 在
-
在
198.18.0.20上,執行curl -v http://198.18.1.20:8080。 -
在
198.18.1.20上,執行curl -v http://198.18.0.20:8080。 -
在 jump 虛擬伺服器上,執行
curl -v http://198.18.2.20:8080。 -
從
198.18.1.20開始,啟動一個iperf3伺服器:iperf3 -s -p 9090。 -
從
198.18.0.20連線至green命名空間中的iperf3伺服器:iperf3 -c 198.18.1.20 -p 9090。 -
從
198.18.1.20向198.18.0.20進行 Ping 測試,反之亦然。 -
請使用
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 以移除該政策並恢復連線。 測試再次通過。