本文已超过一年。较旧的文章可能包含过时的内容。请检查页面中的信息自发布以来是否已不再正确。

使用 Kubernetes Namespaces 管理环境

Kubernetes 提供的一个优势是能够比传统部署策略更容易、更好地管理各种环境。对于大多数非简单的应用来说,您需要测试、预演 (staging) 和生产环境。您可以在预演和生产环境中使用相同的配置启动独立的资源集群,例如虚拟机,但这可能成本高昂,并且管理环境之间的差异可能很困难。
Kubernetes 包含一个很棒的特性,叫做 [命名空间 (namespaces)][4],它使您能够在同一个集群内管理不同的环境。例如,您可以在同一组机器组成的集群中拥有不同的测试和预演环境,从而可能节省资源。您还可以在同一集群中运行不同类型的服务器、批处理或其他作业,而不必担心它们相互影响。

默认命名空间

在 Kubernetes 中指定命名空间是可选的,因为 Kubernetes 默认使用“default”命名空间。如果您刚创建了一个集群,可以使用此命令检查默认命名空间是否存在

$ kubectl get namespaces
NAME          LABELS    STATUS
default                  Active
kube-system              Active

这里您可以看到默认命名空间存在且处于活动状态。命名空间的状态稍后在关闭和删除命名空间时使用。

创建新的命名空间

您创建命名空间的方式与创建任何其他资源的方式相同。创建一个名为 my-namespace.yaml 的文件并添加以下内容

kind: Namespace  
apiVersion: v1  
metadata:  
 name: my-namespace  
 labels:  
   name: my-namespace  

然后您可以运行此命令创建它

$ kubectl create -f my-namespace.yaml

服务名称

使用命名空间,您可以让您的应用指向静态的服务端点,这些端点不会随环境改变。例如,您的 MySQL 数据库服务在生产和预演环境中都可以命名为 mysql,即使它们运行在同一基础设施上。

这是可行的,因为集群中的每个资源默认只会“看到”同一命名空间中的其他资源。这意味着您可以通过在不同命名空间中创建具有相同名称的 Pod、Service 和 Replication Controller 来避免命名冲突。在命名空间内,服务的短 DNS 名称会解析到该命名空间内服务的 IP 地址。例如,您可能有一个 Elasticsearch 服务,只要访问它的容器位于同一命名空间中,就可以通过 DNS 名称 elasticsearch 进行访问。

您仍然可以通过完整的 DNS 名称访问其他命名空间中的服务,其形式为 SERVICE-NAME.NAMESPACE-NAME。例如,生产环境是 elasticsearch.prod,金丝雀环境是 elasticsearch.canary。

示例

让我们看一个示例应用。假设您想在 Kubernetes 中部署您的音乐商店服务 MyTunes。您可以在同一集群中运行该应用的生产环境和预演环境,以及一些一次性应用。通过运行一些命令,您可以更好地了解情况

~$ kubectl get namespaces  
NAME                    LABELS    STATUS  
default                     Active  
mytunes-prod                Active  
mytunes-staging             Active  
my-other-app                Active  

这里您可以看到一些运行中的命名空间。接下来,让我们列出预演环境中的服务

~$ kubectl get services --namespace=mytunes-staging
NAME          LABELS                    SELECTOR        IP(S)             PORT(S)  
mytunes       name=mytunes,version=1    name=mytunes    10.43.250.14      80/TCP  
                                                        104.185.824.125     
mysql         name=mysql                name=mysql      10.43.250.63      3306/TCP  

接下来检查生产环境

~$ kubectl get services --namespace=mytunes-prod  
NAME          LABELS                    SELECTOR        IP(S)             PORT(S)  
mytunes       name=mytunes,version=1    name=mytunes    10.43.241.145     80/TCP  
                                                        104.199.132.213     
mysql         name=mysql                name=mysql      10.43.245.77      3306/TCP  

请注意,尽管服务的名称本身相同,但根据使用的命名空间不同,IP 地址也会不同。此功能使得配置您的应用变得极其简单——因为您只需要将您的应用指向服务名称即可——并且有可能使您在预演或测试环境中配置您的应用与在生产环境中完全相同。

注意事项

虽然您可以在同一集群中运行预演和生产环境,并通过这样做节省资源和资金,但您需要小心设置资源限制,以免您的预演环境争抢生产环境的 CPU、内存或磁盘资源。正确设置资源限制并测试它们是否正常工作需要大量时间和精力,因此除非您能通过将生产环境与预演或测试环境运行在同一集群中来显著节省资金,否则您可能不太愿意这样做。

无论您是否在同一集群中运行预演和生产环境,命名空间都是在同一集群中对不同应用进行分区的绝佳方式。命名空间也将成为您可以应用资源限制的级别,因此请期待未来在命名空间级别提供更多资源管理功能。