LXC容器有许多HOOK,通过指定这些HOOK对应的脚本,可以在容器的各个阶段做一些处理。

 

但是有些小伙伴不知道如何正确使用这些HOOK。

 

下面是官方对这些HOOK的解释:

  • lxc.hook.pre-start (called before any initialization is done)
  • lxc.hook.pre-mount (called after creating the mount namespace but before mounting anything)
  • lxc.hook.mount (called after the mounts but before pivot_root)
  • lxc.hook.autodev (identical to mount but only called if using autodev)
  • lxc.hook.start (called in the container right before /sbin/init)
  • lxc.hook.post-stop (run after the container has been shutdown)
  • lxc.hook.clone (called when cloning a container into a new one)

但是这些解释还是有些难以理解,比方说pre_start指定的脚本到底在哪个名字空间运行呢?下面我们来验证一下:

首先我们写几个脚本pre_start.sh, pre_mount.sh

pre_mount.sh

#!/bin/sh

set -e

ls -la /proc/self/ns > /var/pre-mount-ns.txt

  

pre_start.sh

#!/bin/sh

ls -la /proc/self/ns > /var/pre-start-ns.txt

  

然后我们将这些脚本链接到lxc configure文件的HOOK上:

lxc.hook.pre-start = /var/lib/lxc/ns1/pre_start.sh
lxc.hook.pre-mount = /var/lib/lxc/ns1/pre_mount.sh

  

然后我们启动这个容器,之后我们再检查下/var/pre-mount-ns.txt和/var/pre-start-ns.txt的内容:

[router] # cat /var/pre-mount-ns.txt
dr-x--x--x    2 root     root             0 Mar 30 21:48 .
dr-xr-xr-x    8 root     root             0 Mar 30 21:48 ..
lrwxrwxrwx    1 root     root             0 Mar 30 21:48 ipc -> ipc:[4026532790]
lrwxrwxrwx    1 root     root             0 Mar 30 21:48 mnt -> mnt:[4026532788]
lrwxrwxrwx    1 root     root             0 Mar 30 21:48 net -> net:[4026532793]
lrwxrwxrwx    1 root     root             0 Mar 30 21:48 pid -> pid:[4026532791]
lrwxrwxrwx    1 root     root             0 Mar 30 21:48 user -> user:[4026531837]
lrwxrwxrwx    1 root     root             0 Mar 30 21:48 uts -> uts:[4026532789]
[router] # cat /var/pre-start-ns.txt
dr-x--x--x    2 root     root             0 Mar 30 21:48 .
dr-xr-xr-x    8 root     root             0 Mar 30 21:48 ..
lrwxrwxrwx    1 root     root             0 Mar 30 21:48 ipc -> ipc:[4026531839]
lrwxrwxrwx    1 root     root             0 Mar 30 21:48 mnt -> mnt:[4026531840]
lrwxrwxrwx    1 root     root             0 Mar 30 21:48 net -> net:[4026531885]
lrwxrwxrwx    1 root     root             0 Mar 30 21:48 pid -> pid:[4026531836]
lrwxrwxrwx    1 root     root             0 Mar 30 21:48 user -> user:[4026531837]
lrwxrwxrwx    1 root     root             0 Mar 30 21:48 uts -> uts:[4026531838]

  

我们可以看到pre-start和pre-mount的脚本是在不同的名字空间执行的。我们检查一下容器中的某个进程的名字空间:

[router] # ls -la /proc/12440/ns/
dr-x--x--x    2 root     root             0 Mar 30 21:52 .
dr-xr-xr-x    8 root     root             0 Mar 30 21:48 ..
lrwxrwxrwx    1 root     root             0 Mar 30 21:52 ipc -> ipc:[4026532790]
lrwxrwxrwx    1 root     root             0 Mar 30 21:52 mnt -> mnt:[4026532788]
lrwxrwxrwx    1 root     root             0 Mar 30 21:52 net -> net:[4026532793]
lrwxrwxrwx    1 root     root             0 Mar 30 21:52 pid -> pid:[4026532791]
lrwxrwxrwx    1 root     root             0 Mar 30 21:52 user -> user:[4026531837]
lrwxrwxrwx    1 root     root             0 Mar 30 21:52 uts -> uts:[4026532789]

  

可以看到容器中进程所在的名字空间跟pre-mount脚本所在的名字空间是一样的。

我们再看看host里面的进程所在的名字空间:

[router] # ls -la /proc/1/ns
dr-x--x--x    2 root     root             0 Mar 30 22:10 .
dr-xr-xr-x    8 root     root             0 Mar 30 03:47 ..
lrwxrwxrwx    1 root     root             0 Mar 30 22:10 ipc -> ipc:[4026531839]
lrwxrwxrwx    1 root     root             0 Mar 30 22:10 mnt -> mnt:[4026531840]
lrwxrwxrwx    1 root     root             0 Mar 30 22:10 net -> net:[4026531885]
lrwxrwxrwx    1 root     root             0 Mar 30 22:10 pid -> pid:[4026531836]
lrwxrwxrwx    1 root     root             0 Mar 30 22:10 user -> user:[4026531837]
lrwxrwxrwx    1 root     root             0 Mar 30 22:10 uts -> uts:[4026531838]
[router] #

  

可以看到host里面的进程所在的名字空间跟pre-start脚本所在的名字空间是一样的。

 

这也就说明了pre-start脚本是在host的名字空间里执行的,而pre-mount脚本则是在容器的名字空间里执行的。

 

理解了上面的区别之后,我们就知道如果是针对host上面的一些操作,需要放在pre-start脚本里执行,如果是针对容器本身的操作,需要放在pre-mount脚本或者start脚本中执行。

 

比方说我们想在容器中创建一些iptables的规则,则必须放在pre-mount或start脚本里。