目录贴: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资源管理的更多相关文章

  1. kubernetes 资源管理

    前言 在kubernetes环境下,无论集群再大,对应的集群资源(cpu.memory.storage)总是有上限的.而默认情况下,我们启动的pod.以及pod中运行的容器,对应的资源是不加限制的.理 ...

  2. [Kubernetes]资源模型与资源管理

    作为 Kubernetes 的资源管理与调度部分的基础,需要从它的资源模型说起. 资源管理模型的设计 我们知道,在 Kubernetes 里面, Pod 是最小的原子调度单位,这就意味着,所有和调度和 ...

  3. Kubernetes学习系列

    这段时间项目组内想要引入Kubernetes,作为第二代容器调度引擎,故最近在系统的学习Kubernetes.整理了一些学习笔记,心得,放到博客中,一来记录自己的学习经过,二来看能否帮到有需要的同学. ...

  4. Kubernetes 资源对象

    概述 我将它们简单的分类为以下几种资源对象: 类别 名称 资源对象 Pod.ReplicaSet.ReplicationController.Deployment.StatefulSet.Daemon ...

  5. Kubernetes 多集群在开源项目 KubeSphere 的应用

    Kubernetes 多集群使用场景 随着容器的普及和 Kubernetes 的日渐成熟,企业内部运行多个 Kubernetes 集群已变得颇为常见.概括起来,多个集群的使用场景主要有以下几种. 多集 ...

  6. Apache Spark 3.0 将内置支持 GPU 调度

    如今大数据和机器学习已经有了很大的结合,在机器学习里面,因为计算迭代的时间可能会很长,开发人员一般会选择使用 GPU.FPGA 或 TPU 来加速计算.在 Apache Hadoop 3.1 版本里面 ...

  7. Spark(一)Spark简介

    一.官网介绍 1 什么是Spark 官网地址:http://spark.apache.org/ Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎.Spark是UC Berkel ...

  8. Kubernetes-运维指南

    Node隔离与恢复 cat unschedule_node.yaml apiVersion: kind: Node metadata: name: k8s-node-1 labels: kuberne ...

  9. Apache Spark 3.0 预览版正式发布,多项重大功能发布

    2019年11月08日 数砖的 Xingbo Jiang 大佬给社区发了一封邮件,宣布 Apache Spark 3.0 预览版正式发布,这个版本主要是为了对即将发布的 Apache Spark 3. ...

随机推荐

  1. IT观察】网络通信、图片显示、数据库操作……Android程序员如何利用开源框架

    每个Android 程序员都不是Android应用开发之路上孤军奋战的一个人,GitHub上浩如烟海的开源框架或类库就是前人为我们发明的轮子,有的轮子能提高软件性能,而有的轮子似乎是以牺牲性能为代价换 ...

  2. SQL Server 中,如何獲得上個月的第一天和最後一天( 帶時間戳)

    select DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-1, 0) --First day of previous month select DATEA ...

  3. 服务器tail输出正常,vim打开中文乱码

    修改服务器端, 在/etc/vim/vimrc文件末尾加上 set fileencodings=utf-8,ucs-bom,gb18030,gbk,gb2312,cp936set termencodi ...

  4. JS数组常用方法总结

    JavaScript中创建数组有两种方式 (一)使用 Array 构造函数: var arr1 = new Array(); //创建一个空数组 var arr2 = new Array(20); / ...

  5. JS精准倒计时(支持自定义模板)

    /** * 倒计时 Create By TuJia @2017.10.17 * 使用方法: * leftTimer.run(container[,theme][,callback]); * * 支持 ...

  6. Kafka获取订阅某topic的所有consumer group【客户端版】

    之前写过如何用服务器端的API代码来获取订阅某topic的所有consumer group,参见这里.使用服务器端的API需要用到kafka.admin.AdminClient类,但是这个类在0.11 ...

  7. 查询表DML和DDL操作的最后时间

    查询test表DML操作的最后时间的语句: select max(ora_rowscn),to_char(scn_to_timestamp(max(ora_rowscn)),'yyyy-mm-dd h ...

  8. Git 与 SVN 命令学习笔记

    一:Git git config --global user.name "you name"   #设置用户名git config --global user.email &quo ...

  9. Oracle课程档案,第五天

    集合操作 desc job_history:改变历史职位 job_history:历史表 vnion:重复值只保留一个 去除重复值 ★★ vnion all: 把所有重复值保留 不去除重复值★★ in ...

  10. mysql中主外键关系

    一.外键: 1.什么是外键 2.外键语法 3.外键的条件 4.添加外键 5.删除外键 1.什么是外键: 主键:是唯一标识一条记录,不能有重复的,不允许为空,用来保证数据完整性 外键:是另一表的主键, ...