{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "Kubernetes 0.18.2 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.18.2/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.18.2/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", " --service-cluster-ip-range=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.18.2/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.18.2/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.18.2/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.18.2/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"]} } } }