篇首语:本文由编程笔记#小编为大家整理,主要介绍了k8s的进阶--04相关的知识,希望对你有一定的参考价值。在KubernetesRESTAPI中,所有的对象都是通
篇首语:本文由编程笔记#小编为大家整理,主要介绍了k8s的进阶--04相关的知识,希望对你有一定的参考价值。
在Kubernetes REST API 中,所有的对象都是通过 name 和 UID 唯一性确定。对于非唯一用户提供的属性,Kubernetes提供labels。
Names:
Name在一个对象中同一时间只能拥有单个Name,如果对象被删除,也可以使用相同Name创建新的对象,Name用于在资源引用URL中的对象,例如/api/v1/pods/some-name。通常情况,Kubernetes资源的Name能有最长到253个字符(包括数字字符、-和.),但某些资源可能有更具体的限制条件。
可以通过 namespace + name 唯一性地确定一个 RESTFUL 对象,例如:
/api/v1/namespaces/{namespace}/pods/{name}
同一个名称空间下,同一个类型的对象,可以通过 name 唯一性确定。如果删除该对象之后,可以再重新创建一个同名对象。
下面是三种广泛使用的资源名称的限制类型:
DNS Subdomain Names:
绝大部分资源类型的名称必须符合 DNS subdomain 命名规则(参考 https://tools.ietf.org/html/rfc1123):
最长不超过 253个字符
必须由小写字母、数字、减号 -、小数点 . 组成
由字母开始
由字母结束
DNS Label Names:
部分类型的资源要求其名称符合 DNS Label 的命名规则(参考https://tools.ietf.org/html/rfc1123)
(opens new window),具体如下:
最长不超过 63个字符
必须由小写字母、数字、减号 -、小数点 . 组成
由字母开始
由字母结束
Path Segment Names:
部分类型的资源要求其名称可以被编码到路径中。换句话说,名称中不能包含 .、..、/、%。
例如,下面的配置文件定义了一个 name 为 nginx-demo 的 Pod,该 Pod 包含一个 name 为 nginx 的容器:
apiVersion: v1
kind: Pod
metadata:
name: nginx-demo
spec:
containers:
- name: nginx
image: nginx:1.18.1
ports:
- containerPort: 80
UID:
UID 是由 Kubernetes 系统生成的,唯一标识某个 Kubernetes 对象的字符串。
Kubernetes集群中,每创建一个对象,都有一个唯一的 UID。用于区分多次创建的同名对象(如前所述,按照名字删除对象后,重新再创建同名对象时,两次创建的对象 name 相同,但是 UID 不同。)
Kubernetes 中的 UID 是全局唯一的标识符(UUIDs,符合规范 ISO/IEC 9834-8 以及 ITU-T X.667),即它们在空间和时间上是唯一的。
下面引入新的名词:命名空间(namespace)。Kubernetes通过名称空间(namespace)在同一个物理集群上支持多个虚拟集群。
何时使用名称空间呢?
名称空间的用途是,为不同团队的用户(或项目)提供虚拟的集群空间,也可以用来区分开发环境/测试环境、准上线环境/生产环境。
名称空间为 名称 提供了作用域。名称空间内部的同类型对象不能重名,但是跨名称空间可以有同名同类型对象。名称空间不可以嵌套,任何一个Kubernetes对象只能在一个名称空间中。
名称空间可以用来在不同的团队(用户)之间划分集群的资源。
在 Kubernetes 将来的版本中,同名称空间下的对象将默认使用相同的访问控制策略。
当KUbernetes对象之间的差异不大时,无需使用名称空间来区分,例如,同一个软件的不同版本,只需要使用 labels 来区分即可。
如何使用名称空间呢?
查看命名空间:
执行命令 kubectl get namespaces 可以查看名称空间,输出结果如下所示:
NAME STATUS AGE
default Active 4d
kube-system Active 4d
kube-public Active 4d
Kubernetes 安装成功后,默认有初始化了三个名称空间:
default 默认名称空间,如果 Kubernetes 对象中不定义 metadata.namespace 字段,该对象将放在此名称空间下
kube-system Kubernetes系统创建的对象放在此名称空间下
kube-public 此名称空间自动在安装集群是自动创建,并且所有用户都是可以读取的(即使是那些未登录的用户)。主要是为集群预留的,例如,某些情况下,某些Kubernetes对象应该被所有集群用户看到。
在执行请求时设定namespace:
执行 kubectl 命令时,可以使用 --namespace 参数指定名称空间,例如:
kubectl run nginx --image=nginx --namespace=<您的名称空间>
kubectl get pods --namespace=<您的名称空间>
设置名称空间偏好:
可以通过 set-context 命令改变当前 kubectl 上下文 的名称空间,后续所有命令都默认在此名称空间下执行。
kubectl config set-context
kubectl config view
名称空间与DNS:
当您创建一个 Service 时,Kubernetes 为其创建一个对应的 DNS 条目。该 DNS记录的格为 ..svc.cluster.local,也就是说,如果在容器中只使用 ,其DNS将解析到同名称空间下的 Service。这个特点在多环境的情况下非常有用,例如将开发环境、测试环境、生产环境部署在不同的名称空间下,应用程序只需要使用 即可进行服务发现,无需为不同的环境修改配置。如果您想跨名称空间访问服务,则必须使用完整的域名(fully qualified domain name,FQDN)。
执行一下命令可查看哪些 Kubernetes 对象在名称空间里,哪些不在:
kubectl api-resources --namespaced=true
kubectl api-resources --namespaced=false
查看名称空间的概要信息:需要用到describe:
kubectl describe namespaces <name>
kubectl describe namespaces kube-system
输出结果如下所示:
Name: kube-system
Labels:
Annotations:
Status: Active
No resource quota.
No LimitRange resource.
名称空间可能有两种状态(phase):
如何创建名称空间呢?
使用 kubectl 有两种方式可以创建名称空间:
kubectl create namespace <名称空间的名字>
apiVersion: v1
kind: Namespace
metadata:
name: <名称空间的名字>
执行命令
kubectl create -f ./my-namespace.yaml
查看上边创建名称空间的结果:
TIP
名称空间的名字必须与 DNS 兼容:
不能带小数点 .
不能带下划线 _
使用数字、小写字母和减号 - 组成的字符串
名称空间可以定义一个可选项字段 finalizers,在名称空间被删除时,用来清理相关的资源。
WARNING
如果您定义了一个不存在的 finalizer,您仍然可以成功创建名称空间,但是当您删除该名称空间时,将卡在 Terminating 状态。
删除名称空间
执行如下命令可删除名称空间:
kubectl delete namespaces <名称空间的名字>
WARNING
该操作将删除名称空间中的所有内容
此删除操作是异步的,您可能会观察到名称空间停留会在 Terminating 状态停留一段时间。
在创建k8s集群时,默认有个default 名称空间,用来将承载那些未指定名称空间的 Pod、Service、Deployment等对象。
创建新的名称空间
在此练习中,我们将创建两个 Kubernetes 名称空间。
假设企业使用同一个集群作为开发环境和生产环境(注意:通常开发环境和生产环境是物理隔绝的):
开发团队期望有一个集群中的空间,以便他们可以查看查看和使用他们创建的 Pod、Service、Deployment等。在此空间中,Kubernetes对象被创建又被删除,为了适应敏捷开发的过程,团队中的许多人都可以在此空间内做他们想做的事情。
运维团队也期望有一个集群中的空间,在这里,将有严格的流程控制谁可以操作 Pod、Service、Deployment等对象,因为这些对象都直接服务于生产环境。
此时,该企业可以将一个Kubernetes集群切分成两个名称空间:development 和 production。创建名称空间的 yaml 文件如下所示:
apiVersion: v1
kind: Namespace
metadata:
name: development
labels:
name: development
执行命令以创建 development 名称空间:
kubectl create -f dev-namespace.yaml
执行命令以创建 production 名称空间:
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
name: production
kubectl create -f pro-namespace.yaml
执行命令查看已创建的名称空间
kubectl get namespaces --show-labels
输出结果如下所示
NAME STATUS AGE LABELS
default Active 22d
development Active 40s name=development
production Active 19s name=production
在每个名称空间中创建 Pod
Kubernetes名称空间为集群中的 Pod、Service、Deployment 提供了一个作用域。可以限定使用某个名称空间的用户不能看到另外一个名称空间中的内容。我们可以在 development 名称空间中创建一个简单的 Deployment 和 Pod 来演示这个特性。
首先,执行命令以检查当前的 kubectl 上下文
输出结果如下显示:
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://apiserver.lau:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
执行命令
kubectl config current-context
输出结果如下:
kubernetes-admin@kubernetes
接下来,为 kubectl 定义一个上下文,以便在不同的名称空间中工作。cluster 和 user 字段的取值从前面的 current context 复制过来:
kubectl config set-context dev --namespace=development --cluster=kubernetes --user=kubernetes-admin@kubernetes
kubectl config set-context prod --namespace=production --cluster=kubernetes --user=kubernetes-admin@kubernetes
上面的命令创建了两个 kubectl 的上下文,使得您可以在两个不同的名称空间中工作:
切换到 development 名称空间:
kubectl config use-context dev
验证
kubectl config current-context
dev
此时,通过 kubectl 向 Kubernetes 集群发出的所有指令都限定在名称空间 development 里,
创建一个 nginx:
kubectl run nginx-demo --image=nginx:1.18.1 --replicas=3
刚刚创建的 Deployment 副本数为 3,运行了一个 nginx 容器。
输出结果如下
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-demo 3 3 3 3 3m
执行命令
kubectl get pods -l run=nginx-demo
输出结果如下
NAME READY STATUS RESTARTS AGE
nginx-demo-3968820950-9dgr8 1/1 Running 0 3m
nginx-demo-3968820950-vgc4n 1/1 Running 0 3m
nginx-demo-3968820950-7gt5g 1/1 Running 0 3m
此时,开发人员可以做任何他想要做的操作,所有操作都限定在名称空间 development 里,而无需担心影响到 production 名称空间中的内容。
切换到 production 名称空间:
kubectl config use-context prod
production 名称空间应该是空的,下面两个命令将返回的结果都应该为空:
kubectl get deployment
kubectl get pods
此时,我们在 production 名称空间运行另一个 deployment:
kubectl run prod-nginx --image=nginx:1.18.1 --replicas=5
kubectl get deployment
输出结果如下所示:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
prod-nginx 5 5 5 5 10s
执行命令
kubectl get pods -l run=prod-nginx
输出结果如下所示:
NAME READY STATUS RESTARTS AGE
prod-nginx-2263376956-41xy6 1/1 Running 0 34s
prod-nginx-2263376956-kw466 1/1 Running 0 34s
prod-nginx-2263376956-n4v97 1/1 Running 0 34s
prod-nginx-2263376956-p5p3i 1/1 Running 0 34s
prod-nginx-2263376956-sxpth 1/1 Running 0 34s
至此,我们可以了解到,用户在一个名称空间创建的内容对于另外一个名称空间来说是不可见的。也可以为不同的名称空间定义不同的访问权限控制。
为什么需要名称空间
一个Kubernetes集群应该可以满足多组用户的不同需要。Kubernetes名称空间可以使不同的项目、团队或客户共享同一个 Kubernetes 集群。实现的方式是,提供:
每一个用户组都期望独立于其他用户组进行工作。通过名称空间,每个用户组拥有自己的:
可能的使用情况有:
集群管理员通过一个Kubernetes集群支持多个用户组
集群管理员将集群中某个名称空间的权限分配给用户组中的受信任的成员
集群管理员可以限定某一个用户组可以消耗的资源数量,以避免其他用户组受到影响
集群用户可以使用自己的Kubernetes对象,而不会与集群中的其他用户组相互干扰