Deploy CoreOS with Ansible
CoreOS is a lightweight Linux operating system designed for clustered deployments providing automation, security, and scalability for your most critical applications. I’ve been playing with CoreOS to replace Debian hosts which run Docker containers on Nousmotards project. CoreOS helps on simplifying bare metal deployment and avoid managing OS upgrade.
As I’m still an Ansible lover, I’ve made 2 roles:
- CoreOS Ansible: Ansible role to deploy pypy to CoreOS to be able to get Ansible prerequisites
- CoreOS: Ansible CoreOS role to deploy CoreOS on bare metal servers
If you want to quickly look at the result:
The first one is for installing pypy to run Ansible and the other one to bootstrap CoreOS with Cloudinit or/and Igninition. Those role will bootstrap a complete cluster with etcd, flannel, fleet etc…ready to run a Kubernetes cluster on it! It will generate configs for each hosts and deploy them automatically. It will permit to add vars, generate the configs and you can keep history with git for example. Here are the options of the role:
# Choose CoreOS channel between stable, beta or alpha channels
coreos_channel: "stable"
# Generate a token: https://discovery.etcd.io/new?size=3
coreos_token: "81b89915ae4edd9a65ad9d0301381c52"
# Choose reboot strategy between: etcd-lock, reboot and off
coreos_reboot_strategy: "etcd-lock"
# Define your public interface and IP
coreos_public_ip: "{{ansible_default_ipv4.address}}"
coreos_public_if: "{{ansible_default_ipv4.interface}}"
# Define your private interface and IP
coreos_private_ip: "{{priv_ip}}"
coreos_private_if: "{{priv_if}}"
# Define dedicated subnet for containers communication
coreos_flanneld_subnet: "10.1.0.0/16"
# Add fleet metadata
coreos_fleet_metadata: "cluster=dev"
# If true, will bootstrap the server (data may be lost),
# else config files will be generated
coreos_launch_bootstrap: true
coreos_device_install: "/dev/sda"
coreos_install_additional_options: ""
coreos_eject_cd_before_reboot: true
coreos_reboot_after_bootstrap: true
# Dump generated Ingition and Cloudinit configs
coreos_dump_ignition_cloudinit_config: true
coreos_dump_ignition_cloudinit_dest: "{{role_path}}/files/generated_configs"
# Select Timezone
coreos_timezone: "UTC"
# CoreOS toolbox image type
coreos_toolbox_docker_image: "debian"
coreos_toolbox_docker_tag: "stable"
# Ignition
coreos_bootstrap_ignition: false
coreos_ignition:
ignition:
version: "2.0.0"
storage:
disks:
- device: "/dev/sdb"
wipeTable: true
partitions:
- label: "data.0"
number: 1
size: 0
start: 0
- device: "/dev/sdc"
wipeTable: true
partitions:
- label: "data.1"
number: 1
size: 0
start: 0
# Cloudinit
coreos_bootstrap_cloudinit: true
coreos_cloudinit:
hostname: "{{inventory_hostname}}"
coreos:
etcd2:
discovery: "https://discovery.etcd.io/{{coreos_token}}"
#name: 'cluster01'
advertise-client-urls: "http://{{coreos_public_ip}}:2379"
#initial-cluster-token: 'cluster-prod'
#initial-cluster-state: "{{coreos_cluster_state}}"
#initial-cluster: "core01=http://172.17.8.101:2380, core02=http://172.17.8.102:2380, core03=http://172.17.8.103:2380,"
initial-advertise-peer-urls: "http://{{coreos_private_ip}}:2380"
listen-peer-urls: "http://{{coreos_private_ip}}:2380,http://{{coreos_private_ip}}:7001"
listen-client-urls: "http://0.0.0.0:2379,http://0.0.0.0:4001"
update:
group: "{{coreos_channel}}"
reboot-strategy: "{{coreos_reboot_strategy}}"
fleet:
public-ip: "{{coreos_public_ip}}"
metadata: "{{coreos_fleet_metadata}}"
flannel:
interface: "{{coreos_public_ip}}"
units:
- name: "00-{{coreos_public_if}}.network"
runtime: true
content: |
[Match]
Name={{coreos_public_if}}
[Network]
DHCP=true
- name: "00-{{coreos_private_if}}.network"
runtime: true
content: |
[Match]
Name={{coreos_private_if}}
[Network]
Address={{coreos_private_ip}}/24
- name: iptables-restore.service
enable: true
command: start
- name: settimezone.service
command: start
content: |
[Unit]
Description=Set the time zone
[Service]
ExecStart=/usr/bin/timedatectl set-timezone {{coreos_timezone}}
RemainAfterExit=yes
Type=oneshot
- name: systemd-modules-load.service
command: restart
- name: systemd-sysctl.service
command: restart
- name: systemd-timesyncd.service
command: start
- name: etcd2.service
command: start
- name: fleet.service
command: start
- name: docker.service
command: start
- name: flanneld.service
drop-ins:
- name: 50-network-config.conf
content: |
[Service]
ExecStartPre=/usr/bin/etcdctl set /coreos.com/network/config '{ "Network": "{{coreos_flanneld_subnet}}" }'
command: start
- name: docker-tcp.socket
command: start
enable: true
content: |
[Unit]
Description=Docker Socket for the API
After=mnt-data.mount
Requires=mnt-data.mount
[Socket]
ListenStream=2375
Service=docker.service
BindIPv6Only=both
[Install]
WantedBy=sockets.target
write_files:
- path: "/home/core/.toolboxrc"
owner: core
content: |
TOOLBOX_DOCKER_IMAGE={{coreos_toolbox_docker_image}}
TOOLBOX_DOCKER_TAG={{coreos_toolbox_docker_tag}}
- path: /var/lib/iptables/rules-save
permissions: 0644
owner: root:root
content: |
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -i {{coreos_private_if}} -j ACCEPT
-A INPUT -i tap0 -p all -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 0 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 3 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 11 -j ACCEPT
COMMIT
users:
- name: 'core'
ssh-authorized-keys:
- "your ssh key here"
ansible_ssh_user: core
ansible_python_interpreter: "/opt/python/bin/python"
Finally call it that way:
- name: coreos-ansible
hosts: coreos
user: core
become: yes
gather_facts: False
serial: 1
roles:
- deimosfr.coreos-ansible
vars:
ansible_ssh_user: core
ansible_python_interpreter: "/opt/python/bin/python"
- name: coreos-bootstrap
hosts: coreos
user: core
become: yes
#become_method: su
#gather_facts: False
roles:
- deimosfr.coreos
vars:
ansible_ssh_user: core
ansible_python_interpreter: "/opt/python/bin/python"
Inside this role you’ll also find a Vagrantfile to deploy a test cluster easily!
Do not hesitate to give feedback and participate to enhance them :-)