-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP: introduce VLAN for private networking #38
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
## template: jinja | ||
#cloud-config | ||
package_update: true | ||
package_upgrade: true | ||
package_reboot_if_required: true | ||
write_files: | ||
- path: /etc/sysctl.d/10-ip-forwarding.conf | ||
content: | | ||
net.ipv4.ip_forward=1 | ||
- path: /etc/iptables/rules.v4 | ||
content: | | ||
# Generated by iptables-save v1.8.4 on Tue Aug 24 19:16:37 2021 | ||
*filter | ||
:INPUT ACCEPT [0:0] | ||
:FORWARD ACCEPT [0:0] | ||
:OUTPUT ACCEPT [0:0] | ||
COMMIT | ||
# Completed on Tue Aug 24 19:16:37 2021 | ||
# Generated by iptables-save v1.8.4 on Tue Aug 24 19:16:37 2021 | ||
*nat | ||
:PREROUTING ACCEPT [0:0] | ||
:INPUT ACCEPT [0:0] | ||
:OUTPUT ACCEPT [0:0] | ||
:POSTROUTING ACCEPT [0:0] | ||
-A POSTROUTING -o bond0 -j MASQUERADE | ||
COMMIT | ||
# Completed on Tue Aug 24 19:16:37 2021 | ||
- path: /etc/iptables/rules.v6 | ||
content: | | ||
# Generated by ip6tables-save v1.8.4 on Tue Aug 24 19:16:37 2021 | ||
*filter | ||
:INPUT ACCEPT [0:0] | ||
:FORWARD ACCEPT [0:0] | ||
:OUTPUT ACCEPT [0:0] | ||
COMMIT | ||
- path: /etc/network/interfaces | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is certainly not correct for non-Debian based systems There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As a starting point for changes to consider, ChatGPT suggests: ...
- path: /etc/sysconfig/iptables
content: |
... same
- path: /etc/sysconfig/ip6tables
content: |
... same
- path: /etc/sysconfig/network-scripts/ifcfg-bond0.${metal_vlan_id}
content: |
DEVICE=bond0.${metal_vlan_id}
BOOTPROTO=static
ONBOOT=yes
IPADDR=${address}
NETMASK=${netmask}
VLAN=yes
... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With a little more prodding (again, this is just to serve as a pointer in the general direction of what may be needed): - path: /etc/sysconfig/network-scripts/ifcfg-bond0.${metal_vlan_id}
content: |
DEVICE=bond0.${metal_vlan_id}
NAME=bond0.${metal_vlan_id}
TYPE=Bond
BONDING_MASTER=yes
IPADDR=${address}
NETMASK=${netmask}
ONBOOT=yes
BOOTPROTO=none
BONDING_OPTS="mode=1 miimon=100"
NM_CONTROLLED="no"
- path: /etc/sysconfig/network-scripts/ifcfg-eth0
content: |
DEVICE=eth0
NAME=bond0-slave
TYPE=Ethernet
ONBOOT=yes
BOOTPROTO=none
MASTER=bond0
SLAVE=yes
NM_CONTROLLED="no"
- path: /etc/sysconfig/network-scripts/ifcfg-eth1
content: |
DEVICE=eth1
NAME=bond0-slave
TYPE=Ethernet
ONBOOT=yes
BOOTPROTO=none
MASTER=bond0
SLAVE=yes
NM_CONTROLLED="no"
...
runcmd:
- modprobe bonding
- ifup eth0
- ifup eth1
- ifup bond0.${metal_vlan_id}
... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know if we'll have eth0/eth1 names. On the bootstrap node this may be tricky unless we can disable predictable names for the first boot (Arch guidance may have relevance: https://wiki.archlinux.org/title/Network_configuration#Revert_to_traditional_interface_names) We'll also need to add kernel command line args for the IPXE scripts to have them come up bonded, which may also need to include There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alternatively, |
||
append: true | ||
content: | | ||
|
||
auto bond0.${metal_vlan_id} | ||
iface bond0.${metal_vlan_id} inet static | ||
pre-up sleep 5 | ||
address ${address} | ||
netmask ${netmask} | ||
vlan-raw-device bond0 | ||
- path: /etc/dnsmasq.d/openshift.config | ||
append: true | ||
content: | | ||
bind-interfaces | ||
interface=bond0.${metal_vlan_id} | ||
dhcp-range=${host_dhcp_start},${host_dhcp_end},${lease_time} | ||
packages: | ||
- iptables | ||
- iptables-services | ||
- dnsmasq | ||
runcmd: | ||
- sysctl -p /etc/sysctl.d/10-ip-forwarding.conf | ||
- systemctl restart networking | ||
- systemctl restart dnsmasq |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,7 +16,38 @@ resource "equinix_metal_device" "lb" { | |
operating_system = var.operating_system | ||
billing_cycle = var.billing_cycle | ||
project_id = var.project_id | ||
user_data = file("${path.module}/assets/user_data_${var.operating_system}.sh") | ||
user_data = data.cloudinit_config.lb.rendered | ||
} | ||
|
||
|
||
resource "equinix_metal_port" "lb_bond0" { | ||
port_id = [for p in equinix_metal_device.lb.ports : p.id if p.name == "bond0"][0] | ||
layer2 = false | ||
bonded = true | ||
vlan_ids = [var.vlan] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. rename to metal_vlan for consistency |
||
} | ||
|
||
|
||
data "cloudinit_config" "lb" { | ||
gzip = false | ||
base64_encode = false | ||
|
||
part { | ||
filename = "cloud-config.cfg" | ||
content = templatefile("${path.module}/assets/cloudinit_${var.operating_system}.cfg.tpl", | ||
{ | ||
metal_vlan_id = 1000, | ||
address = cidrhost(var.cluster_subnet, 2), | ||
netmask = cidrnetmask(var.cluster_subnet), | ||
host_dhcp_start = cidrhost(var.cluster_subnet, 3), | ||
host_dhcp_end = cidrhost(var.cluster_subnet, 15), | ||
lease_time = "infinite", | ||
}) | ||
} | ||
part { | ||
filename = "user-data" | ||
content = file("${path.module}/assets/user_data_${var.operating_system}.sh") | ||
} | ||
} | ||
|
||
resource "null_resource" "dircheck" { | ||
|
@@ -72,7 +103,7 @@ resource "null_resource" "ipxe_files" { | |
|
||
content = templatefile("${path.module}/assets/ipxe.tpl", { | ||
node_type = each.value | ||
bastion_ip = equinix_metal_device.lb.access_public_ipv4 | ||
bastion_ip = equinix_metal_device.lb.access_private_ipv4 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. access_private_ipv4 needs to be replaced with an address from the VRF range, 192.168.100.2 |
||
ocp_version = var.ocp_version | ||
ocp_version_zstream = var.ocp_version_zstream | ||
}) | ||
|
@@ -107,7 +138,7 @@ resource "null_resource" "ignition_append_files" { | |
|
||
content = templatefile("${path.module}/assets/ignition-append.json.tpl", { | ||
node_type = each.value | ||
bastion_ip = equinix_metal_device.lb.access_public_ipv4 | ||
bastion_ip = equinix_metal_device.lb.access_private_ipv4 | ||
cluster_name = var.cluster_name | ||
cluster_basedomain = var.cluster_basedomain | ||
}) | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,60 @@ | ||||||
locals { | ||||||
vlan_id = var.create_vlan ? element(equinix_metal_vlan.openshift[*].id, 0) : element(data.equinix_metal_vlan.openshift[*].id, 0) | ||||||
vxlan = var.create_vlan ? element(equinix_metal_vlan.openshift[*].vxlan, 0) : element(data.equinix_metal_vlan.openshift[*].vxlan, 0) | ||||||
vrf_id = var.create_vrf ? element(equinix_metal_vrf.openshift[*].id, 0) : element(data.equinix_metal_vrf.openshift[*].id, 0) | ||||||
} | ||||||
|
||||||
|
||||||
# This generates a random suffix to avoid VRF name | ||||||
# collisions when multiple clusters are deployed to | ||||||
# an existing Metal project | ||||||
resource "random_string" "vrf_name_suffix" { | ||||||
length = 5 | ||||||
special = false | ||||||
} | ||||||
|
||||||
|
||||||
resource "equinix_metal_vlan" "openshift" { | ||||||
count = var.create_vlan ? 1 : 0 | ||||||
project_id = var.project_id | ||||||
description = var.metal_vlan_description | ||||||
metro = var.metal_metro | ||||||
} | ||||||
|
||||||
|
||||||
data "equinix_metal_vlan" "openshift" { | ||||||
count = var.create_vlan ? 0 : 1 | ||||||
project_id = var.project_id | ||||||
vxlan = var.metal_vlan_id | ||||||
} | ||||||
|
||||||
resource "equinix_metal_vrf" "openshift" { | ||||||
count = var.create_vrf ? 1 : 0 | ||||||
description = "VRF with ASN 65000 and a pool of address space that includes 192.168.100.0/25" | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
name = "openshift-vrf-${random_string.vrf_name_suffix.result}" | ||||||
metro = var.metal_metro | ||||||
local_asn = "65000" | ||||||
ip_ranges = [var.cluster_subnet] | ||||||
project_id = var.project_id | ||||||
} | ||||||
|
||||||
data "equinix_metal_vrf" "openshift" { | ||||||
count = var.create_vrf ? 0 : 1 | ||||||
vrf_id = var.vrf_id | ||||||
} | ||||||
|
||||||
resource "equinix_metal_reserved_ip_block" "openshift" { | ||||||
description = "Reserved IP block (${var.cluster_subnet}) taken from on of the ranges in the VRF's pool of address space." | ||||||
project_id = var.project_id | ||||||
metro = var.metal_metro | ||||||
type = "vrf" | ||||||
vrf_id = local.vrf_id | ||||||
cidr = split("/", var.cluster_subnet)[1] | ||||||
network = cidrhost(var.cluster_subnet, 0) | ||||||
} | ||||||
|
||||||
resource "equinix_metal_gateway" "gateway" { | ||||||
project_id = var.project_id | ||||||
vlan_id = local.vlan_id | ||||||
ip_reservation_id = equinix_metal_reserved_ip_block.openshift.id | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
output "vrf_id" { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This entire module needs a |
||
value = local.vrf_id | ||
} | ||
|
||
output "vlan_id" { | ||
value = local.vlan_id | ||
} | ||
|
||
output "reserved_ip_block_id" { | ||
value = equinix_metal_reserved_ip_block.openshift.id | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
variable "cluster_subnet" { default = "192.168.100.0/22" } | ||
variable "metal_metro" { default = "da" } | ||
variable "create_vrf" { default = true } | ||
variable "project_id" {} | ||
|
||
variable "create_vlan" { | ||
type = bool | ||
default = true | ||
description = "Whether to create a new VLAN for this project." | ||
} | ||
variable "metal_vlan_id" { | ||
type = number | ||
default = null | ||
description = "ID of the VLAN you wish to use." | ||
} | ||
|
||
variable "metal_vlan_description" { | ||
type = string | ||
default = "openshift-demo" | ||
description = "Description to add to created VLAN." | ||
} | ||
|
||
|
||
variable "vrf_id" { | ||
type = string | ||
default = null | ||
description = "ID of the VRF you wish to use." | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
terraform { | ||
required_providers { | ||
equinix = { | ||
source = "equinix/equinix" | ||
version = "~> 1.14" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider bumping all Equinix provider version deps to |
||
} | ||
null = { | ||
source = "hashicorp/null" | ||
} | ||
} | ||
required_version = ">= 1.0.0" | ||
provider_meta "equinix" { | ||
module_name = "equinix-metal-openshift-on-baremetal/bastion" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,5 +8,9 @@ resource "equinix_metal_device" "node" { | |
count = var.node_count | ||
billing_cycle = "hourly" | ||
project_id = var.project_id | ||
ip_address { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be removed. There was a starting thought that all nodes could use the EM Private IPs, but DHCP management needs, configuring a gateway, meant that VRF and DHCP services running on the bastion would be a better fit. |
||
type = "private_ipv4" | ||
cidr = 30 | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
output "node_ip" { | ||
value = equinix_metal_device.node.*.access_public_ipv4 | ||
value = equinix_metal_device.node.*.access_private_ipv4 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This may pose a problem. |
||
} | ||
|
||
output "finished" { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,6 +32,11 @@ variable "metal_project_id" { | |
description = "Your Equinix Metal Project ID" | ||
} | ||
|
||
variable "metal_vlan" { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We'll want to allow for existing VLANs to be plumbed in. The network module already supports that. |
||
description = "Your Equinix Metal VLAN (ex. 1000)" | ||
default = 1000 | ||
} | ||
|
||
variable "bastion_operating_system" { | ||
description = "Your preferred bastion operating systems (RHEL or CentOS)" | ||
default = "rhel_7" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: create an equivalent RHEL 7 config