使kubernetes pod,docker容器使用systemctl- 问题:Failed to get D-Bus connection: Operation not permitted

一、问题原因

我们有时在使用 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。

总的来说,这两个文件都用于系统初始化,但它们之间的主要区别在于其来源和用途

你可能感兴趣的:(kubernetes,docker,kubernetes,docker,容器)