前面我们对K8s的基本组件与概念有了个大致的印象,并且基于K8s实现了一个初步的CI/CD流程,但对里面涉及的各个对象(如Namespace, Pod, Deployment, Service, Ingress, PVC等)及各对象的管理可能还缺乏深入的理解与实践,接下来的文章就让我们一起深入K8s的各组件内部来一探究竟吧。下图是基于个人的理解梳理的一个K8s结构图,示例了各个组件(只包含了主要组件)如何协同。

后续几篇文章围绕该图涉及组件进行整理介绍,本文主要探究Namespace及与Namespace管理相关的资源限制ResourceQuota/LimitRange部分。

Namespace

理解

Namespace即命名空间,主要有两个方面的作用:

  1. 资源隔离:可为不同的团队/用户(或项目)提供虚拟的集群空间,共享同一个Kubernetes集群的资源。比如可以为团队A创建一个Namespace ns-a,团队A的项目都部署运行在 ns-a 中,团队B创建另一个Namespace ns-b,其项目都部署运行在 ns-b 中,或者为开发、测试、生产环境创建不同的Namespace,以做到彼此之间相互隔离,互不影响。我们可以使用 ResourceQuota 与 Resource LimitRange 来指定与限制 各个namesapce的资源分配与使用
  2. 权限控制:可以指定某个namespace哪些用户可以访问,哪些用户不能访问

Kubernetes 安装成功后,默认会创建三个namespace:

  • default:默认的namespace,如果创建Kubernetes对象时不指定 metadata.namespace,该对象将在default namespace下创建
  • kube-system:Kubernetes系统创建的对象放在此namespace下,我们前面说的kube-apiserver,etcd,kube-proxy等都在该namespace下
  • kube-public:顾名思义,共享的namespace,所有用户对该namespace都是可读的。主要是为集群做预留,一般都不在该namespace下创建对象

实践

1.查看namesapce

  1. kubectl get namespaces
  2. kubectl get namesapce
  3. kubectl get ns # 三个操作等效
  4. kubectl get ns --show-labels # 显示namespace的label

使用namesapces,namesapce,ns都是可以的。如下列出了当前集群中的所有namespace

  1. [root@kmaster ~]# kubectl get ns
  2. NAME STATUS AGE
  3. default Active 34d
  4. develop Active 17d
  5. ingress-nginx Active 33d
  6. kube-node-lease Active 34d
  7. kube-public Active 34d
  8. kube-system Active 34d
  9. kubernetes-dashboard Active 31d
  10. pre-release Active 17d

可以使用 kubectl describe 命令来查看某个namespace的概要信息,如

  1. [root@kmaster ~]# kubectl describe ns default
  2. Name: default
  3. Labels: <none>
  4. Annotations: <none>
  5. Status: Active
  6. No resource quota.
  7. No resource limits.

2.创建namespace

有两种方式:通过yaml定义文件创建或直接使用命令创建。

  1. # 方式1. 通过yaml定义文件创建
  2. [root@kmaster ~]# vim test-namespace.yaml
  3. apiVersion: v1
  4. kind: Namespace
  5. metadata:
  6. name: test # namespace的名称
  7. labels:
  8. name: ns-test
  9. [root@kmaster ~]# kubectl create -f ./test-namespace.yaml
  10. # 方式2. 直接使用命令创建
  11. [root@kmaster ~]# kubectl create ns test

3.在namesapce中创建对象

  1. # 1. 在yaml中通过metadata.namesapce 指定
  2. [root@kmaster ~]# kubectl get deploy my-nginx -o yaml
  3. apiVersion: apps/v1
  4. kind: Deployment
  5. metadata:
  6. labels:
  7. run: my-nginx
  8. name: my-nginx
  9. namespace: test # 指定namespace
  10. spec:
  11. ...
  12. # 2. 在命令中通过 -n 或 --namesapce 指定
  13. [root@kmaster ~]# kubectl run dev-nginx --image=nginx:latest --replicas=3 -n test

4.设定kubectl namesapce上下文

