当前位置:   article > 正文

k8s实践(5)k8s的命名空间Namespace_k8s创建namespace

k8s创建namespace

一、什么是Namespace?



你可以认为namespaces是你kubernetes集群中的虚拟化集群。在一个Kubernetes集群中可以拥有多个命名空间,它们在逻辑上彼此隔离。 他们可以为您和您的团队提供组织,安全甚至性能方面的帮助!

“default” Namespace
大多数的Kubernetes中的集群默认会有一个叫default的namespace。实际上,应该是3个:

default:你的service和app默认被创建于此。
kube-system:kubernetes系统组件使用。
kube-public:公共资源使用。但实际上现在并不常用。
这个默认(default)的namespace并没什么特别,但你不能删除它。这很适合刚刚开始使用kubernetes和一些小的产品系统。但不建议应用于大型生产系统。因为,这种复杂系统中,团队会非常容易意外地或者无意识地重写或者中断其他服务service。相反,请创建多个命名空间来把你的服务service分割成更容易管理的块。

命名空间主要有两个方面的作用:  k8s命名空间主要用于隔离集群资源、隔离容器等,为集群提供了一种虚拟隔离的策略;

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

二、Namespace查看和创建


 1、查看namesapce

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

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

2、创建namespace

不要害怕创建namespace。它不会降低服务的性能,反而大多情况下会提升你的工作效率。
创建namespace只需一个很简单的命令,例如,创建一个名字为:test的namespace,执行:
kubectl create namespace test
或者使用yaml文件,然后执行kubectl apply -f test.yaml

 #test.yaml:

 kind: Namespace
   apiVersion: v1
   metadata:
      name: test
   labels:
      name: test

查看namespace:kubectl get namespace

会看到test和其他系统默认的命名空间。

三、在namespace中创建资源


如下是一个简单的 Pod YAML文件:

apiVersion: v1
kind: Pod
metadata:
  name: mypod
  labels:
    name: mypod
spec:
  containers:
  - name: mypod
    image: nginx

你会发现没有提到namespace。如果你通过命令kubectl apply 来创建pod,它会在当前的命名空间中创建pod。这个命名空间就是defaut,除非你更改过。
有2种方法来指定资源的namespace:

1、kubectl apply -f pod.yaml --namespace=test
2、在yaml中指定:
apiVersion: v1
kind: Pod
metadata:
  name: mypod
  namespace: test
  labels:
    name: mypod
spec:
  containers:
  - name: mypod
    image: nginx

如果你用命令$ kubectl get pods来查看你的pod,你会得到:资源未找到的错误。
这是因为命令是在当前(default)命名空间中,如果要查看其他namespace资源,你需要指定namespace:

$ kubectl get pods --namespace=test
NAME      READY     STATUS    RESTARTS   AGE
mypod     1/1       Running   0          10s

但是,这很让人烦,每次都要指定namespace。下面让我们看看如何修正这个“烦恼”。

四、管理当前激活的namespace


一开始默认的激活的命名空间是default。因此,当你在其他namespace创建了资源,那么每次使用kubectl命令都要带上namespace将会很痛苦。幸好,神器 kubens 能够解决这个问题。
当你运行kubens命令,它会高亮当前的namespace:
要更换到test空间,运行:kubens test
现在你会看到:

这是,你所有的命令会在这个namespace下执行:

$ kubectl get pods
NAME      READY     STATUS    RESTARTS   AGE
mypod     1/1       Running   0          10m



五、跨namespace通信


1、命名空间彼此是透明的

      命名空间彼此是透明的。但它们并不是绝对相互隔绝但。一个namespace中service可以和另一个namespace中的service通信。这非常有用,比如你团队的一个service要和另外一个团队的service通信,而你们的service都在各自的namespace中。

       我们通常会把mysql,redis,rabbitmq,mongodb这些公用组件放在一个namespace里,或者每个公用组件都有自己的namespace,而你的业务组件会统一放在自己的namespace里,这时就涉及到了跨namespace的数据通讯问题。    
       当你的应用app要访问Kubernetes的service,你可以使用内置的DNS服务发现并把你的app指到Service的名称。然而,你可以在多个namespace中创建同名的service。解决这个问题,就用到 DNS地址的扩展形式。
     在Kubernetes中,Service通过一个DNS模式来暴露endpoint。这个模式类似:
     <Service Name>.<Namespace Name>.svc.cluster.local
      一般情况下,你只需要service的名称,DNS会自动解析到它的全地址。然而,如果你要访问其他namespace中的service,那么你就需要同时使用service名称和namespace名称。例如,你想访问namespace为test中的“database”服务,你可以使用下面的地址:

   database.test
