Kubernetes资源管理
目录贴:Kubernetes学习系列
1、资源模型
虛拟化技术是云计算平台的基础,其目标是对计算资源进行整合或划分,这是云计算管理平台中的关键技术。虚拟化技术为云计算管理乎台的资源管理提供了资源调配上的灵活性,从而使得云计算管理平台可以通过虚拟化层整合或划分计算资源。
相比于虚拟机,新出现的容器技术使用了一系列的系统级别的机制,诸如利用Linux Namespace进行空间隔离,通过文件系统的挂载点决定容器可以访问哪些文件,通过Cgroup确定每个容器可以利用多少资源。此外,容器之间共享同一个系统内核,这样当同一个内核被多个容器使用时,内存的使用效率会得到提升。
容器和虛拟机两大虛拟化技术,虽然实现方式完全不同,但是它们的资源需求和模型其实是类似的。容器像虛拟机一样需要内存、CPU、硬盘空间和网络带宽,宿主机系统可以将虛拟机和容器都视作一个整体,为这个整体分配其所需的资源,并进行管理。当然, 虚拟机提供了专用操作系统的安全性和更牢固的逻辑边界,而容器在资源边界上比较松散,这带来了灵活性以及不确定性。
Kubernetes是一个容器集群管理平台,Kubernetes需要统计整体平台的资源使用情况,合理地将资源分配给容器使用,并且要保证容器生命周期内有足够的资源来保证其运行。 更进一步,如果资源发放是独占的,即资源已发放给了个容器,同样的资源不会发放给另外一个容器,对于空闲的容器来说占用着没有使用的资源比如CPU是非常浪费的,Kubernetes需要考虑如何在优先度和公平性的前提下提高资源的利用率。
2、资源请求与限制
创建Pod的时候,可以指定计算资源(目前支持的资源类型有CPU和内存),即指定每个容器的资源请求(Request)和资源限制(Limit),资源请求是容器所需的最小资源需求,资源限制则是容器不能超过的资源上限。它们的大小关系是:
0<=request<=limit<=infinity
Pod的资源请求就是Pod中容器资源请求之和。Kubernetes在调度Pod时,会根据Node中的资源总量(通过cAdvisor接口获得),以及该Node上已使用的计算资源,来判断该Node是否满足需求。
资源请求能够保证Pod有足够的资源来运行,而资源限制则是防止某个Pod无限制地使用资源,导致其他Pod崩溃。特别是在公有云场景,往往会有恶意软件通过抢占内存来攻击平台。
原理:Docker 通过使用Linux Cgroup来实现对容器资源的控制,具体到启动参数上是--memory和--cpu-shares。Kubernetes中是通过控制这两个参数来实现对容器资源的控制。
以下给出某个Pod申请内存及CPU的示例:
[root@k8s-master demon2]# cat test-limit.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
name: test-limit
role: master
name: test-limit
spec:
containers:
- name: test-limit
image: registry:/back_demon:1.0
resources:
requests:
memory: "256Mi"
cpu: "500m"
limits:
memory: "512Mi"
cpu: "1000m"
command:
- /run.sh
待Pod调度到具体某个机器上之后,在该机器上查询对应容器的详情,如下:
[root@k8s-node- home]# docker inspect 1fdbd6f1b39b
[
{
"Id": "1fdbd6f1b39b561d09084adafb382b721959e5edd0ee9538472313ed0a39162a",
"Created": "2017-03-20T05:40:30.756006226Z",
"Path": "/run.sh",
"Args": [],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": ,
"ExitCode": ,
"Error": "",
"StartedAt": "2017-03-20T05:40:31.113657323Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:9369911131d30b12759074e5b72356345446996bf6044950c2def787471e9b4c",
"ResolvConfPath": "/var/lib/docker/containers/8fdb38a4d0074b07ff2f07e21fd8602fdbf4267eafc76179e931d4f5d9265940/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/8fdb38a4d0074b07ff2f07e21fd8602fdbf4267eafc76179e931d4f5d9265940/hostname",
"HostsPath": "/var/lib/kubelet/pods/ba75e7a9-0d2f-11e7-b3d5-fa163ebba51b/etc-hosts",
"LogPath": "/var/lib/docker/containers/1fdbd6f1b39b561d09084adafb382b721959e5edd0ee9538472313ed0a39162a/1fdbd6f1b39b561d09084adafb382b721959e5edd0ee9538472313ed0a39162a-json.log",
"Name": "/k8s_test-limit.79cbd53f_test-limit_default_ba75e7a9-0d2f-11e7-b3d5-fa163ebba51b_efc94078",
"RestartCount": ,
"Driver": "devicemapper",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "",
"ExecIDs": null,
"HostConfig": {
"Binds": [
"/var/lib/kubelet/pods/ba75e7a9-0d2f-11e7-b3d5-fa163ebba51b/etc-hosts:/etc/hosts:Z",
"/var/lib/kubelet/pods/ba75e7a9-0d2f-11e7-b3d5-fa163ebba51b/containers/test-limit/efc94078:/dev/termination-log:Z"
],
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "container:8fdb38a4d0074b07ff2f07e21fd8602fdbf4267eafc76179e931d4f5d9265940",
"PortBindings": null,
"RestartPolicy": {
"Name": "",
"MaximumRetryCount":
},
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": null,
"CapAdd": null,
"CapDrop": null,
"Dns": null,
"DnsOptions": null,
"DnsSearch": null,
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "container:8fdb38a4d0074b07ff2f07e21fd8602fdbf4267eafc76179e931d4f5d9265940",
"Cgroup": "",
"Links": null,
"OomScoreAdj": ,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyRootfs": false,
"SecurityOpt": [
"seccomp=unconfined"
],
"UTSMode": "",
"UsernsMode": "",
"ShmSize": ,
"Runtime": "docker-runc",
"ConsoleSize": [
, ],
"Isolation": "",
"CpuShares": ,
"Memory": ,
"CgroupParent": "",
"BlkioWeight": ,
"BlkioWeightDevice": null,
"BlkioDeviceReadBps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteIOps": null,
"CpuPeriod": ,
"CpuQuota": ,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DiskQuota": ,
"KernelMemory": ,
"MemoryReservation": ,
"MemorySwap": -,
"MemorySwappiness": -,
"OomKillDisable": false,
"PidsLimit": ,
"Ulimits": null,
"CpuCount": ,
"CpuPercent": ,
"IOMaximumIOps": ,
"IOMaximumBandwidth":
},
"GraphDriver": {
"Name": "devicemapper",
"Data": {
"DeviceId": "",
"DeviceName": "docker-253:0-100693626-cb08877222f483f043fc45c5c4b024de8da9c393c3c06c6252d3c59d330dd4d4",
"DeviceSize": ""
}
},
"Mounts": [
{
"Source": "/var/lib/kubelet/pods/ba75e7a9-0d2f-11e7-b3d5-fa163ebba51b/etc-hosts",
"Destination": "/etc/hosts",
"Mode": "Z",
"RW": true,
"Propagation": "rprivate"
},
{
"Source": "/var/lib/kubelet/pods/ba75e7a9-0d2f-11e7-b3d5-fa163ebba51b/containers/test-limit/efc94078",
"Destination": "/dev/termination-log",
"Mode": "Z",
"RW": true,
"Propagation": "rprivate"
}
],
"Config": {
"Hostname": "test-limit",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"222/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"KUBERNETES_PORT_443_TCP_PROTO=tcp",
"KUBERNETES_PORT_443_TCP_PORT=443",
"FRONTEND_SERVICE_PORT=tcp://10.254.232.119:8080",
"REDIS_SERVICE_SERVICE_PORT=6379",
"REDIS_SERVICE_PORT_6379_TCP_ADDR=10.254.71.136",
"KUBERNETES_SERVICE_PORT_HTTPS=443",
"KUBERNETES_SERVICE_HOST=10.254.0.1",
"KUBERNETES_PORT_443_TCP=tcp://10.254.0.1:443",
"BACK_SERVICE_PORT_8080_TCP_PORT=8080",
"FRONTEND_SERVICE_PORT_8080_TCP=tcp://10.254.232.119:8080",
"FRONTEND_SERVICE_PORT_8080_TCP_ADDR=10.254.232.119",
"REDIS_SERVICE_PORT_6379_TCP=tcp://10.254.71.136:6379",
"REDIS_MASTER_PORT_6379_TCP_PORT=6379",
"FRONTEND_PORT_80_TCP_PORT=80",
"REDIS_MASTER_PORT_6379_TCP_ADDR=10.254.132.210",
"REDIS_SLAVE_PORT_6379_TCP=tcp://10.254.104.23:6379",
"REDIS_SLAVE_PORT_6379_TCP_PORT=6379",
"BACK_SERVICE_SERVICE_HOST=10.254.246.51",
"BACK_SERVICE_PORT=tcp://10.254.246.51:8080",
"BACK_SERVICE_PORT_8080_TCP_PROTO=tcp",
"FRONTEND_PORT=tcp://10.254.93.91:80",
"REDIS_MASTER_SERVICE_HOST=10.254.132.210",
"REDIS_MASTER_PORT_6379_TCP_PROTO=tcp",
"KUBERNETES_SERVICE_PORT=443",
"FRONTEND_SERVICE_PORT_8080_TCP_PROTO=tcp",
"REDIS_MASTER_SERVICE_PORT=6379",
"REDIS_SLAVE_SERVICE_HOST=10.254.104.23",
"REDIS_SLAVE_PORT=tcp://10.254.104.23:6379",
"REDIS_SERVICE_PORT_6379_TCP_PROTO=tcp",
"REDIS_MASTER_PORT=tcp://10.254.132.210:6379",
"KUBERNETES_PORT_443_TCP_ADDR=10.254.0.1",
"BACK_SERVICE_SERVICE_PORT=8080",
"FRONTEND_SERVICE_HOST=10.254.93.91",
"FRONTEND_SERVICE_SERVICE_PORT=8080",
"REDIS_SERVICE_SERVICE_HOST=10.254.71.136",
"REDIS_SERVICE_PORT=tcp://10.254.71.136:6379",
"BACK_SERVICE_PORT_8080_TCP=tcp://10.254.246.51:8080",
"REDIS_SLAVE_SERVICE_PORT=6379",
"REDIS_SLAVE_PORT_6379_TCP_PROTO=tcp",
"REDIS_SLAVE_PORT_6379_TCP_ADDR=10.254.104.23",
"KUBERNETES_PORT=tcp://10.254.0.1:443",
"BACK_SERVICE_PORT_8080_TCP_ADDR=10.254.246.51",
"FRONTEND_PORT_80_TCP=tcp://10.254.93.91:80",
"FRONTEND_PORT_80_TCP_ADDR=10.254.93.91",
"FRONTEND_SERVICE_PORT_8080_TCP_PORT=8080",
"REDIS_MASTER_PORT_6379_TCP=tcp://10.254.132.210:6379",
"FRONTEND_PORT_80_TCP_PROTO=tcp",
"FRONTEND_SERVICE_SERVICE_HOST=10.254.232.119",
"REDIS_SERVICE_PORT_6379_TCP_PORT=6379"
],
"Cmd": null,
"Image": "registry:5000/back_demon:1.0",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": [
"/run.sh"
],
"OnBuild": null,
"Labels": {
"io.kubernetes.container.hash": "79cbd53f",
"io.kubernetes.container.name": "test-limit",
"io.kubernetes.container.restartCount": "",
"io.kubernetes.container.terminationMessagePath": "/dev/termination-log",
"io.kubernetes.pod.name": "test-limit",
"io.kubernetes.pod.namespace": "default",
"io.kubernetes.pod.terminationGracePeriod": "",
"io.kubernetes.pod.uid": "ba75e7a9-0d2f-11e7-b3d5-fa163ebba51b"
}
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": ,
"Ports": null,
"SandboxKey": "",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "",
"Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": ,
"IPAddress": "",
"IPPrefixLen": ,
"IPv6Gateway": "",
"MacAddress": "",
"Networks": null
}
}
]
3、LimitRange
LimitRange设计的初衷是为了满足以下场景:
能够约束租户的资源需求。
能够约束容器的资源请求范围。
能够约束Pod的资源请求范围。
能够指定容器的默认资源限制。
能够指定Pod的默认资源限制。
能够约束资源请求和限制之间的比例。
4、Resource Quota
Kubernetes是一个多租户架构,当多用户或者团队共享一个Kubernetes系统的时候,系统管理员需要防止租户的资源抢占,定义好资源分配策略。比如Kubernetes系统共有20 核CPU和32GB内存,分配给A租户5核CPU和16GB,分配给B租户5核CPU 和8GB,预留10核CPU和8GB内存。这样,租户中所使用的CPU和内存的总和不能超过指定的资源配额,促使其更合理地使用资源。
Kubernetes提供API对象Resource Quota(资源配额)来实现资源配额,Resource Quota不仅可以作用于CPU和內存,另外还可以限制比如创建Pod的总数目、Service总数目、RC总数目等。
默认情况下,Namespace是没有Resource Quota的,需要另外创建Resource Quota。一旦Namespace中有了Resource Quota,那么创建Pod的时候就必须制定资源请求,否则Pod就会创建失败。
Kubernetes资源管理的更多相关文章
- kubernetes 资源管理
前言 在kubernetes环境下,无论集群再大,对应的集群资源(cpu.memory.storage)总是有上限的.而默认情况下,我们启动的pod.以及pod中运行的容器,对应的资源是不加限制的.理 ...
- [Kubernetes]资源模型与资源管理
作为 Kubernetes 的资源管理与调度部分的基础,需要从它的资源模型说起. 资源管理模型的设计 我们知道,在 Kubernetes 里面, Pod 是最小的原子调度单位,这就意味着,所有和调度和 ...
- Kubernetes学习系列
这段时间项目组内想要引入Kubernetes,作为第二代容器调度引擎,故最近在系统的学习Kubernetes.整理了一些学习笔记,心得,放到博客中,一来记录自己的学习经过,二来看能否帮到有需要的同学. ...
- Kubernetes 资源对象
概述 我将它们简单的分类为以下几种资源对象: 类别 名称 资源对象 Pod.ReplicaSet.ReplicationController.Deployment.StatefulSet.Daemon ...
- Kubernetes 多集群在开源项目 KubeSphere 的应用
Kubernetes 多集群使用场景 随着容器的普及和 Kubernetes 的日渐成熟,企业内部运行多个 Kubernetes 集群已变得颇为常见.概括起来,多个集群的使用场景主要有以下几种. 多集 ...
- Apache Spark 3.0 将内置支持 GPU 调度
如今大数据和机器学习已经有了很大的结合,在机器学习里面,因为计算迭代的时间可能会很长,开发人员一般会选择使用 GPU.FPGA 或 TPU 来加速计算.在 Apache Hadoop 3.1 版本里面 ...
- Spark(一)Spark简介
一.官网介绍 1 什么是Spark 官网地址:http://spark.apache.org/ Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎.Spark是UC Berkel ...
- Kubernetes-运维指南
Node隔离与恢复 cat unschedule_node.yaml apiVersion: kind: Node metadata: name: k8s-node-1 labels: kuberne ...
- Apache Spark 3.0 预览版正式发布,多项重大功能发布
2019年11月08日 数砖的 Xingbo Jiang 大佬给社区发了一封邮件,宣布 Apache Spark 3.0 预览版正式发布,这个版本主要是为了对即将发布的 Apache Spark 3. ...
随机推荐
- Zend Optimizer,Zend Guard Loader 和 Zend Opcache 三者之间的区别
PHP的加速插件有三个:Zend Optimizer.Zend Guard Loader 和 Zend Opcache.但其实都是一个,针对不通的php版本.名字叫法不一样而已. Zend Optim ...
- 【Dubbo 源码解析】06_Dubbo 服务调用
Dubbo 服务调用 根据上图,可以看出,服务调用过程为: Consumer 端的 Proxy 调用 Cluster 层选择集群中的某一个 Invoker(负载均衡) Invoker 最终会调用 Pr ...
- node-log4js3.0.6配置
const log4js = require('log4js'); const conf = { "appenders": { "access": { &quo ...
- 深度解剖session运行原理
已经大半年没有更新博客了,一方面有比博客更重要的事情要做,另外一方面也没有时间来整理知识,所以希望在接下来的日子里面能够多多的写博客来与大家交流 什么是session session的官方定义是:Se ...
- CentOS7.X中设置nginx和php-fpm的开机自启动
一.设置nginx的开机自启动方法 1.在/etc/init.d/目录下创建nginx文件 vi /etc/init.d/nginx 编写内容如下: #!/bin/sh # # nginx - thi ...
- Python Django 配置QQ邮箱发送邮件
一.实验环境 Python2.7 + Django1.10.0 二.获取QQ邮箱授权码 1.什么是授权码? 授权码是QQ邮箱推出的,用于登录第三方客户端的专用密码. 适用于登录以下服务:POP3/IM ...
- 10.27 rest_framework(1)
2018-10-27 16:48:04 前几天在整理django博客! 新学的rest_framework框架是源于Django的 使用的时候得 pip install djangorestframe ...
- node 把文件封装一层文件夹
把 pages 下面的单个js文件,封装上一个文件夹 var glob = require("glob"); const fs = require("fs-extra&q ...
- 伪分布式hadoop启动后jps查不到namenode的解决办法
启动过程没有发现错误,但是jps查看进程时,发现少了NameNode,而DataNode却存在: 原因: 是端口9000已经被占用,解决办法有两个, 第一种:查找占用端口的进程,kill掉它. had ...
- html form禁止表单回车自动提交(通常原因是为在ajax提交前、后进行js判断控制)
@*onkeydown事件用于禁止回车自动提交form,这样就不经过js控制跳转*@ <form action="/Account/CheckPsw" method=&quo ...