MongoDB 与 Kubernetes 一起运行的最佳实践

前言

Kubernetes 是目前最流行的容器编排平台,而 MongoDB 是最流行的 NoSQL 数据库之一。将 MongoDB 部署在 Kubernetes 上,可以在保持高可用性和可伸缩性的同时,减少运维的复杂性。本篇文章将介绍在 Kubernetes 上运行 MongoDB 的最佳实践。

环境准备

在开始部署 MongoDB 前,需要准备以下环境:

  • Kubernetes 集群
  • 持久化存储(例如,nfs、ceph 等)
  • TLS 证书(可选)

部署 MongoDB

  1. 创建一个 StatefulSet

Kubernetes 提供了 StatefulSet API 对有状态的应用进行管理。一个 MongoDB 部署通常包含多个节点组成的复制集,因此我们将创建一个 StatefulSet,每个 pod 中运行一个 MongoDB 实例。以下是一个 StatefulSet 的 YAML 配置示例:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mongodb
spec:
  serviceName: "mongodb"
  replicas: 3  # 副本数
  selector:
    matchLabels:
      app: mongodb
  template:
    metadata:
      labels:
        app: mongodb
    spec:
      containers:
      - name: mongodb
        image: mongo
        command:
        - mongod
        args:
        - "--bind_ip"
        - "0.0.0.0"
        - "--replSet"
        - "rs0"
        ports:
        - containerPort: 27017
        volumeMounts:
        - name: mongodb-persistent-storage
          mountPath: /data/db
  volumeClaimTemplates:
  - metadata:
      name: mongodb-persistent-storage
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 100Gi
  1. 创建能够自动加入复制集的 ConfigMap

在复制集中,每个实例需要知道其他实例的信息,因此我们需要为每个实例创建一个配置文件。我们可以为每个实例生成一个单独的 YAML 文件,或者创建一个 ConfigMap。

apiVersion: v1
kind: ConfigMap
metadata:
  name: mongodb-config
data:
  mongodb-node1.yml: |-
    storage:
      dbPath: /data/db
    net:
      port: 27017
      bindIp: mongodb-0.mongodb.default.svc.cluster.local
    replication:
      replSetName: rs0
  mongodb-node2.yml: |-
    storage:
      dbPath: /data/db
    net:
      port: 27017
      bindIp: mongodb-1.mongodb.default.svc.cluster.local
    replication:
      replSetName: rs0
  mongodb-node3.yml: |-
    storage:
      dbPath: /data/db
    net:
      port: 27017
      bindIp: mongodb-2.mongodb.default.svc.cluster.local
    replication:
      replSetName: rs0

在以上示例中,我们使用了 ConfigMap 来存储复制集的配置信息,并指定了每个实例的 YAML 配置文件。

  1. 创建一个 Service
apiVersion: v1
kind: Service
metadata:
  name: mongodb
spec:
  selector:
    app: mongodb
  ports:
    - name: mongo
      port: 27017
      targetPort: 27017
  clusterIP: None

以上配置创建了一个 headless service,它不会创建负载均衡器,因为我们直接访问每个 pod 的 IP 地址。我们将通过 Service Name(即 mongodb)进行访问。

  1. 初始化复制集

在 StatefulSet 中创建的 MongoDB 实例还没有加入复制集,需要手动初始化。可以在其中一个实例上执行以下命令:

$ kubectl exec mongodb-0 -- sh -c 'echo "rs.initiate({_id: \"rs0\", members: [{ _id: 0, host: \"mongodb-0.mongodb.default.svc.cluster.local:27017\" },{ _id: 1, host: \"mongodb-1.mongodb.default.svc.cluster.local:27017\" },{ _id: 2, host: \"mongodb-2.mongodb.default.svc.cluster.local:27017\" }]})"|mongo'

以上命令将初始化一个名为 rs0 的复制集,并添加所有实例作为成员。

至此,我们已经成功地在 Kubernetes 中部署了 MongoDB 集群。但这仅仅是一个简单的示例,我们还需要完善它。

使用 TLS

如果您的 MongoDB 数据库包含敏感数据,建议使用 TLS 来加密客户端和服务器之间的通信。以下是一些简单的步骤来为 MongoDB 添加 TLS:

  1. 创建带有自签名证书的 Secret
$ openssl genrsa -out mongodb.key 2048
$ openssl req -new -key mongodb.key -out mongodb.csr
# 填写 CSR 中的信息
$ openssl x509 -req -in mongodb.csr -signkey mongodb.key -out mongodb.crt
$ kubectl create secret tls mongodb-tls --key mongodb.key --cert mongodb.crt

以上命令将生成一个自签名证书,然后用它创建一个 Secret。

  1. 更新 StatefulSet 配置
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mongodb
spec:
  serviceName: mongodb
  replicas: 3
  selector:
    matchLabels:
      app: mongodb
  template:
    metadata:
      labels:
        app: mongodb
    spec:
      containers:
      - name: mongodb
        image: mongo
        command:
        - mongod
        args:
        - "--bind_ip"
        - "0.0.0.0"
        - "--replSet"
        - "rs0"
        - "--sslMode"
        - "requireSSL"
        - "--sslPEMKeyFile"
        - "/etc/ssl/mongodb.pem"
        ports:
        - containerPort: 27017
        volumeMounts:
        - name: mongodb-persistent-storage
          mountPath: /data/db
        - name: mongo-tls
          mountPath: /etc/ssl
  volumeClaimTemplates:
  - metadata:
      name: mongodb-persistent-storage
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 100Gi
  volumeMounts:
  - name: mongo-tls
    readOnly: true
    mountPath: /etc/ssl

在以上配置中,我们添加了一些参数来开启 TLS,并挂载了创建的 Secret。

  1. 更新 Service 配置
apiVersion: v1
kind: Service
metadata:
  name: mongodb
spec:
  selector:
    app: mongodb
  ports:
    - name: mongo
      port: 27017
      targetPort: 27017
      protocol: TCP
  clusterIP: None
  type: LoadBalancer
  loadBalancerIP: 10.0.0.25
  tls:
  - secretName: mongodb-tls
    hosts:
    - mongodb.example.com

在以上配置中,我们添加了以下参数:

  • type:指定 LoadBalancer 类型。
  • loadBalancerIP:指定 LoadBalancer 的 IP 地址。
  • tls:指定使用的 Secret 和主机名。

总结

本篇文章介绍了如何在 Kubernetes 上运行 MongoDB,并添加了 TLS 加密。以上内容只是一个示例,实际场景可能需要更多的配置。通过使用 Kubernetes 和 MongoDB,可以更轻松地管理和扩展数据库,从而提高系统的可用性和灵活性。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65ab1ed3add4f0e0ff4b9777


纠错反馈