kubectl上下文即集群、namespace、用户的组合,设定kubectl上下文,即可以以上下文指定的用户,在上下文指定的集群与namespace中进行操作管理。查看当前集群kubectl上下文

  1. # 查看当前kubectl上下文
  2. [root@kmaster ~]# kubectl config view
  3. apiVersion: v1
  4. clusters:
  5. - cluster:
  6. certificate-authority-data: DATA+OMITTED
  7. server: https://192.168.40.111:6443
  8. name: kubernetes
  9. contexts:
  10. - context:
  11. cluster: kubernetes
  12. user: kubernetes-admin
  13. name: kubernetes-admin@kubernetes
  14. current-context: kubernetes-admin@kubernetes
  15. kind: Config
  16. preferences: {}
  17. users:
  18. - name: kubernetes-admin
  19. user:
  20. client-certificate-data: REDACTED
  21. client-key-data: REDACTED

可见当前上下文为kubernetes-admin@kubernetes (current-context: kubernetes-admin@kubernetes)。

创建一个kubectl上下文

  1. [root@kmaster ~]# kubectl config set-context test --namespace=test --cluster=kubernetes --user=kubernetes-admin
  2. Context "test" created.

再次执行 kubectl config view 将可以看到上面创建的test上下文。

切换上下文

  1. # 设置当前上下文
  2. [root@kmaster ~]# kubectl config use-context test
  3. Switched to context "test".
  4. # 查看当前所在的上下文
  5. [root@kmaster ~]# kubectl config current-context
  6. test

指定了上下文,后续操作都在该上下文对应的namespace中进行,不需要再显式指定namespace。在上下文中创建对象

  1. # 在当前上下文中创建对象
  2. [root@kmaster ~]# kubectl run my-nginx --image=nginx:latest --replicas=2
  3. kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
  4. deployment.apps/my-nginx created
  5. # 查看创建的对象,不需要指定namespace
  6. [root@kmaster ~]# kubectl get deploy
  7. NAME READY UP-TO-DATE AVAILABLE AGE
  8. my-nginx 2/2 2 2 25m
  9. [root@kmaster ~]# kubectl get pod
  10. NAME READY STATUS RESTARTS AGE
  11. my-nginx-667764d77b-ldb78 1/1 Running 0 24m
  12. my-nginx-667764d77b-wpgxw 1/1 Running 0 24m

删除上下文

  1. [root@kmaster ~]# kubectl config delete-context test
  2. deleted context test from /root/.kube/config

也可以使用如下命令直接切换默认的namespace

  1. # 将默认namespace设置为test
  2. [root@kmaster ~]# kubectl config set-context --current --namespace=test

5.删除namesapce

可以使用 kubectl delete ns <namespace名称> 来删除一个namesapce,该操作会删除namespace中的所有内容。

  1. [root@kmaster ~]# kubectl delete ns test

Resource Quota

Resource Quota即资源配额,限定单个namespace中可使用集群资源的总量,包括两个维度:

  1. 限定某个对象类型(如Pod)可创建对象的总数;
  2. 限定某个对象类型可消耗的计算资源(CPU、内存)与存储资源(存储卷声明)总数

如果在 namespace 中为计算资源 CPU 和内存设定了 ResourceQuota,用户在创建对象(Pod、Service等)时,必须指定 requests 和 limits;如果在创建或更新对象时申请的资源与 namespace 的 ResourceQuota 冲突,则 apiserver 会返回 HTTP 状态码 403,以及对应的错误提示信息。当集群中总的容量小于各个 namespace 资源配额的总和时,可能会发生资源争夺,此时 Kubernetes 将按照先到先得的方式分配资源。

对象数量限制

声明格式为: count/<resource>.<group>, 如下列出各类对象的声明格式

  1. count/persistentvolumeclaims
  2. count/services
  3. count/secrets
  4. count/configmaps
  5. count/replicationcontrollers
  6. count/deployments.apps
  7. count/replicasets.apps
  8. count/statefulsets.apps
  9. count/jobs.batch
  10. count/cronjobs.batch
  11. count/deployments.extensions

计算资源限制

