LXCFS is a small FUSE filesystem written with the intention of making Linux containers feel more like a virtual machine. It started as a side-project of LXC but is useable by any runtime.
"
Объясню по человечески:
xcfs — это реализация FUSE (файловой системы Userland) с открытым исходным кодом для поддержки контейнеров LXC, она также может поддерживать контейнеры Docker. Позвольте приложению в контейнере пройти сопоставление lxcfs при чтении информации о памяти и ЦП и перейти к своим собственным виртуальным данным, прочитанным через информацию определения, связанную с контейнером, в контрольной группе.
"
Что такое изоляция представления ресурсов?
Технология контейнеров обеспечивает изоляцию среды, которая отличается от традиционной технологии виртуальных машин. Обычные контейнеры Linux ускоряют упаковку и запуск контейнера, но также снижают степень изоляции контейнера. Одной из самых известных проблем с контейнерами Linux является проблема изоляции представления ресурсов.
Контейнеры могут использовать контрольные группы для ограничения использования ресурсов, в том числе: памяти, ЦП и т. д. Однако следует отметить, что если процесс в контейнере использует некоторые общие команды мониторинга, такие как: free, top и другие команды, то он фактически видит данные физической машины, а не данные контейнера. Это потому, что контейнер не делает это правильно/proc
, /sys
Изоляция представлений ресурсов, таких как файловые системы.
Зачем нужна изоляция представления ресурсов контейнера?
-
С точки зрения контейнеров обычно есть некоторые бизнес-разработчики, которые привыкли использовать традиционные физические машины и виртуальные машины.
top
,free
Дождитесь команд для просмотра использования ресурсов системы, но контейнер не изолирует представление ресурсов, поэтому данные, видимые в контейнере, по-прежнему являются данными физической машины. -
С точки зрения приложения среда выполнения процесса в контейнере отличается от среды выполнения процесса на виртуальной машине физической машины. И некоторые приложения, запускающие процессы в контейнерах, будут иметь некоторые риски безопасности:
Для многих Java-программ на основе JVM размер кучи и стека JVM будет распределяться в соответствии с ограничением системных ресурсов при запуске приложения. Однако при запуске приложения JAVA в контейнере данные памяти, полученные JVM, по-прежнему являются данными физической машины, а квота ресурсов, выделенная контейнером, меньше, чем размер ресурсов, требуемый при запуске JVM, что приведет к программа запускается безуспешно.
Для программ, которым необходимо получить информацию о процессоре хоста, например, при разработке сервера golang, вам необходимо получить golang
runtime.GOMAXPROCS(runtime.NumCPU())
Или когда эксплуатация и техническое обслуживание задают количество процессов запуска службы (типа worker_processes auto в конфигурации nginx), они вроде автоматически определяют количество ЦП в запущенной среде через программу. Но процесс внутри контейнера всегда будет начинаться с/proc/cpuinfo
Количество ядер ЦП, полученных в контейнере, и количество ядер в контейнере/proc
Файловая система по-прежнему находится на физическом компьютере, что влияет на статус работы службы, работающей в контейнере.Как сделать изоляцию представления ресурсов контейнера?
lxcfs был создан, чтобы решить эту проблему.
lxcfs считывает соответствующую информацию о системе в cgroup посредством монтирования файлов и монтирует ее в систему proc внутри контейнера через том докера. Тогда пусть приложение в докере думает, что это настоящий прок хоста, который читается при чтении информации в проке.
Ниже приведена архитектурная схема принципа работы lxcfs:
Объясните эту картину, когда мы ставим хост
/var/lib/lxcfs/proc/memoinfo
файл, смонтированный в контейнер Docker/proc/meminfo
После расположения, когда процесс в контейнере читает содержимое соответствующего файла, lxcfs/dev/fuse
Реализация будет считывать правильный лимит памяти из соответствующей Cgroup контейнера. Это позволяет приложению получать правильные ограничения ресурсов. То же самое верно и для ограничений процессора.Изоляция представления ресурсов через lxcfs
установить lxcfs
wget https://copr-be.cloud.fedoraproject.org/results/ganto/lxc3/epel-7-x86_64/01041891-lxcfs/lxcfs-3.1.2-0.2.el7.x86_64.rpm; rpm -ivh lxcfs-3.1.2-0.2.el7.x86_64.rpm --force --nodeps
Проверьте, прошла ли установка успешно
[root@ifdasdfe2344 system]# lxcfs -h Usage: lxcfs [-f|-d] [-p pidfile] mountpoint -f running foreground by default; -d enable debug output Default pidfile is /run/lxcfs.pid lxcfs -h
запустить lxcfs
Начать прямо в фоновом режиме
lxcfs /var/lib/lxcfs &
Запустить через systemd (рекомендуется)
touch /usr/lib/systemd/system/lxcfs.service cat > /usr/lib/systemd/system/lxcfs.service <<EOF [Unit] Description=lxcfs [Service] ExecStart=/usr/bin/lxcfs -f /var/lib/lxcfs Restart=on-failure #ExecReload=/bin/kill -s SIGHUP $MAINPID [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl start lxcfs.service
Проверьте, был ли запуск успешным
[root@ifdasdfe2344 system]# ps aux | grep lxcfs root 3276 0.0 0.0 112708 980 pts/2 S+ 15:45 0:00 grep --color=auto lxcfs root 18625 0.0 0.0 234628 1296 ? Ssl 14:16 0:00 /usr/bin/lxcfs -f /var/lib/lxcfs
Запущен успешно.
Проверить эффект lxcfs
lxcfs не включен
Сначала мы запускаем контейнер на машине, на которой не включена lxcfs, и входим в контейнер, чтобы просмотреть информацию о процессоре и памяти. Чтобы увидеть очевидную разницу, мы использовали сервер высокой конфигурации (32c128g).
# 执行以下操作 systemctl stop lxcfs docker run -it ubuntu /bin/bash # 进入到 nginx 容器中 free -h
Из приведенных выше результатов видно, что хотя информация о памяти просматривается в контейнере, отображается meminfo хоста.
# 看一下 CPU 的核数 cat /proc/cpuinfo| grep "processor"| wc -l
Результат согласуется с нашей догадкой: если lxcfs не включена, информация о процессоре, видимая контейнером, совпадает с информацией о хосте.
включить lxcfs
systemctl start lxcfs # 启动一个容器,用 lxcfs 的 /proc 文件映射到容器中的 /proc 文件,容器内存设置为 256M: 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:latest /bin/bash free -h
Видно, что память самого контейнера получена корректно, и изоляция представления ресурсов для памяти прошла успешно.
# --cpus 2,限定容器最多只能使用两个逻辑CPU docker run -it --rm -m 256m --cpus 2 \\ -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:latest /bin/sh
cpuinfo также является количеством логических процессоров, которые может использовать наш контейнер. Указание того, что контейнер может работать только на указанном количестве ЦП, должно иметь больше преимуществ, чем недостатков, то есть при создании контейнера вам нужно выполнить некоторую дополнительную работу и разумно выделить процессорный набор.
Kubernetes на практике с lxcfs
Использование lxcfs в kubernetes требует решения двух проблем:
Первая проблема заключается в запуске lxcfs на каждом узле;
Вторая проблема заключается в монтировании файла /proc, поддерживаемого lxcfs, в каждый контейнер;
Способ DaemonSet для запуска файловой системы lxcfs FUSE
Для первого вопроса мы используем daemonset для установки lxcfs на каждом узле k8s.
Используйте следующий файл yaml напрямую:
apiVersion: apps/v1 kind: DaemonSet metadata: name: lxcfs labels: app: lxcfs spec: 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:3.0.4 imagePullPolicy: Always securityContext: privileged: true volumeMounts: - name: cgroup mountPath: /sys/fs/cgroup - name: lxcfs mountPath: /var/lib/lxcfs mountPropagation: Bidirectional - name: usr-local mountPath: /usr/local volumes: - name: cgroup hostPath: path: /sys/fs/cgroup - name: usr-local hostPath: path: /usr/local - name: lxcfs hostPath: path: /var/lib/lxcfs type: DirectoryOrCreate
kubectl apply -f lxcfs-daemonset.yaml
Вы можете видеть, что набор демонов lxcfs был развернут на каждом узле.
Сопоставьте файлы proc lxcfs с контейнерами
Что касается второй проблемы, у нас есть два метода ее решения.
Первый — просто объявить хост в yaml-файле развертывания k8s.
/var/lib/lxcfs/proc
Серия файловых креплений.Второй метод использует механизм расширения Kubernetes Initializer для автоматического монтирования файла lxcfs. но
InitializerConfiguration
Функция k8s больше не поддерживается после k8s 1.14 и здесь повторяться не будет. Но мы можем для достижения той же цели реализовать administrator-webhook (управление доступом (Admission Control) для дальнейшей проверки запроса после авторизации или добавить параметры по умолчанию, https://kubernetes.feisky.xyz/extension/auth/admission).# 验证你的 k8s 集群是否支持 admission $ kubectl api-versions | grep admissionregistration.k8s.io/v1beta1 admissionregistration.k8s.io/v1beta1
Написание accept-webhook выходит за рамки этой статьи, вы можете перейти к официальной документации, чтобы узнать больше.
Вот пример реализации веб-хука допуска lxcfs, вы можете обратиться к: https://github.com/hantmac/lxcfs-admission-webhook.
Суммировать
В этой статье представлен метод обеспечения изоляции представления ресурсов контейнера с помощью lxcfs, который может помочь некоторым контейнерным приложениям лучше идентифицировать ограничения ресурсов среды выполнения контейнера.
В то же время в этой статье мы представляем использование контейнеров и DaemonSet для развертывания lxcfs FUSE, что не только значительно упрощает развертывание, но и облегчает использование собственных возможностей управления контейнерами Kubernetes для поддержки автоматического восстановления, когда процесс lxcfs при сбое и при масштабировании кластера.Это также может обеспечить согласованность развертывания узла. Этот метод применим к другому подобному мониторингу или расширению системы.
Кроме того, мы представили использование веб-перехватчика допуска Kubernetes для автоматизации монтирования файлов lxcfs. Весь процесс прозрачен для разработчиков приложений, что может значительно упростить эксплуатацию и обслуживание.