2020-12-25 20:10:27 +00:00
# Kubernetes on AWS with Terraform
2016-06-07 19:45:25 +00:00
2020-12-25 20:10:27 +00:00
## Overview
2016-06-07 19:45:25 +00:00
2017-03-01 17:25:58 +00:00
This project will create:
2016-06-07 19:45:25 +00:00
2020-12-25 20:10:27 +00:00
- VPC with Public and Private Subnets in # Availability Zones
- Bastion Hosts and NAT Gateways in the Public Subnet
- A dynamic number of masters, etcd, and worker nodes in the Private Subnet
- even distributed over the # of Availability Zones
- AWS ELB in the Public Subnet for accessing the Kubernetes API from the internet
## Requirements
2019-12-12 11:42:33 +00:00
- Terraform 0.12.0 or newer
2016-06-07 19:45:25 +00:00
2020-12-25 20:10:27 +00:00
## How to Use
2016-06-07 19:45:25 +00:00
2017-04-12 13:11:39 +00:00
- Export the variables for your AWS credentials or edit `credentials.tfvars` :
2016-06-07 19:45:25 +00:00
2020-12-25 20:10:27 +00:00
```commandline
2018-07-05 09:20:02 +00:00
export TF_VAR_AWS_ACCESS_KEY_ID="www"
export TF_VAR_AWS_SECRET_ACCESS_KEY ="xxx"
export TF_VAR_AWS_SSH_KEY_NAME="yyy"
export TF_VAR_AWS_DEFAULT_REGION="zzz"
2016-06-07 19:45:25 +00:00
```
2020-12-25 20:10:27 +00:00
2020-08-28 09:28:53 +00:00
- Update `contrib/terraform/aws/terraform.tfvars` with your data. By default, the Terraform scripts use Ubuntu 18.04 LTS (Bionic) as base image. If you want to change this behaviour, see note "Using other distrib than Ubuntu" below.
2017-09-05 15:41:47 +00:00
- Create an AWS EC2 SSH Key
2017-04-12 13:11:39 +00:00
- Run with `terraform apply --var-file="credentials.tfvars"` or `terraform apply` depending if you exported your AWS credentials
2017-09-05 15:41:47 +00:00
Example:
2020-12-25 20:10:27 +00:00
2017-09-05 15:41:47 +00:00
```commandline
2018-05-08 09:25:52 +00:00
terraform apply -var-file=credentials.tfvars
2017-09-05 15:41:47 +00:00
```
2017-04-12 13:11:39 +00:00
- Terraform automatically creates an Ansible Inventory file called `hosts` with the created infrastructure in the directory `inventory`
2022-08-24 13:54:03 +00:00
- Ansible will automatically generate an ssh config file for your bastion hosts. To connect to hosts with ssh using bastion host use generated `ssh-bastion.conf` . Ansible automatically detects bastion and changes `ssh_args`
2020-12-25 20:10:27 +00:00
2017-09-07 20:26:52 +00:00
```commandline
2017-11-30 15:27:52 +00:00
ssh -F ./ssh-bastion.conf user@$ip
2017-09-07 20:26:52 +00:00
```
2017-06-16 17:25:46 +00:00
- Once the infrastructure is created, you can run the kubespray playbooks and supply inventory/hosts with the `-i` flag.
2016-06-07 19:45:25 +00:00
2020-08-28 09:28:53 +00:00
Example (this one assumes you are using Ubuntu)
2020-12-25 20:10:27 +00:00
2017-09-05 15:41:47 +00:00
```commandline
2020-08-28 09:28:53 +00:00
ansible-playbook -i ./inventory/hosts ./cluster.yml -e ansible_user=ubuntu -b --become-user=root --flush-cache
2017-09-05 15:41:47 +00:00
```
2020-12-25 20:10:27 +00:00
2020-08-28 09:28:53 +00:00
***Using other distrib than Ubuntu***
If you want to use another distribution than Ubuntu 18.04 (Bionic) LTS, you can modify the search filters of the 'data "aws_ami" "distro"' in variables.tf.
2017-11-30 15:27:52 +00:00
For example, to use:
2020-10-29 01:30:59 +00:00
2017-11-30 15:27:52 +00:00
- Debian Jessie, replace 'data "aws_ami" "distro"' in variables.tf with
2020-10-29 01:30:59 +00:00
2020-12-25 20:10:27 +00:00
```ini
2017-11-30 15:27:52 +00:00
data "aws_ami" "distro" {
most_recent = true
filter {
name = "name"
values = ["debian-jessie-amd64-hvm-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["379101102735"]
}
2020-10-29 01:30:59 +00:00
```
2017-11-30 15:27:52 +00:00
- Ubuntu 16.04, replace 'data "aws_ami" "distro"' in variables.tf with
2020-10-29 01:30:59 +00:00
2020-12-25 20:10:27 +00:00
```ini
2017-11-30 15:27:52 +00:00
data "aws_ami" "distro" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["099720109477"]
}
2020-10-29 01:30:59 +00:00
```
2017-11-30 15:27:52 +00:00
- Centos 7, replace 'data "aws_ami" "distro"' in variables.tf with
2020-10-29 01:30:59 +00:00
2020-12-25 20:10:27 +00:00
```ini
2017-11-30 15:27:52 +00:00
data "aws_ami" "distro" {
most_recent = true
filter {
name = "name"
values = ["dcos-centos7-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["688023202711"]
}
2020-10-29 01:30:59 +00:00
```
## Connecting to Kubernetes
You can use the following set of commands to get the kubeconfig file from your newly created cluster. Before running the commands, make sure you are in the project's root folder.
2020-12-25 20:10:27 +00:00
```commandline
2020-10-29 01:30:59 +00:00
# Get the controller's IP address.
2021-03-24 00:26:05 +00:00
CONTROLLER_HOST_NAME=$(cat ./inventory/hosts | grep "\[kube_control_plane\]" -A 1 | tail -n 1)
2020-10-29 01:30:59 +00:00
CONTROLLER_IP=$(cat ./inventory/hosts | grep $CONTROLLER_HOST_NAME | grep ansible_host | cut -d'=' -f2)
# Get the hostname of the load balancer.
LB_HOST=$(cat inventory/hosts | grep apiserver_loadbalancer_domain_name | cut -d'"' -f2)
# Get the controller's SSH fingerprint.
ssh-keygen -R $CONTROLLER_IP > /dev/null 2>& 1
ssh-keyscan -H $CONTROLLER_IP >> ~/.ssh/known_hosts 2>/dev/null
# Get the kubeconfig from the controller.
mkdir -p ~/.kube
ssh -F ssh-bastion.conf centos@$CONTROLLER_IP "sudo chmod 644 /etc/kubernetes/admin.conf"
scp -F ssh-bastion.conf centos@$CONTROLLER_IP:/etc/kubernetes/admin.conf ~/.kube/config
sed -i "s^server:.*^server: https://$LB_HOST:6443^" ~/.kube/config
kubectl get nodes
```
2017-09-05 15:41:47 +00:00
2020-12-25 20:10:27 +00:00
## Troubleshooting
2017-04-12 13:11:39 +00:00
2020-12-25 20:10:27 +00:00
### Remaining AWS IAM Instance Profile
2017-04-12 13:11:39 +00:00
If the cluster was destroyed without using Terraform it is possible that
the AWS IAM Instance Profiles still remain. To delete them you can use
the `AWS CLI` with the following command:
2020-12-25 20:10:27 +00:00
```commandline
2017-04-12 13:11:39 +00:00
aws iam delete-instance-profile --region < region_name > --instance-profile-name < profile_name >
```
2020-12-25 20:10:27 +00:00
### Ansible Inventory doesn't get created
2017-04-12 13:11:39 +00:00
2018-10-31 13:27:58 +00:00
It could happen that Terraform doesn't create an Ansible Inventory file automatically. If this is the case copy the output after `inventory=` and create a file named `hosts` in the directory `inventory` and paste the inventory into the file.
2017-04-12 13:11:39 +00:00
2020-12-25 20:10:27 +00:00
## Architecture
2016-06-07 19:45:25 +00:00
2017-03-01 17:25:58 +00:00
Pictured is an AWS Infrastructure created with this Terraform project distributed over two Availability Zones.
2016-06-07 19:45:25 +00:00
2017-06-16 17:25:46 +00:00
![AWS Infrastructure with Terraform ](docs/aws_kubespray.png )