千家信息网

Kubernetes容器隔离问题实例分析

发表于:2025-01-28 作者:千家信息网编辑
千家信息网最后更新 2025年01月28日,这篇文章主要讲解了"Kubernetes容器隔离问题实例分析",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"Kubernetes容器隔离问题实例分析"吧
千家信息网最后更新 2025年01月28日Kubernetes容器隔离问题实例分析

这篇文章主要讲解了"Kubernetes容器隔离问题实例分析",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"Kubernetes容器隔离问题实例分析"吧!

背景

  • 容器中看到的/proc伪文件系统的信息是宿主的/proc,没有隔离/proc 意味着获取不到容器中进程相关的proc信息。另外,一些需要读取proc信息的应用,会获取到错误的数据。 /proc/meminfo,/proc/cpuinfo, /proc/stat, /proc/uptime, /proc/loadavg

  • 用户UID/GID的映射,导致容器中的进程具有宿主上相同uid/gid用户的权限

需求分析

方案调研

Docker社区里有讨论过类似的问题,https://github.com/docker/docker/issues/8427,可以通过kernel patch或者bind mount /proc 来实现。 淘宝团队在几年前曾经发过一个kernel patch https://github.com/alibaba/taobao-kernel/blob/master/patches.taobao/overlayfs-0005-vfs-introduce-clone_private_mount.patch

业界讨论主要有以下几种方案:

## 方案一、-  直接修改proc文件系统 - https://lkml.org/lkml/2012/5/28/299- mount -t proc -o meminfo-from-cgroup none /path/to/container/proc缺点:不可能要求并入内核## 方案二、- Procg 方案: 把文件系统挂载进容器,替代原本的proc文件系统-  通过读cgroup指定的信息替代原本的/proc/meminfo信息- https://github.com/fabiokung/procg/缺点:内核的cgroup中没有公开读取内存数据函数接口## 方案三、基于lxcfs的docker容器procps软件包升级方案 --修改free、top、uptime等源码缺点:不是一个广泛接受的方案,不说自己修改命令可能产生的bug 和成本。不同的linux版本,可能会需要不同的补丁。

解决方案

为LXC准备的FUSE文件系统, 提供了如下的特性:

* a cgroupfs compatible view for unprivileged containers* a set of cgroup-aware files:    * cpuinfo    * meminfo    * stat    * uptime

用户空间文件系统 (Filesystem in Userspace, FUSE)

用户空间文件系统 是操作系统中的概念,指完全在用户态实现的文件系统。

目前Linux通过内核模块对此进行支持。一些文件系统如ZFS,glusterfs使用FUSE实现。

FUSE的工作原理如上图所示。假设基于FUSE的用户态文件系统hello挂载在/tmp/fuse目录下。当应用层程序要访问/tmp/fuse下的文件时,通过glibc中的函数进行系统调用,处理这些系统调用的VFS中的函数会调用FUSE在内核中的文件系统;内核中的FUSE文件系统将用户的请求,发送给用户态文件系统hello;用户态文件系统收到请求后,进行处理,将结果返回给内核中的FUSE文件系统;最后,内核中的FUSE文件系统将数据返回给用户态程序。

  • Linux内核从2.6.14支持通过FUSE模块

  • 用户空间实现文件系统

  • libfuse: 用户空间的fuse库, 非特权用户可访问。

LXCFS - 基于FUSE实现的用户空间文件系统

  • 站在文件系统的角度: 通过调用libfuse库内核的FUSE模块交互实现

  • 两个基本功能

  • 让每个容器有自身的cgroup文件系统视图,类似 Cgroup Namespace

  • 提供容器内部虚拟的proc文件系统

LXCFS 视角

从main函数可以看出,初始化的过程包括:

  1. 将运行时工作目录/run/lxcfs/controllers/ 挂载到 tmpfs文件系统

  2. 将当前系统的各个group子系统重新挂载到 /run/lxcfs/controllers/ 目录

  3. 调用libfuse库的主函数 fuse_main(), 指定用户态文件系统的目标目录- /var/lib/lxcfs/

  4. 使用struct fuse_operations 的ops方法, 与内核中的FUSE模块交互。 lxcfs.c:701