定义CPU、内存请求(requests)、限制(limits)使用的总量,包括

  • limits.cpu:namespace中,所有非终止状态的 Pod 的 CPU 限制 resources.limits.cpu 总和不能超过该值
  • limits.memory:namespace中,所有非终止状态的 Pod 的内存限制 resources.limits.memory 总和不能超过该值
  • requests.cpu:namespace中,所有非终止状态的 Pod 的 CPU 请求 resources.requrest.cpu 总和不能超过该值
  • requests.memory:namespace中,所有非终止状态的 Pod 的 CPU 请求 resources.requests.memory 总和不能超过该值

存储资源限制

定义存储卷声明请求的存储总量或创建存储卷声明数量的限制,包括

  • requests.storage:namespace中,所有存储卷声明(PersistentVolumeClaim)请求的存储总量不能超过该值
  • persistentvolumeclaims:namespace中,可以创建的存储卷声明的总数不能超过该值
  • <storage-class-name>.storageclass.storage.k8s.io/requests.storage:namespace中,所有与指定存储类(StorageClass)关联的存储卷声明请求的存储总量不能超过该值
  • <storage-class-name>.storageclass.storage.k8s.io/persistentvolumeclaims:namespace中,所有与指定存储类关联的存储卷声明的总数不能超过该值

除此之外,还可以对本地临时存储资源进行限制定义

  • requests.ephemeral-storage:namespace中,所有 Pod 的本地临时存储(local ephemeral storage)请求的总和不能超过该值
  • limits.ephemeral-storage:namespace中,所有 Pod 的本地临时存储限定的总和不能超过此值

实践

查看是否开启 Resource Quota 支持,默认一般是开启的。如果没有,可在启动 apiserver 时为参数 --enable-admission-plugins 添加 ResourceQuota 配置项。

1.创建ResourceQuota

  1. # 创建namespace
  2. [root@kmaster ~]# kubectl create namespace test
  3. # 编辑ResourceQuota定义文档
  4. [root@kmaster ~]# vim quota-test.yaml
  5. apiVersion: v1
  6. kind: ResourceQuota
  7. metadata:
  8. name: quota-test
  9. namespace: test
  10. spec:
  11. hard:
  12. requests.cpu: "2"
  13. requests.memory: 2Gi
  14. limits.cpu: "4"
  15. limits.memory: 4Gi
  16. requests.nvidia.com/gpu: 4
  17. pods: "3"
  18. services: "6"
  19. # 创建ResourceQuota
  20. [root@kmaster ~]# kubectl apply -f quota-test.yaml
  21. # 查看
  22. [root@kmaster ~]# kubectl get quota -n test
  23. NAME CREATED AT
  24. quota-test 2020-05-26T10:31:10Z
  25. [root@kmaster ~]# kubectl describe quota quota-test -n test
  26. Name: quota-test
  27. Namespace: test
  28. Resource Used Hard
  29. -------- ---- ----
  30. limits.cpu 0 4
  31. limits.memory 0 4Gi
  32. pods 0 3
  33. requests.cpu 0 2
  34. requests.memory 0 2Gi
  35. requests.nvidia.com/gpu 0 4
  36. services 0 6

或者使用kubectl命令,如

  1. [root@kmaster ~]# kubectl create quota quota-test --hard=count/deployments.extensions=2,count/replicasets.extensions=4,count/pods=3,count/secrets=4 --namespace=test

我们在namespace test中创建了一个ResourceQuota,限制CPU、内存请求为2、2GB,限制CPU、内存限定使用为4、4GB,限制Pod个数为3 等。

