什么是MongoDB
MongoDB是一种非关系型数据库管理系统(NoSQL),它被设计用于存储和检索大量数据,特别适用于处理大数据和实时应用程序。MongoDB的名称源自"humongous"(巨大的)这个词,它强调了MongoDB的优势,即能够轻松处理大规模的数据。以下是MongoDB的一些关键特点和概念:
- 非关系型数据存储:与传统的关系型数据库不同,MongoDB不使用表格结构,而是采用文档存储模型。数据以文档的形式存储,通常使用JSON或类似的格式,这使得MongoDB更加灵活,可以存储各种不同结构的数据。
- 高度可扩展:MongoDB是一个分布式数据库系统,可以在多台服务器上运行。它支持水平扩展,可以通过添加更多的服务器来增加存储容量和处理能力,以应对大规模数据和高负载的需求。
- 强大的查询语言:MongoDB提供了丰富的查询和索引功能,使您可以轻松地检索数据、筛选数据和执行聚合操作。
- 高性能:MongoDB的设计目标之一是提供高性能的读写操作。它使用内存映射文件来加速数据访问,同时支持垂直分割和水平分割以提高性能。
- 复制和故障容忍性:MongoDB支持数据复制,可以在多个服务器之间复制数据,以提供冗余和故障容忍性。如果一个服务器出现故障,系统可以自动切换到备用服务器。
- 开源和活跃的社区:MongoDB是开源的,拥有庞大的社区支持和活跃的开发团队。这意味着它不仅免费,还有许多可用的工具和扩展,以满足各种不同的需求。
MongoDB广泛用于各种应用程序,包括Web应用程序、大数据分析、物联网(IoT)应用程序、日志管理和许多其他领域,因为它的灵活性和可扩展性使其适用于各种不同类型的数据存储需求。
实现背景
在实际企业环境中,MongoDB需要多节点部署组成一个集群,可用于确保高可用性、容量扩展、负载均衡和数据备份。此时需要对整个MongoDB集群进行监控,持续关注集群的健康状况。因此我们使用MongoDB Exporter将指标转换为Prometheus的数据类型。最后通过Prometheus进行收集Mongodb集群的监控指标,并采用Grafana可视化。
创建StorageClasses
基于NFS创建StorageClasses,作为Mongodb集群持久化存储。
# 创建StorageClasses
$ kubectl apply -f sc.yml
storageclass.storage.k8s.io/kubesre-nfs created
# 查看StorageClasses
$ kubectl get storageclasses.storage.k8s.io
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
kubesre-nfs example.com/external-nfs Delete Immediate false 63s
standard (default) rancher.io/local-path Delete WaitForFirstConsumer false 13d
MaongoDB集群部署
通过Helm方式进行部署MongoDB集群
# 添加Helm仓库
$ helm repo add bitnami https://charts.bitnami.com/bitnami
"bitnami" has been added to your repositories
# 搜索 MangoDB
$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "higress.io" chart repository
...Successfully got an update from the "bitnami" chart repository
...Successfully got an update from the "ingress-nginx" chart repository
Update Complete. ⎈Happy Helming!⎈
$ helm search repo mongodb
NAME CHART VERSION APP VERSION DESCRIPTION
bitnami/mongodb 13.18.4 6.0.10 MongoDB(R) is a relational open source NoSQL da...
bitnami/mongodb-sharded 6.6.6 6.0.10 MongoDB(R) is an open source NoSQL database tha...
# 将MongoDB Chat下载到本地
$ mkdir mongodb && cd mongodb
$ helm pull bitnami/mongodb
$ tar zxf mongodb-13.18.4.tgz
$ cp mongodb/values.yaml ./values-test.yaml
# 修改values-test.yaml
$ cat values-test.yaml
## 配置文件中定义 storageClass: "",会使用集群配置的 openebs 提供的 storageClass,
## 使用此文档部署,需要自行解决 storageClass 问题 (ceph, nfs, 公有云提供的 nfs)
global:
# 定义 storageClass 使用的类型
storageClass: "nfs-client"
# 定义 mongodb 集群为副本集模式
architecture: replicaset
# 启动集群认证功能,设置超级管理员账户密码
auth:
enabled: true
rootUser: root
rootPassword: "root"
# 设置集群数量,3个
replicaCount: 3
# 启用持久化存储,使用 global.storageClass 自动创建 pvc
persistence:
enabled: true
size: 20Gi
# 安装MongoDB集群
helm install mongodb-cluster mongodb -f ./values-test.yaml
NAME: mongodb-cluster
LAST DEPLOYED: Tue Sep 19 15:54:36 2023
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: mongodb
CHART VERSION: 13.18.4
APP VERSION: 6.0.10
** Please be patient while the chart is being deployed **
MongoDB® can be accessed on the following DNS name(s) and ports from within your cluster:
mongodb-cluster-0.mongodb-cluster-headless.default.svc.cluster.local:27017
mongodb-cluster-1.mongodb-cluster-headless.default.svc.cluster.local:27017
mongodb-cluster-2.mongodb-cluster-headless.default.svc.cluster.local:27017
To get the root password run:
export MONGODB_ROOT_PASSWORD=$(kubectl get secret --namespace default mongodb-cluster -o jsonpath="{.data.mongodb-root-password}" | base64 -d)
To connect to your database, create a MongoDB® client container:
kubectl run --namespace default mongodb-cluster-client --rm --tty -i --restart='Never' --env="MONGODB_ROOT_PASSWORD=$MONGODB_ROOT_PASSWORD" --image docker.io/bitnami/mongodb:6.0.10-debian-11-r0 --command -- bash
Then, run the following command:
mongosh admin --host "mongodb-cluster-0.mongodb-cluster-headless.default.svc.cluster.local:27017,mongodb-cluster-1.mongodb-cluster-headless.default.svc.cluster.local:27017,mongodb-cluster-2.mongodb-cluster-headless.default.svc.cluster.local:27017" --authenticationDatabase admin -u $MONGODB_ROOT_USER -p $MONGODB_ROOT_PASSWORD
# 查看运行状态
$ kubectl get pods | grep mongo
mongodb-cluster-0 1/1 Running 0 17m
mongodb-cluster-1 1/1 Running 0 6m42s
mongodb-cluster-2 1/1 Running 0 4m29s
mongodb-cluster-arbiter-0 1/1 Running 4 (7m51s ago) 20m
MongoDB Exporter 部署
接下来部署Mongodb Exporter:
# 部署Mongodb Exporter
$ cat exporter.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mongo-expoter
spec:
template:
metadata:
labels:
app: mongo-expoter
spec:
containers:
- args:
- '--web.listen-address=:9104'
- '--mongodb.uri'
- >-
mongodb://mongodb-cluster-0.mongodb-cluster-headless.default.svc.cluster.local:27017,mongodb-cluster-1.mongodb-cluster-headless.default.svc.cluster.local:27017,mongodb-cluster-2.mongodb-cluster-headless.default.svc.cluster.local:27017/admin?authSource=admin
image: 'percona/mongodb_exporter:0.39.0'
imagePullPolicy: Always
name: mongo-expoter
resources:
requests:
cpu: 250m
memory: 512Mi
$ kubectl apply -f exporter.yml
# 部署Mongodb Exporter Service
$ cat service.yml
apiVersion: v1
kind: Service
metadata:
name: mongo-exporter
spec:
internalTrafficPolicy: Cluster
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- port: 9104
protocol: TCP
targetPort: 9104
selector:
app: mongo-exporter
type: ClusterIP
$ kubectl apply -f service.yml
到此Exporter部署完毕!
Prometheus安装
接下来需要创建一个Configmap 存储Prometheus 的配置映射:
$ cat prometheus-cm.yml
apiVersion: v1
data:
prometheus.yml: |-
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: "exporter"
static_configs:
- targets: ["mongo-exporter:9104"]
kind: ConfigMap
name: prometheus
$ kubectl apply -f prometheus-cm.yml
# 部署Prometheus
$ cat prometheus.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus
spec:
template:
metadata:
labels:
app: prometheus
name: prometheus-pod
spec:
containers:
- image: prom/prometheus
imagePullPolicy: IfNotPresent
name: prometheus
ports:
- containerPort: 9090
name: metrics
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /etc/prometheus
name: prometheus-config
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 15
volumes:
- configMap:
defaultMode: 420
items:
- key: prometheus.yml
path: prometheus.yml
name: prometheus
name: prometheus-config
# 创建Prometheus Service
$ cat prometheus-service.yml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: '2023-09-19T14:12:15Z'
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
'f:spec':
'f:internalTrafficPolicy': {}
'f:ipFamilyPolicy': {}
'f:ports':
.: {}
'k:{"port":9090,"protocol":"TCP"}':
.: {}
'f:port': {}
'f:protocol': {}
'f:targetPort': {}
'f:selector': {}
'f:sessionAffinity': {}
'f:type': {}
manager: ACK-Console Apache-HttpClient
operation: Update
time: '2023-09-19T14:12:15Z'
name: prometheues
namespace: default
resourceVersion: '531698594'
uid: 0187137d-6805-4179-9981-dfa5481b8d5e
spec:
clusterIP: 172.25.7.25
clusterIPs:
- 172.25.7.25
internalTrafficPolicy: Cluster
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- port: 9090
protocol: TCP
targetPort: 9090
selector:
app: prometheus
sessionAffinity: None
type: ClusterIP
status:
loadBalancer: {}
$ kubectl apply -f prometheus-service.yml
此时可以访问Prometheus控制台了:
Grafana 部署
开始部署Grafana喽:
# 部署Grafana
$ cat grafana.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: grafana
spec:
template:
metadata:
labels:
tool: grafana
name: grafana-pod
spec:
containers:
- image: grafana/grafana
imagePullPolicy: IfNotPresent
name: grafana
ports:
- containerPort: 3000
protocol: TCP
$ kubectl apply -f grafana.yml
# 创建Service
$ cat grafana-service.yml
apiVersion: v1
kind: Service
metadata:
name: grafana
spec:
internalTrafficPolicy: Cluster
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- port: 3000
protocol: TCP
targetPort: 3000
selector:
tool: grafana
sessionAffinity: None
type: ClusterIP
$ kubectl apply -f grafana-service.yml
可视化展示
访问Grafana:默认账户/密码:admin/admin
配置Prometheus数据源:
导入模版查看数据: