Running CoreOS Container Linux on EC2

The current AMIs for all Container Linux channels and EC2 regions are listed below and updated frequently. Using CloudFormation is the easiest way to launch a cluster, but it is also possible to follow the manual steps at the end of the article. Questions can be directed to the CoreOS IRC channel or user mailing list.

Choosing a channel

Container Linux is designed to be updated automatically with different schedules per channel. You can disable this feature, although we don't recommend it. Read the release notes for specific features and bug fixes.

The Alpha channel closely tracks master and is released frequently. The newest versions of system libraries and utilities will be available for testing. The current version is Container Linux 1662.0.0.

View as json feed
EC2 Region AMI Type AMI ID CloudFormation
ap-northeast-1 PV ami-c1583ea7 Launch Stack
HVM ami-545a3c32 Launch Stack
ap-northeast-2 PV ami-5e1cbc30 Launch Stack
HVM ami-a41cbcca Launch Stack
ap-south-1 PV ami-f26f399d Launch Stack
HVM ami-7260361d Launch Stack
ap-southeast-1 PV ami-39493645 Launch Stack
HVM ami-cd4936b1 Launch Stack
ap-southeast-2 PV ami-31a25d53 Launch Stack
HVM ami-12a35c70 Launch Stack
ca-central-1 PV ami-6b64e10f Launch Stack
HVM ami-225adf46 Launch Stack
cn-north-1 PV ami-720ad71f Launch Stack
HVM ami-a500ddc8 Launch Stack
eu-central-1 PV ami-cf5cc3a0 Launch Stack
HVM ami-615cc30e Launch Stack
eu-west-1 PV ami-0bc65e72 Launch Stack
HVM ami-8fc25af6 Launch Stack
eu-west-2 PV ami-f8c2d99c Launch Stack
HVM ami-86c0dbe2 Launch Stack
sa-east-1 PV ami-d57b36b9 Launch Stack
HVM ami-387e3354 Launch Stack
us-east-1 PV ami-2fffd055 Launch Stack
HVM ami-85e5caff Launch Stack
us-east-2 PV ami-8be9c3ee Launch Stack
HVM ami-d5eac0b0 Launch Stack
us-gov-west-1 PV ami-58951c39 Launch Stack
HVM ami-59951c38 Launch Stack
us-west-1 PV ami-763f3d16 Launch Stack
HVM ami-ad3d3fcd Launch Stack
us-west-2 PV ami-256edd5d Launch Stack
HVM ami-136fdc6b Launch Stack

The Beta channel consists of promoted Alpha releases. The current version is Container Linux 1632.1.0.

View as json feed
EC2 Region AMI Type AMI ID CloudFormation
ap-northeast-1 PV ami-8aae32ec Launch Stack
HVM ami-08a9356e Launch Stack
ap-northeast-2 PV ami-f6c66698 Launch Stack
HVM ami-94c666fa Launch Stack
ap-south-1 PV ami-b75d09d8 Launch Stack
HVM ami-e7580c88 Launch Stack
ap-southeast-1 PV ami-4c9ee830 Launch Stack
HVM ami-4390e63f Launch Stack
ap-southeast-2 PV ami-76ca3814 Launch Stack
HVM ami-22c73540 Launch Stack
ca-central-1 PV ami-91e461f5 Launch Stack
HVM ami-06e76262 Launch Stack
cn-north-1 PV ami-96df02fb Launch Stack
HVM ami-f1de039c Launch Stack
eu-central-1 PV ami-c3dd4eac Launch Stack
HVM ami-dfde4db0 Launch Stack
eu-west-1 PV ami-a926b1d0 Launch Stack
HVM ami-d827b0a1 Launch Stack
eu-west-2 PV ami-57c5dd33 Launch Stack
HVM ami-87c7dfe3 Launch Stack
sa-east-1 PV ami-a6b9faca Launch Stack
HVM ami-feb8fb92 Launch Stack
us-east-1 PV ami-68603012 Launch Stack
HVM ami-137b2b69 Launch Stack
us-east-2 PV ami-dae5cebf Launch Stack
HVM ami-40e7cc25 Launch Stack
us-gov-west-1 PV ami-9877f9f9 Launch Stack
HVM ami-9a79f7fb Launch Stack
us-west-1 PV ami-b76464d7 Launch Stack
HVM ami-a86363c8 Launch Stack
us-west-2 PV ami-d073d9a8 Launch Stack
HVM ami-1476dc6c Launch Stack

The Stable channel should be used by production clusters. Versions of Container Linux are battle-tested within the Beta and Alpha channels before being promoted. The current version is Container Linux 1576.5.0.

View as json feed
EC2 Region AMI Type AMI ID CloudFormation
ap-northeast-1 PV ami-2aa13d4c Launch Stack
HVM ami-44a03c22 Launch Stack
ap-northeast-2 PV ami-8bc969e5 Launch Stack
HVM ami-b3c969dd Launch Stack
ap-south-1 PV ami-894410e6 Launch Stack
HVM ami-655a0e0a Launch Stack
ap-southeast-1 PV ami-ef80f693 Launch Stack
HVM ami-d085f3ac Launch Stack
ap-southeast-2 PV ami-fccf3d9e Launch Stack
HVM ami-21ce3c43 Launch Stack
ca-central-1 PV ami-8adb5eee Launch Stack
HVM ami-11e46175 Launch Stack
cn-north-1 PV ami-6ad90407 Launch Stack
HVM ami-9bdf02f6 Launch Stack
eu-central-1 PV ami-cbc754a4 Launch Stack
HVM ami-90c152ff Launch Stack
eu-west-1 PV ami-71da4c08 Launch Stack
HVM ami-32d1474b Launch Stack
eu-west-2 PV ami-ccc7dfa8 Launch Stack
HVM ami-f2fae296 Launch Stack
sa-east-1 PV ami-7dbefd11 Launch Stack
HVM ami-78befd14 Launch Stack
us-east-1 PV ami-0984d473 Launch Stack
HVM ami-e582d29f Launch Stack
us-east-2 PV ami-6cfad109 Launch Stack
HVM ami-07fbd062 Launch Stack
us-gov-west-1 PV ami-7f77f91e Launch Stack
HVM ami-9579f7f4 Launch Stack
us-west-1 PV ami-6e68680e Launch Stack
HVM ami-e0696980 Launch Stack
us-west-2 PV ami-3746ec4f Launch Stack
HVM ami-dc4ce6a4 Launch Stack

CloudFormation will launch a cluster of Container Linux machines with a security and autoscaling group.

Container Linux Configs

Container Linux allows you to configure machine parameters, configure networking, launch systemd units on startup, and more via Container Linux Configs. These configs are then transpiled into Ignition configs and given to booting machines. Head over to the docs to learn about the supported features.

You can provide a raw Ignition config to Container Linux via the Amazon web console or via the EC2 API.

As an example, this Container Linux Config will configure and start etcd:

This is the human-readable config file. This should not be immediately passed to Container Linux. Learn more.
# This config is meant to be consumed by the config transpiler, which will
# generate the corresponding Ignition config. Do not pass this config directly
# to instances of Container Linux.

etcd:
  # All options get passed as command line flags to etcd.
  # Any information inside curly braces comes from the machine at boot time.

  # multi_region and multi_cloud deployments need to use {PUBLIC_IPV4}
  advertise_client_urls:       "http://{PRIVATE_IPV4}:2379"
  initial_advertise_peer_urls: "http://{PRIVATE_IPV4}:2380"
  # listen on both the official ports and the legacy ports
  # legacy ports can be omitted if your application doesn't depend on them
  listen_client_urls:          "http://0.0.0.0:2379"
  listen_peer_urls:            "http://{PRIVATE_IPV4}:2380"
  # generate a new token for each unique cluster from https://discovery.etcd.io/new?size=3
  # specify the initial size of your cluster with ?size=X
  discovery:                   "https://discovery.etcd.io/<token>"
This is the raw machine configuration, which is not intended for editing. Learn more. Validate the config here.
{
  "ignition": {
    "config": {},
    "timeouts": {},
    "version": "2.1.0"
  },
  "networkd": {},
  "passwd": {},
  "storage": {},
  "systemd": {
    "units": [
      {
        "dropins": [
          {
            "contents": "[Unit]\nRequires=coreos-metadata.service\nAfter=coreos-metadata.service\n\n[Service]\nEnvironmentFile=/run/metadata/coreos\nExecStart=\nExecStart=/usr/lib/coreos/etcd-wrapper $ETCD_OPTS \\\n  --listen-peer-urls=\"http://${COREOS_EC2_IPV4_LOCAL}:2380\" \\\n  --listen-client-urls=\"http://0.0.0.0:2379\" \\\n  --initial-advertise-peer-urls=\"http://${COREOS_EC2_IPV4_LOCAL}:2380\" \\\n  --advertise-client-urls=\"http://${COREOS_EC2_IPV4_LOCAL}:2379\" \\\n  --discovery=\"https://discovery.etcd.io/\u003ctoken\u003e\"",
            "name": "20-clct-etcd-member.conf"
          }
        ],
        "enable": true,
        "name": "etcd-member.service"
      }
    ]
  }
}

Instance storage

Ephemeral disks and additional EBS volumes attached to instances can be mounted with a .mount unit. Amazon's block storage devices are attached differently depending on the instance type. Here's the Container Linux Config to format and mount the first ephemeral disk, xvdb, on most instance types:

This is the human-readable config file. This should not be immediately passed to Container Linux. Learn more.
# This config is meant to be consumed by the config transpiler, which will
# generate the corresponding Ignition config. Do not pass this config directly
# to instances of Container Linux.

storage:
  filesystems:
    - mount:
        device: /dev/xvdb
        format: ext4
        wipe_filesystem: true

systemd:
  units:
    - name: media-ephemeral.mount
      enable: true
      contents: |
        [Mount]
        What=/dev/xvdb
        Where=/media/ephemeral
        Type=ext4

        [Install]
        RequiredBy=local-fs.target
This is the raw machine configuration, which is not intended for editing. Learn more. Validate the config here.
{
  "ignition": {
    "config": {},
    "timeouts": {},
    "version": "2.1.0"
  },
  "networkd": {},
  "passwd": {},
  "storage": {
    "filesystems": [
      {
        "mount": {
          "device": "/dev/xvdb",
          "format": "ext4",
          "wipeFilesystem": true
        }
      }
    ]
  },
  "systemd": {
    "units": [
      {
        "contents": "[Mount]\nWhat=/dev/xvdb\nWhere=/media/ephemeral\nType=ext4\n\n[Install]\nRequiredBy=local-fs.target",
        "enable": true,
        "name": "media-ephemeral.mount"
      }
    ]
  }
}

For more information about mounting storage, Amazon's own documentation is the best source. You can also read about mounting storage on Container Linux.

Adding more machines

To add more instances to the cluster, just launch more with the same Container Linux Config, the appropriate security group and the AMI for that region. New instances will join the cluster regardless of region if the security groups are configured correctly.

SSH to your instances

Container Linux is set up to be a little more secure than other cloud images. By default, it uses the core user instead of root and doesn't use a password for authentication. You'll need to add an SSH key(s) via the AWS console or add keys/passwords via your Container Linux Config in order to log in.

To connect to an instance after it's created, run:

ssh core@<ip address>

Optionally, you may want to configure your ssh-agent to more easily run fleet commands.

Multiple clusters

If you would like to create multiple clusters you will need to change the "Stack Name". You can find the direct template file on S3.

Manual setup

TL;DR: launch three instances of ami-2fffd055 in us-east-1 with a security group that has open port 22, 2379, 2380, 4001, and 7001 and the same "User Data" of each host. SSH uses the core user and you have etcd and Docker to play with.

Creating the security group

You need open port 2379, 2380, 7001 and 4001 between servers in the etcd cluster. Step by step instructions below.

This step is only needed once

First we need to create a security group to allow Container Linux instances to communicate with one another.

  1. Go to the security group page in the EC2 console.
  2. Click "Create Security Group"
    • Name: coreos-testing
    • Description: Container Linux instances
    • VPC: No VPC
    • Click: "Yes, Create"
  3. In the details of the security group, click the Inbound tab
  4. First, create a security group rule for SSH
    • Create a new rule: SSH
    • Source: 0.0.0.0/0
    • Click: "Add Rule"
  5. Add two security group rules for etcd communication
    • Create a new rule: Custom TCP rule
    • Port range: 2379
    • Source: type "coreos-testing" until your security group auto-completes. Should be something like "sg-8d4feabc"
    • Click: "Add Rule"
    • Repeat this process for port range 2380, 4001 and 7001 as well
  6. Click "Apply Rule Changes"

Launching a test cluster

We will be launching three instances, with a few parameters in the User Data, and selecting our security group.

  1. Open the quick launch wizard to boot ami-2fffd055.
  2. On the second page of the wizard, launch 3 servers to test our clustering
    • Number of instances: 3
    • Click "Continue"
  3. Next, we need to specify a discovery URL, which contains a unique token that allows us to find other hosts in our cluster. If you're launching your first machine, generate one at https://discovery.etcd.io/new?size=3, configure the `?size=` to your initial cluster size and add it to the metadata. You should re-use this key for each machine in the cluster.
  4. Use ct to convert the following configuration into an Ignition config, and back in the EC2 dashboard, paste it into the "User Data" field.
    This is the human-readable config file. This should not be immediately passed to Container Linux. Learn more.
    # This config is meant to be consumed by the config transpiler, which will
    # generate the corresponding Ignition config. Do not pass this config directly
    # to instances of Container Linux.
    
              etcd:
                # All options get passed as command line flags to etcd.
                # Any information inside curly braces comes from the machine at boot time.
              
                # multi_region and multi_cloud deployments need to use {PUBLIC_IPV4}
                advertise_client_urls:       "http://{PRIVATE_IPV4}:2379"
                initial_advertise_peer_urls: "http://{PRIVATE_IPV4}:2380"
                # listen on both the official ports and the legacy ports
                # legacy ports can be omitted if your application doesn't depend on them
                listen_client_urls:          "http://0.0.0.0:2379"
                listen_peer_urls:            "http://{PRIVATE_IPV4}:2380"
                # generate a new token for each unique cluster from https://discovery.etcd.io/new?size=3
                # specify the initial size of your cluster with ?size=X
                discovery:                   "https://discovery.etcd.io/<token>"
    
    This is the raw machine configuration, which is not intended for editing. Learn more. Validate the config here.
    {
      "ignition": {
        "config": {},
        "timeouts": {},
        "version": "2.1.0"
      },
      "networkd": {},
      "passwd": {},
      "storage": {},
      "systemd": {
        "units": [
          {
            "dropins": [
              {
                "contents": "[Unit]\nRequires=coreos-metadata.service\nAfter=coreos-metadata.service\n\n[Service]\nEnvironmentFile=/run/metadata/coreos\nExecStart=\nExecStart=/usr/lib/coreos/etcd-wrapper $ETCD_OPTS \\\n  --listen-peer-urls=\"http://${COREOS_EC2_IPV4_LOCAL}:2380\" \\\n  --listen-client-urls=\"http://0.0.0.0:2379\" \\\n  --initial-advertise-peer-urls=\"http://${COREOS_EC2_IPV4_LOCAL}:2380\" \\\n  --advertise-client-urls=\"http://${COREOS_EC2_IPV4_LOCAL}:2379\" \\\n  --discovery=\"https://discovery.etcd.io/\u003ctoken\u003e\"",
                "name": "20-clct-etcd-member.conf"
              }
            ],
            "enable": true,
            "name": "etcd-member.service"
          }
        ]
      }
    }
    
    • Paste configuration into "User Data"
    • "Continue"
  5. Storage Configuration
    • "Continue"
  6. Tags
    • "Continue"
  7. Create Key Pair
    • Choose a key of your choice, it will be added in addition to the one in the gist.
    • "Continue"
  8. Choose one or more of your existing Security Groups
    • "coreos-testing" as above.
    • "Continue"
  9. Launch!

