一、什么是Namespace?
你可以认为namespaces是你kubernetes集群中的虚拟化集群。在一个Kubernetes集群中可以拥有多个命名空间,它们在逻辑上彼此隔离。
他们可以为您和您的团队提供组织,安全甚至性能方面的帮助!
“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
分割成更容易管理的块。
二、Namespace的管理
创建Namespace
不要害怕创建namespace。它不会降低服务的性能,反而大多情况下会提升你的工作效率。创建namespace只需一个很简单的命令。
例如:创建一个名字为:test的namespace,执行:
kind: NamespaceapiVersion: v1metadata:name: testlabels:name: test
然后,执行kubectl apply -f test.yaml
查看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和其他系统默认的命名空间。
在namespace中创建资源
如下是一个简单的 Pod YAML文件:
apiVersion: v1
kind: Pod
metadata:name: mypodlabels:name: mypod
spec:containers:- name: mypodimage: nginx
你会发现没有提到namespace。如果你通过命令kubectl apply
来创建pod,它会在当前的命名空间中创建pod。这个命名空间就是defaut,除非你更改过。
有2种方法来指定资源的namespac
e:
kubectl apply -f pod.yaml --namespace=test
- 在yaml中指定:
apiVersion: v1
kind: Pod
metadata:name: mypodnamespace: testlabels:name: mypod
spec:containers:- name: mypodimage: 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。下面让我们看看如何修正这个“烦恼”。
管理当前激活的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下执行:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
mypod 1/1 Running 0 10m
三、跨namespace通信
命名空间彼此是透明的。但它们并不是绝对相互隔绝但。一个namespace中service可以和另一个namespace中的service通信。这非常有用,比如你团队的一个service要和另外一个团队的service通信,而你们的service都在各自的namespace中。
当你的应用app要访问Kubernetes的service,你可以使用内置的DNS服务发现并把你的app指到Service的名称。然而,你可以在多个namespace中创建同名的service。解决这个问题,就用到DNS地址的扩展形式。
在Kubernetes中,Service通过一个DNS模式来暴露endpoint。这个模式类似:
..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来解决。当然这是另一个话题。
四、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最佳实践剧集,我将向您展示如何锁定命名空间中的资源并为您的群集引入更多安全性和隔离性!