6 Commits
Author SHA1 Message Date
shnee 4a62875b8e Added outputs for IPs.
- Made sure node-memory ad node-vcpus is passed down to module.
- Fixed get-vm-ips.sh after move to module.
2021-11-11 14:50:45 -05:00
shnee 3d7bd95f78 node module is working. 2021-11-10 22:22:17 -05:00
shnee 474f6c746a Setting passwords and keys working via variables.
- Setting hostnames is working also.
2021-11-10 15:29:22 -05:00
shnee af17823d68 Setting keys and password with cloud-init working. 2021-11-10 13:59:07 -05:00
shnee b126da8acf Initial attempt is working. 2021-11-10 11:24:50 -05:00
shnee 483c44b695 Add example configs from libvirt provider. 2021-11-09 17:06:17 -05:00
42 changed files with 93 additions and 1618 deletions
-12
View File
@@ -11,8 +11,6 @@
# Crash log files # Crash log files
crash.log crash.log
# Added to original pulled from github/gitignore
crash*.log
# Exclude all .tfvars files, which are likely to contain sentitive data, such as # Exclude all .tfvars files, which are likely to contain sentitive data, such as
# password, private keys, and other secrets. These should not be part of version # password, private keys, and other secrets. These should not be part of version
@@ -38,13 +36,3 @@ override.tf.json
# Ignore CLI configuration files # Ignore CLI configuration files
.terraformrc .terraformrc
terraform.rc terraform.rc
################################################################################
# end Pulled from github/gitignore 2021-11-10 commit 1a84870
################################################################################
k8s-key*
*admin-key*
STARTHERE
inventory
-57
View File
@@ -1,57 +0,0 @@
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/dmacvicar/libvirt" {
version = "0.6.11"
hashes = [
"h1:6QzHY/7aNdaaDxJZKygotWnM5uHoS2gs/03CzUCJX60=",
"zh:15300a1c3c294eccade4c8a678412d81602ab041dc0a5aab72fee5425d778e89",
"zh:1605806de0d3b86b7e94b5d04a7ad9b6ac695781f9672ab6002c23caef43b98e",
"zh:21efc5937d89f9ec96bc626d2ce3621c0919b3da97ab63b4e520c37d3f5c7357",
"zh:2c143a6909917fd11191447de4c496f084c7da5200beb9f512791a80a1f33e7c",
"zh:3ca369718cc49feefc3a6ffa795a9055e60de33989a9f1c72b6db16048a181fa",
"zh:71db1d1cf2c06984bba408ad5dc9b4e25285684ee5c530a61583b202cff21b96",
"zh:a67adfc988311d34adcc119500c2ef048a45d632b00bb5a15ea6d3ffdc1c3d1c",
"zh:a83448cbcc194e3b52af9b89b9273a116082d83f2c966035bf8a8c5d5606ca9c",
"zh:a9c5a818dd2606460d4d6f33af7cb387f3e984d631fc233aaec0dda4e0756c2b",
"zh:af3263e66cf9138361d6d7408533edd6de8498e67c88cf0084421ae31fe89054",
"zh:b9596cb26c1e391172472de4ada9b3b0a08e4777e41327db8e021454cc6aae20",
"zh:e28124b9ee0b8c18b6f776eb6523d8935f3072c47cd803ea2f1a06206effaa48",
"zh:edd00638d8c088b8a38e7ab8b9e8ab3bd710f7357d0f6b4a38e0028bd49d8460",
]
}
provider "registry.terraform.io/hashicorp/aws" {
version = "3.64.2"
hashes = [
"h1:oFsgTmmt/eJ8KLo59PSmYu/irUHJiPnQEey0VqaOOck=",
"zh:0b029a2282beabfe410eb2969e18ca773d3473415e442be4dc8ce0eb6d1cd8c5",
"zh:3209de3266a1138f1ccb09f094fdd98b6f55afc06e291db0abe092ec5dbe7640",
"zh:40648266551631cbc15f8a76e80faf300510e3b38c2544d43fc25e37e6802727",
"zh:483c8af92ae70146f2790a70c1a810251e7135aa912b66e769c934eddceebe32",
"zh:4d106d8d415d8df342f3f85e58c35418e6c55e3cb7f02897f832cefac4dca68c",
"zh:972626a6ddb31d5216606d12ab5c30fbf8d51ed2bbe0efcdd7cffa68c1141557",
"zh:a230d55ec52b1695148d40296877ee23e0b302e817154f9b838eb117c87b13fa",
"zh:c95fddfbd7f870db949da0601323e866e0f0fb0d4a93e96725ae5b88029e84d5",
"zh:ea0c7f568074f835f22273c8e7e61e87f5277e32004c72122915fd3c8df49ccc",
"zh:f96d25887e6e2d2ae47659e2c586efea2167995b59a479ae65a02b097da86474",
"zh:fe7502d8e52d3b5ccb2b3c178e7ea894344783093aa71ffb20e978914c976182",
]
}
provider "registry.terraform.io/hashicorp/template" {
version = "2.2.0"
hashes = [
"h1:94qn780bi1qjrbC3uQtjJh3Wkfwd5+tTtJHOb7KTg9w=",
"zh:01702196f0a0492ec07917db7aaa595843d8f171dc195f4c988d2ffca2a06386",
"zh:09aae3da826ba3d7df69efeb25d146a1de0d03e951d35019a0f80e4f58c89b53",
"zh:09ba83c0625b6fe0a954da6fbd0c355ac0b7f07f86c91a2a97849140fea49603",
"zh:0e3a6c8e16f17f19010accd0844187d524580d9fdb0731f675ffcf4afba03d16",
"zh:45f2c594b6f2f34ea663704cc72048b212fe7d16fb4cfd959365fa997228a776",
"zh:77ea3e5a0446784d77114b5e851c970a3dde1e08fa6de38210b8385d7605d451",
"zh:8a154388f3708e3df5a69122a23bdfaf760a523788a5081976b3d5616f7d30ae",
"zh:992843002f2db5a11e626b3fc23dc0c87ad3729b3b3cff08e32ffb3df97edbde",
"zh:ad906f4cebd3ec5e43d5cd6dc8f4c5c9cc3b33d2243c89c5fc18f97f7277b51d",
"zh:c979425ddb256511137ecd093e23283234da0154b7fa8b21c2687182d9aea8b2",
]
}
-46
View File
@@ -1,53 +1,7 @@
A terraform script that will setup VMs via AWS or KVM/QEMU (libvirt).
The modules allow you create N VMs of a specific type. So you could create 1
master node and 3 worker nodes or you could create 3 Ubuntu VMs and 5 CentOS
VMs, or whatever fits your needs.
This script creates the VMs and then uses Cloud-init for initial configuration
of the VMs.
libvirt vs. AWS
----------------------------------------
This script allows VMs to be created libvirt or AWS. You can choose either one,
however, running both at the same time has not been tested. Therefore, when
using one, you should comment out all code pertaining to the other provider.
Cloud-Init
----------------------------------------
Both the libvirt and aws modules use cloud-init for initial configuration of the
VMs. Cloud-init is used to create the admin user and add the mss-admin keys.
Cloud-init is also used to install some initial packages. The goal is to get
these VMs setup enough so that they can be configured via Ansible.
Environment Setup
----------------------------------------
1. From within the nodes-terraform directory run `terraform init`. You will a
see bunch if output as terraform grabs the dependencies it needs.
2. Copy the shared `terraform.tfvars` from S3.
```shell
aws s3 cp s3://mss-terraform-state/global/s3/terraform.tfvars .
```
For instructions on getting AWS CLI to work correctly see `aws-api-setup.md`
in the `doc-ops` repo.
Take care to copy your `terraform.tfvars` back to the S3 bucket whenever you
make a change to it.
3. Verify that you branch and variables match whats deployed by running
`terraform plan`. If everything is in sync you should see `No changes. Your
infrastructure matches the configuration.` _IF_ you do not see this message
make sure to sync with the other admins before continuing.
Dependencies Dependencies
---------------------------------------- ----------------------------------------
_UNFINISHED_
TODO REM add libvirt provider TODO REM add libvirt provider
libvirt provider depends on mkisofs libvirt provider depends on mkisofs
+5 -19
View File
@@ -24,23 +24,9 @@ chpasswd:
expire: false expire: false
hostname: ${hostname} hostname: ${hostname}
fqdn: ${hostname}
package_update: true # Use this when it's determined that we need a bigger disk image.
package_upgrade: true # This must be used in conjuction with 'size' in 'libvirt_volume'
package_reboot_if_required: true # growpart:
# mode: auto
%{ if install-qemu-agent } # devices: ['/']
packages:
# This are only necessary for libvirt.
- qemu-guest-agent
runcmd:
# TODO At some point revisit this, this was added because it seemed like
# apparmor was causing dhclient to not get an IP address for ubuntu. This
# should be double checked.
- echo "/proc/*/task/*/comm wr," | tee -a /etc/apparmor.d/local/sbin.dhclient
# These are only necessary for libvirt.
- systemctl enable qemu-guest-agent
- systemctl start qemu-guest-agent
- systemctl status qemu-guest-agent
%{ endif }
-74
View File
@@ -1,74 +0,0 @@
vm-name-prefix = "ansible-test"
# A CIDR block ending in '/32' equates to a single IP address, '0.0.0.0/0'
# equates to any ip address.
admin-ips = [ "8.8.8.8/32", "0.0.0.0/0" ]
disk-image-dir = "/path/to/disk/pool/"
libvirt-connection-url = "qemu+ssh://<user>@<host>/system"
node-memory = 2048
node-vcpus = 2
## libvirt disk size
# 1 GiB = 1073741824
# 4 GiB
# libvirt-node-disk-size = "${4 * 1073741824}"
# 8 GiB
# libvirt-node-disk-size = "${8 * 1073741824}"
# 12 GiB
# libvirt-node-disk-size = "${12 * 1073741824}"
################################################################################
# AWS images (AMIs)
################################################################################
## Amazon Linux 2
# AWS Amazon Linux 2 AMI (HVM), SSD Volume Type - Oregon - 2021.11.11 - free
# base-image = "ami-00be885d550dcee43"
# AWS Amazon Linux 2 AMI (HVM), SSD Volume Type - us-east-2 - 2021.11.12 - free
base-image = "ami-0dd0ccab7e2801812"
## CentOS
# CentOS 7.9.2009 x86_64 - us-east-2 - 2021-11-15
# base-image = "ami-00f8e2c955f7ffa9b"
# CentOS 8.4.2105 x86_64 - us-east-2 - 2021-11015
# base-image = "ami-057cacbfbbb471bb3"
## Ubuntu
# Ubuntu Server 20.04 LTS (HVM), SSD Volume Type
# us-east-2 - (64-bit x86) - 2021.11.12 - free
# base-image = "ami-0629230e074c580f2"
## Arch linux
# arch-linux-lts-hvm-2021.06.02.x86_64-ebs - us-east-2
# base-image = "ami-02653f06de985e3ba"
################################################################################
# libvirt images
################################################################################
# base-image = "https://cloud-images.ubuntu.com/releases/focal/release/ubuntu-20.04-server-cloudimg-amd64-disk-kvm.img"
# From https://cloud.centos.org/centos/7/images/ from 2020-12-06
# base-image = "https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-2111.qcow2"
## Arch
# From https://gitlab.archlinux.org/archlinux/arch-boxes/-/jobs/40102/artifacts/browse/output
# on 2021-11-28
# base-image = "/media/nas/software/isos/Arch-Linux-x86_64-libvirt-20211128.40102.box"
## Arch
# From https://gitlab.archlinux.org/archlinux/arch-boxes/-/jobs/40102/artifacts/browse/output
# on 2021-11-28
# base-image = "/media/nas/software/isos/Arch-Linux-x86_64-libvirt-20211128.40102.box"
################################################################################
# Keys/Passwords
################################################################################
# Password hash created with:
# python3 -c 'import crypt; print(crypt.crypt("linux", crypt.mksalt(crypt.METHOD_SHA512)))'
# where "linux" is the password.
root-admin-passwd = "$6$fiLRWvGQkdK.MnZA$Co9NkA5ruuBUA389JzmKJiC8gKRohmyM09AFnVBOD7ErZnxK4RHMUlKvYg1HSgwaCXTl7H/q1svoeQeUfgc6f0"
root-admin-pub-key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDfDcjMFmWd6qy9KIlnIHNbEfeNLHC885UUH3jGwESmMTpFfPUn01t9hq5GGaFDrBR55VgdKebAv2JSVl209+r3tE5XxUX5/s2Pu3o2283PiZhA+D18skL7fzaolygOY8mxi9CZSDFia//lLbqT/OE45VGahVBRtda4gmjrade0XRKqjJUCkIo6huG9Ub6yP4gFtFU/C1rRvQo0hqT/imsMYU0Q5XzrKVWv3CpzA7EIQq8llU0fRGMuXWYYOXznPeqqf5BTbWhMWUXVS0o7Cz+zvbxwq1dOR1qHbJ8Vrkt30Cz5QEd159dIM3LHCtOHnveeOpkFo0RqkhQdpZM+2cKzESvivGNGP9h+PrSjcveADxVwDHcxguumUyM012M3yR8cK9KY+GqW5jPdAs13yXGTG4OWiQKeKEgX910l/FndhQi0tSpSEhIlfcEpa3k3P8RrhKJbwiRgR7Qvus4R/KU+lx4OiOr4RKyPQJobC0i0/bvqkw+UHWp4U0Hqivjsb6k= admin"
-4
View File
@@ -1,4 +0,0 @@
#!/bin/sh
aws ec2 describe-instance-status | \
jq '.InstanceStatuses[] | {id: .InstanceId, instance_status: .InstanceStatus.Status, system_status: .SystemStatus.Status}'
-81
View File
@@ -1,81 +0,0 @@
#!/bin/bash
# This script will grab the IPs for libvirt VMs. This script is only needed when
# using a bridge as the network for the VMs. This should only be needed while
# https://github.com/dmacvicar/terraform-provider-libvirt/issues/891 is
# unresolved.
# These are the network interfaces that this script will attempt to get the IP
# address for.
# Ubuntu 20.04 ens3
# Centos 7 & 8 eth0
NET_INTERFACES="eth0 ens3"
LIBVIRT_CONNECTION_URL="libvirt-connection-url"
VM_NAME_PREFIX="vm-name-prefix"
INV_GROUPS="$( \
cat terraform.tfstate | \
jq '.resources[] | select(.type=="libvirt_domain") | .module' | \
sed 's/".*\[\\"\(.*\)\\.*$/\1/g' )"
# Grab the connection URL and the vm name prefix. We do this by greping all
# *.tfvars files making sure to cat terraform.tfvars last. Then we just grab the
# last grep result, this way we make sure any value in terraform.tfvars will
# take priority.
CONN_URLS="$( \
find . -name "*.tfvars" -exec grep "$LIBVIRT_CONNECTION_URL" {} \; && \
grep "$LIBVIRT_CONNECTION_URL" terraform.tfvars)"
CONN_URL="$(echo "$CONN_URLS" | tail -n 1 | sed 's/^.*=\s*"\(.*\)"/\1/g')"
NAME_PREFIXES="$( \
find . -name "*.tfvars" -exec grep "$VM_NAME_PREFIX" {} \; && \
grep "$VM_NAME_PREFIX" terraform.tfvars)"
NAME_PREFIX="$(echo "$NAME_PREFIXES" | tail -n 1 | sed 's/^.*=\s*"\(.*\)"/\1/g')"
# These can be used for debugging.
# echo "Using connection URL: $CONN_URL"
# echo "Using prefix: $NAME_PREFIX"
# Get the names of our VMs from libvirt.
VMS="$(virsh -c $CONN_URL list --all | grep $NAME_PREFIX | awk '{print $2}')"
# Convert the lines of VM names to an array.
OLD_IFS=$IFS
IFS=$'\n'
VMS=($VMS)
IFS=$OLD_IFS
# Loop over our VM array and grab the ipv4 IP address from libvirt. Then add the
# result to VM_IP_PAIRS as <vm-name>:<ipv4-address>.
VM_IP_PAIRS=""
for VM in "${VMS[@]}"; do
for INTERFACE in $NET_INTERFACES; do
IP="$( \
virsh -c $CONN_URL qemu-agent-command $VM '{"execute": "guest-network-get-interfaces"}' | \
jq '.return[] | select(.name=="'"$INTERFACE"'") | ."ip-addresses"[] | select(."ip-address-type"=="ipv4") | ."ip-address"' | \
sed 's/"//g')"
# Add the VM:IP pair if IP is not empty.
if [ ! -z "$IP" ]; then
VM_IP_PAIRS="$VM_IP_PAIRS"$'\n'"$VM:$IP"
fi
done
done
# Write inventory
cat /dev/null > inventory
for GROUP in $INV_GROUPS; do
echo "[$GROUP]" >> inventory
echo "$VM_IP_PAIRS" | \
grep $GROUP | \
sed 's/^\(.*\):\(.*\)$/\1 ansible_host=\2/g' >> inventory
done
# Print vars
echo "$VM_IP_PAIRS" | \
sed 's/^\(.*\):\(.*\)$/\1=\2/g' | \
sed s/$NAME_PREFIX-//g | \
sed 's/-/_/g' | \
awk '{print toupper($1)}'
+12 -91
View File
@@ -1,98 +1,19 @@
#!/bin/bash #!/bin/sh
# This script will create environment variables for all of the output IPs. An
# anisble inventory file is created as well.
#
# Use eval $(./get-vm-ips.sh) to set env vars for ips. # Use eval $(./get-vm-ips.sh) to set env vars for ips.
terraform refresh > /dev/null terraform refresh > /dev/null
# The file to write the inventory to. This file will be completely overridden. IPS_JSON="$(terraform show -json | jq '.values.outputs')"
INVENTORY_FILE="inventory"
# Grab the the vm name prefix. We do this by greping all *.tfvars files making echo $IPS_JSON | \
# sure to cat terraform.tfvars last. Then we just grab the last grep result, jq '."master-ips".value[]' | \
# this way we make sure any value in terraform.tfvars will take priority. nl -v 0 | \
VM_NAME_PREFIX_VAR="vm-name-prefix" awk '{print "export MASTER" $1 "=" $2}' | \
VM_NAME_PREFIXES="$( \ sed 's/"//g'
find . -name "*.tfvars" -exec grep "$VM_NAME_PREFIX_VAR" {} \; && \
grep "$VM_NAME_PREFIX_VAR" terraform.tfvars)"
VM_NAME_PREFIX="$(
echo "$VM_NAME_PREFIXES" | \
tail -n 1 | \
sed 's/^.*=\s*"\(.*\)"/\1/g')"
PUBLIC_IP_OUTPUT="groups_hostnames_ips" echo $IPS_JSON | \
PRIVATE_IP_OUTPUT="groups_hostnames_private_ips" jq '."worker-ips".value[]' | \
IP_TYPE="$PRIVATE_IP_OUTPUT" nl -v 0 | \
awk '{print "export WORKER" $1 "=" $2}' | \
# This command stores the output data in the format below. sed 's/"//g'
# [
# {
# "group": "master",
# "vms": [
# {
# "hostname": "ansible-test-master-0",
# "ip": "52.14.114.48"
# }
# ]
# },
# {
# "group": "worker",
# "vms": [
# {
# "hostname": "ansible-test-worker-0",
# "ip": "3.145.121.159"
# },
# {
# "hostname": "ansible-test-worker-1",
# "ip": "18.217.112.176"
# }
# ]
# }
# ]
DATA="$(terraform show -json | \
jq '.values.outputs.'"$IP_TYPE"'.value | to_entries |
map({group: .key, vms:.value | to_entries |
map({hostname:.key,ip:.value})})')"
# Pull out the groups from $DATA. The format is a single string with the groups
# separated by spaces, ie. "group1 group2 group3".
ANS_GROUPS="$(
echo $DATA | \
jq '.[] | .group' | \
sed 's/"//g' | \
tr '\n' ' '
)"
# Clear the inventory file.
cat /dev/null > $INVENTORY_FILE
# For each group, write the VM info to $INVENTORY_FILE and also print a variable
# expression to stdout.
for GROUP in $ANS_GROUPS; do
# Write the inventory file to $INVENTORY_FILE.
echo "[$GROUP]" >> $INVENTORY_FILE
echo $DATA | \
jq '.[] | select(.group=="'"$GROUP"'") | .vms[] |
"\(.hostname) ansible_host=\(.ip)"' | \
sed 's/"//g' \
>> $INVENTORY_FILE
# For this group, collect expressions into VARS. The format is:
# HOSTNAME1=0.0.0.0
# HOSTNAME2=0.0.0.0
VARS="$(
echo -n $DATA | \
jq '.[] | select(.group=="'"$GROUP"'") | .vms[] |
"\(.hostname)=\(.ip)"' | \
sed 's/"//g' | \
sed "s/$VM_NAME_PREFIX-//g" | \
sed 's/-/_/g'
)"
# Print the contents of $VARS converted to uppercase. If it's not expty.
if [ ! -z "$VARS" ]; then
echo "${VARS^^}"
fi
done
+39 -365
View File
@@ -1,379 +1,53 @@
terraform {
locals { required_version = ">= 0.13"
old-k8s-subnets-ids = [ required_providers {
# module.aws-network-from-scratch.subnet.id, libvirt = {
module.aws-network-existing-managed.subnet-by-name["subnet_1"].id, source = "dmacvicar/libvirt"
module.aws-network-existing-managed.subnet-by-name["subnet_3"].id, version = "0.6.11"
] }
new-k8s-subnets-ids = [
module.aws-network-existing-mss-dev.subnet-by-name["mssdev Subnet 1"].id,
module.aws-network-existing-mss-dev.subnet-by-name["mssdev Subnet 3"].id,
]
nfs-subnets = [
# module.aws-network-from-scratch.subnet,
module.aws-network-existing-managed.subnet-by-name["subnet_4"],
]
aws-managed-security-group-id = module.aws-network-existing-managed.default-sg.id
aws-mss-dev-security-group-id = module.aws-network-existing-mss-dev.default-sg.id
# aws-managed-security-group-id = module.aws-network-from-scratch.default-security-group.id
# The names of these nodes is created by:
# "{var.vm-name-prefix}-{name from nodes-config}-{number}"
# The length of this full name must be < 16 characters. This is a limitaion of
# Active Directory? The "realm join" command failed when the name was too
# long, although it did not give the reason for the failure, the reason was
# surmised because it looked like it was truncating the name when attempting
# to join.
#
# NOTE: This naming restriction is only important if you plan on joining these
# VMs to Active Directory.
nodes-config = {
# TODO if the above comment about the name length is true, then this name is
# too long. IMPORTANT! If you change this then you need to change the k8s
# ansible role that assigns roles based on wether or not 'master' is in the
# name.
"k8s-master" = {
base-image = module.aws-ami-constants.ubuntu-ami
aws-ec2-type = module.ec2-types.t2-medium-4gib-2vcpu
subnet-ids = local.old-k8s-subnets-ids
security-groups = [local.aws-managed-security-group-id]
num = 1
},
"k8s-wrkr" = {
base-image = module.aws-ami-constants.ubuntu-ami
aws-ec2-type = module.ec2-types.c5a-xlarge-amd-8gib-4vcpu
subnet-ids = local.old-k8s-subnets-ids
security-groups = [local.aws-managed-security-group-id]
disk-size = 32
num = 2
},
"worker" = {
base-image = module.aws-ami-constants.ubuntu-ami
aws-ec2-type = module.ec2-types.c5a-xlarge-amd-8gib-4vcpu
subnet-ids = local.old-k8s-subnets-ids
security-groups = [local.aws-managed-security-group-id]
disk-size = 64
num = 3
},
"tst-master" = {
base-image = module.aws-ami-constants.ubuntu-ami
aws-ec2-type = module.ec2-types.t2-medium-4gib-2vcpu
subnet-ids = local.old-k8s-subnets-ids
security-groups = [local.aws-managed-security-group-id]
num = 0
},
"tst-wrkr" = {
base-image = module.aws-ami-constants.ubuntu-ami
aws-ec2-type = module.ec2-types.c5a-xlarge-amd-8gib-4vcpu
subnet-ids = local.old-k8s-subnets-ids
security-groups = [local.aws-managed-security-group-id]
disk-size = 32
num = 0
},
"rancher-master" = {
base-image = module.aws-ami-constants.ubuntu-ami
aws-ec2-type = module.ec2-types.c5a-xlarge-amd-8gib-4vcpu
subnet-ids = local.new-k8s-subnets-ids
security-groups = [local.aws-mss-dev-security-group-id]
disk-size = 64
num = 1
},
"rancher-worker" = {
base-image = module.aws-ami-constants.ubuntu-ami
aws-ec2-type = module.ec2-types.c5a-xlarge-amd-8gib-4vcpu
subnet-ids = local.new-k8s-subnets-ids
security-groups = [local.aws-mss-dev-security-group-id]
disk-size = 64
num = 2
},
"dev" = {
base-image = module.aws-ami-constants.ubuntu-ami
aws-ec2-type = module.ec2-types.c5a-xlarge-amd-8gib-4vcpu
# subnet-ids = [module.aws-network-from-scratch.subnet.id]
subnet-ids = [module.aws-network-existing-managed.subnet-by-name["subnet_4"].id]
security-groups = [local.aws-managed-security-group-id]
disk-size = 32
num = 2
},
"nfs" = {
base-image = module.aws-ami-constants.ubuntu-ami
aws-ec2-type = module.ec2-types.t3a-medium-amd-4gib-2vcpu
# subnet-ids = [module.aws-network-from-scratch.subnet.id]
subnet-ids = [module.aws-network-existing-managed.subnet-by-name["subnet_4"].id]
security-groups = [local.aws-managed-security-group-id]
num = 1
num-disks = 1
# TODO Remove this, prefferred method is to use 'disks' and 'disk-mounts'
# like shown below.
zfs-disk-size = 10
},
"proxy" = {
base-image = module.aws-ami-constants.ubuntu-ami
aws-ec2-type = module.ec2-types.t2-micro-1gib-1vcpu
# subnet-ids = [module.aws-network-from-scratch.subnet.id]
subnet-ids = [module.aws-network-existing-managed.subnet-by-name["subnet_4"].id]
security-groups = [local.aws-managed-security-group-id]
private-ips = [var.aws-proxy-private-ip]
num = 1
},
}
disks = {
"zfs-64g" = {
num = 1,
size = 64
availability_zone = local.nfs-subnets[0].availability_zone
},
"zfs-256g" = {
num = 1,
size = 256
availability_zone = local.nfs-subnets[0].availability_zone
},
}
disk-mounts = [
{
# TODO make this attach field work.
attach = false
ec2-id = module.nodes["nfs"].nodes[0].id,
disk-group = "zfs-64g"
# TODO also make sure that get drive letters or whetever still works. did
# it ever work?
# TODO We need to have a map of drive letters to device path in linux.
# This gets a little more complicated becuase the t2 instances map to
# /dev/xvdg while the t3a instance types map to /dev/nvme0n1 where 0 is
# the nth drive connected. The nth drive does not seem to map to a drive
# letter, ie. drive letter "f" does not map to 6, the nth drive simply
# increments by 1 for each drive attached regardless of the drive letter
# set.
drive-letters = ["g", "h", "i"]
},
{
# TODO make this attach field work.
attach = false
ec2-id = module.nodes["nfs"].nodes[0].id,
disk-group = "zfs-256g"
# TODO also make sure that get drive letters or whetever still works. did
# it ever work?
# TODO We need to have a map of drive letters to device path in linux.
# This gets a little more complicated becuase the t2 instances map to
# /dev/xvdg while the t3a instance types map to /dev/nvme0n1 where 0 is
# the nth drive connected. The nth drive does not seem to map to a drive
# letter, ie. drive letter "f" does not map to 6, the nth drive simply
# increments by 1 for each drive attached regardless of the drive letter
# set.
drive-letters = ["j", "k", "l"]
},
]
# This is only needed for libvirt.
install-qemu-agent = false
}
################################################################################
# cloud-init
################################################################################
module "cloud-init-config" {
for_each = local.nodes-config
source = "./modules/cloud-init-config"
cloud-init-template = "${path.module}/cloud_init.cfg"
hostname-prefix = "${var.vm-name-prefix}-${each.key}"
num = each.value.num
root-admin-passwd = var.root-admin-passwd
root-admin-pub-key = var.root-admin-pub-key
install-qemu-agent = local.install-qemu-agent
}
################################################################################
# aws
# To use the aws module, uncomment the aws modules/resources and comment out the
# libvirt modules/resources.
################################################################################
# This module sets the ec2-types constants.
module "ec2-types" {
source = "./modules/ec2-types"
}
# This module sets the AWS AMI constants.
module "aws-ami-constants" {
source = "./modules/aws-ami-constants"
}
# This module will grab the latest ami for a variety of distros. Uncomment to
# get a list of the latest AMIs for our supported distros.
# module "aws-amis" {
# source = "./modules/aws-amis"
# }
# output "amis" {
# value = module.aws-amis.amis
# }
################################################################################
# AWS Networking
# Use the 2 modules below to create resources for the AWS network.
# aws-network-from-scratch will build the AWS network from scratch.
# aws-network-existing will query AWS for an existing VPC.
################################################################################
# module "aws-network-from-scratch" {
# source = "./modules/aws-network-from-scratch"
# name-prefix = var.vm-name-prefix
# vpc-cidr-block = var.aws-vpc-cidr-block
# subnet-cidr-block = var.aws-subnet-cidr-block
# admin-ips = var.admin-ips
# }
module "aws-network-existing-managed" {
source = "./modules/aws-network-existing"
default-vpc-name = var.aws-existing-managed-vpc-name
default-security-group-name = var.aws-existing-managed-sg-name
existing-subnet-names = var.aws-existing-managed-subnet-names
}
module "aws-network-existing-mss-dev" {
source = "./modules/aws-network-existing"
default-vpc-name = var.aws-existing-mss-dev-vpc-name
default-security-group-name = var.aws-existing-mss-dev-sg-name
existing-subnet-names = var.aws-existing-mss-dev-subnet-names
}
################################################################################
# This key pair is not actually used. Keys are added to the nodes via cloud-init
# instead. We just add this here that this key will show up in the AWS console."
resource "aws_key_pair" "key" {
key_name = "${var.vm-name-prefix}-key}"
public_key = var.root-admin-pub-key
tags = {
Name = "${var.vm-name-prefix}-key"
} }
} }
module "disks" { provider "libvirt" {
for_each = local.disks uri = var.libvirt-connection-url
source = "./modules/aws-disks"
availability_zone = each.value.availability_zone
size = each.value.size
num = each.value.num
prefix = each.key
} }
module "disk-mounts" { module "master-nodes" {
source = "./modules/aws-disk-mounts" source = "./modules/node"
disks = module.disks[element(local.disk-mounts, count.index).disk-group].disks pool-name = libvirt_pool.images.name
ec2-id = element(local.disk-mounts, count.index).ec2-id name-prefix = "${var.vm-name-prefix}-master"
drive-letters = try(element(local.disk-mounts, count.index).drive-letters, null) num-nodes = var.master-nodes
count = length(local.disk-mounts) node-memory = var.node-memory
node-vcpus = var.node-vcpus
base-image = var.ubuntu-image
root-admin-passwd = var.root-admin-passwd
root-admin-pub-key = var.root-admin-pub-key
libvirt-connection-url = var.libvirt-connection-url
} }
# TODO REM remove if unuesed. module "worker-nodes" {
resource "aws_ebs_volume" "zfs" { source = "./modules/node"
# TODO REM look at types. pool-name = libvirt_pool.images.name
availability_zone = local.nfs-subnets[0].availability_zone name-prefix = "${var.vm-name-prefix}-worker"
size = local.nodes-config["nfs"].zfs-disk-size num-nodes = var.worker-nodes
encrypted = true node-memory = var.node-memory
count = local.nodes-config["nfs"].num-disks node-vcpus = var.node-vcpus
tags = { base-image = var.ubuntu-image
Name = "zfs-disk-${count.index}" root-admin-passwd = var.root-admin-passwd
} root-admin-pub-key = var.root-admin-pub-key
libvirt-connection-url = var.libvirt-connection-url
} }
resource "aws_volume_attachment" "mount-nfs-volume" { resource "libvirt_pool" "images" {
device_name = "/dev/sd${element(var.aws-zfs-drive-letters, count.index)}" name = var.disk-image-pool-name
instance_id = module.nodes["nfs"].nodes[0].id type = "dir"
count = local.nodes-config["nfs"].num-disks path = var.disk-image-dir
volume_id = element(aws_ebs_volume.zfs, count.index).id
} }
output "zfs-drive-letters" { output "master-ips" {
value = aws_volume_attachment.mount-nfs-volume.*.device_name value = module.master-nodes.ips
} }
module "nodes" { output "worker-ips" {
for_each = local.nodes-config value = module.worker-nodes.ips
source = "./modules/aws-nodes"
ec2-instance-type = each.value.aws-ec2-type
ami = each.value.base-image
subnet-ids = each.value.subnet-ids
private-ips = try(each.value.private-ips, [])
security-group-ids = each.value.security-groups
user-datas = lookup(module.cloud-init-config, each.key, null).user-datas
disk-size = try(each.value.disk-size, null)
num-nodes = each.value.num
name-prefix = "${var.vm-name-prefix}-${each.key}"
# TODO add a input for the key so that it will show up as the key in the aws
# console.
}
# TODO an attempt to create a windows machine.
# module "nodes-win" {
# source = "./modules/aws-nodes"
# ec2-instance-type = module.ec2-types.t2-small-2gib-1vcpu
# ami = module.aws-ami-constants.win-srv-2019-ami
# subnet-ids = [module.aws-network-existing-managed.subnet-by-name["subnet_2"].id]
# private-ips = []
# security-group-ids = [local.aws-managed-security-group-id]
# # TODO REM need to figure out how to not pass a user data.
# user-datas = [null]
# num-nodes = 1
# name-prefix = "${var.vm-name-prefix}-win-test"
# }
################################################################################
# end aws
################################################################################
################################################################################
# libvirt
# To use the libvirt module, uncomment the libvirt modules/resources and comment
# out the aws modules/resources.
################################################################################
# provider "libvirt" {
# uri = var.libvirt-connection-url
# }
#
# module "libvirt-images" {
# source = "./modules/libvirt-images"
# }
#
# module "nodes" {
# for_each = local.nodes-config
# source = "./modules/libvirt-nodes"
# pool-name = libvirt_pool.images.name
# name-prefix = "${var.vm-name-prefix}-${each.key}"
# num-nodes = each.value.num
# node-memory = var.node-memory
# node-vcpus = var.node-vcpus
# node-disk-size = var.libvirt-node-disk-size
# base-image = each.value.base-image
# network-name = var.libvirt-network-name
# root-admin-passwd = var.root-admin-passwd
# root-admin-pub-key = var.root-admin-pub-key
# libvirt-connection-url = var.libvirt-connection-url
# user-datas = lookup(module.cloud-init-config, each.key, null).user-datas
# }
#
# resource "libvirt_pool" "images" {
# name = var.disk-image-pool-name
# type = "dir"
# path = var.disk-image-dir
# }
################################################################################
# end libvirt
################################################################################
# This will outpus a map of group => [{hostname, ip}].
# TODO A 'names' output needs to be added to libvirt.
output "groups_hostnames_ips" {
value = { for type, node in module.nodes : type => zipmap(node.names, node.ips) }
}
# This will outpus a map of group => [{hostname, private_ip}].
# TODO Figure out how what to do about private_ips for libvirt.
output "groups_hostnames_private_ips" {
value = { for type, node in module.nodes : type => zipmap(node.names, node.private_ips) }
} }
-58
View File
@@ -1,58 +0,0 @@
################################################################################
# AWS AMI vars
# These outputs are really more like constants. Using outputs improves
# readability. The values are manually updated. Use the aws-amis module to get
# the latest for each distro. Keep in mind that AMIs are region specific this is
# why you may see values and other regions commented out.
################################################################################
output "amzn2-ami" {
# us-east-2
# default = "ami-0dd0ccab7e2801812"
# us-gov-west-1
value = "ami-02ab588324a95cf31"
description = "The AMI to use for Amazon Linux 2."
}
output "ubuntu-ami" {
# us-east-2
# value = "ami-06c7d6c0987eaa46c"
# us-gov-west-1
value = "ami-066189aeb91baa0ab"
description = "The AMI to use for Ubuntu."
}
output "centos7-ami" {
# us-east-2
value = "ami-00f8e2c955f7ffa9b"
description = "The AMI to use for CentOS 7."
}
output "centos8-ami" {
# us-east-2
value = "ami-057cacbfbbb471bb3"
description = "The AMI to use for CentOS 8."
}
output "arch-ami" {
# us-east-2
value = "ami-02653f06de985e3ba"
description = "The AMI to use for Arch Linux."
}
output "rhel7-ami" {
# us-east-2
# value = "ami-0a509b3c2a4d05b3f"
# us-gov-west-1
value = "ami-04ccdf5793086ea95"
description = "The AMI to use for RHEL 7."
}
output "rhel8-ami" {
# us-east-2
# value = "ami-0d871ca8a77af2948"
# us-gov-west-1
value = "ami-0b1f10cd1cd107dd2"
description = "The AMI to use for RHEL 8."
}
output "win-srv-2019-ami" {
# us-east-2
# value = ???
# us-gov-west-1
value = "ami-0f838c3c35ab60fc4"
description = "The AMI to use for Windows Server 2019."
}
-86
View File
@@ -1,86 +0,0 @@
locals {
amis = {
amzn2 = {
# us-east-2
# owner-id = "137112412989"
# us-gov-west-1
owner-id = "045324592363"
name = "amzn2-ami-hvm-2*x86_64-gp2"
},
ubuntu = {
# us-east-2
# owner-id = "099720109477"
# us-gov-west-1
owner-id = "513442679011"
name = "ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"
},
# centos7 = {
# # us-east-2
# # owner-id = "125523088429"
# # us-gov-west-1
# # owner-id = THERE IS NO CENTOS7 IMAGE in us-gov-west-1!!
# name = "CentOS 7.*x86_64"
# },
# centos8 = {
# # us-east-2
# # owner-id = "125523088429"
# # us-gov-west-1
# # owner-id = THERE IS NO CENTOS8 IMAGE in us-gov-west-1!!
# name = "CentOS 8.*x86_64"
# },
# arch = {
# # us-east-2
# # owner-id = "093273469852"
# # us-gov-west-1
# # owner-id = THERE IS NO ARCH IMAGE in us-gov-west-1!!
# name = "arch-linux-lts-hvm*x86_64-ebs"
# },
rhel7 = {
# us-east-2
# owner-id = "309956199498"
# us-gov-west-1
owner-id = "219670896067"
name = "RHEL-7.*HVM*x86_64*GP2"
},
rhel8 = {
# us-east-2
# owner-id = "309956199498"
# us-gov-west-1
owner-id = "219670896067"
name = "RHEL-8.*HVM*x86_64*GP2"
},
win-srv-2019 = {
# us-east-2
# owner-id = "???"
# us-gov-west-1
owner-id = "077303321853"
name = "Windows_Server-2019-English-Full-Base*"
},
}
}
data "aws_ami" "amis" {
for_each = local.amis
most_recent = true
owners = [each.value.owner-id]
filter {
name = "name"
values = [each.value.name]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "architecture"
values = ["x86_64"]
}
filter {
name = "root-device-type"
values = ["ebs"]
}
}
-3
View File
@@ -1,3 +0,0 @@
output "amis" {
value = tomap({ for type, ami in data.aws_ami.amis : type => ami.id })
}
-6
View File
@@ -1,6 +0,0 @@
resource "aws_volume_attachment" "mount-volume" {
device_name = "/dev/sd${element(var.drive-letters, count.index)}"
instance_id = var.ec2-id
count = length(var.disks)
volume_id = element(var.disks, count.index).id
}
View File
-16
View File
@@ -1,16 +0,0 @@
variable "drive-letters" {
default = ["f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
description = "These drive letters will be used when arraching disks to EC2 instance with `ec2-id'"
type = list(string)
nullable = false
}
variable "disks" {
description = "An array of disks to attach to the EC2 isntance with `ec2-id`"
type = list
}
variable "ec2-id" {
description = "The ID of the EC@ instance to attach the drives to."
type = string
}
-10
View File
@@ -1,10 +0,0 @@
resource "aws_ebs_volume" "disks" {
availability_zone = var.availability_zone
size = var.size
count = var.num
encrypted = true
tags = {
Name = "${var.prefix}-${count.index}"
}
}
-3
View File
@@ -1,3 +0,0 @@
output "disks" {
value = aws_ebs_volume.disks
}
-19
View File
@@ -1,19 +0,0 @@
variable "availability_zone" {
description = "The availability zone this disk will reside in. This AZ is applied to all 'num' disks."
type = string
}
variable "num" {
description = "The number of disks to be created with this config."
type = number
}
variable "prefix" {
description = "This prefix will be used in the name of each disk created with this module. If the prefix is 'zfs', then it will create disks with names, zfs-0 and zfs-1."
type = string
}
variable "size" {
description = "The size of the disk in GB."
type = number
}
-35
View File
@@ -1,35 +0,0 @@
locals {
az-to-subnets = {
for s in data.aws_subnet.subnets : s.availability_zone => s.id...
}
}
data "aws_vpc" "default" {
tags = {
Name = var.default-vpc-name
}
}
data "aws_subnets" "subnet-ids" {
filter {
name = "vpc-id"
values = [data.aws_vpc.default.id]
}
}
data "aws_subnet" "subnets" {
for_each = toset(data.aws_subnets.subnet-ids.ids)
id = each.key
}
data "aws_subnet" "subnet-by-name" {
for_each = toset(var.existing-subnet-names)
filter {
name = "tag:Name"
values = [each.key]
}
}
data "aws_security_group" "default" {
name = var.default-security-group-name
}
-27
View File
@@ -1,27 +0,0 @@
output "default-vpc" {
value = data.aws_vpc.default
}
output "default-sg" {
value = data.aws_security_group.default
}
output "subnets" {
description = "An array of all subnets in default-vpc."
value = data.aws_subnet.subnets
}
output "one-subnet-per-az" {
description = "An array of subnets that selects 1 subnet per az."
value = [for k,v in local.az-to-subnets : v[0]]
}
output "subnet-by-name" {
description = "A map of subnet name to subnet resource."
value = data.aws_subnet.subnet-by-name
}
output "az-to-subnets" {
description = "A map of availability zone to array of subnets that are in thet availability zone."
value = local.az-to-subnets
}
-13
View File
@@ -1,13 +0,0 @@
variable "default-security-group-name" {
description = "The name of the existing default security group. This module will query AWS for a security group with this name,"
}
variable "default-vpc-name" {
description = "The name of the existing default VPC. This module will query AWS for a VPC with this name,"
}
variable "existing-subnet-names" {
description = "A list of subnet names that already exist in default-vpc-name"
default = []
type = list(string)
}
-67
View File
@@ -1,67 +0,0 @@
resource "aws_vpc" "vpc" {
cidr_block = var.vpc-cidr-block
tags = {
Name = "${var.name-prefix}-vpc"
}
}
resource "aws_subnet" "subnet" {
vpc_id = aws_vpc.vpc.id
cidr_block = var.subnet-cidr-block
# availability_zone = var.avail_zone
tags = {
Name = "${var.name-prefix}-subnet"
}
}
resource "aws_default_security_group" "sg" {
vpc_id = aws_vpc.vpc.id
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = var.admin-ips
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
prefix_list_ids = []
}
tags = {
Name = "${var.name-prefix}-ssh-from-admins-sg"
}
}
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.vpc.id
tags = {
Name = "${var.name-prefix}-igw"
}
}
resource "aws_default_route_table" "route-table" {
default_route_table_id = aws_vpc.vpc.main_route_table_id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}
# default route, mapping VPC CIDR block to "local", created implicitly and
# cannot be specified.
tags = {
Name = "${var.name-prefix}-route-table"
}
}
# Associate subnet with Route Table
resource "aws_route_table_association" "a-rtb-subnet" {
subnet_id = aws_subnet.subnet.id
route_table_id = aws_default_route_table.route-table.id
}
@@ -1,11 +0,0 @@
output "vpc" {
value = aws_vpc.vpc
}
output "subnet" {
value = aws_subnet.subnet
}
output "default-security-group" {
value = aws_default_security_group.sg
}
@@ -1,23 +0,0 @@
variable "admin-ips" {
description = "A list of ips or cidr blocks that are allowed to connect to the nodes."
type = list(string)
}
variable "name-prefix" {
default = "tf"
description = "This prefix will be used in all the names of the resources creates in our AWS network."
type = string
}
variable "subnet-cidr-block" {
default = "10.0.1.0/24"
description = "The address space to be used for this subnet."
type = string
}
variable "vpc-cidr-block" {
default = "10.0.0.0/16"
description = "The address space to be used for out networks VPC."
type = string
}
-67
View File
@@ -1,67 +0,0 @@
resource "aws_vpc" "vpc" {
cidr_block = var.vpc-cidr-block
tags = {
Name = "${var.name-prefix}-vpc"
}
}
resource "aws_subnet" "subnet" {
vpc_id = aws_vpc.vpc.id
cidr_block = var.subnet-cidr-block
# availability_zone = var.avail_zone
tags = {
Name = "${var.name-prefix}-subnet"
}
}
resource "aws_default_security_group" "sg" {
vpc_id = aws_vpc.vpc.id
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = var.admin-ips
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
prefix_list_ids = []
}
tags = {
Name = "${var.name-prefix}-ssh-from-admins-sg"
}
}
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.vpc.id
tags = {
Name = "${var.name-prefix}-igw"
}
}
resource "aws_default_route_table" "route-table" {
default_route_table_id = aws_vpc.vpc.main_route_table_id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}
# default route, mapping VPC CIDR block to "local", created implicitly and
# cannot be specified.
tags = {
Name = "${var.name-prefix}-route-table"
}
}
# Associate subnet with Route Table
resource "aws_route_table_association" "a-rtb-subnet" {
subnet_id = aws_subnet.subnet.id
route_table_id = aws_default_route_table.route-table.id
}
-11
View File
@@ -1,11 +0,0 @@
output "vpc" {
value = aws_vpc.vpc
}
output "subnet" {
value = aws_subnet.subnet
}
output "default-security-group" {
value = aws_default_security_group.sg
}
-23
View File
@@ -1,23 +0,0 @@
variable "admin-ips" {
description = "A list of ips or cidr blocks that are allowed to connect to the nodes."
type = list(string)
}
variable "name-prefix" {
default = "tf"
description = "This prefix will be used in all the names of the resources creates in our AWS network."
type = string
}
variable "subnet-cidr-block" {
default = "10.0.1.0/24"
description = "The address space to be used for this subnet."
type = string
}
variable "vpc-cidr-block" {
default = "10.0.0.0/16"
description = "The address space to be used for out networks VPC."
type = string
}
-21
View File
@@ -1,21 +0,0 @@
resource "aws_instance" "nodes" {
ami = var.ami
instance_type = var.ec2-instance-type
# TODO Make this a variable.
associate_public_ip_address = true
subnet_id = element(var.subnet-ids, count.index % length(var.subnet-ids))
# Set a private IP if var.private-ips is not empty, otherwise let AWS assign
# the IP.
private_ip = length(var.private-ips) == 0 ? null : element(var.private-ips, count.index)
vpc_security_group_ids = var.security-group-ids
user_data = element(var.user-datas.*.rendered, count.index)
root_block_device {
volume_size = var.disk-size
delete_on_termination = true
}
count = var.num-nodes
tags = {
Name = "${var.name-prefix}-${count.index}"
}
}
-15
View File
@@ -1,15 +0,0 @@
output "ips" {
value = aws_instance.nodes.*.public_ip
}
output "private_ips" {
value = aws_instance.nodes.*.private_ip
}
output "names" {
value = aws_instance.nodes.*.tags.Name
}
output "nodes" {
value = aws_instance.nodes
}
-48
View File
@@ -1,48 +0,0 @@
variable "ami" {
description = "The AWS AMI to be used for all the nodes"
type = string
}
variable "disk-size" {
default = 8
description = "The size of the root FS disk in GB."
type = number
}
variable "ec2-instance-type" {
default = "t2.micro"
description = "The AWS instance type to use for all nodes."
type = string
}
variable "name-prefix" {
default = "tf-node"
description = "This prefix will be applied to all names created by this module."
type = string
}
variable "num-nodes" {
default = 1
description = "The number of nodes to create from the given input parameters."
type = number
}
variable "private-ips" {
default = []
description = "A list of private IP addresses to use for the nodes. If the list is empty then each node will get an IP assigned from AWS."
type = list(string)
}
variable "user-datas" {
description = "A list of cloud-init configs that get applied to their corresponding node."
}
variable "subnet-ids" {
description = "An array of subnet ids. These subnets will be round robined as the subnet to use for each node."
type = list(string)
}
variable "security-group-ids" {
description = "A list of security group IDs to be applied to all the nodes."
type = list(string)
}
-10
View File
@@ -1,10 +0,0 @@
data "template_file" "user-datas" {
template = file("${var.cloud-init-template}")
vars = {
admin-passwd = "${var.root-admin-passwd}"
admin-pub-key = "${var.root-admin-pub-key}"
hostname = "${var.hostname-prefix}-${count.index}"
install-qemu-agent = var.install-qemu-agent
}
count = var.num
}
-3
View File
@@ -1,3 +0,0 @@
output "user-datas" {
value = data.template_file.user-datas
}
-28
View File
@@ -1,28 +0,0 @@
variable "cloud-init-template" {
default = "../../cloud_init.cfg"
description = "The path to the cloud-init config template."
type = string
}
variable "hostname-prefix" {
description = "This prefix wil be applied as a prefix for the hostnames."
}
variable "install-qemu-agent" {
default = false
description = "This flag determines whether or not qemu-agent is installed."
type = bool
}
variable "num" {
description = "The number of user-datas to create with these parameters."
}
variable "root-admin-passwd" {
description = "This value will be substituted for any occurence of 'admin-password' in the cloud-init config template."
}
variable "root-admin-pub-key" {
description = "This value will be substituted for any occurence of 'admin-pub-key' in the cloud-init config template."
}
-45
View File
@@ -1,45 +0,0 @@
################################################################################
# AWS EC2 types.
# Thesee are only here to help readability. Using these outputs allows the user
# to be able to see the resources of each type without having to look them up.
################################################################################
output "t2-micro-1gib-1vcpu" {
description = "t2.micro EC2 instance with 1 GiB mem and 1 vCPU."
value = "t2.micro"
}
output "t2-small-2gib-1vcpu" {
description = "t2.small EC2 instance with 2 GiB mem and 1 vCPUs."
value = "t2.small"
}
output "t2-medium-4gib-2vcpu" {
description = "t2.medium EC2 instance with 4 GiB mem and 2 vCPUs."
value = "t2.medium"
}
output "t2-large-8gib-2vcpu" {
description = "t2.large EC2 instance with 8 GiB mem and 2 vCPUs."
value = "t2.large"
}
output "t2-xlarge-16gib-4vcpu" {
description = "t2.xlarge EC2 instance with 16 GiB mem and 4 vCPUs."
value = "t2.xlarge"
}
output "t3a-medium-amd-4gib-2vcpu" {
description = "t3a.medium EC2 instance on AMD with GiB mem and 2 vCPUs."
value = "t3a.medium"
}
output "t3a-large-amd-8gib-2vcpu" {
description = "t3a.large EC2 instance on AMD with 8 GiB mem and 2 vCPUs."
value = "t3a.large"
}
output "c5a-xlarge-amd-8gib-4vcpu" {
description = "c5a.xlarge EC2 instance on AMD with 8 GiB mem and 4 vCPUs."
value = "c5a.xlarge"
}
-22
View File
@@ -1,22 +0,0 @@
################################################################################
# Libvirt Images
# These outputs are really more like constants. Using outputs improves
# readability. The values are manually updated.
################################################################################
output "ubuntu-img" {
value = "https://cloud-images.ubuntu.com/releases/focal/release/ubuntu-20.04-server-cloudimg-amd64-disk-kvm.img"
description = "The libvirt image to use for Ubuntu."
}
output "centos7-img" {
# Latest as of 2021-12-06.
value = "https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-2111.qcow2"
description = "The libvirt image to use for CentOS 7."
}
output "centos8-img" {
value = "https://cloud.centos.org/centos/8/x86_64/images/CentOS-8-GenericCloud-8.4.2105-20210603.0.x86_64.qcow2"
description = "The libvirt image to use for CentOS 8."
}
-6
View File
@@ -1,6 +0,0 @@
# This only works on the default network. They will not work using the bridged
# network.
# output "ips" {
# value = libvirt_domain.nodes.*.network_interface.0.addresses.0
# }
@@ -8,19 +8,26 @@ terraform {
} }
} }
provider "libvirt" {
uri = var.libvirt-connection-url
}
resource "libvirt_volume" "node-images" { resource "libvirt_volume" "node-images" {
name = "${var.name-prefix}-base" name = "${var.name-prefix}-${count.index}"
pool = var.pool-name pool = var.pool-name
source = var.base-image source = var.base-image
count = var.num-nodes
format = "qcow2" format = "qcow2"
} }
resource "libvirt_volume" "node-images-resized" { data "template_file" "node-user-datas" {
name = "${var.name-prefix}-${count.index}-resized" template = file("${path.module}/cloud_init.cfg")
pool = var.pool-name vars = {
base_volume_id = libvirt_volume.node-images.id admin-passwd = "${var.root-admin-passwd}"
count = var.num-nodes admin-pub-key = "${var.root-admin-pub-key}"
size = var.node-disk-size hostname = "${var.name-prefix}-${count.index}"
}
count = var.num-nodes
} }
data "template_file" "network-config" { data "template_file" "network-config" {
@@ -29,24 +36,24 @@ data "template_file" "network-config" {
resource "libvirt_cloudinit_disk" "node-inits" { resource "libvirt_cloudinit_disk" "node-inits" {
name = "${var.name-prefix}-${count.index}-init" name = "${var.name-prefix}-${count.index}-init"
user_data = element(var.user-datas.*.rendered, count.index) user_data = element(data.template_file.node-user-datas.*.rendered, count.index)
network_config = data.template_file.network-config.rendered network_config = data.template_file.network-config.rendered
pool = var.pool-name pool = var.pool-name
count = var.num-nodes count = var.num-nodes
} }
resource "libvirt_domain" "nodes" { resource "libvirt_domain" "nodes" {
count = var.num-nodes count = var.num-nodes
name = "${var.name-prefix}-${count.index}" name = "${var.name-prefix}-${count.index}"
memory = var.node-memory memory = var.node-memory
vcpu = var.node-vcpus vcpu = var.node-vcpus
cloudinit = element(libvirt_cloudinit_disk.node-inits.*.id, count.index) cloudinit = element(libvirt_cloudinit_disk.node-inits.*.id, count.index)
network_interface { network_interface {
network_name = var.network-name network_name = "default"
hostname = "${var.name-prefix}-${count.index}" hostname = "${var.name-prefix}-${count.index}"
# wait_for_lease = true wait_for_lease = true
} }
# IMPORTANT: this is a known bug on cloud images, since they expect a console # IMPORTANT: this is a known bug on cloud images, since they expect a console
@@ -65,7 +72,7 @@ resource "libvirt_domain" "nodes" {
} }
disk { disk {
volume_id = element(libvirt_volume.node-images-resized.*.id, count.index) volume_id = element(libvirt_volume.node-images.*.id, count.index)
} }
graphics { graphics {
+4
View File
@@ -0,0 +1,4 @@
output "ips" {
value = libvirt_domain.nodes.*.network_interface.0.addresses.0
}
@@ -12,16 +12,6 @@ variable "name-prefix" {
description = "This will be a prefix for all resource names, ie. domains will be created suck as \"k8s-node-2\"." description = "This will be a prefix for all resource names, ie. domains will be created suck as \"k8s-node-2\"."
} }
variable "network-name" {
default = "default"
description = "The name of a pre-existing virtual-network."
}
variable "node-disk-size" {
default = 4294967296
description = "The size of the disk to be used for libvirt nodes. (in bytes)"
}
variable "node-memory" { variable "node-memory" {
default = "2048" default = "2048"
description = "The amount of memory to be used for all the nodes." description = "The amount of memory to be used for all the nodes."
@@ -34,10 +24,6 @@ variable "node-vcpus" {
type = number type = number
} }
variable "user-datas" {
description = "A list of cloud-init configs that get applied to their corresponding node."
}
variable "num-nodes" { variable "num-nodes" {
description = "The number of nodes to create with this config." description = "The number of nodes to create with this config."
} }
-77
View File
@@ -1,77 +0,0 @@
provider "aws" {
region = var.aws-region
# profile = <aws cli profile>
}
terraform {
required_version = ">= 1.0.8"
backend "s3" {
bucket = "mss-terraform-state"
key = "global/s3/terraform.tfstate"
region = "us-gov-west-1"
dynamodb_table = "mss-terraform-state-lock"
encrypt = true
}
required_providers {
libvirt = {
source = "dmacvicar/libvirt"
version = "0.6.11"
}
}
}
##
#S3 bucket create to hold our TFState file so we can all share env settings
resource "aws_s3_bucket" "terraform_state" {
bucket = "mss-terraform-state"
# enable versioning for the state files
versioning {
enabled = true
}
#enable server-side encryption
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
}
##
# no sql database used so that we can lock the TFstate file in the S3 bucket to ensure two people
# are not running a terraform command at the same time
resource "aws_dynamodb_table" "terraform_locks" {
name = "mss-terraform-state-lock"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}
##
# output variable to give details on the s3 bucket created
#TODO: move to output.tf
output "s3_bucket_arn" {
value = aws_s3_bucket.terraform_state.arn
description = "The ARN of the S3 bucket"
}
+13 -89
View File
@@ -1,80 +1,3 @@
variable "admin-ips" {
default = ["0.0.0.0/0"]
description = "A list of ips or cidr blocks that are allowed to connect to the nodes. This variable is only used when using the aws-network-from-scratch module."
type = list(string)
}
variable "aws-zfs-drive-letters" {
default = ["f", "g", "h", "i", "j"]
description = "These are the drove letters to use when attaching EBS volumes, ie. /dev/sdf or /dev/sdg"
type = list(string)
}
################################################################################
# Query existing infrastructure.
# Variables used to grab existing resources from AWS.
#
# We have 2 sets of three variables in this section. 1 section has 'managed' in
# the name and the other has 'mss-dev' in the name. There are not restrictions
# as to what we can put into these VPCs. The names of the variable simply match
# the names of the VPCs and have no meaning for what resources are allowed.
################################################################################
variable "aws-existing-managed-sg-name" {
default = "change-me-if-using-aws-network-existing"
description = "The name of the existing security group when using aws-network-existing."
}
variable "aws-existing-managed-vpc-name" {
default = "change-me-if-using-aws-network-existing"
description = "The name of the existing VPC when using aws-network-existing."
}
variable "aws-existing-managed-subnet-names" {
description = "A list of subnet names that already exist in aws-existing-managed-vpc-name"
default = []
type = list(string)
}
variable "aws-existing-mss-dev-sg-name" {
default = "change-me-if-using-aws-network-existing"
description = "The name of the existing security group when using aws-network-existing with the mss-dev VPC."
}
variable "aws-existing-mss-dev-vpc-name" {
default = "change-me-if-using-aws-network-existing"
description = "The name of the existing VPC when using aws-network-existing with the mss-dev VPC."
}
variable "aws-existing-mss-dev-subnet-names" {
description = "A list of subnet names that already exist in aws-existing-mss-dev-vpc-name"
default = []
type = list(string)
}
################################################################################
# End query existing infrastructure.
################################################################################
variable "aws-proxy-private-ip" {
description = "The private IP to request for the proxy instance."
type = string
}
variable "aws-region" {
default = "us-east-1"
description = "The AWS region to use."
}
variable "aws-subnet-cidr-block" {
default = "10.0.1.0/24"
description = "The address space to be used for this subnet."
}
variable "aws-vpc-cidr-block" {
default = "10.0.0.0/16"
description = "The address space to be used for the VPC that all the AWS nodes will be in."
}
variable "disk-image-dir" { variable "disk-image-dir" {
description = "This is the location on the KVM hypervisor host where all the disk images will be kept." description = "This is the location on the KVM hypervisor host where all the disk images will be kept."
@@ -86,20 +9,9 @@ variable "disk-image-pool-name" {
} }
variable "libvirt-connection-url" { variable "libvirt-connection-url" {
default = "nobody@localhost"
description = "The libvirt connection URI, ie. qemu+ssh://<user>@<host>/system" description = "The libvirt connection URI, ie. qemu+ssh://<user>@<host>/system"
} }
variable "libvirt-network-name" {
default = "default"
description = "The name of a pre-existing libvirt virtual-network."
}
variable "libvirt-node-disk-size" {
default = 4294967296
description = "The size of the disk to be used for libvirt nodes. (in bytes)"
}
variable "node-memory" { variable "node-memory" {
default = "2048" default = "2048"
description = "The amount of memory to be used for all the nodes." description = "The amount of memory to be used for all the nodes."
@@ -120,7 +32,19 @@ variable "root-admin-pub-key" {
description = "The public key to be added to authorized_keys for the root and admin accounts." description = "The public key to be added to authorized_keys for the root and admin accounts."
} }
variable "base-image" { variable "master-nodes" {
default = 1
description = "The number of master nodes to create."
type = number
}
variable "worker-nodes" {
default = 2
description = "The number of worker nodes to create."
type = number
}
variable "ubuntu-image" {
default = "https://cloud-images.ubuntu.com/releases/focal/release/ubuntu-20.04-server-cloudimg-amd64-disk-kvm.img" default = "https://cloud-images.ubuntu.com/releases/focal/release/ubuntu-20.04-server-cloudimg-amd64-disk-kvm.img"
} }