在本地的 Kubernetes 环境中搭建 RocketChat(使用 Local Volume)

简而言之

我将在本地的Kubernetes环境中搭建名为RocketChat的类似Slack的开源聊天工具。

在RocketChat中,使用了mongoDB,并且本次使用LocalVolume作为所使用的卷。数据将保存在运行mongoDB的节点的本地存储中,形式简单。

以这种状态来看的话,无法应对节点故障、无法使用mongoDB的副本集(包括复制和自动故障转移功能),等等存在一些问题。不过,本次计划将按照这种方式进行。

稍后,我打算在文章中提到使用NFS而不是LocalVolume的步骤。

构成

将如下步骤在workerNode1上创建用于RocketChat和mongoDB的POD。
在创建之前,请先创建一个NodePort,并在浏览器中通过http连接到Node的IP地址和设置的NodePort上的端口。

local図.PNG

前面提到的条件

操作系统:Ubuntu 16.04.6 LTS

vagrant@master:~$ kubectl version
Client Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.1", GitCommit:"b7394102d6ef778017f2ca4046abbaa23b8
8c290", GitTreeState:"clean", BuildDate:"2019-04-08T17:11:31Z", GoVersion:"go1.12.1", Compiler:"gc", Platform:"linux/amd
64"}
Server Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.2", GitCommit:"66049e3b21efe110454d67df4fa62b08ea7
9a19b", GitTreeState:"clean", BuildDate:"2019-05-16T16:14:56Z", GoVersion:"go1.12.5", Compiler:"gc", Platform:"linux/amd
64"}

创作了SC

首先,我们将创建一个与LocalVolume兼容的StorageClass。

由于LocalVolume不支持动态卷配置功能Dynamic Volume Provisioning,因此无法使用。
因此,如果要使用LocalVolume,则需要选择provisioner为“kubernetes.io/no-provisioner”。

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: local-storage
provisioner: kubernetes.io/no-provisioner

执行结果

vagrant@master:/vagrant/yaml_file$ kubectl create -f sc_chat.yaml
storageclass.storage.k8s.io/local-storage created
vagrant@master:/vagrant/yaml_file$ kubectl get sc
NAME            PROVISIONER                    AGE
local-storage   kubernetes.io/no-provisioner   6s

制作PV和PVC

我们创建 PersistentVolume。
通过 nodeAffinity,将 PV 设置为在 node1 上创建。
访问模式设置为 ReadWriteOnce,可以在单个节点上进行读写操作。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-pv
spec:
  capacity:
    storage: 2Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  local:
    path: /chat_data
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - node1

执行结果

vagrant@master:/vagrant/yaml_file$ kubectl create -f pv_chat.yaml
persistentvolume/local-pv created
vagrant@master:/vagrant/yaml_file$ kubectl get pv -o wide
NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM                STORAGECLASS    REASON   AGE
local-pv   2Gi        RWO            Retain           Available                        local-storage            6s

接下来,我们将创建PersistentVolumeClaim。
在storageClassName中指定我们之前创建的SC的metadata.name。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: local-claim
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: local-storage
  resources:
    requests:
      storage: 2Gi

执行结果

vagrant@master:/vagrant/yaml_file$ kubectl create -f pvc_chat.yaml
persistentvolumeclaim/local-claim created
vagrant@master:/vagrant/yaml_file$ kubectl get pvc
NAME          STATUS   VOLUME     CAPACITY   ACCESS MODES   STORAGECLASS    AGE
local-claim   Bound    local-pv   2Gi        RWO            local-storage   3s

创建一个MongoDB的POD

spec.replicas: 1 で、レプリカセットをシングルノードで作成します。
スタンドアロンモードでの作成も可能ですが、レプリカセットを使うことでトランザクション機能が使用できるようになります。

从4.0版本开始,MongoDB提供了对副本集进行多文档事务处理的能力。
https://docs.mongodb.com/manual/release-notes/4.0/

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mongodb-deployment
spec:
  replicas: 1 #シングルノードで作成
  selector:
    matchLabels:
      app: mondb
  template:
    metadata:
      labels:
        app: mondb
    spec:
      containers:
      - name: mongodb
        image: mongo:4.0.18-xenial
        args: ["--smallfiles","--replSet","rs0","--oplogSize","128"]
        env:
        volumeMounts:
        - name: vol
          mountPath: /data/db
      volumes:
      - name: vol
        persistentVolumeClaim:
          claimName: local-claim

