Skip to content

Commit 39ac72a

Browse files
authored
Merge pull request #1638 from RichardORCL/main
Added information on how to have multiple egress IPs and use OCI vLANs with Openshift
2 parents 95cf86e + d8e1abd commit 39ac72a

File tree

9 files changed

+330
-0
lines changed

9 files changed

+330
-0
lines changed

cloud-infrastructure/virtualization-solutions/openshift-on-oci/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Reviewed: 06.11.2024
1414

1515
## Reference Architectures & Step-by-step Guides
1616

17+
- [Use multiple and floating Egress IP(s) by leveraging OCI VLANs](openshift-floating-egress-ip/README.md)
1718
- [Enable Seamless Access to Red Hat OpenShift Container Platform on OCI from On-Premises to VCNs in the Same Region](https://docs.oracle.com/en/learn/oci-openshift-vcn/)
1819

1920
## OpenShift Day-2 - Operations
Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
# OCI-OpenShift-Floating-EgressIP
2+
3+
If you want to use a fixed egress IP address in openshift for your pods, you need to make sure that the egress IP is "floatable" across your worker nodes.
4+
In case the host fails that was assigned to the EgressIP.
5+
6+
Traditionally this is difficult to do in a public cloud using Layer 3 networking, as the cloud control plane controls
7+
the assigned IP Addresses and another instance can not just reclaim an IP address in case of failure.
8+
9+
The Oracle Cloud (OCI) does not just support Layer 3 network subnets, but also has the capability to support Layer 2 VLANs.
10+
In these VLANs any instance can claim IP addresses using normal ARP. Initially this VLAN concept was designed for use with
11+
the Oracle Cloud VMware Solution, but it can also be used for normal OCI Compute Instances (VMs and Bare metal servers).
12+
https://docs.oracle.com/en-us/iaas/Content/VMware/Tasks/ocvsmanagingl2net.htm
13+
14+
We can use these VLANs for our OpenShift worker nodes as secondary NIC interfaces and route the EgressIP traffic over.
15+
16+
17+
## Create VLAN and assign addition vNIC(s) to worker nodes attached to the VLAN in OCI
18+
19+
1. Create a VLAN and assign it a CIDR range. The first available address in this CIDR range will be used by OCI for the gateway service.
20+
All other addresses are free to be used. There is no DHCP service in the VLAN.
21+
22+
In this example, we have created a VLAN with the CIDR: 10.0.101.0/24. Hence the default gateway of this segment will be 10.0.101.1
23+
24+
2. On each worker node VM add a vNIC attached to the created VLAN
25+
26+
**TIP: Automate Step 1 and Step 2**: Use the provided [vlan.tf](tf_Create_and_Add_VLAN/vlan.tf) file to automate the creation of the VLAN and the assignment of vNICs to worker nodes. This Terraform script will handle the setup for you, ensuring that the VLAN is created with the specified CIDR range and that each worker node VM has a vNIC attached to the created VLAN.
27+
28+
29+
3. Login to one of the worker nodes and confirm a 2nd NIC is visible and note down the device name (In this example it is ens5)
30+
31+
```
32+
oc debug node/[your node name]
33+
chroot /host
34+
ifconfig
35+
```
36+
37+
38+
<img src="images/vnicsetup.jpg">
39+
40+
41+
## Setup IP configuration for worker nodes for the new VLAN vNICs
42+
43+
1. Install openshift-nmstate operator via the operator hub. After installation, click on 'create instance' on the operator and click 'create'
44+
45+
Check if the NodeNetworkConfigurationPolicy CRD exists
46+
47+
linux:
48+
49+
```oc get crds | grep nodenetworkconfigurationpolicies```
50+
51+
windows:
52+
53+
```oc get crds | findstr nodenetworkconfigurationpolicies```
54+
55+
<img src="images/netconfigpolicy.jpg">
56+
57+
2. Create node_config.yaml file:
58+
59+
You can create 1 file per worker node or just add multiple worker nodes into one file. The example below show the configuration of 2 workers nodes.
60+
61+
**IMPORTANT:** Ensure you use the correct device name, in my example it is 'ens5', but check in your environment. Set the correct IP address and prefix.
62+
63+
**IMPORTANT:** All nodes that can run worload pods must have VLAN attached to them and have an individual IP setup in this VLAN
64+
65+
Reminder: OCI does not provide DHCP on a VLAN, so you need to maintain assigned IP addresses yourself. You need 1 IP address per worker node and you need 1 IP address per egress IP you want to use.
66+
67+
The next-hop-address needs to be set to the VLANs gateway, which is the first available address in the assigned CIDR block of the VLAN. In this example this is 10.0.101.1
68+
69+
```
70+
apiVersion: nmstate.io/v1
71+
kind: NodeNetworkConfigurationPolicy
72+
metadata:
73+
name: node1-ens5-vlan-static-ip
74+
spec:
75+
nodeSelector:
76+
kubernetes.io/hostname: os-compute-1.private.openshiftvcn.oraclevcn.com
77+
desiredState:
78+
interfaces:
79+
- name: ens5
80+
type: ethernet
81+
state: up
82+
ipv4:
83+
enabled: true
84+
address:
85+
- ip: 10.0.101.11
86+
prefix-length: 24
87+
dhcp: false
88+
mtu: 9000
89+
routes:
90+
config:
91+
- destination: 0.0.0.0/0
92+
next-hop-address: 10.0.101.1
93+
next-hop-interface: ens5
94+
metric: 500
95+
---
96+
apiVersion: nmstate.io/v1
97+
kind: NodeNetworkConfigurationPolicy
98+
metadata:
99+
name: node2-ens5-vlan-static-ip
100+
spec:
101+
nodeSelector:
102+
kubernetes.io/hostname: os-compute-2.private.openshiftvcn.oraclevcn.com
103+
desiredState:
104+
interfaces:
105+
- name: ens5
106+
type: ethernet
107+
state: up
108+
ipv4:
109+
enabled: true
110+
address:
111+
- ip: 10.0.101.12
112+
prefix-length: 24
113+
dhcp: false
114+
mtu: 9000
115+
routes:
116+
config:
117+
- destination: 0.0.0.0/0
118+
next-hop-address: 10.0.101.1
119+
next-hop-interface: ens5
120+
metric: 500
121+
---
122+
123+
```
124+
125+
3. Apply the configuration:
126+
```
127+
oc apply -f node_config.yaml
128+
```
129+
130+
4. enable ipForwarding to the network.operator
131+
132+
run
133+
```
134+
oc edit network.operator
135+
```
136+
137+
add the line: "ipForwarding: Global" directly after the gatewayConfig line
138+
139+
```
140+
defaultNetwork:
141+
ovnKubernetesConfig:
142+
egressIPConfig: {}
143+
gatewayConfig:
144+
ipForwarding: Global
145+
```
146+
147+
The Opsnshift environment and its worker nodes are now setup correctly to use the VLANs and have the egressIP(s) float on it.
148+
149+
## Setup EgressIP(s) and assign them to namespaces
150+
151+
## Egress Labels
152+
We first need to allow the hosts you want to use as egress controllers. We can do this by assigning them
153+
the correct k8s label:
154+
155+
```
156+
oc get nodes --show-labels | grep egress
157+
oc label node <node-name> k8s.ovn.org/egress-assignable=true
158+
```
159+
160+
Ensure you have set the egress-assignable=true label to all the hosts you have connected to the VLAN(s)
161+
162+
## Namespaces
163+
Lets create 2 example namespaces, each with it's own deployement in it and a label called egress.
164+
165+
```
166+
oc new-project test1
167+
oc label namespace test1 egress=egress_ip1
168+
oc new-app httpd
169+
170+
oc new-project test2
171+
oc label namespace test2 egress=egress_ip2
172+
oc new-app httpd
173+
```
174+
175+
We can not create an egressip config file and apply it to the OpenShift cluster.
176+
Example egressip.yaml
177+
178+
```
179+
apiVersion: k8s.ovn.org/v1
180+
kind: EgressIP
181+
metadata:
182+
name: egressips-oci-vlan-01
183+
spec:
184+
egressIPs:
185+
- 10.0.101.101
186+
namespaceSelector:
187+
matchLabels:
188+
egress: egress_ip1
189+
---
190+
apiVersion: k8s.ovn.org/v1
191+
kind: EgressIP
192+
metadata:
193+
name: egressips-oci-vlan-02
194+
spec:
195+
egressIPs:
196+
- 10.0.101.102
197+
namespaceSelector:
198+
matchLabels:
199+
egress: egress_ip2
200+
```
201+
202+
Create the above egressip.yaml and apply to your cluster
203+
```
204+
oc apply -f egressip.yaml
205+
```
206+
207+
You can not check if the EgressIPs are running and from what node the out going traffic goes.
208+
```
209+
oc get egressip
210+
```
211+
212+
<img src="./images/egressips.jpg">
213+
214+
Having completed this setup, the 2 projects will both now have a unique fixed EgressIP. The workernode routing the Egress traffic can now fail over to any other worker node fully automatically.
215+
216+
## Having Public IP addresses for the EgressIP
217+
218+
Using the external access feature on the VLAN in OCI, you can assign each private IP Address to a Public IP Address. Do make sure that the VLAN has a Internet Gateway service (not NAT Gateway)
219+
220+
<img src='images/publicip.jpg'>
221+
222+
Now when you pods communicate with resources on the internet, per namespace you will have different source public IP Addresses as well.
223+
224+
<img src='images/result.jpg'>
225+
226+
## Known limitation
227+
228+
The amount of VNICs attached to a compute instance (worker node) is tied to the size of the Compute instance: https://docs.oracle.com/en-us/iaas/Content/Compute/References/computeshapes.htm#vm-standard
229+
230+
If you want to connect to multiple VLANs, keep this limit in mind. There is no restriction to how many EgressIPs you can use within a VLAN.
231+
232+
233+
234+
235+
236+
81.5 KB
Loading
Loading
83.2 KB
Loading
180 KB
Loading
Loading
220 KB
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#====================================================
2+
# Create VLAN and assign to OpenShift Worker Nodes
3+
#====================================================
4+
5+
terraform {
6+
required_providers {
7+
oci = {
8+
source = "oracle/oci"
9+
version = "~> 5.0"
10+
}
11+
}
12+
}
13+
14+
provider "oci" {
15+
}
16+
17+
#====================================================
18+
# Define variables
19+
#====================================================
20+
variable "OpenShiftNameSpace" {
21+
description = "The namespace for the OpenShift environment"
22+
type = string
23+
default = "---OCI Namespace that is being used for your OpenShift Cluster---"
24+
}
25+
26+
variable "compartment_id" {
27+
description = "The compartment OCID in which to create resources"
28+
type = string
29+
default = "---OCID of the Compartment the OpenShift cluster is in---"
30+
}
31+
32+
variable "vcn_id" {
33+
description = "The OCID of the VCN in which the VLAN (subnet) will be created"
34+
type = string
35+
default = "---OCID of the VCN your are using---"
36+
}
37+
38+
variable "vlan_cidr" {
39+
description = "The CIDR block for the VLAN (subnet) to be created"
40+
type = string
41+
default = "10.0.101.0/24" # Change to CIDR range that is part of your VCN and is still available
42+
}
43+
44+
variable "vlan_name" {
45+
description = "Name of the VLAN"
46+
type = string
47+
default = "EgressVLAN"
48+
}
49+
50+
#====================================================
51+
# Create VLAN in existing (specified) VCN
52+
#====================================================
53+
resource "oci_core_vlan" "new_vlan" {
54+
compartment_id = var.compartment_id
55+
vcn_id = var.vcn_id
56+
cidr_block = var.vlan_cidr
57+
display_name = "vlan-${var.vlan_name}"
58+
}
59+
60+
#====================================================
61+
# DATA SOURCE: GET Openshift Worker Nodes based on tag
62+
#====================================================
63+
data "oci_core_instances" "compute_instances" {
64+
compartment_id = var.compartment_id
65+
66+
filter {
67+
# Use defined tag filtering syntax: defined_tags.<namespace>.<tag-key>
68+
name = "defined_tags.${var.OpenShiftNameSpace}.instance-role"
69+
values = ["compute"]
70+
}
71+
}
72+
73+
#====================================================
74+
# LOCALS: Create list of Worker nodes instances
75+
#====================================================
76+
locals {
77+
compute_instances = {
78+
for instance in data.oci_core_instances.compute_instances.instances :
79+
instance.id => instance
80+
}
81+
}
82+
83+
#====================================================
84+
# Attach VLAN to each worker node
85+
#====================================================
86+
resource "oci_core_vnic_attachment" "vlan_vnic" {
87+
for_each = local.compute_instances
88+
instance_id = each.key
89+
create_vnic_details{
90+
display_name = "vlan-${var.vlan_name}"
91+
vlan_id = oci_core_vlan.new_vlan.id
92+
}
93+
}

0 commit comments

Comments
 (0)