Day24 - 为 Kubernetes 应用增添 Database

前言

今天你接到了一份新任务,要求在 Kubernetes 的 NodeJS 应用增添一个 MongoDB ,身为维运人员的你要怎麽做 ?

在 Helm Chart 建置 MongoDB 元件

在之前的章节我们已经将 NodeJS 应用包在 Helm Chart 里面,内容如下

webapp
├── charts
├── Chart.yaml
├── templates
│   ├── deployment.yaml
│   ├── service.yaml
│   └── tests
└── values.yaml

若需要对 Kubernetes 应用增加新功能,可以遵循以下流程

  • 在 Helm Chart 的 templates 里增加所需的 yaml 档案
  • 在 Kubernetes 测试环境检查 Helm Chart 有无问题
  • 将变动更新到 Git Repo ,部属 Stage 以及 Production 环境

万事起头难,一开始要先想好需要创建哪些 yaml 档案,可以简单画个架构图帮助思考。

https://ithelp.ithome.com.tw/upload/images/20210924/20139235M0WiEcYlpu.png

目标很简单,就是创建让 App 可以 Access 到的 Database ,总共有以下 yaml 档案需要创建

  • db-service
    • 让 DB Pod 可以跟外界连线, Type 会设为 clusterIP 使内部可以访问该服务,而外部则无法存取
  • db-pvc
    • PVC ( Persistent Volume Claims ) 是一个存储的请求,若该物件被建立 GCP 会建立一个储存空间
  • db-secret
    • 将资料库帐密存在 Kubernetes 内部,可以做为环境变数将帐密挂到 Pod 上
  • db-deployment
    • 会将 DataBase 的资料路径 Mount 到 Persistent Volume ,当 Pod Crash 掉资料也能保留住
  1. 进入 Cloud Shell 网站

  2. 点击倒三角形->点选专案的 PROJECT_ID,开启专案 Terminal

  1. cd 到 templates 资料夹,建立所需 yaml 档案
cd ~/webapp/templates
touch db-deployment.yaml db-pvc.yaml db-secret.yaml db-service.yaml
  1. 点击左上 Explorer -> Open Folder -> 选择 webapp 资料夹 -> Open

  1. 点击 db-pvc.yaml 档案并贴上以下内容
  • db-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: db-pv-claim
  labels:
    app: mongo
spec:
  accessModes:
    - ReadWriteOnce 
  resources:
    requests:
      storage: 1Gi

PVC 只是对存储空间提出请求,使用上还需要在 deployment 里设定 mount 的方式。

  1. 点击 secret.yaml 档案并贴上以下内容
  • db-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: db-secret
  labels:
    app: mongo
data:
  MONGO_INITDB_ROOT_USERNAME: ZGJ1c2Vy
  MONGO_INITDB_ROOT_PASSWORD: ZGJwYXNzd2Q=

secret 对变数要求 base64 的编码,上述的乱码是由 echo -n "string" | base64 所生成的

  1. 点击 db-deployment.yaml 档案并贴上以下内容
  • db-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}
spec:
  replicas: {{ .Values.app.replicaCount }}
  selector:
    matchLabels:
      app: {{ .Release.Name }}
  template:
    metadata:
      labels:
        app: {{ .Release.Name }}
    spec:
      containers:
        - name: {{ .Release.Name }}
          image: {{ .Values.app.image.repo }}:{{ .Values.app.image.tag }}
          ports:
            - containerPort: 8080
          env:
          - name: MONGO_HOST
            value: mongo
          - name: MONGO_INITDB_ROOT_USERNAME
            valueFrom:
              secretKeyRef:
                name: db-secret
                key: MONGO_INITDB_ROOT_USERNAME
          - name: MONGO_INITDB_ROOT_PASSWORD
            valueFrom:
              secretKeyRef:
                name: db-secret
                key: MONGO_INITDB_ROOT_PASSWORD

这里会建立 PV ,并将 /data/db 路径 Mount 到 PV 上,并且将 Secret 作为环境变数来设定 DB 的帐密。

  1. 点击 deployment.yaml 并在最後新增以下内容

https://ithelp.ithome.com.tw/upload/images/20210924/20139235hAzoI2Br8j.png

          envFrom:
          - secretRef:
              name: db-secret

将 Secret 作为环境变数,让 Application 有 DB 的权限。

  1. 点击 db-service.yaml 档案并贴上以下内容
  • db-service.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: mongo
  name: mongo
spec:
  clusterIP: None
  ports:
  - port: 27017
    targetPort: 27017
  selector:
    app: mongo

这里的 clusterIP 设为 None 是希望 App 能以 Domain Name 去连线

需要的 yaml 档案都已建置完成,新的 Helm Chart 目录内容如下

