容器Namespace - 2

本文探讨Docker容器如何通过命名空间实现资源隔离,并分析容器内超级用户权限的限制及背后涉及的Linux能力集机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      容器通过namespace建立属于自己的一个相对隔离的环境,从上一篇《容器Namespace - 1》我们知道centos7默认没有启用user namespace。

      

      上图显示容器的user namespace与宿主机是同一个ID:4026531837,接下来简单分析下docker创建namespace的代码。

 

vendor/github.com/containerd/containerd/oci/spec_unix.go,这个文件定义了缺省的namespace以及capability。

func defaultCaps() []string {

        return []string{

                "CAP_CHOWN",

                "CAP_DAC_OVERRIDE",

                "CAP_FSETID",

                "CAP_FOWNER",

                "CAP_MKNOD",

                "CAP_NET_RAW",

                "CAP_SETGID",

                "CAP_SETUID",

                "CAP_SETFCAP",

                "CAP_SETPCAP",

                "CAP_NET_BIND_SERVICE",

                "CAP_SYS_CHROOT",

                "CAP_KILL",

                "CAP_AUDIT_WRITE",

        }

}



func defaultNamespaces() []specs.LinuxNamespace {

        return []specs.LinuxNamespace{

                {

                        Type: specs.PIDNamespace,

                },

                {

                        Type: specs.IPCNamespace,

                },

                {

                        Type: specs.UTSNamespace,

                },

                {

                        Type: specs.MountNamespace,

                },

                {

                        Type: specs.NetworkNamespace,

                },

        }

}

创建启动容器过程中,会在下面的目录下生成run-time的config.json

/run/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/容器id/config.json

解析下这个文件(jq is a tool for processing JSON inputs):

cat config.json | jq . > /opt/config.json

/opt/config.json文件相关的namespace配置

  "namespaces": [

      {

        "type": "mount"

      },

      {

        "type": "network"

      },

      {

        "type": "uts"

      },

      {

        "type": "pid"

      },

      {

        "type": "ipc"

      }

    ],

 

创建容器namespace的逻辑在:

vendor/github.com/opencontainers/runc/libcontainer/nsenter/nsexec.c

 if (config.namespaces)

       join_namespaces(config.namespaces);



void join_namespaces(char *nslist)

{

        struct namespace_t {

                int fd;

                int ns;

                char type[PATH_MAX];

                char path[PATH_MAX];

        } *namespaces = NULL;



      //准备namespace

                fd = open(path, O_RDONLY);

                if (fd < 0)

                        bail("failed to open %s", path);



                ns->fd = fd;

                ns->ns = nsflag(namespace);

                strncpy(ns->path, path, PATH_MAX - 1);





        for (i = 0; i < num; i++) {

                struct namespace_t ns = namespaces[i];


                // 通过setns设置
                if (setns(ns.fd, ns.ns) < 0)

                        bail("failed to setns to %s", ns.path);



                close(ns.fd);

        }



        free(namespaces);



}

详细的代码分析逻辑需要仔细再看看,这里只是个大概过程。

 

既然docker容器user namespace的管理员root是“map root to root”,它应该就具备super priviledge权限,我们来看看。

[root@centos opt]# unshare -m --mount-proc -u -i -n -p -U -r -f  /bin/bash

[root@centos opt]# ip link show

1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT

    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

[root@centos opt]# ip link set dev lo down

[root@centos opt]# ip link set dev lo up

 

[root@centos opt]#docker run -ti centos /bin/bash

[root@f45f03e236ec /]#ip link set lo down

RTNETLINK answers: Operation not permitted

为什么docker容器在设置loop接口状态时提示:“RTNETLINK answers: Operation not permitted”?

[root@f45f03e236ec /]# mount -t tmpfs -o size=20m tmpfs /tmp1

mount: permission denied       // mount 也不允许

这个super user的权限是怎么限制的呢?

 

这个就需要讲讲linux系统的capability了。