我们来尝试创建一个如下定义的Deployment来测试一下,

  1. # 创建一个测试deploy
  2. [root@kmaster ~]# vim quota-test-deploy.yaml
  3. apiVersion: apps/v1
  4. kind: Deployment
  5. metadata:
  6. name: quota-test-deploy
  7. spec:
  8. selector:
  9. matchLabels:
  10. purpose: quota-test
  11. replicas: 3
  12. template:
  13. metadata:
  14. labels:
  15. purpose: quota-test
  16. spec:
  17. containers:
  18. - name: quota-test
  19. image: nginx
  20. resources:
  21. limits:
  22. memory: "2Gi"
  23. cpu: "1"
  24. requests:
  25. memory: "500Mi"
  26. cpu: "500m"
  27. [root@kmaster ~]# kubectl apply -f quota-test-deploy.yaml -n test
  28. # 查看pod
  29. [root@kmaster ~]# kubectl get pod -n test
  30. NAME READY STATUS RESTARTS AGE
  31. quota-test-deploy-6b89fdc686-2dthq 1/1 Running 0 3m54s
  32. quota-test-deploy-6b89fdc686-9m2qw 1/1 Running 0 3m54s
  33. # 查看deploy状态
  34. [root@kmaster ~]# kubectl get deploy quota-test-deploy -n test -o yaml
  35. message: 'pods "quota-test-deploy-6b89fdc686-rmktq" is forbidden: exceeded quota:
  36. quota-test, requested: limits.memory=2Gi, used: limits.memory=4Gi, limited:
  37. limits.memory=4Gi'

replicas: 3定义创建三个Pod副本,但只成功创建了两个Pod,在deploy的status部分(最后一条命令结果),我们可以看到message提示第三个Pod创建时被拒绝,因为内存已达到限定。我们也可以将limits.memory调整为1Gi,将replicas调整为4,来验证对Pod个数的限制。可看到最终只起了三个Pod,status部分message提示 pods "quota-test-deploy-9dc54f95c-gzqw7" is forbidden: exceeded quota:quota-test, requested: pods=1, used: pods=3, limited: pods=3

Resource Limit Range

理解

Resource Quota 是对namespace中总体的资源使用进行限制,Resource Limit Range 则是对具体某个Pod或容器的资源使用进行限制。默认情况下,namespace中Pod或容器的资源消耗是不受限制的,这就可能导致某个容器应用内存泄露耗尽资源影响其它应用的情况。Limit Range可以用来限定namespace内Pod(或容器)可以消耗资源的数量。

使用LimitRange对象,我们可以:

  1. 限制namespace中每个Pod或容器的最小与最大计算资源
  2. 限制namespace中每个Pod或容器计算资源request、limit之间的比例
  3. 限制namespace中每个存储卷声明(PersistentVolumeClaim)可使用的最小与最大存储空间
  4. 设置namespace中容器默认计算资源的request、limit,并在运行时自动注入到容器中

如果创建或更新对象(Pod、容器、PersistentVolumeClaim)对资源的请求与LimitRange相冲突,apiserver会返回HTTP状态码403,以及相应的错误提示信息;如果namespace中定义了LimitRange 来限定CPU与内存等计算资源的使用,则用户创建Pod、容器时,必须指定CPU或内存的request与limit,否则将被系统拒绝;当namespace总的limit小于其中Pod、容器的limit之和时,将发生资源争夺,Pod或者容器将不能创建,但不影响已经创建的Pod或容器。

实践

创建一个测试namespace test-limitrange,

  1. # 创建测试namespace
  2. [root@kmaster ~]# kubectl create namespace test-limitrange
  3. # 切换默认的namespace
  4. [root@kmaster ~]# kubectl config set-context --current --namespace=test-limitrange

创建LimitRange定义文件 lr-test.yaml

  1. apiVersion: v1
  2. kind: LimitRange
  3. metadata:
  4. name: lr-test
  5. spec:
  6. limits:
  7. - type: Container #资源类型
  8. max:
  9. cpu: "1" #限定最大CPU
  10. memory: "1Gi" #限定最大内存
  11. min:
  12. cpu: "100m" #限定最小CPU
  13. memory: "100Mi" #限定最小内存
  14. default:
  15. cpu: "900m" #默认CPU限定
  16. memory: "800Mi" #默认内存限定
  17. defaultRequest:
  18. cpu: "200m" #默认CPU请求
  19. memory: "200Mi" #默认内存请求
  20. maxLimitRequestRatio:
  21. cpu: 2 #限定CPU limit/request比值最大为2
  22. memory: 1.5 #限定内存limit/request比值最大为1.5
  23. - type: Pod
  24. max:
  25. cpu: "2" #限定Pod最大CPU
  26. memory: "2Gi" #限定Pod最大内存
  27. - type: PersistentVolumeClaim
  28. max:
  29. storage: 2Gi #限定PVC最大的requests.storage
  30. min:
  31. storage: 1Gi #限定PVC最小的requests.storage

