Skip to content

Commit 9b683d8

Browse files
committed
feat: added Cilium CNI.
This is a reimplementation of #722. Signed-off-by: Ali Mukadam <[email protected]>
1 parent 3d96325 commit 9b683d8

File tree

7 files changed

+318
-0
lines changed

7 files changed

+318
-0
lines changed

module-extensions.tf

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@ module "extensions" {
2424
cni_type = var.cni_type
2525
pods_cidr = var.pods_cidr
2626

27+
# CNI: Cilium
28+
cilium_install = var.cilium_install
29+
cilium_reapply = var.cilium_reapply
30+
cilium_namespace = var.cilium_namespace
31+
cilium_helm_version = var.cilium_helm_version
32+
cilium_helm_values = var.cilium_helm_values
33+
cilium_helm_values_files = var.cilium_helm_values_files
34+
35+
2736
# CNI: Multus
2837
multus_install = var.multus_install
2938
multus_namespace = var.multus_namespace

module-operator.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ module "operator" {
5858
availability_domain = coalesce(var.operator_availability_domain, lookup(local.ad_numbers_to_names, local.ad_numbers[0]))
5959
cloud_init = var.operator_cloud_init
6060
image_id = local.operator_image_id
61+
install_cilium = var.cilium_install
6162
install_helm = var.operator_install_helm
6263
install_k9s = var.operator_install_k9s
6364
install_kubectx = var.operator_install_kubectx

modules/extensions/cilium.tf

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
# Copyright (c) 2023 Oracle Corporation and/or its affiliates.
2+
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl
3+
4+
locals {
5+
cilium_helm_crds_file = join("/", [local.yaml_manifest_path, "cilium.crds.yaml"])
6+
cilium_helm_manifest_file = join("/", [local.yaml_manifest_path, "cilium.manifest.yaml"])
7+
cilium_helm_values_file = join("/", [local.yaml_manifest_path, "cilium.values.yaml"])
8+
cilium_net_attach_def_file = join("/", [local.yaml_manifest_path, "cilium.net_attach_def.yaml"])
9+
cilium_veth_config_map_file = join("/", [local.yaml_manifest_path, "cilium.cni_config_map.yaml"])
10+
11+
cilium_helm_crds = one(data.helm_template.cilium[*].crds)
12+
cilium_helm_manifest = one(data.helm_template.cilium[*].manifest)
13+
14+
cilium_vxlan_cni = {
15+
install = true
16+
chainingMode = "none"
17+
exclusive = true # !var.multus_install
18+
}
19+
20+
# TODO Support Flannel w/ generic-veth & tunnel disabled
21+
cilium_tunnel = "vxlan" # var.cni_type == "flannel" ? "disabled" : "vxlan"
22+
cilium_flannel_cni = {
23+
install = true
24+
chainingMode = "generic-veth"
25+
configMap = "cni-configuration"
26+
customConf = var.cni_type == "flannel"
27+
exclusive = !var.multus_install
28+
}
29+
30+
cilium_helm_values = {
31+
annotateK8sNode = true
32+
cluster = { name = "oke-${var.state_id}" }
33+
clustermesh = { useAPIServer = true }
34+
cni = local.cilium_vxlan_cni
35+
containerRuntime = { integration = "crio" }
36+
installIptablesRules = true
37+
installNoConntrackIptablesRules = false
38+
ipam = { mode = "kubernetes" }
39+
ipv4NativeRoutingCIDR = element(var.vcn_cidrs, 0)
40+
kubeProxyReplacement = "disabled"
41+
pmtuDiscovery = { enabled = true }
42+
tunnel = local.cilium_tunnel
43+
44+
hubble = {
45+
metrics = {
46+
dashboards = { enabled = var.prometheus_install }
47+
# serviceMonitor = { enabled = var.prometheus_enabled }
48+
}
49+
relay = { enabled = true }
50+
ui = { enabled = true }
51+
}
52+
53+
k8s = {
54+
requireIPv4PodCIDR = true # wait for Kubernetes to provide the PodCIDR (ipam kubernetes)
55+
enableIPv4Masquerade = true # var.cni_type != "flannel" # masquerade IPv4 traffic leaving the node from endpoints
56+
}
57+
58+
# Prometheus metrics
59+
metrics = {
60+
dashboards = { enabled = var.prometheus_install }
61+
# # serviceMonitor = { enabled = var.prometheus_enabled }
62+
}
63+
64+
prometheus = {
65+
enabled = var.prometheus_install
66+
# serviceMonitor = { enabled = var.prometheus_enabled }
67+
}
68+
69+
operator = {
70+
prometheus = {
71+
enabled = var.prometheus_install
72+
# serviceMonitor = { enabled = var.prometheus_enabled }
73+
}
74+
}
75+
}
76+
77+
cilium_net_attach_def_conf = {
78+
cniVersion = "0.3.1"
79+
name = "cilium"
80+
plugins = [
81+
{
82+
cniVersion = "0.3.1"
83+
name = "cilium"
84+
type = "cilium-cni"
85+
},
86+
{
87+
name = "cilium-sbr"
88+
type = "sbr"
89+
}
90+
],
91+
}
92+
93+
cilium_net_attach_def = {
94+
apiVersion = "k8s.cni.cncf.io/v1"
95+
kind = "NetworkAttachmentDefinition"
96+
metadata = { name = "cilium" }
97+
spec = { config = jsonencode(local.cilium_net_attach_def_conf) }
98+
}
99+
100+
cilium_veth_conf = {
101+
cniVersion = "0.3.1"
102+
name = "cbr0"
103+
"plugins" = [
104+
{
105+
type = "flannel"
106+
delegate = {
107+
hairpinMode = true
108+
isDefaultGateway = true
109+
}
110+
},
111+
{
112+
type = "portmap"
113+
capabilities = { portMappings = true }
114+
},
115+
{ type = "cilium-cni" },
116+
]
117+
}
118+
119+
cilium_veth_config_map = {
120+
apiVersion = "v1"
121+
kind = "ConfigMap"
122+
metadata = {
123+
name = "cni-configuration"
124+
namespace = var.cilium_namespace
125+
}
126+
data = { "cni-config" = jsonencode(local.cilium_veth_conf) }
127+
}
128+
129+
cilium_net_attach_def_yaml = yamlencode(local.cilium_net_attach_def)
130+
cilium_veth_config_map_yaml = yamlencode(local.cilium_veth_config_map)
131+
cilium_helm_values_yaml = yamlencode(local.cilium_helm_values)
132+
}
133+
134+
data "helm_template" "cilium" {
135+
count = var.cilium_install ? 1 : 0
136+
chart = "cilium"
137+
repository = "https://helm.cilium.io"
138+
version = var.cilium_helm_version
139+
kube_version = var.kubernetes_version
140+
141+
name = "cilium"
142+
namespace = var.cilium_namespace
143+
create_namespace = true
144+
include_crds = true
145+
skip_tests = true
146+
values = concat(
147+
[local.cilium_helm_values_yaml],
148+
[for path in var.cilium_helm_values_files : file(path)],
149+
)
150+
151+
lifecycle {
152+
precondition {
153+
condition = alltrue([for path in var.cilium_helm_values_files : fileexists(path)])
154+
error_message = format("Missing Helm values files in configuration: %s",
155+
jsonencode([for path in var.cilium_helm_values_files : path if !fileexists(path)])
156+
)
157+
}
158+
}
159+
}
160+
161+
resource "null_resource" "cilium" {
162+
count = var.cilium_install ? 1 : 0
163+
depends_on = [null_resource.prometheus]
164+
165+
triggers = {
166+
helm_version = var.cilium_helm_version
167+
crds_md5 = try(md5(join("\n", local.cilium_helm_crds)), null)
168+
manifest_md5 = try(md5(local.cilium_helm_manifest), null)
169+
reapply = var.cilium_reapply ? uuid() : null
170+
}
171+
172+
connection {
173+
bastion_host = var.bastion_host
174+
bastion_user = var.bastion_user
175+
bastion_private_key = var.ssh_private_key
176+
host = var.operator_host
177+
user = var.operator_user
178+
private_key = var.ssh_private_key
179+
timeout = "40m"
180+
type = "ssh"
181+
}
182+
183+
provisioner "remote-exec" {
184+
inline = ["mkdir -p ${local.yaml_manifest_path}"]
185+
}
186+
187+
provisioner "file" {
188+
content = join("\n", local.cilium_helm_crds)
189+
destination = local.cilium_helm_crds_file
190+
}
191+
192+
provisioner "file" {
193+
content = local.cilium_helm_manifest
194+
destination = local.cilium_helm_manifest_file
195+
}
196+
197+
provisioner "file" {
198+
content = local.cilium_helm_values_yaml
199+
destination = local.cilium_helm_values_file
200+
}
201+
202+
provisioner "file" {
203+
content = local.cilium_net_attach_def_yaml
204+
destination = local.cilium_net_attach_def_file
205+
}
206+
207+
provisioner "file" {
208+
content = local.cilium_veth_config_map_yaml
209+
destination = local.cilium_veth_config_map_file
210+
}
211+
212+
provisioner "remote-exec" {
213+
inline = [for c in compact([
214+
# Create namespace if non-standard and missing
215+
(contains(["kube-system", "default"], var.cilium_namespace) ? null
216+
: format(local.kubectl_create_missing_ns, var.cilium_namespace)),
217+
218+
# Install CRDs first
219+
format(local.kubectl_apply_server_ns_file, var.cilium_namespace, local.cilium_helm_crds_file),
220+
221+
# Install full manifest
222+
format(local.kubectl_apply_ns_file, var.cilium_namespace, local.cilium_helm_manifest_file),
223+
224+
# Install Network Attachment Definition when Multus is enabled
225+
# var.multus_install ? format(local.kubectl_apply_file, local.cilium_net_attach_def_file) : null,
226+
227+
# Install CNI ConfigMap for Flannel
228+
# var.cni_type == "flannel" ? format(local.kubectl_apply_file, local.cilium_veth_config_map_file) : null,
229+
]) : format(local.output_log, c, "cilium")
230+
]
231+
}
232+
233+
lifecycle {
234+
precondition {
235+
condition = var.cni_type == "flannel"
236+
error_message = "Incompatible cni_type for installation - must be 'flannel'."
237+
}
238+
}
239+
}

modules/extensions/variables.tf

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ variable "vcn_cidrs" { type = list(string) }
2020
variable "cni_type" { type = string }
2121
variable "pods_cidr" { type = string }
2222

23+
# CNI: Cilium
24+
variable "cilium_install" { type = bool }
25+
variable "cilium_reapply" { type = bool }
26+
variable "cilium_namespace" { type = string }
27+
variable "cilium_helm_version" { type = string }
28+
variable "cilium_helm_values" { type = map(string) }
29+
variable "cilium_helm_values_files" { type = list(string) }
30+
2331
# CNI: Multus
2432
variable "multus_install" { type = bool }
2533
variable "multus_namespace" { type = string }

modules/operator/cloudinit.tf

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ locals {
1212
developer_EPEL = "${local.baserepo}_developer_EPEL"
1313
olcne17 = "${local.baserepo}_olcne17"
1414
developer_olcne = "${local.baserepo}_developer_olcne"
15+
arch_amd = "amd64"
16+
arch_arm = "aarch64"
1517

1618
}
1719

@@ -154,6 +156,25 @@ data "cloudinit_config" "operator" {
154156
}
155157
}
156158

159+
# Optional cilium cli installation
160+
dynamic "part" {
161+
for_each = var.install_cilium ? [1] : []
162+
content {
163+
content_type = "text/cloud-config"
164+
content = jsonencode({
165+
runcmd = [
166+
"CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/master/stable.txt)",
167+
"CLI_ARCH=${local.arch_amd}",
168+
"if [ '$(uname -m)' = ${local.arch_arm} ]; then CLI_ARCH=${local.arch_arm}; fi",
169+
"curl -L --fail --remote-name-all https://github.com/cilium/cilium-cli/releases/download/$CILIUM_CLI_VERSION/cilium-linux-$CLI_ARCH.tar.gz",
170+
"tar xzvfC cilium-linux-$CLI_ARCH.tar.gz /usr/local/bin"
171+
]
172+
})
173+
filename = "20-cilium.yml"
174+
merge_type = local.default_cloud_init_merge_type
175+
}
176+
}
177+
157178
# Write user bashrc to filesystem
158179
part {
159180
content_type = "text/cloud-config"

modules/operator/variables.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ variable "assign_dns" { type = bool }
1414
variable "availability_domain" { type = string }
1515
variable "cloud_init" { type = list(map(string)) }
1616
variable "image_id" { type = string }
17+
variable "install_cilium" { type = bool }
1718
variable "install_helm" { type = bool }
1819
variable "install_k9s" { type = bool }
1920
variable "install_kubectx" { type = bool }

variables-extensions.tf

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,44 @@
11
# Copyright (c) 2017, 2023 Oracle Corporation and/or its affiliates.
22
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl
33

4+
# CNI: Cilium
5+
6+
variable "cilium_install" {
7+
default = false
8+
description = "Whether to deploy the Cilium Helm chart. May only be enabled when cni_type = 'flannel'. See https://docs.cilium.io. NOTE: Provided only as a convenience and not supported by or sourced from Oracle - use at your own risk."
9+
type = bool
10+
}
11+
12+
variable "cilium_reapply" {
13+
default = false
14+
description = "Whether to force reapply of the chart when no changes are detected, e.g. with state modified externally."
15+
type = bool
16+
}
17+
18+
variable "cilium_namespace" {
19+
default = "kube-system"
20+
description = "Kubernetes namespace for deployed resources."
21+
type = string
22+
}
23+
24+
variable "cilium_helm_version" {
25+
default = "1.14.4"
26+
description = "Version of the Helm chart to install. List available releases using `helm search repo [keyword] --versions`."
27+
type = string
28+
}
29+
30+
variable "cilium_helm_values" {
31+
default = {}
32+
description = "Map of individual Helm chart values. See https://registry.terraform.io/providers/hashicorp/helm/latest/docs/data-sources/template."
33+
type = map(string)
34+
}
35+
36+
variable "cilium_helm_values_files" {
37+
default = []
38+
description = "Paths to a local YAML files with Helm chart values (as with `helm install -f` which supports multiple). Generate with defaults using `helm show values [CHART] [flags]`."
39+
type = list(string)
40+
}
41+
442
# CNI: Multus
543

644
variable "multus_install" {
@@ -328,3 +366,4 @@ variable "gatekeeper_helm_values_files" {
328366
description = "Paths to a local YAML files with Helm chart values (as with `helm install -f` which supports multiple). Generate with defaults using `helm show values [CHART] [flags]`."
329367
type = list(string)
330368
}
369+

0 commit comments

Comments
 (0)