Monday, July 6, 2015

Intro to Systemd and Unit Files

Systemd is an init system, managing how you start, stop and restart services. It also manages how services come up when you start a machine. Most linux distros have been using SysVinit and Ubuntu has been using Upstart up until recently, but Systemd seems to be what all of the distros are standardizing on. Systemd basically calls daemons, which we refer to as units. A unit is any service or resource that the systems manages or controls. They may go by other names depending on the OS. Linux calls them daemons, Windows calls them processes, and so on. All units have their own start scripts.

Prerequisites: Helps to know a bit about How Sysadmins Keep Services Running. This article was written for Linux users.

Example Systemd Commands

# check which units we have on our system
# lists services, slices, sockets, and others
systemctl list-units

# only list the services
systemctl list-units | grep .service

# to check the status of a service
systemctl status [NAME]

# to start a service, ssh for example
sudo systemctl start ssh

# to restart a service, ssh for example
sudo systemctl start ssh.service

# to disable
sudo systemctl disable [NAME]

Even though systemd manages .service files, when running commands against them, you don't need to put in the extension because it's already assumed.

Note: You need to use sudo when you want to manipulate services, but not when you just need to check the status.

# list the units that failed to run on machine startup
systemctl --failed

# determine if a service is disabled 
systemctl is-enabled [NAME]

# reboot the system
systemctl reboot

# shutdown the system
systemctl poweroff

# suspend the machine to ram
systemctl suspend

Usually in an enterprise environment, you may not want all of your services running all the time, either for security reasons or for cost-effectiveness. Definitely leverage Systemd to have more control over those services.

Systemd Logging

journalctl is used when you want to output binary logs.

# see everything in the log
journalctl

# show only log messages from this boot
journalctl -b

# show only log messages from a specific unit
journalctl -u [NAME]

Service Files

Now, let's create a service file for Systemd call it example.service. The system's unit files are normally stored in /lib/systemd/system. It's best to leave those files alone and store your own inside /etc/systemd/system, which supersede the lib unit files, anyway. Give it the following contents:

Before moving on, let's talk about the structure of this file. Unit files are chunks that are made up of Sections, Directives, and values. Take note of the casing, if you want to go by conventions. For a full list of Section Directives and other options, check the Systemd man page or header over to this link.

[Section]
Directive=value
Directive=value
Directive=value

Now, let me take a second to explain the various terms littered throughout this unit file.

  • The [Unit] section describes the basic metadata. We describe the unit and require the service to start only after docker.service is active.
  • The [Service] section encompasses the commands we'll be executing to get our container up and running. We also define commands that will execute before and after the container spins up.
  • The [Install] section defines the behavior of a unit if it's enabled or disabled. We set a Systemd target, or state we want our service started in, and assign the value to the WantedBy directive. Targets are the rough equivalent or SysVinit runlevels. We're using multi-user.target, which means multiple users can access this through a text-based console or via the network. Another type of target would be rescue.target which is single user and used for maintenance mode. See this SysVinit to Systemd cheatsheet if you'd like to learn more.

Unit File Types

Systemd defines different formats for different tasks, each unit file having its own configuration. The following categories are:

  • *.service
  • *.target
  • *.socket
  • *.device
  • *.mount
  • *.automount
  • *.path
  • *.snapshot
  • *.swap
  • *.timer

When you want to break out your files more granularly, create a directory named after the unit and append .d to the end. See the following example:

 |~etc/
 | `~systemd/
 |   `~system/
 |     |~example.service.d/
 |     | `-local.conf

Now, you're free to safely override the configuration for any vendor files. To override our previous example.service we could do something like the following, adding a check to ensure that /var/www exists before running the service:

[Unit]
Description="My Service"
AssertPathExists=/var/www

Now, that about concludes the topics in this article. We'll be revisiting these concepts in the future, when we go over CoreOS and Fleet, and continue to expand upon them as we find more ways to apply this knowledge, so check back often.

No comments:

Post a Comment