We will be launching three instances, with a few parameters in the User Data, and selecting our security group.

  1. Open the quick launch wizard to boot ami-68603012.
  2. On the second page of the wizard, launch 3 servers to test our clustering
    • Number of instances: 3
    • Click "Continue"
  3. Next, we need to specify a discovery URL, which contains a unique token that allows us to find other hosts in our cluster. If you're launching your first machine, generate one at https://discovery.etcd.io/new?size=3, configure the `?size=` to your initial cluster size and add it to the metadata. You should re-use this key for each machine in the cluster.
  4. Use ct to convert the following configuration into an Ignition config, and back in the EC2 dashboard, paste it into the "User Data" field.
    This is the human-readable config file. This should not be immediately passed to Container Linux. Learn more.
    # This config is meant to be consumed by the config transpiler, which will
    # generate the corresponding Ignition config. Do not pass this config directly
    # to instances of Container Linux.
    
              etcd:
                # All options get passed as command line flags to etcd.
                # Any information inside curly braces comes from the machine at boot time.
              
                # multi_region and multi_cloud deployments need to use {PUBLIC_IPV4}
                advertise_client_urls:       "http://{PRIVATE_IPV4}:2379"
                initial_advertise_peer_urls: "http://{PRIVATE_IPV4}:2380"
                # listen on both the official ports and the legacy ports
                # legacy ports can be omitted if your application doesn't depend on them
                listen_client_urls:          "http://0.0.0.0:2379"
                listen_peer_urls:            "http://{PRIVATE_IPV4}:2380"
                # generate a new token for each unique cluster from https://discovery.etcd.io/new?size=3
                # specify the initial size of your cluster with ?size=X
                discovery:                   "https://discovery.etcd.io/<token>"
    
    This is the raw machine configuration, which is not intended for editing. Learn more. Validate the config here.
    {
      "ignition": {
        "config": {},
        "timeouts": {},
        "version": "2.1.0"
      },
      "networkd": {},
      "passwd": {},
      "storage": {},
      "systemd": {
        "units": [
          {
            "dropins": [
              {
                "contents": "[Unit]\nRequires=coreos-metadata.service\nAfter=coreos-metadata.service\n\n[Service]\nEnvironmentFile=/run/metadata/coreos\nExecStart=\nExecStart=/usr/lib/coreos/etcd-wrapper $ETCD_OPTS \\\n  --listen-peer-urls=\"http://${COREOS_EC2_IPV4_LOCAL}:2380\" \\\n  --listen-client-urls=\"http://0.0.0.0:2379\" \\\n  --initial-advertise-peer-urls=\"http://${COREOS_EC2_IPV4_LOCAL}:2380\" \\\n  --advertise-client-urls=\"http://${COREOS_EC2_IPV4_LOCAL}:2379\" \\\n  --discovery=\"https://discovery.etcd.io/\u003ctoken\u003e\"",
                "name": "20-clct-etcd-member.conf"
              }
            ],
            "enable": true,
            "name": "etcd-member.service"
          }
        ]
      }
    }
    
    • Paste configuration into "User Data"
    • "Continue"
  5. Storage Configuration
    • "Continue"
  6. Tags
    • "Continue"
  7. Create Key Pair
    • Choose a key of your choice, it will be added in addition to the one in the gist.
    • "Continue"
  8. Choose one or more of your existing Security Groups
    • "coreos-testing" as above.
    • "Continue"
  9. Launch!

