238 lines
9.5 KiB
Markdown
238 lines
9.5 KiB
Markdown
# AWS
|
|
|
|
In this tutorial, we'll create a Kubernetes v1.9.1 cluster on AWS.
|
|
|
|
We'll declare a Kubernetes cluster in Terraform using the Typhoon Terraform module. On apply, a VPC, gateway, subnets, auto-scaling groups of controllers and workers, network load balancers for controllers and workers, and security groups will be created.
|
|
|
|
Controllers and workers are provisioned to run a `kubelet`. A one-time [bootkube](https://github.com/kubernetes-incubator/bootkube) bootstrap schedules an `apiserver`, `scheduler`, `controller-manager`, and `kube-dns` on controllers and runs `kube-proxy` and `calico` or `flannel` on each node. A generated `kubeconfig` provides `kubectl` access to the cluster.
|
|
|
|
## Requirements
|
|
|
|
* AWS Account and IAM credentials
|
|
* AWS Route53 DNS Zone (registered Domain Name or delegated subdomain)
|
|
* Terraform v0.10.x and [terraform-provider-ct](https://github.com/coreos/terraform-provider-ct) installed locally
|
|
|
|
## Terraform Setup
|
|
|
|
Install [Terraform](https://www.terraform.io/downloads.html) v0.10.x on your system.
|
|
|
|
```sh
|
|
$ terraform version
|
|
Terraform v0.10.7
|
|
```
|
|
|
|
Add the [terraform-provider-ct](https://github.com/coreos/terraform-provider-ct) plugin binary for your system.
|
|
|
|
```sh
|
|
wget https://github.com/coreos/terraform-provider-ct/releases/download/v0.2.0/terraform-provider-ct-v0.2.0-linux-amd64.tar.gz
|
|
tar xzf terraform-provider-ct-v0.2.0-linux-amd64.tar.gz
|
|
sudo mv terraform-provider-ct-v0.2.0-linux-amd64/terraform-provider-ct /usr/local/bin/
|
|
```
|
|
|
|
Add the plugin to your `~/.terraformrc`.
|
|
|
|
```
|
|
providers {
|
|
ct = "/usr/local/bin/terraform-provider-ct"
|
|
}
|
|
```
|
|
|
|
Read [concepts](concepts.md) to learn about Terraform, modules, and organizing resources. Change to your infrastructure repository (e.g. `infra`).
|
|
|
|
```
|
|
cd infra/clusters
|
|
```
|
|
|
|
## Provider
|
|
|
|
Login to your AWS IAM dashboard and find your IAM user. Select "Security Credentials" and create an access key. Save the id and secret to a file that can be referenced in configs.
|
|
|
|
```
|
|
[default]
|
|
aws_access_key_id = xxx
|
|
aws_secret_access_key = yyy
|
|
```
|
|
|
|
Configure the AWS provider to use your access key credentials in a `providers.tf` file.
|
|
|
|
```tf
|
|
provider "aws" {
|
|
region = "eu-central-1"
|
|
shared_credentials_file = "/home/user/.config/aws/credentials"
|
|
}
|
|
```
|
|
|
|
Additional configuration options are described in the `aws` provider [docs](https://www.terraform.io/docs/providers/aws/).
|
|
|
|
!!! tip
|
|
Regions are listed in [docs](http://docs.aws.amazon.com/general/latest/gr/rande.html#ec2_region) or with `aws ec2 describe-regions`.
|
|
|
|
## Cluster
|
|
|
|
Define a Kubernetes cluster using the module `aws/container-linux/kubernetes`.
|
|
|
|
```tf
|
|
module "aws-tempest" {
|
|
source = "git::https://github.com/poseidon/typhoon//aws/container-linux/kubernetes"
|
|
|
|
cluster_name = "tempest"
|
|
|
|
# AWS
|
|
dns_zone = "aws.example.com"
|
|
dns_zone_id = "Z3PAABBCFAKEC0"
|
|
controller_count = 1
|
|
controller_type = "t2.medium"
|
|
worker_count = 2
|
|
worker_type = "t2.small"
|
|
ssh_authorized_key = "ssh-rsa AAAAB3Nz..."
|
|
|
|
# bootkube
|
|
asset_dir = "/home/user/.secrets/clusters/tempest"
|
|
}
|
|
```
|
|
|
|
Reference the [variables docs](#variables) or the [variables.tf](https://github.com/poseidon/typhoon/blob/master/aws/container-linux/kubernetes/variables.tf) source.
|
|
|
|
## ssh-agent
|
|
|
|
Initial bootstrapping requires `bootkube.service` be started on one controller node. Terraform uses `ssh-agent` to automate this step. Add your SSH private key to `ssh-agent`.
|
|
|
|
```sh
|
|
ssh-add ~/.ssh/id_rsa
|
|
ssh-add -L
|
|
```
|
|
|
|
!!! warning
|
|
`terraform apply` will hang connecting to a controller if `ssh-agent` does not contain the SSH key.
|
|
|
|
## Apply
|
|
|
|
Initialize the config directory if this is the first use with Terraform.
|
|
|
|
```sh
|
|
terraform init
|
|
```
|
|
|
|
Get or update Terraform modules.
|
|
|
|
```sh
|
|
$ terraform get # downloads missing modules
|
|
$ terraform get --update # updates all modules
|
|
Get: git::https://github.com/poseidon/typhoon (update)
|
|
Get: git::https://github.com/poseidon/bootkube-terraform.git?ref=v0.9.1 (update)
|
|
```
|
|
|
|
Plan the resources to be created.
|
|
|
|
```sh
|
|
$ terraform plan
|
|
Plan: 98 to add, 0 to change, 0 to destroy.
|
|
```
|
|
|
|
Apply the changes to create the cluster.
|
|
|
|
```sh
|
|
$ terraform apply
|
|
...
|
|
module.aws-tempest.null_resource.bootkube-start: Still creating... (4m50s elapsed)
|
|
module.aws-tempest.null_resource.bootkube-start: Still creating... (5m0s elapsed)
|
|
module.aws-tempest.null_resource.bootkube-start: Creation complete after 11m8s (ID: 3961816482286168143)
|
|
|
|
Apply complete! Resources: 98 added, 0 changed, 0 destroyed.
|
|
```
|
|
|
|
In 4-8 minutes, the Kubernetes cluster will be ready.
|
|
|
|
## Verify
|
|
|
|
[Install kubectl](https://coreos.com/kubernetes/docs/latest/configure-kubectl.html) on your system. Use the generated `kubeconfig` credentials to access the Kubernetes cluster and list nodes.
|
|
|
|
```
|
|
$ KUBECONFIG=/home/user/.secrets/clusters/tempest/auth/kubeconfig
|
|
$ kubectl get nodes
|
|
NAME STATUS AGE VERSION
|
|
ip-10-0-12-221 Ready 34m v1.9.1
|
|
ip-10-0-19-112 Ready 34m v1.9.1
|
|
ip-10-0-4-22 Ready 34m v1.9.1
|
|
```
|
|
|
|
List the pods.
|
|
|
|
```
|
|
$ kubectl get pods --all-namespaces
|
|
NAMESPACE NAME READY STATUS RESTARTS AGE
|
|
kube-system calico-node-1m5bf 2/2 Running 0 34m
|
|
kube-system calico-node-7jmr1 2/2 Running 0 34m
|
|
kube-system calico-node-bknc8 2/2 Running 0 34m
|
|
kube-system kube-apiserver-4mjbk 1/1 Running 0 34m
|
|
kube-system kube-controller-manager-3597210155-j2jbt 1/1 Running 1 34m
|
|
kube-system kube-controller-manager-3597210155-j7g7x 1/1 Running 0 34m
|
|
kube-system kube-dns-1187388186-wx1lg 3/3 Running 0 34m
|
|
kube-system kube-proxy-14wxv 1/1 Running 0 34m
|
|
kube-system kube-proxy-9vxh2 1/1 Running 0 34m
|
|
kube-system kube-proxy-sbbsh 1/1 Running 0 34m
|
|
kube-system kube-scheduler-3359497473-5plhf 1/1 Running 0 34m
|
|
kube-system kube-scheduler-3359497473-r7zg7 1/1 Running 1 34m
|
|
kube-system pod-checkpointer-4kxtl 1/1 Running 0 34m
|
|
kube-system pod-checkpointer-4kxtl-ip-10-0-12-221 1/1 Running 0 33m
|
|
```
|
|
|
|
## Going Further
|
|
|
|
Learn about [version pinning](concepts.md#versioning), maintenance, and [addons](addons/overview.md).
|
|
|
|
!!! note
|
|
On Container Linux clusters, install the `container-linux-update-operator` addon to coordinate reboots and drains when nodes auto-update. Otherwise, updates may not be applied until the next reboot.
|
|
|
|
## Variables
|
|
|
|
### Required
|
|
|
|
| Name | Description | Example |
|
|
|:-----|:------------|:--------|
|
|
| cluster_name | Unique cluster name (prepended to dns_zone) | "tempest" |
|
|
| dns_zone | AWS Route53 DNS zone | "aws.example.com" |
|
|
| dns_zone_id | AWS Route53 DNS zone id | "Z3PAABBCFAKEC0" |
|
|
| ssh_authorized_key | SSH public key for ~/.ssh_authorized_keys | "ssh-rsa AAAAB3NZ..." |
|
|
| os_channel | Container Linux AMI channel | stable, beta, alpha |
|
|
| asset_dir | Path to a directory where generated assets should be placed (contains secrets) | "/home/user/.secrets/clusters/tempest" |
|
|
|
|
#### DNS Zone
|
|
|
|
Clusters create a DNS A record `${cluster_name}.${dns_zone}` to resolve a network load balancer backed by controller instances. This FQDN is used by workers and `kubectl` to access the apiserver. In this example, the cluster's apiserver would be accessible at `tempest.aws.example.com`.
|
|
|
|
You'll need a registered domain name or subdomain registered in a AWS Route53 DNS zone. You can set this up once and create many clusters with unique names.
|
|
|
|
```tf
|
|
resource "aws_route53_zone" "zone-for-clusters" {
|
|
name = "aws.example.com."
|
|
}
|
|
```
|
|
|
|
Reference the DNS zone id with `"${aws_route53_zone.zone-for-clusters.zone_id}"`.
|
|
|
|
!!! tip ""
|
|
If you have an existing domain name with a zone file elsewhere, just carve out a subdomain that can be managed on Route53 (e.g. aws.mydomain.com) and [update nameservers](http://docs.aws.amazon.com/Route53/latest/DeveloperGuide/SOA-NSrecords.html).
|
|
|
|
### Optional
|
|
|
|
| Name | Description | Default | Example |
|
|
|:-----|:------------|:--------|:--------|
|
|
| controller_count | Number of controllers (i.e. masters) | 1 | 1 |
|
|
| controller_type | Controller EC2 instance type | "t2.small" | "t2.medium" |
|
|
| worker_count | Number of workers | 1 | 3 |
|
|
| worker_type | Worker EC2 instance type | "t2.small" | "t2.medium" |
|
|
| disk_size | Size of the EBS volume in GB | "40" | "100" |
|
|
| networking | Choice of networking provider | "calico" | "calico" or "flannel" |
|
|
| network_mtu | CNI interface MTU (calico only) | 1480 | 8981 |
|
|
| host_cidr | CIDR range to assign to EC2 instances | "10.0.0.0/16" | "10.1.0.0/16" |
|
|
| pod_cidr | CIDR range to assign to Kubernetes pods | "10.2.0.0/16" | "10.22.0.0/16" |
|
|
| service_cidr | CIDR range to assign to Kubernetes services | "10.3.0.0/16" | "10.3.0.0/24" |
|
|
| cluster_domain_suffix | FQDN suffix for Kubernetes services answered by kube-dns. | "cluster.local" | "k8s.example.com" |
|
|
|
|
Check the list of valid [instance types](https://aws.amazon.com/ec2/instance-types/).
|
|
|
|
!!! tip "MTU"
|
|
If your EC2 instance type supports [Jumbo frames](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/network_mtu.html#jumbo_frame_instances) (most do), we recommend you change the `network_mtu` to 8991! You will get better pod-to-pod bandwidth.
|
|
|