Skip to content

Instantly share code, notes, and snippets.

@dhruvasagar
Created July 18, 2018 05:11

Revisions

  1. dhruvasagar created this gist Jul 18, 2018.
    307 changes: 307 additions & 0 deletions kube-on-aws.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,307 @@
    if [ ! -x "$(command -v aws)" ]; then
    echo 'Please install following dependencies: '
    echo '* jq'
    echo '* cfssl'
    echo '* aws cli'
    exit 1
    fi

    usage () {
    echo "Usage: $0 [tag]"
    }

    awsip () {
    (aws ec2 describe-instances --filters "Name=tag:Name,Values=$1" | jq -r .Reservations[].Instances[].NetworkInterfaces[].Association.PublicIp)
    }

    TAG=${1:-"kube-klstr-way"}
    AMIID=ami-ee8ea481 # bionic from https://cloud-images.ubuntu.com/locator/ec2/

    create_tags () {
    aws ec2 create-tags --resources $1 --tags Key=Name,Value=$TAG
    }

    create_vpc () {
    VPCID=$(aws ec2 create-vpc --cidr-block 10.10.0.0/16 | jq -r .Vpc.VpcId)
    create_tags $VPCID
    aws ec2 modify-vpc-attribute --enable-dns-hostnames --vpc-id $VPCID
    aws ec2 modify-vpc-attribute --enable-dns-support --vpc-id $VPCID
    }

    create_subnet () {
    SUBNETID=$(aws ec2 create-subnet --vpc-id=$VPCID --cidr-block=10.10.128.0/17 | jq -r .Subnet.SubnetId)
    create_tags $SUBNETID
    }

    create_route_table () {
    RTBID=$(aws ec2 create-route-table --vpc-id $VPCID | jq -r .RouteTable.RouteTableId)
    create_tags $RTBID
    aws ec2 associate-route-table --subnet-id $SUBNETID --route-table-id $RTBID
    }

    create_internet_gateway () {
    IGWID=$(aws ec2 create-internet-gateway | jq -r .InternetGateway.InternetGatewayId)
    create_tags $IGWID
    aws ec2 attach-internet-gateway --internet-gateway-id $IGWID --vpc-id $VPCID
    aws ec2 create-route --route-table-id $RTBID --destination-cidr-block 0.0.0.0/0 --gateway-id $IGWID
    }

    create_security_group () {
    SGID=$(aws ec2 create-security-group --group-name $TAG --description "allows ssh and 6443" --vpc-id $VPCID | jq -r .GroupId)
    create_tags $SGID
    # Allow traffic on all tcp ports within the internal network
    aws ec2 authorize-security-group-ingress --group-id $SGID --protocol all --port 0-65536 --cidr 10.10.0.0/16
    # For ssh from outside
    aws ec2 authorize-security-group-ingress --group-id $SGID --protocol tcp --port 22 --cidr 0.0.0.0/0
    # For API Server from outside
    aws ec2 authorize-security-group-ingress --group-id $SGID --protocol tcp --port 6443 --cidr 0.0.0.0/0
    }

    create_key_pair () {
    (aws ec2 create-key-pair --key-name kube-klstr-way | jq -r .KeyMaterial) > kube-klstr-way.pem
    chmod 600 kube-klstr-way.pem
    ssh-add kube-klstr-way.pem
    }

    create_controllers () {
    for i in 0 1 2; do
    instance_id=$(aws ec2 run-instances \
    --image-id=$AMIID \
    --subnet-id $SUBNETID \
    --security-group-ids $SGID \
    --private-ip-address 10.10.128.1${i} \
    --key-name kube-klstr-way \
    --block-device-mapping DeviceName=/dev/sda1,Ebs={VolumeSize=32} \
    --associate-public-ip-address \
    --instance-type t2.medium | jq -r .Instances[0].InstanceId)
    aws ec2 modify-instance-attribute \
    --instance-id ${instance_id} \
    --no-source-dest-check
    aws ec2 create-tags --resources $instance_id --tags Key=Name,Value=kkw-controller-${i}
    done
    }

    generate_install_kubernetes_script () {
    cat > install_kubernetes.sh <<EOF
    sudo apt-get update
    sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common
    sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
    sudo add-apt-repository "deb https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") $(lsb_release -cs) stable"
    sudo apt-get update && apt-get install -y docker-ce
    sudo apt-get update && apt-get install -y apt-transport-https curl
    sudo curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
    sudo cat <<EF >/etc/apt/sources.list.d/kubernetes.list
    deb http://apt.kubernetes.io/ kubernetes-xenial main
    EF
    sudo apt-get update
    sudo apt-get install -y kubelet kubeadm kubectl
    EOF
    }

    generate_etcd_certificates () {
    mkdir tls
    cd tls

    cat > tls/ca-config.json <<EOF
    {
    "signing": {
    "default": {
    "expiry": "8760h"
    },
    "profiles": {
    "etcd": {
    "usages": ["signing", "key encipherment", "server auth", "client auth"],
    "expiry": "8760h"
    }
    }
    }
    }
    EOF

    cat > tls/ca-csr.json <<EOF
    {
    "CN": "KubeKlstrWay",
    "key": {
    "algo": "rsa",
    "size": 2048
    },
    "names": [
    {
    "C": "IN",
    "L": "Chennai",
    "O": "etcd",
    "OU": "CA",
    "ST": "TN"
    }
    ]
    }
    EOF

    cfssl gencert -initca tls/ca-csr.json | cfssljson -bare tls/ca

    cat > tls/etcd-csr.json <<EOF
    {
    "CN": "etcd",
    "key": {
    "algo": "rsa",
    "size": 2048
    },
    "names": [
    {
    "C": "IN",
    "L": "Chennai",
    "O": "etcd",
    "OU": "Kube Klstr Way",
    "ST": "TN"
    }
    ]
    }
    EOF
    cfssl gencert \
    -ca=tls/ca.pem \
    -ca-key=tls/ca-key.pem \
    -config=tls/ca-config.json \
    -hostname=10.10.128.10,10.10.128.11,10.10.128.12,ip-10-10-128-10,ip-10-10-128-11,ip-10-10-128-12,127.0.0.1 \
    -profile=etcd \
    tls/etcd-csr.json | cfssljson -bare tls/etcd

    for i in 0 1 2; do
    scp -r tls ubuntu@`awsip kkw-controller-${i}`:~
    done
    }

    generate_setup_etcd_script () {
    cat > setup_etcd.sh <<EOF
    sudo mkdir /etc/etcd
    sudo mkdir -p /var/lib/etcd
    sudo cp tls/* /etc/etcd/
    INTERNAL_IP=$(curl -s http://169.254.169.254/latest/meta-data/local-ipv4)
    ETCD_NAME=$(curl -s http://169.254.169.254/latest/meta-data/local-hostname | cut -d '.' -f1)
    cat > etcd.service <<EF
    [Unit]
    Description=etcd
    After=docker.service
    Requires=docker.service
    Documentation=https://github.com/coreos
    [Service]
    ExecStartPre=/usr/bin/docker pull quay.io/coreos/etcd:v3.3
    ExecStart=/usr/bin/docker run --rm --name %n \\
    -v /var/lib/etcd:/var/lib/etcd \\
    -v /etc/etcd:/etc/etcd \\
    --net host \\
    quay.io/coreos/etcd:v3.3 \\
    /usr/local/bin/etcd \\
    --name ${ETCD_NAME} \\
    --cert-file=/etc/etcd/etcd.pem \\
    --key-file=/etc/etcd/etcd-key.pem \\
    --peer-cert-file=/etc/etcd/etcd.pem \\
    --peer-key-file=/etc/etcd/etcd-key.pem \\
    --trusted-ca-file=/etc/etcd/ca.pem \\
    --peer-trusted-ca-file=/etc/etcd/ca.pem \\
    --peer-client-cert-auth \\
    --client-cert-auth \\
    --initial-advertise-peer-urls https://${INTERNAL_IP}:2380 \\
    --listen-peer-urls https://${INTERNAL_IP}:2380 \\
    --listen-client-urls https://${INTERNAL_IP}:2379,http://127.0.0.1:2379 \\
    --advertise-client-urls https://${INTERNAL_IP}:2379 \\
    --initial-cluster-token etcd-cluster-0 \\
    --initial-cluster ip-10-10-128-10=https://10.10.128.10:2380,ip-10-10-128-11=https://10.10.128.11:2380,ip-10-10-128-12=https://10.10.128.12:2380 \\
    --initial-cluster-state new \\
    --data-dir=/var/lib/etcd
    Restart=on-failure
    RestartSec=5
    [Install]
    WantedBy=multi-user.target
    EF
    sudo mv etcd.service /etc/systemd/system/
    sudo systemctl daemon-reload
    sudo systemctl enable etcd
    sudo systemctl start etcd
    EOF
    }

    setup_controllers () {
    generate_etcd_certificates
    generate_install_kubernetes_script
    generate_setup_etcd_script
    ssh -A -l ubuntu $(awsip kkw-controller-0) 'bash -s' < install_kubernetes.sh
    ssh -A -l ubuntu $(awsip kkw-controller-0) 'bash -s' < setup_etcd.sh
    }

    create_load_balanacer () {
    ELBARN=$(aws elbv2 create-load-balancer --name kube-klstr-way --subnets $SUBNETID --scheme internet-facing --type network | jq -r .LoadBalancers[].LoadBalancerArn)
    TGARN=$(aws elbv2 create-target-group --name kube-klstr-way --protocol TCP --port 6443 --vpc-id $VPCID --target-type ip | jq -r .TargetGroups[].TargetGroupArn)
    aws elbv2 register-targets --target-group-arn $TGARN --targets Id=10.10.128.10
    LISTENERARN=$(aws elbv2 create-listener --load-balancer-arn $ELBARN --protocol TCP --port 6443 --default-actions Type=forward,TargetGroupArn=$TGARN | jq -r .Listeners[].ListenerArn)
    KUBE_PUBLIC_DNS=$(aws elbv2 describe-load-balancers --load-balancer-arn $ELBARN | jq -r .LoadBalancers[].DNSName)
    }

    initiate_first_controller () {
    cat > kubeadm.cfg <<EOF
    apiVersion: kubeadm.k8s.io/v1alpha2
    kind: MasterConfiguration
    kubernetesVersion: v1.11.0
    apiServerCertSANs:
    - ${KUBE_PUBLIC_DNS}
    api:
    controlPlaneEndpoint: "${KUBE_PUBLIC_DNS}:6443"
    etcd:
    external:
    endpoints:
    - https://10.10.128.10:2379
    - https://10.10.128.11:2379
    - https://10.10.128.12:2379
    caFile: /etc/etcd/ca.pem
    certFile: /etc/etcd/etcd.pem
    keyFile: /etc/etcd/etcd-key.pem
    networking:
    # This CIDR is a canal default
    podSubnet: "10.244.0.0/16"
    EOF

    scp kubeadm.cfg ubuntu@`awsip kkw-controller-0`:
    ssh -A -l ubuntu $(awsip kkw-controller-0) 'bash -s' sudo kubeadm init --config kubeadm.cfg
    }

    initiate_remaining_controllers () {
    ssh -A -l ubuntu $(awsip kkw-controller-0) <<EOF
    cd /etc/kubernetes/pki
    sudo tar -cvf /home/ubuntu/certs.tar ca.crt ca.key sa.key sa.pub front-proxy-ca.crt front-proxy-ca.key
    cd $HOME
    scp kubeadm.cfg ubuntu@10.10.128.11:
    scp certs.tar ubuntu@10.10.128.11:
    scp kubeadm.cfg ubuntu@10.10.128.12:
    scp certs.tar ubuntu@10.10.128.12:
    EOF

    for i in 1 2; do
    ssh -A -l ubuntu $(awsip kkw-controller-${i}) <<EOF
    tar xvf certs.tar
    sudo mkdir -p /etc/kubernetes/pki
    sudo cp *.crt *.key *.pub /etc/kubernetes/pki/
    sudo kubeadm init --config kubeadm.cfg
    EOF
    done
    }

    add_other_controllers_to_load_balancer () {
    aws elbv2 register-targets --target-group-arn $TGARN --targets Id=10.10.128.11 Id=10.10.128.12
    }

    create_vpc
    create_subnet
    create_route_table
    create_internet_gateway
    create_security_group
    create_key_pair
    create_controllers
    setup_controllers
    create_load_balanacer
    initiate_first_controller
    initiate_remaining_controllers