作者选择了 多样性在技术基金作为 写给捐款计划的一部分接受捐款。
介绍
Pulumi是一款用于创建、部署和管理基础设施的工具,使用代码编写在通用编程语言中。它支持自动化所有DigitalOcean的管理服务,如Droplets、管理数据库、DNS记录和Kubernetes集群,除了应用程序配置之外。
Pulumi 支持多种语言,但在本教程中,您将使用 TypeScript,使用 Node.js运行时间的 JavaScript的静态打字版本。
在本教程中,您将提供一个DigitalOcean Kubernetes集群,一个负荷均衡的Kubernetes应用程序,以及一个DigitalOcean DNS域,使您的应用程序在您选择的稳定域名中可用。所有这些都可以提供60行基础设施代码和单个pulumi up
命令行手势。
如果您正在寻找一个管理的Kubernetes托管服务,请查看我们的简单的,用于增长的管理的Kubernetes服务(https://www.digitalocean.com/products/kubernetes)。
前提条件
要遵循本教程,您将需要:
如果你已经没有一个, 注册这里。
- A DigitalOcean API Token to perform automated deployments. Generate a personal access token here并保持方便,因为你将在步骤2中使用它,所以你将需要创建并使用Kubernetes群集,你将需要 安装
kubectl
不要担心进一步配置它 - 你会这样做以后。 - 你会写你的基础设施-as-code在TypeScript中,所以你需要Node.js 8或更晚。 下载这里或安装它使用你的系统包管理器的名称(https://nodejs.org/en/download/package-manager/)。 MBRK1 * 您将使用Pulumi的部署来
步骤 1 - 创建一个新的项目
第一步是创建一个目录,该目录将包含基础设施定义的源代码,以及描述项目及其NPM依赖的元数据文件。
首先,创建目录:
1mkdir do-k8s
接下来,进入新创建的目录:
1cd do-k8s
从现在开始,从新创建的do-k8s
目录中运行命令。
接下来,创建一个新的Pulumi项目有不同的方法来实现这一点,但最简单的方法是使用pulumi new
命令与typescript
项目模板一起使用。
1pulumi new typescript -y
在这里,您已将-y
选项转移到新
命令,该命令告诉它接受默认项目选项,例如,项目名称是从当前目录的名称中提取的,所以将是do-k8s
。
运行命令后,列出目录的内容为ls
:
1ls
以下文件现在将存在:
1[secondary_label Output]
2Pulumi.yaml index.ts node_modules
3package-lock.json package.json tsconfig.json
您将编辑的主要文件是 index.ts
. 虽然本教程只使用这个单个文件,但您可以通过使用 Node.js 模块以任何您认为合适的方式组织您的项目。 该教程还描述了一次性的一个步骤,利用Pulumi 能够检测并逐步部署只发生了变化。
现在你已经准备好了你的新项目,你已经准备好添加需要遵循教程的依赖。
步骤二:增加依赖性
下一步是在 DigitalOcean 和 Kubernetes 套件上安装并添加依赖性,首先使用 NPM 来安装它们:
1npm install @pulumi/digitalocean @pulumi/kubernetes
这将下载NPM包,Pulumi插件,并将其保存为依赖。
接下来,用你最喜欢的编辑器打开index.ts
文件,本教程将使用nano:
1nano index.ts
取代您的index.ts
的内容如下:
1[label index.ts]
2import * as digitalocean from "@pulumi/digitalocean";
3import * as kubernetes from "@pulumi/kubernetes";
例如,如果您使用理解 TypeScript 和 Node.js 的 IDE 键入digitalocean
。
添加内容后保存和关闭文件。
<$>[注]
注: 我们将使用这些包中可用的子集。 有关资源、属性和相关API的完整文档,请参阅 @pulumi/digitalocean
和 pulumi/kubernetes
包的相关API文档。
<$>
接下来,您将配置您的 DigitalOcean 代币,以便 Pulumi 在您的帐户中提供资源:
1pulumi config set digitalocean:token YOUR_TOKEN_HERE --secret
注意--秘密
旗帜,它使用Pulumi的加密服务来加密你的代币,确保它存储在cyphertext中. 如果你喜欢,你可以使用DIGITALOCEAN_TOKEN
环境变量,但你需要记住每次更新你的程序时设置它,而使用配置会自动存储并用于你的项目。
在此步骤中,您添加了必要的依赖,并与Pulumi配置了您的API代币,以便您可以提供您的Kubernetes集群。
步骤 3 – 提供 Kubernetes 集群
现在你已经准备好创建一个DigitalOcean Kubernetes集群了. 通过重新打开‘index.ts’文件开始:
1nano index.ts
将这些行添加到您的 index.ts 文件的末尾:
1[label index.ts]
2...
3const cluster = new digitalocean.KubernetesCluster("do-cluster", {
4 region: digitalocean.Regions.SFO2,
5 version: "latest",
6 nodePool: {
7 name: "default",
8 size: digitalocean.DropletSlugs.DropletS2VPCU2GB,
9 nodeCount: 3,
10 },
11});
12
13export const kubeconfig = cluster.kubeConfigs[0].rawConfig;
此新代码分配了一个digitalocean.KubernetesCluster
的实例,并为其设置了一些属性。 其中包括使用sfo2
区域 slug,Kubernetes的最新的
支持版本,s-2vcpu-2gb
Droplet 尺寸 slug,并表示您想要的三个 Droplet 实例的数目。 请勿对这些实例进行任何更改,但请注意,DigitalOcean Kubernetes在本文写作时仅在某些地区提供。 您可以参阅 产品文档有关区域可用性的最新信息。
有关您可以在集群中配置的所有属性的完整列表,请参阅 KubernetesCluster
API 文档。
该代码片段的最后一行将导出结果的 Kubernetes 集群的 kubeconfig
文件,使其易于使用。
现在你已经准备好部署你的集群了,要做到这一点,运行pulumi up
:
1pulumi up
此命令会执行程序,生成创建所描述的基础设施的计划,并执行一系列步骤来部署这些更改。
1[secondary_label Output]
2Previewing update (dev):
3
4 Type Name Plan
5 + pulumi:pulumi:Stack do-k8s-dev create
6 + └─ digitalocean:index:KubernetesCluster do-cluster create
7
8Resources:
9 + 2 to create
10
11Do you want to perform this update?
12 yes
13> no
14 details
这意味着更新将创建一个名为Do-cluster
的Kubernetes集群。Yes/No/Details
提示允许我们确认这是在实际进行任何更改之前所需的结果。
1[secondary_label Output]
2Updating (dev):
3
4 Type Name Status
5 + pulumi:pulumi:Stack do-k8s-dev created
6 + └─ digitalocean:index:KubernetesCluster do-cluster created
7
8Outputs:
9 kubeconfig: "..."
10
11Resources:
12 + 2 created
13
14Duration: 6m5s
15
16Permalink: https://app.pulumi.com/.../do-k8s/dev/updates/1
创建集群需要几分钟,但然后它将启动并运行,并将完整的kubeconfig
打印到控制台上。
1pulumi stack output kubeconfig > kubeconfig.yml
然后用kubectl
来执行任何Kubernetes命令:
1KUBECONFIG=./kubeconfig.yml kubectl get nodes
您将收到类似于以下的输出:
1[secondary_label Output]
2NAME STATUS ROLES AGE VERSION
3default-o4sj Ready <none> 4m5s v1.14.2
4default-o4so Ready <none> 4m3s v1.14.2
5default-o4sx Ready <none> 3m37s v1.14.2
在此时,您已经设置了基础设施作为代码,并有可重复的方式来创建和配置新的DigitalOcean Kubernetes集群. 在下一步,您将建立在这个基础设施中,以代码定义Kubernetes基础设施,并学习如何以类似的方式部署和管理它们。
步骤 4 – 部署应用程序到您的集群
接下来,您将描述使用基础设施代码的Kubernetes应用程序的配置,这将由三个部分组成:
一个供应商
对象,该对象告诉Pulumi将Kubernetes资源部署到DigitalOcean群集中,而不是默认配置的任何kubectl
来使用。
2. A Kubernetes部署,这是Kubernetes的标准方式来部署在任何数量的Pod上复制的Docker容器图像。
这是一个相当标准的 _reference 架构,用于在 Kubernetes 中运行负载均衡服务。
要部署这三种,请重新打开您的 index.ts 文件:
1nano index.ts
打开文件后,将此代码附加到文件的末尾:
1[label index.ts]
2...
3const provider = new kubernetes.Provider("do-k8s", { kubeconfig })
4
5const appLabels = { "app": "app-nginx" };
6const app = new kubernetes.apps.v1.Deployment("do-app-dep", {
7 spec: {
8 selector: { matchLabels: appLabels },
9 replicas: 5,
10 template: {
11 metadata: { labels: appLabels },
12 spec: {
13 containers: [{
14 name: "nginx",
15 image: "nginx",
16 }],
17 },
18 },
19 },
20}, { provider });
21const appService = new kubernetes.core.v1.Service("do-app-svc", {
22 spec: {
23 type: "LoadBalancer",
24 selector: app.spec.template.metadata.labels,
25 ports: [{ port: 80 }],
26 },
27}, { provider });
28
29export const ingressIp = appService.status.loadBalancer.ingress[0].ip;
此代码类似于标准的Kubernetes配置,对象及其属性的行为相当,但它与其他基础设施声明一起写在TypeScript中。
保存并关闭文件后进行更改。
就像以前一样,运行pulumi up
来预览,然后部署更改:
1pulumi up
选择是
后,CLI 会打印详细的状态更新,包括有关 Pod 可用性的诊断、IP 地址分配等。
完整的输出将看起来像这样的东西:
1[secondary_label Output]
2Updating (dev):
3
4 Type Name Status
5 pulumi:pulumi:Stack do-k8s-dev
6 + ├─ pulumi:providers:kubernetes do-k8s created
7 + ├─ kubernetes:apps:Deployment do-app-dep created
8 + └─ kubernetes:core:Service do-app-svc created
9
10Outputs:
11 + ingressIp : "157.230.199.202"
12
13Resources:
14 + 3 created
15 2 unchanged
16
17Duration: 2m52s
18
19Permalink: https://app.pulumi.com/.../do-k8s/dev/updates/2
完成此操作后,请注意所需数量的Pod正在运行:
1KUBECONFIG=./kubeconfig.yml kubectl get pods
1[secondary_label Output]
2NAME READY STATUS RESTARTS AGE
3do-app-dep-vyf8k78z-758486ff68-5z8hk 1/1 Running 0 1m
4do-app-dep-vyf8k78z-758486ff68-8982s 1/1 Running 0 1m
5do-app-dep-vyf8k78z-758486ff68-94k7b 1/1 Running 0 1m
6do-app-dep-vyf8k78z-758486ff68-cqm4c 1/1 Running 0 1m
7do-app-dep-vyf8k78z-758486ff68-lx2d7 1/1 Running 0 1m
类似于该程序如何导出集群的kubeconfig
文件,该程序还导出由 Kubernetes 服务产生的负载平衡器的 IP 地址。
1curl $(pulumi stack output ingressIp)
1[secondary_label Output]
2<!DOCTYPE html>
3<html>
4<head>
5<title>Welcome to nginx!</title>
6<style>
7 body {
8 width: 35em;
9 margin: 0 auto;
10 font-family: Tahoma, Verdana, Arial, sans-serif;
11 }
12</style>
13</head>
14<body>
15<h1>Welcome to nginx!</h1>
16<p>If you see this page, the nginx web server is successfully installed and
17working. Further configuration is required.</p>
18
19<p>For online documentation and support please refer to
20<a href="http://nginx.org/">nginx.org</a>.<br/>
21Commercial support is available at
22<a href="http://nginx.com/">nginx.com</a>.</p>
23
24<p><em>Thank you for using nginx.</em></p>
25</body>
26</html>
从这里,您可以轻松编辑和重新部署您的应用基础设施,例如,尝试更改复制: 5
行,说复制: 7
,然后重复pulumi up
:
1pulumi up
注意,它只显示了发生了什么变化,并且选择细节显示了准确的差异:
1[secondary_label Output]
2Previewing update (dev):
3
4 Type Name Plan Info
5 pulumi:pulumi:Stack do-k8s-dev
6 ~ └─ kubernetes:apps:Deployment do-app-dep update [diff: ~spec]
7
8Resources:
9 ~ 1 to update
10 4 unchanged
11
12Do you want to perform this update? details
13 pulumi:pulumi:Stack: (same)
14 [urn=urn:pulumi:dev::do-k8s::pulumi:pulumi:Stack::do-k8s-dev]
15 ~ kubernetes:apps/v1:Deployment: (update)
16 [id=default/do-app-dep-vyf8k78z]
17 [urn=urn:pulumi:dev::do-k8s::kubernetes:apps/v1:Deployment::do-app-dep]
18 [provider=urn:pulumi:dev::do-k8s::pulumi:providers:kubernetes::do-k8s::80f36105-337f-451f-a191-5835823df9be]
19 ~ spec: {
20 ~ replicas: 5 => 7
21 }
现在您既有完全功能的 Kubernetes 集群,也拥有一个工作应用程序. 随着应用程序的启动和运行,您可能想要配置一个自定义域以与应用程序一起使用。
步骤 5 — 创建 DNS 域名(可选)
虽然Kubernetes集群和应用程序正在运行,但应用程序的地址取决于集群自动分配IP地址的诱惑。当你调整和重新部署东西时,这个地址可能会发生变化。
<$>[注] 注: 要完成此步骤,请确保您拥有使用 DigitalOcean 的 DNS 名称服务器的域名:ns1.digitalocean.com、ns2.digitalocean.com 和ns3.digitalocean.com。
要配置 DNS,请打开 index.ts 文件,并将下列代码附加到文件的末尾:
1[label index.ts]
2...
3const domain = new digitalocean.Domain("do-domain", {
4 name: "your_domain",
5 ipAddress: ingressIp,
6});
此代码会创建一个新的 DNS 条目,其中包含一个 A 条目,该条目指向您的 Kubernetes 服务的 IP 地址。
通常,需要额外的子域,如www
,指向 Web 应用程序. 这是很容易实现的,使用一个 DigitalOcean DNS 记录. 为了使这个例子更有趣,还添加一个CNAME
记录,指向www.your_domain.com
到your_domain.com
:
1[label index.ts]
2...
3const cnameRecord = new digitalocean.DnsRecord("do-domain-cname", {
4 domain: domain.name,
5 type: "CNAME",
6 name: "www",
7 value: "@",
8});
保存并关闭这些更改后的文件。
最后,运行pulumi up
来部署 DNS 更改,以指向您的现有应用程序和群集:
1[secondary_label Output]
2Updating (dev):
3
4 Type Name Status
5 pulumi:pulumi:Stack do-k8s-dev
6 + ├─ digitalocean:index:Domain do-domain created
7 + └─ digitalocean:index:DnsRecord do-domain-cname created
8
9Resources:
10 + 2 created
11 5 unchanged
12
13Duration: 6s
14
15Permalink: https://app.pulumi.com/.../do-k8s/dev/updates/3
在 DNS 更改扩散后,您将能够在自定义域访问您的内容:
1curl www.your_domain.com
您将收到类似于以下的输出:
1[secondary_label Output]
2<!DOCTYPE html>
3<html>
4<head>
5<title>Welcome to nginx!</title>
6<style>
7 body {
8 width: 35em;
9 margin: 0 auto;
10 font-family: Tahoma, Verdana, Arial, sans-serif;
11 }
12</style>
13</head>
14<body>
15<h1>Welcome to nginx!</h1>
16<p>If you see this page, the nginx web server is successfully installed and
17working. Further configuration is required.</p>
18
19<p>For online documentation and support please refer to
20<a href="http://nginx.org/">nginx.org</a>.<br/>
21Commercial support is available at
22<a href="http://nginx.com/">nginx.com</a>.</p>
23
24<p><em>Thank you for using nginx.</em></p>
25</body>
26</html>
通过此,您已成功设置了一个新的DigitalOcean Kubernetes集群,部署了一个负载平衡的Kubernetes应用程序,并给该应用程序的负载平衡器一个使用DigitalOcean DNS的稳定域名,所有在60行代码和一个pulumi up
命令。
下一步将引导您删除资源,如果您不再需要它们。
步骤 6 — 删除资源(可选)
在完成教程之前,您可能想要摧毁上述所有资源,这将确保您不会为未使用的资源收取费用。
运行以下命令来摧毁资源. 要小心使用这个,因为它不能被取消!
1pulumi destroy
与上
命令一样,摧毁
在采取行动之前会显示预览和提示:
1[secondary_label Output]
2Previewing destroy (dev):
3
4 Type Name Plan
5 - pulumi:pulumi:Stack do-k8s-dev delete
6 - ├─ digitalocean:index:DnsRecord do-domain-cname delete
7 - ├─ digitalocean:index:Domain do-domain delete
8 - ├─ kubernetes:core:Service do-app-svc delete
9 - ├─ kubernetes:apps:Deployment do-app-dep delete
10 - ├─ pulumi:providers:kubernetes do-k8s delete
11 - └─ digitalocean:index:KubernetesCluster do-cluster delete
12
13Resources:
14 - 7 to delete
15
16Do you want to perform this destroy?
17 yes
18> no
19 details
假设这是你想要的,选择是
并观看删除发生:
1[secondary_label Output]
2Destroying (dev):
3
4 Type Name Status
5 - pulumi:pulumi:Stack do-k8s-dev deleted
6 - ├─ digitalocean:index:DnsRecord do-domain-cname deleted
7 - ├─ digitalocean:index:Domain do-domain deleted
8 - ├─ kubernetes:core:Service do-app-svc deleted
9 - ├─ kubernetes:apps:Deployment do-app-dep deleted
10 - ├─ pulumi:providers:kubernetes do-k8s deleted
11 - └─ digitalocean:index:KubernetesCluster do-cluster deleted
12
13Resources:
14 - 7 deleted
15
16Duration: 7s
17
18Permalink: https://app.pulumi.com/.../do-k8s/dev/updates/4
此时,没有剩下任何东西: DNS 条目已经消失,Kubernetes 集群以及内部运行的应用程序已经消失了。永久链接仍然可用,因此您仍然可以返回并查看此堆栈的完整更新历史记录。
如果您想摧毁整个项目,请删除堆栈:
1pulumi stack rm
您将收到输出,要求您通过键入堆栈名称来确认删除:
1[secondary_label Output]
2This will permanently remove the 'dev' stack!
3Please confirm that this is what you'd like to do by typing ("dev"):
与删除命令不同,该命令删除云基础设施资源,删除堆栈完全从Pulumi的预览中删除您的堆栈的完整历史。
结论
在本教程中,您已部署了DigitalOcean基础设施资源,包括具有A和CNAME记录的Kubernetes集群和DNS域,以及使用该集群的Kubernetes应用程序配置。
从这里开始,你可以采取以下几个步骤:
- 探索由Pulumi支持的完整的DigitalOcean资源集.
- 探索Pulumi对Kubernetes应用程序的支持,包括常见架构.
- 触发器自动部署与CI/CD和Git工作流集成
- 使你的程序的某些元素可配置如 例子做,到 促进更大的项目和多堆方法 (如开发,测试,舞台制作)。
本教程的全部样本可在GitHub上找到(https://github.com/do-community/pulumi-kubernetes)。 有关如何在今天的项目中使用Pulumi基础设施作为代码的详细信息,请查看 Pulumi 文档, 教程,或 Getting Started指南。