diff --git a/ca.crt b/ca.crt new file mode 100644 index 000000000..277bd3064 --- /dev/null +++ b/ca.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDJTCCAg2gAwIBAgIUSq2Ks96UnmxPg7646uNhdJXpvC8wDQYJKoZIhvcNAQEL +BQAwIjEPMA0GA1UEAwwGcWRyYW50MQ8wDQYDVQQKDAZrdWJlZGIwHhcNMjYwNTE4 +MDgwODU1WhcNMjcwNTE4MDgwODU1WjAiMQ8wDQYDVQQDDAZxZHJhbnQxDzANBgNV +BAoMBmt1YmVkYjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALcmKSZa +Nos6KlwCCJogYZY9/Wo6Lt0+rqc9OgbbMk6RP4teEIcyEOfKjHmnLiBPKPhfPJkX +CPCynNbw/MAKq4Y0q2pLzT1RcY0AJMWXdLoAEEtnxHDXvZUIjWjeJ8Eo0VFKIxvR +IyVL+wSfanMU3gI9Wzx2hwT7DZG6CqZnFLq/gXx/0GpAE6CzJHejjp3T1Hhwesbo +mnZxPgf54+qKVxQ0jb5fygh6SfZ4rmLvOBemBXzt09vlEjtMz5UOa2DuN6vL/yTE +4YExM6ULPdUJrzJVSQkCF7uM4Lc5SCRrcnaSjkzg9JBVIrWybGS2Bdz7Z3Cqv9r6 +jzdpJppM7E/3IekCAwEAAaNTMFEwHQYDVR0OBBYEFOdPZ7nipiw08sy5tHDKcJVY +dF/AMB8GA1UdIwQYMBaAFOdPZ7nipiw08sy5tHDKcJVYdF/AMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQELBQADggEBAAyprbEOEyeNGC0Vki7o61M6cmhsliSZ +NX36ofQlq7EpZqtOYFm3LgsJXkponD8HUY+A6A2ingymDRHjzDwgFk4adnbzptIC +hF3jaLHtuzzkPDtW+MLb5xQ5U9adNq3+vMRfA7zhg+2PIwR+ENxFblHgOZySni57 +iUNVPG7lfSrd5YNSqx8+80mLWV0lt8Mnwsv/yBHqJ3Ab/HwbOKwTL8MGtKkYG0wO +bPgGkLhNHK7QUu2XwJLZiP8M/dsaGBUYvDCigscHLMIgIBfRo2OALWBHxOZbCx5u +czVeZTXo5bAEER8Wg3KJD06zZWqVybvQXIIcb/bLW7tMUmtAkrxIa/U= +-----END CERTIFICATE----- diff --git a/ca.key b/ca.key new file mode 100644 index 000000000..888892ddf --- /dev/null +++ b/ca.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC3JikmWjaLOipc +AgiaIGGWPf1qOi7dPq6nPToG2zJOkT+LXhCHMhDnyox5py4gTyj4XzyZFwjwspzW +8PzACquGNKtqS809UXGNACTFl3S6ABBLZ8Rw172VCI1o3ifBKNFRSiMb0SMlS/sE +n2pzFN4CPVs8docE+w2RugqmZxS6v4F8f9BqQBOgsyR3o46d09R4cHrG6Jp2cT4H ++ePqilcUNI2+X8oIekn2eK5i7zgXpgV87dPb5RI7TM+VDmtg7jery/8kxOGBMTOl +Cz3VCa8yVUkJAhe7jOC3OUgka3J2ko5M4PSQVSK1smxktgXc+2dwqr/a+o83aSaa +TOxP9yHpAgMBAAECggEAFJNc8XTBG/MflHvwq3Vn1pEwScwvklDbHj6//h/cuabn +v1MvWCuaapqpcswCtUPaE800lEkE4BsGM7+Z0EQNRmPfE29gp2WMSY2dPqA9T4gi +TIEOjf7ZdZzNsN0EalbuQnZUa2jwzIffXi2VWp3FiKA2rRxDyZ4gGsxj1eikE4wE +1JNbfml6Tcva//aiEMy+W+cguyRTMV/5mHFvaLlzHSi/ZuNj4SMpTNNfXJzlQ7pk +3aX5PjBrQhG6gL2U9b7a98EeTABb8h8ONFX2qw36Skac9p96ZK/cdlX2c4mqTRgl +uBi0l5Hc94NvzEnj8fgU4neZpfU7iTUg2gISommOYQKBgQDmHFn7mYFCa/F83ljl +BriBJzLx99M71zZiaLkYGAt6AHn358VQzEbcIN+BBllS5mJjv5Fkma7mbZeKDfyR +KxXU31GEfCh8AYGC/W15YxNqXrUOClHIg+0O6eZk6wFYqH6803sMMrAE7SuXM1w0 +ZlpNNtJ37b4ymG1+DuW/WKG1cwKBgQDLwTgYQQq64sNjgJJDte5ir7d8TjZX1zcj +dy92cdn3dTqQ2BUjf0VU/GDX39JgTY5AMl4kYa26yLaYnJPtAnA8jcAWQBHIKMvF +3MkOTsCVZDzcbIAPR/UU/nlK7QJUWr3E2xZImYDMPAq0YSK8AOuYsz6vrC9r+Vyq +Jpt+Z2EUMwKBgFpiXH3VB86dM5eGhog/IY2pZfthCpmAqR3yYHG0UB21vjK/2OMp +udORHflCEyfa0l63ylYnf2mHNnTFlaU3tTWOGijd09ERjltzS+LYJbIsTRWcvA70 +stKe0R5mqHq4hD+LGdPqvPTSa8LSK69xXJrjo7vzqDebY7aWB2wnVi09AoGAK0I4 +gJ2+g3MFfKidZRbJJ9aapB+O1hNxN2xkfUcquaj/6CSYSFMLC0IR5YM1jRCqNOL8 +rci3M8LNUZVcqqMr5Q9LSu4LWG2g5b88SHdb19vSOBIpFhV26SAl7ExphDNHuvWw +w3UjrTjKJQXCdBvV6TOVCYMLBmeIzu8ncCzOpZUCgYEAmomOzZz3z9OEN4/i8PTr +81PZSmUJ0TpOYgluwAeSN/CHD1Tr68bftdWKf09XAES5gyUi/T+U2XhPyn43aC+E +d2L8ME0uBlJGFj3ptwcYJK0H0yxTC6BjiakWr2zXyn0NkX/t2NCoUWHZAafIKcjY +Gves4F5qVBAsgiNpTdiTQuw= +-----END PRIVATE KEY----- diff --git a/docs/examples/qdrant/autoscaler/compute/qdrant-as-compute.yaml b/docs/examples/qdrant/autoscaler/compute/qdrant-as-compute.yaml new file mode 100644 index 000000000..c8f421f77 --- /dev/null +++ b/docs/examples/qdrant/autoscaler/compute/qdrant-as-compute.yaml @@ -0,0 +1,24 @@ +apiVersion: autoscaling.kubedb.com/v1alpha1 +kind: QdrantAutoscaler +metadata: + name: qdrant-as-compute + namespace: demo +spec: + databaseRef: + name: qdrant-sample + opsRequestOptions: + timeout: 3m + apply: IfReady + compute: + node: + trigger: "On" + podLifeTimeThreshold: 5m + resourceDiffPercentage: 20 + minAllowed: + cpu: 400m + memory: 400Mi + maxAllowed: + cpu: 1 + memory: 2Gi + controlledResources: ["cpu", "memory"] + containerControlledValues: "RequestsAndLimits" diff --git a/docs/examples/qdrant/autoscaler/compute/qdrant.yaml b/docs/examples/qdrant/autoscaler/compute/qdrant.yaml new file mode 100644 index 000000000..07ffb37f9 --- /dev/null +++ b/docs/examples/qdrant/autoscaler/compute/qdrant.yaml @@ -0,0 +1,28 @@ +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + replicas: 3 + storageType: Durable + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + podTemplate: + spec: + containers: + - name: qdrant + resources: + requests: + cpu: "200m" + memory: "512Mi" + limits: + cpu: "200m" + memory: "512Mi" + deletionPolicy: WipeOut diff --git a/docs/examples/qdrant/autoscaler/storage/qdrant-as-storage.yaml b/docs/examples/qdrant/autoscaler/storage/qdrant-as-storage.yaml new file mode 100644 index 000000000..d76313abe --- /dev/null +++ b/docs/examples/qdrant/autoscaler/storage/qdrant-as-storage.yaml @@ -0,0 +1,14 @@ +apiVersion: autoscaling.kubedb.com/v1alpha1 +kind: QdrantAutoscaler +metadata: + name: qdrant-as-storage + namespace: demo +spec: + databaseRef: + name: qdrant-sample + storage: + node: + trigger: "On" + usageThreshold: 20 + scalingThreshold: 20 + expansionMode: "Online" diff --git a/docs/examples/qdrant/autoscaler/storage/qdrant.yaml b/docs/examples/qdrant/autoscaler/storage/qdrant.yaml new file mode 100644 index 000000000..67ca1c8f0 --- /dev/null +++ b/docs/examples/qdrant/autoscaler/storage/qdrant.yaml @@ -0,0 +1,17 @@ +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + replicas: 3 + storageType: Durable + storage: + storageClassName: "longhorn" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut diff --git a/docs/examples/qdrant/backup/logical/aws-secret.yaml b/docs/examples/qdrant/backup/logical/aws-secret.yaml new file mode 100644 index 000000000..15100ad5d --- /dev/null +++ b/docs/examples/qdrant/backup/logical/aws-secret.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Secret +metadata: + name: aws-secret + namespace: default +type: Opaque +stringData: + AWS_ACCESS_KEY_ID: minioadmin + AWS_SECRET_ACCESS_KEY: minioadmin \ No newline at end of file diff --git a/docs/examples/qdrant/backup/logical/backup-configuration.yaml b/docs/examples/qdrant/backup/logical/backup-configuration.yaml new file mode 100644 index 000000000..bd5677c58 --- /dev/null +++ b/docs/examples/qdrant/backup/logical/backup-configuration.yaml @@ -0,0 +1,39 @@ +apiVersion: core.kubestash.com/v1alpha1 +kind: BackupConfiguration +metadata: + name: qdrant-sample-backup + namespace: default +spec: + target: + apiGroup: kubedb.com + kind: Qdrant + namespace: default + name: qdrant-sample + backends: + - name: minio-backend + storageRef: + namespace: default + name: minio-storage + retentionPolicy: + name: demo-retention + namespace: default + sessions: + - name: frequent-backup + scheduler: + schedule: "*/5 * * * *" + jobTemplate: + backoffLimit: 1 + repositories: + - name: minio-qdrant-repo + backend: minio-backend + directory: /qdrant + encryptionSecret: + name: encrypt-secret + namespace: default + addon: + name: qdrant-addon + tasks: + - name: logical-backup + params: + collections: "my_collection" + diff --git a/docs/examples/qdrant/backup/logical/backup-storage.yaml b/docs/examples/qdrant/backup/logical/backup-storage.yaml new file mode 100644 index 000000000..53bef0c25 --- /dev/null +++ b/docs/examples/qdrant/backup/logical/backup-storage.yaml @@ -0,0 +1,20 @@ +apiVersion: storage.kubestash.com/v1alpha1 +kind: BackupStorage +metadata: + name: minio-storage + namespace: default +spec: + storage: + provider: s3 + s3: + bucket: qdrant-backups + endpoint: http://minio.default.svc:9000 + insecureTLS: true + prefix: backup/demo + region: us-east-1 + secretName: aws-secret + usagePolicy: + allowedNamespaces: + from: All + default: true + deletionPolicy: Delete \ No newline at end of file diff --git a/docs/examples/qdrant/backup/logical/encryption-secret.yaml b/docs/examples/qdrant/backup/logical/encryption-secret.yaml new file mode 100644 index 000000000..571688e40 --- /dev/null +++ b/docs/examples/qdrant/backup/logical/encryption-secret.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Secret +type: Opaque +metadata: + name: encrypt-secret + namespace: default +stringData: + RESTIC_PASSWORD: "changeit" \ No newline at end of file diff --git a/docs/examples/qdrant/backup/logical/examples/backupconfiguration.yaml b/docs/examples/qdrant/backup/logical/examples/backupconfiguration.yaml new file mode 100644 index 000000000..5d5df2379 --- /dev/null +++ b/docs/examples/qdrant/backup/logical/examples/backupconfiguration.yaml @@ -0,0 +1,38 @@ +apiVersion: core.kubestash.com/v1alpha1 +kind: BackupConfiguration +metadata: + name: qdrant-sample-backup + namespace: demo +spec: + target: + apiGroup: kubedb.com + kind: Qdrant + namespace: demo + name: qdrant-sample + backends: + - name: minio-backend + storageRef: + namespace: demo + name: minio-storage + retentionPolicy: + name: demo-retention + namespace: demo + sessions: + - name: frequent-backup + scheduler: + schedule: "*/5 * * * *" + jobTemplate: + backoffLimit: 1 + repositories: + - name: minio-qdrant-repo + backend: minio-backend + directory: /qdrant + encryptionSecret: + name: encrypt-secret + namespace: demo + addon: + name: qdrant-addon + tasks: + - name: logical-backup + params: + collections: "my_collection" diff --git a/docs/examples/qdrant/backup/logical/examples/backupstorage.yaml b/docs/examples/qdrant/backup/logical/examples/backupstorage.yaml new file mode 100644 index 000000000..b6178875a --- /dev/null +++ b/docs/examples/qdrant/backup/logical/examples/backupstorage.yaml @@ -0,0 +1,20 @@ +apiVersion: storage.kubestash.com/v1alpha1 +kind: BackupStorage +metadata: + name: minio-storage + namespace: demo +spec: + storage: + provider: s3 + s3: + bucket: qdrant-backups + endpoint: http://minio.demo.svc:9000 + insecureTLS: true + prefix: backup/demo + region: us-east-1 + secretName: aws-secret + usagePolicy: + allowedNamespaces: + from: All + default: true + deletionPolicy: Delete diff --git a/docs/examples/qdrant/backup/logical/examples/minio.yaml b/docs/examples/qdrant/backup/logical/examples/minio.yaml new file mode 100644 index 000000000..c1035cbe5 --- /dev/null +++ b/docs/examples/qdrant/backup/logical/examples/minio.yaml @@ -0,0 +1,74 @@ +# MinIO Deployment +apiVersion: apps/v1 +kind: Deployment +metadata: + name: minio + namespace: demo +spec: + selector: + matchLabels: + app: minio + template: + metadata: + labels: + app: minio + spec: + containers: + - name: minio + image: minio/minio:latest + args: + - server + - /data + - --console-address + - ":9001" + env: + - name: MINIO_ROOT_USER + value: minioadmin + - name: MINIO_ROOT_PASSWORD + value: minioadmin + ports: + - containerPort: 9000 + - containerPort: 9001 + volumeMounts: + - name: data + mountPath: /data + volumes: + - name: data + emptyDir: {} +--- +# MinIO Service +apiVersion: v1 +kind: Service +metadata: + name: minio + namespace: demo +spec: + ports: + - name: api + port: 9000 + - name: console + port: 9001 + selector: + app: minio +--- +# MinIO Setup Job +apiVersion: batch/v1 +kind: Job +metadata: + name: minio-setup + namespace: demo +spec: + template: + spec: + containers: + - name: mc + image: minio/mc:latest + command: + - /bin/sh + - -c + - | + sleep 10 + mc alias set myminio http://minio:9000 minioadmin minioadmin + mc mb myminio/qdrant-backups --ignore-existing + echo "Bucket created" + restartPolicy: Never diff --git a/docs/examples/qdrant/backup/logical/examples/qdrant-restored.yaml b/docs/examples/qdrant/backup/logical/examples/qdrant-restored.yaml new file mode 100644 index 000000000..db0bbe966 --- /dev/null +++ b/docs/examples/qdrant/backup/logical/examples/qdrant-restored.yaml @@ -0,0 +1,19 @@ +apiVersion: kubedb.com/v1 +kind: Qdrant +metadata: + name: restored-qdrant + namespace: demo +spec: + init: + waitForInitialRestore: true + version: "1.17.0" + mode: Distributed + replicas: 3 + storage: + storageClassName: longhorn + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 200Mi + deletionPolicy: WipeOut diff --git a/docs/examples/qdrant/backup/logical/examples/qdrant.yaml b/docs/examples/qdrant/backup/logical/examples/qdrant.yaml new file mode 100644 index 000000000..040f48afa --- /dev/null +++ b/docs/examples/qdrant/backup/logical/examples/qdrant.yaml @@ -0,0 +1,17 @@ +apiVersion: kubedb.com/v1 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + mode: Distributed + replicas: 3 + storage: + storageClassName: longhorn + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 200Mi + deletionPolicy: WipeOut diff --git a/docs/examples/qdrant/backup/logical/examples/restoresession.yaml b/docs/examples/qdrant/backup/logical/examples/restoresession.yaml new file mode 100644 index 000000000..4460f9b9e --- /dev/null +++ b/docs/examples/qdrant/backup/logical/examples/restoresession.yaml @@ -0,0 +1,21 @@ +apiVersion: core.kubestash.com/v1alpha1 +kind: RestoreSession +metadata: + name: restore-qdrant-sample + namespace: demo +spec: + target: + apiGroup: kubedb.com + kind: Qdrant + namespace: demo + name: restored-qdrant + dataSource: + repository: minio-qdrant-repo + snapshot: latest + encryptionSecret: + name: encrypt-secret + namespace: demo + addon: + name: qdrant-addon + tasks: + - name: logical-backup-restore diff --git a/docs/examples/qdrant/backup/logical/examples/retentionpolicy.yaml b/docs/examples/qdrant/backup/logical/examples/retentionpolicy.yaml new file mode 100644 index 000000000..a3415eedc --- /dev/null +++ b/docs/examples/qdrant/backup/logical/examples/retentionpolicy.yaml @@ -0,0 +1,11 @@ +apiVersion: storage.kubestash.com/v1alpha1 +kind: RetentionPolicy +metadata: + name: demo-retention + namespace: demo +spec: + default: true + maxNumberOfSnapshots: 5 + usagePolicy: + allowedNamespaces: + from: All diff --git a/docs/examples/qdrant/backup/logical/examples/storage-secret.yaml b/docs/examples/qdrant/backup/logical/examples/storage-secret.yaml new file mode 100644 index 000000000..1a2312fed --- /dev/null +++ b/docs/examples/qdrant/backup/logical/examples/storage-secret.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Secret +metadata: + name: aws-secret + namespace: demo +type: Opaque +stringData: + AWS_ACCESS_KEY_ID: minioadmin + AWS_SECRET_ACCESS_KEY: minioadmin diff --git a/docs/examples/qdrant/backup/logical/minio.yaml b/docs/examples/qdrant/backup/logical/minio.yaml new file mode 100644 index 000000000..5955390a6 --- /dev/null +++ b/docs/examples/qdrant/backup/logical/minio.yaml @@ -0,0 +1,78 @@ +--- +# Minimal MinIO Deployment for Qdrant Snapshots +apiVersion: v1 +kind: Namespace +metadata: + name: default +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: minio + namespace: default +spec: + selector: + matchLabels: + app: minio + template: + metadata: + labels: + app: minio + spec: + containers: + - name: minio + image: minio/minio:latest + args: + - server + - /data + - --console-address + - ":9001" + env: + - name: MINIO_ROOT_USER + value: minioadmin + - name: MINIO_ROOT_PASSWORD + value: minioadmin + ports: + - containerPort: 9000 + - containerPort: 9001 + volumeMounts: + - name: data + mountPath: /data + volumes: + - name: data + emptyDir: {} +--- +apiVersion: v1 +kind: Service +metadata: + name: minio + namespace: default +spec: + ports: + - name: api + port: 9000 + - name: console + port: 9001 + selector: + app: minio +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: minio-setup + namespace: default +spec: + template: + spec: + containers: + - name: mc + image: minio/mc:latest + command: + - /bin/sh + - -c + - | + sleep 10 + mc alias set myminio http://minio:9000 minioadmin minioadmin + mc mb myminio/qdrant-backups --ignore-existing + echo "Bucket created" + restartPolicy: Never \ No newline at end of file diff --git a/docs/examples/qdrant/backup/logical/qdrant-addon.yaml b/docs/examples/qdrant/backup/logical/qdrant-addon.yaml new file mode 100644 index 000000000..23cba00e6 --- /dev/null +++ b/docs/examples/qdrant/backup/logical/qdrant-addon.yaml @@ -0,0 +1,116 @@ +apiVersion: addons.kubestash.com/v1alpha1 +kind: Addon +metadata: + name: qdrant-addon +spec: + backupTasks: + - name: logical-backup + function: qdrant-backup + driver: Restic + executor: Job + singleton: true + parameters: + - name: collections + usage: Comma-separated list of collections to backup. If not specified, all collections will be backed up. + required: false + - name: args + usage: Arguments to be passed to the dump command. + required: false + - name: enableCache + usage: Enable or disable caching. Disabling caching may impact backup performance. + required: false + default: "true" + - name: scratchDir + usage: Directory for holding temporary files and restic cache. + required: false + default: /kubestash-tmp + volumeTemplate: + - name: kubestash-tmp-volume + usage: Holds temporary files and restic cache. + source: + emptyDir: {} + volumeMounts: + - name: kubestash-tmp-volume + mountPath: /kubestash-tmp + - name: volume-snapshot + function: qdrant-csi-snapshotter + driver: VolumeSnapshotter + executor: Job + singleton: true + parameters: + - name: volumeSnapshotClassName + usage: The VolumeSnapshotClassName to be used by volumeSnapshot + required: false + - name: manifest-backup + function: kubedbmanifest-backup + driver: Restic + executor: Job + singleton: true + parameters: + - name: enableCache + usage: Enable or disable caching. Disabling caching may impact backup performance. + required: false + default: "true" + - name: scratchDir + usage: Directory for holding temporary files and restic cache. + required: false + default: /kubestash-tmp + volumeTemplate: + - name: kubestash-tmp-volume + usage: Holds temporary files and restic cache. + source: + emptyDir: {} + volumeMounts: + - name: kubestash-tmp-volume + mountPath: /kubestash-tmp + restoreTasks: + - name: logical-backup-restore + function: qdrant-restore + driver: Restic + executor: Job + singleton: true + parameters: + - name: collections + usage: Comma-separated list of collections to restore. If not provided, all collections will be restored. + required: false + - name: args + usage: Arguments to be passed to the dump command. + required: false + - name: enableCache + usage: Enable or disable caching. Disabling caching may impact backup performance. + required: false + default: "true" + - name: scratchDir + usage: Directory for holding temporary files and restic cache. + required: false + default: /kubestash-tmp + volumeTemplate: + - name: kubestash-tmp-volume + usage: Holds temporary files and restic cache. + source: + emptyDir: {} + volumeMounts: + - name: kubestash-tmp-volume + mountPath: /kubestash-tmp + - name: manifest-restore + function: kubedbmanifest-restore + driver: Restic + executor: Job + singleton: true + parameters: + - name: enableCache + usage: Enable or disable caching. Disabling caching may impact backup performance. + required: false + default: "true" + - name: scratchDir + usage: Directory for holding temporary files and restic cache. + required: false + default: /kubestash-tmp + volumeTemplate: + - name: kubestash-tmp-volume + usage: Holds temporary files and restic cache. + source: + emptyDir: {} + volumeMounts: + - name: kubestash-tmp-volume + mountPath: /kubestash-tmp \ No newline at end of file diff --git a/docs/examples/qdrant/backup/logical/qdrant-backup-function.yaml b/docs/examples/qdrant/backup/logical/qdrant-backup-function.yaml new file mode 100644 index 000000000..766e7d65c --- /dev/null +++ b/docs/examples/qdrant/backup/logical/qdrant-backup-function.yaml @@ -0,0 +1,14 @@ +apiVersion: addons.kubestash.com/v1alpha1 +kind: Function +metadata: + name: qdrant-backup +spec: + args: + - backup + - --namespace=${namespace:=default} + - --backupsession=${backupSession:=} + - --enable-cache=${enableCache:=} + - --scratch-dir=${scratchDir:=} + - --wait-timeout=${waitTimeout:=300} + - --collections=${collections:=} + image: almasood/qdrant-restic-plugin:20260428144910 \ No newline at end of file diff --git a/docs/examples/qdrant/backup/logical/qdrant-restore-function.yaml b/docs/examples/qdrant/backup/logical/qdrant-restore-function.yaml new file mode 100644 index 000000000..ad9ba17ee --- /dev/null +++ b/docs/examples/qdrant/backup/logical/qdrant-restore-function.yaml @@ -0,0 +1,15 @@ +apiVersion: addons.kubestash.com/v1alpha1 +kind: Function +metadata: + name: qdrant-restore +spec: + args: + - restore + - --namespace=${namespace:=default} + - --restoresession=${restoreSession:=} + - --snapshot=${snapshot:=} + - --enable-cache=${enableCache:=} + - --scratch-dir=${scratchDir:=} + - --wait-timeout=${waitTimeout:=300} + - --collections=${collections:=} + image: almasood/qdrant-restic-plugin:20260428144910 diff --git a/docs/examples/qdrant/backup/logical/retention-policy.yaml b/docs/examples/qdrant/backup/logical/retention-policy.yaml new file mode 100644 index 000000000..fffcfcd0d --- /dev/null +++ b/docs/examples/qdrant/backup/logical/retention-policy.yaml @@ -0,0 +1,15 @@ +apiVersion: storage.kubestash.com/v1alpha1 +kind: RetentionPolicy +metadata: + name: demo-retention + namespace: default +spec: + default: true + failedSnapshots: + last: 2 + maxRetentionPeriod: 2mo + successfulSnapshots: + last: 5 + usagePolicy: + allowedNamespaces: + from: All \ No newline at end of file diff --git a/docs/examples/qdrant/backup/volumesnapshot/backup-configuration.yaml b/docs/examples/qdrant/backup/volumesnapshot/backup-configuration.yaml new file mode 100644 index 000000000..8d94eb39e --- /dev/null +++ b/docs/examples/qdrant/backup/volumesnapshot/backup-configuration.yaml @@ -0,0 +1,33 @@ +apiVersion: core.kubestash.com/v1alpha1 +kind: BackupConfiguration +metadata: + name: qdrant-sample-backup + namespace: default +spec: + target: + apiGroup: kubedb.com + kind: Qdrant + namespace: default + name: qdrant-sample + backends: + - name: minio-storage + storageRef: + name: minio-storage + namespace: default + sessions: + - name: frequent-backup + scheduler: + schedule: "*/5 * * * *" + jobTemplate: + backoffLimit: 1 + repositories: + - name: minio-qdrant-repo + backend: minio-storage + directory: /qdrant + encryptionSecret: + name: encrypt-secret + namespace: default + addon: + name: qdrant-addon + tasks: + - name: volume-snapshot diff --git a/docs/examples/qdrant/backup/volumesnapshot/backup-storage.yaml b/docs/examples/qdrant/backup/volumesnapshot/backup-storage.yaml new file mode 100644 index 000000000..53bef0c25 --- /dev/null +++ b/docs/examples/qdrant/backup/volumesnapshot/backup-storage.yaml @@ -0,0 +1,20 @@ +apiVersion: storage.kubestash.com/v1alpha1 +kind: BackupStorage +metadata: + name: minio-storage + namespace: default +spec: + storage: + provider: s3 + s3: + bucket: qdrant-backups + endpoint: http://minio.default.svc:9000 + insecureTLS: true + prefix: backup/demo + region: us-east-1 + secretName: aws-secret + usagePolicy: + allowedNamespaces: + from: All + default: true + deletionPolicy: Delete \ No newline at end of file diff --git a/docs/examples/qdrant/backup/volumesnapshot/encryption-secret.yaml b/docs/examples/qdrant/backup/volumesnapshot/encryption-secret.yaml new file mode 100644 index 000000000..571688e40 --- /dev/null +++ b/docs/examples/qdrant/backup/volumesnapshot/encryption-secret.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Secret +type: Opaque +metadata: + name: encrypt-secret + namespace: default +stringData: + RESTIC_PASSWORD: "changeit" \ No newline at end of file diff --git a/docs/examples/qdrant/backup/volumesnapshot/examples/backupconfiguration.yaml b/docs/examples/qdrant/backup/volumesnapshot/examples/backupconfiguration.yaml new file mode 100644 index 000000000..afd881a4e --- /dev/null +++ b/docs/examples/qdrant/backup/volumesnapshot/examples/backupconfiguration.yaml @@ -0,0 +1,38 @@ +apiVersion: core.kubestash.com/v1alpha1 +kind: BackupConfiguration +metadata: + name: qdrant-sample-backup + namespace: demo +spec: + target: + apiGroup: kubedb.com + kind: Qdrant + namespace: demo + name: qdrant-sample + backends: + - name: minio-backend + storageRef: + namespace: demo + name: minio-storage + retentionPolicy: + name: demo-retention + namespace: demo + sessions: + - name: frequent-backup + scheduler: + schedule: "*/5 * * * *" + jobTemplate: + backoffLimit: 1 + repositories: + - name: minio-qdrant-repo + backend: minio-backend + directory: /qdrant + encryptionSecret: + name: encrypt-secret + namespace: demo + addon: + name: qdrant-addon + tasks: + - name: volume-snapshot + params: + volumeSnapshotClassName: "longhorn-snapshot-vsc" diff --git a/docs/examples/qdrant/backup/volumesnapshot/examples/backupstorage.yaml b/docs/examples/qdrant/backup/volumesnapshot/examples/backupstorage.yaml new file mode 100644 index 000000000..b6178875a --- /dev/null +++ b/docs/examples/qdrant/backup/volumesnapshot/examples/backupstorage.yaml @@ -0,0 +1,20 @@ +apiVersion: storage.kubestash.com/v1alpha1 +kind: BackupStorage +metadata: + name: minio-storage + namespace: demo +spec: + storage: + provider: s3 + s3: + bucket: qdrant-backups + endpoint: http://minio.demo.svc:9000 + insecureTLS: true + prefix: backup/demo + region: us-east-1 + secretName: aws-secret + usagePolicy: + allowedNamespaces: + from: All + default: true + deletionPolicy: Delete diff --git a/docs/examples/qdrant/backup/volumesnapshot/examples/qdrant-restored.yaml b/docs/examples/qdrant/backup/volumesnapshot/examples/qdrant-restored.yaml new file mode 100644 index 000000000..db0bbe966 --- /dev/null +++ b/docs/examples/qdrant/backup/volumesnapshot/examples/qdrant-restored.yaml @@ -0,0 +1,19 @@ +apiVersion: kubedb.com/v1 +kind: Qdrant +metadata: + name: restored-qdrant + namespace: demo +spec: + init: + waitForInitialRestore: true + version: "1.17.0" + mode: Distributed + replicas: 3 + storage: + storageClassName: longhorn + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 200Mi + deletionPolicy: WipeOut diff --git a/docs/examples/qdrant/backup/volumesnapshot/examples/qdrant.yaml b/docs/examples/qdrant/backup/volumesnapshot/examples/qdrant.yaml new file mode 100644 index 000000000..040f48afa --- /dev/null +++ b/docs/examples/qdrant/backup/volumesnapshot/examples/qdrant.yaml @@ -0,0 +1,17 @@ +apiVersion: kubedb.com/v1 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + mode: Distributed + replicas: 3 + storage: + storageClassName: longhorn + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 200Mi + deletionPolicy: WipeOut diff --git a/docs/examples/qdrant/backup/volumesnapshot/examples/restoresession.yaml b/docs/examples/qdrant/backup/volumesnapshot/examples/restoresession.yaml new file mode 100644 index 000000000..d87876ff0 --- /dev/null +++ b/docs/examples/qdrant/backup/volumesnapshot/examples/restoresession.yaml @@ -0,0 +1,21 @@ +apiVersion: core.kubestash.com/v1alpha1 +kind: RestoreSession +metadata: + name: restore-qdrant-sample + namespace: demo +spec: + target: + apiGroup: kubedb.com + kind: Qdrant + namespace: demo + name: restored-qdrant + dataSource: + repository: minio-qdrant-repo + snapshot: latest + encryptionSecret: + name: encrypt-secret + namespace: demo + addon: + name: qdrant-addon + tasks: + - name: volume-snapshot-restore diff --git a/docs/examples/qdrant/backup/volumesnapshot/examples/retentionpolicy.yaml b/docs/examples/qdrant/backup/volumesnapshot/examples/retentionpolicy.yaml new file mode 100644 index 000000000..a3415eedc --- /dev/null +++ b/docs/examples/qdrant/backup/volumesnapshot/examples/retentionpolicy.yaml @@ -0,0 +1,11 @@ +apiVersion: storage.kubestash.com/v1alpha1 +kind: RetentionPolicy +metadata: + name: demo-retention + namespace: demo +spec: + default: true + maxNumberOfSnapshots: 5 + usagePolicy: + allowedNamespaces: + from: All diff --git a/docs/examples/qdrant/backup/volumesnapshot/examples/storage-secret.yaml b/docs/examples/qdrant/backup/volumesnapshot/examples/storage-secret.yaml new file mode 100644 index 000000000..1a2312fed --- /dev/null +++ b/docs/examples/qdrant/backup/volumesnapshot/examples/storage-secret.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Secret +metadata: + name: aws-secret + namespace: demo +type: Opaque +stringData: + AWS_ACCESS_KEY_ID: minioadmin + AWS_SECRET_ACCESS_KEY: minioadmin diff --git a/docs/examples/qdrant/backup/volumesnapshot/examples/volumesnapshotclass.yaml b/docs/examples/qdrant/backup/volumesnapshot/examples/volumesnapshotclass.yaml new file mode 100644 index 000000000..e250158bc --- /dev/null +++ b/docs/examples/qdrant/backup/volumesnapshot/examples/volumesnapshotclass.yaml @@ -0,0 +1,8 @@ +apiVersion: snapshot.storage.k8s.io/v1 +kind: VolumeSnapshotClass +metadata: + name: longhorn-snapshot-vsc +driver: driver.longhorn.io +deletionPolicy: Delete +parameters: + type: snap diff --git a/docs/examples/qdrant/backup/volumesnapshot/qdrant-addon.yaml b/docs/examples/qdrant/backup/volumesnapshot/qdrant-addon.yaml new file mode 100644 index 000000000..b154b92fd --- /dev/null +++ b/docs/examples/qdrant/backup/volumesnapshot/qdrant-addon.yaml @@ -0,0 +1,21 @@ +apiVersion: addons.kubestash.com/v1alpha1 +kind: Addon +metadata: + name: qdrant-addon +spec: + backupTasks: + - name: volume-snapshot + function: qdrant-csi-snapshotter + driver: VolumeSnapshotter + executor: Job + singleton: true + parameters: + - name: volumeSnapshotClassName + usage: The VolumeSnapshotClassName to be used by volumeSnapshot + required: false + restoreTasks: + - name: volume-snapshot-restore + function: qdrant-csi-snapshotter + driver: VolumeSnapshotter + executor: Job + singleton: true diff --git a/docs/examples/qdrant/backup/volumesnapshot/qdrant-csi-snapshotter-function.yaml b/docs/examples/qdrant/backup/volumesnapshot/qdrant-csi-snapshotter-function.yaml new file mode 100644 index 000000000..1aa544cc1 --- /dev/null +++ b/docs/examples/qdrant/backup/volumesnapshot/qdrant-csi-snapshotter-function.yaml @@ -0,0 +1,11 @@ +apiVersion: addons.kubestash.com/v1alpha1 +kind: Function +metadata: + name: qdrant-csi-snapshotter +spec: + args: + - volume-snapshot + - --namespace=${namespace:=default} + - --backupsession=${backupSession:=} + - --wait-timeout=${waitTimeout:=300} + image: almasood/qdrant-restic-plugin:20260428144910 diff --git a/docs/examples/qdrant/backup/volumesnapshot/qdrant-restore.yaml b/docs/examples/qdrant/backup/volumesnapshot/qdrant-restore.yaml new file mode 100644 index 000000000..8fa605fc3 --- /dev/null +++ b/docs/examples/qdrant/backup/volumesnapshot/qdrant-restore.yaml @@ -0,0 +1,17 @@ +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample-restore + namespace: demo +spec: + version: 1.17.0 + mode: Distributed + replicas: 3 + storage: + storageClassName: longhorn + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 200Mi + deletionPolicy: WipeOut diff --git a/docs/examples/qdrant/backup/volumesnapshot/restore-session.yaml b/docs/examples/qdrant/backup/volumesnapshot/restore-session.yaml new file mode 100644 index 000000000..ff13c67a5 --- /dev/null +++ b/docs/examples/qdrant/backup/volumesnapshot/restore-session.yaml @@ -0,0 +1,21 @@ +apiVersion: core.kubestash.com/v1alpha1 +kind: RestoreSession +metadata: + name: restore-qdrant-sample + namespace: demo +spec: + target: + apiGroup: kubedb.com + kind: Qdrant + namespace: demo + name: qdrant-sample-restore + dataSource: + repository: minio-qdrant-repo + snapshot: latest + encryptionSecret: + name: encrypt-secret + namespace: demo + addon: + name: qdrant-addon + tasks: + - name: volume-snapshot-restore diff --git a/docs/examples/qdrant/backup/volumesnapshot/volumesnapshotclass.yaml b/docs/examples/qdrant/backup/volumesnapshot/volumesnapshotclass.yaml new file mode 100644 index 000000000..176829012 --- /dev/null +++ b/docs/examples/qdrant/backup/volumesnapshot/volumesnapshotclass.yaml @@ -0,0 +1,8 @@ +apiVersion: snapshot.storage.k8s.io/v1 +kind: VolumeSnapshotClass +metadata: + name: longhorn-snapshot-vsc +driver: driver.longhorn.io +deletionPolicy: Delete +parameters: + type: bak \ No newline at end of file diff --git a/docs/examples/qdrant/configuration/configuration-secret.yaml b/docs/examples/qdrant/configuration/configuration-secret.yaml new file mode 100644 index 000000000..1ee3e56ee --- /dev/null +++ b/docs/examples/qdrant/configuration/configuration-secret.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +stringData: + config.yaml: | + log_level: DEBUG + service: + max_request_size_mb: 64 +kind: Secret +metadata: + name: qdrant-configuration + namespace: demo +type: Opaque diff --git a/docs/examples/qdrant/configuration/qdrant.yaml b/docs/examples/qdrant/configuration/qdrant.yaml new file mode 100644 index 000000000..58c5ca923 --- /dev/null +++ b/docs/examples/qdrant/configuration/qdrant.yaml @@ -0,0 +1,18 @@ +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + replicas: 3 + configuration: + secretName: qdrant-configuration + storage: + storageClassName: "longhorn" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut diff --git a/docs/examples/qdrant/quickstart/distributed.yaml b/docs/examples/qdrant/quickstart/distributed.yaml new file mode 100644 index 000000000..9eca490b6 --- /dev/null +++ b/docs/examples/qdrant/quickstart/distributed.yaml @@ -0,0 +1,17 @@ +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + mode: Distributed + replicas: 3 + storage: + storageClassName: standard + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 2Gi + deletionPolicy: WipeOut diff --git a/docs/examples/qdrant/quickstart/yamls/qdrant-distributed.yaml b/docs/examples/qdrant/quickstart/yamls/qdrant-distributed.yaml new file mode 100644 index 000000000..56301a747 --- /dev/null +++ b/docs/examples/qdrant/quickstart/yamls/qdrant-distributed.yaml @@ -0,0 +1,28 @@ +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: 1.17.0 + mode: Distributed + replicas: 3 + storage: + storageClassName: longhorn + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 200Mi + podTemplate: + spec: + containers: + - name: qdrant + resources: + requests: + cpu: 100m + memory: 100Mi + limits: + cpu: 100m + memory: 100Mi + deletionPolicy: WipeOut diff --git a/docs/examples/qdrant/quickstart/yamls/qdrant-hor-scaling.yaml b/docs/examples/qdrant/quickstart/yamls/qdrant-hor-scaling.yaml new file mode 100644 index 000000000..9a9138fd8 --- /dev/null +++ b/docs/examples/qdrant/quickstart/yamls/qdrant-hor-scaling.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdrant-hor-scaling + namespace: demo +spec: + type: HorizontalScaling + databaseRef: + name: qdrant-sample + horizontalScaling: + node: 5 diff --git a/docs/examples/qdrant/reconfigure-tls/add-tls.yaml b/docs/examples/qdrant/reconfigure-tls/add-tls.yaml new file mode 100644 index 000000000..dd8ef68d9 --- /dev/null +++ b/docs/examples/qdrant/reconfigure-tls/add-tls.yaml @@ -0,0 +1,25 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-add-tls + namespace: demo +spec: + type: ReconfigureTLS + databaseRef: + name: qdrant-sample + tls: + issuerRef: + name: qdrant-issuer + kind: Issuer + apiGroup: "cert-manager.io" + certificates: + - alias: server + subject: + organizations: + - kubedb:server + dnsNames: + - localhost + ipAddresses: + - "127.0.0.1" + timeout: 5m + apply: IfReady diff --git a/docs/examples/qdrant/reconfigure-tls/issuer.yaml b/docs/examples/qdrant/reconfigure-tls/issuer.yaml new file mode 100644 index 000000000..ca65585cc --- /dev/null +++ b/docs/examples/qdrant/reconfigure-tls/issuer.yaml @@ -0,0 +1,8 @@ +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: qdrant-issuer + namespace: demo +spec: + ca: + secretName: qdrant-ca diff --git a/docs/examples/qdrant/reconfigure-tls/ops-request.yaml b/docs/examples/qdrant/reconfigure-tls/ops-request.yaml new file mode 100644 index 000000000..825d29ef7 --- /dev/null +++ b/docs/examples/qdrant/reconfigure-tls/ops-request.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdrant-reconfigure-tls + namespace: demo +spec: + type: ReconfigureTLS + databaseRef: + name: qdrant-sample + tls: + rotateCertificates: true \ No newline at end of file diff --git a/docs/examples/qdrant/reconfigure-tls/qdrant.yaml b/docs/examples/qdrant/reconfigure-tls/qdrant.yaml new file mode 100644 index 000000000..549a356d3 --- /dev/null +++ b/docs/examples/qdrant/reconfigure-tls/qdrant.yaml @@ -0,0 +1,15 @@ +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + replicas: 3 + storage: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut diff --git a/docs/examples/qdrant/reconfigure-tls/remove-tls.yaml b/docs/examples/qdrant/reconfigure-tls/remove-tls.yaml new file mode 100644 index 000000000..362cb8033 --- /dev/null +++ b/docs/examples/qdrant/reconfigure-tls/remove-tls.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-remove-tls + namespace: demo +spec: + type: ReconfigureTLS + databaseRef: + name: qdrant-sample + tls: + remove: true diff --git a/docs/examples/qdrant/reconfigure-tls/rotate-tls.yaml b/docs/examples/qdrant/reconfigure-tls/rotate-tls.yaml new file mode 100644 index 000000000..b97358b35 --- /dev/null +++ b/docs/examples/qdrant/reconfigure-tls/rotate-tls.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-rotate-tls + namespace: demo +spec: + type: ReconfigureTLS + databaseRef: + name: qdrant-sample + tls: + rotateCertificates: true diff --git a/docs/examples/qdrant/reconfigure/apply-config.yaml b/docs/examples/qdrant/reconfigure/apply-config.yaml new file mode 100644 index 000000000..0c2077147 --- /dev/null +++ b/docs/examples/qdrant/reconfigure/apply-config.yaml @@ -0,0 +1,16 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-reconfigure-apply-config + namespace: demo +spec: + type: Reconfigure + databaseRef: + name: qdrant-sample + configuration: + applyConfig: + config.yaml: | + log_level: DEBUG + performance: + max_search_threads: 6 + update_rate_limit: 100 diff --git a/docs/examples/qdrant/reconfigure/configuration-secret.yaml b/docs/examples/qdrant/reconfigure/configuration-secret.yaml new file mode 100644 index 000000000..2a3176d41 --- /dev/null +++ b/docs/examples/qdrant/reconfigure/configuration-secret.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +stringData: + config.yaml: | + log_level: DEBUG + performance: + max_search_threads: 4 + update_rate_limit: 100 +kind: Secret +metadata: + name: qdrant-configuration + namespace: demo +type: Opaque diff --git a/docs/examples/qdrant/reconfigure/new-configuration-secret.yaml b/docs/examples/qdrant/reconfigure/new-configuration-secret.yaml new file mode 100644 index 000000000..836cce67f --- /dev/null +++ b/docs/examples/qdrant/reconfigure/new-configuration-secret.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +stringData: + config.yaml: | + log_level: DEBUG + performance: + max_search_threads: 8 + update_rate_limit: 100 +kind: Secret +metadata: + name: new-qdrant-configuration + namespace: demo +type: Opaque diff --git a/docs/examples/qdrant/reconfigure/ops-request.yaml b/docs/examples/qdrant/reconfigure/ops-request.yaml new file mode 100644 index 000000000..bba0604b3 --- /dev/null +++ b/docs/examples/qdrant/reconfigure/ops-request.yaml @@ -0,0 +1,13 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdrant-reconfigure + namespace: demo +spec: + type: Reconfigure + databaseRef: + name: qdrant-sample + configuration: + applyConfig: + production.yaml: | + log_level: INFO \ No newline at end of file diff --git a/docs/examples/qdrant/reconfigure/qdrant.yaml b/docs/examples/qdrant/reconfigure/qdrant.yaml new file mode 100644 index 000000000..556ffb44d --- /dev/null +++ b/docs/examples/qdrant/reconfigure/qdrant.yaml @@ -0,0 +1,17 @@ +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + replicas: 3 + configSecret: + name: qdrant-configuration + storage: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut diff --git a/docs/examples/qdrant/reconfigure/reconfigure-using-secret.yaml b/docs/examples/qdrant/reconfigure/reconfigure-using-secret.yaml new file mode 100644 index 000000000..fb4fbfdf5 --- /dev/null +++ b/docs/examples/qdrant/reconfigure/reconfigure-using-secret.yaml @@ -0,0 +1,14 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-reconfigure-config + namespace: demo +spec: + type: Reconfigure + databaseRef: + name: qdrant-sample + configuration: + configSecret: + name: new-qdrant-configuration + timeout: 5m + apply: IfReady diff --git a/docs/examples/qdrant/reconfigure/remove-config.yaml b/docs/examples/qdrant/reconfigure/remove-config.yaml new file mode 100644 index 000000000..ecc77fbb1 --- /dev/null +++ b/docs/examples/qdrant/reconfigure/remove-config.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-reconfigure-remove + namespace: demo +spec: + type: Reconfigure + databaseRef: + name: qdrant-sample + configuration: + removeCustomConfig: true diff --git a/docs/examples/qdrant/restart/ops-request.yaml b/docs/examples/qdrant/restart/ops-request.yaml new file mode 100644 index 000000000..a354476bd --- /dev/null +++ b/docs/examples/qdrant/restart/ops-request.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-restart + namespace: demo +spec: + type: Restart + databaseRef: + name: qdrant-sample + timeout: 3m + apply: Always diff --git a/docs/examples/qdrant/rotate-auth/custom-auth-secret.yaml b/docs/examples/qdrant/rotate-auth/custom-auth-secret.yaml new file mode 100644 index 000000000..e9053a903 --- /dev/null +++ b/docs/examples/qdrant/rotate-auth/custom-auth-secret.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +stringData: + api-key: MyCus0mAPIKey +kind: Secret +metadata: + name: my-custom-auth-secret + namespace: demo +type: Opaque diff --git a/docs/examples/qdrant/rotate-auth/ops-custom.yaml b/docs/examples/qdrant/rotate-auth/ops-custom.yaml new file mode 100644 index 000000000..98b41cd32 --- /dev/null +++ b/docs/examples/qdrant/rotate-auth/ops-custom.yaml @@ -0,0 +1,12 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-rotate-auth-custom + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: qdrant-sample + authentication: + secretRef: + name: my-custom-auth-secret diff --git a/docs/examples/qdrant/rotate-auth/ops-request.yaml b/docs/examples/qdrant/rotate-auth/ops-request.yaml new file mode 100644 index 000000000..0efac8951 --- /dev/null +++ b/docs/examples/qdrant/rotate-auth/ops-request.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-rotate-auth + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: qdrant-sample + timeout: 5m + apply: IfReady diff --git a/docs/examples/qdrant/rotate-auth/qdrant.yaml b/docs/examples/qdrant/rotate-auth/qdrant.yaml new file mode 100644 index 000000000..549a356d3 --- /dev/null +++ b/docs/examples/qdrant/rotate-auth/qdrant.yaml @@ -0,0 +1,15 @@ +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + replicas: 3 + storage: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut diff --git a/docs/examples/qdrant/scaling/horizontal-scaling/hscale-down.yaml b/docs/examples/qdrant/scaling/horizontal-scaling/hscale-down.yaml new file mode 100644 index 000000000..d2cfa6d0c --- /dev/null +++ b/docs/examples/qdrant/scaling/horizontal-scaling/hscale-down.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-hscale-down + namespace: demo +spec: + type: HorizontalScaling + databaseRef: + name: qdrant-sample + horizontalScaling: + node: 4 diff --git a/docs/examples/qdrant/scaling/horizontal-scaling/hscale-up.yaml b/docs/examples/qdrant/scaling/horizontal-scaling/hscale-up.yaml new file mode 100644 index 000000000..5a4fc6373 --- /dev/null +++ b/docs/examples/qdrant/scaling/horizontal-scaling/hscale-up.yaml @@ -0,0 +1,13 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-hscale-up + namespace: demo +spec: + type: HorizontalScaling + databaseRef: + name: qdrant-sample + horizontalScaling: + node: 5 + timeout: 5m + apply: IfReady diff --git a/docs/examples/qdrant/scaling/horizontal-scaling/ops-request.yaml b/docs/examples/qdrant/scaling/horizontal-scaling/ops-request.yaml new file mode 100644 index 000000000..6f1b3fae7 --- /dev/null +++ b/docs/examples/qdrant/scaling/horizontal-scaling/ops-request.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdrant-horizontal-scale + namespace: demo +spec: + type: HorizontalScaling + databaseRef: + name: qdrant-sample + horizontalScaling: + node: 5 \ No newline at end of file diff --git a/docs/examples/qdrant/scaling/horizontal-scaling/qdrant.yaml b/docs/examples/qdrant/scaling/horizontal-scaling/qdrant.yaml new file mode 100644 index 000000000..74d7dec35 --- /dev/null +++ b/docs/examples/qdrant/scaling/horizontal-scaling/qdrant.yaml @@ -0,0 +1,16 @@ +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + replicas: 3 + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut diff --git a/docs/examples/qdrant/scaling/vertical-scaling/ops-request.yaml b/docs/examples/qdrant/scaling/vertical-scaling/ops-request.yaml new file mode 100644 index 000000000..146b71415 --- /dev/null +++ b/docs/examples/qdrant/scaling/vertical-scaling/ops-request.yaml @@ -0,0 +1,18 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdrant-vertical-scale + namespace: demo +spec: + type: VerticalScaling + databaseRef: + name: qdrant-sample + verticalScaling: + node: + resources: + requests: + cpu: "500m" + memory: 1Gi + limits: + cpu: "1" + memory: 2Gi \ No newline at end of file diff --git a/docs/examples/qdrant/scaling/vertical-scaling/qdrant.yaml b/docs/examples/qdrant/scaling/vertical-scaling/qdrant.yaml new file mode 100644 index 000000000..74d7dec35 --- /dev/null +++ b/docs/examples/qdrant/scaling/vertical-scaling/qdrant.yaml @@ -0,0 +1,16 @@ +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + replicas: 3 + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut diff --git a/docs/examples/qdrant/scaling/vertical-scaling/vscale.yaml b/docs/examples/qdrant/scaling/vertical-scaling/vscale.yaml new file mode 100644 index 000000000..c95242583 --- /dev/null +++ b/docs/examples/qdrant/scaling/vertical-scaling/vscale.yaml @@ -0,0 +1,20 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-vscale + namespace: demo +spec: + type: VerticalScaling + databaseRef: + name: qdrant-sample + verticalScaling: + node: + resources: + requests: + cpu: "500m" + memory: "1Gi" + limits: + cpu: "1" + memory: "2Gi" + timeout: 5m + apply: IfReady diff --git a/docs/examples/qdrant/tls/issuer.yaml b/docs/examples/qdrant/tls/issuer.yaml new file mode 100644 index 000000000..ba8149eea --- /dev/null +++ b/docs/examples/qdrant/tls/issuer.yaml @@ -0,0 +1,8 @@ +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: qdrant-ca-issuer + namespace: demo +spec: + ca: + secretName: qdrant-ca diff --git a/docs/examples/qdrant/tls/tls-qdrant.yaml b/docs/examples/qdrant/tls/tls-qdrant.yaml new file mode 100644 index 000000000..34b5fbe25 --- /dev/null +++ b/docs/examples/qdrant/tls/tls-qdrant.yaml @@ -0,0 +1,23 @@ +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-tls + namespace: demo +spec: + version: "1.17.0" + mode: Distributed + replicas: 3 + tls: + issuerRef: + apiGroup: cert-manager.io + name: qdrant-ca-issuer + kind: Issuer + client: true + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut diff --git a/docs/examples/qdrant/update-version/ops-request.yaml b/docs/examples/qdrant/update-version/ops-request.yaml new file mode 100644 index 000000000..666e99b07 --- /dev/null +++ b/docs/examples/qdrant/update-version/ops-request.yaml @@ -0,0 +1,13 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-update-version + namespace: demo +spec: + type: UpdateVersion + databaseRef: + name: qdrant-sample + updateVersion: + targetVersion: "1.17.0" + timeout: 5m + apply: IfReady diff --git a/docs/examples/qdrant/update-version/qdrant.yaml b/docs/examples/qdrant/update-version/qdrant.yaml new file mode 100644 index 000000000..971c3a293 --- /dev/null +++ b/docs/examples/qdrant/update-version/qdrant.yaml @@ -0,0 +1,15 @@ +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.16.2" + replicas: 3 + storage: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut diff --git a/docs/examples/qdrant/volume-expansion/ops-request.yaml b/docs/examples/qdrant/volume-expansion/ops-request.yaml new file mode 100644 index 000000000..d0f996d64 --- /dev/null +++ b/docs/examples/qdrant/volume-expansion/ops-request.yaml @@ -0,0 +1,12 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-vol-exp + namespace: demo +spec: + type: VolumeExpansion + databaseRef: + name: qdrant-sample + volumeExpansion: + mode: "Offline" + node: 3Gi diff --git a/docs/examples/qdrant/volume-expansion/qdrant.yaml b/docs/examples/qdrant/volume-expansion/qdrant.yaml new file mode 100644 index 000000000..1e644039a --- /dev/null +++ b/docs/examples/qdrant/volume-expansion/qdrant.yaml @@ -0,0 +1,16 @@ +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + replicas: 3 + storage: + storageClassName: "longhorn" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut diff --git a/docs/guides/README.md b/docs/guides/README.md index 8f620422d..fae1fb6ab 100644 --- a/docs/guides/README.md +++ b/docs/guides/README.md @@ -18,25 +18,32 @@ aliases: Guides to show you how to perform tasks with KubeDB: - [Cassandra](/docs/guides/cassandra/README.md). Shows how to manage Cassandra using KubeDB. - [ClickHouse](/docs/guides/clickhouse/README.md). Shows how to manage ClickHouse using KubeDB. +- [DB2](/docs/guides/db2/README.md). Shows how to manage DB2 using KubeDB. +- [DocumentDB](/docs/guides/documentdb/README.md). Shows how to manage DocumentDB using KubeDB. - [Druid](/docs/guides/druid/README.md). Shows how to manage Druid using KubeDB. - [Elasticsearch](/docs/guides/elasticsearch/README.md). Shows how to manage Elasticsearch & OpenSearch using KubeDB. - [FerretDB](/docs/guides/ferretdb/README.md). Shows how to manage FerretDB using KubeDB. +- [HanaDB](/docs/guides/hanadb/README.md). Shows how to manage HanaDB using KubeDB. - [Hazelcast](/docs/guides/hazelcast/README.md). Shows how to manage Hazelcast using KubeDB. - [Ignite](/docs/guides/ignite/README.md). Shows how to manage Ignite using KubeDB. - [Kafka](/docs/guides/kafka/README.md). Shows how to manage Kafka using KubeDB. - [MariaDB](/docs/guides/mariadb). Shows how to manage MariaDB using KubeDB. - [Memcached](/docs/guides/memcached/README.md). Shows how to manage Memcached using KubeDB. +- [Milvus](/docs/guides/milvus/README.md). Shows how to manage Milvus using KubeDB. - [Microsoft SQL Server](/docs/guides/mssqlserver/README.md). Shows how to manage Microsoft SQL Server using KubeDB. - [MongoDB](/docs/guides/mongodb/README.md). Shows how to manage MongoDB using KubeDB. - [MySQL](/docs/guides/mysql/README.md). Shows how to manage MySQL using KubeDB. +- [Neo4j](/docs/guides/neo4j/README.md). Shows how to manage Neo4j using KubeDB. - [Oracle](/docs/guides/oracle/README.md). Shows how to manage Oracle using KubeDB. - [Percona XtraDB](/docs/guides/percona-xtradb/README.md). Shows how to manage Percona XtraDB using KubeDB. - [PgBouncer](/docs/guides/pgbouncer/README.md). Shows how to manage PgBouncer using KubeDB. - [Pgpool](/docs/guides/pgpool/README.md). Shows how to manage Pgpool using KubeDB. - [PostgreSQL](/docs/guides/postgres/README.md). Shows how to manage PostgreSQL using KubeDB. - [ProxySQL](/docs/guides/proxysql/README.md). Shows how to manage ProxySQL using KubeDB. +- [Qdrant](/docs/guides/qdrant/README.md). Shows how to manage Qdrant using KubeDB. - [RabbitMQ](/docs/guides/rabbitmq/README.md). Shows how to manage RabbitMQ using KubeDB. - [Redis](/docs/guides/redis/README.md). Shows how to manage Redis using KubeDB. - [SingleStore](/docs/guides/singlestore/README.md). Shows how to manage SingleStore using KubeDB. - [Solr](/docs/guides/solr/README.md). Shows how to manage Solr using KubeDB. +- [Weaviate](/docs/guides/weaviate/README.md). Shows how to manage Weaviate using KubeDB. - [ZooKeeper](/docs/guides/zookeeper/README.md). Shows how to manage ZooKeeper using KubeDB. diff --git a/docs/guides/oracle/README.md b/docs/guides/oracle/README.md index e6952f370..4e3ff000b 100644 --- a/docs/guides/oracle/README.md +++ b/docs/guides/oracle/README.md @@ -38,4 +38,9 @@ aliases: - [Quickstart Oracle](/docs/guides/oracle/quickstart/guide.md) with KubeDB Operator. +## Concepts + +- [Oracle CRD](/docs/guides/oracle/concepts/oracle.md) defines the schema for Oracle custom resource. +- [OracleVersion CRD](/docs/guides/oracle/concepts/catalog.md) defines the schema for OracleVersion custom resource. + diff --git a/docs/guides/postgres/README.md b/docs/guides/postgres/README.md index 3f15fda67..4cb93ed20 100644 --- a/docs/guides/postgres/README.md +++ b/docs/guides/postgres/README.md @@ -54,6 +54,7 @@ aliases: - Monitor your PostgreSQL database with KubeDB using [`out-of-the-box` Prometheus operator](/docs/guides/postgres/monitoring/using-prometheus-operator.md). - Use [private Docker registry](/docs/guides/postgres/private-registry/using-private-registry.md) to deploy PostgreSQL with KubeDB. - Detail concepts of [Postgres object](/docs/guides/postgres/concepts/postgres.md). +- Detail concepts of [PostgresAutoscaler object](/docs/guides/postgres/concepts/autoscaler.md). - Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). diff --git a/docs/guides/qdrant/README.md b/docs/guides/qdrant/README.md new file mode 100644 index 000000000..1ce6a6cb5 --- /dev/null +++ b/docs/guides/qdrant/README.md @@ -0,0 +1,54 @@ +--- +title: Qdrant +menu: + docs_{{ .version }}: + identifier: qdrant-readme + name: Qdrant + parent: qdrant-guides + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +url: /docs/{{ .version }}/guides/qdrant/ +aliases: + - /docs/{{ .version }}/guides/qdrant/README/ +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Overview + +Qdrant is a high-performance open-source vector database designed for similarity search and AI-powered applications. KubeDB supports provisioning and management of Qdrant clusters directly inside Kubernetes, enabling scalable and production-ready vector search infrastructure with minimal operational overhead. Deploy Qdrant in distributed mode to achieve horizontal scalability, replication, and high availability for large-scale embedding workloads. KubeDB automates cluster lifecycle management tasks such as deployment, scaling, monitoring, backups, and version upgrades, simplifying operations for machine learning and semantic search applications. With seamless Kubernetes integration, users can efficiently run and manage resilient Qdrant deployments for modern AI and retrieval-augmented generation (RAG) workloads. + +## Supported Qdrant Features + +| Features | Availability | +|--------------------------|:------------:| +| Standalone provisioning | ✓ | +| Distributed provisioning | ✓ | +| TLS | ✓ | +| Logical Backup | ✓ | +| Volume Snapshot | ✓ | +| Monitoring | ✓ | +| Ops Requests | ✓ | +| Autoscaler | ✓ | + +## Supported Microsoft SQL Server Versions + +KubeDB supports the following Microsoft SQL Server Version. +- `1.15.4` +- `1.16.2` +- `1.17.0` + +## Life Cycle of a Qdrant Object + +

