zoukankan      html  css  js  c++  java
  • 在k8s中解决pod资源的正确识别

    1、容器资源限制概述

    在使用docker作为容器引擎的时候,可以通过添加--memory--cpus及更多参数来限制容器可用的cpu和内存,具体参数可以参考docker资源限制docker对容器进行限制的原理实际上是利用Linux内核的cgroups实现的,cgroups可以限制、记录、隔离进程组所使用的物理资源(包括:CPUmemoryIO 等),为容器实现虚拟化提供了基本保证,是构建Docker等一系列虚拟化管理工具的基石

    关于cgroups资源限制实现可以参考Docker背后的内核知识-cgroups资源限制

    2、问题背景

    对于某些容器中运行的服务,通常会自动对当前环境的可用资源数量进行检测,接着根据这些数据来合理分配相应资源

    例如nginx容器,nginx通过在配置文件中指定nginx worker_processes选项,默认这个选项参数的值为1,表示nginx仅启动1个worker进程

    如果需要在大并发环境下优化nginx性能,可以将这个值手动设置成对应环境的cpu核数,或者直接配置成auto让其自动设置,两种设置方法中前者需要将配置文件进行挂载并手动变更配置,后者更为灵活但在容器环境下会有一定问题,因为不管是通过docker直接运行的容器还是通过k8s运行的最小化单元Pod中的容器,识别到的cpu和内存都是所在node节点机器的资源信息,因此对nginx来说并不能直接通过auto参数对cpu进行正确的自动识别,例如我这里的一台node节点及节点上的pod资源信息

    # kubectl describe nodes k8s-node-07|grep -A 5 "Capacity"
    Capacity:
      cpu:                16
      ephemeral-storage:  74408452Ki
      hugepages-2Mi:      0
      memory:             16430184Ki
      pods:               110
    # docker info|grep -A 6 "Kernel"
    Kernel Version: 4.4.247-1.el7.elrepo.x86_64
    Operating System: CentOS Linux 7 (Core)
    OSType: linux
    Architecture: x86_64
    CPUs: 16
    Total Memory: 15.67GiB
    Name: k8s-node-07
    # kubectl exec -it test-pod-5dff4b89fd-bsh6b -- bash
    root@test-pod-5dff4b89fd-bsh6b:/# free -m
                  total        used        free      shared  buff/cache   available
    Mem:          16045        7915        2354        1002        5775        6222
    Swap:             0           0           0
    root@test-pod-5dff4b89fd-bsh6b:/# head -2 /proc/meminfo
    MemTotal:       16430184 kB
    MemFree:         2374064 kB
    

    如果在k8s中通过resources限制了Podcpu和内存,例如

            resources:
              limits:
                cpu: "1"
                memory: 2Gi
              requests:
                cpu: 200m
                memory: 512Mi
    

    可以在创建出来的pod所在节点机器上通过docker命令查看具体的资源信息

    # docker inspect b1f4bfb53a2c|grep -i cgroup
                "Cgroup": "",
                "CgroupParent": "/kubepods/burstable/podc4a25564-225b-4562-afee-fab8cc5d694f",
                "DeviceCgroupRules": null,
    # cat /sys/fs/cgroup/cpu/kubepods/burstable/podc4a25564-225b-4562-afee-fab8cc5d694f/cpu.cfs_quota_us
    100000
    # cat /sys/fs/cgroup/cpu/kubepods/burstable/podc4a25564-225b-4562-afee-fab8cc5d694f/cpu.cfs_period_us
    100000
    

    通过查找相关资料得知,对nginx来说,获取CPU核心数是通过系统调用sysconf(_SC_NPROCESSORS_ONLN)来获取的,实际上是通过读取文件/sys/devices/system/cpu/online来获取的,而默认情况下pod中的这个文件信息和宿主机是一样的,因此nginxworker_processes参数如果设置成auto,那么最终启动的worker进程数将会是16个,而nginx所在的Pod本身的cpu限制配置较小时,导致每个worker分配的时间片比较少,这会带来明显的响应慢的问题

    # kubectl exec -it test-pod-5dff4b89fd-bsh6b -- cat /sys/devices/system/cpu/online
    0-15
    

    3、引入lxcfs

    lxcfs是一个的小型FUSE文件系统,旨在使Linux容器更像一个虚拟机,能够帮助容器正确的识别自身资源,处理对以下文件的信息

    /proc/cpuinfo
    /proc/diskstats
    /proc/meminfo
    /proc/stat
    /proc/swaps
    /proc/uptime
    /sys/devices/system/cpu/online
    

    当容器启动时,容器中的/proc/xxx会被挂载成hostlxcfs的目录。例如当容器内的应用如果需要读取/proc/meminfo的信息时,请求就会被导向lxcfs,而lxcfs又会通过cgroup的信息来返回正确的值最终使得容器内的应用正确识别

    3.1 在k8s中部署lxcfs

    基于k8s部署的lxcfs文件系统的项目地址:https://github.com/denverdino/lxcfs-admission-webhook

    其最终利用的原理是基于k8s动态准入控制AdmissionWebhook

    我这里的k8s集群版本如下

    # kubectl version -o yaml
    clientVersion:
      buildDate: "2020-12-08T17:59:43Z"
      compiler: gc
      gitCommit: af46c47ce925f4c4ad5cc8d1fca46c7b77d13b38
      gitTreeState: clean
      gitVersion: v1.20.0
      goVersion: go1.15.5
      major: "1"
      minor: "20"
      platform: darwin/amd64
    serverVersion:
      buildDate: "2019-06-19T16:32:14Z"
      compiler: gc
      gitCommit: e8462b5b5dc2584fdcd18e6bcfe9f1e4d970a529
      gitTreeState: clean
      gitVersion: v1.15.0
      goVersion: go1.12.5
      major: "1"
      minor: "15"
      platform: linux/amd64
    

    首先获取资源清单并通过脚本一键部署

    # git clone https://github.com/denverdino/lxcfs-admission-webhook.git
    # cd lxcfs-admission-webhook
    # ls deployment 
    deployment.yaml                lxcfs-daemonset.yaml           mutatingwebhook.yaml           uninstall.sh                   web.yaml                       webhook-patch-ca-bundle.sh
    install.sh                     mutatingwebhook-ca-bundle.yaml service.yaml                   validatingwebhook.yaml         webhook-create-signed-cert.sh
    # kubectl apply -f deployment/lxcfs-daemonset.yaml                    
    daemonset.apps/lxcfs created
    # ./deployment/install.sh  
    creating certs in tmpdir /var/folders/8n/11ndbfq95jv79gds8wqj2scc0000gn/T/tmp.c6OKXi4L 
    Generating RSA private key, 2048 bit long modulus
    .......................................+++
    ...............+++
    e is 65537 (0x10001)
    certificatesigningrequest.certificates.k8s.io/lxcfs-admission-webhook-svc.default created
    NAME                                  AGE   REQUESTOR   CONDITION
    lxcfs-admission-webhook-svc.default   0s    admin       Pending
    certificatesigningrequest.certificates.k8s.io/lxcfs-admission-webhook-svc.default approved
    W0327 16:35:14.764281    8953 helpers.go:553] --dry-run is deprecated and can be replaced with --dry-run=client.
    secret/lxcfs-admission-webhook-certs created
    NAME                            TYPE     DATA   AGE
    lxcfs-admission-webhook-certs   Opaque   2      0s
    deployment.apps/lxcfs-admission-webhook-deployment created
    service/lxcfs-admission-webhook-svc created
    mutatingwebhookconfiguration.admissionregistration.k8s.io/mutating-lxcfs-admission-webhook-cfg created
    

    查看部署结果,会运行一个名为lxcfs-admission-webhook-deploymentpod,以及在所有节点上以ds的方式运行一个lxcfspod

    kubectl get pods -o wide|grep lxcfs
    lxcfs-admission-webhook-deployment-6896958c4c-56k54   1/1     Running   0          80s     172.20.7.51    172.16.1.111   <none>           <none>
    lxcfs-67cgk                                           1/1     Running   0          94s     172.20.0.25    172.16.1.100   <none>           <none>
    lxcfs-c4lkx                                           1/1     Running   0          93s     172.20.1.25    172.16.1.101   <none>           <none>
    ...
    

    3.2 开启命名空间注入

    # kubectl label namespace default lxcfs-admission-webhook=enabled
    

    为指定的命名空间开启lxcfs注入,开启后该命名空间下所有新创建的Pod都将被注入lxcfs

    3.3 还原

    如果是要还原安装的环境,执行目录中的卸载脚本即可

    # ./deployment/uninstall.sh 
    mutatingwebhookconfiguration.admissionregistration.k8s.io "mutating-lxcfs-admission-webhook-cfg" deleted
    service "lxcfs-admission-webhook-svc" deleted
    deployment.apps "lxcfs-admission-webhook-deployment" deleted
    secret "lxcfs-admission-webhook-certs" deleted
    # kubectl delete -f deployment/lxcfs-daemonset.yaml        
    daemonset.apps "lxcfs" deleted
    

    4、测试

    克隆下来的代码中提供了一个用于测试的httpd podyaml,可以直接部署

    # kubectl apply -f deployment/web.yaml 
    deployment.apps/web created
    # kubectl get pods -l app=web
    NAME                   READY   STATUS    RESTARTS   AGE
    web-5ff5cd75f8-74pr6   1/1     Running   0          27s
    web-5ff5cd75f8-bcm2x   1/1     Running   0          27s
    

    进入容器查看资源

    kubectl exec -it web-5ff5cd75f8-74pr6 -- bash
    root@web-5ff5cd75f8-74pr6:/usr/local/apache2# free -m
                 total       used       free     shared    buffers     cached
    Mem:           256         15        240          0          0          0
    -/+ buffers/cache:         14        241
    Swap:            0          0          0
    root@web-5ff5cd75f8-74pr6:/usr/local/apache2# cat /proc/cpuinfo| grep "processor"| wc -l
    1
    

    实际上通过lxcfs+动态准入控制,在创建新的pod时自动挂载了主机的相关文件,可以通过下面的方式查看

    # kubectl describe pods web-5ff5cd75f8-74pr6
    ...
        Mounts:
          /proc/cpuinfo from lxcfs-proc-cpuinfo (rw)
          /proc/diskstats from lxcfs-proc-diskstats (rw)
          /proc/loadavg from lxcfs-proc-loadavg (rw)
          /proc/meminfo from lxcfs-proc-meminfo (rw)
          /proc/stat from lxcfs-proc-stat (rw)
          /proc/swaps from lxcfs-proc-swaps (rw)
          /proc/uptime from lxcfs-proc-uptime (rw)
          /sys/devices/system/cpu/online from lxcfs-sys-devices-system-cpu-online (rw)
          /var/run/secrets/kubernetes.io/serviceaccount from default-token-jtj98 (ro)
    ...
    

    5、小结

    容器中的pod已经能正确的读取到cpu及内存的限制值了,如果是自身应用要读取所在环境的资源配置,如果出现问题,一定要从底层弄清楚是如何获取到的环境资源

    通过上面的测试可以看到lxcfs也自动挂载了nginx需要的/sys/devices/system/cpu/online文件到pod中了,因此nginx容器中worker process自动设置的问题经过测试验证也已得到了解决

    参考:

    https://github.com/denverdino/lxcfs-admission-webhook

  • 相关阅读:
    网页打开速度的心理学
    UML建模——用例图(Use Case Diagram)
    漫谈干系人识别管理
    干系人分析的3个方法:除了目标用户还要考虑谁?
    计算机网络-复习笔记
    项目经理必掌握的国际项目管理知识体系结构及内容
    剑指Offer面试题:5.重建二叉树
    剑指Offer面试题:4.从尾到头打印链表
    剑指Offer面试题:3.替换空格
    剑指Offer面试题:2.二维数组中的查找
  • 原文地址:https://www.cnblogs.com/ssgeek/p/14586389.html
Copyright © 2011-2022 走看看