> ## Documentation Index
> Fetch the complete documentation index at: https://ayakaleaf-pro.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# 3. Triển khai MongoDB và Redis

> Chạy MongoDB dưới dạng replica set và Redis với lưu trữ bền vững, hoặc trỏ tới các dịch vụ của riêng bạn.

Ayakaleaf Pro cần:

* **MongoDB 8** dưới dạng một **replica set** (nó sử dụng transaction). Ba thành viên trải trên ba node có thể chịu được việc mất một node; một thành viên duy nhất cũng hoạt động được.
* **Redis 7**, một máy chủ với lưu trữ bền vững AOF. Redis chứa các chỉnh sửa chưa được ghi vào MongoDB, các phiên, và các thông điệp giữa các dịch vụ Overleaf. Overleaf kết nối tới một máy chủ Redis duy nhất: Sentinel và Redis Cluster không được hỗ trợ.

> [!NOTE]
>
> Bạn có thể dùng các dịch vụ được quản lý thay thế, chẳng hạn MongoDB Atlas hoặc Redis của nhà cung cấp đám mây. Hãy bỏ qua trang này và đặt `OVERLEAF_MONGO_URL` và `OVERLEAF_REDIS_HOST` trỏ tới chúng ở [bước 4](https://ayakaleaf-pro.mintlify.site/vi/on-premises/installation/using-kubernetes/4.-personalizing-your-instance.md).

**1. MongoDB**

```yaml title="10-mongo.yaml" wrap theme={null}
apiVersion: v1
kind: Service
metadata:
  name: mongo
  namespace: overleaf
spec:
  clusterIP: None                 # headless: gives mongo-0.mongo, mongo-1.mongo, ...
  publishNotReadyAddresses: true  # members must resolve each other before the set is initiated
  selector:
    app: mongo
  ports:
    - name: mongo
      port: 27017
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mongo
  namespace: overleaf
spec:
  serviceName: mongo
  replicas: 3
  selector:
    matchLabels:
      app: mongo
  template:
    metadata:
      labels:
        app: mongo
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchLabels:
                  app: mongo
              topologyKey: kubernetes.io/hostname
      containers:
        - name: mongo
          image: mongo:8.0
          args:
            - --replSet=overleaf
            - --bind_ip_all
            - --wiredTigerCacheSizeGB=0.25   # default is 50% of (RAM - 1 GB); size it for your nodes
          # env:
          #   - name: GLIBC_TUNABLES        # only on kernel 6.19+ (SERVER-121912)
          #     value: glibc.pthread.rseq=1
          ports:
            - containerPort: 27017
          readinessProbe:
            tcpSocket:
              port: 27017
          resources:
            requests:
              cpu: 100m
              memory: 384Mi
            limits:
              memory: 768Mi
          volumeMounts:
            - name: data
              mountPath: /data/db
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: [ReadWriteOnce]
        resources:
          requests:
            storage: 5Gi
---
# Initiates the replica set once. Safe to re-run: it does nothing when the set exists.
apiVersion: batch/v1
kind: Job
metadata:
  name: mongo-init-replica-set
  namespace: overleaf
spec:
  backoffLimit: 20
  template:
    spec:
      restartPolicy: OnFailure
      containers:
        - name: init
          image: mongo:8.0
          command:
            - mongosh
            - --quiet
            - --host=mongo-0.mongo
            - --eval
            - |
              try {
                rs.status()
                print('replica set already initiated')
              } catch (e) {
                rs.initiate({
                  _id: 'overleaf',
                  members: [
                    { _id: 0, host: 'mongo-0.mongo.overleaf.svc.cluster.local:27017' },
                    { _id: 1, host: 'mongo-1.mongo.overleaf.svc.cluster.local:27017' },
                    { _id: 2, host: 'mongo-2.mongo.overleaf.svc.cluster.local:27017' },
                  ],
                })
              }
```

```bash theme={null}
kubectl apply -f 10-mongo.yaml
kubectl -n overleaf rollout status statefulset/mongo
kubectl -n overleaf wait --for=condition=complete job/mongo-init-replica-set --timeout=5m
kubectl -n overleaf exec mongo-0 -- mongosh --quiet --eval 'rs.status().members.map(m => m.name + " " + m.stateStr)'
```

Sau vài giây, một thành viên sẽ là `PRIMARY` và các thành viên còn lại là `SECONDARY`. Job sẽ thử lại cho đến khi tất cả các thành viên phản hồi, vì vậy việc có vài pod Job thất bại là bình thường.

* Service headless cần `publishNotReadyAddresses: true`: các thành viên phải tìm thấy nhau theo tên trước khi replica set tồn tại.
* Các thành viên được thêm vào bằng tên ổn định của chúng (`mongo-0.mongo.overleaf.svc.cluster.local`), không bao giờ dùng IP của pod, vốn thay đổi sau mỗi lần khởi động lại.
* Với một thành viên duy nhất, hãy đặt `replicas: 1` và chỉ giữ lại `mongo-0` trong Job.

**2. Redis**

```yaml title="20-redis.yaml" wrap theme={null}
apiVersion: v1
kind: Service
metadata:
  name: redis
  namespace: overleaf
spec:
  selector:
    app: redis
  ports:
    - name: redis
      port: 6379
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis
  namespace: overleaf
spec:
  serviceName: redis
  replicas: 1
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
        - name: redis
          image: redis:7.4
          args: [--appendonly, "yes"]
          ports:
            - containerPort: 6379
          readinessProbe:
            tcpSocket:
              port: 6379
          resources:
            requests:
              cpu: 50m
              memory: 128Mi
            limits:
              memory: 512Mi
          volumeMounts:
            - name: data
              mountPath: /data
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: [ReadWriteOnce]
        resources:
          requests:
            storage: 2Gi
```

```bash theme={null}
kubectl apply -f 20-redis.yaml
kubectl -n overleaf rollout status statefulset/redis
```

### Q\&A

> [accordion] MongoDB 8 bị lỗi khi khởi động trên một kernel mới. Tại sao?
>
> **Trả lời:** MongoDB 8 gặp lỗi trên Linux kernel 6.19 trở lên ([SERVER-121912](https://jira.mongodb.org/browse/SERVER-121912)). Hãy bỏ chú thích biến môi trường `GLIBC_TUNABLES` trong `10-mongo.yaml`.

> [accordion] MongoDB cần bao nhiêu bộ nhớ?
>
> **Trả lời:** Theo mặc định, MongoDB dùng một nửa bộ nhớ của node trừ đi 1 GB cho bộ nhớ đệm, và nó nhìn thấy bộ nhớ của node chứ không phải giới hạn của pod. Hãy đặt `--wiredTigerCacheSizeGB` cho phù hợp với các node của bạn; giá trị `0.25` giữ mỗi thành viên ở mức khoảng 200 đến 260 MiB trên các node thử nghiệm 4 GB của chúng tôi.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.