iT邦幫忙

2021 iThome 鐵人賽

DAY 24
0
DevOps

DevOps 好想學!新手也能打造雲端 Study Lab系列 第 24

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: mongo
  labels:
    app: mongo
spec:
  selector: 
    matchLabels:
      app: mongo
  replicas: 1
  template:
    metadata:
      labels:
        app: mongo
    spec:
      containers:
      - image: mongo:latest
        name: mongo
        ports:
        - containerPort: 27017
          name: mongo
        volumeMounts:
        - name: mongo-persistent-storage
          mountPath: /data/db
        envFrom:
        - secretRef:
            name: db-secret
      volumes:
      - name: mongo-persistent-storage 
        persistentVolumeClaim:
          claimName: db-pv-claim

這裡會建立 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 部屬新的元件,以及講解環境測試的一些實用小技巧,很多細節就沒有一一介紹了。


上一篇
Day23 - 有了 CI/CD Pipeline ,還需要合適的 Git Workflow
下一篇
Day25 - 如何安全的把 Kubernetes Secret 儲存到 Git Repository
系列文
DevOps 好想學!新手也能打造雲端 Study Lab30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言