We will be launching three instances, with a few parameters in the User Data, and selecting our security group.

  1. Open the quick launch wizard to boot ami-0984d473.
  2. On the second page of the wizard, launch 3 servers to test our clustering
    • Number of instances: 3
    • Click "Continue"
  3. Next, we need to specify a discovery URL, which contains a unique token that allows us to find other hosts in our cluster. If you're launching your first machine, generate one at https://discovery.etcd.io/new?size=3, configure the `?size=` to your initial cluster size and add it to the metadata. You should re-use this key for each machine in the cluster.
  4. Use ct to convert the following configuration into an Ignition config, and back in the EC2 dashboard, paste it into the "User Data" field.
    This is the human-readable config file. This should not be immediately passed to Container Linux. Learn more.
    # This config is meant to be consumed by the config transpiler, which will
    # generate the corresponding Ignition config. Do not pass this config directly
    # to instances of Container Linux.
    
              etcd:
                # All options get passed as command line flags to etcd.
                # Any information inside curly braces comes from the machine at boot time.
              
                # multi_region and multi_cloud deployments need to use {PUBLIC_IPV4}
                advertise_client_urls:       "http://{PRIVATE_IPV4}:2379"
                initial_advertise_peer_urls: "http://{PRIVATE_IPV4}:2380"
                # listen on both the official ports and the legacy ports
                # legacy ports can be omitted if your application doesn't depend on them
                listen_client_urls:          "http://0.0.0.0:2379"
                listen_peer_urls:            "http://{PRIVATE_IPV4}:2380"
                # generate a new token for each unique cluster from https://discovery.etcd.io/new?size=3
                # specify the initial size of your cluster with ?size=X
                discovery:                   "https://discovery.etcd.io/<token>"
    
    This is the raw machine configuration, which is not intended for editing. Learn more. Validate the config here.
    {
      "ignition": {
        "config": {},
        "timeouts": {},
        "version": "2.1.0"
      },
      "networkd": {},
      "passwd": {},
      "storage": {},
      "systemd": {
        "units": [
          {
            "dropins": [
              {
                "contents": "[Unit]\nRequires=coreos-metadata.service\nAfter=coreos-metadata.service\n\n[Service]\nEnvironmentFile=/run/metadata/coreos\nExecStart=\nExecStart=/usr/lib/coreos/etcd-wrapper $ETCD_OPTS \\\n  --listen-peer-urls=\"http://${COREOS_EC2_IPV4_LOCAL}:2380\" \\\n  --listen-client-urls=\"http://0.0.0.0:2379\" \\\n  --initial-advertise-peer-urls=\"http://${COREOS_EC2_IPV4_LOCAL}:2380\" \\\n  --advertise-client-urls=\"http://${COREOS_EC2_IPV4_LOCAL}:2379\" \\\n  --discovery=\"https://discovery.etcd.io/\u003ctoken\u003e\"",
                "name": "20-clct-etcd-member.conf"
              }
            ],
            "enable": true,
            "name": "etcd-member.service"
          }
        ]
      }
    }
    
    • Paste configuration into "User Data"
    • "Continue"
  5. Storage Configuration
    • "Continue"
  6. Tags
    • "Continue"
  7. Create Key Pair
    • Choose a key of your choice, it will be added in addition to the one in the gist.
    • "Continue"
  8. Choose one or more of your existing Security Groups
    • "coreos-testing" as above.
    • "Continue"
  9. Launch!

Using CoreOS Container Linux

Now that you have a machine booted it is time to play around. Check out the Container Linux Quickstart guide or dig into more specific topics.