注意⚠️:如果你创建的namespace的名字正好映射到顶级域名,如 “com” 或者 “org”,然后,你创建的service的名称和一个网站名称一样,如 “google” 或者 “baidu”。那么 Kubernetes会拦截到 “google.com” 或者 “baidu.com”的请求并转发到你的service中。
当然,这个技术在测试或者代理功能中非常好用。但请慎重!

如果你不想使namespace相互隔离,你可以使用network policy来解决。当然这是另一个话题。

2、多namespace的service场景

六、资源限制Resource Quota


Kubernetes的资源限制一般是以Namespace为单位进行限制为Namespace限额的方式有两种:ResourceQuota和LimitRange

ResourceQuota 即资源配额,用来限制 namespace 中所有的 Pod 占用的总的资源 request 和 limit 。即限定单个namespace中可使用集群资源的总量,包括两个维度:

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

LimitRange 用来限制 namespace 中 单个Pod 默认资源 request 和 limit。

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

1、对象数量限制

声明格式为: 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

2、计算资源限制

定义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 总和不能超过该值

3、存储资源限制

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

  • 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 的本地临时存储限定的总和不能超过此值

4、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或容器。

5、案例

创建一个测试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值

七、Namespace的粒度


通常大家会问:我应该创建多少个namespace?有什么用?什么是真正的可控的块?创建多了吧,碍事;创建少了吧,你还用不上namespace真正的好处。
我认为,这个答案取决于你的项目或者公司处于什么阶段----从小团队到大公司,各自都有自己的组织结构。根据不同的情况,你可以采用相对的命名空间的策略。

小团队

这种场景下,你一般运作5 - 10 个微服务,很容易做到管理这些服务。这种情况下,你将所有的服务创建在default空间中是合理的。当然你可以创建 “production” 和 “development” 两个空间,但一般情况下,你会在你本地机器上的development环境进行测试,例如使用minikube。

快速增长的团队

这种场景下,你带领一个快速增长的团队运作 10+个微服务。你将团队分成很多子团队负责各自的微服务。但可能每个人都知道整个系统是如何运行的,因此每次变更越来越难以和其他每个人进行确认,而且每个人每天会在自己本地机器运行这个复杂的全栈系统。这时,有必要针对生产环境和开发环境使用多个集群或者命名空间了。每个团队拥有各自的命名空间,这样更容易进行管理。

大公司

在大的公司中,并不是每个人都认识其他人。团队间可能并不清楚各自的机能。微服务间通过service contract(例如gRPC)来通信,并通过service mesh(如istio)来协调通信。
试图在本地运行整个堆栈是不可能的。 强烈建议使用Kubernetes-aware Continuous Delivery系统(例如,Spinnaker)。
此时,每个团队肯定需要自己的命名空间。 每个团队甚至可以选择多个名称空间来运行其开发和生产环境。 设置RBAC和ResourceQuotas也是一个好主意。 多个集群开始显得很有意义,但可能不一定是必要的。

企业

在这种规模下,有些群体甚至不知道其他群体的存在。 某个组也可能是外部公司,服务之间通过标准文档定义的API来通信。 每个小组都有多个拥有一定数量微服务的团队。 这时使用我上面提到的所有工具是必要的。 人们不应该手工部署服务,同时应该被锁定在他们不拥有的命名空间之外。此时,拥有多个集群以减少配置不当的应用程序导致的爆炸半径,以及简化计费和资源管理可能是有意义的。

结论


命名空间可以帮助您组织Kubernetes资源,同时可以提高团队的开发效率。 请继续关注未来的Kubernetes最佳实践剧集,我将向您展示如何锁定命名空间中的资源并为您的群集引入更多安全性和隔离性!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/128332
推荐阅读
相关标签
  

闽ICP备14008679号