Skip to content
This repository has been archived by the owner on Jun 29, 2022. It is now read-only.

Commit

Permalink
Add Tinkerbell platform
Browse files Browse the repository at this point in the history
This commit adds Tinkerbell as a supported platform by the Lokomotive.

The Terraform code consumes newly introduced controller and worker
Terraform modules, which reduces the amount of code required for
introducing this new platform.

The commit currently lacks several parts, which will be added at later
stage:
- Unit tests
- Configuration validation rules
- CI implementation
- Reference documentation
- Quick start guide

Closes #382.

Signed-off-by: Mateusz Gozdek <[email protected]>
  • Loading branch information
invidian committed Oct 12, 2020
1 parent 4e6c95f commit cd1cc65
Show file tree
Hide file tree
Showing 40 changed files with 2,513 additions and 51 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# Self-hosted Kubernetes assets (kubeconfig, manifests)
module "bootkube" {
source = "../../bootkube"
source = "../../../bootkube"

cluster_name = var.cluster_name
api_servers = [format("%s.%s", var.cluster_name, var.dns_zone)]
etcd_servers = module.controller.etcd_servers
api_servers_external = var.ip_addresses
api_servers_ips = var.ip_addresses
etcd_servers = module.controller[0].etcd_servers
asset_dir = var.asset_dir
network_mtu = var.network_mtu
pod_cidr = var.pod_cidr
Expand All @@ -15,7 +17,7 @@ module "bootkube" {

certs_validity_period_hours = var.certs_validity_period_hours

bootstrap_tokens = concat([module.controller.worker_bootstrap_token], var.worker_bootstrap_tokens)
bootstrap_tokens = concat(module.controller.*.bootstrap_token, var.worker_bootstrap_tokens)
enable_tls_bootstrap = true
disable_self_hosted_kubelet = false
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
module "controller" {
source = "../../controller"
source = "../../../controller"

count = var.node_count

cluster_name = var.cluster_name
controllers_count = var.node_count
dns_zone = var.dns_zone
node_count = var.node_count
count_index = count.index
cluster_dns_service_ip = module.bootkube.cluster_dns_service_ip
ssh_keys = var.ssh_keys
clc_snippets = var.clc_snippets
cluster_domain_suffix = var.cluster_domain_suffix
clc_snippet_index = <<EOF
host_dns_ip = var.host_dns_ip
apiserver = format("%s.%s", var.cluster_name, var.dns_zone)
ca_cert = module.bootkube.ca_cert

clc_snippets = concat(var.clc_snippets, [
<<EOF
storage:
files:
- path: /etc/hostname
filesystem: root
mode: 0644
contents:
inline: |
controller%d
${var.cluster_name}-controller-${count.index}
EOF
,
])
}

resource "tinkerbell_template" "main" {
Expand All @@ -26,9 +35,8 @@ resource "tinkerbell_template" "main" {
name = "${var.cluster_name}-controller-${count.index}"

content = templatefile("${path.module}/templates/flatcar-install.tmpl", {
ignition_config = module.controller.clc_configs[count.index]
ignition_config = module.controller[count.index].clc_config
flatcar_install_base_url = var.flatcar_install_base_url
machine = "${var.cluster_name}_controller_${count.index}"
os_version = var.os_version
os_channel = var.os_channel
})
Expand All @@ -38,7 +46,7 @@ resource "tinkerbell_workflow" "main" {
count = var.node_count

hardwares = <<EOF
{"${var.cluster_name}_controller_${count.index}": "${var.ip_addresses[count.index]}"}
{"device_1": "${var.ip_addresses[count.index]}"}
EOF
template = tinkerbell_template.main[count.index].id
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ output "kubeconfig-admin" {
value = module.bootkube.kubeconfig-admin
}

output "ca_cert" {
value = module.bootkube.ca_cert
}

output "apiserver" {
value = format("%s.%s", var.cluster_name, var.dns_zone)
}

# values.yaml content for all deployed charts.
output "pod-checkpointer_values" {
value = module.bootkube.pod-checkpointer_values
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ resource "null_resource" "copy-controller-secrets" {
}

provisioner "file" {
content = module.bootkube.kubeconfig-kubelet
content = module.controller[count.index].bootstrap_kubeconfig
destination = "$HOME/kubeconfig"
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: flatcar-install
global_timeout: 1800
tasks:
- name: "flatcar-install"
worker: "{{.${machine}}}"
worker: "{{.device_1}}"
volumes:
- /dev:/dev
- /statedir:/statedir
Expand Down Expand Up @@ -34,7 +34,7 @@ tasks:
- ${flatcar_install_base_url}
%{~ endif ~}
- name: "reboot" # This task shouldn't really be there, but there is no other way to reboot the worker into target OS in Tinkerbell for now.
image: alpine
image: flatcar-install
command:
- sh
- -c
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,9 @@ variable "worker_bootstrap_tokens" {
description = "List of token-id and token-secret of each node."
type = list(any)
}

variable "host_dns_ip" {
type = string
description = "IP address of DNS server to configure on the nodes."
default = "8.8.8.8"
}
49 changes: 49 additions & 0 deletions assets/terraform-modules/platforms/tinkerbell/workerpool/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
module "worker" {
source = "../../../worker"

count = var.node_count
count_index = count.index

cluster_dns_service_ip = var.cluster_dns_service_ip
ssh_keys = var.ssh_keys
cluster_domain_suffix = var.cluster_domain_suffix
host_dns_ip = var.host_dns_ip
ca_cert = var.ca_cert
apiserver = var.apiserver

clc_snippets = concat(var.clc_snippets, [
<<EOF
storage:
files:
- path: /etc/hostname
filesystem: root
mode: 0644
contents:
inline: |
${var.cluster_name}-worker-${var.name}-${count.index}
EOF
,
])
}

resource "tinkerbell_template" "main" {
count = var.node_count

name = "${var.cluster_name}-worker-${var.name}-${count.index}"

content = templatefile("${path.module}/templates/flatcar-install.tmpl", {
ignition_config = module.worker[count.index].clc_config
flatcar_install_base_url = var.flatcar_install_base_url
os_version = var.os_version
os_channel = var.os_channel
})
}

resource "tinkerbell_workflow" "main" {
count = var.node_count

hardwares = <<EOF
{"device_1": "${var.ip_addresses[count.index]}"}
EOF
template = tinkerbell_template.main[count.index].id
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
output "bootstrap_tokens" {
value = module.worker.*.bootstrap_token
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
variable "cluster_name" {
type = string
}

variable "name" {
type = string
}

variable "ip_addresses" {
type = list(string)
}

variable "flatcar_install_base_url" {
type = string
default = ""
}

variable "os_version" {
type = string
default = ""
}

variable "os_channel" {
type = string
default = ""
}

variable "kubeconfig" {
type = string
description = "Content of kubelet's kubeconfig file"
}

# Required variables.
variable "ssh_keys" {
type = list(string)
description = "List of SSH public keys for user `core`. Each element must be specified in a valid OpenSSH public key format, as defined in RFC 4253 Section 6.6, e.g. 'ssh-rsa AAAAB3N...'."
default = []
}

# Optional variables.
variable "node_count" {
type = number
description = "Number of nodes to create."
default = 1
}

variable "cluster_dns_service_ip" {
type = string
description = "IP address of cluster DNS Service. Passed to kubelet as --cluster_dns parameter."
default = "10.3.0.10"
}

variable "clc_snippets" {
type = list(string)
description = "Extra CLC snippets to include in the configuration."
default = []
}

variable "cluster_domain_suffix" {
type = string
description = "Cluster domain suffix. Passed to kubelet as --cluster_domain flag."
default = "cluster.local"
}

variable "host_dns_ip" {
type = string
description = "IP address of DNS server to configure on the nodes."
default = "8.8.8.8"
}

variable "ca_cert" {
description = "Kubernetes CA certificate needed in the kubeconfig file."
type = string
}

variable "apiserver" {
description = "Apiserver private endpoint needed in the kubeconfig file."
type = string
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Terraform version and plugin versions

terraform {
required_version = ">= 0.13"

required_providers {
tinkerbell = {
source = "tinkerbell/tinkerbell"
version = "0.1.0"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
state
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
SET ROLE tinkerbell;

CREATE TABLE IF NOT EXISTS hardware (
id UUID UNIQUE
, inserted_at TIMESTAMPTZ
, deleted_at TIMESTAMPTZ
, data JSONB
);

CREATE INDEX IF NOT EXISTS idx_id ON hardware (id);
CREATE INDEX IF NOT EXISTS idx_deleted_at ON hardware (deleted_at NULLS FIRST);
CREATE INDEX IF NOT EXISTS idxgin_type ON hardware USING GIN (data JSONB_PATH_OPS);

CREATE TABLE IF NOT EXISTS template (
id UUID UNIQUE NOT NULL
, name VARCHAR(200) NOT NULL
, created_at TIMESTAMPTZ
, updated_at TIMESTAMPTZ
, deleted_at TIMESTAMPTZ
, data BYTEA

CONSTRAINT CK_name CHECK (name ~ '^[a-zA-Z0-9_-]*$')
);

CREATE INDEX IF NOT EXISTS idx_tid ON template (id);
CREATE INDEX IF NOT EXISTS idx_tdeleted_at ON template (deleted_at NULLS FIRST);

CREATE TABLE IF NOT EXISTS workflow (
id UUID UNIQUE NOT NULL
, template UUID NOT NULL
, devices JSONB NOT NULL
, created_at TIMESTAMPTZ
, updated_at TIMESTAMPTZ
, deleted_at TIMESTAMPTZ
);

CREATE INDEX IF NOT EXISTS idx_wid ON workflow (id);
CREATE INDEX IF NOT EXISTS idx_wdeleted_at ON workflow (deleted_at NULLS FIRST);

CREATE TABLE IF NOT EXISTS workflow_state (
workflow_id UUID UNIQUE NOT NULL
, current_task_name VARCHAR(200)
, current_action_name VARCHAR(200)
, current_action_state SMALLINT
, current_worker VARCHAR(200)
, action_list JSONB
, current_action_index int
, total_number_of_actions INT
);

CREATE INDEX IF NOT EXISTS idx_wfid ON workflow_state (workflow_id);

CREATE TABLE IF NOT EXISTS workflow_event (
workflow_id UUID NOT NULL
, worker_id UUID NOT NULL
, task_name VARCHAR(200)
, action_name VARCHAR(200)
, execution_time int
, message VARCHAR(200)
, status SMALLINT
, created_at TIMESTAMPTZ
);

CREATE INDEX IF NOT EXISTS idx_event ON workflow_event (created_at);

CREATE TABLE IF NOT EXISTS workflow_worker_map (
workflow_id UUID NOT NULL
, worker_id UUID NOT NULL
);

CREATE TABLE IF NOT EXISTS workflow_data (
workflow_id UUID NOT NULL
, version INT
, metadata JSONB
, data JSONB
);
Loading

0 comments on commit cd1cc65

Please sign in to comment.