Skip to content
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

Simplify HAproxy and upgrade provider #14

Merged
merged 5 commits into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 1 addition & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ A simple kubernetes cluster using Fedora Core OS, Proxmox and k0sctl.

## Dependencies

`Client` refers to the node that will be executing `terraform apply` to create the cluster. The `Raspberry Pi` can be replaced with a VM or a LXC container. The items marked `Optional` are needed only when you want to expose your kubernetes services to the internet via WireGuard.
`Client` refers to the node that will be executing `terraform apply` to create the cluster.

| Dependency | Location |
| ------ | ------ |
Expand All @@ -15,9 +15,6 @@ A simple kubernetes cluster using Fedora Core OS, Proxmox and k0sctl.
| [jq](https://stedolan.github.io/jq/) | Client |
| [Terraform](https://www.terraform.io/) | Client |
| [k0sctl](https://github.com/k0sproject/k0sctl) | Client |
| [HAproxy](http://www.haproxy.org/) | Raspberry Pi |
| [Wireguard](https://www.wireguard.com/) (Optional) | Raspberry Pi & Cloud VPS |
| [Docker](https://docs.docker.com/) (Optional) | Cloud VPS |

## One-time Configuration

Expand All @@ -31,12 +28,6 @@ cd simple-fcos-cluster/scripts
chmod +x ./versions.sh
```

### Create an HA Proxy Server

I've installed `haproxy` on my Raspberry Pi. You can choose to do the same in a LXC container or a VM.

You need to have passwordless SSH access to a user (from the Client node) in this node which has the permissions to modify the file `/etc/haproxy/haproxy.cfg` and permissions to run `sudo systemctl restart haproxy`. An example is covered in this [doc](https://github.com/Naman1997/simple-fcos-cluster/blob/main/docs/HA_Proxy.md).


### Create the terraform.tfvars file

Expand Down
46 changes: 35 additions & 11 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ terraform {
required_providers {
proxmox = {
source = "bpg/proxmox"
version = "0.57.1"
version = "0.61.1"
}
}
}
Expand All @@ -21,9 +21,10 @@ data "external" "versions" {
}

locals {
fcos_version = data.external.versions.result["fcos_version"]
k0s_version = data.external.versions.result["k0s_version"]
iso_url = "https://builds.coreos.fedoraproject.org/prod/streams/stable/builds/${local.fcos_version}/x86_64/fedora-coreos-${local.fcos_version}-qemu.x86_64.qcow2.xz"
ha_proxy_user = "ubuntu"
fcos_version = data.external.versions.result["fcos_version"]
k0s_version = data.external.versions.result["k0s_version"]
iso_url = "https://builds.coreos.fedoraproject.org/prod/streams/stable/builds/${local.fcos_version}/x86_64/fedora-coreos-${local.fcos_version}-qemu.x86_64.qcow2.xz"
}

resource "null_resource" "download_fcos_image" {
Expand Down Expand Up @@ -165,12 +166,20 @@ module "worker_domain" {
target_node = var.TARGET_NODE
}

module "proxy" {
source = "./modules/proxy"
ha_proxy_user = local.ha_proxy_user
DEFAULT_BRIDGE = var.DEFAULT_BRIDGE
TARGET_NODE = var.TARGET_NODE
}


resource "local_file" "haproxy_config" {

depends_on = [
module.master_domain.node,
module.worker_domain.node
module.worker_domain.node,
module.proxy.node
]

content = templatefile("${path.root}/templates/haproxy.tmpl",
Expand All @@ -190,16 +199,16 @@ resource "local_file" "haproxy_config" {
destination = "/etc/haproxy/haproxy.cfg"
connection {
type = "ssh"
host = var.ha_proxy_server
user = var.ha_proxy_user
host = module.proxy.proxy_ipv4_address
user = local.ha_proxy_user
private_key = file("~/.ssh/id_rsa")
}
}

provisioner "remote-exec" {
connection {
host = var.ha_proxy_server
user = var.ha_proxy_user
host = module.proxy.proxy_ipv4_address
user = local.ha_proxy_user
private_key = file("~/.ssh/id_rsa")
}

Expand All @@ -225,7 +234,7 @@ resource "local_file" "k0sctl_config" {
),
"user" = "core",
"k0s_version" = local.k0s_version,
"ha_proxy_server" : var.ha_proxy_server
"ha_proxy_server" : module.proxy.proxy_ipv4_address
}
)
filename = "k0sctl.yaml"
Expand All @@ -239,7 +248,22 @@ resource "null_resource" "setup_cluster" {

provisioner "local-exec" {
command = <<-EOT
k0sctl apply --config k0sctl.yaml --disable-telemetry
MAX_RETRIES=5
RETRY_INTERVAL=10
for ((i = 1; i <= MAX_RETRIES; i++)); do
k0sctl apply --config k0sctl.yaml --disable-telemetry
code=$?
if [ $code -eq 0 ]; then
break
fi
if [ $i -lt $MAX_RETRIES ]; then
echo "Unable to apply config. Retrying in 10 seconds..."
sleep $RETRY_INTERVAL
else
echo "Maximum retries reached. Unable to apply config."
exit 1
fi
done
mkdir -p ~/.kube
k0sctl kubeconfig > ~/.kube/config --disable-telemetry
chmod 600 ~/.kube/config
Expand Down
4 changes: 2 additions & 2 deletions modules/domain/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ terraform {
required_providers {
proxmox = {
source = "bpg/proxmox"
version = "0.57.1"
version = "0.61.1"
}
}
}
Expand All @@ -27,7 +27,7 @@ resource "proxmox_virtual_environment_vm" "node" {

agent {
enabled = true
timeout = "120s"
timeout = "600s"
}

clone {
Expand Down
136 changes: 136 additions & 0 deletions modules/proxy/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
terraform {
required_providers {
proxmox = {
source = "bpg/proxmox"
version = "0.61.1"
}
}
}

data "local_file" "ssh_public_key" {
filename = pathexpand("~/.ssh/id_rsa.pub")
}

resource "proxmox_virtual_environment_file" "cloud_config" {
content_type = "snippets"
datastore_id = "local"
node_name = var.TARGET_NODE

source_raw {
data = <<-EOF
#cloud-config
users:
- default
- name: ${var.ha_proxy_user}
groups:
- sudo
shell: /bin/bash
ssh_authorized_keys:
- ${trimspace(data.local_file.ssh_public_key.content)}
sudo: ALL=(ALL) NOPASSWD:ALL
runcmd:
- apt update -y && apt dist-upgrade -y
- apt install -y qemu-guest-agent haproxy net-tools unattended-upgrades
- timedatectl set-timezone America/Toronto
- systemctl enable qemu-guest-agent
- systemctl enable --now haproxy
- systemctl start qemu-guest-agent
- chown -R ${var.ha_proxy_user}:${var.ha_proxy_user} /etc/haproxy/
- echo "done" > /tmp/cloud-config.done
EOF

file_name = "cloud-config.yaml"
}
}

resource "proxmox_virtual_environment_download_file" "ubuntu_cloud_image" {
content_type = "iso"
datastore_id = "local"
node_name = var.TARGET_NODE

url = "https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img"
}

resource "proxmox_virtual_environment_vm" "node" {
name = "haproxy"
node_name = var.TARGET_NODE

agent {
enabled = true
}

cpu {
cores = 2
}

memory {
dedicated = 2048
}

disk {
datastore_id = "local-lvm"
file_id = proxmox_virtual_environment_download_file.ubuntu_cloud_image.id
interface = "virtio0"
iothread = true
discard = "on"
size = 20
}

initialization {
ip_config {
ipv4 {
address = "dhcp"
}
}

user_data_file_id = proxmox_virtual_environment_file.cloud_config.id
}

network_device {
bridge = var.DEFAULT_BRIDGE
}

provisioner "local-exec" {
command = <<-EOT
n=0
until [ "$n" -ge 10 ]
do
echo "Attempt number: $n"
ssh-keygen -R $ADDRESS
if [ $? -eq 0 ]; then
echo "Successfully removed $ADDRESS"
break
fi
n=$((n+1))
sleep $[ ( $RANDOM % 10 ) + 1 ]s
done
EOT
environment = {
ADDRESS = element(flatten(self.ipv4_addresses), 1)
}
when = destroy
}

provisioner "local-exec" {
command = <<-EOT
n=0
until [ "$n" -ge 10 ]
do
echo "Attempt number: $n"
ssh-keyscan -H $ADDRESS >> ~/.ssh/known_hosts
ssh -q -o StrictHostKeyChecking=no ${var.ha_proxy_user}@$ADDRESS exit < /dev/null
if [ $? -eq 0 ]; then
echo "Successfully added $ADDRESS"
break
fi
n=$((n+1))
sleep $[ ( $RANDOM % 10 ) + 1 ]s
done
EOT
environment = {
ADDRESS = element(flatten(self.ipv4_addresses), 1)
}
when = create
}

}
3 changes: 3 additions & 0 deletions modules/proxy/output.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
output "proxy_ipv4_address" {
value = proxmox_virtual_environment_vm.node.ipv4_addresses[1][0]
}
14 changes: 14 additions & 0 deletions modules/proxy/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
variable "ha_proxy_user" {
description = "Username for proxy VM"
type = string
}

variable "DEFAULT_BRIDGE" {
description = "Bridge to use when creating VMs in proxmox"
type = string
}

variable "TARGET_NODE" {
description = "Target node name in proxmox"
type = string
}
11 changes: 0 additions & 11 deletions varaibles.tf
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,4 @@ variable "worker_config" {
vcpus = number
sockets = number
})
}

# HA Proxy config
variable "ha_proxy_server" {
description = "IP address of server running haproxy"
type = string
}

variable "ha_proxy_user" {
description = "User on ha_proxy_server that can modify '/etc/haproxy/haproxy.cfg' and restart haproxy.service"
type = string
}
Loading