容器视角

  • 把虚拟proc文件系统挂载到docker容器

  • 用户在容器中读取/proc/meminfo ,cpuinfo 等信息

  • 在 proc_meminfo_read 操作中实现 读取meminfo

  • 过程: 拿到 meminfo进程的pid传给 lxcfs --> 拿到pid的cgroup分组 --> host的/cgroup目录对应进程的cgroup子系统信息

存在的问题以及如何解决

  1. LXCFS的部署问题以及带来的影响和成本? 见如下补充的 LxcFS - k8s实践

  2. 故障恢复,如何自动remount? 如果lxcfs进程重启了,那么容器里的/proc/cpuinfo等等都会报transport connected failed 这个是因为/var/lib/lxcfs会删除再重建,inode变了。所以参考豆瓣的做法,共享mount事件,重新给容器挂载

  • https://github.com/lxc/lxcfs/issues/193

  • https://github.com/alibaba/pouch/issues/140

User Namespace

解决什么问题?

  • 用户UID/GID的映射,导致容器中的进程具有宿主上相同uid/gid用户的权限

  • docker 从1.10版本 开始支持user namespace 隔离。使用参数:DOCKER_OPTS="--userns-remap=default"

相关文档链接:

  1. 基于LXCFS增强docker容器隔离性的分析 2015.12.9

  2. docker容器显示问题及修复 2017-03-23

  3. lxc-1.0.9 lxcfs-2.0.0 fuse-2.8.7源码详细注释分析

  4. Kubernetes之路 2 - 利用LXCFS提升容器资源可见性

  5. Kubernetes Initializers

  6. 看看大阿里pouch怎么解决remount这个问题

lxcfs 的 Kubernetes实践

注:以下内容来自文档链接4,内容有稍作修改

首先我们要在集群节点上安装并启动lxcfs,我们将用Kubernetes的方式,用利用容器和DaemonSet方式来运行 lxcfs FUSE文件系统。

本文所有示例代码可以通过以下地址从Github上获得

git clone https://github.com/denverdino/lxcfs-initializercd lxcfs-initializer

其manifest文件如下

apiVersion: apps/v1beta2kind: DaemonSetmetadata:  name: lxcfs  labels:    app: lxcfsspec:  selector:    matchLabels:      app: lxcfs  template:    metadata:      labels:        app: lxcfs    spec:      hostPID: true      tolerations:      - key: node-role.kubernetes.io/master        effect: NoSchedule      containers:      - name: lxcfs        image: dockerhub.nie.netease.com/whale/lxcfs:2.0.8        imagePullPolicy: Always        securityContext:          privileged: true        volumeMounts:        - name: rootfs          mountPath: /host      volumes:      - name: rootfs        hostPath:          path: /

注: 由于 lxcfs FUSE需要共享系统的PID名空间以及需要特权模式,所有我们配置了相应的容器启动参数。

可以通过如下命令在所有集群节点上自动安装、部署完成 lxcfs,是不是很简单?:-)

kubectl create -f lxcfs-daemonset.yaml

那么如何在Kubernetes中使用 lxcfs 呢?和上文一样,我们可以在Pod的定义中添加对 /proc 下面文件的 volume(文件卷)和对 volumeMounts(文件卷挂载)定义。然而这就让K8S的应用部署文件变得比较复杂,有没有办法让系统自动完成相应文件的挂载呢?

Kubernetes提供了 Initializer 扩展机制,可以用于对资源创建进行拦截和注入处理,我们可以借助它优雅地完成对lxcfs文件的自动化挂载。

其 manifest 文件如下

apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata:  name: lxcfs-initializer-default  namespace: kube-systemrules:- apiGroups: ["*"]  resources: ["deployments"]  verbs: ["initialize", "patch", "watch", "list"]---apiVersion: v1kind: ServiceAccountmetadata:  name: lxcfs-initializer-service-account  namespace: kube-system---kind: ClusterRoleBindingapiVersion: rbac.authorization.k8s.io/v1metadata:  name: lxcfs-initializer-role-bindingsubjects:- kind: ServiceAccount  name: lxcfs-initializer-service-account  namespace: kube-systemroleRef:  kind: ClusterRole  name: lxcfs-initializer-default  apiGroup: rbac.authorization.k8s.io---apiVersion: apps/v1beta1kind: Deploymentmetadata:  initializers:    pending: []  labels:    app: lxcfs-initializer  name: lxcfs-initializerspec:  replicas: 1  template:    metadata:      labels:        app: lxcfs-initializer      name: lxcfs-initializer    spec:      serviceAccountName: lxcfs-initializer-service-account      containers:        - name: lxcfs-initializer          image: dockerhub.nie.netease.com/whale/lxcfs-initializer:0.0.2          imagePullPolicy: Always          args:            - "-annotation=initializer.kubernetes.io/lxcfs"            - "-require-annotation=true"---apiVersion: admissionregistration.k8s.io/v1alpha1kind: InitializerConfigurationmetadata:  name: lxcfs.initializerinitializers:  - name: lxcfs.initializer.kubernetes.io    rules:      - apiGroups:          - "*"        apiVersions:          - "*"        resources:          - deployments

