{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "Kubernetes 0.17.0 on EC2 powered by CoreOS 681.0.0 (alpha)",
  "Mappings": {
      "RegionMap": {
          "eu-central-1" : {
              "AMI" : "ami-4c4f7151"
          },
          "ap-northeast-1" : {
              "AMI" : "ami-3a35fd3a"
          },
          "us-gov-west-1" : {
              "AMI" : "ami-57117174"
          },
          "sa-east-1" : {
              "AMI" : "ami-fbcc4ae6"
          },
          "ap-southeast-2" : {
              "AMI" : "ami-593c4263"
          },
          "ap-southeast-1" : {
              "AMI" : "ami-3a083668"
          },
          "us-east-1" : {
              "AMI" : "ami-40322028"
          },
          "us-west-2" : {
              "AMI" : "ami-23b58613"
          },
          "us-west-1" : {
              "AMI" : "ami-15618f51"
          },
          "eu-west-1" : {
              "AMI" : "ami-8d1164fa"
          }
      }
  },
  "Parameters": {
    "InstanceType": {
      "Description": "EC2 HVM instance type (m3.medium, etc).",
      "Type": "String",
      "Default": "m3.medium",
      "AllowedValues": [
        "m3.medium",
        "m3.large",
        "m3.xlarge",
        "m3.2xlarge",
        "c3.large",
        "c3.xlarge",
        "c3.2xlarge",
        "c3.4xlarge",
        "c3.8xlarge",
        "cc2.8xlarge",
        "cr1.8xlarge",
        "hi1.4xlarge",
        "hs1.8xlarge",
        "i2.xlarge",
        "i2.2xlarge",
        "i2.4xlarge",
        "i2.8xlarge",
        "r3.large",
        "r3.xlarge",
        "r3.2xlarge",
        "r3.4xlarge",
        "r3.8xlarge",
        "t2.micro",
        "t2.small",
        "t2.medium"
      ],
      "ConstraintDescription": "Must be a valid EC2 HVM instance type."
    },
    "ClusterSize": {
      "Description": "Number of nodes in cluster (2-12).",
      "Default": "2",
      "MinValue": "2",
      "MaxValue": "12",
      "Type": "Number"
    },
    "AllowSSHFrom": {
      "Description": "The net block (CIDR) that SSH is available to.",
      "Default": "0.0.0.0/0",
      "Type": "String"
    },
    "KeyPair": {
      "Description": "The name of an EC2 Key Pair to allow SSH access to the instance.",
      "Type": "AWS::EC2::KeyPair::KeyName"
    },
    "VpcId": {
      "Description": "The ID of the VPC to launch into.",
      "Type": "AWS::EC2::VPC::Id"
    },
    "SubnetId": {
      "Description": "The ID of the subnet to launch into (that must be within the supplied VPC)",
      "Type": "AWS::EC2::Subnet::Id"
    },
    "SubnetAZ": {
      "Description": "The availability zone of the subnet supplied (for example eu-west-1a)",
      "Type": "String"
    }
  },
  "Conditions": {
    "UseEC2Classic": {"Fn::Equals": [{"Ref": "VpcId"}, ""]}
  },
  "Resources": {
    "KubernetesSecurityGroup": {
      "Type": "AWS::EC2::SecurityGroup",
      "Properties": {
        "VpcId": {"Fn::If": ["UseEC2Classic", {"Ref": "AWS::NoValue"}, {"Ref": "VpcId"}]},
        "GroupDescription": "Kubernetes SecurityGroup",
        "SecurityGroupIngress": [
          {
            "IpProtocol": "tcp",
            "FromPort": "22",
            "ToPort": "22",
            "CidrIp": {"Ref": "AllowSSHFrom"}
          }
        ]
      }
    },
    "KubernetesIngress": {
      "Type": "AWS::EC2::SecurityGroupIngress",
      "Properties": {
        "GroupId": {"Fn::GetAtt": ["KubernetesSecurityGroup", "GroupId"]},
        "IpProtocol": "tcp",
        "FromPort": "1",
        "ToPort": "65535",
        "SourceSecurityGroupId": {
          "Fn::GetAtt" : [ "KubernetesSecurityGroup", "GroupId" ]
        }
      }
    },
    "KubernetesIngressUDP": {
      "Type": "AWS::EC2::SecurityGroupIngress",
      "Properties": {
        "GroupId": {"Fn::GetAtt": ["KubernetesSecurityGroup", "GroupId"]},
        "IpProtocol": "udp",
        "FromPort": "1",
        "ToPort": "65535",
        "SourceSecurityGroupId": {
          "Fn::GetAtt" : [ "KubernetesSecurityGroup", "GroupId" ]
        }
      }
    },
    "KubernetesMasterInstance": {
      "Type": "AWS::EC2::Instance",
      "Properties": {
        "NetworkInterfaces" : [{
          "GroupSet"                 : [{"Fn::GetAtt": ["KubernetesSecurityGroup", "GroupId"]}],
          "AssociatePublicIpAddress" : "true",
          "DeviceIndex"              : "0",
          "DeleteOnTermination"      : "true",
          "SubnetId"                 : {"Fn::If": ["UseEC2Classic", {"Ref": "AWS::NoValue"}, {"Ref": "SubnetId"}]}
        }],
        "ImageId": {"Fn::FindInMap" : ["RegionMap", {"Ref": "AWS::Region" }, "AMI"]},
        "InstanceType": {"Ref": "InstanceType"},
        "KeyName": {"Ref": "KeyPair"},
        "Tags" : [
          {"Key" : "Name", "Value" : {"Fn::Join" : [ "-", [ {"Ref" : "AWS::StackName"}, "k8s-master" ] ]}},
          {"Key" : "KubernetesRole", "Value" : "node"}
        ],
        "UserData": { "Fn::Base64": {"Fn::Join" : ["", [
          "#cloud-config\n\n",
          "write_files:\n",
          "- path: /opt/bin/waiter.sh\n",
          "  owner: root\n",
          "  content: |\n",
          "    #! /usr/bin/bash\n",
          "    until curl http://127.0.0.1:2379/v2/machines; do sleep 2; done\n",
          "coreos:\n",
          "  etcd2:\n",
          "    name: master\n",
          "    initial-cluster-token: k8s_etcd\n",
          "    initial-cluster: master=http://$private_ipv4:2380\n",
          "    listen-peer-urls: http://$private_ipv4:2380,http://localhost:2380\n",
          "    initial-advertise-peer-urls: http://$private_ipv4:2380\n",
          "    listen-client-urls: http://$private_ipv4:2379,http://localhost:2379\n",
          "    advertise-client-urls: http://$private_ipv4:2379\n",
          "  fleet:\n",
          "    etcd_servers: http://localhost:2379\n",
          "    metadata: k8srole=master\n",
          "  flannel:\n",
          "    etcd_endpoints: http://localhost:2379\n",
          "  locksmithd:\n",
          "    endpoint: http://localhost:2379\n",
          "  units:\n",
          "    - name: etcd2.service\n",
          "      command: start\n",
          "    - name: fleet.service\n",
          "      command: start\n",
          "    - name: etcd2-waiter.service\n",
          "      command: start\n",
          "      content: |\n",
          "        [Unit]\n",
          "        Description=etcd waiter\n",
          "        Wants=network-online.target\n",
          "        Wants=etcd2.service\n",
          "        After=etcd2.service\n",
          "        After=network-online.target\n",
          "        Before=flanneld.service fleet.service locksmithd.service\n\n",
          "        [Service]\n",
          "        ExecStart=/usr/bin/bash /opt/bin/waiter.sh\n",
          "        RemainAfterExit=true\n",
          "        Type=oneshot\n",
          "    - name: flanneld.service\n",
          "      command: start\n",
          "      drop-ins:\n",
          "        - name: 50-network-config.conf\n",
          "          content: |\n",
          "            [Service]\n",
          "            ExecStartPre=-/usr/bin/etcdctl mk /coreos.com/network/config '{\"Network\": \"10.244.0.0/16\", \"Backend\": {\"Type\": \"vxlan\"}}'\n",
          "    - name: docker-cache.service\n",
          "      command: start\n",
          "      content: |\n",
          "        [Unit]\n",
          "        Description=Docker cache proxy\n",
          "        Requires=early-docker.service\n",
          "        After=early-docker.service\n",
          "        Before=early-docker.target\n\n",
          "        [Service]\n",
          "        Restart=always\n",
          "        TimeoutStartSec=0\n",
          "        RestartSec=5\n",
          "        Environment=TMPDIR=/var/tmp/\n",
          "        Environment=DOCKER_HOST=unix:///var/run/early-docker.sock\n",
          "        ExecStartPre=-/usr/bin/docker kill docker-registry\n",
          "        ExecStartPre=-/usr/bin/docker rm docker-registry\n",
          "        ExecStartPre=/usr/bin/docker pull quay.io/devops/docker-registry:latest\n",
          "        # GUNICORN_OPTS is an workaround for\n",
          "        # https://github.com/docker/docker-registry/issues/892\n",
          "        ExecStart=/usr/bin/docker run --rm --net host --name docker-registry \\\n",
          "            -e STANDALONE=false \\\n",
          "            -e GUNICORN_OPTS=[--preload] \\\n",
          "            -e MIRROR_SOURCE=https://registry-1.docker.io \\\n",
          "            -e MIRROR_SOURCE_INDEX=https://index.docker.io \\\n",
          "            -e MIRROR_TAGS_CACHE_TTL=1800 \\\n",
          "            quay.io/devops/docker-registry:latest\n",
          "    - name: get-kubectl.service\n",
          "      command: start\n",
          "      content: |\n",
          "        [Unit]\n",
          "        Description=Get kubectl client tool\n",
          "        Documentation=https://github.com/GoogleCloudPlatform/kubernetes\n",
          "        Requires=network-online.target\n",
          "        After=network-online.target\n\n",
          "        [Service]\n",
          "        ExecStart=/usr/bin/wget -N -P /opt/bin https://storage.googleapis.com/kubernetes-release/release/v0.17.0/bin/linux/amd64/kubectl\n",
          "        ExecStart=/usr/bin/chmod +x /opt/bin/kubectl\n",
          "        Type=oneshot\n",
          "        RemainAfterExit=true\n",
          "    - name: kube-apiserver.service\n",
          "      command: start\n",
          "      content: |\n",
          "        [Unit]\n",
          "        Description=Kubernetes API Server\n",
          "        Documentation=https://github.com/GoogleCloudPlatform/kubernetes\n",
          "        Requires=etcd2-waiter.service\n",
          "        After=etcd2-waiter.service\n\n",
          "        [Service]\n",
          "        ExecStartPre=/usr/bin/wget -N -P /opt/bin https://storage.googleapis.com/kubernetes-release/release/v0.17.0/bin/linux/amd64/kube-apiserver\n",
          "        ExecStartPre=/usr/bin/chmod +x /opt/bin/kube-apiserver\n",
          "        ExecStart=/opt/bin/kube-apiserver \\\n",
          "        --insecure-bind-address=0.0.0.0 \\\n",
          "        --portal-net=10.100.0.0/16 \\\n",
          "        --etcd-servers=http://localhost:2379\n",
          "        Restart=always\n",
          "        RestartSec=10\n",
          "    - name: kube-controller-manager.service\n",
          "      command: start\n",
          "      content: |\n",
          "        [Unit]\n",
          "        Description=Kubernetes Controller Manager\n",
          "        Documentation=https://github.com/GoogleCloudPlatform/kubernetes\n",
          "        Requires=kube-apiserver.service\n",
          "        After=kube-apiserver.service\n\n",
          "        [Service]\n",
          "        ExecStartPre=/usr/bin/wget -N -P /opt/bin https://storage.googleapis.com/kubernetes-release/release/v0.17.0/bin/linux/amd64/kube-controller-manager\n",
          "        ExecStartPre=/usr/bin/chmod +x /opt/bin/kube-controller-manager\n",
          "        ExecStart=/opt/bin/kube-controller-manager \\\n",
          "        --master=127.0.0.1:8080\n",
          "        Restart=always\n",
          "        RestartSec=10\n",
          "    - name: kube-scheduler.service\n",
          "      command: start\n",
          "      content: |\n",
          "        [Unit]\n",
          "        Description=Kubernetes Scheduler\n",
          "        Documentation=https://github.com/GoogleCloudPlatform/kubernetes\n",
          "        Requires=kube-apiserver.service\n",
          "        After=kube-apiserver.service\n\n",
          "        [Service]\n",
          "        ExecStartPre=/usr/bin/wget -N -P /opt/bin https://storage.googleapis.com/kubernetes-release/release/v0.17.0/bin/linux/amd64/kube-scheduler\n",
          "        ExecStartPre=/usr/bin/chmod +x /opt/bin/kube-scheduler\n",
          "        ExecStart=/opt/bin/kube-scheduler \\\n",
          "        --master=127.0.0.1:8080\n",
          "        Restart=always\n",
          "        RestartSec=10\n",
          "    - name: kube-register.service\n",
          "      command: start\n",
          "      content: |\n",
          "        [Unit]\n",
          "        Description=Kubernetes Registration Service\n",
          "        Documentation=https://github.com/kelseyhightower/kube-register\n",
          "        Requires=kube-apiserver.service fleet.service\n",
          "        After=kube-apiserver.service fleet.service\n\n",
          "        [Service]\n",
          "        ExecStartPre=-/usr/bin/wget -nc -O /opt/bin/kube-register https://github.com/kelseyhightower/kube-register/releases/download/v0.0.3/kube-register-0.0.3-linux-amd64\n",
          "        ExecStartPre=/usr/bin/chmod +x /opt/bin/kube-register\n",
          "        ExecStart=/opt/bin/kube-register \\\n",
          "        --metadata=k8srole=node \\\n",
          "        --fleet-endpoint=unix:///var/run/fleet.sock \\\n",
          "        --api-endpoint=http://127.0.0.1:8080\n",
          "        Restart=always\n",
          "        RestartSec=10\n",
          "  update:\n",
          "    group: alpha\n",
          "    reboot-strategy: off\n"
          ]]}
        }
      }
    },
    "KubernetesNodeLaunchConfig": {
      "Type": "AWS::AutoScaling::LaunchConfiguration",
      "Properties": {
        "ImageId": {"Fn::FindInMap" : ["RegionMap", {"Ref": "AWS::Region" }, "AMI" ]},
        "InstanceType": {"Ref": "InstanceType"},
        "KeyName": {"Ref": "KeyPair"},
        "AssociatePublicIpAddress" : "true",
        "SecurityGroups": [{"Fn::If": [
          "UseEC2Classic",
          {"Ref": "KubernetesSecurityGroup"},
          {"Fn::GetAtt": ["KubernetesSecurityGroup", "GroupId"]}]
        }],
        "UserData": { "Fn::Base64": {"Fn::Join" : ["", [
          "#cloud-config\n\n",
          "coreos:\n",
          "  etcd2:\n",
          "    listen-client-urls: http://localhost:2379\n",
          "    initial-cluster: master=http://", {"Fn::GetAtt" :["KubernetesMasterInstance" , "PrivateIp"]}, ":2380\n",
          "    proxy: on\n",
          "  fleet:\n",
          "    etcd_servers: http://localhost:2379\n",
          "    metadata: k8srole=node\n",
          "  flannel:\n",
          "    etcd_endpoints: http://localhost:2379\n",
          "  locksmithd:\n",
          "    endpoint: http://localhost:2379\n",
          "  units:\n",
          "    - name: etcd2.service\n",
          "      command: start\n",
          "    - name: fleet.service\n",
          "      command: start\n",
          "    - name: flanneld.service\n",
          "      command: start\n",
          "    - name: docker.service\n",
          "      command: start\n",
          "      drop-ins:\n",
          "        - name: 50-docker-mirror.conf\n",
          "          content: |\n",
          "            [Service]\n",
          "            Environment=DOCKER_OPTS='--registry-mirror=http://", {"Fn::GetAtt" :["KubernetesMasterInstance" , "PrivateIp"]}, ":5000'\n",
          "    - name: kubelet.service\n",
          "      command: start\n",
          "      content: |\n",
          "        [Unit]\n",
          "        Description=Kubernetes Kubelet\n",
          "        Documentation=https://github.com/GoogleCloudPlatform/kubernetes\n",
          "        Requires=network-online.target\n",
          "        After=network-online.target\n\n",
          "        [Service]\n",
          "        ExecStartPre=/usr/bin/wget -N -P /opt/bin https://storage.googleapis.com/kubernetes-release/release/v0.17.0/bin/linux/amd64/kubelet\n",
          "        ExecStartPre=/usr/bin/chmod +x /opt/bin/kubelet\n",
          "        ExecStart=/opt/bin/kubelet \\\n",
          "        --api-servers=", {"Fn::GetAtt" :["KubernetesMasterInstance" , "PrivateIp"]}, ":8080 \\\n",
          "        --hostname-override=$private_ipv4\n",
          "        Restart=always\n",
          "        RestartSec=10\n",
          "    - name: kube-proxy.service\n",
          "      command: start\n",
          "      content: |\n",
          "        [Unit]\n",
          "        Description=Kubernetes Proxy\n",
          "        Documentation=https://github.com/GoogleCloudPlatform/kubernetes\n",
          "        Requires=network-online.target\n",
          "        After=network-online.target\n\n",
          "        [Service]\n",
          "        ExecStartPre=/usr/bin/wget -N -P /opt/bin https://storage.googleapis.com/kubernetes-release/release/v0.17.0/bin/linux/amd64/kube-proxy\n",
          "        ExecStartPre=/usr/bin/chmod +x /opt/bin/kube-proxy\n",
          "        ExecStart=/opt/bin/kube-proxy \\\n",
          "        --master=http://", {"Fn::GetAtt" :["KubernetesMasterInstance" , "PrivateIp"]}, ":8080\n",
          "        Restart=always\n",
          "        RestartSec=10\n",
          "  update:\n",
          "    group: alpha\n",
          "    reboot-strategy: off\n"
          ]]}
        }
      }
    },
    "KubernetesAutoScalingGroup": {
      "Type": "AWS::AutoScaling::AutoScalingGroup",
      "Properties": {
        "AvailabilityZones": {"Fn::If": ["UseEC2Classic", {"Fn::GetAZs": ""}, [{"Ref": "SubnetAZ"}]]},
        "VPCZoneIdentifier": {"Fn::If": ["UseEC2Classic", {"Ref": "AWS::NoValue"}, [{"Ref": "SubnetId"}]]},
        "LaunchConfigurationName": {"Ref": "KubernetesNodeLaunchConfig"},
        "MinSize": "2",
        "MaxSize": "12",
        "DesiredCapacity": {"Ref": "ClusterSize"},
        "Tags" : [
          {"Key" : "Name", "Value" : {"Fn::Join" : [ "-", [ {"Ref" : "AWS::StackName"}, "k8s-node" ] ]}, "PropagateAtLaunch" : true},
          {"Key" : "KubernetesRole", "Value" : "node", "PropagateAtLaunch" : true}
        ]
      }
    }
  },
  "Outputs": {
    "KubernetesMasterPublicIp": {
    "Description": "Public Ip of the newly created Kubernetes Master instance",
      "Value": {"Fn::GetAtt": ["KubernetesMasterInstance" , "PublicIp"]}
    }
  }
}