+  lifecycle +

+ + +## User Guide + +- [Quickstart Qdrant](/docs/guides/qdrant/quickstart/quickstart.md) with KubeDB operator. +- Deploy [Distributed Qdrant](/docs/guides/qdrant/distributed-deployment/overview.md) cluster. +- Detail concepts of [Qdrant Object](/docs/guides/qdrant/concepts/). +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). diff --git a/docs/guides/qdrant/_index.md b/docs/guides/qdrant/_index.md new file mode 100644 index 000000000..b77c4abea --- /dev/null +++ b/docs/guides/qdrant/_index.md @@ -0,0 +1,10 @@ +--- +title: Qdrant +menu: + docs_{{ .version }}: + identifier: qdrant-guides + name: Qdrant + parent: guides + weight: 17 +menu_name: docs_{{ .version }} +--- \ No newline at end of file diff --git a/docs/guides/qdrant/autoscaler/_index.md b/docs/guides/qdrant/autoscaler/_index.md new file mode 100644 index 000000000..c2349712a --- /dev/null +++ b/docs/guides/qdrant/autoscaler/_index.md @@ -0,0 +1,10 @@ +--- +title: Qdrant Autoscaler +menu: + docs_{{ .version }}: + identifier: qdrant-autoscaler + name: Autoscaler + parent: qdrant-guides + weight: 140 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/qdrant/autoscaler/compute/_index.md b/docs/guides/qdrant/autoscaler/compute/_index.md new file mode 100644 index 000000000..5160e8257 --- /dev/null +++ b/docs/guides/qdrant/autoscaler/compute/_index.md @@ -0,0 +1,10 @@ +--- +title: Compute +menu: + docs_{{ .version }}: + identifier: qdrant-autoscaler-compute + name: Compute + parent: qdrant-autoscaler + weight: 10 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/qdrant/autoscaler/compute/compute-autoscale.md b/docs/guides/qdrant/autoscaler/compute/compute-autoscale.md new file mode 100644 index 000000000..c955f0901 --- /dev/null +++ b/docs/guides/qdrant/autoscaler/compute/compute-autoscale.md @@ -0,0 +1,247 @@ +--- +title: Qdrant Compute Autoscaler +menu: + docs_{{ .version }}: + identifier: qdrant-autoscaler-compute-description + name: Autoscale Compute Resources + parent: qdrant-autoscaler-compute + weight: 20 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Autoscaling the Compute Resource of a Qdrant Database + +This guide will show you how to use `KubeDB` to auto-scale compute resources i.e. CPU and memory of a Qdrant database. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the `kubectl` command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Install `KubeDB` Community, Ops-Manager and Autoscaler operator in your cluster following the steps [here](/docs/setup/README.md). + +- Install `Metrics Server` from [here](https://github.com/kubernetes-sigs/metrics-server#installation). + +- You should be familiar with the following `KubeDB` concepts: + - [Qdrant](/docs/guides/qdrant/concepts/) + - [QdrantAutoscaler](/docs/guides/qdrant/concepts/autoscaler.md) + - [QdrantOpsRequest](/docs/guides/qdrant/concepts/opsrequest.md) + - [Compute Resource Autoscaling Overview](/docs/guides/qdrant/autoscaler/overview.md) + +To keep everything isolated, we are going to use a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +## Autoscaling of Database + +Here, we are going to deploy a `Qdrant` database using a supported version by `KubeDB` operator. Then we are going to apply `QdrantAutoscaler` to set up autoscaling. + +### Deploy Qdrant Database + +In this section, we are going to deploy a Qdrant database with version `1.17.0`. Then, in the next section we will set up autoscaling for this database using `QdrantAutoscaler` CRD. Below is the YAML of the `Qdrant` CR that we are going to create: + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + replicas: 3 + storageType: Durable + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + podTemplate: + spec: + containers: + - name: qdrant + resources: + requests: + cpu: "200m" + memory: "512Mi" + limits: + cpu: "200m" + memory: "512Mi" + deletionPolicy: WipeOut +``` + +Let's create the `Qdrant` CR we have shown above: + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/autoscaler/compute/qdrant.yaml +qdrant.kubedb.com/qdrant-sample created +``` + +Now, wait until `qdrant-sample` has status `Ready`: + +```bash +$ kubectl get qdrant -n demo +NAME VERSION STATUS AGE +qdrant-sample 1.17.0 Ready 51s +``` + +Let's check the Pod container resources: + +```bash +$ kubectl get pod -n demo qdrant-sample-0 -o json | jq '.spec.containers[].resources' +{ + "limits": { + "cpu": "200m", + "memory": "512Mi" + }, + "requests": { + "cpu": "200m", + "memory": "512Mi" + } +} +``` + +We are now ready to apply the `QdrantAutoscaler` CRD to set up autoscaling for this database. + +### Compute Resource Autoscaling + +Here, we are going to set up compute resource autoscaling using a `QdrantAutoscaler` Object. + +#### Create QdrantAutoscaler Object + +In order to set up compute resource autoscaling for this database, we have to create a `QdrantAutoscaler` CR with our desired configuration. Below is the YAML of the `QdrantAutoscaler` object that we are going to create: + +```yaml +apiVersion: autoscaling.kubedb.com/v1alpha1 +kind: QdrantAutoscaler +metadata: + name: qdrant-as-compute + namespace: demo +spec: + databaseRef: + name: qdrant-sample + opsRequestOptions: + timeout: 3m + apply: IfReady + compute: + node: + trigger: "On" + podLifeTimeThreshold: 10m + resourceDiffPercentage: 20 + minAllowed: + cpu: 400m + memory: 400Mi + maxAllowed: + cpu: 1 + memory: 2Gi + controlledResources: ["cpu", "memory"] + containerControlledValues: "RequestsAndLimits" +``` + +Here, + +- `spec.databaseRef.name` specifies that we are performing compute autoscaling on `qdrant-sample` database. +- `spec.compute.node.trigger` specifies that compute resource autoscaling is enabled for the Qdrant nodes. +- `spec.compute.node.podLifeTimeThreshold` specifies the minimum age of a Pod before the `VerticalPodAutoscaler` can recommend a resource update. +- `spec.compute.node.resourceDiffPercentage` specifies the minimum percentage change needed before applying a new resource recommendation. +- `spec.compute.node.minAllowed` specifies the minimum allowed resources for the Qdrant nodes. +- `spec.compute.node.maxAllowed` specifies the maximum allowed resources for the Qdrant nodes. +- `spec.compute.node.controlledResources` specifies the resource types that will be auto-scaled. +- `spec.compute.node.containerControlledValues` specifies which resource values should be controlled, here both requests and limits. +- `spec.opsRequestOptions.apply` has two supported values: `IfReady` and `Always`. Use `IfReady` to process the ops request only when the database is Ready. Use `Always` to process the execution irrespective of the database state. +- `spec.opsRequestOptions.timeout` specifies the maximum time for each step of the ops request. If a step doesn't finish within the specified timeout, the ops request will result in failure. + +Let's create the `QdrantAutoscaler` CR we have shown above: + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/autoscaler/compute/qdrant-as-compute.yaml +qdrantautoscaler.autoscaling.kubedb.com/qdrant-as-compute created +``` + +#### Verify Autoscaler is set up successfully + +Let's check that the `QdrantAutoscaler` resource is created successfully: + +```bash +$ kubectl get qdrantautoscaler -n demo +NAME AGE +qdrant-as-compute 0s + +$ kubectl describe qdrantautoscaler qdrant-as-compute -n demo +Name: qdrant-as-compute +Namespace: demo +Labels: +Annotations: +API Version: autoscaling.kubedb.com/v1alpha1 +Kind: QdrantAutoscaler +Spec: + Compute: + Node: + Container Controlled Values: RequestsAndLimits + Controlled Resources: + cpu + memory + Max Allowed: + Cpu: 1 + Memory: 2Gi + Min Allowed: + Cpu: 400m + Memory: 400Mi + Pod Life Time Threshold: 10m + Resource Diff Percentage: 20 + Trigger: On + Database Ref: + Name: qdrant-sample + Ops Request Options: + Apply: IfReady + Max Retries: 1 + Timeout: 3m +Status: + Vpas: + Vpa Name: qdrant-sample +Events: +``` + +So, the `QdrantAutoscaler` resource is created successfully. The operator will now watch the resource usage of the Qdrant pods and create `QdrantOpsRequest` resources to scale when needed. + +After some time, you can observe that the autoscaler has created a `QdrantOpsRequest` with type `VerticalScaling`: + +```bash +$ kubectl get qdrantopsrequest -n demo +NAME TYPE STATUS AGE +qdops-qdrant-sample-829lnp VerticalScaling Successful 45s +``` + +You can then verify the updated resources on the pods: + +```bash +$ kubectl get pod -n demo qdrant-sample-0 -o json | jq '.spec.containers[].resources' +{ + "limits": { + "cpu": "400m", + "memory": "400Mi" + }, + "requests": { + "cpu": "400m", + "memory": "400Mi" + } +} +``` + +The above output verifies that we have successfully autoscaled the resources of the Qdrant database. + +## Cleaning Up + +To clean up the Kubernetes resources created by this tutorial, run: + +```bash +kubectl delete qdrant -n demo qdrant-sample +kubectl delete qdrantautoscaler -n demo qdrant-as-compute +kubectl delete ns demo +``` diff --git a/docs/guides/qdrant/autoscaler/compute/overview.md b/docs/guides/qdrant/autoscaler/compute/overview.md new file mode 100644 index 000000000..5248c7883 --- /dev/null +++ b/docs/guides/qdrant/autoscaler/compute/overview.md @@ -0,0 +1,55 @@ +--- +title: Qdrant Compute Autoscaling Overview +menu: + docs_{{ .version }}: + identifier: qdrant-autoscaler-compute-overview + name: Overview + parent: qdrant-autoscaler-compute + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Qdrant Compute Resource Autoscaling + +This guide will give an overview on how KubeDB Autoscaler operator autoscales the database compute resources i.e. cpu and memory using `QdrantAutoscaler` crd. + +## Before You Begin + +- You should be familiar with the following `KubeDB` concepts: + - [Qdrant](/docs/guides/qdrant/concepts/) + - [QdrantOpsRequest](/docs/guides/qdrant/concepts/opsrequest.md) + - [QdrantAutoscaler](/docs/guides/qdrant/concepts/autoscaler.md) + +## How Compute Autoscaling Works + +The following diagram shows how KubeDB Autoscaler operator autoscales the resources of `Qdrant` database components. Open the image in a new tab to see the enlarged version. + +
+  Compute Auto Scaling process of Qdrant +
Fig: Compute Auto Scaling process of Qdrant
+
+ +The Auto Scaling process consists of the following steps: + +1. At first, a user creates a `Qdrant` Custom Resource Object (CRO). + +2. `KubeDB` Provisioner operator watches the `Qdrant` CRO. + +3. When the operator finds a `Qdrant` CRO, it creates `PetSet` and related necessary stuff like secrets, services, etc. + +4. Then, in order to set up autoscaling of the `Qdrant` database the user creates a `QdrantAutoscaler` CRO with desired configuration. + +5. `KubeDB` Autoscaler operator watches the `QdrantAutoscaler` CRO. + +6. `KubeDB` Autoscaler operator generates recommendation using the modified version of kubernetes [official recommender](https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler/pkg/recommender) for different components of the database, as specified in the `QdrantAutoscaler` CRO. + +7. If the generated recommendation doesn't match the current resources of the database, then `KubeDB` Autoscaler operator creates a `QdrantOpsRequest` CRO to scale the database to match the recommendation generated. + +8. `KubeDB` Ops-manager operator watches the `QdrantOpsRequest` CRO. + +9. Then the `KubeDB` Ops-manager operator will scale the database component vertically as specified on the `QdrantOpsRequest` CRO. + +In the next docs, we are going to show a step-by-step guide on Autoscaling of various Qdrant database using `QdrantAutoscaler` CRD. diff --git a/docs/guides/qdrant/autoscaler/storage/_index.md b/docs/guides/qdrant/autoscaler/storage/_index.md new file mode 100644 index 000000000..0eb112cc1 --- /dev/null +++ b/docs/guides/qdrant/autoscaler/storage/_index.md @@ -0,0 +1,10 @@ +--- +title: Storage +menu: + docs_{{ .version }}: + identifier: qdrant-autoscaler-storage + name: Storage + parent: qdrant-autoscaler + weight: 20 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/qdrant/autoscaler/storage/overview.md b/docs/guides/qdrant/autoscaler/storage/overview.md new file mode 100644 index 000000000..c5da67fb5 --- /dev/null +++ b/docs/guides/qdrant/autoscaler/storage/overview.md @@ -0,0 +1,59 @@ +--- +title: Qdrant Storage Autoscaling Overview +menu: + docs_{{ .version }}: + identifier: qdrant-autoscaler-storage-overview + name: Overview + parent: qdrant-autoscaler-storage + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Qdrant Storage Autoscaling + +This guide will give an overview on how KubeDB `Autoscaler` operator autoscales the database storage using `QdrantAutoscaler` CRD. + +## Before You Begin + +- You should be familiar with the following `KubeDB` concepts: + - [Qdrant](/docs/guides/qdrant/concepts/) + - [QdrantAutoscaler](/docs/guides/qdrant/concepts/autoscaler.md) + - [QdrantOpsRequest](/docs/guides/qdrant/concepts/opsrequest.md) + + +## How Storage Autoscaling Works + +The following diagram shows how KubeDB Autoscaler operator autoscales the resources of `Qdrant`. Open the image in a new tab to see the enlarged version. + +
+  Storage Auto Scaling process of Qdrant +
Fig: Storage Auto Scaling process of Qdrant
+
+ + +The Auto Scaling process consists of the following steps: + +1. At first, a user creates a `Qdrant` Custom Resource Object (CRO). + +2. `KubeDB` Provisioner operator watches the `Qdrant` CRO. + +3. When the operator finds a `Qdrant` CRO, it creates required number of `PetSets` and related necessary stuff like secrets, services, etc. + +4. Each PetSet creates a Persistent Volumes according to the Volume Claim Template provided in the petset's configuration. + +5. Then, in order to set up storage autoscaling of the `Qdrant` database the user creates a `QdrantAutoscaler` CRO with desired configuration. + +6. `KubeDB` Autoscaler operator watches the `QdrantAutoscaler` CRO. + +7. `KubeDB` Autoscaler operator continuously watches persistent volumes of the databases to check if it exceeds the specified usage threshold. + +8. If the usage exceeds the specified usage threshold, then `KubeDB` Autoscaler operator creates a `QdrantOpsRequest` to expand the storage of the database. + +9. `KubeDB` Ops-manager operator watches the `QdrantOpsRequest` CRO. + +10. Then the `KubeDB` Ops-manager operator will expand the storage of the database as specified on the `QdrantOpsRequest` CRO. + +In the next docs, we are going to show a step-by-step guide on Autoscaling storage of Qdrant database using `QdrantAutoscaler` CRD. diff --git a/docs/guides/qdrant/autoscaler/storage/storage-autoscale.md b/docs/guides/qdrant/autoscaler/storage/storage-autoscale.md new file mode 100644 index 000000000..9cfa178e6 --- /dev/null +++ b/docs/guides/qdrant/autoscaler/storage/storage-autoscale.md @@ -0,0 +1,228 @@ +--- +title: Qdrant Storage Autoscaler +menu: + docs_{{ .version }}: + identifier: qdrant-autoscaler-storage-description + name: Autoscale Storage + parent: qdrant-autoscaler-storage + weight: 20 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Storage Autoscaling of a Qdrant Database + +This guide will show you how to use `KubeDB` to autoscale the storage of a Qdrant database. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the `kubectl` command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Install `KubeDB` Community, Enterprise and Autoscaler operator in your cluster following the steps [here](/docs/setup/README.md). + +- Install `Metrics Server` from [here](https://github.com/kubernetes-sigs/metrics-server#installation). + +- Install Prometheus from [here](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack). + +- You must have a `StorageClass` that supports volume expansion. + +- You should be familiar with the following `KubeDB` concepts: + - [Qdrant](/docs/guides/qdrant/concepts/) + - [QdrantAutoscaler](/docs/guides/qdrant/concepts/autoscaler.md) + - [QdrantOpsRequest](/docs/guides/qdrant/concepts/opsrequest.md) + - [Storage Autoscaling Overview](/docs/guides/qdrant/autoscaler/overview.md) + +To keep everything isolated, we are going to use a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +## Storage Autoscaling of Database + +At first, verify that your cluster has a storage class that supports volume expansion: + +```bash +$ kubectl get storageclass +NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE +local-path (default) rancher.io/local-path Delete WaitForFirstConsumer false 28d +longhorn (default) driver.longhorn.io Delete Immediate true 25d +longhorn-static driver.longhorn.io Delete Immediate true 28d +``` + +We can see from the output that `longhorn` storage class has `ALLOWVOLUMEEXPANSION` set to `true`. We will use it for this tutorial. + +Now, we are going to deploy a `Qdrant` database using a supported version by `KubeDB` operator. Then we are going to apply `QdrantAutoscaler` to set up autoscaling. + +### Deploy Qdrant Database + +In this section, we are going to deploy a Qdrant database with version `1.17.0`. Then, in the next section we will set up autoscaling for this database using `QdrantAutoscaler` CRD. Below is the YAML of the `Qdrant` CR that we are going to create: + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + replicas: 3 + storageType: Durable + storage: + storageClassName: "longhorn" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut +``` + +Let's create the `Qdrant` CR we have shown above: + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/autoscaler/storage/qdrant.yaml +qdrant.kubedb.com/qdrant-sample created +``` + +Now, wait until `qdrant-sample` has status `Ready`: + +```bash +$ kubectl get qdrant -n demo +NAME VERSION STATUS AGE +qdrant-sample 1.17.0 Ready 101s +``` + +Let's check the volume size from the Petset and from the persistent volumes: + +```bash +$ kubectl get petset -n demo qdrant-sample -o json | jq '.spec.volumeClaimTemplates[].spec.resources.requests.storage' +"1Gi" + +$ kubectl get pv -o custom-columns=NAME:.metadata.name,CAPACITY:.spec.capacity.storage,STORAGECLASS:.spec.storageClassName,CLAIM:.spec.claimRef.name | grep qdrant-sample +pvc-31485d1d-5048-4dc2-a2c3-18910b27b661 1Gi longhorn data-qdrant-sample-0 +pvc-683755b9-023d-4d36-8318-8a22d5b79acb 1Gi longhorn data-qdrant-sample-1 +pvc-d494f0aa-41b8-458d-ab56-39946c9b9bfe 1Gi longhorn data-qdrant-sample-2 +``` + +You can see the Petset has 1GB storage and the capacity of all the persistent volumes is also 1GB. + +We are now ready to apply the `QdrantAutoscaler` CRD to set up storage autoscaling for this database. + +### Storage Autoscaling + +Here, we are going to set up storage autoscaling using a `QdrantAutoscaler` Object. + +#### Create QdrantAutoscaler Object + +In order to set up storage autoscaling for this database, we have to create a `QdrantAutoscaler` CR with our desired configuration. Below is the YAML of the `QdrantAutoscaler` object that we are going to create: + +```yaml +apiVersion: autoscaling.kubedb.com/v1alpha1 +kind: QdrantAutoscaler +metadata: + name: qdrant-as-storage + namespace: demo +spec: + databaseRef: + name: qdrant-sample + storage: + node: + trigger: "On" + usageThreshold: 20 + scalingThreshold: 20 + expansionMode: "Online" +``` + +Here, + +- `spec.databaseRef.name` specifies that we are performing storage autoscaling on `qdrant-sample` database. +- `spec.storage.node.trigger` specifies that storage autoscaling is enabled for the Qdrant nodes. +- `spec.storage.node.usageThreshold` specifies the storage usage threshold — if storage usage exceeds `20%`, storage autoscaling will be triggered. +- `spec.storage.node.scalingThreshold` specifies the scaling threshold — storage will be scaled to `20%` of the current amount. +- `spec.storage.node.expansionMode` specifies the expansion mode of the volume expansion `QdrantOpsRequest` created by `QdrantAutoscaler`. longhorn supports online volume expansion so `expansionMode` is set to `Online`. + +Let's create the `QdrantAutoscaler` CR we have shown above: + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/autoscaler/storage/qdrant-as-storage.yaml +qdrantautoscaler.autoscaling.kubedb.com/qdrant-as-storage created +``` + +#### Verify Autoscaler is set up successfully + +Let's check that the `QdrantAutoscaler` resource is created successfully: + +```bash +$ kubectl get qdrantautoscaler -n demo +NAME AGE +qdrant-as-storage 33s + +$ kubectl describe qdrantautoscaler qdrant-as-storage -n demo +Name: qdrant-as-storage +Namespace: demo +Labels: +Annotations: +API Version: autoscaling.kubedb.com/v1alpha1 +Kind: QdrantAutoscaler +Spec: + Database Ref: + Name: qdrant-sample + Storage: + Node: + Expansion Mode: Online + Scaling Threshold: 20 + Trigger: On + Usage Threshold: 20 +Events: +``` + +So, the `QdrantAutoscaler` resource is created successfully. The operator will now continuously watch the storage usage of the Qdrant pods. When the usage crosses the `usageThreshold`, it will create a `QdrantOpsRequest` to expand the storage. + +Now, for this demo, we are going to manually fill up the persistent volume to exceed the `usageThreshold` using the `dd` command to see if storage autoscaling is working: + +```bash +$ kubectl exec -n demo qdrant-sample-0 -- df -h /qdrant/storage +Filesystem Size Used Avail Use% Mounted on +/dev/longhorn/pvc-9d79a391-6777-4be5-8f9e-0139d178aada 974M 296K 958M 1% /qdrant/storage + +$ kubectl exec -n demo qdrant-sample-0 -- bash -c "dd if=/dev/zero of=/qdrant/storage/file.img bs=250M count=1 && df -h /qdrant/storage" +1+0 records in +1+0 records out +262144000 bytes (262 MB, 250 MiB) copied, 2.01673 s, 130 MB/s +Filesystem Size Used Avail Use% Mounted on +/dev/longhorn/pvc-9d79a391-6777-4be5-8f9e-0139d178aada 974M 251M 708M 27% /qdrant/storage +``` + +Now let's watch the `QdrantOpsRequest` in the demo namespace: + +```bash +$ kubectl get qdrantopsrequest -n demo -w +NAME TYPE STATUS AGE +qdops-qdrant-sample-ka4wgv VolumeExpansion Progressing 2s +qdops-qdrant-sample-ka4wgv VolumeExpansion Successful 8m +``` + +After the `QdrantOpsRequest` completes successfully, let's check the updated storage: + +```bash +$ kubectl get pv -o custom-columns=NAME:.metadata.name,CAPACITY:.spec.capacity.storage,STORAGECLASS:.spec.storageClassName,CLAIM:.spec.claimRef.name | grep qdrant-sample +pvc-31485d1d-5048-4dc2-a2c3-18910b27b661 1168Mi longhorn data-qdrant-sample-0 +pvc-683755b9-023d-4d36-8318-8a22d5b79acb 1168Mi longhorn data-qdrant-sample-1 +pvc-d494f0aa-41b8-458d-ab56-39946c9b9bfe 1168Mi longhorn data-qdrant-sample-2 +``` + +The storage has been automatically scaled from 1Gi to ~1168Mi as we specified a `scalingThreshold` of 20%. + +## Cleaning Up + +To clean up the Kubernetes resources created by this tutorial, run: + +```bash +kubectl delete qdrant -n demo qdrant-sample +kubectl delete qdrantautoscaler -n demo qdrant-as-storage +kubectl delete ns demo +``` diff --git a/docs/guides/qdrant/backup/_index.md b/docs/guides/qdrant/backup/_index.md new file mode 100644 index 000000000..6efdd7d9b --- /dev/null +++ b/docs/guides/qdrant/backup/_index.md @@ -0,0 +1,11 @@ +--- +title: Qdrant Backup & Restore +menu: + docs_{{ .version }}: + identifier: qdrant-backup + name: Backup & Restore + parent: qdrant-guides + weight: 60 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- diff --git a/docs/guides/qdrant/backup/logical/index.md b/docs/guides/qdrant/backup/logical/index.md new file mode 100644 index 000000000..be96c3321 --- /dev/null +++ b/docs/guides/qdrant/backup/logical/index.md @@ -0,0 +1,531 @@ +--- +title: Backup & Restore Qdrant | KubeStash +description: Backup Qdrant database using KubeStash +menu: + docs_{{ .version }}: + identifier: guides-qdrant-logical-backup + name: Logical Backup + parent: qdrant-backup + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +# Backup and Restore Qdrant Database Using KubeStash + +KubeStash allows you to backup and restore `Qdrant` databases logically. This guide will show you how to take logical backup and restore your `Qdrant` databases using KubeStash. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the `kubectl` command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using `Minikube` or `Kind`. +- Install `KubeDB` in your cluster following the steps [here](/docs/setup/README.md). +- Install `KubeStash` in your cluster following the steps [here](https://kubestash.com/docs/latest/setup/install/kubestash). +- Install KubeStash `kubectl` plugin following the steps [here](https://kubestash.com/docs/latest/setup/install/kubectl-plugin/). +- If you are not familiar with how KubeStash backup and restore Qdrant databases, please check the following guide [here](/docs/guides/qdrant/backup/overview/index.md). + +You should be familiar with the following `KubeStash` concepts: + +- [BackupStorage](https://kubestash.com/docs/latest/concepts/crds/backupstorage/) +- [BackupConfiguration](https://kubestash.com/docs/latest/concepts/crds/backupconfiguration/) +- [BackupSession](https://kubestash.com/docs/latest/concepts/crds/backupsession/) +- [RestoreSession](https://kubestash.com/docs/latest/concepts/crds/restoresession/) +- [Addon](https://kubestash.com/docs/latest/concepts/crds/addon/) +- [Function](https://kubestash.com/docs/latest/concepts/crds/function/) +- [Task](https://kubestash.com/docs/latest/concepts/crds/addon/#task-specification) + +To keep everything isolated, we are going to use a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +> **Note:** YAML files used in this tutorial are stored in [docs/examples/qdrant/backup/logical/examples](https://github.com/kubedb/docs/tree/{{< param "info.version" >}}/docs/examples/qdrant/backup/logical/examples) directory of [kubedb/docs](https://github.com/kubedb/docs) repository. + +## Backup Qdrant + +KubeStash supports logical backup for `Qdrant` databases. In this demonstration, we'll backup a Qdrant database into a S3-compatible storage (MinIO). + +This section will demonstrate how to backup a `Qdrant` database. Here, we are going to deploy a `Qdrant` database using KubeDB. Then, we are going to backup this database into a `MinIO` bucket. Finally, we will restore the backed up data into another `Qdrant` database. + +### Deploy Sample Qdrant Database + +Let's deploy a sample `Qdrant` database and insert some data into it. + +**Create Qdrant CR:** + +Below is the YAML of a sample `Qdrant` CRD that we are going to create for this tutorial: + +```yaml +apiVersion: kubedb.com/v1 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + mode: Distributed + replicas: 3 + storage: + storageClassName: longhorn + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 200Mi + deletionPolicy: WipeOut +``` + +Create the above `Qdrant` CR, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/backup/logical/examples/qdrant.yaml +qdrant.kubedb.com/qdrant-sample created +``` + +KubeDB will deploy a Qdrant database according to the above specification. It will also create the necessary `Secrets` and `Services` to access the database. + +Let's check if the database is ready to use, + +```bash +$ kubectl get qdrant -n demo +NAME VERSION STATUS AGE +qdrant-sample 1.17.0 Ready 4m22s +``` + +The database is `Ready`. Verify that KubeDB has created a `Secret` and a `Service` for this database using the following commands, + +```bash +$ kubectl get secret -n demo -l=app.kubernetes.io/instance=qdrant-sample +NAME TYPE DATA AGE +qdrant-sample-auth Opaque 2 4m58s + +$ kubectl get service -n demo -l=app.kubernetes.io/instance=qdrant-sample +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +qdrant-sample ClusterIP 10.96.55.61 6333/TCP 97s +qdrant-sample-pods ClusterIP None 6333/TCP 97s +``` + +KubeDB creates an [AppBinding](/docs/guides/qdrant/concepts/appbinding/index.md) CR that holds the necessary information to connect with the database. + +**Verify AppBinding:** + +Verify that the `AppBinding` has been created successfully using the following command, + +```bash +$ kubectl get appbindings -n demo +NAME AGE +qdrant-sample 9m24s +``` + +**Insert Sample Data:** + +Now, we are going to exec into the database pod and create some sample data. At first, find out the database `Pod` using the following command, + +```bash +$ kubectl get pods -n demo --selector="app.kubernetes.io/instance=qdrant-sample" +NAME READY STATUS RESTARTS AGE +qdrant-sample-0 1/1 Running 0 2m41s +qdrant-sample-1 1/1 Running 0 2m35s +qdrant-sample-2 1/1 Running 0 2m29s +``` + +Now, let's exec into the `Pod` to insert some sample data into Qdrant: + +```bash +$ kubectl exec -it -n demo qdrant-sample-0 -- sh +# Upload some sample points to a collection +$ wget -qO- --header 'Content-Type: application/json' \ + --post-data '{ + "vectors": [ + {"id": 1, "vector": [0.1, 0.2, 0.3, 0.4]}, + {"id": 2, "vector": [0.5, 0.6, 0.7, 0.8]} + ] + }' \ + http://localhost:6333/collections/my_collection/points +# Exit the pod +$ exit +``` + +Now, we are ready to backup the database. + +### Prepare Backend + +We are going to store our backed up data into a MinIO bucket. We have to create a Secret with necessary credentials and a `BackupStorage` CR to use this backend. If you want to use a different backend, please read the respective backend configuration doc from [here](https://kubestash.com/docs/latest/guides/backends/overview/). + +**Deploy MinIO:** + +Let's deploy MinIO in the `demo` namespace: + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/backup/logical/examples/minio.yaml +deployment.apps/minio created +service/minio created +job.batch/minio-setup created +``` + +Verify MinIO is running: + +```bash +$ kubectl get pods -n demo -l app=minio +NAME READY STATUS RESTARTS AGE +minio-xxxxxxxxxx-xxxxx 1/1 Running 0 2m +``` + +**Create Storage Secret:** + +Create a secret with credentials to access the MinIO storage: + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/backup/logical/examples/storage-secret.yaml +secret/aws-secret created +``` + +**Create BackupStorage:** + +Create a `BackupStorage` CR to configure the backup storage: + +```yaml +apiVersion: storage.kubestash.com/v1alpha1 +kind: BackupStorage +metadata: + name: minio-storage + namespace: demo +spec: + storage: + provider: s3 + s3: + bucket: qdrant-backups + endpoint: http://minio.demo.svc:9000 + insecureTLS: true + prefix: backup/demo + region: us-east-1 + secretName: aws-secret + usagePolicy: + allowedNamespaces: + from: All + default: true + deletionPolicy: Delete +``` + +Apply the BackupStorage: + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/backup/logical/examples/backupstorage.yaml +backupstorage.storage.kubestash.com/minio-storage created +``` + +**Create Encryption Secret:** + +Create a secret for encrypting the backup data: + +```bash +$ echo -n 'changeit' > RESTIC_PASSWORD +$ kubectl create secret generic -n demo encrypt-secret \ + --from-file=./RESTIC_PASSWORD +secret "encrypt-secret" created +``` + +**Create RetentionPolicy:** + +Now, let's create a `RetentionPolicy` to specify how the old Snapshots should be cleaned up. + +Below is the YAML of the `RetentionPolicy` object that we are going to create, + +```yaml +apiVersion: storage.kubestash.com/v1alpha1 +kind: RetentionPolicy +metadata: + name: demo-retention + namespace: demo +spec: + default: true + maxNumberOfSnapshots: 5 + usagePolicy: + allowedNamespaces: + from: All +``` + +Let's create the above `RetentionPolicy`, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/backup/logical/examples/retentionpolicy.yaml +retentionpolicy.storage.kubestash.com/demo-retention created +``` + +### Backup + +We have to create a `BackupConfiguration` targeting respective `qdrant-sample` Qdrant database. Then, KubeStash will create a `CronJob` for each session to take periodic backup of that database. + +**Create BackupConfiguration:** + +Below is the YAML for `BackupConfiguration` CR to backup the `qdrant-sample` database that we have deployed earlier, + +```yaml +apiVersion: core.kubestash.com/v1alpha1 +kind: BackupConfiguration +metadata: + name: qdrant-sample-backup + namespace: demo +spec: + target: + apiGroup: kubedb.com + kind: Qdrant + namespace: demo + name: qdrant-sample + backends: + - name: minio-backend + storageRef: + namespace: demo + name: minio-storage + retentionPolicy: + name: demo-retention + namespace: demo + sessions: + - name: frequent-backup + scheduler: + schedule: "*/5 * * * *" + jobTemplate: + backoffLimit: 1 + repositories: + - name: minio-qdrant-repo + backend: minio-backend + directory: /qdrant + encryptionSecret: + name: encrypt-secret + namespace: demo + addon: + name: qdrant-addon + tasks: + - name: logical-backup + params: + collections: "my_collection" +``` + +Here, +- `.spec.sessions[*].schedule` specifies that we want to backup the database at `5 minutes` interval. +- `.spec.target` refers to the targeted `qdrant-sample` Qdrant database that we created earlier. +- `.spec.sessions[*].addon.tasks[*].name` specifies that the `logical-backup` task will be executed. The `params.collections` field can be used to specify which collection(s) to backup. + +Let's create the `BackupConfiguration` CR that we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/backup/logical/examples/backupconfiguration.yaml +backupconfiguration.core.kubestash.com/qdrant-sample-backup created +``` + +**Verify Backup Setup Successful:** + +If everything goes well, the phase of the `BackupConfiguration` should be `Ready`. The `Ready` phase indicates that the backup setup is successful. Let's verify the `Phase` of the BackupConfiguration, + +```bash +$ kubectl get backupconfiguration -n demo +NAME PHASE PAUSED AGE +qdrant-sample-backup Ready 2m50s +``` + +Additionally, we can verify that the `Repository` specified in the `BackupConfiguration` has been created using the following command, + +```bash +$ kubectl get repo -n demo +NAME INTEGRITY SNAPSHOT-COUNT SIZE PHASE LAST-SUCCESSFUL-BACKUP AGE +minio-qdrant-repo 0 0 B Ready 3m +``` + +**Verify CronJob:** + +It will also create a `CronJob` with the schedule specified in `spec.sessions[*].scheduler.schedule` field of `BackupConfiguration` CR. + +Verify that the `CronJob` has been created using the following command, + +```bash +$ kubectl get cronjob -n demo +NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE +trigger-qdrant-sample-backup-frequent-backup */5 * * * * 0 2m45s 3m25s +``` + +**Verify BackupSession:** + +KubeStash triggers an instant backup as soon as the `BackupConfiguration` is ready. After that, backups are scheduled according to the specified schedule. + +```bash +$ kubectl get backupsession -n demo -w + +NAME INVOKER-TYPE INVOKER-NAME PHASE DURATION AGE +qdrant-sample-backup-frequent-backup-xyz BackupConfiguration qdrant-sample-backup Succeeded 7m22s +``` + +We can see from the above output that the backup session has succeeded. Now, we are going to verify whether the backed up data has been stored in the backend. + +**Verify Backup:** + +Once a backup is complete, KubeStash will update the respective `Repository` CR to reflect the backup. Check that the repository `minio-qdrant-repo` has been updated by the following command, + +```bash +$ kubectl get repository -n demo minio-qdrant-repo +NAME INTEGRITY SNAPSHOT-COUNT SIZE PHASE LAST-SUCCESSFUL-BACKUP AGE +minio-qdrant-repo true 1 806 B Ready 8m27s 9m18s +``` + +Run the following command to check the respective `Snapshot` which represents the state of a backup run for an application. + +```bash +$ kubectl get snapshots -n demo -l=kubestash.com/repo-name=minio-qdrant-repo +NAME REPOSITORY SESSION SNAPSHOT-TIME DELETION-POLICY PHASE AGE +minio-qdrant-repo-qdrant-sample-backup-frequent-backup-xyz minio-qdrant-repo frequent-backup 2024-01-23T13:10:54Z Delete Succeeded 16h +``` + +> Note: KubeStash creates a `Snapshot` with the following labels: +> - `kubestash.com/app-ref-kind: ` +> - `kubestash.com/app-ref-name: ` +> - `kubestash.com/app-ref-namespace: ` +> - `kubestash.com/repo-name: ` +> +> These labels can be used to watch only the `Snapshot`s related to our target Database or `Repository`. + +> KubeStash uses `qdrant-restic-plugin` to perform backups of target `Qdrant` databases. Therefore, the component name for logical backups is set as `dump`. + +## Restore + +In this section, we are going to restore the database from the backup we have taken in the previous section. We are going to deploy a new database and initialize it from the backup. + +#### Deploy Restored Database: + +Now, we have to deploy the restored database similarly as we have deployed the original `qdrant-sample` database. However, this time there will be the following differences: + +- We are going to specify `.spec.init.waitForInitialRestore` field that tells KubeDB to wait for first restore to complete before marking this database is ready to use. + +Below is the YAML for `Qdrant` CRD we are going deploy to initialize from backup, + +```yaml +apiVersion: kubedb.com/v1 +kind: Qdrant +metadata: + name: restored-qdrant + namespace: demo +spec: + init: + waitForInitialRestore: true + version: "1.17.0" + mode: Distributed + replicas: 3 + storage: + storageClassName: longhorn + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 200Mi + deletionPolicy: WipeOut +``` + +Let's create the above database, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/backup/logical/examples/qdrant-restored.yaml +qdrant.kubedb.com/restored-qdrant created +``` + +If you check the database status, you will see it is stuck in `Provisioning` state. + +```bash +$ kubectl get qdrant -n demo restored-qdrant +NAME VERSION STATUS AGE +restored-qdrant 1.17.0 Provisioning 61s +``` + +#### Create RestoreSession: + +Now, we need to create a RestoreSession CRD pointing to targeted `Qdrant` database. + +Below, is the contents of YAML file of the `RestoreSession` object that we are going to create to restore backed up data into the newly created database provisioned by Qdrant object named `restored-qdrant`. + +```yaml +apiVersion: core.kubestash.com/v1alpha1 +kind: RestoreSession +metadata: + name: restore-qdrant-sample + namespace: demo +spec: + target: + apiGroup: kubedb.com + kind: Qdrant + namespace: demo + name: restored-qdrant + dataSource: + repository: minio-qdrant-repo + snapshot: latest + encryptionSecret: + name: encrypt-secret + namespace: demo + addon: + name: qdrant-addon + tasks: + - name: logical-backup-restore +``` + +Let's create the RestoreSession CRD object we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/backup/logical/examples/restoresession.yaml +restoresession.core.kubestash.com/restore-qdrant-sample created +``` + +Once, you have created the `RestoreSession` object, KubeStash will create restore Job. Run the following command to watch the phase of the `RestoreSession` object, + +```bash +$ watch kubectl get restoresession -n demo +Every 2.0s: kubectl get restores... AppsCode-PC-03: Wed Aug 21 10:44:05 2024 + +NAME REPOSITORY FAILURE-POLICY PHASE DURATION AGE +restore-qdrant-sample minio-qdrant-repo Succeeded 3s 53s +``` + +The `Succeeded` phase means that the restore process has been completed successfully. + +#### Verify Restored Data: + +In this section, we are going to verify whether the desired data has been restored successfully. We are going to connect to the database server and check whether the collection we created earlier in the original database are restored. + +At first, check if the database has gone into `Ready` state by the following command, + +```bash +$ kubectl get qdrant -n demo restored-qdrant +NAME VERSION STATUS AGE +restored-qdrant 1.17.0 Ready 34m +``` + +Now, find out the database `Pod` by the following command, + +```bash +$ kubectl get pods -n demo --selector="app.kubernetes.io/instance=restored-qdrant" +NAME READY STATUS RESTARTS AGE +restored-qdrant-0 1/1 Running 0 39m +``` + +Now, let's exec into the Pod to enter into Qdrant and verify restored data, + +```bash +$ kubectl exec -it -n demo restored-qdrant-0 -- sh +# Check if the collection exists and has data +$ wget -qO- http://localhost:6333/collections/my_collection +# Exit the pod +$ exit +``` + +So, from the above output, we can see that the `my_collection` collection we created earlier in the original database and now, it is restored successfully. + +## Cleanup + +To cleanup the Kubernetes resources created by this tutorial, run: + +```bash +kubectl delete backupconfigurations.core.kubestash.com -n demo qdrant-sample-backup +kubectl delete restoresessions.core.kubestash.com -n demo restore-qdrant-sample +kubectl delete retentionpolicies.storage.kubestash.com -n demo demo-retention +kubectl delete backupstorage -n demo minio-storage +kubectl delete secret -n demo aws-secret +kubectl delete secret -n demo encrypt-secret +kubectl delete qdrant -n demo restored-qdrant +kubectl delete qdrant -n demo qdrant-sample +``` diff --git a/docs/guides/qdrant/backup/overview/index.md b/docs/guides/qdrant/backup/overview/index.md new file mode 100644 index 000000000..a54a7f57e --- /dev/null +++ b/docs/guides/qdrant/backup/overview/index.md @@ -0,0 +1,79 @@ +--- +title: Backup & Restore Qdrant Using KubeStash +menu: + docs_{{ .version }}: + identifier: guides-qdrant-backup-overview + name: Overview + parent: qdrant-backup + weight: 5 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +{{< notice type="warning" message="Please install [KubeStash](https://kubestash.com/docs/latest/setup/install/kubestash/) to try this feature. Database backup with KubeStash is already included in the KubeDB license. So, you don't need a separate license for KubeStash." >}} + +# Qdrant Backup & Restore Overview + +KubeDB uses [KubeStash](https://kubestash.com) to backup and restore databases. KubeStash by AppsCode is a cloud native data backup and recovery solution for Kubernetes workloads and databases. KubeStash utilizes [restic](https://github.com/restic/restic) to securely backup stateful applications to any cloud or on-prem storage backends (for example, S3, GCS, Azure Blob storage, Minio, NetApp, Dell EMC etc.). + +## How Backup Works + +The backup process consists of the following steps: + +1. At first, a user creates a `Secret`. This secret holds the credentials to access the backend where the backed up data will be stored. + +2. Then, she creates a `BackupStorage` custom resource that specifies the backend information, along with the `Secret` containing the credentials needed to access the backend. + +3. KubeStash operator watches for `BackupStorage` custom resources. When it finds a `BackupStorage` object, it initializes the `BackupStorage` by uploading the `metadata.yaml` file to the specified backend. + +4. Next, she creates a `BackupConfiguration` custom resource that specifies the target database, addon information (including backup tasks), backup schedules, storage backends for storing the backup data, and other additional settings. + +5. KubeStash operator watches for `BackupConfiguration` objects. + +6. Once the KubeStash operator finds a `BackupConfiguration` object, it creates `Repository` with the information specified in the `BackupConfiguration`. + +7. KubeStash operator watches for `Repository` custom resources. When it finds the `Repository` object, it Initializes `Repository` by uploading `repository.yaml` file into the `spec.sessions[*].repositories[*].directory` path specified in `BackupConfiguration`. + +8. Then, it creates a `CronJob` for each session with the schedule specified in `BackupConfiguration` to trigger backup periodically. + +9. KubeStash operator triggers an instant backup as soon as the `BackupConfiguration` is ready. Backups are otherwise triggered by the `CronJob` based on the specified schedule. + +10. KubeStash operator watches for `BackupSession` custom resources. + +11. When it finds a `BackupSession` object, it creates a `Snapshot` custom resource for each `Repository` specified in the `BackupConfiguration`. + +12. Then it resolves the respective `Addon` and `Function` and prepares backup `Job` definition. + +13. Then, it creates the `Job` to backup the targeted `Qdrant` database. + +14. The backup `Job` reads necessary information (e.g. auth secret, port) to connect with the database from the `AppBinding` CR. It also reads backend information and access credentials from `BackupStorage` CR, Storage Secret and `Repository` path respectively. + +15. Then, the `Job` dumps the targeted `Qdrant` database and uploads the output to the backend. KubeStash pipes the output of dump command to uploading process. Hence, backup `Job` does not require a large volume to hold the entire dump output. + +16. After the backup process is completed, the backup `Job` updates the `status.components[dump]` field of the `Snapshot` resources with backup information of the target `Qdrant` database. + +## How Restore Process Works + +The restore process consists of the following steps: + +1. At first, a user creates a `Qdrant` database where the data will be restored or the user can use the same `Qdrant` database. + +2. Then, she creates a `RestoreSession` custom resource that specifies the target database where the backed-up data will be restored, addon information (including restore tasks), the target snapshot to be restored, the Repository containing that snapshot, and other additional settings. + +3. KubeStash operator watches for `RestoreSession` custom resources. + +4. When it finds a `RestoreSession` custom resource, it resolves the respective `Addon` and `Function` and prepares a restore `Job` definition. + +5. Then, it creates the `Job` to restore the target. + +6. The `Job` reads necessary information to connect with the database from respective `AppBinding` CR. It also reads backend information and access credentials from `Repository` CR and storage `Secret` respectively. + +7. Then, the `Job` downloads the backed up data from the backend and injects into the desired database. KubeStash pipes the downloaded data to the respective database tool to inject into the database. Hence, restore `Job` does not require a large volume to download entire backup data inside it. + +8. Finally, when the restore process is completed, the `Job` updates the `status.components[*]` field of the `RestoreSession` with restore information of the target database. + +## Next Steps + +- Backup a `Qdrant` database using KubeStash by the following guides from [here](/docs/guides/qdrant/backup/logical/index.md). diff --git a/docs/guides/qdrant/backup/volumesnapshot/index.md b/docs/guides/qdrant/backup/volumesnapshot/index.md new file mode 100644 index 000000000..07dee987a --- /dev/null +++ b/docs/guides/qdrant/backup/volumesnapshot/index.md @@ -0,0 +1,448 @@ +--- +title: Volume Snapshot Backup & Restore Qdrant +description: Backup Qdrant database using Volume Snapshot +menu: + docs_{{ .version }}: + identifier: guides-qdrant-volume-snapshot + name: Volume Snapshot + parent: qdrant-backup + weight: 20 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +# Volume Snapshot Backup and Restore Qdrant Database + +KubeStash allows you to take volume snapshot backups of Qdrant databases. Volume snapshots provide a fast and efficient way to backup and restore the entire storage volume of your Qdrant cluster. This guide will show you how to configure volume snapshot backup and restore for Qdrant databases. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the `kubectl` command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using `Minikube` or `Kind`. +- Install `KubeDB` in your cluster following the steps [here](/docs/setup/README.md). +- Install `KubeStash` in your cluster following the steps [here](https://kubestash.com/docs/latest/setup/install/kubestash). +- To install `External-snapshotter` in your cluster following the steps [here](https://github.com/kubernetes-csi/external-snapshotter/tree/release-5.0). + +To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +> **Note:** YAML files used in this tutorial are stored in [docs/examples/qdrant/backup/volumesnapshot/examples](https://github.com/kubedb/docs/tree/{{< param "info.version" >}}/docs/examples/qdrant/backup/volumesnapshot/examples) directory of [kubedb/docs](https://github.com/kubedb/docs) repository. + +### BackupStorage +BackupStorage is a CR provided by KubeStash that can manage storage from various providers like GCS, S3, and more. + +```yaml +apiVersion: storage.kubestash.com/v1alpha1 +kind: BackupStorage +metadata: + name: storage + namespace: demo +spec: + storage: + provider: s3 + s3: + endpoint: s3.amazonaws.com + bucket: qdrant-backups + region: us-east-1 + prefix: backup-demo + secretName: s3-secret + usagePolicy: + allowedNamespaces: + from: All + deletionPolicy: WipeOut +``` + +Apply the BackupStorage: + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/backup/volumesnapshot/examples/backupstorage.yaml +backupstorage.storage.kubestash.com/minio-storage created +``` +Note: Before applying this yaml, verify that a bucket named `qdrant-backups` is already created on your bucket provider. + +### Create Storage Secret + +Create a secret with credentials to access the storage: + +```yaml +apiVersion: v1 +kind: Secret +type: Opaque +metadata: + name: s3-secret + namespace: demo +stringData: + AWS_ACCESS_KEY_ID: "*************26CX" + AWS_SECRET_ACCESS_KEY: "************jj3lp" + AWS_ENDPOINT: s3.amazonaws.com +``` + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/backup/volumesnapshot/examples/storage-secret.yaml +secret/s3-secret created +``` + +### Create Encryption Secret + +Create a secret for encrypting the backup data: + +```bash +$ echo -n 'changeit' > RESTIC_PASSWORD +$ kubectl create secret generic -n demo encrypt-secret \ + --from-file=./RESTIC_PASSWORD +secret "encrypt-secret" created +``` + +### Create RetentionPolicy + +Now, let's create a `RetentionPolicy` to specify how the old Snapshots should be cleaned up. + +Below is the YAML of the `RetentionPolicy` object that we are going to create, + +```yaml +apiVersion: storage.kubestash.com/v1alpha1 +kind: RetentionPolicy +metadata: + name: qdrant-retention-policy + namespace: demo +spec: + maxNumberOfSnapshots: 5 + usagePolicy: + allowedNamespaces: + from: All +``` + +Let's create the above `RetentionPolicy`, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/backup/volumesnapshot/examples/retentionpolicy.yaml +retentionpolicy.storage.kubestash.com/demo-retention created +``` + +## Deploy Sample Qdrant Database + +Let's deploy a sample `Qdrant` database and insert some data into it. + +**Create Qdrant CR:** + +Below is the YAML of a sample `Qdrant` CRD that we are going to create for this tutorial: + +```yaml +apiVersion: kubedb.com/v1 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + mode: Distributed + replicas: 3 + storage: + storageClassName: longhorn + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 200Mi + deletionPolicy: WipeOut +``` + +Create the above `Qdrant` CR, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/backup/volumesnapshot/examples/qdrant.yaml +qdrant.kubedb.com/qdrant-sample created +``` + +KubeDB will deploy a Qdrant database according to the above specification. + +Let's check if the database is ready to use, + +```bash +$ kubectl get qdrant -n demo +NAME VERSION STATUS AGE +qdrant-sample 1.17.0 Ready 4m22s +``` + +**Insert Sample Data:** + +Now, we are going to exec into the database pod and create some sample data. At first, find out the database `Pod` using the following command, + +```bash +$ kubectl get pods -n demo --selector="app.kubernetes.io/instance=qdrant-sample" +NAME READY STATUS RESTARTS AGE +qdrant-sample-0 1/1 Running 0 2m41s +qdrant-sample-1 1/1 Running 0 2m35s +qdrant-sample-2 1/1 Running 0 2m29s +``` + +Now, let's exec into the Pod to insert some sample data into Qdrant: + +```bash +$ kubectl exec -it -n demo qdrant-sample-0 -- sh +# Upload some sample points to a collection +$ wget -qO- --header 'Content-Type: application/json' \ + --post-data '{ + "vectors": [ + {"id": 1, "vector": [0.1, 0.2, 0.3, 0.4]}, + {"id": 2, "vector": [0.5, 0.6, 0.7, 0.8]} + ] + }' \ + http://localhost:6333/collections/my_collection/points +# Exit the pod +$ exit +``` + +Now, we are ready to backup the database. + +## Backup + +We have to create a `BackupConfiguration` targeting respective `qdrant-sample` Qdrant database. Then, KubeStash will create a `CronJob` for each session to take periodic backup of that database using volume snapshots. + +**Create BackupConfiguration:** + +Below is the YAML for `BackupConfiguration` CR to backup the `qdrant-sample` database that we have deployed earlier, + +```yaml +apiVersion: core.kubestash.com/v1alpha1 +kind: BackupConfiguration +metadata: + name: qdrant-sample-backup + namespace: demo +spec: + target: + apiGroup: kubedb.com + kind: Qdrant + namespace: demo + name: qdrant-sample + backends: + - name: minio-backend + storageRef: + namespace: demo + name: minio-storage + retentionPolicy: + name: demo-retention + namespace: demo + sessions: + - name: frequent-backup + scheduler: + schedule: "*/5 * * * *" + jobTemplate: + backoffLimit: 1 + repositories: + - name: minio-qdrant-repo + backend: minio-backend + directory: /qdrant + encryptionSecret: + name: encrypt-secret + namespace: demo + addon: + name: qdrant-addon + tasks: + - name: volume-snapshot + params: + volumeSnapshotClassName: "longhorn-snapshot-vsc" +``` + +Here, +- `.spec.sessions[*].schedule` specifies that we want to backup the database at `5 minutes` interval. +- `.spec.target` refers to the targeted `qdrant-sample` Qdrant database that we created earlier. +- `.spec.sessions[*].addon.tasks[*].params[*].volumeSnapshotClassName` specifies the `VolumeSnapshotClass` to use for creating volume snapshots. + +Let's create the `BackupConfiguration` CR that we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/backup/volumesnapshot/examples/backupconfiguration.yaml +backupconfiguration.core.kubestash.com/qdrant-sample-backup created +``` + +**Verify Backup Setup Successful:** + +If everything goes well, the phase of the `BackupConfiguration` should be `Ready`. The `Ready` phase indicates that the backup setup is successful. Let's verify the `Phase` of the BackupConfiguration, + +```bash +$ kubectl get backupconfiguration -n demo +NAME PHASE PAUSED AGE +qdrant-sample-backup Ready 2m50s +``` + +Additionally, we can verify that the `Repository` specified in the `BackupConfiguration` has been created using the following command, + +```bash +$ kubectl get repo -n demo +NAME INTEGRITY SNAPSHOT-COUNT SIZE PHASE LAST-SUCCESSFUL-BACKUP AGE +minio-qdrant-repo 0 0 B Ready 3m +``` + +**Verify VolumeSnapshot:** + +It will create a `VolumeSnapshot` for each PVC of the Qdrant database. + +Verify that the `VolumeSnapshot` has been created using the following command, + +```bash +$ kubectl get volumesnapshot -n demo +NAME READYTOUSE SOURCEPVC SOURCESNAPSHOTCONTENT RESTORESIZE SNAPSHOTCLASS SNAPSHOTCONTENT CREATIONTIME AGE +minio-qdrant-repo-xyz true data-qdrant-sample-0 1Gi longhorn-snapshot-vsc snapcontent-xyz 2m 2m +``` + +**Verify BackupSession:** + +KubeStash triggers an instant backup as soon as the `BackupConfiguration` is ready. After that, backups are scheduled according to the specified schedule. + +```bash +$ kubectl get backupsession -n demo -w + +NAME INVOKER-TYPE INVOKER-NAME PHASE DURATION AGE +qdrant-sample-backup-frequent-backup-xyz BackupConfiguration qdrant-sample-backup Succeeded 7m22s +``` + +We can see from the above output that the backup session has succeeded. + +## Restore + +In this section, we are going to restore the database from the volume snapshot backup we have taken in the previous section. We are going to deploy a new database and initialize it from the backup. + +#### Deploy Restored Database: + +Now, we have to deploy the restored database similarly as we have deployed the original `qdrant-sample` database. However, this time there will be the following differences: + +- We are going to specify `.spec.init.waitForInitialRestore` field that tells KubeDB to wait for first restore to complete before marking this database is ready to use. + +Below is the YAML for `Qdrant` CRD we are going deploy to initialize from backup, + +```yaml +apiVersion: kubedb.com/v1 +kind: Qdrant +metadata: + name: restored-qdrant + namespace: demo +spec: + init: + waitForInitialRestore: true + version: "1.17.0" + mode: Distributed + replicas: 3 + storage: + storageClassName: longhorn + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 200Mi + deletionPolicy: WipeOut +``` + +Let's create the above database, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/backup/volumesnapshot/examples/qdrant-restored.yaml +qdrant.kubedb.com/restored-qdrant created +``` + +If you check the database status, you will see it is stuck in `Provisioning` state. + +```bash +$ kubectl get qdrant -n demo restored-qdrant +NAME VERSION STATUS AGE +restored-qdrant 1.17.0 Provisioning 61s +``` + +#### Create RestoreSession: + +Now, we need to create a RestoreSession CRD pointing to targeted `Qdrant` database. + +Below, is the contents of YAML file of the `RestoreSession` object that we are going to create to restore backed up data into the newly created database provisioned by Qdrant object named `restored-qdrant`. + +```yaml +apiVersion: core.kubestash.com/v1alpha1 +kind: RestoreSession +metadata: + name: restore-qdrant-sample + namespace: demo +spec: + target: + apiGroup: kubedb.com + kind: Qdrant + namespace: demo + name: restored-qdrant + dataSource: + repository: minio-qdrant-repo + snapshot: latest + encryptionSecret: + name: encrypt-secret + namespace: demo + addon: + name: qdrant-addon + tasks: + - name: volume-snapshot-restore +``` + +Let's create the RestoreSession CRD object we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/backup/volumesnapshot/examples/restoresession.yaml +restoresession.core.kubestash.com/restore-qdrant-sample created +``` + +Once, you have created the `RestoreSession` object, KubeStash will create restore Job. Run the following command to watch the phase of the `RestoreSession` object, + +```bash +$ watch kubectl get restoresession -n demo +Every 2.0s: kubectl get restores... AppsCode-PC-03: Wed Aug 21 10:44:05 2024 + +NAME REPOSITORY FAILURE-POLICY PHASE DURATION AGE +restore-qdrant-sample minio-qdrant-repo Succeeded 3s 53s +``` + +The `Succeeded` phase means that the restore process has been completed successfully. + +#### Verify Restored Data: + +In this section, we are going to verify whether the desired data has been restored successfully. We are going to connect to the database server and check whether the collection we created earlier in the original database are restored. + +At first, check if the database has gone into `Ready` state by the following command, + +```bash +$ kubectl get qdrant -n demo restored-qdrant +NAME VERSION STATUS AGE +restored-qdrant 1.17.0 Ready 34m +``` + +Now, find out the database `Pod` by the following command, + +```bash +$ kubectl get pods -n demo --selector="app.kubernetes.io/instance=restored-qdrant" +NAME READY STATUS RESTARTS AGE +restored-qdrant-0 1/1 Running 0 39m +``` + +Now, let's exec into the Pod to enter into Qdrant and verify restored data, + +```bash +$ kubectl exec -it -n demo restored-qdrant-0 -- sh +# Check if the collection exists and has data +$ wget -qO- http://localhost:6333/collections/my_collection +# Exit the pod +$ exit +``` + +So, from the above output, we can see that the `my_collection` collection we created earlier in the original database and now, it is restored successfully. + +## Cleanup + +To cleanup the Kubernetes resources created by this tutorial, run: + +```bash +kubectl delete backupconfigurations.core.kubestash.com -n demo qdrant-sample-backup +kubectl delete restoresessions.core.kubestash.com -n demo restore-qdrant-sample +kubectl delete retentionpolicies.storage.kubestash.com -n demo demo-retention +kubectl delete backupstorage -n demo minio-storage +kubectl delete secret -n demo aws-secret +kubectl delete secret -n demo encrypt-secret +kubectl delete qdrant -n demo restored-qdrant +kubectl delete qdrant -n demo qdrant-sample +``` diff --git a/docs/guides/qdrant/concepts/_index.md b/docs/guides/qdrant/concepts/_index.md new file mode 100644 index 000000000..589884fba --- /dev/null +++ b/docs/guides/qdrant/concepts/_index.md @@ -0,0 +1,10 @@ +--- +title: Qdrant Concepts +menu: + docs_{{ .version }}: + identifier: qdrant-concepts + name: Concepts + parent: qdrant-guides + weight: 20 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/qdrant/concepts/autoscaler.md b/docs/guides/qdrant/concepts/autoscaler.md new file mode 100644 index 000000000..c29a3c9b3 --- /dev/null +++ b/docs/guides/qdrant/concepts/autoscaler.md @@ -0,0 +1,127 @@ +--- +title: QdrantAutoscaler CRD +menu: + docs_{{ .version }}: + identifier: qdrant-autoscaler-concepts + name: QdrantAutoscaler + parent: qdrant-concepts + weight: 30 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# QdrantAutoscaler + +## What is QdrantAutoscaler + +`QdrantAutoscaler` is a Kubernetes `Custom Resource Definitions` (CRD). It provides a declarative configuration for automatic scaling of [Qdrant](https://qdrant.tech/) compute resources (CPU, memory) and storage in a Kubernetes native way. + +## QdrantAutoscaler CRD Specifications + +Like any official Kubernetes resource, a `QdrantAutoscaler` has `TypeMeta`, `ObjectMeta`, `Spec` and `Status` sections. + +**Sample `QdrantAutoscaler` for compute autoscaling:** + +```yaml +apiVersion: autoscaling.kubedb.com/v1alpha1 +kind: QdrantAutoscaler +metadata: + name: qdrant-as-compute + namespace: demo +spec: + databaseRef: + name: qdrant-sample + opsRequestOptions: + timeout: 3m + apply: IfReady + compute: + node: + trigger: "On" + podLifeTimeThreshold: 10m + resourceDiffPercentage: 20 + minAllowed: + cpu: 400m + memory: 400Mi + maxAllowed: + cpu: 1 + memory: 2Gi + controlledResources: ["cpu", "memory"] + containerControlledValues: "RequestsAndLimits" +``` + +**Sample `QdrantAutoscaler` for storage autoscaling:** + +```yaml +apiVersion: autoscaling.kubedb.com/v1alpha1 +kind: QdrantAutoscaler +metadata: + name: qdrant-as-storage + namespace: demo +spec: + databaseRef: + name: qdrant-sample + storage: + node: + trigger: "On" + usageThreshold: 20 + scalingThreshold: 20 + expansionMode: "Online" +``` + +### QdrantAutoscaler `Spec` + +A `QdrantAutoscaler` object has the following fields in the `spec` section: + +#### spec.databaseRef + +`spec.databaseRef` is a required field that points to the [Qdrant](/docs/guides/qdrant/concepts/) object for which autoscaling will be performed. It contains: + +- `spec.databaseRef.name` — the name of the target Qdrant database (required). + +#### spec.compute + +`spec.compute` specifies the compute (CPU and memory) autoscaling configuration. It contains: + +- `spec.compute.node` — the per-node compute autoscaling configuration: + - `trigger` — enables (`On`) or disables (`Off`) compute autoscaling. + - `podLifeTimeThreshold` — the minimum age of a pod before VPA can recommend resource updates. + - `resourceDiffPercentage` — the minimum percentage difference required before applying a recommendation. + - `minAllowed` — the minimum allowed CPU and memory resources. + - `maxAllowed` — the maximum allowed CPU and memory resources. + - `controlledResources` — the list of resources to be controlled (e.g., `["cpu", "memory"]`). + - `containerControlledValues` — specifies whether to control `RequestsAndLimits` or `RequestsOnly`. + - `inMemoryStorage` — configuration for in-memory storage autoscaling per node: + - `scalingFactorPercentage` — the scaling factor percentage for in-memory storage. + - `usageThresholdPercentage` — the usage threshold percentage that triggers scaling. +- `spec.compute.nodeTopology` — specifies per-node topology for compute autoscaling: + - `name` — the name of the topology entry. + - `scaleDownDiffPercentage` — the scale-down difference percentage for this topology. + - `scaleUpDiffPercentage` — the scale-up difference percentage for this topology. + +#### spec.storage + +`spec.storage` specifies the storage autoscaling configuration. It contains a `node` sub-section with the following fields: + +- `spec.storage.node.trigger` — enables (`On`) or disables (`Off`) storage autoscaling. +- `spec.storage.node.usageThreshold` — the storage usage threshold (percentage) that triggers autoscaling. +- `spec.storage.node.scalingThreshold` — the percentage by which storage will be scaled when triggered. +- `spec.storage.node.expansionMode` — the volume expansion mode (`Online` or `Offline`). +- `spec.storage.node.upperBound` — the upper bound for storage size. +- `spec.storage.node.scalingRules` — a list of scaling rule objects, each containing: + - `appliesUpto` — the upper limit for which this rule applies. + - `threshold` — the threshold for this scaling rule. + +#### spec.opsRequestOptions + +`spec.opsRequestOptions` specifies the options for the `QdrantOpsRequest` created by the autoscaler. It contains: + +- `spec.opsRequestOptions.timeout` — the timeout for the generated ops request. +- `spec.opsRequestOptions.apply` — when to apply the ops request. Can be `Always` or `IfReady`. +- `spec.opsRequestOptions.maxRetries` — the maximum number of retries for the ops request. + +## Next Steps + +- Read the [Qdrant autoscaler overview](/docs/guides/qdrant/autoscaler/overview.md). +- See the [compute autoscaler guide](/docs/guides/qdrant/autoscaler/compute/compute-autoscale.md) and [storage autoscaler guide](/docs/guides/qdrant/autoscaler/storage/storage-autoscale.md). \ No newline at end of file diff --git a/docs/guides/qdrant/concepts/catalog.md b/docs/guides/qdrant/concepts/catalog.md new file mode 100644 index 000000000..f7fc209e3 --- /dev/null +++ b/docs/guides/qdrant/concepts/catalog.md @@ -0,0 +1,98 @@ +--- +title: QdrantVersion CRD +menu: + docs_{{ .version }}: + identifier: qdrant-catalog-concepts + name: QdrantVersion + parent: qdrant-concepts + weight: 15 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# QdrantVersion + +## What is QdrantVersion + +`QdrantVersion` is a Kubernetes `Custom Resource Definitions` (CRD). It provides a declarative configuration to specify the Docker images to be used for [Qdrant](https://qdrant.tech/) database deployed with KubeDB in a Kubernetes native way. + +When you install KubeDB, a `QdrantVersion` custom resource will be created automatically for every supported Qdrant version. You have to specify the name of the `QdrantVersion` CRD in `spec.version` field of the [Qdrant](/docs/guides/qdrant/concepts/qdrant.md) CRD. Then, KubeDB will use the Docker images specified in the `QdrantVersion` CRD to create your expected database. + +Using a separate CRD for specifying respective Docker images allows us to modify images independent of the KubeDB operator. This also allows users to use a custom image for the database. + +## QdrantVersion Specification + +As with all other Kubernetes objects, a `QdrantVersion` needs `apiVersion`, `kind`, and `metadata` fields. It also needs a `.spec` section. + +```yaml +apiVersion: catalog.kubedb.com/v1alpha1 +kind: QdrantVersion +metadata: + name: "1.17.0" +spec: + version: "1.17.0" + db: + image: "qdrant/qdrant:v1.17.0" + deprecated: false +``` + +### metadata.name + +`metadata.name` is a required field that specifies the name of the `QdrantVersion` CRD. You have to specify this name in `spec.version` field of the [Qdrant](/docs/guides/qdrant/concepts/qdrant.md) CRD. + +The naming convention for `QdrantVersion` CRD follows the pattern `{Original Qdrant version}`. + +### spec.version + +`spec.version` is a required field that specifies the original version of the Qdrant database that has been used to build the Docker image specified in `spec.db.image` field. + +### spec.deprecated + +`spec.deprecated` is an optional field that specifies whether the Docker images specified here are supported by the current KubeDB operator. + +The default value of this field is `false`. If `spec.deprecated` is set to `true`, KubeDB operator will not create the database and other respective resources for this version. + +### spec.db.image + +`spec.db.image` is a required field that specifies the Docker image which will be used to create the Petset by KubeDB operator to create the expected Qdrant database. + +```bash +$ kubectl get qdrantversions +NAME VERSION DB_IMAGE DEPRECATED AGE +1.15.4 1.15.4 docker.io/qdrant/qdrant:v1.15.4-unprivileged 28d +1.16.2 1.16.2 docker.io/qdrant/qdrant:v1.16.2-unprivileged 28d +1.17.0 1.17.0 docker.io/qdrant/qdrant:v1.17.0-unprivileged 28d +``` + +### spec.endOfLife + +`spec.endOfLife` is an optional `` field that indicates whether this Qdrant version has reached its end of life. + +### spec.securityContext + +`spec.securityContext` specifies the security context for the database container. It contains: + +- `spec.securityContext.runAsUser` — the user ID to run the container as. + +### spec.ui + +`spec.ui` is an optional array that specifies the UI configuration for this Qdrant version. Each entry contains: + +- `name` — the name of the UI component. +- `version` — the version of the UI component. +- `values` — configuration values for the UI component. +- `disable` — whether the UI component is disabled. + +### spec.updateConstraints + +`spec.updateConstraints` specifies constraints for version updates. It contains: + +- `spec.updateConstraints.allowlist` — a list of versions that are allowed as update targets from this version. +- `spec.updateConstraints.denylist` — a list of versions that are forbidden as update targets from this version. + +## Next Steps + +- Learn about the [Qdrant CRD](/docs/guides/qdrant/concepts/qdrant.md). +- Deploy your first Qdrant database with KubeDB by following the guide [here](/docs/guides/qdrant/quickstart/quickstart.md). \ No newline at end of file diff --git a/docs/guides/qdrant/concepts/opsrequest.md b/docs/guides/qdrant/concepts/opsrequest.md new file mode 100644 index 000000000..4a7ab819a --- /dev/null +++ b/docs/guides/qdrant/concepts/opsrequest.md @@ -0,0 +1,273 @@ +--- +title: QdrantOpsRequest CRD +menu: + docs_{{ .version }}: + identifier: qdrant-opsrequest-concepts + name: QdrantOpsRequest + parent: qdrant-concepts + weight: 25 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# QdrantOpsRequest + +## What is QdrantOpsRequest + +`QdrantOpsRequest` is a Kubernetes `Custom Resource Definitions` (CRD). It provides declarative configuration for [Qdrant](https://qdrant.tech/) administrative operations like database version updating, horizontal scaling, vertical scaling, etc. in a Kubernetes native way. + +## QdrantOpsRequest CRD Specifications + +Like any official Kubernetes resource, a `QdrantOpsRequest` has `TypeMeta`, `ObjectMeta`, `Spec` and `Status` sections. + +Here are some sample `QdrantOpsRequest` CRs for different administrative operations: + +**Sample `QdrantOpsRequest` for updating database version:** + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-update-version + namespace: demo +spec: + type: UpdateVersion + databaseRef: + name: qdrant-sample + updateVersion: + targetVersion: "1.18.0" +status: + conditions: + - lastTransitionTime: "2024-10-01T10:00:00Z" + message: The controller has updated the Qdrant successfully + reason: OpsRequestSuccessful + status: "True" + type: Successful + phase: Successful +``` + +**Sample `QdrantOpsRequest` for horizontal scaling:** + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-hscale-up + namespace: demo +spec: + type: HorizontalScaling + databaseRef: + name: qdrant-sample + horizontalScaling: + node: 5 +status: + conditions: + - lastTransitionTime: "2024-10-01T10:00:00Z" + message: The controller has scaled/updated the Qdrant successfully + reason: OpsRequestSuccessful + status: "True" + type: Successful + phase: Successful +``` + +**Sample `QdrantOpsRequest` for vertical scaling:** + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-vscale + namespace: demo +spec: + type: VerticalScaling + databaseRef: + name: qdrant-sample + verticalScaling: + node: + resources: + requests: + memory: "1Gi" + cpu: "500m" + limits: + memory: "1Gi" + cpu: "500m" +status: + conditions: + - lastTransitionTime: "2024-10-01T10:00:00Z" + message: The controller has scaled/updated the Qdrant successfully + reason: OpsRequestSuccessful + status: "True" + type: Successful + phase: Successful +``` + +### QdrantOpsRequest `Spec` + +A `QdrantOpsRequest` object has the following fields in the `spec` section: + +#### spec.databaseRef + +`spec.databaseRef` is a required field that points to the [Qdrant](/docs/guides/qdrant/concepts/qdrant.md) object where the administrative operations will be applied. It contains: + +- `spec.databaseRef.name` — the name of the target Qdrant database (required). + +#### spec.type + +`spec.type` specifies the type of operation that will be applied to the database. Supported operations are: + +- `Reconfigure` — reconfigure a running Qdrant database with new configuration. +- `ReconfigureTLS` — reconfigure TLS configuration for a running Qdrant database. +- `Restart` — restart the database pods in a rolling fashion. +- `RotateAuth` — rotate the authentication credentials of a running Qdrant database. +- `UpdateVersion` — update the version of a running Qdrant database. +- `HorizontalScaling` — scale the number of nodes up or down. +- `VerticalScaling` — vertically scale the resources (CPU and memory) of database pods. +- `VolumeExpansion` — expand the persistent volume claim size of a running Qdrant database. + +#### spec.authentication + +`spec.authentication` is used when `spec.type` is `RotateAuth`. It contains: + +- `spec.authentication.secretRef` — a reference to the secret containing the new authentication credentials: + - `apiGroup` — the API group of the referenced secret. + - `kind` — the kind of the referenced secret. + - `name` — the name of the secret (required). + +#### spec.maxRetries + +`spec.maxRetries` is an optional `` field that specifies the maximum number of times the ops request should be retried if it fails. + +#### spec.migration + +`spec.migration` is used when `spec.type` is `VolumeExpansion` or other migration-requiring operations. It contains: + +- `spec.migration.storageClassName` — the target storage class name for migration. +- `spec.migration.oldPVReclaimPolicy` — the reclaim policy for the old PersistentVolume. + +#### spec.restart + +`spec.restart` is used when `spec.type` is `Restart`. It is an empty object (`{}`). No further configuration is needed for a restart operation. + +#### spec.updateVersion + +`spec.updateVersion` is used when `spec.type` is `UpdateVersion`. It contains: + +- `spec.updateVersion.targetVersion` — the target `QdrantVersion` to update to. + +#### spec.horizontalScaling + +`spec.horizontalScaling` is used when `spec.type` is `HorizontalScaling`. It contains: + +- `spec.horizontalScaling.node` — the desired number of Qdrant nodes. + +#### spec.verticalScaling + +`spec.verticalScaling` is used when `spec.type` is `VerticalScaling`. It contains: + +- `spec.verticalScaling.node` — the per-node vertical scaling configuration: + - `resources` — the CPU and memory resource requests and limits for Qdrant nodes. + - `nodeSelectionPolicy` — the policy for selecting nodes to scale. + - `topology` — the topology constraints for the vertical scaling operation: + - `key` — the topology key (required). + - `value` — the topology value (required). + +#### spec.volumeExpansion + +`spec.volumeExpansion` is used when `spec.type` is `VolumeExpansion`. It contains: + +- `spec.volumeExpansion.node` — the per-node volume expansion configuration. Can be an empty object `{}` if the volume expansion should use defaults. +- `spec.volumeExpansion.mode` — the volume expansion mode. Can be `Online` or `Offline`. + +#### spec.tls + +`spec.tls` is used when `spec.type` is `ReconfigureTLS`. It contains: + +- `spec.tls.client` — TLS configuration for client connections. +- `spec.tls.p2p` — TLS configuration for peer-to-peer connections. +- `spec.tls.remove` — specifies whether to remove TLS configuration. +- `spec.tls.rotateCertificates` — specifies whether to rotate TLS certificates. + +#### spec.configuration + +`spec.configuration` is used when `spec.type` is `Reconfigure`. It contains: + +- `spec.configuration.applyConfig` — a map of key-value pairs for inline configuration changes. +- `spec.configuration.configSecret` — the secret containing the new configuration. +- `spec.configuration.removeCustomConfig` — specifies whether to remove the custom configuration. +- `spec.configuration.restart` — specifies the restart behavior after applying configuration. Supported values are `auto`, `true`, and `false`. + +#### spec.timeout + +`spec.timeout` is an optional field that specifies the timeout duration for the OpsRequest to complete. If the OpsRequest does not complete within the specified timeout, it will be marked as failed. The value is in the form of a Kubernetes duration (e.g., `5m`, `1h`). + +#### spec.apply + +`spec.apply` is an optional field that specifies when the OpsRequest will be applied. Possible values are `Always` and `IfReady`. The default is `IfReady`, which means the OpsRequest will only be applied when the target database is in `Ready` state. + +### QdrantOpsRequest `Status` + +`.status` describes the current state and progress of the `QdrantOpsRequest` operation. It has the following fields: + +#### status.phase + +`status.phase` indicates the overall phase of the operation for this `QdrantOpsRequest`. It can have the following values: + +| Phase | Meaning | +|--------------------|---------------------------------------------------------------------------------| +| Pending | The QdrantOpsRequest has been created but execution has not started yet | +| Progressing | KubeDB has started the execution of the applied QdrantOpsRequest | +| Successful | KubeDB has successfully performed the operation requested in the QdrantOpsRequest | +| Failed | KubeDB has failed the operation requested in the QdrantOpsRequest | +| Denied | KubeDB has denied the operation requested in the QdrantOpsRequest | +| Skipped | KubeDB has skipped the operation requested in the QdrantOpsRequest | +| WaitingForApproval | The QdrantOpsRequest is waiting for approval before execution | + +Ops-manager Operator can skip an opsRequest only if its execution has not been started yet and there is a newer opsRequest applied in the cluster. `spec.type` has to be the same as the skipped one, in this case. + +#### status.pausedBackups + +`status.pausedBackups` is a list of references to backup objects that were paused during the operation. Each entry has: + +- `apiGroup` — the API group of the paused backup. +- `kind` — the kind of the paused backup. +- `name` — the name of the paused backup (required). +- `namespace` — the namespace of the paused backup. + +#### status.observedGeneration + +`status.observedGeneration` shows the most recent generation observed by the `QdrantOpsRequest` controller. + +#### status.conditions + +`status.conditions` is an array that specifies the conditions of different steps of `QdrantOpsRequest` processing. Each condition entry has the following fields: + +- `type` specifies the type of the condition. QdrantOpsRequest has the following types of conditions: + +| Type | Meaning | +|---------------------|----------------------------------------------------------------------------------| +| `Progressing` | Specifies that the operation is now progressing | +| `Successful` | Specifies that the operation on the database has been successful | +| `HaltDatabase` | Specifies that the database is halted by the operator | +| `ResumeDatabase` | Specifies that the database is resumed by the operator | +| `Failed` | Specifies that the operation on the database has failed | +| `Scaling` | Specifies that the scaling operation on the database has started | +| `VerticalScaling` | Specifies that vertical scaling has performed successfully on the database | +| `HorizontalScaling` | Specifies that horizontal scaling has performed successfully on the database | +| `Updating` | Specifies that the database updating operation has started | +| `UpdateVersion` | Specifies that version updating on the database has performed successfully | + +- The `status` field is a string, with possible values `"True"`, `"False"`, and `"Unknown"`. + - `status` will be `"True"` if the current transition is succeeded. + - `status` will be `"False"` if the current transition is failed. + - `status` will be `"Unknown"` if the current transition is denied. +- The `message` field is a human-readable message indicating details about the condition. +- The `reason` field is a unique, one-word, CamelCase reason for the condition's last transition. +- The `lastTransitionTime` field provides a timestamp for when the operation last transitioned from one state to another. +- The `observedGeneration` shows the most recent condition transition generation observed by the controller. + +## Next Steps + +- See [Qdrant ops request overview](/docs/guides/qdrant/ops-request/overview.md) for operation links. +- Follow operation tutorials like [Restart](/docs/guides/qdrant/restart/restart.md) and [Volume Expansion](/docs/guides/qdrant/volume-expansion/volume-expansion.md). \ No newline at end of file diff --git a/docs/guides/qdrant/concepts/qdrant.md b/docs/guides/qdrant/concepts/qdrant.md new file mode 100644 index 000000000..f01e39773 --- /dev/null +++ b/docs/guides/qdrant/concepts/qdrant.md @@ -0,0 +1,236 @@ +--- +title: Qdrant CRD +menu: + docs_{{ .version }}: + identifier: qdrant-concepts-qdrant + name: Qdrant + parent: qdrant-concepts + weight: 10 +menu_name: docs_{{ .version }} +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Qdrant + +## What is Qdrant + +`Qdrant` is a Kubernetes `Custom Resource Definitions` (CRD). It provides declarative configuration for [Qdrant](https://qdrant.tech/) vector databases in a Kubernetes native way. You only need to describe the desired database configuration in a `Qdrant` object, and the KubeDB operator will create Kubernetes objects in the desired state for you. + +## Qdrant Spec + +As with all other Kubernetes objects, a `Qdrant` CR needs `apiVersion`, `kind`, and `metadata` fields. It also needs a `.spec` section. + +Below is an example `Qdrant` object: + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + replicas: 3 + authSecret: + name: qdrant-sample-auth + configSecret: + name: qdrant-config + storageType: Durable + storage: + storageClassName: standard + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + tls: + issuerRef: + apiGroup: "cert-manager.io" + kind: Issuer + name: qdrant-issuer + monitor: + agent: prometheus.io/operator + prometheus: + serviceMonitor: + labels: + app: kubedb + interval: 10s + podTemplate: + metadata: + annotations: + passMe: ToDatabasePod + spec: + serviceAccountName: my-custom-sa + nodeSelector: + disktype: ssd + imagePullSecrets: + - name: myregistrykey + containers: + - name: qdrant + resources: + requests: + memory: "512Mi" + cpu: "500m" + limits: + memory: "1Gi" + cpu: "1" + serviceTemplates: + - alias: primary + spec: + type: LoadBalancer + deletionPolicy: Halt +``` + +### spec.version + +`spec.version` (required) specifies the name of the [QdrantVersion](/docs/guides/qdrant/concepts/catalog.md) CRD where the docker images are specified. + +```bash +$ kubectl get qdrantversions +NAME VERSION DB_IMAGE DEPRECATED AGE +1.15.4 1.15.4 docker.io/qdrant/qdrant:v1.15.4-unprivileged 28d +1.16.2 1.16.2 docker.io/qdrant/qdrant:v1.16.2-unprivileged 28d +1.17.0 1.17.0 docker.io/qdrant/qdrant:v1.17.0-unprivileged 28d +``` + +### spec.replicas + +`spec.replicas` is an optional `` field that specifies the number of Qdrant pods to run. For a single-node deployment, set it to `1`. For a multi-node distributed cluster, set it to the desired number of replicas (e.g., `3`). + +### spec.mode + +`spec.mode` specifies the deployment mode for the Qdrant cluster. Supported values are: + +- `Standalone` — runs a single Qdrant node. +- `Distributed` — runs a multi-node Qdrant cluster with peer-to-peer communication. Required for `spec.tls.p2p`. + +### spec.authSecret + +`spec.authSecret` is an optional field that points to a Secret used for Qdrant API key authentication. If not provided, KubeDB will create one automatically. It contains the following sub-fields: + +- `name` — the name of the Secret (required). +- `kind` — the kind of the secret reference (required). +- `apiGroup` — the API group of the secret reference. +- `externallyManaged` — specifies whether the secret is managed externally. +- `activeFrom` — the time from which the secret becomes active. +- `rotateAfter` — the duration after which the secret should be rotated. +- `secretStoreName` — the name of the external secret store. + +### spec.configSecret + +`spec.configSecret` is an optional field that points to a Secret containing a custom `production.yaml` configuration file for Qdrant. See [Custom Configuration](/docs/guides/qdrant/configuration/using-config-file.md) for details. + +### spec.configuration + +`spec.configuration` is an optional field for providing custom Qdrant configuration. It has the following sub-fields: + +- `inline` — a map of key-value pairs for inline configuration. +- `secretName` — the name of a Secret containing the configuration. + +### spec.storageType + +`spec.storageType` specifies the type of storage that will be used for Qdrant. Supported values are: + +- `Durable` — uses PersistentVolumeClaims (default). +- `Ephemeral` — uses `EmptyDir` volumes (useful for testing). + +### spec.storage + +`spec.storage` specifies the PersistentVolumeClaim configuration for Qdrant data. It contains standard PVC fields like `storageClassName`, `accessModes`, `resources`, `selector`, etc. + +### spec.healthChecker + +`spec.healthChecker` specifies the configuration for database health checking. It contains the following sub-fields: + +- `disableWriteCheck` — disables write health checks. +- `failureThreshold` — the number of consecutive failures before marking the database as unhealthy. +- `periodSeconds` — the interval between health checks. +- `timeoutSeconds` — the timeout for each health check. + +### spec.halted + +`spec.halted` is an optional `` field. When set to `true`, the database will be halted (all pods stopped) while preserving the PVCs and other resources. + +### spec.disableSecurity + +`spec.disableSecurity` is an optional `` field that disables API key authentication when set to `true`. The default is `false`. + +### spec.tls + +`spec.tls` specifies the TLS/SSL configurations for the Qdrant database. KubeDB uses [cert-manager](https://cert-manager.io/) v1 api to provision and manage TLS certificates. + +The following fields are configurable in the `spec.tls` section: + +- `issuerRef` is a reference to the `Issuer` or `ClusterIssuer` CR of [cert-manager](https://cert-manager.io/docs/concepts/issuer/) that will be used by `KubeDB` to generate necessary certificates. + + - `apiGroup` is the group name of the resource that is being referenced. Currently, the only supported value is `cert-manager.io`. + - `kind` — the type of resource. KubeDB supports both `Issuer` and `ClusterIssuer`. + - `name` — the name of the resource being referenced (required). + +- `client` (optional, ``, default `false`) enables TLS for client-to-server communication. When set to `true`, the Qdrant server will accept TLS-encrypted connections from clients. + +- `p2p` (optional, ``, default `false`) enables TLS for peer-to-peer communication between Qdrant nodes. When set to `true`, inter-node communication within the Qdrant cluster will be encrypted using TLS. Requires `spec.mode` to be `Distributed`. + +- `certificates` (optional) is a list of additional certificates used to configure the Qdrant server. Each certificate has the following fields: + - `alias` — the identifier of the certificate (required). The supported value is `server`. + - `secretName` (optional) specifies the Kubernetes secret name that holds the certificates. If not specified, defaults to `--cert`. + - `issuerRef` (optional) specifies a separate issuer for this certificate. If not set, the top-level `issuerRef` is used. + - `apiGroup` — the API group of the issuer. + - `kind` — the kind of the issuer (`Issuer` or `ClusterIssuer`). + - `name` — the name of the issuer. + - `subject` (optional) specifies an `X.509` distinguished name with the following sub-fields: + - `organizations` — list of organization names. + - `organizationalUnits` — list of organization unit names. + - `countries` — list of country names. + - `localities` — list of locality names. + - `provinces` — list of province names. + - `streetAddresses` — list of street addresses. + - `postalCodes` — list of postal codes. + - `serialNumber` — serial number. + - `duration` (optional) — the validity period of the certificate. + - `renewBefore` (optional) — the time before expiration to renew the certificate. + - `dnsNames` (optional) — list of DNS subject alternative names. + - `ipAddresses` (optional) — list of IP subject alternative names. + - `uris` (optional) — list of URI Subject Alternative Names. + - `emailAddresses` (optional) — list of email Subject Alternative Names. + - `privateKey` (optional) specifies options for the private key: + - `encoding` — the private key encoding. Supported values are `PKCS1` and `PKCS8`. + +### spec.monitor + +`spec.monitor` specifies the monitoring configuration for Qdrant. It contains: + +- `agent` — the monitoring agent. Supported values are `prometheus.io/builtin`, `prometheus.io`, and `prometheus.io/operator`. +- `prometheus` — Prometheus-specific configuration including `exporter` and `serviceMonitor` settings. + +### spec.podTemplate + +KubeDB allows providing a template for database pods through `spec.podTemplate`. KubeDB operator will pass the information provided in `spec.podTemplate` to the PetSet created for Qdrant database. Notable sub-fields include: + +- `spec.podTemplate.spec.serviceAccountName` — provide a custom ServiceAccount. +- `spec.podTemplate.spec.imagePullSecrets` — pull images from a private registry. +- `spec.podTemplate.spec.nodeSelector` — schedule pods on specific nodes. +- `spec.podTemplate.spec.containers[].resources` — configure CPU and memory resources. +- `spec.podTemplate.spec.containers[].env` — set environment variables for the container. + +### spec.serviceTemplates + +`spec.serviceTemplates` is an optional list of service templates. Each entry has: + +- `alias` — the service alias (required). Supported values include `primary`, `standby`, `stats`, `dashboard`, etc. +- `spec` — the service specification including `type`, `clusterIP`, `ports`, etc. + +### spec.deletionPolicy + +`spec.deletionPolicy` controls the behavior when a Qdrant object is deleted. Supported values are: + +- `Halt` — deletes the Qdrant object but keeps underlying resources (PVCs, Secrets). +- `Delete` — deletes the Qdrant object and its PVCs, but not Secrets. +- `WipeOut` — deletes the Qdrant object and all related resources including PVCs and Secrets. +- `DoNotTerminate` — prevents deletion if admission webhook is enabled. + +## Next Steps + +- Learn about [QdrantVersion CRD](/docs/guides/qdrant/concepts/catalog.md). +- Deploy your first Qdrant database with KubeDB by following the guide [here](/docs/guides/qdrant/quickstart/quickstart.md). diff --git a/docs/guides/qdrant/configuration/_index.md b/docs/guides/qdrant/configuration/_index.md new file mode 100644 index 000000000..0e8253456 --- /dev/null +++ b/docs/guides/qdrant/configuration/_index.md @@ -0,0 +1,10 @@ +--- +title: Run Qdrant with Custom Configuration +menu: + docs_{{ .version }}: + identifier: qdrant-configuration + name: Custom Configuration + parent: qdrant-guides + weight: 40 +menu_name: docs_{{ .version }} +--- \ No newline at end of file diff --git a/docs/guides/qdrant/configuration/using-config-file.md b/docs/guides/qdrant/configuration/using-config-file.md new file mode 100644 index 000000000..4be95488a --- /dev/null +++ b/docs/guides/qdrant/configuration/using-config-file.md @@ -0,0 +1,194 @@ +--- +title: Run Qdrant with Custom Configuration +menu: + docs_{{ .version }}: + identifier: qdrant-using-config-file + name: Config File + parent: qdrant-configuration + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Using Custom Configuration File + +KubeDB supports providing custom configuration for Qdrant. This tutorial will show you how to use KubeDB to run a Qdrant database with custom configuration. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the `kubectl` command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps [here](/docs/setup/README.md). + +- To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +> **Note:** YAML files used in this tutorial are stored in [docs/examples/qdrant/configuration](/docs/examples/qdrant/configuration) directory of [kubedb/docs](https://github.com/kubedb/docs) repository. + +## Overview + +KubeDB supports three ways to provide custom configuration for Qdrant: + +| Method | Field | Priority | +|--------|-------|----------| +| **Config Secret** | `spec.configuration.secretName` | Medium | +| **Inline Config** | `spec.configuration.inline` | Highest | +| **Default Config** | (built into the Docker image) | Lowest | + +The priority order is: **Inline Config > Config Secret > Default Config**. When multiple configuration sources specify the same key, the value from the higher-priority source takes precedence. Inline config values are applied last, overriding any values from the config Secret or defaults. + +To know more about configuring Qdrant, see [here](https://qdrant.tech/documentation/guides/configuration/). + +In this tutorial, we will configure `log_level` and `service.max_request_size_mb` using both a config Secret and inline configuration. + +## Custom Configuration via Config Secret + +At first, create a Secret with your custom configuration. Below is the YAML of the `Secret` that we are going to create: + +```yaml +apiVersion: v1 +stringData: + config.yaml: | + log_level: DEBUG + service: + max_request_size_mb: 64 +kind: Secret +metadata: + name: qdrant-configuration + namespace: demo +type: Opaque +``` + +Let's create the `Secret` we have shown above: + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/configuration/configuration-secret.yaml +secret/qdrant-configuration created +``` + +Verify the Secret has the configuration file: + +```yaml +$ kubectl get secret -n demo qdrant-configuration -o yaml +apiVersion: v1 +data: + config.yaml: bG9nX2xldmVsOiBERUJVRwpzZXJ2aWNlOgogIG1heF9yZXF1ZXN0X3NpemVfbWI6IDY0Cg== +kind: Secret +metadata: + creationTimestamp: "2026-05-19T06:39:07Z" + name: qdrant-configuration + namespace: demo + resourceVersion: "3834858" + uid: 9cad78b6-e0e3-4e3e-b999-943c01bfb09c +type: Opaque +``` + +Now, create the `Qdrant` CR specifying `spec.configuration.secretName` field: + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/configuration/qdrant.yaml +qdrant.kubedb.com/qdrant-sample created +``` + +Below is the YAML for the `Qdrant` CR we just created: + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + replicas: 3 + configuration: + secretName: qdrant-configuration + storage: + storageClassName: "longhorn" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut +``` + +Now, wait a few minutes. KubeDB operator will create the necessary PVC, PetSet, services, and secrets. Let's check the status: + +```bash +$ kubectl get qdrant -n demo +NAME VERSION STATUS AGE +qdrant-sample 1.17.0 Ready 68s +``` + +Check that all pods are running: + +```bash +$ kubectl get pod -n demo +NAME READY STATUS RESTARTS AGE +qdrant-sample-0 1/1 Running 0 61s +qdrant-sample-1 1/1 Running 0 57s +qdrant-sample-2 1/1 Running 0 42s +``` + +Now, let's verify that the custom configuration has been applied by checking the config file inside the pod: + +```bash +$ kubectl exec -n demo qdrant-sample-0 -- cat /qdrant/config/config.yaml +log_level: DEBUG +service: + max_request_size_mb: 64 +``` + +The output confirms the database is running with our custom `log_level` and `max_request_size_mb` values. + +As noted in the [Overview](#overview), inline configuration has the highest priority. If both a config Secret and inline config specify the same key, the inline value takes precedence. + +## Inline Configuration + +You can also provide custom configuration inline within the `Qdrant` CR using `spec.configuration.inline`. This is useful for simple config changes without creating a separate Secret. + +Below is an example YAML of a `Qdrant` CR with inline configuration: + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + replicas: 3 + configuration: + inline: + log_level: DEBUG + max_request_size_mb: "64" + storage: + storageClassName: "longhorn" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut +``` + +> **Note:** The `inline` field is a `map[string]string`, so values must be strings. To set the config key `max_request_size_mb` to `64`, write `max_request_size_mb: "64"`. The config Secret method (shown above) supports full nested YAML structure. + +When both `spec.configuration.secretName` and `spec.configuration.inline` are set, the inline values override the corresponding keys from the config Secret. Keys not specified in inline retain their values from the config Secret. + +## Cleaning up + +To clean up the Kubernetes resources created by this tutorial, run: + +```bash +kubectl delete qdrant -n demo qdrant-sample +kubectl delete secret -n demo qdrant-configuration +kubectl delete ns demo +``` \ No newline at end of file diff --git a/docs/guides/qdrant/distributed-deployment/_index.md b/docs/guides/qdrant/distributed-deployment/_index.md new file mode 100644 index 000000000..ba06aa7da --- /dev/null +++ b/docs/guides/qdrant/distributed-deployment/_index.md @@ -0,0 +1,10 @@ +--- +title: Distributed Deployment +menu: + docs_{{ .version }}: + identifier: qdrant-distributed-deployment + name: Distributed Deployment + parent: qdrant-guides + weight: 25 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/qdrant/distributed-deployment/overview.md b/docs/guides/qdrant/distributed-deployment/overview.md new file mode 100644 index 000000000..0fc3e53ea --- /dev/null +++ b/docs/guides/qdrant/distributed-deployment/overview.md @@ -0,0 +1,251 @@ +--- +title: Distributed Deployment +menu: + docs_{{ .version }}: + identifier: qdrant-distributed-deployment-overview + name: Overview + parent: qdrant-distributed-deployment + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Qdrant Distributed Deployment + +Since version v0.8.0, Qdrant supports a distributed deployment mode where multiple Qdrant services communicate with each other to distribute data across peers, extending storage capabilities and increasing stability. In this mode, Qdrant uses the [Raft](https://raft.github.io/) consensus protocol to maintain consistency of cluster topology and collection structure, while sharding enables horizontal scaling by splitting collections across multiple nodes. Replication further enhances reliability by keeping copies of shards across the cluster. + +This tutorial will show you how to deploy a Qdrant database in distributed mode using KubeDB. + +## Before You Begin + +At first, you need to have a Kubernetes cluster, and the `kubectl` command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps [here](/docs/setup/README.md). + +To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +> **Note:** YAML files used in this tutorial are stored in [docs/examples/qdrant/quickstart](/docs/examples/qdrant/quickstart) directory of [kubedb/docs](https://github.com/kubedb/docs) repository. + +## Find Available StorageClass + +We will need to provide `StorageClass` in the Qdrant CR specification. Check available `StorageClass` in your cluster using the following command: + +```bash +$ kubectl get storageclass +NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE +local-path (default) rancher.io/local-path Delete WaitForFirstConsumer false 29d +longhorn (default) driver.longhorn.io Delete Immediate true 26d +standard rancher.io/local-path Delete WaitForFirstConsumer false 21h +``` + +We will use `standard` StorageClass in this tutorial. + +## Find Available QdrantVersion + +When you install KubeDB, it creates `QdrantVersion` CRDs for all supported Qdrant versions. Let's check available `QdrantVersion`s: + +```bash +$ kubectl get qdrantversions +NAME VERSION DB_IMAGE DEPRECATED AGE +1.15.4 1.15.4 docker.io/qdrant/qdrant:v1.15.4-unprivileged 29d +1.16.2 1.16.2 docker.io/qdrant/qdrant:v1.16.2-unprivileged 29d +1.17.0 1.17.0 docker.io/qdrant/qdrant:v1.17.0-unprivileged 29d +``` + +In this tutorial, we will use `1.17.0` QdrantVersion CR to create a distributed Qdrant cluster. + +## Deploy Distributed Qdrant + +KubeDB implements a `Qdrant` CRD to define the specification of a Qdrant database. For distributed deployment, you need to set `spec.mode` to `Distributed` and specify the number of replicas. + +Below is the `Qdrant` object created in this tutorial: + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + mode: Distributed + replicas: 3 + storage: + storageClassName: standard + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 2Gi + deletionPolicy: WipeOut +``` + +Here, +- `spec.version` specifies the version of Qdrant to use +- `spec.mode` set to `Distributed` enables distributed mode +- `spec.replicas` specifies the number of Qdrant nodes (default is 1) +- `spec.storage` specifies the storage configuration for each node + +Let's create the Qdrant object: + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/quickstart/distributed.yaml +qdrant.kubedb.com/qdrant-sample created +``` + +## Verify the Deployment + +Let's check the status of the Qdrant object: + +```bash +$ kubectl get qdrant -n demo +NAME VERSION STATUS AGE +qdrant-sample 1.17.0 Ready 50s +``` + +To see the distributed nodes, check the pods: + +```bash +$ kubectl get pod -n demo -l app.kubernetes.io/instance=qdrant-sample +NAME READY STATUS RESTARTS AGE +qdrant-sample-0 1/1 Running 0 48s +qdrant-sample-1 1/1 Running 0 43s +qdrant-sample-2 1/1 Running 0 39s +``` + +In distributed mode, Qdrant creates a Petset with the specified number of replicas. + +## Interact with the Distributed Cluster + +Now let's interact with the distributed Qdrant cluster. First, get the API key and forward a port: + +```bash +$ kubectl get secret -n demo qdrant-sample-auth -o jsonpath='{.data.api-key}' | base64 -d +F1UxwGOleYzmofu3 + +$ kubectl port-forward -n demo svc/qdrant-sample 6333:6333 & +``` + +Create a collection with sharding and replication: + +```bash +$ curl -X PUT http://localhost:6333/collections/demo_vectors \ + -H "Content-Type: application/json" \ + -H "api-key: F1UxwGOleYzmofu3" \ + -d '{ + "shard_number": 6, + "replication_factor": 2, + "vectors": { + "size": 8, + "distance": "Cosine" + } + }' +{"result":true,"status":"ok","time":0.912871278} +``` + +Add some points to the collection: + +```bash +$ curl -X PUT "http://localhost:6333/collections/demo_vectors/points?wait=true" \ + -H "Content-Type: application/json" \ + -H "api-key: F1UxwGOleYzmofu3" \ + -d '{ + "points": [ + {"id": 1, "vector": [0.15, 0.22, 0.31, 0.44, 0.51, 0.68, 0.73, 0.89], "payload": {"label": "apple"}}, + {"id": 2, "vector": [0.12, 0.28, 0.35, 0.42, 0.53, 0.64, 0.71, 0.85], "payload": {"label": "banana"}}, + {"id": 3, "vector": [0.18, 0.21, 0.33, 0.46, 0.50, 0.66, 0.77, 0.82], "payload": {"label": "cherry"}}, + {"id": 4, "vector": [0.14, 0.25, 0.32, 0.41, 0.54, 0.63, 0.75, 0.88], "payload": {"label": "date"}}, + {"id": 5, "vector": [0.16, 0.23, 0.38, 0.43, 0.55, 0.61, 0.72, 0.86], "payload": {"label": "elderberry"}} + ] + }' +{"result":{"operation_id":1,"status":"completed"},"status":"ok","time":0.002696282} +``` + +Verify that clustering is enabled by checking the root cluster endpoint: + +```bash +$ curl http://localhost:6333/cluster -H "api-key: F1UxwGOleYzmofu3" | jq +{ + "result": { + "status": "enabled", + "peer_id": 5887768058245046, + "peers": { + "6780901721144166": { + "uri": "http://qdrant-sample-2.qdrant-sample-pods.demo.svc.cluster.local:6335/" + }, + "5887768058245046": { + "uri": "http://qdrant-sample-0.qdrant-sample-pods.demo.svc.cluster.local:6335/" + }, + "5462954126296684": { + "uri": "http://qdrant-sample-1.qdrant-sample-pods.demo.svc.cluster.local:6335/" + } + }, + "raft_info": { + "term": 1, + "commit": 27, + "pending_operations": 0, + "leader": 5887768058245046, + "role": "Leader", + "is_voter": true + }, + "consensus_thread_status": { + "consensus_thread_status": "working" + }, + "message_send_failures": {} + }, + "status": "ok" +} +``` + +The output confirms distributed mode is **enabled** with 3 peers and Raft consensus active. + +Now check the collection-level shard distribution: + +```bash +$ curl http://localhost:6333/collections/demo_vectors/cluster \ + -H "api-key: F1UxwGOleYzmofu3" | jq +{ + "result": { + "peer_id": 5887768058245046, + "shard_count": 6, + "local_shards": [ + {"shard_id": 0, "points_count": 1, "state": "Active"}, + {"shard_id": 2, "points_count": 1, "state": "Active"}, + {"shard_id": 3, "points_count": 2, "state": "Active"}, + {"shard_id": 5, "points_count": 0, "state": "Active"} + ], + "remote_shards": [ + {"shard_id": 0, "peer_id": 6780901721144166, "state": "Active"}, + {"shard_id": 1, "peer_id": 6780901721144166, "state": "Active"}, + {"shard_id": 1, "peer_id": 5462954126296684, "state": "Active"}, + {"shard_id": 2, "peer_id": 5462954126296684, "state": "Active"}, + {"shard_id": 3, "peer_id": 6780901721144166, "state": "Active"}, + {"shard_id": 4, "peer_id": 5462954126296684, "state": "Active"}, + {"shard_id": 4, "peer_id": 6780901721144166, "state": "Active"}, + {"shard_id": 5, "peer_id": 5462954126296684, "state": "Active"} + ], + "shard_transfers": [] + }, + "status": "ok" +} +``` + +The output shows that the collection `demo_vectors` is distributed across 3 peers with 6 shards and a replication factor of 2. Each shard is in `Active` state, and local/remote shards are balanced across the cluster nodes. + +## Cleaning Up + +To delete the Qdrant database and all associated resources: + +```bash +$ kubectl delete qdrant -n demo qdrant-sample +qdrant.kubedb.com "qdrant-sample" deleted +``` + +> **Warning:** If you delete the Qdrant object with `deletionPolicy: WipeOut`, all data will be permanently deleted. diff --git a/docs/guides/qdrant/images/qdrant-compute-autoscaling.png b/docs/guides/qdrant/images/qdrant-compute-autoscaling.png new file mode 100644 index 000000000..af6a33318 Binary files /dev/null and b/docs/guides/qdrant/images/qdrant-compute-autoscaling.png differ diff --git a/docs/guides/qdrant/images/qdrant-lifecycle.png b/docs/guides/qdrant/images/qdrant-lifecycle.png new file mode 100644 index 000000000..a4d86b20d Binary files /dev/null and b/docs/guides/qdrant/images/qdrant-lifecycle.png differ diff --git a/docs/guides/qdrant/images/qdrant-storage-autoscaling.png b/docs/guides/qdrant/images/qdrant-storage-autoscaling.png new file mode 100644 index 000000000..cd868481e Binary files /dev/null and b/docs/guides/qdrant/images/qdrant-storage-autoscaling.png differ diff --git a/docs/guides/qdrant/images/qdrant-tls.png b/docs/guides/qdrant/images/qdrant-tls.png new file mode 100644 index 000000000..f3e895057 Binary files /dev/null and b/docs/guides/qdrant/images/qdrant-tls.png differ diff --git a/docs/guides/qdrant/images/qdrant-volume-expansion.png b/docs/guides/qdrant/images/qdrant-volume-expansion.png new file mode 100644 index 000000000..654e2b2a0 Binary files /dev/null and b/docs/guides/qdrant/images/qdrant-volume-expansion.png differ diff --git a/docs/guides/qdrant/monitoring/_index.md b/docs/guides/qdrant/monitoring/_index.md new file mode 100644 index 000000000..502f59cd0 --- /dev/null +++ b/docs/guides/qdrant/monitoring/_index.md @@ -0,0 +1,10 @@ +--- +title: Qdrant Monitoring +menu: + docs_{{ .version }}: + identifier: qdrant-monitoring + name: Monitoring + parent: qdrant-guides + weight: 150 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/qdrant/monitoring/overview.md b/docs/guides/qdrant/monitoring/overview.md new file mode 100644 index 000000000..cbb0ac6d8 --- /dev/null +++ b/docs/guides/qdrant/monitoring/overview.md @@ -0,0 +1,79 @@ +--- +title: Qdrant Monitoring Overview +menu: + docs_{{ .version }}: + identifier: qdrant-monitoring-overview + name: Overview + parent: qdrant-monitoring + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Monitoring Qdrant with KubeDB + +KubeDB has native support for monitoring via [Prometheus](https://prometheus.io/). You can use builtin [Prometheus](https://github.com/prometheus/prometheus) scraper or [Prometheus operator](https://github.com/prometheus-operator/prometheus-operator) to monitor KubeDB managed databases. This tutorial will show you how database monitoring works with KubeDB and how to configure Database CR to enable monitoring. + +## Overview + +KubeDB uses Prometheus [exporter](https://prometheus.io/docs/instrumenting/exporters/#databases) images to export Prometheus metrics for respective databases. Following diagram shows the logical flow of database monitoring with KubeDB. + +

