使kubernetes pod,docker容器使用systemctl- 问题:Failed to get D-Bus connection: Operation not permitted
Docker 是为进程隔离而设计的,而不是为操作系统虚拟化而设计的,因此容器内没有运行其他操作系统进程和守护进程(如 systemd、cron、syslog 等),只有您运行的入口点或命令。使用这个链接可以提供一种方便的方式来访问该程序,因为有时系统管理员可能更喜欢使用/usr/sbin/init而不是直接使用/sbin/init。systemd是用init脚本初始化的,所以需要指定入口点是ini
一、问题原因
我们有时在使用 k8s或docker 的时候,会发现在容器中使用 systemctl 或者 service 的时候,会遇到下面的错误:
Failed to get D-Bus connection: Operation not permitted;
容器里面是没有 systemd 进程的,所以不能正常开启 systemctl 。为什么 会这样呢:
Docker 是为进程隔离而设计的,而不是为操作系统虚拟化而设计的,因此容器内没有运行其他操作系统进程和守护进程(如 systemd、cron、syslog 等),只有您运行的入口点或命令。如果它们包含 systemd 命令,您会发现很多东西都不起作用,因为您的入口点替换了 init。 Systemd 还利用 docker 限制在容器内部的 cgroup,因为更改 cgroup 的能力可能允许进程逃脱容器的隔离。如果没有 systemd 在容器内作为 init 运行,就没有守护进程来处理启动和停止命令。
docker只是提供了进程隔离,不是操作系统的虚拟。
二、解决方案
docker 容器:
首先,使用docker构建容器(以centos为例)加上 privileged 参数,即在docker run命令是要加上 --privileged=true,该参数在docker容器运行时,让系统拥有真正的root权限。
systemd是用init脚本初始化的,所以需要指定入口点是init,在centos7里,它的位置在/usr/sbin/init,启动容器时,在docker run 命令最后,
加上 /sbin/init,最终命令为:
docker run -d -v /tmp/:/tmp --privileged --cap-add SYS_ADMIN -e container=docker -it --name=centos centos /sbin/init
docker exec -it centos bash
命令解释:
--privileged: 指定容器是否是特权容器。
/sbin/init:初始容器里的CENTOS,用于启动dbus-daemon。在容器中运行 /sbin/init 程序。/sbin/init 是系统启动时运行的第一个进程,它负责启动系统的其他进程
-v /tmp/:/tmp:挂载宿主机的一个目录,冒号":"前面的目录是宿主机目录,后面的目录是容器内目录。
--cap-add SYS_ADMIN: 添加系统的权限,不然系统很多功能都用不了的。
-e container=docker:设置容器的类型。
-it: 启动互动模式。
主要添加–privileged 和/sbin/init ,一般只需要这两个就够了
kubernetes pod:
示例yaml:
cat << EOF > centos.yaml
apiVersion: v1
kind: Pod
metadata:
name: centos
labels:
app: centos
spec:
containers:
- image: centos
name: centos
command: ["/sbin/init", "-c", "--"] #初始容器里的CENTOS
securityContext:
privileged: true #特权
EOF
kubectl apply -f centos.yaml
kubectl exec -it centos -- /bin/bash
添加以上特权和初始化参数就可以让容器正常使用systemctl和一些管理命令啦
三、网络参考
一些网络方案会使用/usr/sbin/init加privileged: true ,其实/sbin/init和/usr/sbin/init 都可以配合privileged: true 让容器使用 systemctl:
首先,/sbin/init是Linux系统中传统的系统初始化程序,也被称为SysV init或systemd之前的系统初始化程序。它是所有用户进程的父进程,并在系统启动时负责执行。
而/usr/sbin/init是CentOS等一些Linux发行版中使用的初始化程序。它是/sbin/init的一个符号链接,指向/usr/sbin/init程序。使用这个链接可以提供一种方便的方式来访问该程序,因为有时系统管理员可能更喜欢使用/usr/sbin/init而不是直接使用/sbin/init。
总的来说,这两个文件都用于系统初始化,但它们之间的主要区别在于其来源和用途
扩展: 一些官方容器都是普通用户启动,自己在做实验时可能会使用root用户,这是可以在yaml中添加以下字段
securityContext:
runAsUser: 0
containers:
- image: centos
name: centos
securityContext:
runAsUser: 0
将runAsUser字段设置为0,因为0是Linux系统中root用户的UID。
更多推荐
所有评论(0)