diff --git a/bare-metal/fedora-atomic/kubernetes/LICENSE b/bare-metal/fedora-atomic/kubernetes/LICENSE new file mode 100644 index 00000000..bd9a5eea --- /dev/null +++ b/bare-metal/fedora-atomic/kubernetes/LICENSE @@ -0,0 +1,23 @@ +The MIT License (MIT) + +Copyright (c) 2017 Typhoon Authors +Copyright (c) 2017 Dalton Hubble + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/bare-metal/fedora-atomic/kubernetes/README.md b/bare-metal/fedora-atomic/kubernetes/README.md new file mode 100644 index 00000000..ae254e64 --- /dev/null +++ b/bare-metal/fedora-atomic/kubernetes/README.md @@ -0,0 +1,22 @@ +# Typhoon + +Typhoon is a minimal and free Kubernetes distribution. + +* Minimal, stable base Kubernetes distribution +* Declarative infrastructure and configuration +* Free (freedom and cost) and privacy-respecting +* Practical for labs, datacenters, and clouds + +Typhoon distributes upstream Kubernetes, architectural conventions, and cluster addons, much like a GNU/Linux distribution provides the Linux kernel and userspace components. + +## Features + +* Kubernetes v1.10.0 (upstream, via [kubernetes-incubator/bootkube](https://github.com/kubernetes-incubator/bootkube)) +* Single or multi-master, workloads isolated on workers, [Calico](https://www.projectcalico.org/) or [flannel](https://github.com/coreos/flannel) networking +* On-cluster etcd with TLS, [RBAC](https://kubernetes.io/docs/admin/authorization/rbac/)-enabled, [network policy](https://kubernetes.io/docs/concepts/services-networking/network-policies/) +* Ready for Ingress, Prometheus, Grafana, and other optional [addons](https://typhoon.psdn.io/addons/overview/) + +## Docs + +Please see the [official docs](https://typhoon.psdn.io) and the bare-metal [tutorial](https://typhoon.psdn.io/bare-metal/). + diff --git a/bare-metal/fedora-atomic/kubernetes/bootkube.tf b/bare-metal/fedora-atomic/kubernetes/bootkube.tf new file mode 100644 index 00000000..eb115699 --- /dev/null +++ b/bare-metal/fedora-atomic/kubernetes/bootkube.tf @@ -0,0 +1,17 @@ +# Self-hosted Kubernetes assets (kubeconfig, manifests) +module "bootkube" { + source = "git::https://github.com/poseidon/terraform-render-bootkube.git?ref=61fb176647e15d4d0e72fdccb34d27e47430407c" + + cluster_name = "${var.cluster_name}" + api_servers = ["${var.k8s_domain_name}"] + etcd_servers = ["${var.controller_domains}"] + asset_dir = "${var.asset_dir}" + networking = "${var.networking}" + network_mtu = "${var.network_mtu}" + pod_cidr = "${var.pod_cidr}" + service_cidr = "${var.service_cidr}" + cluster_domain_suffix = "${var.cluster_domain_suffix}" + + # Fedora + trusted_certs_dir = "/etc/pki/tls/certs" +} diff --git a/bare-metal/fedora-atomic/kubernetes/cloudinit/controller.yaml.tmpl b/bare-metal/fedora-atomic/kubernetes/cloudinit/controller.yaml.tmpl new file mode 100644 index 00000000..07acbbd5 --- /dev/null +++ b/bare-metal/fedora-atomic/kubernetes/cloudinit/controller.yaml.tmpl @@ -0,0 +1,147 @@ +#cloud-config +write_files: + - path: /etc/systemd/system/etcd-member.service + content: | + [Unit] + Description=etcd-member + Documentation=https://github.com/coreos/etcd + Wants=network-online.target network.target + After=network-online.target + Requires=docker.service + After=docker.service + [Service] + EnvironmentFile=/etc/etcd/etcd.conf + ExecStartPre=/bin/mkdir -p /var/lib/etcd + ExecStart=/usr/bin/docker run --rm --name etcd-member \ + --net=host \ + -v /etc/pki/tls/certs:/usr/share/ca-certificates:ro,z \ + -v /etc/ssl/etcd:/etc/ssl/certs:ro,Z \ + -v /var/lib/etcd:/var/lib/etcd:Z \ + --env-file=/etc/etcd/etcd.conf \ + quay.io/coreos/etcd:v3.3.3 + ExecStop=/usr/bin/docker stop etcd-member + Restart=on-failure + RestartSec=10s + TimeoutStartSec=0 + LimitNOFILE=40000 + [Install] + WantedBy=multi-user.target + - path: /etc/etcd/etcd.conf + content: | + ETCD_NAME=${etcd_name} + ETCD_DATA_DIR=/var/lib/etcd + ETCD_ADVERTISE_CLIENT_URLS=https://${domain_name}:2379 + ETCD_INITIAL_ADVERTISE_PEER_URLS=https://${domain_name}:2380 + ETCD_LISTEN_CLIENT_URLS=https://0.0.0.0:2379 + ETCD_LISTEN_PEER_URLS=https://0.0.0.0:2380 + ETCD_INITIAL_CLUSTER=${etcd_initial_cluster} + ETCD_STRICT_RECONFIG_CHECK=true + ETCD_TRUSTED_CA_FILE=/etc/ssl/certs/etcd/server-ca.crt + ETCD_CERT_FILE=/etc/ssl/certs/etcd/server.crt + ETCD_KEY_FILE=/etc/ssl/certs/etcd/server.key + ETCD_CLIENT_CERT_AUTH=true + ETCD_PEER_TRUSTED_CA_FILE=/etc/ssl/certs/etcd/peer-ca.crt + ETCD_PEER_CERT_FILE=/etc/ssl/certs/etcd/peer.crt + ETCD_PEER_KEY_FILE=/etc/ssl/certs/etcd/peer.key + ETCD_PEER_CLIENT_CERT_AUTH=true + - path: /etc/systemd/system/kubelet.service + content: | + [Unit] + Description=Kubelet + Wants=rpc-statd.service + [Service] + WorkingDirectory=/etc/kubernetes + ExecStartPre=/bin/mkdir -p /opt/cni/bin + ExecStartPre=/bin/mkdir -p /etc/kubernetes/manifests + ExecStartPre=/bin/mkdir -p /etc/kubernetes/cni/net.d + ExecStartPre=/bin/mkdir -p /etc/kubernetes/checkpoint-secrets + ExecStartPre=/bin/mkdir -p /etc/kubernetes/inactive-manifests + ExecStartPre=/bin/mkdir -p /var/lib/cni + ExecStartPre=/bin/mkdir -p /var/lib/kubelet/volumeplugins + ExecStartPre=/usr/bin/bash -c "grep 'certificate-authority-data' /etc/kubernetes/kubeconfig | awk '{print $2}' | base64 -d > /etc/kubernetes/ca.crt" + # Atomic's system containers and RPMs are old and unfriendly. Use this. + ExecStartPre=/usr/bin/curl -L https://dl.k8s.io/v1.10.0/kubernetes-node-linux-amd64.tar.gz -o kubernetes-node-linux-amd64.tar.gz + ExecStartPre=/usr/bin/tar xzf kubernetes-node-linux-amd64.tar.gz -C /usr/local/bin --strip-components=3 kubernetes/node/bin/kubelet + ExecStart= + ExecStart=/usr/local/bin/kubelet \ + --allow-privileged \ + --anonymous-auth=false \ + --cgroup-driver=systemd \ + --client-ca-file=/etc/kubernetes/ca.crt \ + --cluster_dns=${k8s_dns_service_ip} \ + --cluster_domain=${cluster_domain_suffix} \ + --cni-conf-dir=/etc/kubernetes/cni/net.d \ + --exit-on-lock-contention \ + --hostname-override=${domain_name} \ + --kubeconfig=/etc/kubernetes/kubeconfig \ + --lock-file=/var/run/lock/kubelet.lock \ + --network-plugin=cni \ + --node-labels=node-role.kubernetes.io/master \ + --node-labels=node-role.kubernetes.io/controller="true" \ + --pod-manifest-path=/etc/kubernetes/manifests \ + --register-with-taints=node-role.kubernetes.io/master=:NoSchedule \ + --volume-plugin-dir=/var/lib/kubelet/volumeplugins + Restart=always + RestartSec=10 + [Install] + WantedBy=multi-user.target + - path: /etc/systemd/system/kubelet.path + content: | + [Unit] + Description=Watch for kubeconfig + [Path] + PathExists=/etc/kubernetes/kubeconfig + [Install] + WantedBy=multi-user.target + - path: /etc/systemd/system/bootkube.service + content: | + [Unit] + Description=Bootstrap a Kubernetes cluster + ConditionPathExists=!/var/bootkube/init_bootkube.done + [Service] + Type=oneshot + RemainAfterExit=true + WorkingDirectory=/var/bootkube + ExecStartPre=/bin/mkdir -p /var/bootkube + ExecStart=/usr/local/bin/bootkube-start + ExecStartPost=/bin/touch /var/bootkube/init_bootkube.done + [Install] + WantedBy=multi-user.target + - path: /etc/kubernetes/.keep + - path: /var/bootkube/.keep + - path: /etc/selinux/config + owner: root:root + permissions: '0644' + content: | + SELINUX=permissive + SELINUXTYPE=targeted + - path: /usr/local/bin/bootkube-start + permissions: '0755' + content: | + #!/bin/bash -e + # Wrapper for bootkube start + [ -n "$(ls /var/bootkube/assets/manifests-*/* 2>/dev/null)" ] && mv /var/bootkube/assets/manifests-*/* /var/bootkube/assets/manifests && rm -rf /var/bootkube/assets/manifests-* + /usr/bin/docker run --rm --name bootkube \ + --net=host \ + --volume /etc/kubernetes:/etc/kubernetes:Z \ + --volume /var/bootkube/assets:/assets:Z \ + --entrypoint=/bootkube \ + quay.io/coreos/bootkube:v0.11.0 start --asset-dir=/assets +bootcmd: + - [setenforce, Permissive] +runcmd: + - [systemctl, daemon-reload] + - [systemctl, enable, etcd-member.service] + - [systemctl, start, --no-block, etcd-member.service] + - [hostnamectl, set-hostname, ${domain_name}] + - [systemctl, enable, kubelet.path] + - [systemctl, start, --no-block, kubelet.path] + - [systemctl, disable, firewalld, --now] +users: + - default + - name: fedora + gecos: Fedora Admin + sudo: ALL=(ALL) NOPASSWD:ALL + groups: wheel,adm,systemd-journal,docker + ssh-authorized-keys: + - "${ssh_authorized_key}" diff --git a/bare-metal/fedora-atomic/kubernetes/cloudinit/worker.yaml.tmpl b/bare-metal/fedora-atomic/kubernetes/cloudinit/worker.yaml.tmpl new file mode 100644 index 00000000..39293d2d --- /dev/null +++ b/bare-metal/fedora-atomic/kubernetes/cloudinit/worker.yaml.tmpl @@ -0,0 +1,72 @@ +#cloud-config +write_files: + - path: /etc/systemd/system/kubelet.service + content: | + [Unit] + Description=Kubelet + Wants=rpc-statd.service + [Service] + WorkingDirectory=/etc/kubernetes + ExecStartPre=/bin/mkdir -p /opt/cni/bin + ExecStartPre=/bin/mkdir -p /etc/kubernetes/manifests + ExecStartPre=/bin/mkdir -p /etc/kubernetes/cni/net.d + ExecStartPre=/bin/mkdir -p /etc/kubernetes/checkpoint-secrets + ExecStartPre=/bin/mkdir -p /etc/kubernetes/inactive-manifests + ExecStartPre=/bin/mkdir -p /var/lib/cni + ExecStartPre=/bin/mkdir -p /var/lib/kubelet/volumeplugins + ExecStartPre=/usr/bin/bash -c "grep 'certificate-authority-data' /etc/kubernetes/kubeconfig | awk '{print $2}' | base64 -d > /etc/kubernetes/ca.crt" + # Atomic's system containers and RPMs are old and unfriendly. Use this. + ExecStartPre=/usr/bin/curl -L https://dl.k8s.io/v1.10.0/kubernetes-node-linux-amd64.tar.gz -o kubernetes-node-linux-amd64.tar.gz + ExecStartPre=/usr/bin/tar xzf kubernetes-node-linux-amd64.tar.gz -C /usr/local/bin --strip-components=3 kubernetes/node/bin/kubelet + ExecStart= + ExecStart=/usr/local/bin/kubelet \ + --allow-privileged \ + --anonymous-auth=false \ + --cgroup-driver=systemd \ + --client-ca-file=/etc/kubernetes/ca.crt \ + --cluster_dns=${k8s_dns_service_ip} \ + --cluster_domain=${cluster_domain_suffix} \ + --cni-conf-dir=/etc/kubernetes/cni/net.d \ + --exit-on-lock-contention \ + --hostname-override=${domain_name} \ + --kubeconfig=/etc/kubernetes/kubeconfig \ + --lock-file=/var/run/lock/kubelet.lock \ + --network-plugin=cni \ + --node-labels=node-role.kubernetes.io/node \ + --pod-manifest-path=/etc/kubernetes/manifests \ + --volume-plugin-dir=/var/lib/kubelet/volumeplugins + Restart=always + RestartSec=10 + [Install] + WantedBy=multi-user.target + - path: /etc/systemd/system/kubelet.path + content: | + [Unit] + Description=Watch for kubeconfig + [Path] + PathExists=/etc/kubernetes/kubeconfig + [Install] + WantedBy=multi-user.target + - path: /etc/kubernetes/.keep + - path: /etc/selinux/config + owner: root:root + permissions: '0644' + content: | + SELINUX=permissive + SELINUXTYPE=targeted +bootcmd: + - [setenforce, Permissive] +runcmd: + - [systemctl, daemon-reload] + - [hostnamectl, set-hostname, ${domain_name}] + - [systemctl, enable, kubelet.path] + - [systemctl, start, --no-block, kubelet.path] + - [systemctl, disable, firewalld, --now] +users: + - default + - name: fedora + gecos: Fedora Admin + sudo: ALL=(ALL) NOPASSWD:ALL + groups: wheel,adm,systemd-journal,docker + ssh-authorized-keys: + - "${ssh_authorized_key}" diff --git a/bare-metal/fedora-atomic/kubernetes/groups.tf b/bare-metal/fedora-atomic/kubernetes/groups.tf new file mode 100644 index 00000000..bc11fa7a --- /dev/null +++ b/bare-metal/fedora-atomic/kubernetes/groups.tf @@ -0,0 +1,37 @@ +// Install Fedora to disk +resource "matchbox_group" "fedora-install" { + count = "${length(var.controller_names) + length(var.worker_names)}" + + name = "${format("fedora-install-%s", element(concat(var.controller_names, var.worker_names), count.index))}" + profile = "${element(matchbox_profile.cached-fedora-install.*.name, count.index)}" + + selector { + mac = "${element(concat(var.controller_macs, var.worker_macs), count.index)}" + } + + metadata { + ssh_authorized_key = "${var.ssh_authorized_key}" + } +} + +resource "matchbox_group" "controller" { + count = "${length(var.controller_names)}" + name = "${format("%s-%s", var.cluster_name, element(var.controller_names, count.index))}" + profile = "${element(matchbox_profile.controllers.*.name, count.index)}" + + selector { + mac = "${element(var.controller_macs, count.index)}" + os = "installed" + } +} + +resource "matchbox_group" "worker" { + count = "${length(var.worker_names)}" + name = "${format("%s-%s", var.cluster_name, element(var.worker_names, count.index))}" + profile = "${element(matchbox_profile.workers.*.name, count.index)}" + + selector { + mac = "${element(var.worker_macs, count.index)}" + os = "installed" + } +} diff --git a/bare-metal/fedora-atomic/kubernetes/kickstart/fedora-atomic.ks.tmpl b/bare-metal/fedora-atomic/kubernetes/kickstart/fedora-atomic.ks.tmpl new file mode 100644 index 00000000..0e1ce160 --- /dev/null +++ b/bare-metal/fedora-atomic/kubernetes/kickstart/fedora-atomic.ks.tmpl @@ -0,0 +1,36 @@ +# required +lang en_US.UTF-8 +keyboard us +timezone --utc Etc/UTC + +# wipe disks +zerombr +clearpart --all --initlabel + +# locked root and temporary user +rootpw --lock --iscrypted locked +user --name=none + +# config +autopart --type=lvm --noswap +network --bootproto=dhcp --device=link --activate --onboot=on +bootloader --timeout=1 --append="ds=nocloud\;seedfrom=/var/cloud-init/" +services --enabled=cloud-init,cloud-init-local,cloud-config,cloud-final + +ostreesetup --osname="fedora-atomic" --remote="fedora-atomic-27" --url="${matchbox_http_endpoint}/assets/fedora/27/repo" --ref=fedora/27/x86_64/atomic-host --nogpg + +reboot + +%post --erroronfail +mkdir /var/cloud-init +curl --retry 10 "${matchbox_http_endpoint}/generic?mac=${mac}&os=installed" -o /var/cloud-init/user-data +echo "instance-id: iid-local01" > /var/cloud-init/meta-data + +rm -f /etc/ostree/remotes.d/fedora-atomic-27.conf +ostree remote add fedora-atomic-27 https://kojipkgs.fedoraproject.org/atomic/27 --set=gpgkeypath=/etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-27-primary + +# lock root user +passwd -l root +# remove temporary user +userdel -r none +%end diff --git a/bare-metal/fedora-atomic/kubernetes/outputs.tf b/bare-metal/fedora-atomic/kubernetes/outputs.tf new file mode 100644 index 00000000..41bd79f2 --- /dev/null +++ b/bare-metal/fedora-atomic/kubernetes/outputs.tf @@ -0,0 +1,3 @@ +output "kubeconfig" { + value = "${module.bootkube.kubeconfig}" +} diff --git a/bare-metal/fedora-atomic/kubernetes/profiles.tf b/bare-metal/fedora-atomic/kubernetes/profiles.tf new file mode 100644 index 00000000..252b8f45 --- /dev/null +++ b/bare-metal/fedora-atomic/kubernetes/profiles.tf @@ -0,0 +1,79 @@ +// Cached Fedora Install profile (from matchbox /assets cache) +// Note: Admin must have downloaded Fedora kernel, initrd, and repo into +// matchbox assets. +resource "matchbox_profile" "cached-fedora-install" { + count = "${length(var.controller_names) + length(var.worker_names)}" + name = "${format("%s-cached-fedora-install-%s", var.cluster_name, element(concat(var.controller_names, var.worker_names), count.index))}" + + kernel = "/assets/fedora/27/vmlinuz" + + initrd = [ + "/assets/fedora/27/initrd.img", + ] + + args = [ + "initrd=initrd.img", + "inst.repo=${var.matchbox_http_endpoint}/assets/fedora/27/Server/x86_64/os/", + "inst.ks=${var.matchbox_http_endpoint}/generic?mac=${element(concat(var.controller_macs, var.worker_macs), count.index)}", + "inst.text", + "${var.kernel_args}", + ] + + # kickstart + generic_config = "${element(data.template_file.install-kickstarts.*.rendered, count.index)}" +} + +data "template_file" "install-kickstarts" { + count = "${length(var.controller_names) + length(var.worker_names)}" + + template = "${file("${path.module}/kickstart/fedora-atomic.ks.tmpl")}" + + vars { + matchbox_http_endpoint = "${var.matchbox_http_endpoint}" + mac = "${element(concat(var.controller_macs, var.worker_macs), count.index)}" + } +} + +// Kubernetes Controller profiles +resource "matchbox_profile" "controllers" { + count = "${length(var.controller_names)}" + name = "${format("%s-controller-%s", var.cluster_name, element(var.controller_names, count.index))}" + # cloud-init + generic_config = "${element(data.template_file.controller-configs.*.rendered, count.index)}" +} + +data "template_file" "controller-configs" { + count = "${length(var.controller_names)}" + + template = "${file("${path.module}/cloudinit/controller.yaml.tmpl")}" + + vars { + domain_name = "${element(var.controller_domains, count.index)}" + etcd_name = "${element(var.controller_names, count.index)}" + etcd_initial_cluster = "${join(",", formatlist("%s=https://%s:2380", var.controller_names, var.controller_domains))}" + k8s_dns_service_ip = "${module.bootkube.kube_dns_service_ip}" + cluster_domain_suffix = "${var.cluster_domain_suffix}" + ssh_authorized_key = "${var.ssh_authorized_key}" + } +} + +// Kubernetes Worker profiles +resource "matchbox_profile" "workers" { + count = "${length(var.worker_names)}" + name = "${format("%s-worker-%s", var.cluster_name, element(var.worker_names, count.index))}" + # cloud-init + generic_config = "${element(data.template_file.worker-configs.*.rendered, count.index)}" +} + +data "template_file" "worker-configs" { + count = "${length(var.worker_names)}" + + template = "${file("${path.module}/cloudinit/worker.yaml.tmpl")}" + + vars { + domain_name = "${element(var.worker_domains, count.index)}" + k8s_dns_service_ip = "${module.bootkube.kube_dns_service_ip}" + cluster_domain_suffix = "${var.cluster_domain_suffix}" + ssh_authorized_key = "${var.ssh_authorized_key}" + } +} diff --git a/bare-metal/fedora-atomic/kubernetes/require.tf b/bare-metal/fedora-atomic/kubernetes/require.tf new file mode 100644 index 00000000..e95363d0 --- /dev/null +++ b/bare-metal/fedora-atomic/kubernetes/require.tf @@ -0,0 +1,21 @@ +# Terraform version and plugin versions + +terraform { + required_version = ">= 0.10.4" +} + +provider "local" { + version = "~> 1.0" +} + +provider "null" { + version = "~> 1.0" +} + +provider "template" { + version = "~> 1.0" +} + +provider "tls" { + version = "~> 1.0" +} diff --git a/bare-metal/fedora-atomic/kubernetes/ssh.tf b/bare-metal/fedora-atomic/kubernetes/ssh.tf new file mode 100644 index 00000000..82fd3a14 --- /dev/null +++ b/bare-metal/fedora-atomic/kubernetes/ssh.tf @@ -0,0 +1,120 @@ +# Secure copy etcd TLS assets and kubeconfig to controllers. Activates kubelet.service +resource "null_resource" "copy-controller-secrets" { + count = "${length(var.controller_names)}" + + connection { + type = "ssh" + host = "${element(var.controller_domains, count.index)}" + user = "fedora" + timeout = "60m" + } + + provisioner "file" { + content = "${module.bootkube.kubeconfig}" + destination = "$HOME/kubeconfig" + } + + provisioner "file" { + content = "${module.bootkube.etcd_ca_cert}" + destination = "$HOME/etcd-client-ca.crt" + } + + provisioner "file" { + content = "${module.bootkube.etcd_client_cert}" + destination = "$HOME/etcd-client.crt" + } + + provisioner "file" { + content = "${module.bootkube.etcd_client_key}" + destination = "$HOME/etcd-client.key" + } + + provisioner "file" { + content = "${module.bootkube.etcd_server_cert}" + destination = "$HOME/etcd-server.crt" + } + + provisioner "file" { + content = "${module.bootkube.etcd_server_key}" + destination = "$HOME/etcd-server.key" + } + + provisioner "file" { + content = "${module.bootkube.etcd_peer_cert}" + destination = "$HOME/etcd-peer.crt" + } + + provisioner "file" { + content = "${module.bootkube.etcd_peer_key}" + destination = "$HOME/etcd-peer.key" + } + + provisioner "remote-exec" { + inline = [ + "sudo mkdir -p /etc/ssl/etcd/etcd", + "sudo mv etcd-client* /etc/ssl/etcd/", + "sudo cp /etc/ssl/etcd/etcd-client-ca.crt /etc/ssl/etcd/etcd/server-ca.crt", + "sudo mv etcd-server.crt /etc/ssl/etcd/etcd/server.crt", + "sudo mv etcd-server.key /etc/ssl/etcd/etcd/server.key", + "sudo cp /etc/ssl/etcd/etcd-client-ca.crt /etc/ssl/etcd/etcd/peer-ca.crt", + "sudo mv etcd-peer.crt /etc/ssl/etcd/etcd/peer.crt", + "sudo mv etcd-peer.key /etc/ssl/etcd/etcd/peer.key", + "sudo mv $HOME/kubeconfig /etc/kubernetes/kubeconfig", + ] + } +} + +# Secure copy kubeconfig to all workers. Activates kubelet.service +resource "null_resource" "copy-worker-secrets" { + count = "${length(var.worker_names)}" + + connection { + type = "ssh" + host = "${element(var.worker_domains, count.index)}" + user = "fedora" + timeout = "60m" + } + + provisioner "file" { + content = "${module.bootkube.kubeconfig}" + destination = "$HOME/kubeconfig" + } + + provisioner "remote-exec" { + inline = [ + "sudo mv $HOME/kubeconfig /etc/kubernetes/kubeconfig", + ] + } +} + +# Secure copy bootkube assets to ONE controller and start bootkube to perform +# one-time self-hosted cluster bootstrapping. +resource "null_resource" "bootkube-start" { + # Without depends_on, this remote-exec may start before the kubeconfig copy. + # Terraform only does one task at a time, so it would try to bootstrap + # while no Kubelets are running. + depends_on = [ + "null_resource.copy-controller-secrets", + "null_resource.copy-worker-secrets", + ] + + connection { + type = "ssh" + host = "${element(var.controller_domains, 0)}" + user = "fedora" + timeout = "15m" + } + + provisioner "file" { + source = "${var.asset_dir}" + destination = "$HOME/assets" + } + + provisioner "remote-exec" { + inline = [ + "while [ ! -f /var/lib/cloud/instance/boot-finished ]; do sleep 4; done", + "sudo mv $HOME/assets /var/bootkube", + "sudo systemctl start bootkube", + ] + } +} diff --git a/bare-metal/fedora-atomic/kubernetes/variables.tf b/bare-metal/fedora-atomic/kubernetes/variables.tf new file mode 100644 index 00000000..f2406c7f --- /dev/null +++ b/bare-metal/fedora-atomic/kubernetes/variables.tf @@ -0,0 +1,97 @@ +variable "cluster_name" { + type = "string" + description = "Unique cluster name" +} + +# bare-metal + +variable "matchbox_http_endpoint" { + type = "string" + description = "Matchbox HTTP read-only endpoint (e.g. http://matchbox.example.com:8080)" +} + +# machines +# Terraform's crude "type system" does not properly support lists of maps so we do this. + +variable "controller_names" { + type = "list" +} + +variable "controller_macs" { + type = "list" +} + +variable "controller_domains" { + type = "list" +} + +variable "worker_names" { + type = "list" +} + +variable "worker_macs" { + type = "list" +} + +variable "worker_domains" { + type = "list" +} + +# configuration + +variable "k8s_domain_name" { + description = "Controller DNS name which resolves to a controller instance. Workers and kubeconfig's will communicate with this endpoint (e.g. cluster.example.com)" + type = "string" +} + +variable "ssh_authorized_key" { + type = "string" + description = "SSH public key for user 'fedora'" +} + +variable "asset_dir" { + description = "Path to a directory where generated assets should be placed (contains secrets)" + type = "string" +} + +variable "networking" { + description = "Choice of networking provider (flannel or calico)" + type = "string" + default = "calico" +} + +variable "network_mtu" { + description = "CNI interface MTU (applies to calico only)" + type = "string" + default = "1480" +} + +variable "pod_cidr" { + description = "CIDR IPv4 range to assign Kubernetes pods" + type = "string" + default = "10.2.0.0/16" +} + +variable "service_cidr" { + description = <