[lxc-devel] Shutting down containers properly

Stéphane Graber stgraber at ubuntu.com
Fri May 25 15:00:38 UTC 2012


On 05/25/2012 07:56 AM, Christian Seiler wrote:
> Hi,
> 
> Currently, lxc-stop sends SIGKILL to the init process of the container,
> which causes all the other processes in the container to also receive
> a SIGKILL. I don't think that is a good course of action, since sending
> SIGKILL to for example a database server can lead to potential data
> loss.
> 
> A much better way of stopping containers would be in my opinion to
> first send the container a shutdown signal - and then wait for a
> specified amount of time before really killing the container with a
> KILL signal.
> 
> Unfortunately, no init system will react to SIGTERM and shut down the
> container, so it is not quite as easy. I've looked a bit at different
> init systems to see how to properly shut them down:
> 
>   - lxc application containers (lxc-execute): lxc-init will do a
>     kill(-1, SIGTERM) if it receives a SIGTERM itself, so sending
>     it a SIGTERM is sufficient to initiate a proper shutdown
> 
>   - sysvinit: open /run/initctl (newer Debian) or /dev/initctl (older
>     Debian and other distros) and send them a binary message to switch
>     to runlevel 0
> 
>   - upstart: connect to DBus and tell it to switch to runlevel 0
> 
>   - systemd: either connect to DBus and tell it to switch runlevel or
>     send SIGRTMIN + 4, that will also cause a shutdown
> 
>   - sysvinit + upstart + systemd also all provide a 'telinit' binary,
>     where calling 'telinit 0' will initiate a shutdown
> 
> My proposal would be the following:
> 
> lxc-stop first sends a new SHUTDOWN command (instead of the current
> STOP command), which initiates the shutdown and returns immediately.
> The command handler in lxc-start will then initiate a shutdown of the
> container (see below). lxc-stop will wait for a given amount of seconds
> and if the container is not stopped by then, it will send the current
> STOP command to actually kill the container with SIGKILL.
> 
> On the other hand, add a --force option that will make lxc-stop still
> be able to kill all processes immediately.
> 
> Now how to shut down the container? In lxc.conf there should be a new
> configuration option, lxc.shutdown_method, which can carry the
> following values: "application", "sysvinit", "systemd" and "exec".
> For application containers started with lxc-execute, it will default
> to "application", for system containers started with lxc-start, it will
> default to "sysvinit".
> 
> The following actions will be performed:
> 
> "application": send SIGTERM to init process of the container
> 
> "sysvinit": fork(), child process does setns() for mount namespace,
>              tries to send signal to /run/initctl and /dev/initctl
>              (whichever exists), but first checks whether st_dev and
>              st_ino entries do NOT match those of the host's files,
>              so we don't accidentally shut down the host (if the
>              container hares filesystem with the host)
> 
> "systemd": send SIGRTMIN + 4 to init process of the container
> 
> "exec": run lxc-attach for the container with the contents of the
>          new option lxc.shutdown_command as parameter
> 
> I haven't included any explicit method for shutting down upstart, so
> containers running upstart inside (assuming that's even possible, I
> don't know much about upstart) should probably use method exec and
> execute telinit 0 inside the container. Sending simple signals to the
> init process as in application / systemd or opening a FIFO and writing
> some bytes for sysvinit is still quite trivial, but implementing DBus
> (esp. across container boundaries) - which would be required for native
> upstart shutdown support - seems like overkill to me.
> 
> On the other hand, I do want to explicitly implement the sysvinit way,
> since there we can check that we're definitely not going to shut down
> the host accidentally (by checking the device/inode numbers of the
> initctl FIFOs), which we can't be 100% sure of with exec.
> 
> Caveats:
> 
> 1. application / systemd methods should always work, since we just send
> a signal to the init process; sysvinit will only work if attaching
> mount namespaces is implemented in the kernel and exec only if full
> lxc-attach works (so all namespaces). But the worst case scenario here
> is that we still kill all processes in the container with lxc-stop if
> the kernel doesn't support attach, so there is no loss for current
> users.
> 
> 2. If the container is frozen, the current logic first sends the KILL
> signal and then unfreezes it, so the container immediately goes away.
> However, how should we react if we just want to shut it down? Unfreeze
> it and send the shutdown signal? Or just kill it immediately? Or do
> nothing and report an error?
> 
> Thoughts?
> 
> (Note: I'd be willing to implement this feature, once a consensus is
> reached on how to proceeed.)
> 
> Regards,
> Christian

I only very quickly read through your e-mail, apologize if what I'm
saying below is already covered in your e-mail.

Have you looked at the lxc-shutdown script we have in Ubuntu and the
integration we have with upstart?

lxc-shutdown sends two different signals:
 reboot => SIGINT
 shutdown => SIGPWR

These are caught by upstart and will trigger a clean reboot or shutdown
of the container. It's what happens on shutdown of the host in 12.04 LTS.

lxc-shutdown also allows for a timeout to be set that when hit will
forcibly kill the container.

Apparently lxc-shutdown didn't make it to the upstream git branch yet
but I poked Serge about it on IRC so it should be pushed soon.

-- 
Stéphane Graber
Ubuntu developer
http://www.ubuntu.com

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 900 bytes
Desc: OpenPGP digital signature
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20120525/1dd43d0e/attachment.pgp>


More information about the lxc-devel mailing list