├── .gitignore ├── README.md ├── multipass.tf ├── multipass ├── data.tf ├── main.tf ├── output.tf ├── rook.tf ├── script │ ├── cloud-init.yaml │ ├── kube-init.sh │ └── multipass.py ├── template.tf ├── variables.tf └── workers.tf └── reset.sh /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | __pycache__ 3 | .ipynb_checkpoints/ 4 | *.log 5 | .DS_Store 6 | .terraform/ 7 | terraform.tfstate 8 | terraform.tfstate.backup 9 | commands.txt 10 | .vscode/ 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # terraform-multipass-kubernetes 2 | 3 | Builds a Kubernetes cluster using multipass with terraform. 4 | 5 | 6 | # kubepass 7 | -------------------------------------------------------------------------------- /multipass.tf: -------------------------------------------------------------------------------- 1 | module "multipass" { 2 | source = "./multipass" 3 | } -------------------------------------------------------------------------------- /multipass/data.tf: -------------------------------------------------------------------------------- 1 | data "external" "master" { 2 | program = ["python3", "${path.module}/script/multipass.py" ] 3 | query = { 4 | name = "${var.master}" 5 | cpu = "${var.cpu}" 6 | mem = "${var.mem}" 7 | disk = "${var.disk}" 8 | init = "${data.template_file.cloud_init_master.rendered}" 9 | } 10 | } 11 | 12 | data "external" "workers" { 13 | program = ["python3", "${path.module}/script/multipass.py"] 14 | query = { 15 | name = "${element(var.workers, count.index)}" 16 | cpu = "${var.cpu}" 17 | mem = "${var.mem}" 18 | disk = "${var.disk}" 19 | init = "${data.template_file.cloud_init_worker.rendered}" 20 | } 21 | count = "${length(var.workers)}" 22 | } 23 | 24 | data "external" "kubejoin" { 25 | depends_on = ["null_resource.master"] 26 | program = ["ssh", 27 | "-i", "${pathexpand("~/.ssh/id_rsa")}", 28 | "-l", "root", 29 | "${data.external.master.result.ip}", 30 | "cat", "/etc/join.json" 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /multipass/main.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "master" { 2 | 3 | triggers = { 4 | id = "${data.external.master.result.ip}" 5 | } 6 | 7 | connection { 8 | type = "ssh" 9 | host = "${data.external.master.result.ip}" 10 | user = "root" 11 | private_key = "${file(pathexpand("~/.ssh/id_rsa"))}" 12 | } 13 | 14 | provisioner "remote-exec" { 15 | script = "${path.module}/script/kube-init.sh" 16 | } 17 | 18 | provisioner "local-exec" { 19 | command = </dev/null 22 | then echo '{"join":"'$(kubeadm token create --ttl 0 --print-join-command)'"}' >/etc/join.json 23 | fi 24 | -------------------------------------------------------------------------------- /multipass/script/multipass.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import json 4 | import subprocess 5 | import tempfile 6 | 7 | def log(msg): 8 | with open("multipass.log", "a") as f: 9 | f.write("%s\n" % msg) 10 | 11 | def find_vm(name): 12 | cmd = ["multipass", "list", "--format=json"] 13 | out = subprocess.check_output(cmd) 14 | vms = json.loads(out) 15 | for vm in vms["list"]: 16 | if vm["name"] == name: 17 | return { 18 | "name": name, 19 | "ip": vm["ipv4"][0], 20 | "release": vm["release"], 21 | "state": vm["state"] 22 | } 23 | return None 24 | 25 | def create_vm(name, cpu, mem, disk, data): 26 | temp = tempfile.NamedTemporaryFile(delete=False) 27 | with open(temp.name, "w") as f: 28 | f.write(data) 29 | cmd = ["multipass", "launch", 30 | "--name", name, 31 | "--cpus", cpu, 32 | "--disk", disk, 33 | "--mem", mem, 34 | "--cloud-init", temp.name] 35 | res = subprocess.check_output(cmd) 36 | log("%s: %s" %(cmd, res)) 37 | os.remove(temp.name) 38 | return find_vm(name) 39 | 40 | inp = json.loads(sys.stdin.read()) 41 | name = inp["name"] 42 | mem = inp["mem"] 43 | disk = inp["disk"] 44 | cpu = inp["cpu"] 45 | data = inp["init"] 46 | res = find_vm(name) 47 | if not res: 48 | res = create_vm(name, cpu, mem, disk, data) 49 | 50 | print(json.dumps(res)) 51 | -------------------------------------------------------------------------------- /multipass/template.tf: -------------------------------------------------------------------------------- 1 | data "template_file" "cloud_init_master" { 2 | template = "${file("${path.module}/script/cloud-init.yaml")}" 3 | vars = { 4 | ssh_public_key = "${file(pathexpand("~/.ssh/id_rsa.pub"))}" 5 | extra_cmd = "" 6 | } 7 | } 8 | 9 | data "template_file" "cloud_init_worker" { 10 | template = "${file("${path.module}/script/cloud-init.yaml")}" 11 | vars = { 12 | ssh_public_key = "${file(pathexpand("~/.ssh/id_rsa.pub"))}" 13 | extra_cmd = "- ${data.external.kubejoin.result.join}" 14 | } 15 | } 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /multipass/variables.tf: -------------------------------------------------------------------------------- 1 | variable "disk" { 2 | default = "10G" 3 | } 4 | 5 | variable "mem" { 6 | default = "4G" 7 | } 8 | 9 | variable "cpu" { 10 | default = 2 11 | } 12 | 13 | variable "master" { 14 | default = "kube0" 15 | } 16 | 17 | variable "workers" { 18 | description = "workers" 19 | default = [ "kube1", "kube2", "kube3" ] 20 | } 21 | 22 | 23 | -------------------------------------------------------------------------------- /multipass/workers.tf: -------------------------------------------------------------------------------- 1 | resource "null_resource" "workers" { 2 | 3 | triggers = { 4 | id = "${data.external.workers[count.index].result.ip}" 5 | } 6 | 7 | connection { 8 | type = "ssh" 9 | host = "${data.external.workers[count.index].result.ip}" 10 | user = "root" 11 | private_key = "${file(pathexpand("~/.ssh/id_rsa"))}" 12 | } 13 | 14 | provisioner "remote-exec" { 15 | inline = [ 16 | "cloud-init status --wait" 17 | ] 18 | } 19 | 20 | count = "${length(var.workers)}" 21 | } 22 | 23 | -------------------------------------------------------------------------------- /reset.sh: -------------------------------------------------------------------------------- 1 | multipass delete --all 2 | multipass purge 3 | rm terraform.tfstate 4 | 5 | --------------------------------------------------------------------------------