介绍
Kubernetes是一个用于在规模上运行现代、集装箱化的应用程序的系统,它允许开发人员在机器群中部署和管理应用程序,虽然它可以用于提高单实例应用程序设置的效率和可靠性,但Kubernetes旨在在在机器群中运行多个应用程序实例。
在使用 Kubernetes 创建多服务部署时,许多开发人员选择使用 Helm包管理器。 Helm 通过提供图表和模板来简化创建多个 Kubernetes 资源的过程,以协调这些对象的交互方式。
在本教程中,您将部署一个 Node.js 应用程序与 MongoDB 数据库到使用 Helm 图表的 Kubernetes 集群中。您将使用 官方 Helm MongoDB 复制图表 创建一个 StatefulSet 对象 由三个 Pods,一个 Headless Service 和三个 PersistentVolumeClaims 组成。您还将创建一个图表以使用自定义应用程序的图像部署多重复制 Node.js 应用程序。您将在本教程中构建的设置将反映在 [Containerizing a Nodejs Application with Docker Compose](L
前提条件
要完成本教程,您将需要:
- 启用了以角色为基础的访问控制(RBAC)的Kubernetes 1.10+集群。 此设置将使用 [ DigitalOcean Kubernetes cluster] (https://www.digitalocean.com/products/kubernetes/] , 但是您可以自由使用 [使用另一种方法创建集群] (https://andsky.com/tech/tutorials/how-to-create-a-kubernetes-1-11-cluster-using-kubeadm-on-ubuntu-18-04)
kubectl
命令行工具安装在您的本地机器或开发服务器上, 并配置到连接您的集群 。 您可以在 [官方文档] (https://kubernetes.io/docs/tasks/tools/install-kubectl/)- 中读取更多关于安装
kubectl
的内容。 安装在本地机器或开发服务器上的Helm,安装在集群上的Tiller,遵循了安装在本地机器或开发服务器上的Helm套件管理器如何在Kubernetes集群上安装软件.( _]* Docker中步骤1和2所概述的方向. 如果您与 Ubuntu 18.04 合作, 请遵循 [如何安装和使用 Ubuntu 18.04 上的 Docker (https://andsky.com/tech/tutorials/how-to-install-and-use-docker-on-ubuntu-18-04) 步骤1 和 2 ; 否则, 请遵循 [正式文件] (https://docs.docker.com/install/) , 以了解安装其他操作系统的信息 。 请务必将您的非根用户添加到docker
组中, 如链接教程的第 2 步所描述的那样 。 ( ) * A [Docker Hub] (https://hub.docker.com/) 账户 。 有关如何设置的概况,请参见[本引言 (https://docs.docker.com/docker-hub/)到多克枢纽.
步骤 1 – 克隆和包装应用程序
但是,在包装应用程序之前,我们需要在应用程序代码中修改 MongoDB 连接 URI以确保我们的应用程序可以连接到我们将使用 Helm mongodb-replicaset
图构建的复制组成员。
我们的第一步是将 node-mongo-docker-dev 存储库从 DigitalOcean Community GitHub 帐户克隆。该存储库包括在 Containerizing a Node.js Application for Development With Docker Compose中描述的设置中的代码,该存储库使用了与 MongoDB 数据库一起的 Node.js 演示应用程序来展示如何使用 Docker Compose 设置开发环境。
将存储库克隆成名为node_project
的目录:
1git clone https://github.com/do-community/node-mongo-docker-dev.git node_project
导航到node_project
目录:
1cd node_project
node_project
目录包含用于使用用户输入的鲨鱼信息应用程序的文件和目录,它已被现代化,以便与容器工作:敏感和特定的配置信息已从应用程序代码中删除,并重构为在运行时注入,并将应用程序的状态下载到MongoDB数据库。
有关设计现代集装箱应用程序的更多信息,请参阅 Kubernetes 的应用程序架构和 Kubernetes 的应用程序现代化。
当我们部署Helmmongodb-replicaset
图表时,它将创建:
- 一个 StatefulSet 对象有三个 Pods - MongoDB 复制组的成员(https://docs.mongodb.com/manual/replication/)。每个 Pod 都会有一个相关的 PersistentVolumeClaim,并在重新安排的情况下保持固定的身份
- 一个 MongoDB 复制组由 StatefulSet 中的 Pods 组成。
为了使我们的应用程序能够与数据库复制品进行交互,我们代码中的 MongoDB 连接 URI 需要包括复制品集成员的主机名以及复制品集本身的名称。
我们克隆的存储库中指定数据库连接信息的文件被称为「db.js」。
1nano db.js
目前,该文件包含在数据库连接 URI 时引用的 常数。 这些常数的值是使用 Node 的 process.env
属性注入的,该属性会返回一个对象,该物体在运行时包含有关您的用户环境的信息。 在我们的应用程序代码中动态设置值使我们能够将代码从底层基础设施中分离开来,这在一个动态、无状态的环境中是必要的。 有关这种方式重构应用程序代码的更多信息,请参阅 Step 2 的 Containerizing a Node.js Application for Development With Docker Compose 和 The 12-Factor App
连接 URI 和 URI 字符串本身的常数目前看起来如下:
1[label ~/node_project/db.js]
2...
3const {
4 MONGO_USERNAME,
5 MONGO_PASSWORD,
6 MONGO_HOSTNAME,
7 MONGO_PORT,
8 MONGO_DB
9} = process.env;
10
11...
12
13const url = `mongodb://${MONGO_USERNAME}:${MONGO_PASSWORD}@${MONGO_HOSTNAME}:${MONGO_PORT}/${MONGO_DB}?authSource=admin`;
14...
按照 12FA 方法,我们不希望将我们的复制实例的主机名或我们的复制集名硬编码到这个 URI 字符串中。 现有的 MONGO_HOSTNAME
常数可以扩展到包括多个主机名 - 我们的复制集的成员 - 因此我们将把它留在原地。
将MONGO_REPLICASET
添加到 URI 常数对象和连接字符串中:
1[label ~/node_project/db.js]
2...
3const {
4 MONGO_USERNAME,
5 MONGO_PASSWORD,
6 MONGO_HOSTNAME,
7 MONGO_PORT,
8 MONGO_DB,
9 MONGO_REPLICASET
10} = process.env;
11
12...
13const url = `mongodb://${MONGO_USERNAME}:${MONGO_PASSWORD}@${MONGO_HOSTNAME}:${MONGO_PORT}/${MONGO_DB}?replicaSet=${MONGO_REPLICASET}&authSource=admin`;
14...
使用 URI 选项部分中的 replicaSet
选项允许我们传输复制件集的名称,这与在 MONGO_HOSTNAME
常数中定义的主机名将允许我们连接到组成员。
保存并关闭文件,当你完成编辑。
随着数据库连接信息被修改以与复制集工作,您现在可以包装应用程序,使用 docker build
命令构建图像,并将其推到 Docker Hub。
用「docker build」和「-t」旗帜构建图像,允许您用令人难忘的名称标记图像,在这种情况下,用您的 Docker Hub 用户名标记图像,并命名它为「node-replicas」或您自己选择的名称:
1docker build -t your_dockerhub_username/node-replicas .
命令中的 .
指定了构建背景是当前目录。
它需要一两分钟才能构建图像.一旦完成,请检查您的图像:
1docker images
您将看到以下结果:
1[secondary_label Output]
2REPOSITORY TAG IMAGE ID CREATED SIZE
3your_dockerhub_username/node-replicas latest 56a69b4bc882 7 seconds ago 90.1MB
4node 10-alpine aa57b0242b33 6 days ago 71MB
接下来,登录您在前提条件下创建的 Docker Hub 帐户:
1docker login -u your_dockerhub_username
当被提示时,请输入您的 Docker Hub 帐户密码. 以此方式登录将创建一个 ~/.docker/config.json
文件,在您的非根用户的主目录中与您的 Docker Hub 凭证。
使用 docker push
命令将应用程序图像推到 Docker Hub。 请记住用自己的 Docker Hub 用户名替换 your_dockerhub_username
:
1docker push your_dockerhub_username/node-replicas
现在你有一个应用程序图像,你可以拉到运行你的复制应用程序与Kubernetes. 下一步将是配置特定的参数,用于MongoDB头盔图表。
步骤 2 — 创建 MongoDB 复制套件的秘密
稳定/mongodb-replicaset
图表在使用秘密时提供了不同的选项,我们将创建两个用于我们的图表部署:
- A Secret for our replica set keyfile将作为复制组成员之间的共享密码,允许他们验证其他成员的身份
- A Secret for our MongoDB admin user, who will be created as a root user on the
admin
database. This role will allow you to create subsequent users with limited permissions when deploying your application to production.
有了这些秘密,我们将能够在专用值文件中设置我们偏好的参数值,并使用 Helm 图表创建 StatefulSet 对象和 MongoDB 复制集。
我们将使用 openssl
命令 与 rand
选项生成一个 756 字节的随机字符串为 keyfile:
1openssl rand -base64 756 > key.txt
该命令生成的输出将被编码为 base64,确保数据传输均匀,并重定向到名为 key.txt 的文件,遵循 [mongodb-replicaset
图表身份验证文档](https://github.com/helm/charts/tree/master/stable/mongodb-replicaset#authentication)中的指南。
现在,您可以使用此文件创建一个名为keyfilesecret
的秘密文件,并使用 kubectl create
:
1kubectl create secret generic keyfilesecret --from-file=key.txt
这将在默认
名称空间中创建一个秘密对象,因为我们没有为我们的设置创建一个特定的名称空间。
您将看到以下输出,表示您的秘密已创建:
1[secondary_label Output]
2secret/keyfilesecret created
删除key.txt
:
1rm key.txt
或者,如果您想保存该文件,请确保 限制其权限并将其添加到您的 .gitignore
文件以使其不受版本控制。
接下来,为您的 MongoDB 管理员用户创建秘密,第一步是将您想要的用户名和密码转换为 base64.
转换您的数据库用户名:
1echo -n 'your_database_username' | base64
记下你在输出中看到的值。
接下来,转换您的密码:
1echo -n 'your_database_password' | base64
在这里也注意输出中的价值。
打开秘密的文件:
1nano secret.yaml
<$>[注]
注: Kubernetes 对象是 通常定义使用 YAML,这严格禁止卡片,并需要两个空格来插入。如果您想检查任何 YAML 文件的格式化,您可以使用 linter或使用创建 kubectl
来测试您的语法的有效性,使用干运行
和验证
旗帜:
1kubectl create -f your_yaml_file.yaml --dry-run --validate=true
一般来说,在使用kubectl
创建资源之前,最好先验证语法
将以下代码添加到文件中,以创建一个秘密,该代码将用您刚刚创建的加密值定义一个用户
和密码
。
1[label ~/node_project/secret.yaml]
2apiVersion: v1
3kind: Secret
4metadata:
5 name: mongo-secret
6data:
7 user: your_encoded_username
8 password: your_encoded_password
在这里,我们正在使用mongodb-replicaset
图表所期待的关键名称:用户
和密码
。我们已经命名了秘密对象mongo-secret
,但您可以随意命名。
保存并关闭文件,当你完成编辑。
使用以下命令创建秘密对象:
1kubectl create -f secret.yaml
您将看到以下结果:
1[secondary_label Output]
2secret/mongo-secret created
再次,您可以删除「secret.yaml」或限制其权限,并将其添加到您的「.gitignore」文件中。
创建秘密对象后,您可以继续指定与mongodb-replicaset
图表一起使用的参数值,并创建 MongoDB 部署。
步骤 3 – 配置 MongoDB 头盔图表并创建部署
Helm 配备了一个被积极维护的存储库,名为 stable,其中包含我们将使用的图表: mongodb-replicaset
. 要使用这个图表与我们刚刚创建的秘密,我们将创建一个名为 `mongodb-values.yaml’的配置参数值的文件,然后使用该文件安装该图表。
我們的「mongodb-values.yaml」檔案將大多反映在「mongodb-replicaset」圖表儲存庫中的默認 values.yaml
檔案。
- 我们将
auth
参数设置为true
,以确保我们的数据库实例以 授权启用开始。这意味着所有客户端将被要求对数据库资源和操作进行身份验证. - 我们将添加有关我们在上一步创建的秘密的信息,以便图表可以使用这些值来创建复制集 keyfile和管理用户 *我们将减少与每个Pod在StatefulSet中相关的持久量,以使用 最小可行的数字海洋区块存储单元,1GB,尽管您可以自由地修改以满足您的存储需求
然而,在写入 mongodb-values.yaml
文件之前,您应该首先检查您是否有 StorageClass 创建并配置为提供存储资源。 您的数据库 StatefulSet 中的每个 Pod 都将具有粘贴的身份和相关的 PersistentVolumeClaim,这将动态地为 Pod 提供一个 PersistentVolume。
由于我们正在使用 DigitalOcean Kubernetes,我们的默认存储类供应商
设置为dobs.csi.digitalocean.com
- DigitalOcean Block Storage - 我们可以通过键入来检查:
1kubectl get storageclass
如果您正在使用 DigitalOcean 集群,您将看到以下输出:
1[secondary_label Output]
2NAME PROVISIONER AGE
3do-block-storage (default) dobs.csi.digitalocean.com 21m
如果您不使用 DigitalOcean 集群,则需要创建 StorageClass 并配置您所选择的供应商
。
现在,您已经确认已配置 StorageClass,请打开mongodb-values.yaml
进行编辑:
1nano mongodb-values.yaml
您将在此文件中设置值,该值将执行以下操作:
- 启用授权
- 引用你的
keyfilesecret
和mongo-secret
对象 - 指定
1Gi
为你的 PersistentVolumes - 将你的复制组名设置为
db
. - 指定
3
复制对组 - 将
mongo
图像插入到写入时的最新版本:4.1.9
.
将以下代码插入到文件中:
1[label ~/node_project/mongodb-values.yaml]
2replicas: 3
3port: 27017
4replicaSetName: db
5podDisruptionBudget: {}
6auth:
7 enabled: true
8 existingKeySecret: keyfilesecret
9 existingAdminSecret: mongo-secret
10imagePullSecrets: []
11installImage:
12 repository: unguiculus/mongodb-install
13 tag: 0.7
14 pullPolicy: Always
15copyConfigImage:
16 repository: busybox
17 tag: 1.29.3
18 pullPolicy: Always
19image:
20 repository: mongo
21 tag: 4.1.9
22 pullPolicy: Always
23extraVars: {}
24metrics:
25 enabled: false
26 image:
27 repository: ssalaues/mongodb-exporter
28 tag: 0.6.1
29 pullPolicy: IfNotPresent
30 port: 9216
31 path: /metrics
32 socketTimeout: 3s
33 syncTimeout: 1m
34 prometheusServiceDiscovery: true
35 resources: {}
36podAnnotations: {}
37securityContext:
38 enabled: true
39 runAsUser: 999
40 fsGroup: 999
41 runAsNonRoot: true
42init:
43 resources: {}
44 timeout: 900
45resources: {}
46nodeSelector: {}
47affinity: {}
48tolerations: []
49extraLabels: {}
50persistentVolume:
51 enabled: true
52 #storageClass: "-"
53 accessModes:
54 - ReadWriteOnce
55 size: 1Gi
56 annotations: {}
57serviceAnnotations: {}
58terminationGracePeriodSeconds: 30
59tls:
60 enabled: false
61configmap: {}
62readinessProbe:
63 initialDelaySeconds: 5
64 timeoutSeconds: 1
65 failureThreshold: 3
66 periodSeconds: 10
67 successThreshold: 1
68livenessProbe:
69 initialDelaySeconds: 30
70 timeoutSeconds: 5
71 failureThreshold: 3
72 periodSeconds: 10
73 successThreshold: 1
持久Volume.storageClass
参数在这里被评论:删除评论并将其值设置为"-
将禁用动态配置.在我们的情况下,因为我们将这个值留下未定义,图表将选择默认的供应商
- 在我们的情况下,dobs.csi.digitalocean.com
。
另外,请注意与持久 Volume
键相关的accessMode
:ReadWriteOnce
意味着提供的卷只会由单个节点读写。
有关文件中包含的其他参数的更多信息,请参阅与 Repo 所包含的 配置表。
保存并关闭文件,当你完成编辑。
在部署mongodb-replicaset
图表之前,您将希望使用helm repo update
命令(https://helm.sh/docs/helm/#helm-repo-update)更新 stable repo:
1helm repo update
这将从 **stable ** 存储库中获取最新的图表信息。
最后,用以下命令安装图表:
1helm install --name mongo -f mongodb-values.yaml stable/mongodb-replicaset
<$>[注]
**注:**在安装图表之前,您可以运行helm install
与--dry-run
和--debug
选项,以检查您发布的生成的宣言:
1helm install --name your_release_name -f your_values_file.yaml --dry-run --debug your_chart
美元
请注意,我们正在命名 Helm release mongo
. 这个名称将指示我们已经指定的配置选项的图表的这个特定的部署。
另外,请注意,由于我们没有将--namespace
的旗帜与helm install
相结合,所以我们的图表对象将被创建在默认
的名称空间中。
一旦您创建了版本,您将看到有关其状态的输出,以及有关创建对象的信息和与它们交互的说明:
1[secondary_label Output]
2NAME: mongo
3LAST DEPLOYED: Tue Apr 16 21:51:05 2019
4NAMESPACE: default
5STATUS: DEPLOYED
6
7RESOURCES:
8==> v1/ConfigMap
9NAME DATA AGE
10mongo-mongodb-replicaset-init 1 1s
11mongo-mongodb-replicaset-mongodb 1 1s
12mongo-mongodb-replicaset-tests 1 0s
13...
您现在可以通过以下命令检查创建您的Pods:
1kubectl get pods
您将看到如下的输出,因为Pods正在创建:
1[secondary_label Output]
2NAME READY STATUS RESTARTS AGE
3mongo-mongodb-replicaset-0 1/1 Running 0 67s
4mongo-mongodb-replicaset-1 0/1 Init:0/3 0 8s
这里的准备
和状态
输出表明,我们StatefulSet中的Pods还没有完全准备好:与Pod的容器相关的Init容器(https://kubernetes.io/docs/concepts/workloads/pods/init-containers/)仍在运行,因为StatefulSet成员是(https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#deployment-and-scaling-guarantees)创建的,所以StatefulSet中的每个Pod必须运行
和准备
才能创建下一个Pod。
一旦 Pod 创建并运行所有相关容器,您将看到此输出:
1[secondary_label Output]
2NAME READY STATUS RESTARTS AGE
3mongo-mongodb-replicaset-0 1/1 Running 0 2m33s
4mongo-mongodb-replicaset-1 1/1 Running 0 94s
5mongo-mongodb-replicaset-2 1/1 Running 0 36s
运行
状态
表示您的 Pod 绑定到节点,并且与这些 Pod 相关的容器正在运行。
<$>[注]
注:
如果您在状态
列中看到意想不到的阶段,请记住,您可以使用以下命令来解决您的Pod:
1kubectl describe pods your_pod
2kubectl logs your_pod
美元
您的 StatefulSet 中的每个 Pods 都有一个名称,将 StatefulSet 名称与 Pod 的 ordinal index 相结合,因为我们创建了三种复制品,我们的 StatefulSet 会员被编号为 0-2,每个会员都有一个 稳定 DNS 输入,由以下元素组成: $(statefulset-name)-$(ordinal).$(服务名称)。
在我们的情况下,由mongodb-replicaset
图表创建的StatefulSet和Headless Service都有相同的名称:
1kubectl get statefulset
1[secondary_label Output]
2NAME READY AGE
3mongo-mongodb-replicaset 3/3 4m2s
1kubectl get svc
1[secondary_label Output]
2NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
3kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 42m
4mongo-mongodb-replicaset ClusterIP None <none> 27017/TCP 4m35s
5mongo-mongodb-replicaset-client ClusterIP None <none> 27017/TCP 4m35s
这意味着我们的StatefulSet的第一个成员将有以下DNS输入:
1mongo-mongodb-replicaset-0.mongo-mongodb-replicaset.default.svc.cluster.local
因为我们需要我们的应用程序连接到每个MongoDB实例,所以我们必须拥有这些信息,以便我们可以直接与Pods通信,而不是与服务。
随着数据库实例的启动和运行,您已经准备好为 Node 应用程序创建图表。
步骤 4 – 创建自定义应用程序图表和配置参数
我们将为我们的 Node 应用程序创建自定义 Helm 图表,并修改标准图表目录中的默认文件,以便我们的应用程序可以与我们刚刚创建的复制片集工作。
首先,创建一个名为nodeapp
的新图表目录,使用以下命令:
1helm create nodeapp
这将创建一个名为nodeapp
的目录,在您的~/node_project
文件夹中使用以下资源:
- 包含您图表的基本信息的
Chart.yaml
文件 - 允许您设置特定参数值的
values.yaml
文件,就像您在 MongoDB 部署中一样 - 包含文件和目录模式的
.helmignore
文件 将被忽视在包装图表时 - 将生成 Kubernetes 表现的模板文件
- 测试文件的 `templates/tests/ directory
- 此图表所依赖的任何图表的 `charts/ directory
我们将从这些默认文件中修改的第一个文件是 values.yaml
.现在打开该文件:
1nano nodeapp/values.yaml
我们将在这里设置的价值观包括:
在我们的情况下,这将是我们在 步骤 1中创建的节点复制品
图像。
*在我们部署图表时,我们将指定 LoadBalancer以创建一个访问点到我们的应用程序进行测试。由于我们正在与DigitalOcean Kubernetes集群合作,这将创建一个 DigitalOcean Load Balancer)。
相反,我们将为 ConfigMap 和 Secret 对象创建模板,并将这些值添加到位于 ~/node_project/nodeapp/templates/deployment.yaml
的应用部署示例中。
在 values.yaml
文件中配置以下值:
1[label ~/node_project/nodeapp/values.yaml]
2# Default values for nodeapp.
3# This is a YAML-formatted file.
4# Declare variables to be passed into your templates.
5
6replicaCount: 3
7
8image:
9 repository: your_dockerhub_username/node-replicas
10 tag: latest
11 pullPolicy: IfNotPresent
12
13nameOverride: ""
14fullnameOverride: ""
15
16service:
17 type: LoadBalancer
18 port: 80
19 targetPort: 8080
20...
保存并关闭文件,当你完成编辑。
接下来,在nodeapp/templates
目录中打开secret.yaml
文件:
1nano nodeapp/templates/secret.yaml
在此檔案中,為您的「MONGO_USERNAME」和「MONGO_PASSWORD」應用程式常數添加值. 這些是您的應用程式在執行時預期可以存取的常數,如在「db.js」中所指明,您的資料庫連接檔案. 當您為這些常數添加值時,請記住使用您在 步驟 2中之前使用的 base64--encoded值,當您創建您的「mongo-secret」對象。
将以下代码添加到文件中:
1[label ~/node_project/nodeapp/templates/secret.yaml]
2apiVersion: v1
3kind: Secret
4metadata:
5 name: {{ .Release.Name }}-auth
6data:
7 MONGO_USERNAME: your_encoded_username
8 MONGO_PASSWORD: your_encoded_password
此秘密对象的名称将取决于您的 Helm 发布的名称,您将在部署应用程序图表时指定该名称。
保存并关闭文件,当你完成。
接下来,打开一个文件,为您的应用程序创建 ConfigMap:
1nano nodeapp/templates/configmap.yaml
在此文件中,我们将定义我们的应用程序所期望的剩余变量:MONGO_HOSTNAME
,MONGO_PORT
,MONGO_DB
和MONGO_REPLICASET
。
根据 Kubernetes 文档,当应用程序实施活力和准备验证时, SRV 记录应用于连接到 Pods. 正如在 步骤 3中讨论的那样,我们的 Pod SRV 记录遵循以下模式: $(statefulset-name)-$(ordinal).$(服务名称).$(namespace).svc.cluster.local. 由于我们的 MongoDB StatefulSet 实施活力和准备验证,我们应该在定义
MONGO_HOSTNAME`变量值时使用这些稳定标识符。
将以下代码添加到文件中,定义MONGO_HOSTNAME
,MONGO_PORT
,MONGO_DB
和MONGO_REPLICASET
变量,您可以为您的MONGO_DB
数据库使用另一个名称,但您的MONGO_HOSTNAME
和MONGO_REPLICASET
值必须如下所示:
1[label ~/node_project/nodeapp/templates/configmap.yaml]
2apiVersion: v1
3kind: ConfigMap
4metadata:
5 name: {{ .Release.Name }}-config
6data:
7 MONGO_HOSTNAME: "mongo-mongodb-replicaset-0.mongo-mongodb-replicaset.default.svc.cluster.local,mongo-mongodb-replicaset-1.mongo-mongodb-replicaset.default.svc.cluster.local,mongo-mongodb-replicaset-2.mongo-mongodb-replicaset.default.svc.cluster.local"
8 MONGO_PORT: "27017"
9 MONGO_DB: "sharkinfo"
10 MONGO_REPLICASET: "db"
因为我们已经创建了StatefulSet对象和复制件集,所以列出的主机名必须在你的文件中列出,就像他们出现在这个示例中一样。如果你摧毁这些对象并更名你的MongoDB Helm版本,那么你需要修改包含在这个 ConfigMap中的值。
另外,请注意,这里列出的值是引用,即 Helm 中环境变量的预期。
保存并关闭文件,当你完成编辑。
随着图表参数值定义,创建秘密和 ConfigMap 示例,您可以编辑应用部署模板以使用环境变量。
步骤 5 – 将环境变量整合到您的头盔部署中
有了我们的应用程序秘密和 ConfigMap 的文件,我们将需要确保我们的应用程序部署可以使用这些值,我们还将定制已经在部署宣言中定义的 活力和准备探测器。
打开应用程序部署模板进行编辑:
1nano nodeapp/templates/deployment.yaml
虽然这是一个 YAML 文件,但Helm 模板使用不同的语法与标准的 Kubernetes YAML 文件,以生成宣言。
在文件中,首先在您的应用程序容器规格中添加一个env
键,下面是imagePullPolicy
键,上面是port
:
1[label ~/node_project/nodeapp/templates/deployment.yaml]
2apiVersion: apps/v1
3kind: Deployment
4metadata:
5...
6 spec:
7 containers:
8 - name: {{ .Chart.Name }}
9 image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
10 imagePullPolicy: {{ .Values.image.pullPolicy }}
11 env:
12 ports:
接下来,将以下键添加到env
变量列表中:
1[label ~/node_project/nodeapp/templates/deployment.yaml]
2apiVersion: apps/v1
3kind: Deployment
4metadata:
5...
6 spec:
7 containers:
8 - name: {{ .Chart.Name }}
9 image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
10 imagePullPolicy: {{ .Values.image.pullPolicy }}
11 env:
12 - name: MONGO_USERNAME
13 valueFrom:
14 secretKeyRef:
15 key: MONGO_USERNAME
16 name: {{ .Release.Name }}-auth
17 - name: MONGO_PASSWORD
18 valueFrom:
19 secretKeyRef:
20 key: MONGO_PASSWORD
21 name: {{ .Release.Name }}-auth
22 - name: MONGO_HOSTNAME
23 valueFrom:
24 configMapKeyRef:
25 key: MONGO_HOSTNAME
26 name: {{ .Release.Name }}-config
27 - name: MONGO_PORT
28 valueFrom:
29 configMapKeyRef:
30 key: MONGO_PORT
31 name: {{ .Release.Name }}-config
32 - name: MONGO_DB
33 valueFrom:
34 configMapKeyRef:
35 key: MONGO_DB
36 name: {{ .Release.Name }}-config
37 - name: MONGO_REPLICASET
38 valueFrom:
39 configMapKeyRef:
40 key: MONGO_REPLICASET
41 name: {{ .Release.Name }}-config
每个变量都包含其值的引用,由秘密值的 secretKeyRef
键或 ConfigMapKeyRef 值的 [`LINK1] 定义,这些键指向我们在前一步创建的秘密和 ConfigMap 文件。
接下来,在端口
键下,修改containerPort
定义,以指定我们应用程序将曝光的容器上的端口:
1[label ~/node_project/nodeapp/templates/deployment.yaml]
2apiVersion: apps/v1
3kind: Deployment
4metadata:
5...
6 spec:
7 containers:
8 ...
9 env:
10 ...
11 ports:
12 - name: http
13 containerPort: 8080
14 protocol: TCP
15 ...
接下来,让我们修改本部署中包含的活力和准备检查,这些检查确保我们的应用程序Pods运行并准备服务流量:
- 准备探测器评估Pod是否准备服务流量,停止所有请求到Pod,直到检查成功
- 活力探测器检查基本应用行为,以确定集装箱中的应用程序是否正在运行和行为如预期。
關於兩者之間的更多資訊,請參閱 相關討論在 Kubernetes 的建築應用程序中。
在我们的情况下,我们将建立在Helm默认提供的httpGet
请求(https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#define-a-liveness-http-request)的基础上,并测试我们的应用程序是否正在接受/sharks
终端上的请求。 kubelet’服务将通过向运行在应用程序Pod的容器中的节点服务器发送一个GET请求来执行探测,并在端口8080
上听取。如果响应的状态代码在200到400之间,那么kubelet
将得出结论,容器是健康的。
将以下修改添加到活力和准备探测器的声明路径
:
1[label ~/node_project/nodeapp/templates/deployment.yaml]
2apiVersion: apps/v1
3kind: Deployment
4metadata:
5...
6 spec:
7 containers:
8 ...
9 env:
10 ...
11 ports:
12 - name: http
13 containerPort: 8080
14 protocol: TCP
15 livenessProbe:
16 httpGet:
17 path: /sharks
18 port: http
19 readinessProbe:
20 httpGet:
21 path: /sharks
22 port: http
保存并关闭文件,当你完成编辑。
您现在已经准备好使用 Helm 创建您的应用程序版本,运行下面的 helm install
命令,其中包括发布名称和图表目录的位置:
1helm install --name nodejs ./nodeapp
请记住,你可以先运行头盔安装
和干运行
和调试
选项,正如在 步骤 3中所讨论的那样,以检查你发布的生成的宣言。
再次,由于我们没有将--namespace
旗帜与helm install
列入,我们的图表对象将被创建在默认
名称空间中。
您将看到以下输出,表示您的发布已经创建:
1[secondary_label Output]
2NAME: nodejs
3LAST DEPLOYED: Wed Apr 17 18:10:29 2019
4NAMESPACE: default
5STATUS: DEPLOYED
6
7RESOURCES:
8==> v1/ConfigMap
9NAME DATA AGE
10nodejs-config 4 1s
11
12==> v1/Deployment
13NAME READY UP-TO-DATE AVAILABLE AGE
14nodejs-nodeapp 0/3 3 0 1s
15
16...
再次,输出将显示发布的状态,以及有关创建对象的信息以及您如何与它们交互。
查看您的 Pods 的状态:
1kubectl get pods
1[secondary_label Output]
2NAME READY STATUS RESTARTS AGE
3mongo-mongodb-replicaset-0 1/1 Running 0 57m
4mongo-mongodb-replicaset-1 1/1 Running 0 56m
5mongo-mongodb-replicaset-2 1/1 Running 0 55m
6nodejs-nodeapp-577df49dcc-b5fq5 1/1 Running 0 117s
7nodejs-nodeapp-577df49dcc-bkk66 1/1 Running 0 117s
8nodejs-nodeapp-577df49dcc-lpmt2 1/1 Running 0 117s
一旦您的 Pods 启动并运行,请检查您的服务:
1kubectl get svc
1[secondary_label Output]
2NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
3kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 96m
4mongo-mongodb-replicaset ClusterIP None <none> 27017/TCP 58m
5mongo-mongodb-replicaset-client ClusterIP None <none> 27017/TCP 58m
6nodejs-nodeapp LoadBalancer 10.245.33.46 your_lb_ip 80:31518/TCP 3m22s
与nodejs-nodeapp
服务相关联的EXTERNAL_IP
是您可以从集群外部访问应用程序的IP地址,如果您在EXTERNAL_IP
列中看到<pending>
状态,则意味着您的负载平衡器仍在创建中。
一旦你在该列中看到一个IP,在你的浏览器中导航到它: http://your_lb_ip
。
你应该看到下面的登陆页面:
现在你的复制应用程序正在工作,让我们添加一些测试数据,以确保复制在复制集成员之间工作。
步骤6:测试MongoDB复制
随着我们的应用程序运行并通过外部 IP 地址访问,我们可以添加一些测试数据,并确保它在我们的 MongoDB 复制组成员之间复制。
首先,请确保您已将浏览器导航到应用程序定位页面:
点击获取鲨鱼信息
按钮,您将看到一个页面,其中可以输入鲨鱼的名称和鲨鱼的一般性质描述:
在表格中,添加您所选择的初始鲨鱼。 为了示范,我们将Megalodon Shark
添加到 Shark Name字段,并将Ancient
添加到 Shark Character字段:
点击提交
按钮,您将看到一个页面,其中有这些鲨鱼信息向您显示:
现在回到鲨鱼信息表格,点击上面的导航栏中的 Sharks:
输入你选择的新鲨鱼. 我们将与鲸鲨
和大鲨鱼
一起去:
点击提交
后,您将看到新鲨鱼已被添加到您的数据库中的鲨鱼收藏中:
让我们检查我们输入的数据是否在我们的复制集的主要和次要成员之间复制。
获取您的 Pods 列表:
1kubectl get pods
1[secondary_label Output]
2NAME READY STATUS RESTARTS AGE
3mongo-mongodb-replicaset-0 1/1 Running 0 74m
4mongo-mongodb-replicaset-1 1/1 Running 0 73m
5mongo-mongodb-replicaset-2 1/1 Running 0 72m
6nodejs-nodeapp-577df49dcc-b5fq5 1/1 Running 0 5m4s
7nodejs-nodeapp-577df49dcc-bkk66 1/1 Running 0 5m4s
8nodejs-nodeapp-577df49dcc-lpmt2 1/1 Running 0 5m4s
若要在您的 Pods 上访问 mongo
shell,您可以使用 kubectl exec
命令和您在 步骤 2中创建您的'mongo-secret' 的用户名。
1kubectl exec -it mongo-mongodb-replicaset-0 -- mongo -u your_database_username -p --authenticationDatabase admin
当被提示时,输入与此用户名相关的密码:
1[secondary_label Output]
2MongoDB shell version v4.1.9
3Enter password:
您将被扔进一个行政壳:
1[secondary_label Output]
2MongoDB server version: 4.1.9
3Welcome to the MongoDB shell.
4...
5
6db:PRIMARY>
虽然提示本身包含此信息,但您可以手动检查使用 rs.isMaster()
方法的复制组成员是主要的:
1rs.isMaster()
您将看到输出如下,显示主机的主机名称:
1[secondary_label Output]
2db:PRIMARY> rs.isMaster()
3{
4 "hosts" : [
5 "mongo-mongodb-replicaset-0.mongo-mongodb-replicaset.default.svc.cluster.local:27017",
6 "mongo-mongodb-replicaset-1.mongo-mongodb-replicaset.default.svc.cluster.local:27017",
7 "mongo-mongodb-replicaset-2.mongo-mongodb-replicaset.default.svc.cluster.local:27017"
8 ],
9 ...
10 "primary" : "mongo-mongodb-replicaset-0.mongo-mongodb-replicaset.default.svc.cluster.local:27017",
11 ...
接下来,切换到您的sharkinfo
数据库:
1use sharkinfo
1[secondary_label Output]
2switched to db sharkinfo
列出数据库中的收藏:
1show collections
1[secondary_label Output]
2sharks
将文件输出到收藏中:
1db.sharks.find()
您将看到以下结果:
1[secondary_label Output]
2{ "_id" : ObjectId("5cb7702c9111a5451c6dc8bb"), "name" : "Megalodon Shark", "character" : "Ancient", "__v" : 0 }
3{ "_id" : ObjectId("5cb77054fcdbf563f3b47365"), "name" : "Whale Shark", "character" : "Large", "__v" : 0 }
退出 MongoDB 壳:
1exit
现在我们已经检查了我们的主要数据,让我们检查它是否被复制到次要的. kubectl exec
到 mongo-mongodb-replicaset-1
用以下命令:
1kubectl exec -it mongo-mongodb-replicaset-1 -- mongo -u your_database_username -p --authenticationDatabase admin
一旦进入管理壳,我们将需要使用 db.setSlaveOk()
方法来允许从次要实例读取操作:
1db.setSlaveOk(1)
转到sharkinfo
数据库:
1use sharkinfo
1[secondary_label Output]
2switched to db sharkinfo
允许在鲨鱼
收藏中读取文件的操作:
1db.setSlaveOk(1)
将文件输出到收藏中:
1db.sharks.find()
您现在应该看到您在主实例上运行此方法时看到的相同信息:
1[secondary_label Output]
2db:SECONDARY> db.sharks.find()
3{ "_id" : ObjectId("5cb7702c9111a5451c6dc8bb"), "name" : "Megalodon Shark", "character" : "Ancient", "__v" : 0 }
4{ "_id" : ObjectId("5cb77054fcdbf563f3b47365"), "name" : "Whale Shark", "character" : "Large", "__v" : 0 }
此输出确认您的应用数据正在复制您的复制组成员之间。
结论
您现在已经在使用 Helm 图表的 Kubernetes 集群上部署了复制的、高度可用的鲨鱼信息应用程序. 此演示应用程序和本教程中描述的工作流程可以作为一个起点,当您为您的应用程序构建自定义图表并利用 Helm 的 stable 存储库和 其他图表存储库。
当您向生产前进时,请考虑实施以下措施:
- ** 集中伐木和监测**。 请参看[更新Kubernetes的应用程序(https://andsky.com/tech/tutorials/modernizing-applications-for-kubernetes)中的相关讨论,以了解概况。 也可以研究[如何在Kubernetes上设置弹性搜索、流利和基巴纳(EFK)记录堆栈(https://andsky.com/tech/tutorials/how-to-set-up-an-elasticsearch-fluentd-and-kibana-efk-logging-stack-on-kubernetes),以学习如何用弹性搜索、流利地和Kibana设置伐木堆栈。 另请检查服务网点介绍,了解Istio等服务网点如何实施此功能。 () ( )* ** 入侵资源通往您的集群**。 这在您正在运行多个服务时(每个服务都需要自己的LoadBalancer),或者您想要实施应用级的路由策略(例如A/B & 金丝雀测试)的情况下,是一个很好的替代品. 欲了解更多信息,请查看DigitalOcean Kubernetes上的Nginx Engress与Cert-Manager一起设置一个Nginx Engress,以及服务Meshes介绍中服务网上路由的相关讨论*。 ** Kubernetes对象的备份策略**。 关于使用DigitalOcean的Kubernetes产品Verero(原为Heptio Ark)实施备份的指导意见,请参见[How To back up and recover a Kubernetes Cluster on DigitalOcean Upping Heptio Ark] (https://andsky.com/tech/tutorials/how-to-back-up-and-restore-a-kubernetes-cluster-on-digitalocean-using-heptio-ark). (). (英语)
有关 Helm 的更多信息,请参阅 介绍 Kubernetes 的 Helm 包管理器, 如何使用 Helm 包管理器在 Kubernetes 集群上安装软件,以及 Helm 文档。