webapp/
├── charts
├── Chart.yaml
├── templates
│   ├── db-deployment.yaml
│   ├── db-pvc.yaml
│   ├── db-secret.yaml
│   ├── db-service.yaml
│   ├── deployment.yaml
│   ├── service.yaml
│   └── tests
├── values.production.yaml
├── values.stage.yaml
└── values.yaml

测试 Helm Chart

所需的 yaml 档案都已建置完成,就可以部属到测试环境检查。

  1. 使用 Helm Chart 部属应用
cd ~/webapp
helm install webapp-dev .

若之前已经安装好了可以下 helm upgrade webapp-dev . 来更新环境

(输出结果)

NAME: webapp-dev
LAST DEPLOYED: Fri Sep 24 13:54:55 2021
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
  1. 检查 DB 相关元件
kubectl get all -l app=mongo

(输出结果)

NAME                         READY   STATUS    RESTARTS   AGE
pod/mongo-7f6477fbcb-xfmwd   1/1     Running   0          43s

NAME            TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)     AGE
service/mongo   ClusterIP   None         <none>        27017/TCP   46s

NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/mongo   1/1     1            1           46s

NAME                               DESIRED   CURRENT   READY   AGE
replicaset.apps/mongo-7f6477fbcb   1         1         1       44s

看到 Database 成功运行先别高兴太早,还需要测试 App 是否有权限 Access 到 DB。

  1. 查看所有 Pods
kubectl get pods

(输出结果)

NAME                          READY   STATUS    RESTARTS   AGE
mongo-7f6477fbcb-xfmwd        1/1     Running   0          9m13s
webapp-dev-7744f58bf6-hjjdv   1/1     Running   0          9m13s
webapp-dev-7744f58bf6-k25dk   1/1     Running   0          9m13s
webapp-dev-7744f58bf6-zbnfx   1/1     Running   0          9m13s

再来我们下一个特殊的指令,使用 kubectl exec -it <pod name> -- /bin/sh 进入到容器内部,就能直接从内部测试。

  1. 进入到容器内部,并将 <pod name> 改成其中一个 webapp pod 的名称
kubectl exec -it <pod name> -- /bin/sh

看到 /usr/src/app # 就成功进入到容器内部了。

可以先 ping 看看网路有没有通,这里要 ping 的是 db-Service 的名称( mongo )

  1. 测试网路连线
ping mongo -c 3

(输出结果)

PING mongo (10.0.5.6): 56 data bytes
64 bytes from 10.0.5.6: seq=0 ttl=62 time=0.237 ms
64 bytes from 10.0.5.6: seq=1 ttl=62 time=0.220 ms
64 bytes from 10.0.5.6: seq=2 ttl=62 time=0.231 ms

在容器里面是使用 NodeJS 的环境 ,可以使用 mongoose 来测试连线。

  1. 安装 mongoose 套件
npm install mongoose
  1. 建立 test.js 程序
cat > test.js <<EOF
const mongoose = require('mongoose');
const DATABASEURL = "mongodb://${MONGO_INITDB_ROOT_USERNAME}:${MONGO_INITDB_ROOT_PASSWORD}@${MONGO_HOST}:27017/test?authSource=admin"

mongoose.connect(DATABASEURL, {useNewUrlParser: true, useUnifiedTopology: true})
    .then(()=> {
        console.log("CONNECTION SUCCESS!!");
    })
    .catch(err => {
        console.log("ERROR");
        console.log(err);
    })
EOF

这里是测试是否能用环境变数里的帐密连线到 mongo 里面

  1. 执行测试
node test.js

(输出结果)

CONNECTION SUCCESS!!

成功的连线到 mongoDB !!

  1. 输入 Ctrl + c 退出程序

结论

今天以赶火车的速度讲解完如何在 Helm Chart 部属新的元件,以及讲解环境测试的一些实用小技巧,很多细节就没有一一介绍了。


<<:  Day 9 来了fireEvent

>>:  09 - Metrics - 观察系统的健康指标 (3/6) - 使用 Metricbeat 掌握 Infrastructure 的健康状态 Host 篇

【DAY 01】 学习网页的第一步

前言 不管你是不是学程序的,常常都会接触到网页,常常会听到网页就是HTML、CSS和JavaScri...

[Day11] Face Detection - 使用OpenCV & Dlib:Dlib HOG + Linear SVM

不要被标题一堆名词吓到;当你用过它後,你会惊讶它的易用以及,最重要的,无缝接轨辨识人脸关键点 本文...

Day02:咦?啊产品已经上线了,真的要翻新吗

软件开发有个情境或许大家都不陌生: 团队可能接手外包所开发的程序,或是接手团队其他成员所写的程序继续...

Day 03 认识你的消费者

为什麽要建立品牌的搜寻广告活动 让使用者在搜索您的商家时可以直接进到您的商家官网,避免当使用者在搜索...

Episode 6 - BMI 计算机之我会瘦下来的!

范例档案 GitHub Repo: https://github.com/kaochenlong/...