该文件定义了在namespace test-limitrange 中,容器、Pod、PVC的资源限制,在该namesapce中,只有满足如下条件,对象才能创建成功

  • 容器的resources.limits部分CPU必须在100m-1之间,内存必须在100Mi-1Gi之间,否则创建失败
  • 容器的resources.limits部分CPU与resources.requests部分CPU的比值最大为2,memory比值最大为1.5,否则创建失败
  • Pod内所有容器的resources.limits部分CPU总和最大为2,内存总和最大为2Gi,否则创建失败
  • PVC的resources.requests.storage最大为2Gi,最小为1Gi,否则创建失败

如果容器定义了resources.requests没有定义resources.limits,则LimitRange中的default部分将作为limit注入到容器中;如果容器定义了resources.limits却没有定义resources.requests,则将requests值也设置为limits的值;如果容器两者都没有定义,则使用LimitRange中default作为limits,defaultRequest作为requests值

创建与查看LimitRange,

  1. # 创建LimitRange
  2. [root@kmaster ~]# kubectl apply -f lr-test.yaml
  3. # 查看
  4. [root@kmaster ~]# kubectl describe limits lr-test
  5. Name: lr-test
  6. Namespace: test-limitrange
  7. Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
  8. ---- -------- --- --- --------------- ------------- -----------------------
  9. Container cpu 100m 1 200m 900m 2
  10. Container memory 100Mi 1Gi 200Mi 800Mi 1500m
  11. Pod cpu - 2 - - -
  12. Pod memory - 2Gi - - -
  13. PersistentVolumeClaim storage 1Gi 2Gi - - -

我们可以创建不同配置的容器或Pod对象来验证,出于篇幅不再列出验证步骤。

总结

本文对K8s的Namespace及针对Namespace的资源限制管理ResourceQuota,LimitRange进行了较为深入的探索,其中ResourceQuota对整个Namespace的资源使用情况进行限制,LimitRange则对单个的Pod或容器的资源使用进行限制。Namespace的权限控制可基于RBAC来实现,后续再单独进行梳理介绍。

原文地址:http://blog.jboost.cn/k8s4-namespace.html

相关阅读:

  1. Kubernetes笔记(一):十分钟部署一套K8s环境
  2. Kubernetes笔记(二):了解k8s的基本组件与概念
  3. Kubernetes笔记(三):Gitlab+Jenkins Pipeline+Docker+k8s+Helm自动化部署实践(干货分享!)

作者:雨歌,一枚仍在学习路上的IT老兵

欢迎关注作者公众号:半路雨歌,一起学习成长

