- 博客/
K8s 部署 Lxcfs 准入控制器,实现容器中资源单独可见
Table of Contents
环境说明#
- kubernetes version: v1.17.9 (
kubeadm
) - os: 7.8.2003 (Core)
- kubernetes dashboard: rancher
v2.4.15
概述#
docker 使用 linux 内核中的
cgroup
实现了对 容器使用资源的限制,默认容器启动后依旧挂载了宿主机的/proc
目录,其中包涵了,meminfo
、cpuinfo
、stat
、uptime
等资源信息。一些监控工具如free
、top
、htop
或业务应用
还依赖/proc
下文件内容获取资源配置和使用情况。当它们在容器中运行时,实际还是查看到的是宿主机的资源使用,导致资源使用展示源不对,目前社区主流的解决方法是使用lxcfs
的方法进行解决。
lxcfs#
lxcfs 是一个开源的 fuse(用户态文件系统)最先实现来支持 lxc 容器,但是它也可以支持 Docker 容器。lxcfs 通过用户态文件系统,在容器中提供下列 procfs 的文件。
/proc/cpuinfo /proc/diskstats /proc/meminfo /proc/stat /proc/swaps /proc/uptime
lxcfs 使用示意图
比如,将宿主机的
/var/lib/lxcfs/proc/memoinfo
文件挂载到 docker 容器中对应的/proc/meminfo
位置后。容器中的进程读取相应文件内容时,lxcfs
的fuse
实现会从容器对应的cgroup
中读取正确的内存限制。从而使得应用获得正确的资源使用情况。
admission webhook#
在 Kubernetes apiserver 中包含两个特殊的准入控制器:
MutatingAdmissionWebhook
和ValidatingAdmissionWebhook
,这两个控制器将发送准入请求到外部的 HTTP 回调服务并接收一个准入响应。如果启用了这两个准入控制器,kubernetes 管理员可以在集群中创建和配置一个 admission webhook。
- 检查集群中是否启用了 admission webhook 控制器,并根据需要进行配置。
- 编写处理准入请求的 HTTP 回调,回调可以是一个部署在集群中的简单 HTTP 服务,甚至也可以是一个
serverless
函数,例如 https://github.com/kelseyhightower/denyenv-validating-admission-webhook 这个项目。- 通过
MutatingWebhookConfiguration
和ValidatingWebhookConfiguration
资源配置 admission webhook
这两种 admission webhook 之间的区别是明显的:validating webhooks
可以拒绝请求,但是它们却不能修改准入请求中获取的对象,而 mutating webhooks
可以在返回准入响应之前通过创建补丁来修改对象,如果 webhook 拒绝了一个请求,则会向最终用户返回错误
lxcfs 在 Kubernetes 中实践部署#
下面将示例使用 lxcfs-admission-webhook,部署
admission webhook
给 pod 注入 lxcfs 。
各节点
安装依赖#
注意这里是,所有节点多需要安装一下,否则节点会提示动态库缺失。
yum install -y fuse-libs
kubernetes 开启准入控制器#
我这里使用的是 kubeadm 搭建的集群,可以通过下面命令查看 apiserver pod 的配置
kubectl get node
NAME STATUS ROLES AGE VERSION
node1 Ready master,worker 11d v1.17.9
node2 Ready worker 11d v1.17.9
node3 Ready master,worker 2d22h v1.17.9
node4 Ready worker 2d22h v1.17.9
kubectl get pod kube-apiserver-node1 -n kube-system -o yaml
apiVersion: v1
kind: Pod
metadata:
name: kube-apiserver-node1
namespace: kube-system
......
spec:
containers:
- command:
- kube-apiserver
- --advertise-address=192.168.8.30
- --allow-privileged=true
- --anonymous-auth=True
- --apiserver-count=1
- --authorization-mode=Node,RBAC
- --bind-address=0.0.0.0
- --client-ca-file=/etc/kubernetes/pki/ca.crt
- --enable-admission-plugins=NodeRestriction,NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota
.....
上面的
enable-admission-plugins
参数中带上了MutatingAdmissionWebhook
和ValidatingAdmissionWebhook
两个准入控制插件,如果没有的(在 v1.19.x 版本中是默认开启的),需要添加上这两个参数,然后重启 apiserver。
kubeadm 演示如何为 apiserver 添加参数,和重启 apiserver
使用 kubeadm 部署的集群的话,apiserver 使用的部署方式为
静态pod
,即我们只要更改对应机器上的/etc/kubernetes/manifests/kube-apiserver.yaml
文件即可,当 kubelet watch 到配置文件更改后,它将会为我们进行重启生效。
cat /etc/kubernetes/manifests/kube-apiserver.yaml|grep enable-admission-plugins
- --enable-admission-plugins=NodeRestriction,NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota
查看集群是否开启了 准入控制 api
kubectl api-versions |grep admission
admissionregistration.k8s.io/v1
admissionregistration.k8s.io/v1beta1
部署 lxcfs#
- git clone 代码
git clone https://github.com/denverdino/lxcfs-admission-webhook.git
- 部署 lxcfs 资源清单
cd lxcfs-admission-webhook
kubectl create ns lxcfs # 创建 lxcfs 部署命名空间
# sed -i "s#default#lxcfs#g" deployment/lxcfs-daemonset.yaml # 替换部署命名空间
kubectl apply -f deployment/lxcfs-daemonset.yaml -n lxcfs
更改一下
deployment/install.sh
中部署的命名空间,默认使用的是default
sed -i "s#default#lxcfs#g" deployment/mutatingwebhook.yaml # 替换默认模板文件中的命名空间 cat deployment/install.sh #!/bin/bash ./deployment/webhook-create-signed-cert.sh --namespace lxcfs kubectl get secret lxcfs-admission-webhook-certs -n lxcfs kubectl create -f deployment/deployment.yaml -n lxcfs kubectl create -f deployment/service.yaml -n lxcfs cat ./deployment/mutatingwebhook.yaml | ./deployment/webhook-patch-ca-bundle.sh > ./deployment/mutatingwebhook-ca-bundle.yaml kubectl create -f deployment/mutatingwebhook-ca-bundle.yaml -n lxcfs bash deployment/install.sh # 执行部署
测试#
这里将部署一个 python 程序,进行模拟测试
- 为命名空间注入 lxcfs
kubectl label namespace default lxcfs-admission-webhook=enabled # 为命名空间打入 lxcfs-admission-webhook label 即可
- 创建测试资源清单
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: python3
namespace: default
labels:
app: python3
spec:
replicas: 1
selector:
matchLabels:
app: python3
template:
metadata:
labels:
app: python3
spec:
containers:
- args:
- sleep
- "18000"
name: python3
image: python:3.7-slim-buster
imagePullPolicy: Always
resources:
limits:
cpu: "2"
memory: 4Gi
requests:
cpu: "1"
memory: 2Gi
EOF
- 检查资源限制是否生效
kubectl get po
NAME READY STATUS RESTARTS AGE
python3-5fcbcf5655-sw65s 1/1 Running 0 22s
kubectl exec -it python3-5fcbcf5655-sw65s bash
cat /proc/cpuinfo| grep "cpu cores"| uniq # 查看 cpu 核数
cpu cores : 2
cat /proc/meminfo | grep MemTotal # 查看内存
MemTotal: 4194304 kB
apt update \
&& apt install htop
可以看到上面的资源清单,是更具
limits
设置来。展示输出的。
问题记录#
卸载
kubectl delete -f deployment/lxcfs-daemonset.yaml -n lxcfs cat deployment/uninstall.sh #!/bin/bash # 对脚本中指定了命名空间卸载 kubectl delete -f deployment/mutatingwebhook-ca-bundle.yaml -n lxcfs kubectl delete -f deployment/service.yaml -n lxcfs kubectl delete -f deployment/deployment.yaml -n lxcfs kubectl delete secret lxcfs-admission-webhook-certs -n lxcfs deployment/uninstall.sh # 执行卸载脚本 rm -rf /var/lib/lxcfs/ # 删除宿主机目录,如无法删除时,请尝试重启一下节点。
lxcfs 不支持 使用了
alpine
作为基础镜像的容器。
参考文档#
- https://cloud.tencent.com/developer/article/1645542
- https://github.com/denverdino/lxcfs-admission-webhook
- https://www.qikqiak.com/k8strain2/security/admission/
- https://github.com/lxc/lxcfs