+  Database Monitoring Flow +

+ +When a user creates a database CR with `spec.monitor` section configured, KubeDB operator provisions the respective database and injects an exporter image as sidecar to the database pod. It also creates a dedicated stats service with name `{database-crd-name}-stats` for monitoring. Prometheus server can scrape metrics using this stats service. + +## Configure Monitoring + +In order to enable monitoring for a database, you have to configure `spec.monitor` section. KubeDB provides following options to configure `spec.monitor` section: + +| Field | Type | Uses | +| -------------------------------------------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------- | +| `spec.monitor.agent` | `Required` | Type of the monitoring agent that will be used to monitor this database. It can be `prometheus.io/builtin` or `prometheus.io/operator`. | +| `spec.monitor.prometheus.exporter.port` | `Optional` | Port number where the exporter side car will serve metrics. | +| `spec.monitor.prometheus.exporter.args` | `Optional` | Arguments to pass to the exporter sidecar. | +| `spec.monitor.prometheus.exporter.env` | `Optional` | List of environment variables to set in the exporter sidecar container. | +| `spec.monitor.prometheus.exporter.resources` | `Optional` | Resources required by exporter sidecar container. | +| `spec.monitor.prometheus.exporter.securityContext` | `Optional` | Security options the exporter should run with. | +| `spec.monitor.prometheus.serviceMonitor.labels` | `Optional` | Labels for `ServiceMonitor` CR. | +| `spec.monitor.prometheus.serviceMonitor.interval` | `Optional` | Interval at which metrics should be scraped. | + +## Sample Configuration + +A sample YAML for Qdrant CR with `spec.monitor` section configured to enable monitoring with [Prometheus operator](https://github.com/prometheus-operator/prometheus-operator) is shown below. + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-monitoring + namespace: demo +spec: + version: "1.17.0" + replicas: 3 + storage: + storageClassName: standard + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + monitor: + agent: prometheus.io/operator + prometheus: + serviceMonitor: + labels: + release: prometheus + interval: 10s + deletionPolicy: WipeOut +``` + +Here, we have specified that we are going to monitor this Qdrant cluster using Prometheus operator through `spec.monitor.agent: prometheus.io/operator`. KubeDB will create a `ServiceMonitor` CR in the same namespace and this `ServiceMonitor` will have `release: prometheus` label. + +## Next Steps + +- Learn how to monitor Qdrant with KubeDB using [Builtin Prometheus](/docs/guides/qdrant/monitoring/using-builtin-prometheus.md). +- Learn how to monitor Qdrant with KubeDB using [Prometheus operator](/docs/guides/qdrant/monitoring/using-prometheus-operator.md). diff --git a/docs/guides/qdrant/monitoring/using-prometheus-operator.md b/docs/guides/qdrant/monitoring/using-prometheus-operator.md new file mode 100644 index 000000000..7e04ad1e1 --- /dev/null +++ b/docs/guides/qdrant/monitoring/using-prometheus-operator.md @@ -0,0 +1,366 @@ +--- +title: Monitor Qdrant using Prometheus Operator +menu: + docs_{{ .version }}: + identifier: qdrant-using-prometheus-operator-monitoring + name: Prometheus Operator + parent: qdrant-monitoring + weight: 15 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Monitoring Qdrant Using Prometheus operator + +[Prometheus operator](https://github.com/prometheus-operator/prometheus-operator) provides simple and Kubernetes native way to deploy and configure Prometheus server. This tutorial will show you how to use Prometheus operator to monitor Qdrant deployed with KubeDB. + +## Before You Begin + +- You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps [here](/docs/setup/README.md). + +- To learn how Prometheus monitoring works with KubeDB in general, please visit [here](/docs/guides/qdrant/monitoring/overview.md). + +- To keep Prometheus resources isolated, we are going to use a separate namespace called `monitoring` to deploy respective monitoring resources. We are going to deploy database in `demo` namespace. + + ```bash + $ kubectl create ns monitoring + namespace/monitoring created + + $ kubectl create ns demo + namespace/demo created + ``` + +- We need a [Prometheus operator](https://github.com/prometheus-operator/prometheus-operator) instance running. If you don't already have a running instance, you can deploy one using this helm chart [here](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack). + +> Note: YAML files used in this tutorial are stored in [docs/examples/qdrant/monitoring](https://github.com/kubedb/docs/tree/{{< param "info.version" >}}/docs/examples/qdrant/monitoring) folder in GitHub repository [kubedb/docs](https://github.com/kubedb/docs). + +## Find out required labels for ServiceMonitor + +We need to know the labels used to select `ServiceMonitor` by `Prometheus` Operator. We are going to provide these labels in `spec.monitor.prometheus.serviceMonitor.labels` field of Qdrant CR so that KubeDB creates `ServiceMonitor` object accordingly. + +At first, let's find out the available Prometheus server in our cluster. + +```bash +$ kubectl get prometheus --all-namespaces +NAMESPACE NAME VERSION DESIRED READY RECONCILED AVAILABLE AGE +monitoring prometheus-kube-prometheus-prometheus v2.54.1 1 1 True True 16d +``` + +> If you don't have any Prometheus server running in your cluster, deploy one following the guide specified in **Before You Begin** section. + +Now, let's view the YAML of the available Prometheus server `prometheus-kube-prometheus-prometheus` in `monitoring` namespace. + +```bash +$ kubectl get prometheus -n monitoring prometheus-kube-prometheus-prometheus -oyaml +``` +```yaml +apiVersion: monitoring.coreos.com/v1 +kind: Prometheus +metadata: + annotations: + meta.helm.sh/release-name: prometheus + meta.helm.sh/release-namespace: monitoring + creationTimestamp: "2024-10-14T10:14:36Z" + generation: 1 + labels: + app: kube-prometheus-stack-prometheus + app.kubernetes.io/instance: prometheus + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/part-of: kube-prometheus-stack + app.kubernetes.io/version: 65.2.0 + chart: kube-prometheus-stack-65.2.0 + heritage: Helm + release: prometheus + name: prometheus-kube-prometheus-prometheus + namespace: monitoring + resourceVersion: "1004097" + uid: b7879d3e-e4bb-4425-8d78-f917561d95f7 +spec: + alerting: + alertmanagers: + - apiVersion: v2 + name: prometheus-kube-prometheus-alertmanager + namespace: monitoring + pathPrefix: / + port: http-web + automountServiceAccountToken: true + enableAdminAPI: false + evaluationInterval: 30s + externalUrl: http://prometheus-kube-prometheus-prometheus.monitoring:9090 + hostNetwork: false + image: quay.io/prometheus/prometheus:v2.54.1 + listenLocal: false + logFormat: logfmt + logLevel: info + paused: false + podMonitorNamespaceSelector: {} + podMonitorSelector: + matchLabels: + release: prometheus + portName: http-web + probeNamespaceSelector: {} + probeSelector: + matchLabels: + release: prometheus + replicas: 1 + retention: 10d + routePrefix: / + ruleNamespaceSelector: {} + ruleSelector: + matchLabels: + release: prometheus + scrapeConfigNamespaceSelector: {} + scrapeConfigSelector: + matchLabels: + release: prometheus + scrapeInterval: 30s + securityContext: + fsGroup: 2000 + runAsGroup: 2000 + runAsNonRoot: true + runAsUser: 1000 + seccompProfile: + type: RuntimeDefault + serviceAccountName: prometheus-kube-prometheus-prometheus + serviceMonitorNamespaceSelector: {} + serviceMonitorSelector: + matchLabels: + release: prometheus + shards: 1 + tsdb: + outOfOrderTimeWindow: 0s + version: v2.54.1 + walCompression: true +status: + availableReplicas: 1 + conditions: + - lastTransitionTime: "2024-10-31T07:38:36Z" + message: "" + observedGeneration: 1 + reason: "" + status: "True" + type: Available + - lastTransitionTime: "2024-10-31T07:38:36Z" + message: "" + observedGeneration: 1 + reason: "" + status: "True" + type: Reconciled + paused: false + replicas: 1 + selector: app.kubernetes.io/instance=prometheus-kube-prometheus-prometheus,app.kubernetes.io/managed-by=prometheus-operator,app.kubernetes.io/name=prometheus,operator.prometheus.io/name=prometheus-kube-prometheus-prometheus,prometheus=prometheus-kube-prometheus-prometheus + shardStatuses: + - availableReplicas: 1 + replicas: 1 + shardID: "0" + unavailableReplicas: 0 + updatedReplicas: 1 + shards: 1 + unavailableReplicas: 0 + updatedReplicas: 1 +``` + +Notice the `spec.serviceMonitorSelector` section. Here, `release: prometheus` label is used to select `ServiceMonitor` CR. So, we are going to use this label in `spec.monitor.prometheus.serviceMonitor.labels` field of Qdrant CR. + +## Deploy Qdrant with Monitoring Enabled + +Now, let's deploy a Qdrant cluster with monitoring enabled. Below is the Qdrant object that we are going to create. + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-monitoring + namespace: demo +spec: + version: "1.17.0" + replicas: 3 + storage: + storageClassName: standard + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + monitor: + agent: prometheus.io/operator + prometheus: + serviceMonitor: + interval: 10s + labels: + release: prometheus + deletionPolicy: WipeOut +``` + +Here, + +- `monitor.agent: prometheus.io/operator` indicates that we are going to monitor this Qdrant cluster using Prometheus operator. + +- `monitor.prometheus.serviceMonitor.labels` specifies that KubeDB should create `ServiceMonitor` with these labels. + +- `monitor.prometheus.serviceMonitor.interval` indicates that the Prometheus server should scrape metrics from this database with 10 seconds interval. + +Let's create the Qdrant object that we have shown above, + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/monitoring/qdrant-monitoring.yaml +qdrant.kubedb.com/qdrant-monitoring created +``` + +Now, wait for the database to go into `Ready` state. + +```bash +$ kubectl get qdrant -n demo qdrant-monitoring +NAME VERSION STATUS AGE +qdrant-monitoring 1.17.0 Ready 1m +``` + +KubeDB will create a separate stats service with name `{qdrant cr name}-stats` for monitoring purpose. + +```bash +$ kubectl get svc -n demo --selector="app.kubernetes.io/instance=qdrant-monitoring" +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +qdrant-monitoring ClusterIP 10.96.225.130 6333/TCP 1m +qdrant-monitoring-stats ClusterIP 10.96.147.93 6333/TCP 1m +``` + +Here, `qdrant-monitoring-stats` service has been created for monitoring purpose. + +Let's describe this stats service. + +```bash +$ kubectl describe svc -n demo qdrant-monitoring-stats +``` +```yaml +Name: qdrant-monitoring-stats +Namespace: demo +Labels: app.kubernetes.io/component=database + app.kubernetes.io/instance=qdrant-monitoring + app.kubernetes.io/managed-by=kubedb.com + app.kubernetes.io/name=qdrants.kubedb.com + kubedb.com/role=stats +Annotations: monitoring.appscode.com/agent: prometheus.io/operator +Selector: app.kubernetes.io/instance=qdrant-monitoring,app.kubernetes.io/managed-by=kubedb.com,app.kubernetes.io/name=qdrants.kubedb.com +Type: ClusterIP +Port: metrics 6333/TCP +TargetPort: metrics/TCP +Endpoints: 10.244.0.47:6333,10.244.0.48:6333,10.244.0.49:6333 +``` + +Notice the `Labels` and `Port` fields. `ServiceMonitor` will use these information to target its endpoints. + +KubeDB will also create a `ServiceMonitor` CR in `demo` namespace that select the endpoints of `qdrant-monitoring-stats` service. Verify that the `ServiceMonitor` CR has been created. + +```bash +$ kubectl get servicemonitor -n demo +NAME AGE +qdrant-monitoring-stats 1m +``` + +Let's verify that the `ServiceMonitor` has the label that we had specified in `spec.monitor` section of Qdrant CR. + +```bash +$ kubectl get servicemonitor -n demo qdrant-monitoring-stats -o yaml +``` + +```yaml +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + creationTimestamp: "2024-10-31T07:38:36Z" + generation: 1 + labels: + app.kubernetes.io/component: database + app.kubernetes.io/instance: qdrant-monitoring + app.kubernetes.io/managed-by: kubedb.com + app.kubernetes.io/name: qdrants.kubedb.com + release: prometheus + name: qdrant-monitoring-stats + namespace: demo + ownerReferences: + - apiVersion: v1 + blockOwnerDeletion: true + controller: true + kind: Service + name: qdrant-monitoring-stats + uid: 99193679-301b-41fd-aae5-a732b3070d19 + resourceVersion: "1004080" + uid: 87635ad4-dfb2-4544-89af-e48b40783205 +spec: + endpoints: + - honorLabels: true + interval: 10s + path: /metrics + port: metrics + namespaceSelector: + matchNames: + - demo + selector: + matchLabels: + app.kubernetes.io/component: database + app.kubernetes.io/instance: qdrant-monitoring + app.kubernetes.io/managed-by: kubedb.com + app.kubernetes.io/name: qdrants.kubedb.com + kubedb.com/role: stats +``` + +Notice that the `ServiceMonitor` has label `release: prometheus` that we had specified in Qdrant CR. + +Also notice that the `ServiceMonitor` has selector which match the labels we have seen in the `qdrant-monitoring-stats` service. It also, target the `metrics` port that we have seen in the stats service. + +## Verify Monitoring Metrics + +At first, let's find out the respective Prometheus pod for `prometheus-kube-prometheus-prometheus` Prometheus server. + +```bash +$ kubectl get pod -n monitoring -l=app.kubernetes.io/name=prometheus +NAME READY STATUS RESTARTS AGE +prometheus-prometheus-kube-prometheus-prometheus-0 2/2 Running 1 16d +``` + +Prometheus server is listening to port `9090` of `prometheus-prometheus-kube-prometheus-prometheus-0` pod. We are going to use [port forwarding](https://kubernetes.io/docs/tasks/access-application-cluster/port-forward-access-application-cluster/) to access Prometheus dashboard. + +Run following command on a separate terminal to forward the port 9090 of `prometheus-prometheus-0` pod, + +```bash +$ kubectl port-forward -n monitoring prometheus-prometheus-kube-prometheus-prometheus-0 9090 +Forwarding from 127.0.0.1:9090 -> 9090 +Forwarding from [::1]:9090 -> 9090 +``` + +Now, we can access the dashboard at `localhost:9090`. Open [http://localhost:9090](http://localhost:9090) in your browser. You should see `metrics` endpoint of `qdrant-monitoring-stats` service as one of the targets. + +