spec.template.spec.containers.argsで指定している引数は以下の通りです。
“–smallfiles”:少ない容量で作成
“–replSet”,”rs0″:レプリカセットをrs0という名前で作成
“–oplogSize”:オペログのサイズ

执行结果

vagrant@master:/vagrant/yaml_file$ kubectl apply -f mongodb.yaml
deployment.apps/mongodb-deployment created
vagrant@master:/vagrant/yaml_file$ kubectl get po -o wide
NAME                                  READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
mongodb-deployment-7b75b6447b-hn5xt   1/1     Running   0          6s    10.244.1.248   node1   <none>           <none>
vagrant@master:/vagrant/yaml_file$ kubectl get deployment -o wide
NAME                 READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES                SELECTOR
mongodb-deployment   1/1     1            1           13s   mongodb      mongo:4.0.18-xenial   app=mondb

初始化MongoDB的复制集

レプリカセットの初期化を行います。
作成したmongoDBのメンバーへ接続し、rs.initiate()コマンドで初期化します。
これを忘れてRocketChatのPODを作成しようとすると、エラーが出て正常に作成できません。

・mongoDBに接続
# mongo 10.244.1.248

・初期化前確認
> rs.status()
{
        "operationTime" : Timestamp(0, 0),
        "ok" : 0,
        "errmsg" : "no replset config has been received",
        "code" : 94,
        "codeName" : "NotYetInitialized",
        "$clusterTime" : {
                "clusterTime" : Timestamp(0, 0),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

・初期化実行
> rs.initiate()
{
        "info2" : "no configuration specified. Using a default configuration for the set",
        "me" : "mongodb-deployment-7b75b6447b-hn5xt:27017",
        "ok" : 1,
        "operationTime" : Timestamp(1588334257, 1),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1588334257, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

・実行後、Enterを押すとプロンプトが変化します。
旧)>
新)rs0:PRIMARY>

・初期化後確認
rs0:PRIMARY> rs.status()
{
        "set" : "rs0",
        "date" : ISODate("2020-05-01T11:57:52.337Z"),
        "myState" : 1,

***長いので省略***

        "members" : [
                {
                        "_id" : 0,
                        "name" : "mongodb-deployment-7b75b6447b-hn5xt:27017",
                        "health" : 1,
                        "state" : 1,
                        "stateStr" : "PRIMARY",
                        "uptime" : 945,
                        "optime" : {
                                "ts" : Timestamp(1588334257, 7),
                                "t" : NumberLong(1)
                        },
                        "optimeDate" : ISODate("2020-05-01T11:57:37Z"),
                        "syncingTo" : "",
                        "syncSourceHost" : "",
                        "syncSourceId" : -1,
                        "infoMessage" : "",
                        "electionTime" : Timestamp(1588334257, 2),
                        "electionDate" : ISODate("2020-05-01T11:57:37Z"),
                        "configVersion" : 1,
                        "self" : true,
                        "lastHeartbeatMessage" : ""
                }
        ],
        "ok" : 1,
        "operationTime" : Timestamp(1588334257, 7),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1588334257, 7),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

创建 Cluster IP

在spec.selector.app中,将mongoDB的spec.selector.matchLabels.app列出。
另外,将spec.ports.port指定为27017。

apiVersion: v1
kind: Service
metadata:
  name: mongodb-service
spec:
  type: ClusterIP
  selector:
    app: mondb
  ports:
  - protocol: TCP
    port: 27017

执行结果

vagrant@master:/vagrant/yaml_file$ kubectl apply -f service_chat.yaml
service/mongodb-service created
vagrant@master:/vagrant/yaml_file$ kubectl get svc -o wide
NAME              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)     AGE    SELECTOR
mongodb-service   ClusterIP   10.244.181.86   <none>        27017/TCP   7s     app=mondb

RocketChatの作成

・MONGO_URL:连接到MongoDB的URL
→ 在spec.template.spec.env.value中设置为mongodb://<ClusterIP服务名>:<ClusterIP端口>/<用于RocketChat的MongoDB数据库名称>。

・根网址:RocketChat的URL
→根据环境的不同可能会有所变化,在这里我们设置为http://localhost:3000/。

