@dujun
2015-02-27T16:32:16.000000Z
字数 6460
阅读 7451
Kubernetes写书
什么是namespace
namespace是一个将Kubernetes的资源对象进行细分的一个类似于DNS子域名的概念。namespace能够帮助不同的租户共享一个Kubernetes集群。Kubernetes引入namespace的目的包括:
与namespace相关的kubectl命令如下所示。
命令 | 含义 |
---|---|
kubectl namespace | 查看当前所处的namespace |
kubectl namespace yourspace | 设置当前的namespace为yourspace |
kubectl get namespaces | 罗列系统当前可用的namespace列表 |
表x kubectl与namespace相关的命令及含义
相关参数有以下这些。
参数 | 含义 |
---|---|
--namespace | 将kubectl命令行请求所能操作的kubernetes对象限定在特定namespace中 |
--ns-path | 记录当前namespace内容的文件路径 |
表x kubectl与namespace相关的参数及含义
Kubernetes系统默认namespace是default
,ns-path
默认是user_home_path/.kubernetes_ns
,该文件内容形如。
{"Namespace":"default"}
事实上,通过命令kubectl namespace space
设置当前namespace为space
就是通过将文件.kubernetes_ns
的内容被改为以下内容来实现的。如果新切换的前namespace不存在,则调用系统API创建该namespace?还是返回一个错误信息。关于创建namespace的一些细节,请参考下文的实践案例。
{"Namespace":"space"}
这样,所有的API操作都被限定在namespace space
中,与其他namespace完全隔离开来。而kubectl namespace
命令查看当前namespace则是通过读取文件.kubernetes_ns
的内容来实现的。
多namespace使用案例
假设有一个资源文件:redis-controller.json
,该json
文件定义了一个replication controller,该replication controller又管理着一个pod。首先,在default
namespace中创建一个名为redisController
的replication controller。
kubectl create -f redis-controller.json --namespace=default
接着,用同样方法在myspace
namespace中创建一个名为redisController2
的replication controller。
kubectl create -f redis-controller2.json --namespace=myspace(如果myspace不存在呢?创建一个新的?必需确定下来!)
创建完毕后,查看系统中的replication controller信息。
$ kubectl get replicationController
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS
redisController redis 10.10.103.215:5000/redis name=redis 1
你会惊奇地发现:replication controller只有一个,即redisController
。那为什么看不到redisController2
呢?原来我们现在处于default
namespace,要看到另外一个则需要切换到我们刚刚自定义的myspace
namespace。
$ kubectl get replicationController --namespace=myspace
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS
redisController2 redis 10.10.103.215:5000/redis name=redis 1
这样,redisController2
就对用户可见。而redisController
则只在default
namespace对用户可见。
$ kubectl get replicationController --namespace=default
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS
redisController redis 10.10.103.215:5000/redis name=redis 1
这样通过在kubectl
命令行添加--namespace
参数,我们就初步实现了客户端对kubernetes资源对象的隔离访问。
事实上,Kubernetes支持namespace隔离的资源对象类型至少包括这几种:pod、service、replicationController、event、endpoints。这一点可以通过查看etcd上/registry
目录便可一目了然,在etcd上进行内容持久化的Kubernetes资源的存储路径如下所示。
/registry/{resourceType}/{resource.Namespace}/{resource.Name}
这样,Kubernetes就可以通过etcd的watch机制监测/registry/{resourceType}
目录下数据的变化来及时发现不同namespace的{resourceType}
的更新。
当将一个pod调度到一个特定的主机上时,该pod在etcd上的存储路径形如:/host/{host}/pod/{pod.Namespace}/{pod.Name}
。
以pod为例。
$ etcdctl ls /registry --recursive
...省略部分输出
/registry/pods
/registry/pods/default
/registry/pods/default/f54759d0-a51f-11e4-91b1-005056b43972
/registry/pods/myspace
/registry/pods/myspace/ac8e6983-a51f-11e4-91b1-005056b43972
以上输出表明,pod分别存在于两个namespace:default
和myspace
,其uid
分别为f54759d0-a51f-11e4-91b1-005056b43972
和ac8e6983-a51f-11e4-91b1-005056b43972
,分别对应于redisController
和redisController2
控制的pod。是的,pod与控制该pod的replication Controller处于同一个namespace中,Kubernetes的controller-manager保证了这一点。另外,不同的namespace中允许存在同名的kubernetes资源对象,这与C++
等支持namespace的编程语言类似。
我们再回头看上面提到的与namespace相关的kubctl命令:kubectl get namespaces
,然后与我们熟悉的kubectl get pods
命令相比较,聪明的读者可能已经猜到了,namespace
也是kubernetes内置的对象类型之一。用户可以通过资源文件来描述一个namespace对象,譬如下面的这个namespace-dev.json
文件,定义了一个名为development
的namespace。
{
"kind": "Namespace",
"apiVersion":"v1beta1",
"id": "development",
"spec": {},
"status": {},
"labels": {
"name": "development"
},
}
与Kubernetes的其他对象一样,我们可以使用kubectl create
来创建该namespace对象。
$ kubectl create -f namespace-dev.json
同理,我们可以用同样的方法创建一个名为production
的namespace。
$ kubectl create -f namespace-prod.json
为了检验上述namespace是否成功创建,罗列系统当前可用的namespace列表。
$ kubectl get namespaces
NAME LABELS
default <none>
development name=development
production name=production
上文提到过,kubectl
命令后面加--namespace
参数会将kubectl
客户端限定在特定namespace中,如果读者觉得每条命令后面都加这么一条尾巴觉得累赘,可以使用下面的步骤来设置kubectl
命令的上下文。
定义kubectl
客户端上下文:dev
和prod
。
$ kubectl config set-context dev --namespace=development
$ kubectl config set-context prod --namespace=production
切换到你希望进行操作的namespace。
$ kubectl config use-context dev
这样,接下来的所有kubectl
客户端操作都被限定在development
namespace中。如果需要查看当前所处的上下文,可以这么做。
$ kubectl config view
clusters: {}
contexts:
dev:
cluster: ""
namespace: development
user: ""
prod:
cluster: ""
namespace: production
user: ""
current-context: dev
preferences: {}
users: {}
是的,我们处于dev
上下文中,同时也被限定在development
namespace中。上面的输出也告诉我们,namespace可以与用户的认证授权机制结合在一起使用。随着Kubernetes认证授权机制开发的深入,可以为不同的namespace提供不同的授权规则。下面我们将简单介绍下Kubernetes namespace与Kubernetes认证授权机制结合使用的原理。
namespace与认证授权机制结合
首先,我们来了解一下Kubernetes集群中的各种用户所扮演的角色。
用户 | 角色 |
---|---|
kubernetes admin | kubernetes集群管理员 |
kubernetes service | kubernetes守护进程(如:controller-manager) |
policy manager | kubernetes集群访问控制规则的制定者 |
kubernetes user | kubernetes集群普通用户 |
表x Kubernetes集群用户及其角色
为了支持namespace的资源隔离,Kubernetes APIServer按如下方式描述资源的地址(URL)。即在URL路径中,资源类型(resourceType)位于namespace(ns)之后。
发起以下资源请求的典型用户是kubernetes user或kubernetes service。
请求类型 | HTTP动作 | 资源路径 | 描述 |
---|---|---|---|
CREATE | POST | /api/{version}/ns/{ns}/{resourceType}/ | 在ns namespace中创建资源resourceType 的实例 |
GET | GET | /api/{version}/ns/{ns}/{resourceType}/{name} | 在ns namespace中获取名为name 的资源resourceType 的实例 |
UPDATE | PUT | /api/{version}/ns/{ns}/{resourceType}/{name} | 在ns namespace中更新名为name 的资源resourceType 的实例 |
DELETE | DELETE | /api/{version}/ns/{ns}/{resourceType}/{name} | 在ns namespace中删除名为name 的资源resourceType 的实例 |
LIST | GET | /api/{version}/ns/{ns}/{resourceType} | 罗列ns namespace中资源resourceType 的实例列表 |
WATCH | GET | /api/{version}/watch/ns/{ns}/{resourceType} | 监测ns namespace中资源resourceType 的变化 |
发起以下资源请求的典型用户是由访问控制规则限定的kubernetes admin或kubernetes service。
请求类型 | HTTP动作 | 资源路径 | 描述 |
---|---|---|---|
WATCH | GET | /api/{version}/watch/{resourceType} | 监测集群所有namespace中资源resourceType 的变化 |
LIST | GET | /api/{version}/list/{resourceType} | 罗列集群所有namespace中资源resourceType 的实例列表 |
下面这些API模式是对default
namespace进行操作的别名(alias)。
请求类型 | HTTP动作 | 资源路径 | 描述 |
---|---|---|---|
CREATE | POST | /api/{version}/{resourceType}/ | 在default namespace中创建资源resourceType 的实例 |
GET | GET | /api/{version}/{resourceType}/{name} | 在default namespace中获取名为name 的资源resourceType 的实例 |
UPDATE | PUT | /api/{version}/{resourceType}/{name} | 在default namespace中更新名为name 的资源resourceType 的实例 |
DELETE | DELETE | /api/{version}/{resourceType}/{name} | 在default namespace中删除名为name 的资源resourceType 的实例 |
以上资源路径/api/{version}/{resourceType}/
等价于/api/{version}/ns/default/{resourceType}/
。
由上可以看出,任意一个Kubernetes资源对象在创建之初便与一个namespace绑定,如果API请求上下文中没有明确指定namespace,则APIServer会为之绑定一个默认namespace(default)。因此,当要创建或更新Kubernetes资源对象时,Kubernetes APIServer的认证授权插件会验证发起API请求的客户端所处的namespace是否与请求url路径中的{ns}
相匹配。如果不匹配,Kubernetes APIServer则会拒绝该API请求。并且,Kubernetes APIServer也支持将访问控制规则与HTTP资源路径和动作绑定。这种将namespace
编码到HTTP资源路径中的设计方案使得外部认证授权插件仅凭资源路径就能够执行相应动作。如果API请求认证授权失败,则该请求到此为止;否则将被转发给APIServer。