[lug] Systemd unit file experiments

Lee Woodworth blug-mail at duboulder.com
Sat Mar 31 20:59:47 MDT 2018


On 03/31/2018 01:20 PM, Rob Nagler wrote:
> On Sat, Mar 31, 2018 at 12:04 PM, Zan Lynx wrote:
> 
>> You can parameterize unit files. Look into how to use the @ symbol
>> combined with symbolic links.
>
> You can parameterize with a single parameter (%i). You can't override any
> values by, for example, defining them in foo at bar.service or
> foo at bar.service.d. This restricts polymorphism to simple macro replacement,
> which is sufficient for things like timers but not more complex services.

If you feel like experimenting some more, openrc might be useful:
    https://en.wikipedia.org/wiki/OpenRC
    https://github.com/openrc/openrc/

It is a service manager that doesn't need to be pid 1 and is easily parameterized.
IIRC it was suggested you could run it in a chroot with the newest versions. With
V0.34 it looks like you could run it inside a systemd-nspawn container. It can most
definitely run in lxc containers and KVM instances as well as bare metal.

The init scripts can be pretty simple. Supporting multiple instances of one kind of 
service is straight forward. A useful thing is that startup/shutdown logic is in a
separate file from the service setup config: /etc/init.d and /etc/conf.d. Init scripts
and config files can specify several kinds of dependencies:
	need, use, want, after, before, provide, config

Hypothetical example supposing that /sbin/rc is started by systemd-nspawn in a chroot 
(note the nginx init script is a stripped down version from gentoo with extra actions
like live upgrade removed). Doesn't seem like it would be complicated to automate this.

# cat /etc/init.d/nginx
    #!/sbin/openrc-run
    pidfile=${NGINX_PIDFILE:-/run/nginx.pid}
    user=${NGINX_USER:-nginx}
    group=${NGINX_GROUP:-nginx}
    retry=${NGINX_TERMTIMEOUT:-"TERM/60/KILL/5"}

    depend() {
        need net.ifpublic net.lo
        use dns logger netmount
    }

The shared webapp startup logic; gets params from /etc/conf.d/webapp{,.*}

# cat /etc/init.d/webapp:
    #!/sbin/openrc-run
    cfgfile=${APP_CONFIGFILE-:/etc/webapp/default.conf}
    listen=${LISTEN_ADDR_PORT-:127.11.22.33}
    command=${APP_BIN-:/usr/local/bin/webapp}
    command_args="--listen ${listen} --config ${cfgfile}"

To define the instances rproxy1, rproxy2, app1, and app2:

# cd /etc/init.d
# ln -s nginx ngnix.rproxy1
# ln -s nginx ngnix.rproxy2
# ln -s webapp webapp.app1
# ln -s webapp webapp.app2

# rc-update add nginx.rproxy1 default
# rc-update add nginx.rproxy2 default
# rc-update add webapp.app1 default
# rc-update add webapp.app2 default

Tell openrc it is running in a systemd-nspawn env:

# cat 'rc_sys="systemd-nspawn"' >> /etc/rc.conf

nginx doesn't support much config from the command args
so the per-service vars don't help much with its configuration.
But for your own applications it may be useful.

The per-instance configs, with the reverse proxies specifying
which webapp instance they depend on:

# cat /etc/conf.d/nginx.rproxy1
    NGINX_CONFIGFILE="/etc/nginx/nginx-rproxy1.conf"
    rc_need="webapp.app1"

# cat /etc/conf.d/nginx.rproxy2
    NGINX_CONFIGFILE="/etc/nginx/nginx-rproxy2.conf"
    rc_need="webapp.app2"

# cat /etc/conf.d/webapp.app1
    APP_CONFIGFILE=....
    LISTEN_ADDR_PORT=...
    rc_need="postgresql ldap"

# cat /etc/conf.d/webapp.app2
    APP_CONFIGFILE=....
    LISTEN_ADDR_PORT=...
    rc_need="hadoop memcached"

# cat /etc/conf.d/nginx (values overriden by per instance conf):
    # Configuration file
    NGINX_CONFIGFILE="/etc/nginx/nginx.conf"
    #NGINX_USER="nginx"
    #NGINX_GROUP="nginx"
    #NGINX_SSDARGS="--wait 1000"
    #NGINX_TERMTIMEOUT="TERM/60/KILL/5"


More information about the LUG mailing list