<think>我们正在解决的是`kubectl exec -it <pod-name> -n <namespace> -- bash`报错"container not found"的问题。这个错误通常表示在指定的Pod中没有找到名为"bash"的容器,或者Pod中有多个容器但没有指定容器名。以下是详细的解决步骤: ### 步骤1: 确认Pod中容器的名称 - 使用`kubectl describe pod`命令查看Pod的详细信息,特别是容器名称: ```bash kubectl describe pod <pod-name> -n <namespace> ``` 在输出中查找`Containers:`部分,会列出Pod中所有容器的名称。例如: ``` Containers: nginx-container: Container ID: docker://abcdefg... Image: nginx:latest ... sidecar-container: Container ID: docker://hijklmn... Image: busybox:latest ... ``` 这里有两个容器:`nginx-container`和`sidecar-container`。 ### 步骤2: 检查容器中是否有bash - 并不是所有容器都包含`bash`。例如,基于Alpine Linux的镜像通常使用`sh`作为shell。 - 如果容器中没有`bash`,尝试使用`sh`: ```bash kubectl exec -it <pod-name> -n <namespace> -- sh ``` - 或者使用`/bin/bash`的完整路径(如果存在): ```bash kubectl exec -it <pod-name> -n <namespace> -- /bin/bash ``` ### 步骤3: 指定容器名称(多容器Pod) - 如果Pod中有多个容器,必须使用`-c`或`--container`参数指定容器名称: ```bash kubectl exec -it <pod-name> -n <namespace> -c <container-name> -- bash ``` 例如,对于上面描述的Pod,要进入`nginx-container`,应运行: ```bash kubectl exec -it <pod-name> -n <namespace> -c nginx-container -- bash ``` ### 步骤4: 确认Pod状态 - 确保Pod处于`Running`状态: ```bash kubectl get pod <pod-name> -n <namespace> ``` - 如果Pod状态不是`Running`(如`ContainerCreating`、`CrashLoopBackOff`等),则无法执行命令。需要先解决Pod的问题。 ### 步骤5: 检查容器是否正常运行 - 即使Pod状态是`Running`,容器也可能启动失败。查看Pod日志: ```bash kubectl logs <pod-name> -n <namespace> -c <container-name> # 单容器Pod可省略-c ``` 如果容器启动失败(如应用崩溃),则无法进入。需要根据日志修复容器启动问题。 ### 步骤6: 使用临时调试容器(Kubernetes v1.18+) - 如果目标容器无法提供shell,可以使用临时容器进行调试[^3]: ```bash kubectl debug -it <pod-name> -n <namespace> --image=busybox --target=<container-name> -- sh ``` 注意:此功能需要启用临时容器特性。 ### 步骤7: 验证容器镜像 - 检查容器镜像是否包含`bash`: - 如果镜像不包含`bash`(如使用`scratch`基础镜像),则无法使用bash。考虑使用其他工具(如`sh`)或重新构建镜像包含`bash`。 ### 示例流程 假设有一个名为`web-app`的Pod,命名空间为`prod`,执行命令报错: ```bash kubectl exec -it web-app -n prod -- bash Error: container not found ``` 1. 描述Pod: ```bash kubectl describe pod web-app -n prod ``` 输出显示两个容器:`app-container`和`log-collector`。 2. 由于是双容器Pod,必须指定容器名: ```bash kubectl exec -it web-app -n prod -c app-container -- bash ``` 3. 如果仍然报错,尝试使用`sh`(因为容器可能基于Alpine): ```bash kubectl exec -it web-app -n prod -c app-container -- sh ``` ### 总结 "container not found"错误主要由两个原因引起: 1. **未指定容器名称**:当Pod中有多个容器时,必须使用`-c`参数指定容器名。 2. **容器中不存在bash**:使用`sh`替代,或检查容器镜像是否包含bash。 通过以上步骤,可解决99%的此类问题。如仍无法解决,需检查Pod配置和容器运行状态。 §§相关问题§§ 1. 如何查看Kubernetes Pod的日志? 2. Kubernetes中如何调试崩溃的Pod? 3. 如何在Kubernetes Pod中运行多个容器?</think>### 解决 `kubectl exec -it` 报错 "container not found" 的完整指南 当您执行 `kubectl exec -it <pod-name> -n <namespace> -- bash` 遇到 "container not found" 错误时,通常有四个核心原因。以下是逐步排查和解决方法: --- #### 🚨 步骤1:确认容器名称是否存在(最常见原因) 1. **查看Pod中的容器列表**: ```bash kubectl describe pod <pod-name> -n <namespace> | grep -A 5 "Containers:" ``` 在输出中查找确切的容器名称(如 `nginx-container` 而非默认的 `nginx`) 2. **多容器场景必须指定容器名**: ```bash # 正确格式(使用 -c 指定容器名) kubectl exec -it <pod-name> -n <namespace> -c <container-name> -- bash ``` *示例*: ```bash kubectl exec -it web-server -n prod -c nginx-container -- sh ``` --- #### 🐚 步骤2:检查容器是否支持 Bash 1. **轻量级镜像可能无 Bash**: ```bash kubectl describe pod <pod-name> -n <namespace> | grep Image: ``` - 若镜像为 `alpine`、`busybox` 等,改用 `sh`: ```bash kubectl exec -it <pod-name> -n <namespace> -- sh ``` 2. **尝试通用 shell 路径**: ```bash kubectl exec -it <pod-name> -n <namespace> -- /bin/sh ``` --- #### 🔍 步骤3:验证容器运行状态 1. **检查Pod状态**: ```bash kubectl get pod <pod-name> -n <namespace> -o wide ``` - ❌ 异常状态:`CrashLoopBackOff`、`ImagePullBackOff`、`ContainerCreating` - ✅ 正常状态:`Running` 2. **查看容器事件**: ```bash kubectl describe pod <pod-name> -n <namespace> | grep -A 10 "Events:" ``` 重点关注 `Warning` 事件(如镜像拉取失败、资源不足) --- #### ⚙️ 步骤4:排查容器配置问题 1. **检查容器是否被正确声明**: ```bash kubectl get pod <pod-name> -n <namespace> -o yaml | grep -A 10 "containers:" ``` 确认: - `name` 字段与执行的容器名一致 - `command` 未覆盖默认入口点(如覆盖了 `/bin/bash`) 2. **临时调试容器(Kubernetes v1.18+)**: ```bash kubectl debug -it <pod-name> -n <namespace> --image=busybox --target=<container-name> -- sh ``` --- ### 🔧 完整排查流程示例 ```bash # 1. 检查Pod状态 kubectl get pod web-app -n prod # 2. 查看容器详情 kubectl describe pod web-app -n prod # 输出示例: # Containers: # app-container: # Image: nginx:alpine # log-collector: # Image: fluentd:latest # 3. 正确执行(指定容器名 + 使用 sh) kubectl exec -it web-app -n prod -c app-container -- sh ``` --- ### 💡 关键总结 | 问题原因 | 解决方案 | |---------|----------| | 未指定容器名(多容器Pod) | 添加 `-c <container-name>` | | 容器无Bash | 改用 `sh` 或 `/bin/sh` | | 容器未运行 | 修复Pod状态(查看日志/事件) | | 容器名称错误 | 通过 `kubectl describe` 确认名称 | > 📌 **经验提示**:当使用 `-- bash` 失败时,优先尝试 `-- sh`,Alpine 镜像的普及率已超60%(2023年CNCF报告数据)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值