Configure Puppet on CoreOS

By Bill Ward | September 19, 2016

This will be a quick post on how to get puppet configured to run on CoreOS. We will configure a puppetserver and an agent. Some of you may ask why would we need a configuration management tool for an immutable OS that is configured easily by cloud-config?

Well cloud-config is great for the initial configuration of your server but what about afterwards? This is where Puppet can step in and be a huge help. Puppet can help your organization in the long-term management of your CoreOS servers. In addition, you get the benefits of having factor data and reporting.

We will be setting up a puppet master server in a container found in the Docker hub as puppet/puppetserver-standalone. We will provide the puppet manifests and modules via a volume to /etc/puppetlabs/code and provide your code. The agent will be ran on another server. Things get a little tricky when we need to figure out how to get the two to talk with out fancy stuff like docker compose. We can’t utilize the /etc/hosts file in the container because at the time of this writing, CoreOS’s implementation of cloud-config doesn’t manage anything other than the localhost entry. Our only other option (again without using docker compose, swarm, or kubernetes) is to use DNS just like we normally would in any other Puppet installation.

Configure DNS

Setup your local DNS server to add a new ‘A’ record that will point to your puppetmaster. Here is the example from my lab environment:

/var/lib/bind/billcloud.local.hosts

puppet.billcloud.local. IN  A   192.168.1.20

Make sure to adjust for your environment. We will be statically setting the IP of our puppet server tp 192.168.1.20 using our cloud-config file discussed in the next section.

Puppet Server Configuration

For both of our servers the initial configuration will be performed via cloud-config. The cloud-config file for the puppet server is listed below:

#cloud-config

ssh_authorized_keys:
        - "ssh-rsa AAAAB3NzaC..."
hostname: "puppet"

coreos:  
    units:
        - name: "puppet.service"
          command: "start"
          content: |
                [Unit]
                Description=Puppet
                After=docker.service
                Requires=docker.service

                [Service]
                TimeoutStartSec=0
                ExecStartPre=-/usr/bin/docker kill puppet1
                ExecStartPre=-/usr/bin/docker rm puppet1
                ExecStartPre=/usr/bin/docker pull puppet/puppetserver-standalone
                ExecStart=/usr/bin/docker run --name puppet1 --hostname puppet -v /code:/etc/puppetlabs/code/ -p 8140:8140 -p 443:443 puppet/puppetserver-standalone

                [Install]
                WantedBy=multi-user.target
        - name: 00-ens192.network
          runtime: true
          content: |
                [Match]
                Name=ens192

                [Network]
                DNS=192.168.1.5
                Domains=billcloud.local
                Address=192.168.1.20
                Gateway=192.168.1.1

This is a pretty standard cloud-config file. We set the SSH public key that we will use to connect to our server and we set the hostname. This is of particular importance for us since the agents look for a system with a hostname of puppet. The next section sets up a systemd unit to manage the puppet server docker container. Notice that we expose the ports that puppet needs to communicate: TCP 8140 and 443. We also setup a volume that will house our puppet code in the /code directory on our host that will be mapped to /etc/puppetlabs/code/ on the container.

Configure Puppet Nodes

Startup your puppet server and after it completes booting login using SSH. Change to the /code/ directory. We need to create a directory structure like the following:

.
└── environments
    └── production
        ├── manifests
        │   └── site.pp
        └── modules
            ├── apache
            ├── ntp
            └── stdlib

Run the following command as root to setup the directory structure:

# mkdir environments/production/{manifests,modules} -p

Create a site.pp file in /code/environments/manifests/ with the following contents:

node 'agent.billcloud.local' {
}

There is nothing there yet but you can add configuration for your own modules later. Speaking of modules you need to download those to the /code/environments/production/modules directory. I find it easier to do a git pull since the base CoreOS image doesn’t come with puppet (so that we could do a puppet module install).

# git clone https://github.com/cristifalcas/puppet-etcd.git etcd

Once you get your modules downloaded proceed to the next section where we setup the agent node.

Puppet Agent Configuration

Here is the cloud-config we will use for our agent:

#cloud-config

ssh_authorized_keys:
        - "ssh-rsa AAAAB3NzaC..."
hostname: "agent"

coreos:  
    units:
        - name: "puppet.service"
          command: "start"
          content: |
                [Unit]
                Description=Puppet
                After=docker.service
                Requires=docker.service

                [Service]
                TimeoutStartSec=0
                ExecStartPre=-/usr/bin/docker kill puppet1
                ExecStartPre=-/usr/bin/docker rm puppet1
                ExecStartPre=/usr/bin/docker pull puppet/puppet-agent
                ExecStart=/usr/bin/docker run -rm --privileged --name puppet1 --hostname agent -v /tmp:/tmp -v /etc:/etc -v /var:/var -v /usr:/usr -v /lib64:/lib64 puppet/puppet-agent

                [Install]
                WantedBy=multi-user.target
        - name: 00-ens192.network
          runtime: true
          content: |
                [Match]
                Name=ens192

                [Network]
                DNS=192.168.1.5
                Domains=billcloud.local
                Address=192.168.1.22
                Gateway=192.168.1.1

This one is very similar to our previous cloud-config for our server. For our agent we will use the puppet/puppet-agent. The cool thing about using puppet in a container is ease of installation but we don’t want to manage the container, because containers by definition are immutable. What we can do is share a bunch of volumes that link to the host OS. This will allow the puppet agent in the container to manage our host operating system!

-v /tmp:/tmp -v /etc:/etc -v /var:/var -v /usr:/usr -v /lib64:/lib64

Start up the agent server and login using SSH. Check the status of the puppet.service systemd unit using the journalctl command and you should see output similiar to the following:

$ journalctl -f -u puppet.service -n 40

Sep 20 03:43:47 agent docker[2229]: Info: Caching catalog for agent.billcloud.local
Sep 20 03:43:47 agent docker[2229]: Info: Applying configuration version '1474343027'
Sep 20 03:43:47 agent docker[2229]: Info: Creating state file /opt/puppetlabs/puppet/cache/state/state.yaml
Sep 20 03:43:47 agent docker[2229]: Notice: Applied catalog in 0.03 seconds
Sep 20 03:43:47 agent docker[2229]: Changes:
Sep 20 03:43:47 agent docker[2229]: Events:
Sep 20 03:43:47 agent docker[2229]: Resources:
Sep 20 03:43:47 agent docker[2229]:             Total: 7
Sep 20 03:43:47 agent docker[2229]: Time:
Sep 20 03:43:47 agent docker[2229]:        Filebucket: 0.00
Sep 20 03:43:47 agent docker[2229]:          Schedule: 0.00
Sep 20 03:43:47 agent docker[2229]:    Config retrieval: 0.25
Sep 20 03:43:47 agent docker[2229]:             Total: 0.25
Sep 20 03:43:47 agent docker[2229]:          Last run: 1474343027
Sep 20 03:43:47 agent docker[2229]: Version:
Sep 20 03:43:47 agent docker[2229]:            Config: 1474343027
Sep 20 03:43:47 agent docker[2229]:            Puppet: 4.6.2

You now have a fully functioning puppet environment running in CoreOS! If you are running a cluster of servers just include the puppet agent systemd unit definition in your cloud-config and setup the puppet configuration to manage it.

In future posts I will discuss using Puppet and CoreOS in greater detail.

I hope you enjoyed this post. If you would like to be notified of future posts please sign up for my newsletter:

Subscribe to our mailing list

indicates required
Email Format

comments powered by Disqus
Google Analytics Alternative