・MONGO_OPLOG_URL:用于存储MongoDB的OPLOG
→在spec.template.spec.env.value中设置为mongodb://<ClusterIP的服务名称>:<ClusterIP的端口>/local。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: rocket-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: rocket
  template:
    metadata:
      labels:
        app: rocket
    spec:
      containers:
      - name: rocket
        image: rocket.chat:3.0.12
        ports:
        - containerPort: 3000
        env:
        - name: MONGO_URL
          value: mongodb://mongodb-service:27017/rocket
        - name: ROOT_URL
          value: http://localhost:3000/
        - name: MONGO_OPLOG_URL
          value: mongodb://mongodb-service:27017/local
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: kubernetes.io/hostname
                operator: In
                values:
                - node1

执行结果

vagrant@master:/vagrant/yaml_file$ kubectl apply -f rocketchat.yaml
deployment.apps/rocket-deployment created
vagrant@master:/vagrant/yaml_file$
vagrant@master:/vagrant/yaml_file$ kubectl get deployment -o wide
NAME                 READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES                SELECTOR
mongodb-deployment   1/1     1            1           18m   mongodb      mongo:4.0.18-xenial   app=mondb
rocket-deployment    1/1     1            1           4s    rocket       rocket.chat:3.0.12    app=rocket
vagrant@master:/vagrant/yaml_file$ kubectl get po -o wide
NAME                                  READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
mongodb-deployment-7b75b6447b-hn5xt   1/1     Running   0          18m   10.244.1.248   node1   <none>           <none>
rocket-deployment-77596dcf9f-c9w9z    1/1     Running   0          6s    10.244.1.251   node1   <none>           <none>

确认结果
确认日志后,可以确认服务器正在运行。

vagrant@master:/vagrant/yaml_file$ kubectl logs rocket-deployment-77596dcf9f-c9w9z
Setting default file store to GridFS
LocalStore: store created at
LocalStore: store created at
LocalStore: store created at
ufs: temp directory created at "/tmp/ufs"
Loaded the Apps Framework and loaded a total of 0 Apps!
Updating process.env.MAIL_URL
Using GridFS for custom sounds storage
Using GridFS for custom emoji storage
Browserslist: caniuse-lite is outdated. Please run next command `npm update`
➔ System ➔ startup
➔ +--------------------------------------------------+
➔ |                  SERVER RUNNING                  |
➔ +--------------------------------------------------+
➔ |                                                  |
➔ |  Rocket.Chat Version: 3.0.12                     |
➔ |       NodeJS Version: 12.14.0 - x64              |
➔ |      MongoDB Version: 4.0.18                     |
➔ |       MongoDB Engine: wiredTiger                 |
➔ |             Platform: linux                      |
➔ |         Process Port: 3000                       |
➔ |             Site URL: http://172.16.20.12:3000/  |
➔ |     ReplicaSet OpLog: Enabled                    |
➔ |          Commit Hash: 15ac7670be                 |
➔ |        Commit Branch: HEAD                       |
➔ |                                                  |
➔ +--------------------------------------------------+

创建NodePort

我们将按照以下的指导方针来记录spec.ports。

从Kubernetes的发现和负载均衡资源(第一部分)中引用

spec.ports[x].port            ClusterIPで受け付けるPort番号
spec.ports[x].targetPort      転送先のコンテナのPort番号
spec.ports[x].nodePort        全Kubernetes NodeのIP Adressで受け付けるPort番号

这次我们制作了如下所示的内容。

apiVersion: v1
kind: Service
metadata:
  name: rocket-service
spec:
  type: NodePort
  selector:
    app: rocket
  ports:
  - protocol: TCP
    port: 3000
    targetPort: 3000
    nodePort: 31000

执行结果

vagrant@master:/vagrant/yaml_file$ kubectl apply -f service_nodeport_chat.yaml
service/rocket-service created
vagrant@master:/vagrant/yaml_file$ kubectl get svc -o wide
NAME              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE    SELECTOR
mongodb-service   ClusterIP   10.244.181.86   <none>        27017/TCP        23m    app=mondb
rocket-service    NodePort    10.244.175.43   <none>        3000:31000/TCP   2s     app=rocket

服务连接

我会从浏览器上连接到 http://172.16.20.12:31000/。

image.png
image.png

请以本机汉语进行再创作,请提供一个选项:

・MongoDB相关
在Kubernetes上构建独立的MongoDB服务器的方法
我能理解的系列:MongoDB复制
尝试MongoDB Replica Sets时的备忘录
・RocketChat
官方参考资料
官方安装文档

广告
将在 10 秒后关闭
bannerAds