2016-09-11 09:34:14 +03:00
# Cloud Infrastructure Provisioning - Amazon Web Services
2016-09-11 02:03:47 +03:00
This lab will walk you through provisioning the compute instances required for running a H/A Kubernetes cluster. A total of 9 virtual machines will be created.
2016-09-11 17:59:53 +03:00
The guide assumes you'll be creating resources in the `us-west-2` region.
2016-09-11 02:03:47 +03:00
After completing this guide you should have the following compute instances:
2016-09-11 04:43:53 +03:00
![EC2 Console ](ec2-instances.png )
2016-09-11 02:03:47 +03:00
> All machines will be provisioned with fixed private IP addresses to simplify the bootstrap process.
To make our Kubernetes control plane remotely accessible, a public IP address will be provisioned and assigned to a Load Balancer that will sit in front of the 3 Kubernetes controllers.
2016-09-11 12:53:34 +03:00
## Networking
### VPC
2016-09-11 02:03:47 +03:00
```
VPC_ID=$(aws ec2 create-vpc \
2016-09-12 22:10:44 +03:00
--cidr-block 10.240.0.0/16 \
--output text \
--query '.Vpc.VpcId')
2016-09-11 02:03:47 +03:00
```
2016-09-11 12:40:34 +03:00
```
aws ec2 create-tags \
--resources ${VPC_ID} \
--tags Key=Name,Value=kubernetes
```
2016-09-11 02:03:47 +03:00
```
aws ec2 modify-vpc-attribute \
--vpc-id ${VPC_ID} \
--enable-dns-support '{"Value": true}'
```
```
aws ec2 modify-vpc-attribute \
--vpc-id ${VPC_ID} \
--enable-dns-hostnames '{"Value": true}'
```
2016-09-11 12:53:34 +03:00
### DHCP Option Sets
2016-09-11 02:03:47 +03:00
```
DHCP_OPTION_SET_ID=$(aws ec2 create-dhcp-options \
--dhcp-configuration "Key=domain-name,Values=us-west-2.compute.internal" \
2016-09-12 22:10:44 +03:00
"Key=domain-name-servers,Values=AmazonProvidedDNS" \
--output text \
--query 'DhcpOptions.DhcpOptionsId')
2016-09-11 02:03:47 +03:00
```
2016-09-11 12:40:34 +03:00
```
aws ec2 create-tags \
--resources ${DHCP_OPTION_SET_ID} \
--tags Key=Name,Value=kubernetes
```
2016-09-11 02:03:47 +03:00
```
aws ec2 associate-dhcp-options \
--dhcp-options-id ${DHCP_OPTION_SET_ID} \
--vpc-id ${VPC_ID}
```
2016-09-11 12:53:34 +03:00
### Subnets
2016-09-11 02:03:47 +03:00
Create a subnet for the Kubernetes cluster:
```
SUBNET_ID=$(aws ec2 create-subnet \
--vpc-id ${VPC_ID} \
2016-09-12 22:10:44 +03:00
--cidr-block 10.240.0.0/24 \
--output text \
--query 'Subnet.SubnetId')
2016-09-11 02:03:47 +03:00
```
2016-09-11 12:40:34 +03:00
```
aws ec2 create-tags \
--resources ${SUBNET_ID} \
--tags Key=Name,Value=kubernetes
```
2016-09-11 12:53:34 +03:00
### Internet Gateways
2016-09-11 02:03:47 +03:00
```
2016-09-12 22:10:44 +03:00
INTERNET_GATEWAY_ID=$(aws ec2 create-internet-gateway \
--output text \
--query 'InternetGateway.InternetGatewayId')
2016-09-11 02:03:47 +03:00
```
2016-09-11 12:40:34 +03:00
```
aws ec2 create-tags \
--resources ${INTERNET_GATEWAY_ID} \
--tags Key=Name,Value=kubernetes
```
2016-09-11 02:03:47 +03:00
```
aws ec2 attach-internet-gateway \
--internet-gateway-id ${INTERNET_GATEWAY_ID} \
--vpc-id ${VPC_ID}
```
2016-09-11 12:53:34 +03:00
### Route Tables
2016-09-11 02:03:47 +03:00
```
ROUTE_TABLE_ID=$(aws ec2 create-route-table \
2016-09-12 22:10:44 +03:00
--vpc-id ${VPC_ID} \
--output text \
--query 'RouteTable.RouteTableId')
2016-09-11 02:03:47 +03:00
```
2016-09-11 12:40:34 +03:00
```
aws ec2 create-tags \
--resources ${ROUTE_TABLE_ID} \
--tags Key=Name,Value=kubernetes
```
2016-09-11 02:03:47 +03:00
```
aws ec2 associate-route-table \
--route-table-id ${ROUTE_TABLE_ID} \
--subnet-id ${SUBNET_ID}
```
```
aws ec2 create-route \
--route-table-id ${ROUTE_TABLE_ID} \
--destination-cidr-block 0.0.0.0/0 \
--gateway-id ${INTERNET_GATEWAY_ID}
```
### Firewall Rules
```
SECURITY_GROUP_ID=$(aws ec2 create-security-group \
--group-name kubernetes \
--description "Kubernetes security group" \
2016-09-12 22:10:44 +03:00
--vpc-id ${VPC_ID} \
--output text \
--query 'GroupId')
2016-09-11 02:03:47 +03:00
```
2016-09-11 12:40:34 +03:00
```
aws ec2 create-tags \
--resources ${SECURITY_GROUP_ID} \
--tags Key=Name,Value=kubernetes
```
2016-09-11 02:03:47 +03:00
```
aws ec2 authorize-security-group-ingress \
--group-id ${SECURITY_GROUP_ID} \
--protocol all
```
2016-09-11 06:00:31 +03:00
```
aws ec2 authorize-security-group-ingress \
--group-id ${SECURITY_GROUP_ID} \
--protocol all \
--port 0-65535 \
--cidr 10.240.0.0/16
```
2016-09-11 02:03:47 +03:00
```
aws ec2 authorize-security-group-ingress \
--group-id ${SECURITY_GROUP_ID} \
--protocol tcp \
--port 22 \
--cidr 0.0.0.0/0
```
```
aws ec2 authorize-security-group-ingress \
--group-id ${SECURITY_GROUP_ID} \
--protocol tcp \
2016-09-11 13:57:16 +03:00
--port 6443 \
2016-09-11 02:03:47 +03:00
--cidr 0.0.0.0/0
```
2016-09-11 12:53:34 +03:00
### Kubernetes Public Address
2016-09-11 02:03:47 +03:00
2016-09-11 12:53:34 +03:00
An ELB will be used to load balance traffic across the Kubernetes control plane.
2016-09-11 02:03:47 +03:00
```
2016-09-11 11:05:13 +03:00
aws elb create-load-balancer \
--load-balancer-name kubernetes \
--listeners "Protocol=TCP,LoadBalancerPort=6443,InstanceProtocol=TCP,InstancePort=6443" \
--subnets ${SUBNET_ID} \
--security-groups ${SECURITY_GROUP_ID}
```
2016-09-11 12:53:34 +03:00
2016-09-11 02:03:47 +03:00
## Provision Virtual Machines
All the VMs in this lab will be provisioned using Ubuntu 16.04 mainly because it runs a newish Linux Kernel that has good support for Docker.
2016-09-11 15:11:26 +03:00
All virtual machines in this section will be created with the `--no-source-dest-check` flag to enable traffic between foreign subnets to flow. The will enable Pods to communicate with nodes and other Pods via the Kubernetes service IP.
2016-09-11 15:06:32 +03:00
2016-09-11 02:03:47 +03:00
### Create Instance IAM Policies
```
cat > kubernetes-iam-role.json < < 'EOF'
{
"Version": "2012-10-17",
"Statement": [
{"Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com"}, "Action": "sts:AssumeRole"}
]
}
EOF
```
```
aws iam create-role \
--role-name kubernetes \
--assume-role-policy-document file://kubernetes-iam-role.json
```
```
cat > kubernetes-iam-policy.json < < 'EOF'
{
"Version": "2012-10-17",
"Statement": [
{"Effect": "Allow", "Action": ["ec2:*"], "Resource": ["*"]},
{"Effect": "Allow", "Action": ["elasticloadbalancing:*"], "Resource": ["*"]},
{"Effect": "Allow", "Action": ["route53:*"], "Resource": ["*"]},
{"Effect": "Allow", "Action": ["ecr:*"], "Resource": "*"}
]
}
EOF
```
```
aws iam put-role-policy \
--role-name kubernetes \
--policy-name kubernetes \
--policy-document file://kubernetes-iam-policy.json
```
```
aws iam create-instance-profile \
--instance-profile-name kubernetes
```
```
aws iam add-role-to-instance-profile \
--instance-profile-name kubernetes \
--role-name kubernetes
```
### Chosing an Image
Use the [Ubuntu Amazon EC2 AMI Locator ](https://cloud-images.ubuntu.com/locator/ec2/ ) to find the right image-id for your zone. This guide assumes the `us-west-2` zone.
```
IMAGE_ID="ami-746aba14"
```
### Generate A SSH Key Pair
```
2016-09-12 22:10:44 +03:00
aws ec2 create-key-pair --key-name kubernetes \
--output text \
--query 'KeyMaterial' > ~/.ssh/kubernetes_the_hard_way
2016-09-11 02:03:47 +03:00
```
```
chmod 600 ~/.ssh/kubernetes_the_hard_way
```
```
ssh-add ~/.ssh/kubernetes_the_hard_way
```
2016-09-11 18:20:43 +03:00
#### SSH Access
Once the virtual machines are created you'll be able to login into each machine using ssh like this:
```
WORKER_0_PUBLIC_IP_ADDRESS=$(aws ec2 describe-instances \
2016-09-12 22:10:44 +03:00
--filters "Name=tag:Name,Values=worker0" \
--output text \
--query 'Reservations[].Instances[].PublicIpAddress')
2016-09-11 18:20:43 +03:00
```
2016-09-11 18:22:09 +03:00
> The instance public IP address can also be obtained from the EC2 console. Each node will be tagged with a unique name.
2016-09-11 18:20:43 +03:00
```
ssh ubuntu@${WORKER_0_PUBLIC_IP_ADDRESS}
```
2016-09-11 12:53:34 +03:00
### Virtual Machines
#### etcd
2016-09-11 02:03:47 +03:00
```
ETCD_0_INSTANCE_ID=$(aws ec2 run-instances \
--associate-public-ip-address \
--image-id ${IMAGE_ID} \
--count 1 \
--key-name kubernetes \
--security-group-ids ${SECURITY_GROUP_ID} \
--instance-type t2.small \
--private-ip-address 10.240.0.10 \
2016-09-12 22:10:44 +03:00
--subnet-id ${SUBNET_ID} \
--output text \
--query 'Instances[].InstanceId')
2016-09-11 02:03:47 +03:00
```
```
aws ec2 create-tags \
--resources ${ETCD_0_INSTANCE_ID} \
--tags Key=Name,Value=etcd0
```
```
ETCD_1_INSTANCE_ID=$(aws ec2 run-instances \
--associate-public-ip-address \
--image-id ${IMAGE_ID} \
--count 1 \
--key-name kubernetes \
--security-group-ids ${SECURITY_GROUP_ID} \
--instance-type t2.small \
--private-ip-address 10.240.0.11 \
2016-09-12 22:10:44 +03:00
--subnet-id ${SUBNET_ID} \
--output text \
--query 'Instances[].InstanceId')
2016-09-11 02:03:47 +03:00
```
```
aws ec2 create-tags \
--resources ${ETCD_1_INSTANCE_ID} \
--tags Key=Name,Value=etcd1
```
```
ETCD_2_INSTANCE_ID=$(aws ec2 run-instances \
--associate-public-ip-address \
--image-id ${IMAGE_ID} \
--count 1 \
--key-name kubernetes \
--security-group-ids ${SECURITY_GROUP_ID} \
--instance-type t2.small \
--private-ip-address 10.240.0.12 \
2016-09-12 22:10:44 +03:00
--subnet-id ${SUBNET_ID} \
--output text \
--query 'Instances[].InstanceId')
2016-09-11 02:03:47 +03:00
```
```
aws ec2 create-tags \
--resources ${ETCD_2_INSTANCE_ID} \
--tags Key=Name,Value=etcd2
```
2016-09-11 12:53:34 +03:00
#### Kubernetes Controllers
2016-09-11 02:03:47 +03:00
```
CONTROLLER_0_INSTANCE_ID=$(aws ec2 run-instances \
--associate-public-ip-address \
--iam-instance-profile 'Name=kubernetes' \
--image-id ${IMAGE_ID} \
--count 1 \
--key-name kubernetes \
--security-group-ids ${SECURITY_GROUP_ID} \
--instance-type t2.small \
--private-ip-address 10.240.0.20 \
2016-09-12 22:10:44 +03:00
--subnet-id ${SUBNET_ID} \
--output text \
--query '.Instances[].InstanceId')
2016-09-11 02:03:47 +03:00
```
2016-09-11 15:06:32 +03:00
```
aws ec2 modify-instance-attribute \
--instance-id ${CONTROLLER_0_INSTANCE_ID} \
--no-source-dest-check
```
2016-09-11 02:03:47 +03:00
```
aws ec2 create-tags \
--resources ${CONTROLLER_0_INSTANCE_ID} \
--tags Key=Name,Value=controller0
```
```
CONTROLLER_1_INSTANCE_ID=$(aws ec2 run-instances \
--associate-public-ip-address \
--iam-instance-profile 'Name=kubernetes' \
--image-id ${IMAGE_ID} \
--count 1 \
--key-name kubernetes \
--security-group-ids ${SECURITY_GROUP_ID} \
--instance-type t2.small \
--private-ip-address 10.240.0.21 \
2016-09-12 22:10:44 +03:00
--subnet-id ${SUBNET_ID} \
--output text \
--query 'Instances[].InstanceId')
2016-09-11 02:03:47 +03:00
```
2016-09-11 15:06:32 +03:00
```
aws ec2 modify-instance-attribute \
--instance-id ${CONTROLLER_1_INSTANCE_ID} \
--no-source-dest-check
```
2016-09-11 02:03:47 +03:00
```
aws ec2 create-tags \
--resources ${CONTROLLER_1_INSTANCE_ID} \
--tags Key=Name,Value=controller1
```
```
CONTROLLER_2_INSTANCE_ID=$(aws ec2 run-instances \
--associate-public-ip-address \
--iam-instance-profile 'Name=kubernetes' \
--image-id ${IMAGE_ID} \
--count 1 \
--key-name kubernetes \
--security-group-ids ${SECURITY_GROUP_ID} \
--instance-type t2.small \
--private-ip-address 10.240.0.22 \
2016-09-12 22:10:44 +03:00
--subnet-id ${SUBNET_ID} \
--output text \
--query 'Instances[].InstanceId')
2016-09-11 02:03:47 +03:00
```
2016-09-11 15:06:32 +03:00
```
aws ec2 modify-instance-attribute \
--instance-id ${CONTROLLER_2_INSTANCE_ID} \
--no-source-dest-check
```
2016-09-11 02:03:47 +03:00
```
aws ec2 create-tags \
--resources ${CONTROLLER_2_INSTANCE_ID} \
--tags Key=Name,Value=controller2
```
2016-09-11 12:53:34 +03:00
#### Kubernetes Workers
2016-09-11 02:03:47 +03:00
```
WORKER_0_INSTANCE_ID=$(aws ec2 run-instances \
--associate-public-ip-address \
--iam-instance-profile 'Name=kubernetes' \
--image-id ${IMAGE_ID} \
--count 1 \
--key-name kubernetes \
--security-group-ids ${SECURITY_GROUP_ID} \
--instance-type t2.small \
--private-ip-address 10.240.0.30 \
2016-09-12 22:10:44 +03:00
--subnet-id ${SUBNET_ID} \
--output text \
--query 'Instances[].InstanceId')
2016-09-11 02:03:47 +03:00
```
2016-09-11 15:06:32 +03:00
```
aws ec2 modify-instance-attribute \
--instance-id ${WORKER_0_INSTANCE_ID} \
--no-source-dest-check
```
2016-09-11 02:03:47 +03:00
```
aws ec2 create-tags \
--resources ${WORKER_0_INSTANCE_ID} \
--tags Key=Name,Value=worker0
```
```
WORKER_1_INSTANCE_ID=$(aws ec2 run-instances \
--associate-public-ip-address \
--iam-instance-profile 'Name=kubernetes' \
--image-id ${IMAGE_ID} \
--count 1 \
--key-name kubernetes \
--security-group-ids ${SECURITY_GROUP_ID} \
--instance-type t2.small \
--private-ip-address 10.240.0.31 \
2016-09-12 22:10:44 +03:00
--subnet-id ${SUBNET_ID} \
--output text \
--query 'Instances[].InstanceId')
2016-09-11 02:03:47 +03:00
```
2016-09-11 15:06:32 +03:00
```
aws ec2 modify-instance-attribute \
--instance-id ${WORKER_1_INSTANCE_ID} \
--no-source-dest-check
```
2016-09-11 02:03:47 +03:00
```
aws ec2 create-tags \
--resources ${WORKER_1_INSTANCE_ID} \
--tags Key=Name,Value=worker1
```
```
WORKER_2_INSTANCE_ID=$(aws ec2 run-instances \
--associate-public-ip-address \
--iam-instance-profile 'Name=kubernetes' \
--image-id ${IMAGE_ID} \
--count 1 \
--key-name kubernetes \
--security-group-ids ${SECURITY_GROUP_ID} \
--instance-type t2.small \
--private-ip-address 10.240.0.32 \
2016-09-12 22:10:44 +03:00
--subnet-id ${SUBNET_ID} \
--output text \
--query 'Instances[].InstanceId')
2016-09-11 02:03:47 +03:00
```
2016-09-11 15:06:32 +03:00
```
aws ec2 modify-instance-attribute \
--instance-id ${WORKER_2_INSTANCE_ID} \
--no-source-dest-check
```
2016-09-11 02:03:47 +03:00
```
aws ec2 create-tags \
2016-09-11 04:39:12 +03:00
--resources ${WORKER_2_INSTANCE_ID} \
2016-09-11 02:03:47 +03:00
--tags Key=Name,Value=worker2
```
2016-09-11 04:43:53 +03:00
## Verify
```
aws ec2 describe-instances \
2016-09-12 22:10:44 +03:00
--filters "Name=instance-state-name,Values=running" \
--output text \
--query 'Reservations[].Instances[].{ID:InstanceId, AZ:Placement.AvailabilityZone, PrivateIP:PrivateIpAddress, PublicIP:PublicIpAddress}'
2016-09-11 04:43:53 +03:00
```
```
i-f3714f2e us-west-2c 10.240.0.22 XX.XXX.XX.XX
i-ae714f73 us-west-2c 10.240.0.11 XX.XX.XX.XXX
i-f4714f29 us-west-2c 10.240.0.21 XX.XX.XXX.XXX
i-f6714f2b us-west-2c 10.240.0.12 XX.XX.XX.XX
i-e26e503f us-west-2c 10.240.0.30 XX.XX.XXX.XXX
i-e36e503e us-west-2c 10.240.0.31 XX.XX.XX.XX
i-e8714f35 us-west-2c 10.240.0.10 XX.XX.XXX.XXX
i-78704ea5 us-west-2c 10.240.0.20 XX.XX.XXX.XXX
i-4a6e5097 us-west-2c 10.240.0.32 XX.XX.XX.XX
```