1. 博客/

K8s 部署 Lxcfs 准入控制器,实现容器中资源单独可见

·1598 字·4 分钟· ·
k8s lxcfs admission-webhook
Johny
作者
Johny
熟练的 云原生搬砖师
Table of Contents

环境说明
#

  • kubernetes version: v1.17.9 (kubeadm)
  • os: 7.8.2003 (Core)
  • kubernetes dashboard: rancher v2.4.15

概述
#

docker 使用 linux 内核中的 cgroup 实现了对 容器使用资源的限制,默认容器启动后依旧挂载了宿主机的 /proc 目录,其中包涵了,meminfocpuinfostatuptime 等资源信息。一些监控工具如 freetophtop业务应用 还依赖 /proc 下文件内容获取资源配置和使用情况。当它们在容器中运行时,实际还是查看到的是宿主机的资源使用,导致资源使用展示源不对,目前社区主流的解决方法是使用 lxcfs 的方法进行解决。

lxcfs
#

lxcfs 是一个开源的 fuse(用户态文件系统)最先实现来支持 lxc 容器,但是它也可以支持 Docker 容器。lxcfs 通过用户态文件系统,在容器中提供下列 procfs 的文件。

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

lxcfs 使用示意图

wqtcnpnizo

比如,将宿主机的 /var/lib/lxcfs/proc/memoinfo 文件挂载到 docker 容器中对应的 /proc/meminfo 位置后。容器中的进程读取相应文件内容时,lxcfsfuse 实现会从容器对应的 cgroup 中读取正确的内存限制。从而使得应用获得正确的资源使用情况。

admission webhook
#

在 Kubernetes apiserver 中包含两个特殊的准入控制器:MutatingAdmissionWebhookValidatingAdmissionWebhook,这两个控制器将发送准入请求到外部的 HTTP 回调服务并接收一个准入响应。如果启用了这两个准入控制器,kubernetes 管理员可以在集群中创建和配置一个 admission webhook。

k8s-api-request-lifecycle

  • 检查集群中是否启用了 admission webhook 控制器,并根据需要进行配置。
  • 编写处理准入请求的 HTTP 回调,回调可以是一个部署在集群中的简单 HTTP 服务,甚至也可以是一个 serverless 函数,例如 https://github.com/kelseyhightower/denyenv-validating-admission-webhook 这个项目。
  • 通过 MutatingWebhookConfigurationValidatingWebhookConfiguration 资源配置 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 参数中带上了 MutatingAdmissionWebhookValidatingAdmissionWebhook 两个准入控制插件,如果没有的(在 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  # 执行部署
    

image-20210430151057426

image-20210430151002149

测试
#

这里将部署一个 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 设置来。展示输出的。

image-20210430164850869

问题记录
#

  • 卸载

    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 作为基础镜像的容器。

参考文档
#

Done
#

相关文章

使用 Kubekey 一键 离线/在线 部署 kubernetes 集群
·2338 字·5 分钟·
k8s kubekey install
在 Kubernetes 中部署 nfs storageClass
·1026 字·3 分钟·
devops k8s storage-class nfs
使用 Confluentinc 在 Kubernetes 集群中部署 Kafka 集群
·1133 字·3 分钟·
k8s kafka zookeeper helm
Rancher 单机部署,进行升级后,导致docker无法正常启动
·586 字·2 分钟·
k8s fix docker rancher
Coredns 出现间断性无法正常解析域名问题
·1536 字·4 分钟·
k8s coredns dns
初探 Traefik ingress gateway
·1594 字·4 分钟·
k8s devops traefik