1、namespace概述
你可以认为namespaces是你kubernetes集群中的虚拟化集群。在一个Kubernetes集群中可以拥有多个命名空间,它们在逻辑上彼此隔离。
他们可以为您和您的团队提供组织,安全甚至性能方面的帮助!
2、“default” Namespace
大多数的Kubernetes中的集群默认会有一个叫default的namespace。实际上,应该是3个:
[root@master01 ~]# kubectl get namespace
NAME STATUS AGE
default Active 4d16h
kube-node-lease Active 4d16h
kube-public Active 4d16h
kube-system Active 4d16h
- default:你的service和app默认被创建于此。
- kube-system:kubernetes系统组件使用。
- kube-public:公共资源使用。但实际上现在并不常用。
这个默认(default)的namespace并没什么特别,但你不能删除它。这很适合刚刚开始使用kubernetes和一些小的产品系统。但不建议应用于大型生产系统。因为,这种复杂系统中,团队会非常容易意外地或者无意识地重写或者中断其他服务service。相反,请创建多个命名空间来把你的服务service分割成更容易管理的块。
3、Namespace的管理
(1)创建Namespace
不要害怕创建namespace。它不会降低服务的性能,反而大多情况下会提升你的工作效率。创建namespace只需一个很简单的命令。
//例如:创建一个名字为:test的namespace,执行:
kubectl create namespace test
//或者使用test.yaml文件:
apiVersion: v1
kind: Namespace
metadata:
name: test
labels:
name: test
//然后执行下边语句
kubectl apply -f test.yaml
(2)查看namespace
[root@master01 ~]# kubectl get namespace
NAME STATUS AGE
default Active 4d16h
kube-node-lease Active 4d16h
kube-public Active 4d16h
kube-system Active 4d16h
test Active 6s
会看到test和其他系统默认的命名空间。
(3)在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:
- kubectl apply -f pod.yaml --namespace=test
- 在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:
[root@master01 ~]# kubectl get pods --namespace=test
NAME READY STATUS RESTARTS AGE
mypod 1/1 Running 0 10s
但是,这很让人烦,每次都要指定namespace。下面让我们看看如何修正这个“烦恼”。
(4)管理当前激活的namespace
一开始默认的激活的命名空间是default。因此,当你在其他namespace创建了资源,那么每次使用kubectl命令都要带上namespace将会很痛苦。幸好,神器 kubens 能够解决这个问题。
kubens默认是没有安装的,我们可以通过以下命令安装:
curl -L https://github.com/ahmetb/kubectx/releases/download/v0.9.1/kubens -o /bin/kubens
chmod +x /bin/kubens
当你运行kubens命令,它会高亮当前的namespace。
要更换到test空间,运行:kubens test
[root@master01 ~]# kubens test
Context "kubernetes-admin@kubernetes" modified.
Active namespace is "test".
此时,你所有的命令会在test这个namespace下执行。
4、跨namespace通信
命名空间彼此是透明的。但它们并不是绝对相互隔绝。一个namespace中service可以和另一个namespace中的service通信。这非常有用,比如你团队的一个service要和另外一个团队的service通信,而你们的service都在各自的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名称。例如,你想访问test中的“database”服务,你可以使用下面的地址:
database.test
注意:如果你创建的namespace的名字正好映射到顶级域名,如 “com” 或者“org”,然后,你创建的service的名称和一个网站名称一样,如 “google” 或者 “baidu”。那么Kubernetes会拦截到 “google.com” 或者 “baidu.com”的请求并转发到你的service中。
当然,这个技术在测试或者代理功能中非常好用。但请慎重! 如果你不想使namespace相互隔离,你可以使用network policy来解决。当然这是另一个话题。
5、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资源,同时可以提高团队的开发效率。