[lxc-devel] read-only container root
Daniel Lezcano
daniel.lezcano at free.fr
Tue Feb 16 20:48:59 UTC 2010
Michael Tokarev wrote:
> Daniel Lezcano wrote:
>> Michael Tokarev wrote:
>>> lxc-start: No such file or directory - failed to mount a new
>>> instance of '/dev/pts'
>>> I'm experimenting with a read-only root fs in the container.
>>> So far it does not work.
>>>
>>> First of all, when trying to start a container in a read-only root
>>> lxc-start complains:
>>> lxc-start: Read-only file system - can't make temporary mountpoint
>>>
>>> This is in conf.c:setup_rootfs_pivot_root() function. That function
>>> uses optional parameter "lxc.pivotdir", or creates (and later removes)
>>> a temporary directory for pivot_root. Obviously there's no way to
>>> create a directory in a read-only filesystem.
>>>
>> Why do you need to use a read-only root fs ?
>
> There's no _need_, but it's an extension on a principle of least
> privilege, and also helps keeping things in a more accurate way
> and also guarantees that no bad things will happen with the system
> in case of any unexpected power failure and things like that (in
> that case, say, /var might be badly damaged still, but the system
> will actually boot to the point where some repairment tools are
> available).
Agree, that makes sense.
>>> But lxc.pivotdir does not work either. In the function mentioned above
>>> it is used with leading dot (eg. if I specify "lxc.pivotdir=pivot" in
>>> the config file the pivot_root() syscall will be made to ".pivot" with
>>> leading dot, not to "pivot"), but later on it is used without that dot,
>>> and fails...
> []
>> It's a bug introduced with the pivot_root feature. Investigation on
>> the way.
>
> I tried to debug it too, but realized that the last git repo I have
> locally is from 22th Jan, which is almost a month from now, and I've
> seen quite some changes mentioned on the list. So it is either that
> the changes hasn't been comitted, or the git repository has been
> moved somewhere else. It actually was my 3rd email I planned to
> write, asking what's up with the git repo... ;)
No, the repo is still there but at the moment I am very busy, so I
didn't pushed the patches to the git tree.
There is a pending patches to fix a readlink I didn't took because the
patchset I am about to commit removes this code.
The pending patchset is the fix of the console as I mentioned some weeks
ago when I said the console sucks and the shutdown / reboot support.
I sent the patchset, but as nobody commented it, I supposed no hurry for it.
> []
>> Ok, so your need is to call a script between:
>>
>> lxc.mount.entry = /dev dev tmpfs noexec,nosuid,mode=0755
>>
>> ...
>> lxc.tty = 4
>>
>> where the script will populate /dev, right ?
>>
>> mmh, not obvious.
>
> Or maybe just call it _instead_ of specifying all the
> above (lxc.mount.entry and lxc.tty), leaving only things
> such as network device setup (which can't easily be done
> from shell) to lxc-start.
The console ttys are created outside of the container and the /dev/pts/X
is bind mounted on $rootfs/dev/ttyY
- if this option is not set you won't have the tty
- if this option is set but /dev is not yet populated (no /dev/ttyY)
the tty creation will fail.
This is for this reason I proposed this feature which is though to
implement, but maybe it's overkill.
Otherwise, nothing prevent to create a configuration file with only the
network and call a script doing all the configuration, for example:
#!/bin/sh
ip addr add ...
route add ...
mount ....
chroot $rootfs
exec /sbin/init
And then call lxc-start -n mycontainer mylauncher.sh
no ?
> []
>> What about the lxc.script configuration line which calls a script at
>> the point it is in the configuration file ?
>
> That's not possible. The configuration is an _unordered_ set
> of key=value pairs. lxc-start calls different functions now
> at pre-defined (programmatically) order, regardless of the
> order in which the config file is written.
>
> The specified script (lxc.script) should also be called at some
> (random) pre-determined point in the container setup procedure.
> In that case the script can _replace_ some things from the
> config file if they're at "wrong" order or are staying in
> the way. But it's still not obvious where's that "random"
> place is: for example, is it before lxc-start (implicitly!)
> mounts /dev/pts or after? For my example the script should
> run before /dev/pts is mounted, but maybe someone will want
> to run some other program that uses pseudo-terminals, which
> obviously should be done after /dev/pts is mounted (granted
> I can't think of such a situation/program for now).
Yes, absolutely. The configuration will need some rework. This is why I
said "not obvious" :)
Maybe I misunderstood, but do have an alternative solution ?
>>> The whole mess started when I realized that bind-mounting host's /dev
>>> works perfectly _except_ the syslogging, -- /dev/log does not work with
>>> multiple containers, only the container where syslogd (re)started last
>>> works, all the rest gives "ECONNREFUSED" when trying to send any
>>> message
>>> to /dev/log.
>>>
>> /dev/log is an af_unix socket, the network is isolated, the af_unix
>> belongs to the network namespace.
>> It's probable /dev/log is unlinked, created again and binded by
>> syslogd. So as /dev/ is shared between the containers, the last one
>> get the socket.
>> Any process outside of the container trying to access this socket
>> won't be able.
>
> That's what I figured, and it's quite obvious thing to do really.
>
> Actually it might be a good idea to not start syslogd in containers
> and inherit real /dev from host, -- this way all logging will be
> automatically sent to central syslog (hopefully :). But that works
> up until the host syslogd will be restarted, and at this point we're
> back at ECONNREFUSED.
That won't work too because the check is done when connecting too, so
all the programs belonging to a container with a private network will
fail to log anything. That should be easy to check with "logger".
> Note another my email about mounting new filesystems within containers.
> In this context, like, after restarting syslogd on the host, is it
> possible
> to bind-mount host's /dev/log to container's /dev/log (provided they were
> bind-mointed before)?
Yes, IMO it is possible.
I did something similar by proxying the syslog with a process which
inherited a fd connected to /dev/log in a container. This process then
creates a new af_unix socket in a temporary location and bind mount it
to /dev/log. And after, it accepts data from this newly created socket
and forward them to the inherited fd.
More information about the lxc-devel
mailing list