Red Hat OpenShift 가상화를 위한 Localnet UDN 예시
OpenShift 가상화 VM을 CUDN Localnet 네트워크를 통해 IBM Cloud VPC 서브넷에 연결하여, VLAN 기반의 네임스페이스 격리 트래픽을 구현합니다.
이 튜토리얼에서는 IBM Cloud 의 Red Hat OpenShift on IBM Cloud 에서 가상 사설 클라우드(VPC) 서브넷, 클러스터 사용자 정의 네트워크(CUDN), 로컬넷 및 네임스페이스를 사용하여 3계층 애플리케이션 예제를 만드는 방법을 설명합니다. 이 예제에서는 가상 로컬 영역 네트워크(VLAN) 기반의 localnet 네트워크를 사용하여, ‘ Red Hat OpenShift Virtualization’에서 실행되는 가상 서버를 VPC 서브넷에 직접 연결하는 방법을 보여줍니다. 네트워크 유형에 대한 자세한 내용은 ‘ vSphere® ’ 관리자를 위한 ‘ Red Hat OpenShift ’의 ‘Open Virtual Network(OVN)네트워킹’을 참조하십시오.
개요
이 예제에서는 웹 계층, 데이터베이스 계층, 애플리케이션 계층에 대해 각각 별도의 네트워크 세그먼트를 사용하는 3계층 애플리케이션을 배포합니다. 각 계층은 전용 VPC 서브넷과 고유한 VLAN ID를 가진 로컬넷 CUDN을 사용합니다. 네임스페이스 기반 격리를 보여주기 위해 웹 및 데이터베이스 계층은 하나의 네임스페이스(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 명령어에서 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 ) 보조 네트워크 및 다른 로컬넷과 공존할 수 있습니다. 각 로컬넷에는 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가 필요합니다. 이 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
네임스페이스에 가상 서버 추가하기
다음 매니페스트는 가상 서버 하나를 생성하기 위한 최소한의 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 주소로 대체하십시오.DHCP가 예상된 IP 주소를 할당하려면macAddress가 VNI와 일치해야 합니다.
oc apply -f <file-name>.yml 를 사용하여 다음 매니페스트를 각각 적용하십시오. 다음 링크를 클릭하면 각 매니페스트로 바로 이동할 수 있습니다.
green네임스페이스에 있는 가상 서버plant-web00(위치:vlan20-prodgreen네임스페이스에 있는 가상 서버plant-db00(위치:vlan21-dbred네임스페이스에 있는 가상 서버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® 점프 호스트를 사용할 것을 권장합니다. Jump 호스트에서 SSH를 사용하여 가상 서버 설정 시 지정한 공개 키로 각 가상 서버에 연결하십시오.
SSH 에이전트 전달을 설정하거나, 점프 호스트에 호스팅된 새 키를 사용하십시오. 개인 키를 시스템 간에 복사하지 마십시오.
터미널 세션 하나에서 SSH를 사용하여 웹 계층 가상 서버에 연결합니다:
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으로, 그리고 그 반대로 핑을 보내보세요. -
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 를 실행하여 정책을 제거하고 연결을 복원하십시오. 테스트가 다시 통과되었습니다.