注: 这是一个典型的 Initializer 部署描述,首先我们创建了service account lxcfs-initializer-service-account,并对其授权了 "deployments" 资源的查找、更改等权限。然后我们部署了一个名为 "lxcfs-initializer" 的Initializer,利用上述SA启动一个容器来处理对 "deployments" 资源的创建,如果deployment中包含 initializer.kubernetes.io/lxcfs为true的注释,就会对该应用中容器进行文件挂载

我们可以执行如下命令,部署完成之后就可以愉快地玩耍了

kubectl apply -f lxcfs-initializer.yaml

下面我们部署一个简单的Apache应用,为其分配256MB内存,并且声明了如下注释 "initializer.kubernetes.io/lxcfs": "true"

其manifest文件如下

apiVersion: apps/v1beta1kind: Deploymentmetadata:  annotations:    "initializer.kubernetes.io/lxcfs": "true"  labels:    app: web  name: webspec:  replicas: 1  template:    metadata:      labels:        app: web      name: web    spec:      containers:        - name: web          image: httpd:2          imagePullPolicy: Always          resources:            requests:              memory: "256Mi"              cpu: "500m"            limits:              memory: "256Mi"              cpu: "500m"

我们可以用如下方式进行部署和测试

$ kubectl create -f web.yaml deployment "web" created$ kubectl get podNAME                                 READY     STATUS    RESTARTS   AGEweb-7f6bc6797c-rb9sk                 1/1       Running   0          32s$ kubectl exec web-7f6bc6797c-rb9sk free             total       used       free     shared    buffers     cachedMem:        262144       2876     259268       2292          0        304-/+ buffers/cache:       2572     259572Swap:            0          0          0

我们可以看到 free 命令返回的 total memory 就是我们设置的容器资源容量。

我们可以检查上述Pod的配置,果然相关的 procfs 文件都已经挂载正确

$ kubectl describe pod web-7f6bc6797c-rb9sk...    Mounts:      /proc/cpuinfo from lxcfs-proc-cpuinfo (rw)      /proc/diskstats from lxcfs-proc-diskstats (rw)      /proc/meminfo from lxcfs-proc-meminfo (rw)      /proc/stat from lxcfs-proc-stat (rw)...

在Kubernetes中,还可以通过 Preset 实现类似的功能,篇幅有限。本文不再赘述了。

感谢各位的阅读,以上就是"Kubernetes容器隔离问题实例分析"的内容了,经过本文的学习后,相信大家对Kubernetes容器隔离问题实例分析这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

文件 系统 容器 用户 问题 内核 方案 分析 隔离 信息 空间 进程 函数 目录 资源 应用 实例 实例分析 内容 可以通过 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 2021山西省网络安全答案 爱彼迎软件开发过程 什算机网络技术 数据库查询数字格式 网络安全关系公安机关 游戏服务器怎么清档 软件开发宣传方式有哪些 软件开发设计报告 央视公益感人广告网络安全 上海奉贤区移动软件开发公司 数据库管理系统是在 区块宠物全仿软件开发 方舟手游单机存档怎么改服务器 张店染色软件开发服务 废旧回收app软件开发 什么是服务器操作系统 济南地区浪潮服务器服务商在哪里 邮箱服务器输入密码无效 思迅备份数据库 为什么授权码需要连接服务器 南通市联智互联网络技术 首钢软件开发 网络安全手抄报一等奖内容 光伏电站网络安全预防措施 什么是数据库设计的概念模型 热度在线网络技术北京有限公司 华为通用软件开发工程师笔试题 校园网DNS服务器地址 考网络安全怎么考 湖南专业软件开发服务检测中心
0