From e15bc621f1bca24c1ee61405f8511369f9489716 Mon Sep 17 00:00:00 2001 From: Roman Tsisyk <roman@tsisyk.com> Date: Thu, 21 Jan 2016 22:11:19 +0300 Subject: [PATCH] Fix #1264: multi-instance management using systemd This patch also enables daemon supervision when used with systemd. A prerequisite for Fedora/EPEL7 packages. --- .gitignore | 2 +- README.systemd.md | 177 ++++++++++++++++++++++++++ extra/dist/CMakeLists.txt | 34 +++-- extra/dist/default/tarantool.in | 7 +- extra/dist/tarantool.logrotate.in | 2 +- extra/dist/tarantool.service.in | 36 ------ extra/dist/tarantool.tmpfiles.conf.in | 2 +- extra/dist/tarantool@.service.in | 40 ++++++ rpm/tarantool.spec | 14 +- 9 files changed, 247 insertions(+), 67 deletions(-) create mode 100644 README.systemd.md delete mode 100644 extra/dist/tarantool.service.in create mode 100644 extra/dist/tarantool@.service.in diff --git a/.gitignore b/.gitignore index f1e536f63a..86134f36cf 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,7 @@ extra/bin2c extra/dist/tarantoolctl.1 extra/dist/tarantool.logrotate extra/dist/tarantool.service +extra/dist/tarantool@.service extra/dist/tarantool.tmpfiles.conf cmake_install.cmake config.mk @@ -47,7 +48,6 @@ doc/tnt.ent rpm/tarantool-1*.spec extra/rpm.spec extra/rpm/tarantool.rpm.spec -extra/dist/tarantool.service include/tarantool/config.h src/trivia/config.h install_manifest.txt diff --git a/README.systemd.md b/README.systemd.md new file mode 100644 index 0000000000..5884c9978b --- /dev/null +++ b/README.systemd.md @@ -0,0 +1,177 @@ +# Notes for Systemd Users + +Tarantool package fully supports **systemd** for managing instances and +supervising database daemons. + +## Instance Management + +Package was designed to have multiple running instances of Tarantool on +the same machine. Please use +`systemctl {start|stop|restart|status} tarantool@${MYAPP}` to manage your +databases and Lua applications. + +### Creating Instances + +Simple put your Lua configuration to +`/etc/tarantool/instances.available/${MYAPP}.lua`: + + box.cfg { + slab_alloc_arena = 1.0; -- 1Gb + listen = 3313; + } + + require('myappcode').start() + +Tarantool ships with `example.lua` script which can be used as a start point. + +### Starting Instances + +Use `systemctl start tarantool@${MYAPP}` to start `${MYAPP}` instance: + + # systemctl start tarantool@example + # ps axuf|grep exampl[e] + taranto+ 5350 1.3 0.3 1448872 7736 ? Ssl 20:05 0:28 tarantool example.lua <running> + +Use `systemctl enable tarantool@${MYAPP}` to enable `${MYAPP}` instance +for auto-load during system startup. + +### Monitoring Instances + +Use `systemctl status tarantool@${MYAPP}` to check information about +`${MYAPP}` instance: + + # systemctl status tarantool@example + â— tarantool@example.service - Tarantool Database Server + Loaded: loaded (/etc/systemd/system/tarantool@.service; disabled; vendor preset: disabled) + Active: active (running) + Docs: man:tarantool(1) + Process: 5346 ExecStart=/usr/bin/tarantoolctl start %I (code=exited, status=0/SUCCESS) + Main PID: 5350 (tarantool) + Tasks: 11 (limit: 512) + CGroup: /system.slice/system-tarantool.slice/tarantool@example.service + + 5350 tarantool example.lua <running> + +Use `journalctl -u tarantool@${MYAPP}` to check boot log: + + journalctl -u tarantool@example -n 5 + -- Logs begin at Fri 2016-01-08 12:21:53 MSK, end at Thu 2016-01-21 21:17:47 MSK. -- + Jan 21 21:17:47 localhost.localdomain systemd[1]: Stopped Tarantool Database Server. + Jan 21 21:17:47 localhost.localdomain systemd[1]: Starting Tarantool Database Server... + Jan 21 21:17:47 localhost.localdomain tarantoolctl[5969]: /usr/bin/tarantoolctl: Found example.lua in /etc/tarantool/instances.available + Jan 21 21:17:47 localhost.localdomain tarantoolctl[5969]: /usr/bin/tarantoolctl: Starting instance... + Jan 21 21:17:47 localhost.localdomain systemd[1]: Started Tarantool Database Server + + +### Attaching to Instances + +It is possible to attach to a running Tarantool instance and evaluate some +Lua code using `tarantoolctl` utility: + + # tarantoolctl enter example + /bin/tarantoolctl: Found example.lua in /etc/tarantool/instances.available + /bin/tarantoolctl: Connecting to /var/run/tarantool/example.control + /bin/tarantoolctl: connected to unix/:/var/run/tarantool/example.control + unix/:/var/run/tarantool/example.control> 1 + 1 + --- + - 2 + ... + unix/:/var/run/tarantool/example.control> + + +### Checking Logs + +Tarantool log important events to `/var/log/tarantool/${MYAPP}.log`. + +Let's write something to the log file: + + # tarantoolctl enter example + /bin/tarantoolctl: Found example.lua in /etc/tarantool/instances.available + /bin/tarantoolctl: Connecting to /var/run/tarantool/example.control + /bin/tarantoolctl: connected to unix/:/var/run/tarantool/example.control + unix/:/var/run/tarantool/example.control> require('log').info("Hello for README.systemd readers") + --- + ... + +Then check the logs: + + # tail /var/log/tarantool/example.log + 2016-01-21 21:09:45.982 [5914] iproto I> binary: started + 2016-01-21 21:09:45.982 [5914] iproto I> binary: bound to 0.0.0.0:3301 + 2016-01-21 21:09:45.983 [5914] main/101/tarantoolctl I> ready to accept requests + 2016-01-21 21:09:45.983 [5914] main/101/example I> Run console at /var/run/tarantool/example.control + 2016-01-21 21:09:45.984 [5914] main/101/example I> tcp_server: remove dead UNIX socket: /var/run/tarantool/example.control + 2016-01-21 21:09:45.984 [5914] main/104/console/unix/:/var/run/tarant I> started + 2016-01-21 21:09:45.985 [5914] main C> entering the event loop + 2016-01-21 21:14:43.320 [5914] main/105/console/unix/: I> client unix/: connected + 2016-01-21 21:15:07.115 [5914] main/105/console/unix/: I> Hello for README.systemd readers + 2016-01-21 21:15:09.250 [5914] main/105/console/unix/: I> client unix/: disconnected + +Log rotation is enabled by default if you have `logrotate` installed. + +Please tweak `/etc/logrotate.d/tarantool` to change the default behavior. + +### Stopping Instance + +Use `systemctl stop tarantool@${MYAPP}` to see information about running +`${MYAPP}` instance. + + # systemctl stop tarantool@example + +## Daemon Supervision + +All instances are automatically restarted by `systemd` in case of failure. + +Let's try to destroy an instance: + + # systemctl status tarantool@example|grep PID + Main PID: 5885 (tarantool) + # tarantoolctl enter example + /bin/tarantoolctl: Found example.lua in /etc/tarantool/instances.available + /bin/tarantoolctl: Connecting to /var/run/tarantool/example.control + /bin/tarantoolctl: connected to unix/:/var/run/tarantool/example.control + unix/:/var/run/tarantool/example.control> os.exit(-1) + /bin/tarantoolctl: unix/:/var/run/tarantool/example.control: Remote host closed connection + +`systemd` has revived our Tarantool: + + # systemctl status tarantool@example|grep PID + Main PID: 5914 (tarantool) + +Let's check the boot logs: + + # journalctl -u tarantool@example -n 8 + -- Logs begin at Fri 2016-01-08 12:21:53 MSK, end at Thu 2016-01-21 21:09:45 MSK. -- + Jan 21 21:09:45 localhost.localdomain systemd[1]: tarantool@example.service: Unit entered failed state. + Jan 21 21:09:45 localhost.localdomain systemd[1]: tarantool@example.service: Failed with result 'exit-code'. + Jan 21 21:09:45 localhost.localdomain systemd[1]: tarantool@example.service: Service hold-off time over, scheduling restart. + Jan 21 21:09:45 localhost.localdomain systemd[1]: Stopped Tarantool Database Server. + Jan 21 21:09:45 localhost.localdomain systemd[1]: Starting Tarantool Database Server... + Jan 21 21:09:45 localhost.localdomain tarantoolctl[5910]: /usr/bin/tarantoolctl: Found example.lua in /etc/tarantool/instances.available + Jan 21 21:09:45 localhost.localdomain tarantoolctl[5910]: /usr/bin/tarantoolctl: Starting instance... + Jan 21 21:09:45 localhost.localdomain systemd[1]: Started Tarantool Database Server. + +## Customizing Service File + +Please don't modify `tarantool@.service` file in-place, because it will be +overwrriten during package upgrades. It is recommended to copy this file to +`/etc/systemd/system` and then modify the chosen settings. Alternatively, +one can create a directory named `unit.d/` within `/etc/systemd/system` and +place a drop-in file name.conf there that only changes the specific +settings one is interested in. Please see systemd.unit(5) manual page for +additional information. + +## Precautions + +* Please don't use `tarantoolctl {start,stop,restart}` to control instances + started by systemd. It is still possible to use `tarantoolctl` to start and + stop instances from your local directories (e.g. `${HOME}`) without + obtaining `ROOT` access. + +* `tarantoolctl` is configured to work properly with **systemd**. Please don't + modify system-wide settings of `tarantoolctl`, such as paths, directory + permissions and usernames. Otherwise, you have a chance to shoot yourself + in the foot. + +* systemd scripts are maintained by Tarantool Team (http://tarantool.org). + Please file tickets directly to the upstream's bug tracker rather than to + your Linux distribution. diff --git a/extra/dist/CMakeLists.txt b/extra/dist/CMakeLists.txt index 35a13dc3e1..58ceb727da 100644 --- a/extra/dist/CMakeLists.txt +++ b/extra/dist/CMakeLists.txt @@ -15,6 +15,11 @@ set(TARANTOOL_LOGDIR "${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/log/tarantool") message (STATUS "tarantoolctl logdir: ${TARANTOOL_LOGDIR}") set(TARANTOOL_RUNDIR "${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/run/tarantool") message (STATUS "tarantoolctl rundir: ${TARANTOOL_RUNDIR}") +set(TARANTOOL_USER "tarantool") +set(SYSCONFIG_AVAILABLEDIR "tarantool/instances.available") +set(SYSCONFIG_ENABLEDDIR "tarantool/instances.enabled") +set(TARANTOOL_AVAILABLEDIR "${CMAKE_INSTALL_FULL_SYSCONFDIR}/${SYSCONFIG_AVAILABLEDIR}") +set(TARANTOOL_ENABLEDDIR "${CMAKE_INSTALL_FULL_SYSCONFDIR}/${SYSCONFIG_ENABLEDDIR}") # config file for tarantoolctl if (TARGET_OS_FREEBSD) @@ -44,15 +49,17 @@ install (FILES tarantoolctl DESTINATION ${CMAKE_INSTALL_BINDIR} # directories in /etc/ for tarantoolctl install(DIRECTORY DESTINATION - ${CMAKE_INSTALL_SYSCONFDIR}/tarantool/instances.enabled -) -install(DIRECTORY DESTINATION - ${CMAKE_INSTALL_SYSCONFDIR}/tarantool/instances.available + ${CMAKE_INSTALL_SYSCONFDIR}/${SYSCONFIG_AVAILABLEDIR} ) +if (WITH_SYSVINIT) + install(DIRECTORY DESTINATION + ${CMAKE_INSTALL_SYSCONFDIR}/${SYSCONFIG_ENABLEDDIR} + ) +endif() # an example instance script for tarantoolctl install (FILES example.lua DESTINATION - ${CMAKE_INSTALL_SYSCONFDIR}/tarantool/instances.available + ${CMAKE_INSTALL_SYSCONFDIR}/${SYSCONFIG_AVAILABLEDIR} PERMISSIONS OWNER_READ OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ @@ -93,18 +100,13 @@ if (WITH_SYSTEMD) # architecture, but tarantool-common is noarch package. set(SYSV_INITD_DIR ${CMAKE_INSTALL_PREFIX}/lib/tarantool) - configure_file("tarantool.service.in" "tarantool.service" @ONLY) - install (FILES ${PROJECT_BINARY_DIR}/extra/dist/tarantool.service + configure_file("tarantool@.service.in" "tarantool@.service" @ONLY) + install (FILES ${PROJECT_BINARY_DIR}/extra/dist/tarantool@.service DESTINATION ${SYSTEMD_UNIT_DIR} PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ GROUP_READ WORLD_READ WORLD_READ) - install (FILES tarantool.init DESTINATION ${SYSV_INITD_DIR} - PERMISSIONS - OWNER_READ OWNER_WRITE - GROUP_READ GROUP_EXECUTE - WORLD_READ WORLD_EXECUTE) configure_file(tarantool.tmpfiles.conf.in tarantool.tmpfiles.conf @ONLY) install (FILES "${PROJECT_BINARY_DIR}/extra/dist/tarantool.tmpfiles.conf" DESTINATION "${SYSTEMD_TMPFILES_DIR}" @@ -115,7 +117,7 @@ if (WITH_SYSTEMD) WORLD_READ WORLD_READ) endif() -if(WITH_SYSVINIT) +if (WITH_SYSVINIT) message (STATUS "Using scripts for sysvinit") install (FILES tarantool.init DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/init.d/ RENAME tarantool @@ -123,10 +125,4 @@ if(WITH_SYSVINIT) OWNER_READ OWNER_WRITE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) - install (FILES ${PROJECT_BINARY_DIR}/extra/dist/default/tarantool DESTINATION - ${CMAKE_INSTALL_SYSCONFDIR}/${SYSCONFIG_DEFAULT}/ - PERMISSIONS - OWNER_READ OWNER_WRITE - GROUP_READ - WORLD_READ) endif() diff --git a/extra/dist/default/tarantool.in b/extra/dist/default/tarantool.in index b7f4212635..43370c7aac 100644 --- a/extra/dist/default/tarantool.in +++ b/extra/dist/default/tarantool.in @@ -19,9 +19,10 @@ default_cfg = { snap_dir = "@TARANTOOL_DATADIR@", -- @TARANTOOL_DATADIR@/${INSTANCE} sophia_dir = "@TARANTOOL_DATADIR@", -- @TARANTOOL_DATADIR@/${INSTANCE} logger = "@TARANTOOL_LOGDIR@", -- @TARANTOOL_LOGDIR@/${INSTANCE}.log - username = "tarantool", + username = "@TARANTOOL_USER@", } -instance_dir = "@CMAKE_INSTALL_FULL_SYSCONFDIR@/tarantool/instances.enabled" - +-- instances.available - all available instances +-- instances.enabled - instances to autostart by sysvinit +instance_dir = "@TARANTOOL_AVAILABLEDIR@" -- vim: set ft=lua : diff --git a/extra/dist/tarantool.logrotate.in b/extra/dist/tarantool.logrotate.in index f58e33f027..aee7bb4a5d 100644 --- a/extra/dist/tarantool.logrotate.in +++ b/extra/dist/tarantool.logrotate.in @@ -5,7 +5,7 @@ rotate 10 compress delaycompress - create 0640 tarantool adm + create 0640 @TARANTOOL_USER@ adm postrotate @CMAKE_INSTALL_FULL_BINDIR@/tarantoolctl logrotate `basename ${1%%.*}` endscript diff --git a/extra/dist/tarantool.service.in b/extra/dist/tarantool.service.in deleted file mode 100644 index e4d0a04407..0000000000 --- a/extra/dist/tarantool.service.in +++ /dev/null @@ -1,36 +0,0 @@ -# It's not recommended to modify this file in-place, because it will be -# overwritten during package upgrades. If you want to customize there're -# number of ways: - -# Recommended way: -# 1) Use "/etc/sysconfig/tarantool" or "/etc/default/tarantool" - -# They're supported by our start-stop utility - tarantoolctl - -# Usual way for RPM-based distros -# 2) Create a file "/etc/systemd/system/tarantool.service", -# containing -# .include /usr/lib/systemd/system/tarantool.service -# # Here're your changes -# -# For example, if you want to change CONF_DIR create -# "/etc/systemd/system/tarantool.service" containing: -# .include /usr/lib/systemd/system/tarantool.service -# [Service] -# Environment=CONF_DIR=/etc/tarantool/instances.other -# This will override the settings appearing below - -[Unit] -Description=Tarantool instances -After=network.target -Documentation=man:tarantool(1) - -[Service] -Type=forking -User=tarantool -Group=tarantool -OOMScoreAdjust=-1000 - -ExecStart=@SYSV_INITD_DIR@/tarantool.init start -ExecStop=@SYSV_INITD_DIR@/tarantool.init stop - -TimeoutSec=300 diff --git a/extra/dist/tarantool.tmpfiles.conf.in b/extra/dist/tarantool.tmpfiles.conf.in index 0c03ce3e53..f9578cb5d2 100644 --- a/extra/dist/tarantool.tmpfiles.conf.in +++ b/extra/dist/tarantool.tmpfiles.conf.in @@ -1 +1 @@ -d @TARANTOOL_RUNDIR@ 0755 tarantool tarantool - +d @TARANTOOL_RUNDIR@ 0755 @TARANTOOL_USER@ @TARANTOOL_USER@ - diff --git a/extra/dist/tarantool@.service.in b/extra/dist/tarantool@.service.in new file mode 100644 index 0000000000..39ee79e33c --- /dev/null +++ b/extra/dist/tarantool@.service.in @@ -0,0 +1,40 @@ +# Please don't modify this file in-place, because it will be overwrriten +# during package upgrades. It is recommended to copy this file to +# /etc/systemd/system and then modify the chosen settings. Alternatively, +# one can create a directory named unit.d/ within /etc/systemd/system and +# place a drop-in file name.conf there that only changes the specific +# settings one is interested in. +# +# Please see README.systemd.md for additional information. +# +# +[Unit] +Description=Tarantool Database Server +After=network.target +Documentation=man:tarantool(1) + +# Created by package +AssertPathIsReadWrite=@TARANTOOL_DATADIR@ +AssertPathIsReadWrite=@TARANTOOL_LOGDIR@ +# Created by systemd-tmpfiles +AssertPathIsReadWrite=@TARANTOOL_RUNDIR@ + +[Service] +Type=forking +User=@TARANTOOL_USER@ +Group=@TARANTOOL_USER@ +# Disable OOM killer +OOMScoreAdjust=-1000 + +ExecStart=@CMAKE_INSTALL_BINDIR@/tarantoolctl start %I +ExecStop=@CMAKE_INSTALL_BINDIR@/tarantoolctl stop %I +## NYI: https://github.com/tarantool/tarantool/issues/1229 +#ExecReload=@CMAKE_INSTALL_BINDIR@/tarantoolctl reload %I + +# Give a reasonable amount of time to close xlogs +TimeoutStopSec=10s +Restart=on-failure +RestartSec=100ms + +[Install] +WantedBy=multi-user.target diff --git a/rpm/tarantool.spec b/rpm/tarantool.spec index 6786f4599b..984f9adbd9 100644 --- a/rpm/tarantool.spec +++ b/rpm/tarantool.spec @@ -129,7 +129,7 @@ rm -rf %{buildroot}%{_datarootdir}/doc/tarantool/ %post common %if %{with systemd} %tmpfiles_create tarantool.conf -%systemd_post tarantool.service +%systemd_post tarantool@.service %else chkconfig --add tarantool || : service tarantool start || : @@ -137,7 +137,7 @@ service tarantool start || : %preun common %if %{with systemd} -%systemd_preun tarantool.service +%systemd_preun tarantool@.service %else service tarantool stop chkconfig --del tarantool @@ -145,7 +145,7 @@ chkconfig --del tarantool %postun common %if %{with systemd} -%systemd_postun_with_restart tarantool.service +%systemd_postun_with_restart tarantool@.service %endif %files @@ -170,7 +170,6 @@ chkconfig --del tarantool %{_mandir}/man1/tarantoolctl.1* %config(noreplace) %{_sysconfdir}/sysconfig/tarantool %dir %{_sysconfdir}/tarantool -%dir %{_sysconfdir}/tarantool/instances.enabled %dir %{_sysconfdir}/tarantool/instances.available %config(noreplace) %{_sysconfdir}/tarantool/instances.available/example.lua # Use 0750 for database files @@ -179,15 +178,18 @@ chkconfig --del tarantool %config(noreplace) %{_sysconfdir}/logrotate.d/tarantool %if %{with systemd} -%{_unitdir}/tarantool.service -%{_prefix}/lib/tarantool/tarantool.init +%doc README.systemd.md +%{_unitdir}/tarantool@.service %{_tmpfilesdir}/tarantool.conf %else %{_sysconfdir}/init.d/tarantool +%dir %{_sysconfdir}/tarantool/instances.enabled %attr(-,tarantool,tarantool) %dir %{_localstatedir}/run/tarantool/ %endif %changelog +* Thu Jan 21 2016 Roman Tsisyk <roman@tarantool.org> 1.6.8.376-1 +- Implement proper support of multi-instance management using systemd * Sat Jan 9 2016 Roman Tsisyk <roman@tarantool.org> 1.6.8.0-1 - Change naming scheme to include a postrelease number to Version - Fix arch-specific paths in tarantool-common -- GitLab