Kubernetes笔记(四):详解Namespace与资源限制ResourceQuota,LimitRange的更多相关文章

  1. Kubernetes Pod 驱逐详解

    原文链接:Kubernetes Pod 驱逐详解 在 Kubernetes 中,Pod 使用的资源最重要的是 CPU.内存和磁盘 IO,这些资源可以被分为可压缩资源(CPU)和不可压缩资源(内存,磁盘 ...

  2. Scrapy笔记03- Spider详解

    Scrapy笔记03- Spider详解 Spider是爬虫框架的核心,爬取流程如下: 先初始化请求URL列表,并指定下载后处理response的回调函数.初次请求URL通过start_urls指定, ...

  3. Scrapy笔记04- Selector详解

    Scrapy笔记04- Selector详解 在你爬取网页的时候,最普遍的事情就是在页面源码中提取需要的数据,我们有几个库可以帮你完成这个任务: BeautifulSoup是python中一个非常流行 ...

  4. Kubernetes 部署策略详解-转载学习

    Kubernetes 部署策略详解 参考:https://www.qikqiak.com/post/k8s-deployment-strategies/ 在Kubernetes中有几种不同的方式发布应 ...

  5. Scrapy笔记05- Item详解

    Scrapy笔记05- Item详解 Item是保存结构数据的地方,Scrapy可以将解析结果以字典形式返回,但是Python中字典缺少结构,在大型爬虫系统中很不方便. Item提供了类字典的API, ...

  6. C++游戏服务器编程笔记 IP详解

    C++游戏服务器编程笔记 IP详解 IP详解 INTERNET的历史 上世纪60年底起源于美国 1992年,Internet上的主机超过了100万台 现在已经是现代文明人的必需品    TCP/IP的 ...

  7. 自动化集成:Kubernetes容器引擎详解

    前言:该系列文章,围绕持续集成:Jenkins+Docker+K8S相关组件,实现自动化管理源码编译.打包.镜像构建.部署等操作:本篇文章主要描述Kubernetes引擎用法. 一.基础简介 Kube ...

  8. JavaScript学习笔记-实例详解-类(一)

    实例详解-类(一): //每个javascript函数(除了bind())都自动拥有一个prototype对象// 在未添加属性或重写prototype对象之前,它只包含唯一一个不可枚举属性const ...

  9. [Kubernetes]yaml文件详解

    应前一段时间夸下的海口:[Kubernetes]如何使用yaml文件使得可以向外暴露服务,说过要写一篇关于yaml文件详解的文章出来的,今天来总结一下.yaml文件用在很多地方,但是这里以介绍在Kub ...

随机推荐

  1. 10_CSS入门和高级技巧(8)

    图片透明 先来复习一下盒子的透明问题: opacity:0.6; 介于0~1之间,为了让IE兼容,我们要使用IE自己的滤镜: filter:alpha(opacity=60); 盒子的透明,会让里面的 ...

  2. QtCreator中使用链接库

    说明 之前讨论的DLL的静态链接和动态连接都是基于 MSVC 编译器,但是 MinGW 似乎有另外一套类似但是不相同的机制.下文均在 windows 下使用 Qt Creator 中使用 MinGW ...

  3. [hihoCoder1231 2015BeijingOnline]求圆与多边形公共部分的周长

    题意:如题 思路:离散.将所有交点求出来,相当于将多变形的边切成了很多条元边,对每条元边,有两种情况 在圆内,答案加上此边长 在圆外,答案加上此边相对于圆心的"有向转弧" #inc ...

  4. MySQL 查询当天、本周,本月、上一个月的数据

    mysql查询当天的所有信息: SELECT * FROM 表名 WHERE year(时间字段名)=year(now()) and month(时间字段名) = month(now()) and d ...

  5. Cannot parse "1986-05-04": Illegal instant due to time zone offset transition (Asia/Shanghai)

    调查系统错误时,发现了一个很奇怪的现象,出生日期1986-05-04号的用户始终无法注册.发现后台使用使用jodatime的代码demo如下: public static DateTime parse ...

  6. javaEE ->DBUtils&连接池

    第1章    DBUtils 如果只使用JDBC进行开发,我们会发现冗余代码过多,为了简化JDBC开发,本案例我们讲采用apache commons组件一个成员:DBUtils. DBUtils就是J ...

  7. Spring全家桶之spring boot(二)

    spring boot的两种配置文件: 虽然spring boot可以帮助我们进行一些配置项,但是有些内容还是需要开发者自己进行配置,因此spring boot提供了配置文件以供开发者配置.sprin ...

  8. 数据源管理 | OLAP查询引擎,ClickHouse集群化管理

    本文源码:GitHub·点这里 || GitEE·点这里 一.列式库简介 ClickHouse是俄罗斯的Yandex公司于2016年开源的列式存储数据库(DBMS),主要用于OLAP在线分析处理查询, ...

  9. gRPC负载均衡(自定义负载均衡策略)

    前言 上篇文章介绍了如何实现gRPC负载均衡,但目前官方只提供了pick_first和round_robin两种负载均衡策略,轮询法round_robin不能满足因服务器配置不同而承担不同负载量,这篇 ...

  10. Enjoy the pain about Moloch

    这echo出来的啥子嘛?意思是小姐姐有自虐倾向?可若是moloch有汉化包或翻译文件,小姐姐至于这么“享受”install的过程吗? 过程都走过了,那就记录一下吧:1.找个Ubuntu镜像,阿里云镜像 ...