除了为每个环境创建一个新集群外,您还可以按命名空间或仅在一个命名空间中的不同堆栈来分离部署。最后一种情况(你现在使用的那个)是最容易击中腿部的,因为你必须改变很多东西才能使它孤立。至少您需要一组不同的资源名称(在清单和配置中)和标签来匹配。
在这三种方法中,我认为命名空间分离是最简单的;它适用于基于 DNS 的服务发现。假设您在两个不同的命名空间(例如dev 和prod)中有一个redis 和您的应用程序的副本。应用程序的两个实例都配置为使用redis:6379 的redis。当他们调用 DNS 来解析主机名时,CoreDNS(内部 DNS 服务)会根据请求来自哪个命名空间来响应不同的答案。因此,dev 命名空间中的应用程序将在 dev 命名空间中获得 redis 的 IP 地址,并且来自 prod 命名空间的应用程序将联系来自 prod 命名空间的 redis。此方法不施加任何限制,如果您希望您可以专门使这两个应用程序使用相同的 redis 副本。为此,您必须使用完整的服务 DNS 名称,而不是 redis:6379,如下所示:
redis.<namespace>.svc.cluster.local:6379
无论您选择哪种方法,我强烈建议您熟悉Kustomize、Helm,或两者兼而有之。这些工具旨在帮助您避免重复资源清单,从而减少生成和管理实例的时间。我会给你一个Kustomize 的最小示例,因为它是在kubectl 中构建的。考虑以下目录结构:
.
├── bases
│ └── my-app
│ ├── deployment.yml # your normal deployment manifest
│ └── kustomization.yml
└── instances
├── prod
│ ├── kustomization.yml
│ └── namespace.yml # a manifest that creates 'prod' namespace
└── test
├── kustomization.yml
└── namespace.yml # a manifest that creates 'test' namespace
bases 是您保留应用程序非特定骨架的位置。这并不意味着要部署,就像必须实例化的类一样。 instances 用于描述应用程序的各种实例。实例是用来部署的。
bases/my-app/kustomization.yml:
# which manifests to pick up
resources:
- deployment.yml
instances/prod/kustomization.yml:
# refer what we deploy
bases:
- ../../bases/my-app
resources:
- namespace.yml
# and this overrides namespace attribute for all manifests referenced above
namespace: prod
instances/test/kustomization.yml:
# the same as above, only the namespace is different
bases:
- ../../bases/my-app
resources:
- namespace.yml
namespace: test
现在,如果您进入instances 目录并使用kubectl apply -k prod,您将部署deployment.yml 到prod 命名空间。同样kubectl apply -k test 会将其部署到test 命名空间。
这就是您如何在不同的命名空间中创建应用程序堆栈的多个相同副本的方法。除非涉及来自其他命名空间的一些共享资源,否则它应该是相当隔离的。换句话说,如果您为每个命名空间部署每个组件(例如数据库),并且这些组件未配置为从其他命名空间访问组件 - 它将按预期工作。
我鼓励您阅读更多关于 Kustomize 和 Helm 的内容,因为命名空间覆盖只是它们可以做的基本事情。您可以管理标签、配置、名称、堆栈组件等。