+  Prometheus Target +

+ +Check the `endpoint` and `service` labels. It verifies that the target is our expected database. Now, you can view the collected metrics and create a graph from homepage of this Prometheus dashboard. You can also use this Prometheus server as data source for [Grafana](https://grafana.com/) and create beautiful dashboards with collected metrics. + +## Grafana Dashboards + +There are pre-built Grafana dashboards to monitor Qdrant databases managed by KubeDB: + +- KubeDB / Qdrant / Summary: Shows overall summary of Qdrant instance. +- KubeDB / Qdrant / Pod: Shows individual pod-level information. + +To use these dashboards, download them from [qdrant-dashboards](https://github.com/ops-center/grafana-dashboards/tree/master/qdrant) and import them into your Grafana instance. + +## Cleaning up + +To clean up the Kubernetes resources created by this tutorial, run following commands + +```bash +kubectl delete -n demo qdrant/qdrant-monitoring +kubectl delete ns demo + +helm uninstall prometheus -n monitoring +kubectl delete ns monitoring +``` + +## Next Steps +- Learn about [backup and restore](/docs/guides/qdrant/backup/overview/index.md) Qdrant using KubeStash. +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). diff --git a/docs/guides/qdrant/quickstart/_index.md b/docs/guides/qdrant/quickstart/_index.md new file mode 100644 index 000000000..dfb60004b --- /dev/null +++ b/docs/guides/qdrant/quickstart/_index.md @@ -0,0 +1,10 @@ +--- +title: Qdrant Quickstart +menu: + docs_{{ .version }}: + identifier: qdrant-quickstart + name: Quickstart + parent: qdrant-guides + weight: 10 +menu_name: docs_{{ .version }} +--- \ No newline at end of file diff --git a/docs/guides/qdrant/quickstart/quickstart.md b/docs/guides/qdrant/quickstart/quickstart.md new file mode 100644 index 000000000..df43b0b56 --- /dev/null +++ b/docs/guides/qdrant/quickstart/quickstart.md @@ -0,0 +1,573 @@ +--- +title: Qdrant Quickstart +menu: + docs_{{ .version }}: + identifier: qdrant-quickstart-overview + name: Overview + parent: qdrant-quickstart + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Running Qdrant + +This tutorial will show you how to use KubeDB to run a Qdrant database. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the `kubectl` command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Now, install KubeDB operator in your cluster following the steps [here](/docs/setup/README.md) and make sure install with helm command including `--set global.featureGates.Qdrant=true` to ensure MSSQLServer CRD installation. + +- To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +> **Note:** YAML files used in this tutorial are stored in [docs/examples/qdrant/quickstart](https://github.com/kubedb/docs/tree/{{< param "info.version" >}}/docs/examples/qdrant/quickstart) folder in GitHub repository [kubedb/docs](https://github.com/kubedb/docs). + +## Find Available StorageClass + +We will need to provide `StorageClass` in the Qdrant CR specification. Check available `StorageClass` in your cluster using the following command: + +```bash +$ kubectl get storageclass +NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE +standard (default) rancher.io/local-path Delete WaitForFirstConsumer false 10d +``` + +Here, we have `standard` StorageClass in our cluster. + +## Find Available QdrantVersion + +When you install KubeDB, it creates `QdrantVersion` CRDs for all supported Qdrant versions. Let's check available `QdrantVersion`s: + +```bash +$ kubectl get qdrantversions +NAME VERSION DB_IMAGE DEPRECATED AGE +1.15.4 1.15.4 docker.io/qdrant/qdrant:v1.15.4-unprivileged 13d +1.16.2 1.16.2 docker.io/qdrant/qdrant:v1.16.2-unprivileged 13d +1.17.0 1.17.0 docker.io/qdrant/qdrant:v1.17.0-unprivileged 13d +``` + +Notice the `DEPRECATED` column. `true` means that QdrantVersion is deprecated for the current KubeDB version and KubeDB will not work for that version. + +In this tutorial, we will use `1.17.0` QdrantVersion CR to create a Qdrant cluster. To know more about what `QdrantVersion` CR is and why there may be variation in version names, please visit [here](/docs/guides/qdrant/concepts/catalog.md). + +## Create a Qdrant Database + +KubeDB implements a `Qdrant` CRD to define the specification of a Qdrant database. + +Below is the `Qdrant` object created in this tutorial: + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + mode: "Standalone" + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut +``` + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/quickstart/qdrant-sample.yaml +qdrant.kubedb.com/qdrant-sample created +``` + +Here, + +- `spec.version` is the name of the QdrantVersion CR where Docker images are specified. In this tutorial, a Qdrant `1.17.0` cluster is created. +- `spec.mode` specifies the Qdrant deployment mode `Standalone` or `Distributed`. +- `spec.storage` specifies the size and StorageClass of the PVC that will be dynamically allocated to store data for each Qdrant pod. This storage spec will be passed to the Petset created by KubeDB operator to run database pods. +- `spec.deletionPolicy` specifies what KubeDB should do when a user tries to delete the `Qdrant` CR. Deletion policy `DoNotTerminate` prevents deletion of this object if the admission webhook is enabled. + +> **Note:** `spec.storage` section is used to create PVC for the database pods. Specify only `requests`, not `limits` — PVC does not resize automatically. + +Now, let's watch the progress of creating the `Qdrant` cluster: + +```bash +$ kubectl get qdrant -n demo qdrant-sample -w +NAME VERSION STATUS AGE +qdrant-sample 1.17.0 Provisioning 5s +qdrant-sample 1.17.0 Provisioning 30s +qdrant-sample 1.17.0 Ready 2m +``` + +## Describe Qdrant + +Let's describe the `Qdrant` object to see its current state: + +```bash +$ kubectl describe qdrant -n demo qdrant-sample +Name: qdrant-sample +Namespace: demo +Labels: +Annotations: +API Version: kubedb.com/v1alpha2 +Kind: Qdrant +Metadata: + Creation Timestamp: 2026-05-14T08:43:57Z + Finalizers: + kubedb.com + Generation: 3 + Resource Version: 3259342 + UID: 42df526b-fba5-4d21-aea4-d20ae5f36f30 +Spec: + Auth Secret: + Active From: 2026-05-14T08:43:57Z + API Group: + Kind: Secret + Name: qdrant-sample-auth + Deletion Policy: WipeOut + Health Checker: + Failure Threshold: 3 + Period Seconds: 10 + Timeout Seconds: 10 + Mode: Standalone + Pod Template: + Controller: + Metadata: + Spec: + Containers: + Name: qdrant + Resources: + Limits: + Memory: 1Gi + Requests: + Cpu: 500m + Memory: 1Gi + Security Context: + Allow Privilege Escalation: false + Capabilities: + Drop: + ALL + Run As Group: 1000 + Run As Non Root: true + Run As User: 1000 + Seccomp Profile: + Type: RuntimeDefault + Pod Placement Policy: + Name: default + Security Context: + Fs Group: 1000 + Service Account Name: qdrant-sample + Replicas: 1 + Storage: + Access Modes: + ReadWriteOnce + Resources: + Requests: + Storage: 1Gi + Storage Class Name: standard + Storage Type: Durable + Version: 1.17.0 +Status: + Conditions: + Last Transition Time: 2026-05-14T08:43:57Z + Message: The KubeDB operator has started the provisioning of Qdrant: demo qdrant-sample + Observed Generation: 1 + Reason: DatabaseProvisioningStartedSuccessfully + Status: True + Type: ProvisioningStarted + Last Transition Time: 2026-05-14T08:44:11Z + Message: All desired replicas are ready. + Observed Generation: 3 + Reason: AllReplicasReady + Status: True + Type: ReplicaReady + Last Transition Time: 2026-05-14T08:44:22Z + Message: database demo/qdrant-sample is accepting connection + Observed Generation: 3 + Reason: AcceptingConnection + Status: True + Type: AcceptingConnection + Last Transition Time: 2026-05-14T08:44:22Z + Message: database demo/qdrant-sample is ready + Reason: AllReplicasReady + Status: True + Type: Ready + Last Transition Time: 2026-05-14T08:44:23Z + Message: The Qdrant: demo/qdrant-sample is successfully provisioned. + Observed Generation: 3 + Reason: DatabaseSuccessfullyProvisioned + Status: True + Type: Provisioned + Phase: Ready +Events: + +``` + +## Find Underlying Kubernetes Resources + +KubeDB operator creates a Petset, PVCs, PVs, and Services for the Qdrant database. Let's check them: + +```bash +$ kubectl get petset -n demo qdrant-sample +NAME AGE +qdrant-sample 2m34s + +$ kubectl get pvc -n demo +NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE +data-qdrant-sample-0 Bound pvc-0015c0ad-4ddd-404c-9d8b-b9ea1f6cc15f 1Gi RWO standard + +$ kubectl get pv -n demo +NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE +pvc-0015c0ad-4ddd-404c-9d8b-b9ea1f6cc15f 1Gi RWO Delete Bound demo/data-qdrant-sample-0 standard 4m14s + + +$ kubectl get service -n demo +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +qdrant-sample ClusterIP 10.43.18.112 6333/TCP,6334/TCP 5m36s +qdrant-sample-pods ClusterIP None 6335/TCP 5m36s + +``` + +## Verify Qdrant YAML Output + +KubeDB operator sets the `status.phase` to `Ready` once the database is successfully created and is able to accept client connections. Run the following command to see the modified Qdrant object: + +```bash +$ kubectl get qdrant -n demo qdrant-sample -o yaml +``` + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + annotations: + kubectl.kubernetes.io/last-applied-configuration: | + {"apiVersion":"kubedb.com/v1alpha2","kind":"Qdrant","metadata":{"annotations":{},"name":"qdrant-sample","namespace":"demo"},"spec":{"deletionPolicy":"WipeOut","mode":"Standalone","storage":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"1Gi"}},"storageClassName":"standard"},"version":"1.17.0"}} + creationTimestamp: "2026-05-14T08:43:57Z" + finalizers: + - kubedb.com + generation: 3 + name: qdrant-sample + namespace: demo + resourceVersion: "3259342" + uid: 42df526b-fba5-4d21-aea4-d20ae5f36f30 +spec: + authSecret: + activeFrom: "2026-05-14T08:43:57Z" + apiGroup: "" + kind: Secret + name: qdrant-sample-auth + deletionPolicy: WipeOut + healthChecker: + failureThreshold: 3 + periodSeconds: 10 + timeoutSeconds: 10 + mode: Standalone + podTemplate: + controller: {} + metadata: {} + spec: + containers: + - name: qdrant + resources: + limits: + memory: 1Gi + requests: + cpu: 500m + memory: 1Gi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + runAsGroup: 1000 + runAsNonRoot: true + runAsUser: 1000 + seccompProfile: + type: RuntimeDefault + podPlacementPolicy: + name: default + securityContext: + fsGroup: 1000 + serviceAccountName: qdrant-sample + replicas: 1 + storage: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + storageClassName: standard + storageType: Durable + version: 1.17.0 +status: + conditions: + - lastTransitionTime: "2026-05-14T08:43:57Z" + message: 'The KubeDB operator has started the provisioning of Qdrant: demo qdrant-sample' + observedGeneration: 1 + reason: DatabaseProvisioningStartedSuccessfully + status: "True" + type: ProvisioningStarted + - lastTransitionTime: "2026-05-14T08:44:11Z" + message: All desired replicas are ready. + observedGeneration: 3 + reason: AllReplicasReady + status: "True" + type: ReplicaReady + - lastTransitionTime: "2026-05-14T08:44:22Z" + message: database demo/qdrant-sample is accepting connection + observedGeneration: 3 + reason: AcceptingConnection + status: "True" + type: AcceptingConnection + - lastTransitionTime: "2026-05-14T08:44:22Z" + message: database demo/qdrant-sample is ready + reason: AllReplicasReady + status: "True" + type: Ready + - lastTransitionTime: "2026-05-14T08:44:23Z" + message: 'The Qdrant: demo/qdrant-sample is successfully provisioned.' + observedGeneration: 3 + reason: DatabaseSuccessfullyProvisioned + status: "True" + type: Provisioned + phase: Ready +``` + +## Connect to Qdrant + +KubeDB creates a Secret containing authentication credentials for the Qdrant cluster. Let's check it: + +```bash +$ kubectl get secret -n demo qdrant-sample-auth -o yaml +``` +```yaml +apiVersion: v1 +data: + api-key: ZUlxZVlMcnB4dmJ4SFBsbA== + read-only-api-key: M04yN25yakF3WWtlS0hPYg== +kind: Secret +metadata: + annotations: + kubedb.com/auth-active-from: "2026-05-14T08:43:57Z" + creationTimestamp: "2026-05-14T08:43:57Z" + labels: + app.kubernetes.io/component: database + app.kubernetes.io/instance: qdrant-sample + app.kubernetes.io/managed-by: kubedb.com + app.kubernetes.io/name: qdrants.kubedb.com + name: qdrant-sample-auth + namespace: demo + ownerReferences: + - apiVersion: kubedb.com/v1alpha2 + blockOwnerDeletion: true + controller: true + kind: Qdrant + name: qdrant-sample + uid: 42df526b-fba5-4d21-aea4-d20ae5f36f30 + resourceVersion: "3259248" + uid: 760da5c0-76de-48ae-838d-01a63cf90b8b +type: Opaque +``` + +Now, let's connect to the Qdrant cluster using port forwarding: + +```bash +$ kubectl port-forward -n demo svc/qdrant-sample 6333:6333 +$ export QDRANT_API_KEY=$(kubectl get secret -n demo qdrant-sample-auth -o jsonpath='{.data.api-key}' | base64 -d) + +$ curl -H "api-key: $QDRANT_API_KEY" http://localhost:6333/collections +{"result":{"collections":[{"name":"KubeDBHealthCheckCollection"}]},"status":"ok","time":0.00001235} +``` + +Let's create a collection with some vector data: + +```bash +$ curl -X PUT http://localhost:6333/collections/demo_vectors \ + -H "Content-Type: application/json" \ + -H "api-key: $QDRANT_API_KEY" \ + -d '{ + "vectors": { + "size": 8, + "distance": "Cosine" + } + }' +{"result":true,"status":"ok","time":0.050803361} + +$ curl -X PUT "http://localhost:6333/collections/demo_vectors/points?wait=true" \ + -H "Content-Type: application/json" \ + -H "api-key: $QDRANT_API_KEY" \ + -d '{ + "points": [ + {"id": 1, "vector": [0.15, 0.22, 0.31, 0.44, 0.51, 0.68, 0.73, 0.89], "payload": {"label": "apple"}}, + {"id": 2, "vector": [0.12, 0.28, 0.35, 0.42, 0.53, 0.64, 0.71, 0.85], "payload": {"label": "banana"}}, + {"id": 3, "vector": [0.18, 0.21, 0.33, 0.46, 0.50, 0.66, 0.77, 0.82], "payload": {"label": "cherry"}} + ] + }' +{"result":{"operation_id":1,"status":"completed"},"status":"ok","time":0.001645376} +``` + +Now scroll through the points to verify they were stored: + +```bash +$ curl -X POST http://localhost:6333/collections/demo_vectors/points/scroll \ + -H "Content-Type: application/json" \ + -H "api-key: $QDRANT_API_KEY" \ + -d '{"limit": 5, "with_payload": true, "with_vector": false}' | jq +{ + "result": { + "points": [ + {"id": 1, "payload": {"label": "apple"}, "version": 1}, + {"id": 2, "payload": {"label": "banana"}, "version": 1}, + {"id": 3, "payload": {"label": "cherry"}, "version": 1} + ], + "next_page_offset": null + }, + "status": "ok", + "time": 0.000086921 +} +``` + +## AppBinding + +KubeDB creates an [AppBinding](/docs/guides/qdrant/concepts/appbinding.md) CR that holds the necessary information to connect with the database. + +```bash +$ kubectl get appbinding -n demo -o yaml +``` + +```yaml +apiVersion: v1 +items: + - apiVersion: appcatalog.appscode.com/v1alpha1 + kind: AppBinding + metadata: + annotations: + kubectl.kubernetes.io/last-applied-configuration: | + {"apiVersion":"kubedb.com/v1alpha2","kind":"Qdrant","metadata":{"annotations":{},"name":"qdrant-sample","namespace":"demo"},"spec":{"deletionPolicy":"WipeOut","mode":"Standalone","storage":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"1Gi"}},"storageClassName":"standard"},"version":"1.17.0"}} + creationTimestamp: "2026-05-14T08:44:00Z" + generation: 2 + labels: + app.kubernetes.io/component: database + app.kubernetes.io/instance: qdrant-sample + app.kubernetes.io/managed-by: kubedb.com + app.kubernetes.io/name: qdrants.kubedb.com + name: qdrant-sample + namespace: demo + ownerReferences: + - apiVersion: kubedb.com/v1alpha2 + blockOwnerDeletion: true + controller: true + kind: Qdrant + name: qdrant-sample + uid: 42df526b-fba5-4d21-aea4-d20ae5f36f30 + resourceVersion: "3259280" + uid: 7183b027-3eda-42ed-95f7-0a366d493464 + spec: + appRef: + apiGroup: kubedb.com + kind: Qdrant + name: qdrant-sample + namespace: demo + clientConfig: + service: + name: qdrant-sample + port: 6333 + scheme: http + secret: + apiGroup: "" + kind: Secret + name: qdrant-sample-auth + type: kubedb.com/qdrant + version: 1.17.0 +kind: List +metadata: + resourceVersion: "" +``` + +You can use this AppBinding to connect with the Qdrant cluster from external applications. + +## Database DeletionPolicy + +This field regulates the deletion process of the related resources when the `Qdrant` object is deleted. The available options are: + +**DoNotTerminate:** + +When `deletionPolicy` is set to `DoNotTerminate`, KubeDB prevents deletion of the database using admission webhooks. If you try to delete it, you will get an error: + +```bash +$ kubectl patch -n demo qdrant/qdrant-sample -p '{"spec":{"deletionPolicy":"DoNotTerminate"}}' --type="merge" +qdrant.kubedb.com/qdrant-sample patched + +$ kubectl delete qdrant -n demo qdrant-sample +The Qdrant "qdrant-sample" is invalid: spec.deletionPolicy: Invalid value: "qdrant-sample": Can not delete as deletionPolicy is set to "DoNotTerminate" +``` + +**Halt:** + +When `deletionPolicy` is set to `Halt`, KubeDB deletes the `Qdrant` object and its pods but keeps the `PVCs`, `Secrets`, and backup snapshots intact. This allows you to recreate the database later using the same data. + +At first, set the `deletionPolicy` to `Halt` and then delete the database: + +```bash +$ kubectl patch -n demo qdrant/qdrant-sample -p '{"spec":{"deletionPolicy":"Halt"}}' --type="merge" +qdrant.kubedb.com/qdrant-sample patched + +$ kubectl delete qdrant -n demo qdrant-sample +qdrant.kubedb.com "qdrant-sample" deleted +``` + +Now, check that the PVCs and Secrets still exist: + +```bash +$ kubectl get secret,pvc -n demo +NAME TYPE DATA AGE +secret/qdrant-sample-auth Opaque 2 11m +secret/qdrant-sample-f36f30 Opaque 1 11m + +NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE +persistentvolumeclaim/data-qdrant-sample-0 Bound pvc-0015c0ad-4ddd-404c-9d8b-b9ea1f6cc15f 1Gi RWO standard 11m + +``` + +You can recreate your Qdrant database later using these PVCs and Secrets. + +**Delete:** + +When `deletionPolicy` is set to `Delete`, KubeDB deletes the `Qdrant` object, pods, and `PVCs` but keeps the `Secrets` and backup snapshots. This allows you to restore the database from a previously taken backup. + +**WipeOut:** + +When `deletionPolicy` is set to `WipeOut`, KubeDB deletes all resources of this database (pods, PVCs, Secrets, snapshots, etc.). There is no option to recreate the database once deleted with this policy. + +```bash +$ kubectl patch -n demo qdrant/qdrant-sample -p '{"spec":{"deletionPolicy":"WipeOut"}}' --type="merge" +qdrant.kubedb.com/qdrant-sample patched +``` + +> Be careful when using `WipeOut` — there is no way to recover the database after deletion. + +## Next Steps + +- Learn about [backup and restore](/docs/guides/qdrant/backup/overview/index.md) Qdrant using KubeStash. +- Want to set up distributed Qdrant deployment? Check [Distributed Deployment](/docs/guides/qdrant/distributed-deployment/overview.md). +- Detail concepts of [Qdrant object](/docs/guides/qdrant/concepts/qdrant.md). +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). + +## Cleaning up + +To clean up the Kubernetes resources created by this tutorial, run: + +```bash +kubectl delete qdrant -n demo qdrant-sample +kubectl delete ns demo +``` \ No newline at end of file diff --git a/docs/guides/qdrant/reconfigure-tls/_index.md b/docs/guides/qdrant/reconfigure-tls/_index.md new file mode 100644 index 000000000..5c8936173 --- /dev/null +++ b/docs/guides/qdrant/reconfigure-tls/_index.md @@ -0,0 +1,10 @@ +--- +title: Reconfigure TLS +menu: + docs_{{ .version }}: + identifier: qdrant-reconfigure-tls + name: Reconfigure TLS + parent: qdrant-guides + weight: 80 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/qdrant/reconfigure-tls/overview.md b/docs/guides/qdrant/reconfigure-tls/overview.md new file mode 100644 index 000000000..7967228d5 --- /dev/null +++ b/docs/guides/qdrant/reconfigure-tls/overview.md @@ -0,0 +1,89 @@ +--- +title: Reconfiguring Qdrant TLS +menu: + docs_{{ .version }}: + identifier: qdrant-reconfigure-tls-overview + name: Overview + parent: qdrant-reconfigure-tls + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Reconfiguring TLS for Qdrant + +This guide will give an overview of how KubeDB Ops-manager reconfigures TLS for a `Qdrant` database. + +**QdrantOpsRequest CRD Specification:** + +KubeDB uses the following CRD fields to reconfigure TLS/SSL in `Qdrant`. + +- `spec:` + - `type: ReconfigureTLS` + - `tls:` + - `issuerRef` + - `certificates` + - `client` + - `p2p` + - `rotateCertificates` + - `remove` + +Read about the fields in detail from the [QdrantOpsRequest Concepts](/docs/guides/qdrant/concepts/opsrequest.md) page. + +## Before You Begin + +- You should be familiar with the following `KubeDB` concepts: + - [Qdrant](/docs/guides/qdrant/concepts/qdrant.md) + - [QdrantOpsRequest](/docs/guides/qdrant/concepts/opsrequest.md) + - [TLS/SSL Overview](/docs/guides/qdrant/tls/overview.md) +- Use the example files from `docs/examples/qdrant/quickstart/distributed.yaml` and `docs/examples/qdrant/reconfigure-tls/`. + +```bash +kubectl create ns demo +``` + +## Deploy Qdrant + +```bash +kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/quickstart/distributed.yaml +kubectl get qdrant -n demo qdrant-sample -w +``` + +## How Reconfigure TLS Works + +The following figure shows how `KubeDB` reconfigures TLS in Qdrant. Open the image in a new tab to see the enlarged version. + +
+Reconfigure Qdrant TLS +
Fig: Reconfigure Qdrant TLS
+
+ +The Reconfigure TLS process consists of the following steps: + +1. At first, a user creates a `Qdrant` CR. + +2. `KubeDB-Provisioner` operator watches the `Qdrant` CR. + +3. When the operator finds a `Qdrant` CR, it creates a `PetSet` and related necessary resources like secrets, services, etc. + +4. Then, in order to reconfigure TLS of the `Qdrant` database, the user creates a `QdrantOpsRequest` CR specifying the desired TLS configuration. The user can add TLS to an existing non-TLS database, rotate the existing certificates, change the issuer, or remove TLS entirely. + +5. `KubeDB` Ops-manager operator watches the `QdrantOpsRequest` CR. + +6. When it finds a `QdrantOpsRequest` CR, it pauses the `Qdrant` object so that the `KubeDB-Provisioner` operator doesn't perform any operations on the `Qdrant` during the TLS reconfiguration process. + +7. Then the `KubeDB` Ops-manager operator updates the TLS secrets and restarts the pods in a rolling fashion with the new TLS configuration. + +8. After the successful TLS reconfiguration, the `KubeDB` Ops-manager updates the `Qdrant` object to reflect the updated TLS state. + +9. After the successful Reconfigure TLS, the `KubeDB` Ops-manager resumes the `Qdrant` object so that the `KubeDB-Provisioner` resumes its usual operations. + +KubeDB supports the following TLS reconfiguration operations for Qdrant: + +- **Add TLS** — Enable TLS on an existing non-TLS Qdrant database. +- **Rotate TLS** — Rotate the existing TLS certificates to refresh expiring certificates. +- **Remove TLS** — Remove TLS from an existing TLS-enabled Qdrant database. + +In the next doc, we are going to show a step-by-step guide on reconfiguring TLS for a Qdrant database using `QdrantOpsRequest` CRD. diff --git a/docs/guides/qdrant/reconfigure-tls/reconfigure-tls.md b/docs/guides/qdrant/reconfigure-tls/reconfigure-tls.md new file mode 100644 index 000000000..ba83becad --- /dev/null +++ b/docs/guides/qdrant/reconfigure-tls/reconfigure-tls.md @@ -0,0 +1,262 @@ +--- +title: Reconfigure TLS of Qdrant +menu: + docs_{{ .version }}: + identifier: qdrant-reconfigure-tls-cluster + name: Cluster + parent: qdrant-reconfigure-tls + weight: 30 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Reconfigure Qdrant TLS/SSL (Transport Encryption) + +KubeDB supports reconfiguring TLS/SSL certificates for Qdrant — adding, removing, updating, and rotating certificates via a `QdrantOpsRequest`. This tutorial will show you how to use KubeDB to reconfigure TLS/SSL encryption. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the `kubectl` command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Install `cert-manager` v1.0.0 or later to your cluster to manage your SSL/TLS certificates from [here](https://cert-manager.io/docs/installation/). + +- Now, install `KubeDB` in your cluster following the steps [here](/docs/setup/README.md). + +- You should be familiar with the following `KubeDB` concepts: + - [Qdrant](/docs/guides/qdrant/concepts/qdrant.md) + - [QdrantOpsRequest](/docs/guides/qdrant/concepts/opsrequest.md) + - [TLS/SSL Overview](/docs/guides/qdrant/tls/overview.md) + +To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +> **Note:** YAML files used in this tutorial are stored in [docs/examples/qdrant/reconfigure-tls](/docs/examples/qdrant/reconfigure-tls) directory of [kubedb/docs](https://github.com/kubedb/docs) repository. + +## Add TLS to a Qdrant database + +Here, we are going to create a Qdrant database without TLS and then reconfigure the database to use TLS. + +### Deploy Qdrant without TLS + +In this section, we are going to deploy a Qdrant cluster without TLS. Below is the YAML of the `Qdrant` CR that we are going to create: + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + replicas: 3 + storage: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut +``` + +Let's create the `Qdrant` CR we have shown above: + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/reconfigure-tls/qdrant.yaml +qdrant.kubedb.com/qdrant-sample created +``` + +Now, wait until `qdrant-sample` has status `Ready`: + +```bash +$ kubectl get qdrant -n demo +NAME VERSION STATUS AGE +qdrant-sample 1.17.0 Ready 3m22s +``` + +### Create Issuer + +Now, we are going to create an example `Issuer` that will be used to enable SSL/TLS in Qdrant. Alternatively you can follow this [cert-manager tutorial](https://cert-manager.io/docs/configuration/ca/) to create your own `Issuer`. By following the below steps, we are going to create our desired issuer, + +1. Start off by generating our ca-certificates using openssl, + +```bash +$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./ca.key -out ./ca.crt -subj "/CN=qdrant/O=kubedb" +Generating a RSA private key +................+++++ +........................+++++ +writing new private key to './ca.key' +``` + +2. Create a secret using the certificate files we have just generated, + +```bash +$ kubectl create secret tls qdrant-ca --cert=ca.crt --key=ca.key --namespace=demo +secret/qdrant-ca created +``` + +3. Now we are going to create an `Issuer` using the `qdrant-ca` secret that contains the CA certificate we have just created: + +```yaml +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: qdrant-issuer + namespace: demo +spec: + ca: + secretName: qdrant-ca +``` + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/reconfigure-tls/issuer.yaml +issuer.cert-manager.io/qdrant-issuer created +``` + +### Add TLS + +Now, we are going to create a `QdrantOpsRequest` to add TLS to the running database. + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-add-tls + namespace: demo +spec: + type: ReconfigureTLS + databaseRef: + name: qdrant-sample + tls: + issuerRef: + name: qdrant-issuer + kind: Issuer + apiGroup: "cert-manager.io" + certificates: + - alias: server + subject: + organizations: + - kubedb:server + dnsNames: + - localhost + ipAddresses: + - "127.0.0.1" + timeout: 5m + apply: IfReady +``` + +Here, + +- `spec.databaseRef.name` specifies that we are performing reconfigure TLS operation on `qdrant-sample` database. +- `spec.type` specifies that we are performing `ReconfigureTLS` on our database. +- `spec.tls.issuerRef` specifies the issuer to use for signing certificates. +- `spec.tls.certificates` specifies the certificate configuration. +- `spec.timeout` specifies the timeout for the operation (learn more [here](/docs/guides/qdrant/concepts/opsrequest.md#spectimeout)). +- `spec.apply` specifies when to apply the operation (learn more [here](/docs/guides/qdrant/concepts/opsrequest.md#specapply)). + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/reconfigure-tls/add-tls.yaml +qdrantopsrequest.ops.kubedb.com/qdops-add-tls created +``` + +Let's wait for `QdrantOpsRequest` to be `Successful`: + +```bash +$ watch -n 3 kubectl get QdrantOpsRequest -n demo qdops-add-tls +Every 3.0s: kubectl get QdrantOpsRequest -n demo qdops-add-tls + +NAME TYPE STATUS AGE +qdops-add-tls ReconfigureTLS Successful 6m30s +``` + +## Rotate Certificates + +Now we are going to rotate the certificates of the database. + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-rotate-tls + namespace: demo +spec: + type: ReconfigureTLS + databaseRef: + name: qdrant-sample + tls: + rotateCertificates: true +``` + +Here, + +- `spec.tls.rotateCertificates` specifies that we are requesting to rotate the certificates of the `qdrant-sample` database. + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/reconfigure-tls/rotate-tls.yaml +qdrantopsrequest.ops.kubedb.com/qdops-rotate-tls created +``` + +Let's wait for `QdrantOpsRequest` to be `Successful`: + +```bash +$ kubectl get qdrantopsrequest -n demo qdops-rotate-tls +NAME TYPE STATUS AGE +qdops-rotate-tls ReconfigureTLS Successful 3m8s +``` + +## Remove TLS from the Database + +In this section, we are going to reconfigure TLS setting of the database by removing the TLS configuration. + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-remove-tls + namespace: demo +spec: + type: ReconfigureTLS + databaseRef: + name: qdrant-sample + tls: + remove: true +``` + +Here, + +- `spec.tls.remove` specifies that we are removing the TLS configuration from `qdrant-sample` database. + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/reconfigure-tls/remove-tls.yaml +qdrantopsrequest.ops.kubedb.com/qdops-remove-tls created +``` + +Let's wait for `QdrantOpsRequest` to be `Successful`: + +```bash +$ kubectl get qdrantopsrequest -n demo qdops-remove-tls +NAME TYPE STATUS AGE +qdops-remove-tls ReconfigureTLS Successful 4m20s +``` + +## Next Steps + +- Learn about [backup and restore](/docs/guides/qdrant/backup/overview/index.md) Qdrant using KubeStash. +- Detail concepts of [Qdrant object](/docs/guides/qdrant/concepts/qdrant.md). +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). + +## Cleaning up + +To clean up the Kubernetes resources created by this tutorial, run: + +```bash +kubectl delete qdrantopsrequest -n demo qdops-add-tls qdops-rotate-tls qdops-remove-tls +kubectl delete qdrant -n demo qdrant-sample +kubectl delete issuer -n demo qdrant-issuer +kubectl delete ns demo +``` \ No newline at end of file diff --git a/docs/guides/qdrant/reconfigure/_index.md b/docs/guides/qdrant/reconfigure/_index.md new file mode 100644 index 000000000..b6f1276ca --- /dev/null +++ b/docs/guides/qdrant/reconfigure/_index.md @@ -0,0 +1,10 @@ +--- +title: Reconfigure +menu: + docs_{{ .version }}: + identifier: qdrant-reconfigure + name: Reconfigure + parent: qdrant-guides + weight: 70 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/qdrant/reconfigure/overview.md b/docs/guides/qdrant/reconfigure/overview.md new file mode 100644 index 000000000..c869d99c7 --- /dev/null +++ b/docs/guides/qdrant/reconfigure/overview.md @@ -0,0 +1,54 @@ +--- +title: Reconfiguring Qdrant +menu: + docs_{{ .version }}: + identifier: qdrant-reconfigure-overview + name: Overview + parent: qdrant-reconfigure + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Reconfiguring Qdrant + +This guide will give an overview on how KubeDB Ops-manager operator reconfigures `Qdrant` database. + +## Before You Begin + +- You should be familiar with the following `KubeDB` concepts: + - [Qdrant](/docs/guides/qdrant/concepts/qdrant.md) + - [QdrantOpsRequest](/docs/guides/qdrant/concepts/opsrequest.md) + +## How Reconfiguring Qdrant Process Works + +The following diagram shows how KubeDB Ops-manager operator reconfigures `Qdrant` database. Open the image in a new tab to see the enlarged version. + +
+  Reconfiguring process of Qdrant +
Fig: Reconfiguring process of Qdrant
+
+ +The Reconfiguring Qdrant process consists of the following steps: + +1. At first, a user creates a `Qdrant` Custom Resource (CR). + +2. `KubeDB` Provisioner operator watches the `Qdrant` CR. + +3. When the operator finds a `Qdrant` CR, it creates required number of `PetSets` and related necessary stuff like secrets, services, etc. + +4. Then, in order to reconfigure the `Qdrant` database the user creates a `QdrantOpsRequest` CR with desired information. + +5. `KubeDB` Ops-manager operator watches the `QdrantOpsRequest` CR. + +6. When it finds a `QdrantOpsRequest` CR, it halts the `Qdrant` object which is referred from the `QdrantOpsRequest`. So, the `KubeDB` Provisioner operator doesn't perform any operations on the `Qdrant` object during the reconfiguring process. + +7. Then the `KubeDB` Ops-manager operator will replace the existing configuration with the new configuration provided or merge the new configuration with the existing configuration according to the `QdrantOpsRequest` CR. + +8. Then the `KubeDB` Ops-manager operator will restart the related PetSet Pods so that they restart with the new configuration defined in the `QdrantOpsRequest` CR. + +9. After the successful reconfiguring of the `Qdrant`, the `KubeDB` Ops-manager operator resumes the `Qdrant` object so that the `KubeDB` Provisioner operator resumes its usual operations. + +In the next docs, we are going to show a step-by-step guide on reconfiguring Qdrant database using `QdrantOpsRequest` CR. diff --git a/docs/guides/qdrant/reconfigure/reconfigure.md b/docs/guides/qdrant/reconfigure/reconfigure.md new file mode 100644 index 000000000..d4937b24b --- /dev/null +++ b/docs/guides/qdrant/reconfigure/reconfigure.md @@ -0,0 +1,282 @@ +--- +title: Reconfigure Qdrant +menu: + docs_{{ .version }}: + identifier: qdrant-reconfigure-cluster + name: Cluster + parent: qdrant-reconfigure + weight: 30 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Reconfigure Qdrant + +This guide will show you how to use `KubeDB` Enterprise operator to reconfigure a Qdrant cluster. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the `kubectl` command-line tool must be configured to communicate with your cluster. + +- Install `KubeDB` Community and Enterprise operator in your cluster following the steps [here](/docs/setup/README.md). + +- You should be familiar with the following `KubeDB` concepts: + - [Qdrant](/docs/guides/qdrant/concepts/qdrant.md) + - [QdrantOpsRequest](/docs/guides/qdrant/concepts/opsrequest.md) + - [Reconfigure Overview](/docs/guides/qdrant/reconfigure/overview.md) + +To keep everything isolated, we are going to use a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +> **Note:** YAML files used in this tutorial are stored in [docs/examples/qdrant/reconfigure](/docs/examples/qdrant/reconfigure) directory of [kubedb/docs](https://github.com/kubedb/docs) repository. + +## Prepare Qdrant + +Now, we are going to deploy a `Qdrant` cluster with an initial configuration. + +### Deploy Qdrant with custom config + +Below is the YAML of the configuration `Secret` that we are going to create: + +```yaml +apiVersion: v1 +stringData: + config.yaml: | + log_level: DEBUG + performance: + max_search_threads: 4 + update_rate_limit: 100 +kind: Secret +metadata: + name: qdrant-configuration + namespace: demo +type: Opaque +``` + +Let's create the `Secret` we have shown above: + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/reconfigure/configuration-secret.yaml +secret/qdrant-configuration created +``` + +Below is the YAML of the `Qdrant` CR that we are going to create: + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + replicas: 3 + configSecret: + name: qdrant-configuration + storage: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut +``` + +Let's create the `Qdrant` CR we have shown above: + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/reconfigure/qdrant.yaml +qdrant.kubedb.com/qdrant-sample created +``` + +Now, wait until `qdrant-sample` has status `Ready`: + +```bash +$ kubectl get qdrant -n demo +NAME VERSION STATUS AGE +qdrant-sample 1.17.0 Ready 3m42s +``` + +## Reconfigure using new config secret + +Now we will reconfigure this database to change `max_search_threads` to `8`. + +Below is the YAML of the new configuration `Secret` that we are going to create: + +```yaml +apiVersion: v1 +stringData: + config.yaml: | + log_level: DEBUG + performance: + max_search_threads: 8 + update_rate_limit: 100 +kind: Secret +metadata: + name: new-qdrant-configuration + namespace: demo +type: Opaque +``` + +Let's create the `Secret` we have shown above: + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/reconfigure/new-configuration-secret.yaml +secret/new-qdrant-configuration created +``` + +### Create QdrantOpsRequest + +Now, we will use this secret to replace the previous secret using a `QdrantOpsRequest` CR. Below is the YAML of the `QdrantOpsRequest` that we are going to create: + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-reconfigure-config + namespace: demo +spec: + type: Reconfigure + databaseRef: + name: qdrant-sample + configuration: + configSecret: + name: new-qdrant-configuration + timeout: 5m + apply: IfReady +``` + +Here, + +- `spec.databaseRef.name` specifies that we are reconfiguring `qdrant-sample` database. +- `spec.type` specifies that we are performing `Reconfigure` on our database. +- `spec.configuration.configSecret.name` specifies the name of the new configuration secret. +- `spec.timeout` specifies the timeout for the operation (learn more [here](/docs/guides/qdrant/concepts/opsrequest.md#spectimeout)). +- `spec.apply` specifies when to apply the operation (learn more [here](/docs/guides/qdrant/concepts/opsrequest.md#specapply)). + +Let's create the `QdrantOpsRequest` CR we have shown above: + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/reconfigure/reconfigure-using-secret.yaml +qdrantopsrequest.ops.kubedb.com/qdops-reconfigure-config created +``` + +### Verify the new configuration is working + +If everything goes well, `KubeDB` Enterprise operator will update the `configSecret` of the `Qdrant` object. + +Let's wait for `QdrantOpsRequest` to be `Successful`: + +```bash +$ kubectl get qdops -n demo +NAME TYPE STATUS AGE +qdops-reconfigure-config Reconfigure Successful 3m +``` + +## Reconfigure using applyConfig + +We can also reconfigure our existing secret by modifying configuration inline using `applyConfig`. Below is the YAML of the `QdrantOpsRequest`: + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-reconfigure-apply-config + namespace: demo +spec: + type: Reconfigure + databaseRef: + name: qdrant-sample + configuration: + applyConfig: + config.yaml: | + log_level: DEBUG + performance: + max_search_threads: 6 + update_rate_limit: 100 +``` + +> **Note:** You can modify multiple fields of your current configuration using `applyConfig`. If you don't have any existing config secret, `applyConfig` will create a new secret for you. If a config secret already exists, `applyConfig` will merge the new configuration with the existing one. + +Here, + +- `spec.databaseRef.name` specifies that we are reconfiguring `qdrant-sample` database. +- `spec.type` specifies that we are performing `Reconfigure` on our database. +- `spec.configuration.applyConfig` contains the inline configuration to apply. + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/reconfigure/apply-config.yaml +qdrantopsrequest.ops.kubedb.com/qdops-reconfigure-apply-config created +``` + +### Verify the new configuration is working + +Let's wait for `QdrantOpsRequest` to be `Successful`: + +```bash +$ kubectl get qdops qdops-reconfigure-apply-config -n demo +NAME TYPE STATUS AGE +qdops-reconfigure-apply-config Reconfigure Successful 5m30s +``` + +## Remove Custom Configuration + +We can also remove existing custom config using `QdrantOpsRequest`. Set `spec.configuration.removeCustomConfig: true` to remove the existing custom configuration. + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-reconfigure-remove + namespace: demo +spec: + type: Reconfigure + databaseRef: + name: qdrant-sample + configuration: + removeCustomConfig: true +``` + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/reconfigure/remove-config.yaml +qdrantopsrequest.ops.kubedb.com/qdops-reconfigure-remove created +``` + +Let's wait for `QdrantOpsRequest` to be `Successful`: + +```bash +$ kubectl get qdops qdops-reconfigure-remove -n demo +NAME TYPE STATUS AGE +qdops-reconfigure-remove Reconfigure Successful 97s +``` + +After this, the `Qdrant` CR will no longer reference a `configSecret` and the database will use its default configuration. + +## Next Steps + +- Learn about [backup and restore](/docs/guides/qdrant/backup/overview/index.md) Qdrant using KubeStash. +- Detail concepts of [Qdrant object](/docs/guides/qdrant/concepts/qdrant.md). +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). + +## Cleaning up + +To clean up the Kubernetes resources created by this tutorial, run: + +```bash +$ kubectl delete qdrantopsrequest -n demo qdops-reconfigure-config qdops-reconfigure-apply-config qdops-reconfigure-remove +qdrantopsrequest.ops.kubedb.com "qdops-reconfigure-config" deleted +qdrantopsrequest.ops.kubedb.com "qdops-reconfigure-apply-config" deleted +qdrantopsrequest.ops.kubedb.com "qdops-reconfigure-remove" deleted + +$ kubectl delete qdrant -n demo qdrant-sample +qdrant.kubedb.com "qdrant-sample" deleted + +$ kubectl delete ns demo +namespace "demo" deleted +``` \ No newline at end of file diff --git a/docs/guides/qdrant/restart/_index.md b/docs/guides/qdrant/restart/_index.md new file mode 100644 index 000000000..c649fe0bf --- /dev/null +++ b/docs/guides/qdrant/restart/_index.md @@ -0,0 +1,10 @@ +--- +title: Restart Qdrant +menu: + docs_{{ .version }}: + identifier: qdrant-restart + name: Restart + parent: qdrant-guides + weight: 90 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/qdrant/restart/restart.md b/docs/guides/qdrant/restart/restart.md new file mode 100644 index 000000000..ffbba14bd --- /dev/null +++ b/docs/guides/qdrant/restart/restart.md @@ -0,0 +1,219 @@ +--- +title: Restart Qdrant +menu: + docs_{{ .version }}: + identifier: qdrant-restart-overview + name: Restart Qdrant + parent: qdrant-restart + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Restart Qdrant + +KubeDB supports restarting the Qdrant database via a `QdrantOpsRequest`. Restarting is useful if some pods are stuck in a non-running phase or are not working correctly. This tutorial will show you how to use that. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the `kubectl` command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Now, install `KubeDB` in your cluster following the steps [here](/docs/setup/README.md). + +- You should be familiar with the following `KubeDB` concepts: + - [Qdrant](/docs/guides/qdrant/concepts/qdrant.md) + - [QdrantOpsRequest](/docs/guides/qdrant/concepts/opsrequest.md) + +To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +> **Note:** YAML files used in this tutorial are stored in [docs/examples/qdrant/restart](https://github.com/kubedb/docs/tree/{{< param "info.version" >}}/docs/examples/qdrant/restart) folder in GitHub repository [kubedb/docs](https://github.com/kubedb/docs). + +## Deploy Qdrant + +In this section, we are going to deploy a Qdrant database using KubeDB. + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + replicas: 3 + storage: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut +``` + +Let's create the `Qdrant` CR we have shown above, + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/restart/qdrant.yaml +qdrant.kubedb.com/qdrant-sample created +``` + +Now, wait until `qdrant-sample` has status `Ready`: + +```bash +$ kubectl get qdrant -n demo +NAME VERSION STATUS AGE +qdrant-sample 1.17.0 Ready 3m47s +``` + +## Apply Restart OpsRequest + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-restart + namespace: demo +spec: + type: Restart + databaseRef: + name: qdrant-sample + timeout: 3m + apply: Always +``` + +- `spec.type` specifies the type of the OpsRequest. +- `spec.databaseRef` holds the name of the Qdrant database. The db should be available in the same namespace as the OpsRequest. +- The meaning of `spec.timeout` & `spec.apply` fields can be found [here](/docs/guides/qdrant/concepts/opsrequest.md). + +Let's create the `QdrantOpsRequest` CR we have shown above, + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/restart/ops-request.yaml +qdrantopsrequest.ops.kubedb.com/qdops-restart created +``` + +Now the Ops-manager operator will restart the Qdrant pods one by one, waiting for each pod to come back to `Running` state before proceeding to the next. + +```bash +$ kubectl get qdops -n demo qdops-restart +NAME TYPE STATUS AGE +qdops-restart Restart Successful 66s +``` + +```bash +$ kubectl get qdops -n demo qdops-restart -o yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + annotations: + kubectl.kubernetes.io/last-applied-configuration: | + {"apiVersion":"ops.kubedb.com/v1alpha1","kind":"QdrantOpsRequest","metadata":{"annotations":{},"name":"qdops-restart","namespace":"demo"},"spec":{"apply":"Always","databaseRef":{"name":"qdrant-sample"},"timeout":"3m","type":"Restart"}} + creationTimestamp: "2026-05-15T05:43:05Z" + generation: 1 + name: qdops-restart + namespace: demo + resourceVersion: "3357120" + uid: f90d628f-1db2-4fbc-a20d-e449ab7215a8 +spec: + apply: Always + databaseRef: + name: qdrant-sample + maxRetries: 1 + timeout: 3m + type: Restart +status: + conditions: + - lastTransitionTime: "2026-05-15T05:43:05Z" + message: Qdrant ops-request has started to restart Qdrant nodes + observedGeneration: 1 + reason: Restart + status: "True" + type: Restart + - lastTransitionTime: "2026-05-15T05:44:07Z" + message: Successfully Restarted Qdrant nodes + observedGeneration: 1 + reason: RestartNodes + status: "True" + type: RestartNodes + - lastTransitionTime: "2026-05-15T05:43:17Z" + message: get pod; ConditionStatus:True; PodName:qdrant-sample-0 + observedGeneration: 1 + status: "True" + type: GetPod--qdrant-sample-0 + - lastTransitionTime: "2026-05-15T05:43:18Z" + message: evict pod; ConditionStatus:True; PodName:qdrant-sample-0 + observedGeneration: 1 + status: "True" + type: EvictPod--qdrant-sample-0 + - lastTransitionTime: "2026-05-15T05:43:32Z" + message: running pod; ConditionStatus:True; PodName:qdrant-sample-0 + observedGeneration: 1 + status: "True" + type: RunningPod--qdrant-sample-0 + - lastTransitionTime: "2026-05-15T05:43:37Z" + message: get pod; ConditionStatus:True; PodName:qdrant-sample-1 + observedGeneration: 1 + status: "True" + type: GetPod--qdrant-sample-1 + - lastTransitionTime: "2026-05-15T05:43:38Z" + message: evict pod; ConditionStatus:True; PodName:qdrant-sample-1 + observedGeneration: 1 + status: "True" + type: EvictPod--qdrant-sample-1 + - lastTransitionTime: "2026-05-15T05:43:42Z" + message: running pod; ConditionStatus:True; PodName:qdrant-sample-1 + observedGeneration: 1 + status: "True" + type: RunningPod--qdrant-sample-1 + - lastTransitionTime: "2026-05-15T05:43:47Z" + message: get pod; ConditionStatus:True; PodName:qdrant-sample-2 + observedGeneration: 1 + status: "True" + type: GetPod--qdrant-sample-2 + - lastTransitionTime: "2026-05-15T05:43:48Z" + message: evict pod; ConditionStatus:True; PodName:qdrant-sample-2 + observedGeneration: 1 + status: "True" + type: EvictPod--qdrant-sample-2 + - lastTransitionTime: "2026-05-15T05:44:02Z" + message: running pod; ConditionStatus:True; PodName:qdrant-sample-2 + observedGeneration: 1 + status: "True" + type: RunningPod--qdrant-sample-2 + - lastTransitionTime: "2026-05-15T05:44:08Z" + message: Controller has successfully restarted the Qdrant replicas + observedGeneration: 1 + reason: Successful + status: "True" + type: Successful + observedGeneration: 1 + phase: Successful +``` + +## Next Steps + +- Learn about [backup and restore](/docs/guides/qdrant/backup/overview/index.md) Qdrant using KubeStash. +- Detail concepts of [Qdrant object](/docs/guides/qdrant/concepts/qdrant.md). +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). + +## Cleaning up + +To cleanup the Kubernetes resources created by this tutorial, run: + +```bash +$ kubectl delete qdrantopsrequest -n demo qdops-restart +qdrantopsrequest.ops.kubedb.com "qdops-restart" deleted + +$ kubectl delete qdrant -n demo qdrant-sample +qdrant.kubedb.com "qdrant-sample" deleted + +$ kubectl delete ns demo +namespace "demo" deleted +``` diff --git a/docs/guides/qdrant/rotate-auth/_index.md b/docs/guides/qdrant/rotate-auth/_index.md new file mode 100644 index 000000000..031524a4a --- /dev/null +++ b/docs/guides/qdrant/rotate-auth/_index.md @@ -0,0 +1,10 @@ +--- +title: Rotate Auth +menu: + docs_{{ .version }}: + identifier: qdrant-rotate-auth + name: Rotate Auth + parent: qdrant-guides + weight: 100 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/qdrant/rotate-auth/overview.md b/docs/guides/qdrant/rotate-auth/overview.md new file mode 100644 index 000000000..5e42ce89e --- /dev/null +++ b/docs/guides/qdrant/rotate-auth/overview.md @@ -0,0 +1,47 @@ +--- +title: Rotate Authentication Overview +menu: + docs_{{ .version }}: + identifier: qdrant-rotate-auth-overview + name: Overview + parent: qdrant-rotate-auth + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Rotate Authentication of Qdrant + +This guide will give an overview on how KubeDB Ops-manager operator Rotate Authentication configuration. + +## Before You Begin + +- You should be familiar with the following `KubeDB` concepts: + - [Qdrant](/docs/guides/qdrant/concepts/qdrant.md) + - [QdrantOpsRequest](/docs/guides/qdrant/concepts/opsrequest.md) + +## How Rotate Qdrant Authentication Configuration Process Works + +The authentication rotation process for Qdrant using KubeDB involves the following steps: + +1. A user first creates a `Qdrant` Custom Resource Object (CRO). + +2. The `KubeDB Provisioner operator` continuously watches for `Qdrant` CROs. + +3. When the operator detects a `Qdrant` CR, it provisions the required `PetSets`, along with related resources such as secrets, services, and other dependencies. + +4. To initiate authentication rotation, the user creates a `QdrantOpsRequest` CR with the desired configuration. + +5. The `KubeDB Ops-manager` operator watches for `QdrantOpsRequest` CRs. + +6. Upon detecting a `QdrantOpsRequest`, the operator pauses the referenced `Qdrant` object, ensuring that the Provisioner operator does not perform any operations during the authentication rotation process. + +7. The `Ops-manager` operator then updates the necessary configuration (such as credentials) based on the provided `QdrantOpsRequest` specification. + +8. After applying the updated configuration, the operator restarts all `Qdrant` Pods so they come up with the new authentication environment variables and settings. + +9. Once the authentication rotation is completed successfully, the operator resumes the `Qdrant` object, allowing the Provisioner operator to continue its usual operations. + +In the next section, we will walk you through a step-by-step guide to rotating Qdrant authentication using the `QdrantOpsRequest` CRD. diff --git a/docs/guides/qdrant/rotate-auth/rotate-auth.md b/docs/guides/qdrant/rotate-auth/rotate-auth.md new file mode 100644 index 000000000..938efe152 --- /dev/null +++ b/docs/guides/qdrant/rotate-auth/rotate-auth.md @@ -0,0 +1,208 @@ +--- +title: Rotate Auth of Qdrant +menu: + docs_{{ .version }}: + identifier: qdrant-rotate-auth-description + name: Rotate Auth + parent: qdrant-rotate-auth + weight: 20 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Rotate Authentication for Qdrant + +KubeDB supports rotating authentication credentials (API key) for Qdrant via a `QdrantOpsRequest`. This tutorial will show you how to use KubeDB to rotate authentication credentials. + +KubeDB supports two methods for rotating credentials: +- **Operator Generated** — KubeDB generates a new API key automatically. +- **User Defined** — You provide a custom secret with a new API key. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the `kubectl` command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Now, install `KubeDB` in your cluster following the steps [here](/docs/setup/README.md). + +- You should be familiar with the following `KubeDB` concepts: + - [Qdrant](/docs/guides/qdrant/concepts/qdrant.md) + - [QdrantOpsRequest](/docs/guides/qdrant/concepts/opsrequest.md) + +To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +> **Note:** YAML files used in this tutorial are stored in [docs/examples/qdrant/rotate-auth](https://github.com/kubedb/docs/tree/{{< param "info.version" >}}/docs/examples/qdrant/rotate-auth) folder in GitHub repository [kubedb/docs](https://github.com/kubedb/docs). + +## Deploy Qdrant + +In this section, we are going to deploy a Qdrant database using KubeDB. + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + replicas: 3 + storage: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut +``` + +Let's create the `Qdrant` CR we have shown above: + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/rotate-auth/qdrant.yaml +qdrant.kubedb.com/qdrant-sample created +``` + +Now, wait until `qdrant-sample` has status `Ready`: + +```bash +$ kubectl get qdrant -n demo +NAME VERSION STATUS AGE +qdrant-sample 1.17.0 Ready 3m22s +``` + +When Qdrant is deployed, KubeDB creates a secret called `qdrant-sample-auth` (format: `{db-name}-auth`) that stores the API key used for authentication. + +```bash +$ kubectl get secret -n demo qdrant-sample-auth -o jsonpath='{.data.api-key}' | base64 --decode + +``` + +## Apply RotateAuth OpsRequest + +Now, we are going to create a `QdrantOpsRequest` to rotate the authentication credentials. + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-rotate-auth + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: qdrant-sample + timeout: 5m + apply: IfReady +``` + +Here, + +- `spec.databaseRef.name` specifies that we are rotating auth credentials for `qdrant-sample` Qdrant database. +- `spec.type` specifies that we are performing `RotateAuth` on our database. +- `spec.timeout` specifies the timeout for the operation (learn more [here](/docs/guides/qdrant/concepts/opsrequest.md#spectimeout)). +- `spec.apply` specifies when to apply the operation (learn more [here](/docs/guides/qdrant/concepts/opsrequest.md#specapply)). + +Let's create the `QdrantOpsRequest` CR we have shown above: + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/rotate-auth/ops-request.yaml +qdrantopsrequest.ops.kubedb.com/qdops-rotate-auth created +``` + +## Verify Authentication Rotated + +If everything goes well, `KubeDB` ops-manager operator will rotate the authentication credentials of the `Qdrant` database. + +Let's wait for `QdrantOpsRequest` to be `Successful`: + +```bash +$ watch -n 3 kubectl get QdrantOpsRequest -n demo qdops-rotate-auth +Every 3.0s: kubectl get QdrantOpsRequest -n demo qdops-rotate-auth + +NAME TYPE STATUS AGE +qdops-rotate-auth RotateAuth Successful 2m15s +``` + +We can see from the above output that the `QdrantOpsRequest` has succeeded. Now let's check if the authentication secret has been updated: + +```bash +$ kubectl get secret -n demo qdrant-sample-auth -o jsonpath='{.data.api-key}' | base64 --decode + +``` + +You can see that the API key has been rotated. The new key is different from the initial key. KubeDB has automatically updated the Qdrant instances to use the new credentials. + +## Rotate Auth with a Custom Secret + +You can also rotate the authentication credentials using a custom secret that you provide: + +```yaml +apiVersion: v1 +stringData: + api-key: MyCus0mAPIKey +kind: Secret +metadata: + name: my-custom-auth-secret + namespace: demo +type: Opaque +``` + +Let's create the `Secret` we have shown above: + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/rotate-auth/custom-auth-secret.yaml +secret/my-custom-auth-secret created +``` + +Now, create a `QdrantOpsRequest` with the custom secret reference: + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-rotate-auth-custom + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: qdrant-sample + authentication: + secretRef: + name: my-custom-auth-secret +``` + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/rotate-auth/ops-custom.yaml +qdrantopsrequest.ops.kubedb.com/qdops-rotate-auth-custom created +``` + +## Next Steps + +- Learn about [backup and restore](/docs/guides/qdrant/backup/overview/index.md) Qdrant using KubeStash. +- Detail concepts of [Qdrant object](/docs/guides/qdrant/concepts/qdrant.md). +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). + +## Cleaning up + +To clean up the Kubernetes resources created by this tutorial, run: + +```bash +$ kubectl delete qdrantopsrequest -n demo qdops-rotate-auth qdops-rotate-auth-custom +qdrantopsrequest.ops.kubedb.com "qdops-rotate-auth" deleted +qdrantopsrequest.ops.kubedb.com "qdops-rotate-auth-custom" deleted + +$ kubectl delete secret -n demo my-custom-auth-secret +secret "my-custom-auth-secret" deleted + +$ kubectl delete qdrant -n demo qdrant-sample +qdrant.kubedb.com "qdrant-sample" deleted + +$ kubectl delete ns demo +namespace "demo" deleted +``` \ No newline at end of file diff --git a/docs/guides/qdrant/scaling/_index.md b/docs/guides/qdrant/scaling/_index.md new file mode 100644 index 000000000..7584e95ea --- /dev/null +++ b/docs/guides/qdrant/scaling/_index.md @@ -0,0 +1,10 @@ +--- +title: Scaling +menu: + docs_{{ .version }}: + identifier: qdrant-scaling + name: Scaling + parent: qdrant-guides + weight: 130 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/qdrant/scaling/horizontal-scaling/_index.md b/docs/guides/qdrant/scaling/horizontal-scaling/_index.md new file mode 100644 index 000000000..ed04b2b30 --- /dev/null +++ b/docs/guides/qdrant/scaling/horizontal-scaling/_index.md @@ -0,0 +1,10 @@ +--- +title: Horizontal Scaling +menu: + docs_{{ .version }}: + identifier: qdrant-horizontal-scaling + name: Horizontal Scaling + parent: qdrant-scaling + weight: 10 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/qdrant/scaling/horizontal-scaling/horizontal-scaling.md b/docs/guides/qdrant/scaling/horizontal-scaling/horizontal-scaling.md new file mode 100644 index 000000000..8d3bb2ff7 --- /dev/null +++ b/docs/guides/qdrant/scaling/horizontal-scaling/horizontal-scaling.md @@ -0,0 +1,244 @@ +--- +title: Scale Qdrant Horizontally +menu: + docs_{{ .version }}: + identifier: qdrant-horizontal-scaling-ops + name: Scale Horizontally + parent: qdrant-horizontal-scaling + weight: 20 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Horizontal Scale Qdrant Cluster + +This guide will show you how to use `KubeDB` Ops Manager to increase/decrease the number of nodes in a `Qdrant` cluster. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the `kubectl` command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Install `KubeDB` in your cluster following the steps [here](/docs/setup/README.md). + +- You should be familiar with the following `KubeDB` concepts: + - [Qdrant](/docs/guides/qdrant/concepts/qdrant.md) + - [QdrantOpsRequest](/docs/guides/qdrant/concepts/opsrequest.md) + - [Horizontal Scaling Overview](/docs/guides/qdrant/scaling/horizontal-scaling/overview.md) + +To keep everything isolated, we are going to use a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +> **Note:** YAML files used in this tutorial are stored in [docs/examples/qdrant/scaling/horizontal-scaling](/docs/examples/qdrant/scaling/horizontal-scaling) directory of [kubedb/docs](https://github.com/kubedb/docs) repository. + +## Apply Horizontal Scaling on Qdrant Cluster + +Here, we are going to deploy a `Qdrant` cluster using a supported version by `KubeDB` operator. Then we are going to apply horizontal scaling on it. + +### Prepare Cluster + +At first, we are going to deploy a cluster with 3 nodes. Then, we are going to add two additional nodes through horizontal scaling. Finally, we will remove 1 node from the cluster again via horizontal scaling. + +**Deploy Qdrant Cluster:** + +In this section, we are going to deploy a Qdrant cluster with 3 nodes. Then, in the next section we will scale the cluster using horizontal scaling. Below is the YAML of the `Qdrant` CR that we are going to create: + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + replicas: 3 + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut +``` + +Let's create the `Qdrant` CR we have shown above: + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/scaling/horizontal-scaling/qdrant.yaml +qdrant.kubedb.com/qdrant-sample created +``` + +**Wait for the cluster to be ready:** + +`KubeDB` operator watches for `Qdrant` objects using Kubernetes API. When a `Qdrant` object is created, `KubeDB` operator will create a new PetSet, Services, and Secrets, etc. + +Now, watch `Qdrant` is going to `Running` state and also watch `PetSet` and its pods: + +```bash +$ watch -n 3 kubectl get qdrant -n demo qdrant-sample +Every 3.0s: kubectl get qdrant -n demo qdrant-sample + +NAME VERSION STATUS AGE +qdrant-sample 1.17.0 Ready 4m40m + + +$ watch -n 3 kubectl get petset -n demo qdrant-sample +Every 3.0s: kubectl get petset -n demo qdrant-sample + +NAME READY AGE +qdrant-sample 3/3 4m41m + + +$ watch -n 3 kubectl get pods -n demo +Every 3.0s: kubectl get pod -n demo + +NAME READY STATUS RESTARTS AGE +qdrant-sample-0 1/1 Running 0 4m25m +qdrant-sample-1 1/1 Running 0 4m26m +qdrant-sample-2 1/1 Running 0 4m26m +``` + +Let's check the current number of nodes: + +```bash +$ kubectl get qdrant -n demo qdrant-sample -o=jsonpath='{.spec.replicas}{"\n"}' +3 +``` + +We are ready to apply the `QdrantOpsRequest` CR to scale horizontally. + +### Scale Up + +Here, we are going to scale up the cluster from 3 nodes to 5 nodes. + +**Create QdrantOpsRequest:** + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-hscale-up + namespace: demo +spec: + type: HorizontalScaling + databaseRef: + name: qdrant-sample + horizontalScaling: + node: 5 + timeout: 5m + apply: IfReady +``` + +Here, + +- `spec.databaseRef.name` specifies that we are performing horizontal scaling on `qdrant-sample` Qdrant database. +- `spec.type` specifies that we are performing `HorizontalScaling` on our database. +- `spec.horizontalScaling.node` specifies the desired number of nodes after scaling. +- `spec.timeout` specifies the timeout for the operation (learn more [here](/docs/guides/qdrant/concepts/opsrequest.md#spectimeout)). +- `spec.apply` specifies when to apply the operation (learn more [here](/docs/guides/qdrant/concepts/opsrequest.md#specapply)). + +Let's create the `QdrantOpsRequest` CR we have shown above: + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/scaling/horizontal-scaling/hscale-up.yaml +qdrantopsrequest.ops.kubedb.com/qdops-hscale-up created +``` + +**Verify Qdrant scale-up completed successfully:** + +```bash +$ watch -n 3 kubectl get QdrantOpsRequest -n demo qdops-hscale-up +Every 3.0s: kubectl get QdrantOpsRequest -n demo qdops-hscale-up + +NAME TYPE STATUS AGE +qdops-hscale-up HorizontalScaling Successful 3m57s +``` + +Now let's verify that the number of nodes has increased: + +```bash +$ kubectl get qdrant -n demo qdrant-sample -o=jsonpath='{.spec.replicas}{"\n"}' +5 + +$ kubectl get pods -n demo +NAME READY STATUS RESTARTS AGE +qdrant-sample-0 1/1 Running 0 10m +qdrant-sample-1 1/1 Running 0 10m +qdrant-sample-2 1/1 Running 0 10m +qdrant-sample-3 1/1 Running 0 2m +qdrant-sample-4 1/1 Running 0 1m +``` + +### Scale Down + +Here, we are going to scale down the cluster from 5 nodes to 4 nodes. + +**Create QdrantOpsRequest:** + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-hscale-down + namespace: demo +spec: + type: HorizontalScaling + databaseRef: + name: qdrant-sample + horizontalScaling: + node: 4 +``` + +Let's create the `QdrantOpsRequest` CR we have shown above: + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/scaling/horizontal-scaling/hscale-down.yaml +qdrantopsrequest.ops.kubedb.com/qdops-hscale-down created +``` + +**Verify Qdrant scale-down completed successfully:** + +```bash +$ watch -n 3 kubectl get QdrantOpsRequest -n demo qdops-hscale-down +Every 3.0s: kubectl get QdrantOpsRequest -n demo qdops-hscale-down + +NAME TYPE STATUS AGE +qdops-hscale-down HorizontalScaling Successful 2m15s +``` + +Now let's verify that the number of nodes has decreased: + +```bash +$ kubectl get qdrant -n demo qdrant-sample -o=jsonpath='{.spec.replicas}{"\n"}' +4 + +$ kubectl get pods -n demo +NAME READY STATUS RESTARTS AGE +qdrant-sample-0 1/1 Running 0 14m +qdrant-sample-1 1/1 Running 0 14m +qdrant-sample-2 1/1 Running 0 14m +qdrant-sample-3 1/1 Running 0 6m +``` + +We have successfully performed horizontal scaling on the Qdrant cluster. + +## Next Steps + +- Learn about [backup and restore](/docs/guides/qdrant/backup/overview/index.md) Qdrant using KubeStash. +- Detail concepts of [Qdrant object](/docs/guides/qdrant/concepts/qdrant.md). +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). + +## Cleaning Up + +To clean up the Kubernetes resources created by this tutorial, run: + +```bash +kubectl delete qdrant -n demo qdrant-sample +kubectl delete QdrantOpsRequest -n demo qdops-hscale-up qdops-hscale-down +``` \ No newline at end of file diff --git a/docs/guides/qdrant/scaling/horizontal-scaling/overview.md b/docs/guides/qdrant/scaling/horizontal-scaling/overview.md new file mode 100644 index 000000000..7bf73cd4d --- /dev/null +++ b/docs/guides/qdrant/scaling/horizontal-scaling/overview.md @@ -0,0 +1,56 @@ +--- +title: Qdrant Horizontal Scaling Overview +menu: + docs_{{ .version }}: + identifier: qdrant-horizontal-scaling-overview + name: Overview + parent: qdrant-horizontal-scaling + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Horizontal Scaling Overview + +This guide will give you an overview of how `KubeDB` Ops Manager scales up/down the number of members of a `Qdrant`. + +## Before You Begin + +- You should be familiar with the following `KubeDB` concepts: + - [Qdrant](/docs/guides/qdrant/concepts/qdrant.md) + - [QdrantOpsRequest](/docs/guides/qdrant/concepts/opsrequest.md) + +## How Horizontal Scaling Process Works + +The following diagram shows how `KubeDB` Ops Manager used to scale up the number of members of a `Qdrant` cluster. Open the image in a new tab to see the enlarged version. + +
+  Horizontal scaling Flow +
Fig: Horizontal scaling process of Qdrant
+
+ +The horizontal scaling process consists of the following steps: + +1. At first, a user creates a `Qdrant` CR. + +2. `KubeDB` provisioner operator watches for the `Qdrant` CR. + +3. When it finds one, it creates a `PetSet` and related necessary stuff like secret, service, etc. + +4. Then, in order to scale the cluster up or down, the user creates a `QdrantOpsRequest` CR with the desired number of replicas after scaling. + +5. `KubeDB` Ops Manager watches for `QdrantOpsRequest`. + +6. When it finds one, it halts the `Qdrant` object so that the `KubeDB` provisioner operator doesn't perform any operation on the `Qdrant` during the scaling process. + +7. Then `KubeDB` Ops Manager will add nodes in case of scale up or remove nodes in case of scale down. + +8. Then the `KubeDB` Ops Manager will scale the PetSet replicas to reach the expected number of replicas for the cluster. + +9. After successful scaling of the PetSet's replica, the `KubeDB` Ops Manager updates the `spec.replicas` field of `Qdrant` object to reflect the updated cluster state. + +10. After successful scaling of the `Qdrant` replicas, the `KubeDB` Ops Manager resumes the `Qdrant` object so that the `KubeDB` provisioner operator can resume its usual operations. + +In the next doc, we are going to show a step-by-step guide on scaling of a Qdrant cluster using Horizontal Scaling. diff --git a/docs/guides/qdrant/scaling/vertical-scaling/_index.md b/docs/guides/qdrant/scaling/vertical-scaling/_index.md new file mode 100644 index 000000000..65d0c5aec --- /dev/null +++ b/docs/guides/qdrant/scaling/vertical-scaling/_index.md @@ -0,0 +1,10 @@ +--- +title: Vertical Scaling +menu: + docs_{{ .version }}: + identifier: qdrant-vertical-scaling + name: Vertical Scaling + parent: qdrant-scaling + weight: 20 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/qdrant/scaling/vertical-scaling/overview.md b/docs/guides/qdrant/scaling/vertical-scaling/overview.md new file mode 100644 index 000000000..b7604db81 --- /dev/null +++ b/docs/guides/qdrant/scaling/vertical-scaling/overview.md @@ -0,0 +1,54 @@ +--- +title: Qdrant Vertical Scaling Overview +menu: + docs_{{ .version }}: + identifier: qdrant-vertical-scaling-overview + name: Overview + parent: qdrant-vertical-scaling + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Vertical Scaling Qdrant + +This guide will give you an overview of how KubeDB Ops Manager updates the resources(for example Memory, CPU etc.) of the `Qdrant`. + +## Before You Begin + +- You should be familiar with the following `KubeDB` concepts: + - [Qdrant](/docs/guides/qdrant/concepts/qdrant.md) + - [QdrantOpsRequest](/docs/guides/qdrant/concepts/opsrequest.md) + +## How Vertical Scaling Process Works + +The following diagram shows how the `KubeDB` Ops Manager used to update the resources of the `Qdrant`. Open the image in a new tab to see the enlarged version. + +
+  Vertical scaling process of Qdrant +
Fig: Vertical scaling process of Qdrant
+
+ +The vertical scaling process consists of the following steps: + +1. At first, a user creates a `Qdrant` CR. + +2. `KubeDB` provisioner operator watches for the `Qdrant` CR. + +3. When the operator finds a `Qdrant` CR, it creates a `PetSet` and related necessary stuff like secret, service, etc. + +4. Then, in order to update the resources(for example `CPU`, `Memory` etc.) of the `Qdrant` cluster the user creates a `QdrantOpsRequest` CR with desired information. + +5. `KubeDB` Ops Manager watches for `QdrantOpsRequest`. + +6. When it finds one, it halts the `Qdrant` object so that the `KubeDB` provisioner operator doesn't perform any operation on the `Qdrant` during the scaling process. + +7. Then the KubeDB Ops-manager operator will update resources of the PetSet's Pods to reach desired state. + +8. After successful updating of the resources of the PetSet's Pods, the `KubeDB` Ops Manager updates the `Qdrant` object resources to reflect the updated state. + +9. After successful updating of the `Qdrant` resources, the `KubeDB` Ops Manager resumes the `Qdrant` object so that the `KubeDB` Provisioner operator resumes its usual operations. + +In the next doc, we are going to show a step-by-step guide on updating resources of Qdrant database using vertical scaling operation. diff --git a/docs/guides/qdrant/scaling/vertical-scaling/vertical-scaling.md b/docs/guides/qdrant/scaling/vertical-scaling/vertical-scaling.md new file mode 100644 index 000000000..dd03e7750 --- /dev/null +++ b/docs/guides/qdrant/scaling/vertical-scaling/vertical-scaling.md @@ -0,0 +1,201 @@ +--- +title: Scale Qdrant Vertically +menu: + docs_{{ .version }}: + identifier: qdrant-vertical-scaling-ops + name: Scale Vertically + parent: qdrant-vertical-scaling + weight: 20 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Vertical Scale Qdrant Cluster + +This guide will show you how to use `KubeDB` Ops Manager to update the resources of a `Qdrant` instance. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the `kubectl` command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Install `KubeDB` Provisioner and Ops-manager operator in your cluster following the steps [here](/docs/setup/README.md). + +- You should be familiar with the following `KubeDB` concepts: + - [Qdrant](/docs/guides/qdrant/concepts/qdrant.md) + - [QdrantOpsRequest](/docs/guides/qdrant/concepts/opsrequest.md) + - [Vertical Scaling Overview](/docs/guides/qdrant/scaling/vertical-scaling/overview.md) + +To keep everything isolated, we are going to use a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +> **Note:** YAML files used in this tutorial are stored in [docs/examples/qdrant/scaling/vertical-scaling](/docs/examples/qdrant/scaling/vertical-scaling) directory of [kubedb/docs](https://github.com/kubedb/docs) repository. + +## Apply Vertical Scaling on Qdrant Cluster + +Here, we are going to deploy a `Qdrant` cluster using a supported version by `KubeDB` operator. Then we are going to apply vertical scaling on it. + +**Deploy Qdrant:** + +In this section, we are going to deploy a Qdrant cluster. Then, in the next section, we will update the resources of the database nodes using vertical scaling. Below is the YAML of the `Qdrant` CR that we are going to create: + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + replicas: 3 + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut +``` + +Let's create the `Qdrant` CR we have shown above: + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/scaling/vertical-scaling/qdrant.yaml +qdrant.kubedb.com/qdrant-sample created +``` + +**Wait for the cluster to be ready:** + +```bash +$ watch -n 3 kubectl get qdrant -n demo qdrant-sample +Every 3.0s: kubectl get qdrant -n demo qdrant-sample + +NAME VERSION STATUS AGE +qdrant-sample 1.17.0 Ready 3m16s + +$ watch -n 3 kubectl get petset -n demo qdrant-sample +Every 3.0s: kubectl get petset -n demo qdrant-sample + +NAME READY AGE +qdrant-sample 3/3 3m54s + +$ watch -n 3 kubectl get pod -n demo +Every 3.0s: kubectl get pod -n demo + +NAME READY STATUS RESTARTS AGE +qdrant-sample-0 1/1 Running 0 4m51s +qdrant-sample-1 1/1 Running 0 3m50s +qdrant-sample-2 1/1 Running 0 3m46s +``` + +Let's check the resources of the `qdrant-sample-0` pod: + +```bash +$ kubectl get pod -n demo qdrant-sample-0 -o json | jq '.spec.containers[0].resources' +{ + "limits": { + "memory": "1Gi" + }, + "requests": { + "cpu": "250m", + "memory": "512Mi" + } +} +``` + +We are ready to apply the `QdrantOpsRequest` CR to vertically scale the cluster. + +#### Create QdrantOpsRequest for Vertical Scaling + +In order to update the resources of the database, we have to create a `QdrantOpsRequest` CR with our desired resources. Below is the YAML of the `QdrantOpsRequest` CR that we are going to create: + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-vscale + namespace: demo +spec: + type: VerticalScaling + databaseRef: + name: qdrant-sample + verticalScaling: + node: + resources: + requests: + cpu: "500m" + memory: "1Gi" + limits: + cpu: "1" + memory: "2Gi" + timeout: 5m + apply: IfReady +``` + +Here, + +- `spec.databaseRef.name` specifies that we are performing vertical scaling on `qdrant-sample` Qdrant database. +- `spec.type` specifies that we are performing `VerticalScaling` on our database. +- `spec.verticalScaling.node.resources` specifies the desired CPU and memory resources for the Qdrant nodes. +- `spec.timeout` specifies the timeout for the operation (learn more [here](/docs/guides/qdrant/concepts/opsrequest.md#spectimeout)). +- `spec.apply` specifies when to apply the operation (learn more [here](/docs/guides/qdrant/concepts/opsrequest.md#specapply)). + +Let's create the `QdrantOpsRequest` CR we have shown above: + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/scaling/vertical-scaling/vscale.yaml +qdrantopsrequest.ops.kubedb.com/qdops-vscale created +``` + +#### Verify Qdrant vertical scaling completed successfully + +If everything goes well, `KubeDB` Ops-manager operator will update the resources of the `Qdrant` object and related `PetSet`. + +Let's wait for `QdrantOpsRequest` to be `Successful`: + +```bash +$ watch -n 3 kubectl get QdrantOpsRequest -n demo qdops-vscale +Every 3.0s: kubectl get QdrantOpsRequest -n demo qdops-vscale + +NAME TYPE STATUS AGE +qdops-vscale VerticalScaling Successful 3m12s +``` + +Now, let's verify that the resources of the pods have been updated: + +```bash +$ kubectl get pod -n demo qdrant-sample-0 -o json | jq '.spec.containers[0].resources' +{ + "limits": { + "cpu": "1", + "memory": "2Gi" + }, + "requests": { + "cpu": "500m", + "memory": "1Gi" + } +} +``` + +You can see from the above output that the resources of the `qdrant-sample-0` pod have been updated successfully. All pods in the cluster will have the same updated resource configuration. + +## Next Steps + +- Learn about [backup and restore](/docs/guides/qdrant/backup/overview/index.md) Qdrant using KubeStash. +- Detail concepts of [Qdrant object](/docs/guides/qdrant/concepts/qdrant.md). +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). + +## Cleaning Up + +To clean up the Kubernetes resources created by this tutorial, run: + +```bash +kubectl delete qdrant -n demo qdrant-sample +kubectl delete QdrantOpsRequest -n demo qdops-vscale +``` \ No newline at end of file diff --git a/docs/guides/qdrant/tls/_index.md b/docs/guides/qdrant/tls/_index.md new file mode 100644 index 000000000..608687efa --- /dev/null +++ b/docs/guides/qdrant/tls/_index.md @@ -0,0 +1,10 @@ +--- +title: Qdrant TLS +menu: + docs_{{ .version }}: + identifier: qdrant-tls + name: TLS + parent: qdrant-guides + weight: 50 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/qdrant/tls/configure-tls.md b/docs/guides/qdrant/tls/configure-tls.md new file mode 100644 index 000000000..a573cbc86 --- /dev/null +++ b/docs/guides/qdrant/tls/configure-tls.md @@ -0,0 +1,188 @@ +--- +title: Configure TLS in Qdrant +menu: + docs_{{ .version }}: + identifier: qdrant-tls-description + name: Configure TLS + parent: qdrant-tls + weight: 20 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Configure TLS in Qdrant + +`KubeDB` provides support for TLS encryption for `Qdrant`. This tutorial will show you how to use `KubeDB` to deploy a `Qdrant` database with TLS configuration. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the `kubectl` command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Install [`cert-manager`](https://cert-manager.io/docs/installation/) v1.4.0 or later to your cluster to manage your SSL/TLS certificates. + +- Install `KubeDB` in your cluster following the steps [here](/docs/setup/README.md). + +- You should be familiar with the following `KubeDB` concepts: + - [Qdrant](/docs/guides/qdrant/concepts/qdrant.md) + - [TLS Overview](/docs/guides/qdrant/tls/overview.md) + +To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +> **Note:** YAML files used in this tutorial are stored in [docs/examples/qdrant/tls](/docs/examples/qdrant/tls) directory of [kubedb/docs](https://github.com/kubedb/docs) repository. + +## Overview + +KubeDB uses the following CRD fields to enable TLS/SSL encryption in Qdrant. + +- `spec:` + - `tls:` + - `issuerRef` + - `certificates` + - `client` — enables TLS for client-to-server communication + - `p2p` — enables TLS for peer-to-peer communication between Qdrant nodes + +- `client` (optional, default `false`): When set to `true`, the Qdrant server will accept TLS-encrypted connections from clients. This is essential for securing client access to the database. + +- `p2p` (optional, default `false`): When set to `true`, all inter-node communication within the Qdrant cluster (gossip, replication, etc.) will be encrypted using TLS. This ensures that data in transit between Qdrant nodes is secure. + +### Create Issuer/ClusterIssuer + +Now, we are going to create an example `Issuer` that will be used throughout the duration of this tutorial. Alternatively, you can follow this [cert-manager tutorial](https://cert-manager.io/docs/configuration/ca/) to create your own `Issuer`. By following the below steps, we are going to create our desired issuer, + +- Start off by generating our ca-certificates using openssl: + +```bash +openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./ca.key -out ./ca.crt -subj "/CN=qdrant/O=kubedb" +``` + +- Create a secret using the certificate files we have just generated: + +```bash +$ kubectl create secret tls qdrant-ca --cert=ca.crt --key=ca.key --namespace=demo +secret/qdrant-ca created +``` + +Now, we are going to create an `Issuer` using the `qdrant-ca` secret that contains the CA certificate we have just created. Below is the YAML of the `Issuer` CR that we are going to create: + +```yaml +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: qdrant-ca-issuer + namespace: demo +spec: + ca: + secretName: qdrant-ca +``` + +Let's create the `Issuer` CR we have shown above: + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/tls/issuer.yaml +issuer.cert-manager.io/qdrant-ca-issuer created +``` + +### Deploy Qdrant cluster with TLS configuration + +Here, our issuer `qdrant-ca-issuer` is ready to deploy a `Qdrant` cluster with TLS configuration. Below is the YAML for the Qdrant cluster that we are going to create: + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-tls + namespace: demo +spec: + version: "1.17.0" + mode: Distributed + replicas: 3 + tls: + issuerRef: + apiGroup: cert-manager.io + name: qdrant-ca-issuer + kind: Issuer + client: true + p2p: true + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut +``` + +Here, + +- `spec.tls.issuerRef` refers to the `qdrant-ca-issuer` issuer. It has the following sub-fields: + - `apiGroup` — the API group of the issuer (e.g., `cert-manager.io`). + - `kind` — the kind of issuer (`Issuer` or `ClusterIssuer`). + - `name` — the name of the issuer. +- `spec.tls.client` (optional, default `false`): Enables TLS for client-to-server communication. When set to `true`, clients must connect using TLS. +- `spec.tls.p2p` (optional, default `false`): Enables TLS for peer-to-peer communication between Qdrant nodes in the cluster. +- `spec.tls.certificates` provides options to configure custom certificate settings. You can find more details from [here](/docs/guides/qdrant/concepts/qdrant.md#spectls). + +**Deploy Qdrant Cluster:** + +Let's create the `Qdrant` CR we have shown above: + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/tls/tls-qdrant.yaml +qdrant.kubedb.com/qdrant-tls created +``` + +**Wait for the database to be ready:** + +Now, watch `Qdrant` going to `Running` state and also watch `PetSet` and its pods going to `Running` state: + +```bash +$ watch kubectl get qdrant -n demo qdrant-tls +NAME VERSION STATUS AGE +qdrant-tls 1.17.0 Ready 62s + +$ watch -n 3 kubectl get petset -n demo qdrant-tls +NAME READY AGE +qdrant-tls 3/3 2m30s + +$ watch -n 3 kubectl get pod -n demo -l app.kubernetes.io/instance=qdrant-tls +NAME READY STATUS RESTARTS AGE +qdrant-tls-0 1/1 Running 0 3m5s +qdrant-tls-1 1/1 Running 0 2m40s +qdrant-tls-2 1/1 Running 0 2m20s +``` + +**Verify TLS configuration:** + +Now, let's verify the TLS configuration by checking the secrets created for the Qdrant database: + +```bash +$ kubectl get secrets -n demo | grep qdrant-tls +qdrant-tls-server-cert kubernetes.io/tls 3 3m +qdrant-tls-client-cert kubernetes.io/tls 3 3m +``` + +The TLS certificates have been created and the Qdrant cluster is now configured to use TLS for both client connections and peer-to-peer communication. + +## Next Steps + +- Learn about [backup and restore](/docs/guides/qdrant/backup/overview/index.md) Qdrant using KubeStash. +- Detail concepts of [Qdrant object](/docs/guides/qdrant/concepts/qdrant.md). +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). + +## Cleaning up + +To clean up the Kubernetes resources created by this tutorial, run: + +```bash +kubectl delete qdrant -n demo qdrant-tls +kubectl delete issuer -n demo qdrant-ca-issuer +kubectl delete ns demo +``` \ No newline at end of file diff --git a/docs/guides/qdrant/tls/overview.md b/docs/guides/qdrant/tls/overview.md new file mode 100644 index 000000000..347532a46 --- /dev/null +++ b/docs/guides/qdrant/tls/overview.md @@ -0,0 +1,84 @@ +--- +title: Qdrant TLS Overview +menu: + docs_{{ .version }}: + identifier: qdrant-tls-overview + name: Overview + parent: qdrant-tls + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Qdrant TLS Encryption + +**Prerequisite:** To configure TLS/SSL in `Qdrant`, `KubeDB` uses `cert-manager` to issue certificates. So first you have to make sure that the cluster has `cert-manager` installed. Install `cert-manager` in your cluster following steps [here](https://cert-manager.io/docs/installation/). + +To issue a certificate, the following CRDs of `cert-manager` are used: + +- `Issuer/ClusterIssuer`: Issuers and ClusterIssuers represent certificate authorities (CAs) that are able to generate signed certificates by honoring certificate signing requests. All cert-manager certificates require a referenced issuer that is in a ready condition to attempt to honor the request. You can learn more details [here](https://cert-manager.io/docs/concepts/issuer/). + +- `Certificate`: cert-manager has the concept of Certificates that define a desired x509 certificate which will be renewed and kept up to date. You can learn more details [here](https://cert-manager.io/docs/concepts/certificate/). + +**Qdrant CRD Specification:** + +KubeDB uses the following CRD fields to enable TLS/SSL encryption in `Qdrant`. + +- `spec:` + - `tls:` + - `issuerRef` + - `certificates` + - `client` + - `p2p` + +Read about the fields in detail from the [Qdrant Concepts](/docs/guides/qdrant/concepts/qdrant.md#spectls) page. + +`KubeDB` uses the `Issuer` or `ClusterIssuer` referenced in the `tls.issuerRef` field, and the certificate specs provided in `tls.certificates` to generate certificate secrets. These certificate secrets including `ca.crt`, `server.crt`, `tls.key`, etc. are used to configure the `Qdrant` server. + +Here, + +- `issuerRef` is a reference to the `Issuer` or `ClusterIssuer` CR of [cert-manager](https://cert-manager.io/docs/concepts/issuer/) that will be used by `KubeDB` to generate necessary certificates. + - `apiGroup` is the group name of the resource that is being referenced. Currently, the only supported value is `cert-manager.io`. + - `kind` is the type of resource that is being referenced. `KubeDB` supports both `Issuer` and `ClusterIssuer` as values for this field. + - `name` is the name of the resource (`Issuer` or `ClusterIssuer`) being referenced. + +- `certificates` (optional) is a list of additional certificates used to configure the Qdrant server. You can specify custom `dnsNames`, `ipAddresses`, and `subject` for server certificates. + +- `client` (optional, default `false`) enables TLS for client-to-server communication. When set to `true`, the Qdrant server will accept TLS-encrypted connections from clients. + +- `p2p` (optional, default `false`) enables TLS for peer-to-peer communication between Qdrant nodes. When set to `true`, inter-node communication within the Qdrant cluster will be encrypted using TLS. + +## How TLS/SSL Configures in Qdrant + +The following figure shows how `KubeDB` configures TLS/SSL in Qdrant. Open the image in a new tab to see the enlarged version. + +
+Deploy Qdrant with TLS/SSL +
Fig: Deploy Qdrant with TLS/SSL
+
+ +Deploying Qdrant with TLS/SSL configuration process consists of the following steps: + +1. At first, a user creates a `Issuer/ClusterIssuer` CR. + +2. Then the user creates a `Qdrant` CR which refers to the `Issuer/ClusterIssuer` CR that the user created in the previous step. + +3. `KubeDB-Provisioner` operator watches for the `Qdrant` CR. + +4. When it finds one, it creates `Secret`, `Service`, etc. for the `Qdrant`. + +5. `KubeDB` Ops-manager operator watches for `Qdrant`(5c), `Issuer/ClusterIssuer`(5b), `Secret` and `Service`(5a). + +6. When it finds all the resources (`Qdrant`, `Issuer/ClusterIssuer`, `Secret`, `Service`), it creates `Certificates` by using `tls.issuerRef` and `tls.certificates` field specification from `Qdrant` CR. + +7. `cert-manager` watches for certificates. + +8. When it finds one, it creates certificate secrets `tls-secrets` (server, client secrets, etc.) that hold the actual certificates signed by the CA. + +9. `KubeDB-Provisioner` operator watches for the certificate secrets `tls-secrets`. + +10. When it finds all the tls-secrets, it creates the related `PetSet` so that the Qdrant database can be configured with TLS/SSL. + +In the next doc, we are going to show a step-by-step guide on how to configure a `Qdrant` database with TLS/SSL. diff --git a/docs/guides/qdrant/update-version/_index.md b/docs/guides/qdrant/update-version/_index.md new file mode 100644 index 000000000..23ed313fe --- /dev/null +++ b/docs/guides/qdrant/update-version/_index.md @@ -0,0 +1,10 @@ +--- +title: Update Version +menu: + docs_{{ .version }}: + identifier: qdrant-update-version + name: Update Version + parent: qdrant-guides + weight: 110 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/qdrant/update-version/overview.md b/docs/guides/qdrant/update-version/overview.md new file mode 100644 index 000000000..40d716a6c --- /dev/null +++ b/docs/guides/qdrant/update-version/overview.md @@ -0,0 +1,54 @@ +--- +title: Updating Qdrant Version Overview +menu: + docs_{{ .version }}: + identifier: qdrant-update-version-overview + name: Overview + parent: qdrant-update-version + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Updating Qdrant Version Overview + +This guide will give you an overview on how KubeDB Ops-manager operator update the version of `Qdrant` database. + +## Before You Begin + +- You should be familiar with the following `KubeDB` concepts: + - [Qdrant](/docs/guides/qdrant/concepts/qdrant.md) + - [QdrantOpsRequest](/docs/guides/qdrant/concepts/opsrequest.md) + +## How update version Process Works + +The following diagram shows how KubeDB Ops-manager operator update the version of `Qdrant`. Open the image in a new tab to see the enlarged version. + +
+  updating Process of Qdrant +
Fig: Updating Process of Qdrant
+
+ +The updating process consists of the following steps: + +1. At first, a user creates a `Qdrant` Custom Resource (CR). + +2. `KubeDB` Provisioner operator watches the `Qdrant` CR. + +3. When the operator finds a `Qdrant` CR, it creates `PetSets` and related necessary resources like secrets, services, etc. + +4. Then, in order to update the version of the `Qdrant` the user creates a `QdrantOpsRequest` CR with the desired version. + +5. `KubeDB` Ops-manager operator watches the `QdrantOpsRequest` CR. + +6. When it finds a `QdrantOpsRequest` CR, it halts the `Qdrant` object which is referred from the `QdrantOpsRequest`. So, the `KubeDB` Provisioner operator doesn't perform any operations on the `Qdrant` object during the updating process. + +7. By looking at the target version from `QdrantOpsRequest` CR, `KubeDB` Ops-manager operator updates the images of the `PetSet`. + +8. After successfully updating the `PetSet` and their `Pods` images, the `KubeDB` Ops-manager operator updates the image of the `Qdrant` object to reflect the updated state of the database. + +9. After successfully updating of `Qdrant` object, the `KubeDB` Ops-manager operator resumes the `Qdrant` object so that the `KubeDB` Provisioner operator can resume its usual operations. + +In the next doc, we are going to show a step-by-step guide on updating of a Qdrant using UpdateVersion operation. diff --git a/docs/guides/qdrant/update-version/update-version.md b/docs/guides/qdrant/update-version/update-version.md new file mode 100644 index 000000000..48e54fe4d --- /dev/null +++ b/docs/guides/qdrant/update-version/update-version.md @@ -0,0 +1,351 @@ +--- +title: Update Qdrant Version +menu: + docs_{{ .version }}: + identifier: qdrant-update-version-ops + name: Update Version + parent: qdrant-update-version + weight: 20 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Update Qdrant Version + +This guide will show you how to use `KubeDB` ops-manager operator to update the version of `Qdrant` cr. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the `kubectl` command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Install `KubeDB` in your cluster following the steps [here](/docs/setup/README.md). + +- You should be familiar with the following `KubeDB` concepts: + - [Qdrant](/docs/guides/qdrant/concepts/qdrant.md) + - [QdrantOpsRequest](/docs/guides/qdrant/concepts/opsrequest.md) + - [Updating Overview](/docs/guides/qdrant/update-version/overview/index.md) + +To keep everything isolated, we are going to use a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +> **Note:** YAML files used in this tutorial are stored in [docs/examples/qdrant/update-version](/docs/examples/qdrant/update-version) directory of [kubedb/docs](https://github.com/kubedb/docs) repository. + +## Apply Version Updating on Qdrant + +Here, we are going to deploy a `Qdrant` instance using a supported version by `KubeDB` provisioner. Then we are going to apply update-ops-request on it. + +### Prepare Qdrant + +At first, we are going to deploy a Qdrant instance using a supported `Qdrant` version. In the next two sections, we are going to find out the supported versions and version update constraints. + +**Find supported QdrantVersion:** + +When you have installed `KubeDB`, it has created `QdrantVersion` CR for all supported `Qdrant` versions. Let's check the supported versions: + +```bash +$ kubectl get qdrantversion +NAME VERSION DB_IMAGE DEPRECATED AGE +1.15.4 1.15.4 docker.io/qdrant/qdrant:v1.15.4-unprivileged 24d +1.16.2 1.16.2 docker.io/qdrant/qdrant:v1.16.2-unprivileged 24d +1.17.0 1.17.0 docker.io/qdrant/qdrant:v1.17.0-unprivileged 24d +``` + +The version above that does not show `DEPRECATED` `true` is supported by `KubeDB` for `Qdrant`. You can use any non-deprecated version. Now, we are going to select a non-deprecated version from `QdrantVersion` for the `Qdrant` instance that we will update from this version to another. In the next section, we are going to verify version update constraints. + +**Check update Constraints:** + +Qdrant supports rolling version updates. You can update from any currently running version to a newer patch or minor version. Major version jumps should follow the Qdrant upstream upgrade notes. For example, you can update directly from `1.16.2` to `1.17.0`. + +Let's get one of the `qdrantversion` YAMLs: + +```bash +$ kubectl get qdrantversion 1.17.0 -o yaml +apiVersion: catalog.kubedb.com/v1alpha1 +kind: QdrantVersion +metadata: + labels: + app.kubernetes.io/instance: kubedb + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: kubedb-catalog + name: "1.17.0" +spec: + db: + image: docker.io/qdrant/qdrant:v1.17.0-unprivileged + version: "1.17.0" +``` + +**Deploy Qdrant Instance:** + +In this section, we are going to deploy a Qdrant instance. Then, in the next section, we will update the version of the database using `UpdateVersion`. Below is the YAML of the `Qdrant` cr that we are going to create: + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.16.2" + replicas: 3 + storage: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut +``` + +Let's create the `Qdrant` cr we have shown above: + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/update-version/qdrant.yaml +qdrant.kubedb.com/qdrant-sample created +``` + +**Wait for the database to be ready:** + +`KubeDB` operator watches for `Qdrant` objects using Kubernetes API. When a `Qdrant` object is created, `KubeDB` operator will create a new PetSet, Services, and Secrets, etc. + +Now, watch `Qdrant` is going to `Running` state and also watch `PetSet` and its pod is created and going to `Running` state: + +```bash +$ watch -n 3 kubectl get qdrant -n demo +Every 3.0s: kubectl get qdrant -n demo + +NAME VERSION STATUS AGE +qdrant-sample 1.16.2 Ready 3m42s + +$ watch -n 3 kubectl get petset -n demo qdrant-sample +Every 3.0s: kubectl get petset -n demo qdrant-sample + +NAME READY AGE +qdrant-sample 3/3 4m17s + +$ watch -n 3 kubectl get pod -n demo +Every 3.0s: kubectl get pods -n demo + +NAME READY STATUS RESTARTS AGE +qdrant-sample-0 1/1 Running 0 4m55s +qdrant-sample-1 1/1 Running 0 4m12s +qdrant-sample-2 1/1 Running 0 3m38s +``` + +Let's verify the `Qdrant`, the `PetSet` and its `Pod` image version: + +```bash +$ kubectl get qdrant -n demo qdrant-sample -o=jsonpath='{.spec.version}{"\n"}' +1.16.2 + +$ kubectl get petset -n demo qdrant-sample -o=jsonpath='{.spec.template.spec.containers[0].image}{"\n"}' +docker.io/qdrant/qdrant:v1.16.2-unprivileged + +$ kubectl get pod -n demo qdrant-sample-0 -o=jsonpath='{.spec.containers[0].image}{"\n"}' +docker.io/qdrant/qdrant:v1.16.2-unprivileged + +We are ready to apply version updating on this `Qdrant` instance. + +### UpdateVersion + +Here, we are going to update `Qdrant` from version `1.16.2` to `1.17.0`. + +**Create QdrantOpsRequest:** + +To update the instance, you have to create a `QdrantOpsRequest` cr with your desired version that is supported by `KubeDB`. Below is the YAML of the `QdrantOpsRequest` cr that we are going to create: + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-update-version + namespace: demo +spec: + type: UpdateVersion + updateVersion: + targetVersion: "1.17.0" + databaseRef: + name: qdrant-sample + timeout: 5m + apply: IfReady +``` + +Here, + +- `spec.databaseRef.name` specifies that we are performing operation on `qdrant-sample` Qdrant database. +- `spec.type` specifies that we are going to perform `UpdateVersion` on our database. +- `spec.updateVersion.targetVersion` specifies the expected version `1.17.0` after updating. +- `spec.timeout` specifies the timeout for the operation (learn more [here](/docs/guides/qdrant/concepts/opsrequest.md#spectimeout)). +- `spec.apply` specifies when to apply the operation (learn more [here](/docs/guides/qdrant/concepts/opsrequest.md#specapply)). + +Let's create the `QdrantOpsRequest` cr we have shown above: + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/update-version/ops-request.yaml +qdrantopsrequest.ops.kubedb.com/qdops-update-version created +``` + +#### Verify Qdrant version updated successfully + +If everything goes well, `KubeDB` ops-manager operator will update the image of `Qdrant`, `PetSet`, and its `Pod`. + +At first, we will wait for `QdrantOpsRequest` to be successful. Run the following command to watch `QdrantOpsRequest` cr: + +```bash +$ watch -n 3 kubectl get QdrantOpsRequest -n demo qdops-update-version +Every 3.0s: kubectl get QdrantOpsRequest -n demo qdops-update-version + +NAME TYPE STATUS AGE +qdops-update-version UpdateVersion Successful 3m12s +``` + +We can see from the above output that the `QdrantOpsRequest` has succeeded. If we describe the `QdrantOpsRequest`, we shall see that the `Qdrant`, `PetSet`, and its `Pod` have updated with a new image. + +```bash +$ kubectl describe QdrantOpsRequest -n demo qdops-update-version +Name: qdops-update-version +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: QdrantOpsRequest +Metadata: + Creation Timestamp: 2026-05-15T05:36:46Z + Generation: 1 + Resource Version: 3356440 + UID: 156625b9-5f36-465e-aa88-ff0e5452c7ba +Spec: + Apply: IfReady + Database Ref: + Name: qdrant-sample + Max Retries: 1 + Timeout: 5m + Type: UpdateVersion + Update Version: + Target Version: 1.17.0 +Status: + Conditions: + Last Transition Time: 2026-05-15T05:36:46Z + Message: Qdrant ops-request has started to update version + Observed Generation: 1 + Reason: UpdateVersion + Status: True + Type: UpdateVersion + Last Transition Time: 2026-05-15T05:37:01Z + Message: successfully reconciled the Qdrant with updated version + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2026-05-15T05:38:10Z + Message: Successfully Restarted Qdrant nodes + Observed Generation: 1 + Reason: RestartPods + Status: True + Type: RestartPods + Last Transition Time: 2026-05-15T05:37:15Z + Message: get pod; ConditionStatus:True; PodName:qdrant-sample-0 + Observed Generation: 1 + Status: True + Type: GetPod--qdrant-sample-0 + Last Transition Time: 2026-05-15T05:37:17Z + Message: evict pod; ConditionStatus:True; PodName:qdrant-sample-0 + Observed Generation: 1 + Status: True + Type: EvictPod--qdrant-sample-0 + Last Transition Time: 2026-05-15T05:37:45Z + Message: running pod; ConditionStatus:True; PodName:qdrant-sample-0 + Observed Generation: 1 + Status: True + Type: RunningPod--qdrant-sample-0 + Last Transition Time: 2026-05-15T05:37:30Z + Message: get pod; ConditionStatus:True; PodName:qdrant-sample-1 + Observed Generation: 1 + Status: True + Type: GetPod--qdrant-sample-1 + Last Transition Time: 2026-05-15T05:37:31Z + Message: evict pod; ConditionStatus:True; PodName:qdrant-sample-1 + Observed Generation: 1 + Status: True + Type: EvictPod--qdrant-sample-1 + Last Transition Time: 2026-05-15T05:37:45Z + Message: running pod; ConditionStatus:True; PodName:qdrant-sample-1 + Observed Generation: 1 + Status: True + Type: RunningPod--qdrant-sample-1 + Last Transition Time: 2026-05-15T05:37:50Z + Message: get pod; ConditionStatus:True; PodName:qdrant-sample-2 + Observed Generation: 1 + Status: True + Type: GetPod--qdrant-sample-2 + Last Transition Time: 2026-05-15T05:37:52Z + Message: evict pod; ConditionStatus:True; PodName:qdrant-sample-2 + Observed Generation: 1 + Status: True + Type: EvictPod--qdrant-sample-2 + Last Transition Time: 2026-05-15T05:38:05Z + Message: running pod; ConditionStatus:True; PodName:qdrant-sample-2 + Observed Generation: 1 + Status: True + Type: RunningPod--qdrant-sample-2 + Last Transition Time: 2026-05-15T05:38:11Z + Message: Successfully updated Qdrant version + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 86s KubeDB Ops-manager Operator Pausing Qdrant database demo/qdrant-sample + Normal Successful 86s KubeDB Ops-manager Operator Successfully paused Qdrant database: demo/qdrant-sample for QdrantOpsRequest: qdops-update-version + Normal UpdatePetSets 74s KubeDB Ops-manager Operator successfully reconciled the Qdrant with updated version + Warning get pod; ConditionStatus:True; PodName:qdrant-sample-0 60s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:qdrant-sample-0 + Warning evict pod; ConditionStatus:True; PodName:qdrant-sample-0 58s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:qdrant-sample-0 + Normal RestartPods 5s KubeDB Ops-manager Operator Successfully Restarted Qdrant nodes + Normal Starting 4s KubeDB Ops-manager Operator Resuming Qdrant database: demo/qdrant-sample + Normal Successful 4s KubeDB Ops-manager Operator Successfully resumed Qdrant database: demo/qdrant-sample for QdrantOpsRequest: qdops-update-version +``` + +Now, we are going to verify whether the `Qdrant`, `PetSet` and its `Pod` have updated with the new image. Let's check: + +```bash +$ kubectl get qdrant -n demo qdrant-sample -o=jsonpath='{.spec.version}{"\n"}' +1.17.0 + +$ kubectl get petset -n demo qdrant-sample -o=jsonpath='{.spec.template.spec.containers[0].image}{"\n"}' +docker.io/qdrant/qdrant:v1.17.0-unprivileged + +$ kubectl get pod -n demo qdrant-sample-0 -o=jsonpath='{.spec.containers[0].image}{"\n"}' +docker.io/qdrant/qdrant:v1.17.0-unprivileged +``` + +You can see above that our `Qdrant` has been updated with the new version. It verifies that we have successfully updated our Qdrant instance. + +## Next Steps + +- Learn about [backup and restore](/docs/guides/qdrant/backup/overview/index.md) Qdrant using KubeStash. +- Detail concepts of [Qdrant object](/docs/guides/qdrant/concepts/qdrant.md). +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). + +## Cleaning Up + +To clean up the Kubernetes resources created by this tutorial, run: + +```bash +$ kubectl delete qdrant -n demo qdrant-sample +qdrant.kubedb.com "qdrant-sample" deleted + +$ kubectl delete qdrantopsrequest -n demo qdops-update-version +qdrantopsrequest.ops.kubedb.com "qdops-update-version" deleted + +$ kubectl delete ns demo +namespace "demo" deleted +``` \ No newline at end of file diff --git a/docs/guides/qdrant/volume-expansion/_index.md b/docs/guides/qdrant/volume-expansion/_index.md new file mode 100644 index 000000000..578d4ec84 --- /dev/null +++ b/docs/guides/qdrant/volume-expansion/_index.md @@ -0,0 +1,10 @@ +--- +title: Volume Expansion +menu: + docs_{{ .version }}: + identifier: qdrant-volume-expansion + name: Volume Expansion + parent: qdrant-guides + weight: 120 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/qdrant/volume-expansion/overview.md b/docs/guides/qdrant/volume-expansion/overview.md new file mode 100644 index 000000000..957b4e8f0 --- /dev/null +++ b/docs/guides/qdrant/volume-expansion/overview.md @@ -0,0 +1,56 @@ +--- +title: Expanding Qdrant Storage +menu: + docs_{{ .version }}: + identifier: qdrant-volume-expansion-overview + name: Overview + parent: qdrant-volume-expansion + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Qdrant Volume Expansion + +This guide will give an overview of how KubeDB Ops-manager expands the volume of a `Qdrant` database. + +## Before You Begin + +- You should be familiar with the following `KubeDB` concepts: + - [Qdrant](/docs/guides/qdrant/concepts/qdrant.md) + - [QdrantOpsRequest](/docs/guides/qdrant/concepts/opsrequest.md) + +## How Volume Expansion Process Works + +The following diagram shows how KubeDB Ops Manager expand the volumes of `Qdrant` database components. Open the image in a new tab to see the enlarged version. + +
+  Volume Expansion process of Qdrant +
Fig: Volume Expansion process of Qdrant
+
+ +The Volume Expansion process consists of the following steps: + +1. At first, a user creates a `Qdrant` Custom Resource (CR). + +2. `KubeDB-Provisioner` operator watches the `Qdrant` CR. + +3. When the operator finds a `Qdrant` CR, it creates a `Petset` and related necessary stuff like pods, PVCs, secrets, services, etc. + +4. Each Petset creates a Persistent Volume according to the volume claim template. This Persistent Volume will be expanded by the `KubeDB` Ops-manager operator. + +5. Then, in order to expand the volume of the `Qdrant` database, the user creates a `QdrantOpsRequest` CR with the desired new storage size. + +6. `KubeDB` Ops-manager operator watches the `QdrantOpsRequest` CR. + +7. When it finds a `QdrantOpsRequest` CR, it pauses the `Qdrant` object so that the `KubeDB-Provisioner` operator doesn't perform any operations on the `Qdrant` during the volume expansion process. + +8. Then the `KubeDB` Ops-manager operator expands the persistent volumes to the expected size defined in the `QdrantOpsRequest` CR. + +9. After the successful expansion of the volumes, the `KubeDB` Ops-manager updates the new volume size in the `Qdrant` object to reflect the updated state. + +10. After the successful Volume Expansion, the `KubeDB` Ops-manager resumes the `Qdrant` object so that the `KubeDB-Provisioner` resumes its usual operations. + +In the next doc, we are going to show a step-by-step guide on Volume Expansion of a Qdrant database using `QdrantOpsRequest` CRD. diff --git a/docs/guides/qdrant/volume-expansion/volume-expansion.md b/docs/guides/qdrant/volume-expansion/volume-expansion.md new file mode 100644 index 000000000..8c81de9f6 --- /dev/null +++ b/docs/guides/qdrant/volume-expansion/volume-expansion.md @@ -0,0 +1,322 @@ +--- +title: Expand Qdrant Volume +menu: + docs_{{ .version }}: + identifier: qdrant-volume-expansion-cluster + name: Cluster + parent: qdrant-volume-expansion + weight: 20 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Expand Qdrant Volume + +This guide will show you how to use `KubeDB` Ops-manager operator to expand the volume of a Qdrant database. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the `kubectl` command-line tool must be configured to communicate with your cluster. + +- You must have a `StorageClass` that supports volume expansion. + +- Install `KubeDB` Provisioner and Ops-manager operator in your cluster following the steps [here](/docs/setup/README.md). + +- You should be familiar with the following `KubeDB` concepts: + - [Qdrant](/docs/guides/qdrant/concepts/qdrant.md) + - [QdrantOpsRequest](/docs/guides/qdrant/concepts/opsrequest.md) + - [Volume Expansion Overview](/docs/guides/qdrant/volume-expansion/overview.md) + +To keep everything isolated, we are going to use a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +> **Note:** YAML files used in this tutorial are stored in [docs/examples/qdrant/volume-expansion](/docs/examples/qdrant/volume-expansion) directory of [kubedb/docs](https://github.com/kubedb/docs) repository. + +## Expand Volume of Qdrant Database + +Here, we are going to deploy a `Qdrant` cluster using a supported version by `KubeDB` operator. Then we are going to apply `QdrantOpsRequest` to expand its volume. + +### Prepare Qdrant Database + +At first verify that your cluster has a storage class that supports volume expansion. Let's check, + +```bash +$ kubectl get storageclass +NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE +local-path (default) rancher.io/local-path Delete WaitForFirstConsumer false 2d +longhorn (default) driver.longhorn.io Delete Immediate true 3m25s +longhorn-static driver.longhorn.io Delete Immediate true 3m19s +``` + +We can see from the output that `longhorn (default)` storage class has `ALLOWVOLUMEEXPANSION` field as true. So, this storage class supports volume expansion. We will use this storage class. + +Now, we are going to deploy a `Qdrant` cluster with version `1.17.0`. + +#### Deploy Qdrant + +In this section, we are going to deploy a Qdrant cluster with 1Gi volume. Then, in the next section we will expand its volume to 3Gi using `QdrantOpsRequest` CRD. Below is the YAML of the `Qdrant` CR that we are going to create, + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: Qdrant +metadata: + name: qdrant-sample + namespace: demo +spec: + version: "1.17.0" + replicas: 3 + storage: + storageClassName: "longhorn" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut +``` + +Let's create the `Qdrant` CR we have shown above, + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/volume-expansion/qdrant.yaml +qdrant.kubedb.com/qdrant-sample created +``` + +Now, wait until `qdrant-sample` has status `Ready`: + +```bash +$ kubectl get qdrant -n demo +NAME VERSION STATUS AGE +qdrant-sample 1.17.0 Ready 3m47s +``` + +Let's check volume size from the PetSet and from the persistent volumes: + +```bash +$ kubectl get petset -n demo qdrant-sample -o json | jq '.spec.volumeClaimTemplates[].spec.resources.requests.storage' +"1Gi" + +$ kubectl get pv -n demo +NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS AGE +pvc-0e300ccf-49f1-4e11-b630-bc3756baeaa0 1Gi RWO Delete Bound demo/data-qdrant-sample-0 longhorn 4m +pvc-20ab1d50-23d7-409a-ba2e-759250f9f758 1Gi RWO Delete Bound demo/data-qdrant-sample-2 longhorn 4m +pvc-ccee01bf-9551-4efc-8945-5a3d25c60c7b 1Gi RWO Delete Bound demo/data-qdrant-sample-1 longhorn 4m +``` + +You can see the PetSet has 1Gi storage, and the capacity of all the persistent volumes are also 1Gi. + +We are now ready to apply the `QdrantOpsRequest` CR to expand the volume of this database. + +### Volume Expansion + +Here, we are going to expand the volume of the Qdrant cluster. + +#### Create QdrantOpsRequest + +In order to expand the volume of the database, we have to create a `QdrantOpsRequest` CR with our desired volume size. Below is the YAML of the `QdrantOpsRequest` CR that we are going to create, + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: QdrantOpsRequest +metadata: + name: qdops-vol-exp + namespace: demo +spec: + apply: IfReady + databaseRef: + name: qdrant-sample + type: VolumeExpansion + volumeExpansion: + mode: "Offline" + node: 3Gi +``` + +Here, + +- `spec.databaseRef.name` specifies that we are performing volume expansion operation on `qdrant-sample` Qdrant database. +- `spec.type` specifies that we are performing `VolumeExpansion` on our database. +- `spec.volumeExpansion.node` specifies the desired volume size. +- `spec.volumeExpansion.mode` specifies the desired volume expansion mode (`Online` or `Offline`). Storageclass `longhorn` supports `Offline` volume expansion. + +> **Note:** If the Storageclass you are using support `Online` Volume Expansion, Try Online volume expansion by using `spec.volumeExpansion.mode:"Online"`. + +During `Online` VolumeExpansion KubeDB expands volume without deleting the pods, it directly updates the underlying PVC. And for Offline volume expansion, the database is paused. The Pods are deleted and PVC is updated. Then the database Pods are recreated with updated PVC. + +Let's create the `QdrantOpsRequest` CR we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/qdrant/volume-expansion/ops-request.yaml +qdrantopsrequest.ops.kubedb.com/qdops-vol-exp created +``` + +#### Verify Qdrant volume expanded successfully + +If everything goes well, `KubeDB` Ops-manager operator will update the volume size of the `Qdrant` object and related `PetSet` and `Persistent Volumes`. + +Let's wait for `QdrantOpsRequest` to be `Successful`. Run the following command to watch `QdrantOpsRequest` CR, + +```bash +$ kubectl get qdrantopsrequest -n demo +NAME TYPE STATUS AGE +qdops-vol-exp VolumeExpansion Successful 10m +``` + +We can see from the above output that the `QdrantOpsRequest` has succeeded. If we describe the `QdrantOpsRequest` we will get an overview of the steps that were followed to expand the volume of the database. + +```bash +$ kubectl describe qdrantopsrequest qdops-vol-exp -n demo +Name: qdops-vol-exp +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: QdrantOpsRequest +Spec: + Apply: IfReady + Database Ref: + Name: qdrant-sample + Max Retries: 1 + Type: VolumeExpansion + Volume Expansion: + Mode: Offline + Node: 3Gi +Status: + Conditions: + Last Transition Time: 2026-05-15T05:20:42Z + Message: Qdrant ops-request has started to expand volume of Qdrant nodes + Observed Generation: 1 + Reason: VolumeExpansion + Status: True + Type: VolumeExpansion + Last Transition Time: 2026-05-15T05:21:04Z + Message: successfully deleted the petSets with orphan propagation policy + Observed Generation: 1 + Reason: OrphanPetSetPods + Status: True + Type: OrphanPetSetPods + Last Transition Time: 2026-05-15T05:20:54Z + Message: get petset; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: GetPetset + Last Transition Time: 2026-05-15T05:20:54Z + Message: delete petset; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: DeletePetset + Last Transition Time: 2026-05-15T05:23:15Z + Message: successfully updated node PVC sizes + Observed Generation: 1 + Reason: UpdateNodePVCs + Status: True + Type: UpdateNodePVCs + Last Transition Time: 2026-05-15T05:23:10Z + Message: get pod; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: GetPod + Last Transition Time: 2026-05-15T05:21:15Z + Message: patch ops request; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: PatchOpsRequest + Last Transition Time: 2026-05-15T05:21:15Z + Message: delete pod; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: DeletePod + Last Transition Time: 2026-05-15T05:21:25Z + Message: get pvc; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: GetPvc + Last Transition Time: 2026-05-15T05:21:26Z + Message: patch pvc; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: PatchPvc + Last Transition Time: 2026-05-15T05:23:05Z + Message: compare storage; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: CompareStorage + Last Transition Time: 2026-05-15T05:21:45Z + Message: create pod; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: CreatePod + Last Transition Time: 2026-05-15T05:23:25Z + Message: successfully reconciled the Qdrant resources + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2026-05-15T05:23:36Z + Message: PetSet is recreated + Observed Generation: 1 + Reason: ReadyPetSets + Status: True + Type: ReadyPetSets + Last Transition Time: 2026-05-15T05:23:36Z + Message: Successfully completed volumeExpansion for Qdrant + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 3m KubeDB Ops-manager Operator Pausing Qdrant database demo/qdrant-sample + Normal Successful 3m KubeDB Ops-manager Operator Successfully paused Qdrant database: demo/qdrant-sample for QdrantOpsRequest: qdops-vol-exp + Warning delete petset 3m KubeDB Ops-manager Operator delete petset; ConditionStatus:True + Normal OrphanPetSetPods 3m KubeDB Ops-manager Operator successfully deleted the petSets with orphan propagation policy + Warning delete pod 2m KubeDB Ops-manager Operator delete pod; ConditionStatus:True + Warning patch pvc 2m KubeDB Ops-manager Operator patch pvc; ConditionStatus:True + Warning create pod 1m KubeDB Ops-manager Operator create pod; ConditionStatus:True + Normal UpdateNodePVCs 1m KubeDB Ops-manager Operator successfully updated node PVC sizes + Normal UpdatePetSets 30s KubeDB Ops-manager Operator successfully reconciled the Qdrant resources + Normal ReadyPetSets 10s KubeDB Ops-manager Operator PetSet is recreated + Normal Starting 10s KubeDB Ops-manager Operator Resuming Qdrant database: demo/qdrant-sample + Normal Successful 10s KubeDB Ops-manager Operator Successfully resumed Qdrant database: demo/qdrant-sample for QdrantOpsRequest: qdops-vol-exp +``` + +Now, we are going to verify from the `PetSet` and `Persistent Volumes` whether the volume of the Qdrant database has expanded to meet the desired state: + +```bash +$ kubectl get petset -n demo qdrant-sample -o json | jq '.spec.volumeClaimTemplates[].spec.resources.requests.storage' +"3Gi" + +$ kubectl get pv -n demo +NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS AGE +pvc-0e300ccf-49f1-4e11-b630-bc3756baeaa0 3Gi RWO Delete Bound demo/data-qdrant-sample-0 longhorn 5m +pvc-20ab1d50-23d7-409a-ba2e-759250f9f758 3Gi RWO Delete Bound demo/data-qdrant-sample-2 longhorn 5m +pvc-ccee01bf-9551-4efc-8945-5a3d25c60c7b 3Gi RWO Delete Bound demo/data-qdrant-sample-1 longhorn 5m +``` + +The above output verifies that we have successfully expanded the volume of the Qdrant database. + +## Next Steps + +- Learn about [backup and restore](/docs/guides/qdrant/backup/overview/index.md) Qdrant using KubeStash. +- Detail concepts of [Qdrant object](/docs/guides/qdrant/concepts/qdrant.md). +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). + +## Cleaning Up + +To clean up the Kubernetes resources created by this tutorial, run: + +```bash +$ kubectl delete qdrant -n demo qdrant-sample +qdrant.kubedb.com "qdrant-sample" deleted + +$ kubectl delete qdrantopsrequest -n demo qdops-vol-exp +qdrantopsrequest.ops.kubedb.com "qdops-vol-exp" deleted +``` \ No newline at end of file