千家信息网

Kubernetes中如何利用LXCFS提升容器资源可见性

发表于:2025-01-31 作者:千家信息网编辑
千家信息网最后更新 2025年01月31日,这篇文章将为大家详细讲解有关Kubernetes中如何利用LXCFS提升容器资源可见性,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。下面将介绍在Doc
千家信息网最后更新 2025年01月31日Kubernetes中如何利用LXCFS提升容器资源可见性

这篇文章将为大家详细讲解有关Kubernetes中如何利用LXCFS提升容器资源可见性,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

下面将介绍在Docker和Kubernetes环境中解决遗留应用无法识别容器资源限制的问题。

Linuxs利用Cgroup实现了对容器的资源限制,但在容器内部依然缺省挂载了宿主机上的procfs/proc目录,其包含如:meminfo, cpuinfo,stat, uptime等资源信息。一些监控工具如free/top或遗留应用还依赖上述文件内容获取资源配置和使用情况。当它们在容器中运行时,就会把宿主机的资源状态读取出来,引起错误和不便。

LXCFS简介

社区中常见的做法是利用 lxcfs来提供容器中的资源可见性。lxcfs 是一个开源的FUSE(用户态文件系统)实现来支持LXC容器,它也可以支持Docker容器。

LXCFS通过用户态文件系统,在容器中提供下列 procfs 的文件。

/proc/cpuinfo/proc/diskstats/proc/meminfo/proc/stat/proc/swaps/proc/uptime

LXCFS的示意图如下

image

比如,把宿主机的 /var/lib/lxcfs/proc/memoinfo 文件挂载到Docker容器的/proc/meminfo位置后。容器中进程读取相应文件内容时,LXCFS的FUSE实现会从容器对应的Cgroup中读取正确的内存限制。从而使得应用获得正确的资源约束设定。

Docker环境下LXCFS使用

注:

  • 本文采用CentOS 7.4作为测试环境,并已经开启FUSE模块支持。

  • Docker for Mac/Minikube等开发环境由于采用高度剪裁过的操作系统,无法支持FUSE,并运行LXCFS进行测试。

安装 lxcfs 的RPM包

wget https://copr-be.cloud.fedoraproject.org/results/ganto/lxd/epel-7-x86_64/00486278-lxcfs/lxcfs-2.0.5-3.el7.centos.x86_64.rpmyum install lxcfs-2.0.5-3.el7.centos.x86_64.rpm

启动 lxcfs

lxcfs /var/lib/lxcfs &

测试

$docker run -it -m 256m \      -v /var/lib/lxcfs/proc/cpuinfo:/proc/cpuinfo:rw \      -v /var/lib/lxcfs/proc/diskstats:/proc/diskstats:rw \      -v /var/lib/lxcfs/proc/meminfo:/proc/meminfo:rw \      -v /var/lib/lxcfs/proc/stat:/proc/stat:rw \      -v /var/lib/lxcfs/proc/swaps:/proc/swaps:rw \      -v /var/lib/lxcfs/proc/uptime:/proc/uptime:rw \      ubuntu:16.04 /bin/bash      root@f4a2a01e61cd:/# free              total        used        free      shared  buff/cache   availableMem:         262144         708      261436        2364           0      261436Swap:             0           0           0

我们可以看到total的内存为256MB,配置已经生效。

lxcfs 的 Kubernetes实践

一些同学问过如何在Kubernetes集群环境中使用lxcfs,我们将给大家一个示例方法供参考。

首先我们要在集群节点上安装并启动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: registry.cn-hangzhou.aliyuncs.com/denverdino/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文件的自动化挂载。

注: 阿里云Kubernetes集群,已经默认开启了对 Initializer 的支持,如果是在自建集群上进行测试请参见文档开启相应功能

其 manifest 文件如下

apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata:  name: lxcfs-initializer-default  namespace: defaultrules:- apiGroups: ["*"]  resources: ["deployments"]  verbs: ["initialize", "patch", "watch", "list"]---apiVersion: v1kind: ServiceAccountmetadata:  name: lxcfs-initializer-service-account  namespace: default---kind: ClusterRoleBindingapiVersion: rbac.authorization.k8s.io/v1metadata:  name: lxcfs-initializer-role-bindingsubjects:- kind: ServiceAccount  name: lxcfs-initializer-service-account  namespace: defaultroleRef:  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: registry.cn-hangzhou.aliyuncs.com/denverdino/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/lxcfstrue的注释,就会对该应用中容器进行文件挂载

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

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中如何利用LXCFS提升容器资源可见性就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

0