diff --git a/comps/third_parties/nebula/deployment/kubernetes/README.md b/comps/third_parties/nebula/deployment/kubernetes/README.md new file mode 100644 index 0000000000..93f3fd2cc8 --- /dev/null +++ b/comps/third_parties/nebula/deployment/kubernetes/README.md @@ -0,0 +1,71 @@ +# Deploy NebulaGraph cluster (with Kubectl) + +## 1. Install cert-manager + +```bash +kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download//cert-manager.yaml +``` + +## 2. Install Nebula Operator + +```bash +helm repo add nebula-operator https://vesoft-inc.github.io/nebula-operator/charts +helm repo update +helm install nebula-operator nebula-operator/nebula-operator --namespace= --version=1.1.0 +``` + +## 3. Install and start NebulaGraph cluster + +Choose between the Enterprise and Community configuration files base on your license. Create a StorageClass or use an existing one in the k8s cluster. Edit the config with the proper storageClassName and run the command below: + +```bash +kubectl create -f enterprise_edition.yaml +or +kubectl create -f community_edition.yaml +``` + +## 4. Connect to NebulaGraph databases + +Once you've set up a NebulaGraph cluster using Nebula Operator on Kubernetes, you can connect to NebulaGraph databases both from inside the cluster and from external sources. + +### 4.1. Connect to NebulaGraph databases from within a NebulaGraph cluster + +Run the following command to check the IP of the Service: + +```bash +$ kubectl get service -l app.kubernetes.io/cluster= # is a variable value. Replace it with the desired name. +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +nebula-graphd-svc ClusterIP 10.98.213.34 9669/TCP,19669/TCP,19670/TCP 23h +nebula-metad-headless ClusterIP None 9559/TCP,19559/TCP,19560/TCP 23h +nebula-storaged-headless ClusterIP None 9779/TCP,19779/TCP,19780/TCP,9778/TCP +``` + +Run the following commands to get the cluster ip and service port of the service: + +```bash +cluster_ip=$(kubectl get service | grep nebula-graphd-svc | awk '/nebula-graphd-svc/ {print $3}') +service_port=$(kubectl get service | grep nebula-graphd-svc | awk '{print $5}' | cut -d',' -f1 | cut -d'/' -f1) +``` + +Run the following command to connect to the NebulaGraph database using the cluster ip and service port the -graphd-svc service above: + +```bash +kubectl run -ti --image vesoft/nebula-console --restart=Never -- -addr -port -u -p +``` + +For example: + +```bash +kubectl run -ti --image vesoft/nebula-console --restart=Never -- nebula-console -addr 10.98.213.34 -port 9669 -u root -p vesoft + +``` + +A successful connection to the database is indicated if the following is returned: + +If you don't see a command prompt, try pressing enter. + +(root@nebula) [(none)]> + +### 4.2. Connect to NebulaGraph databases from outside a NebulaGraph cluster + +Refer to the [NebulaGraph Database Manual](https://docs.nebula-graph.io/3.1.3/nebula-operator/4.connect-to-nebula-graph-service/) for more information. diff --git a/comps/third_parties/nebula/deployment/kubernetes/community_edition.yaml b/comps/third_parties/nebula/deployment/kubernetes/community_edition.yaml new file mode 100644 index 0000000000..2db7ea50f0 --- /dev/null +++ b/comps/third_parties/nebula/deployment/kubernetes/community_edition.yaml @@ -0,0 +1,72 @@ +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: apps.nebula-graph.io/v1alpha1 +kind: NebulaCluster +metadata: + name: nebula + #namespace: nebula-operator-system +spec: + graphd: + resources: + requests: + cpu: "500m" + memory: "500Mi" + limits: + cpu: "1" + memory: "1Gi" + replicas: 1 + image: vesoft/nebula-graphd:v3.8.0 + service: + type: NodePort + externalTrafficPolicy: Local + logVolumeClaim: + resources: + requests: + storage: 2Gi + storageClassName: "${STORAGE_CLASS_NAME}" + metad: + resources: + requests: + cpu: "500m" + memory: "500Mi" + limits: + cpu: "1" + memory: "1Gi" + replicas: 1 + image: vesoft/nebula-metad:v3.8.0 + dataVolumeClaim: + resources: + requests: + storage: 2Gi + storageClassName: "${STORAGE_CLASS_NAME}" + logVolumeClaim: + resources: + requests: + storage: 2Gi + storageClassName: "${STORAGE_CLASS_NAME}" + storaged: + resources: + requests: + cpu: "500m" + memory: "500Mi" + limits: + cpu: "1" + memory: "1Gi" + replicas: 3 + image: vesoft/nebula-storaged:v3.8.0 + dataVolumeClaim: + resources: + requests: + storage: 2Gi + storageClassName: "${STORAGE_CLASS_NAME}" + logVolumeClaim: + resources: + requests: + storage: 2Gi + storageClassName: "${STORAGE_CLASS_NAME}" + reference: + name: statefulsets.apps + version: v1 + schedulerName: default-scheduler + imagePullPolicy: Always diff --git a/comps/third_parties/nebula/deployment/kubernetes/enterprise_edition.yaml b/comps/third_parties/nebula/deployment/kubernetes/enterprise_edition.yaml new file mode 100644 index 0000000000..afac07d1ec --- /dev/null +++ b/comps/third_parties/nebula/deployment/kubernetes/enterprise_edition.yaml @@ -0,0 +1,110 @@ +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +apiVersion: apps.nebula-graph.io/v1alpha1 +kind: NebulaCluster +metadata: + annotations: + nebula-graph.io/owner: test + name: nebula +spec: + enablePVReclaim: true + graphd: + readinessProbe: + failureThreshold: 3 + httpGet: + path: /status + port: 19669 + scheme: HTTP + initialDelaySeconds: 40 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 10 + image: reg.vesoft-inc.com/vesoft-ent/nebula-graphd + logVolumeClaim: + resources: + requests: + storage: 2Gi + storageClassName: fast-disks + replicas: 1 + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 500m + memory: 500Mi + version: v3.1.3 + imagePullPolicy: Always + imagePullSecrets: + - name: vesoft + metad: + license: + secretName: nebula-license + licenseKey: nebula.license + readinessProbe: + failureThreshold: 3 + httpGet: + path: /status + port: 19559 + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 5 + image: reg.vesoft-inc.com/vesoft-ent/nebula-metad + logVolumeClaim: + resources: + requests: + storage: 2Gi + storageClassName: fast-disks + dataVolumeClaim: + resources: + requests: + storage: 2Gi + storageClassName: fast-disks + replicas: 1 + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 500m + memory: 500Mi + version: v3.1.3 + reference: + name: statefulsets.apps + version: v1 + schedulerName: default-scheduler + storaged: + readinessProbe: + failureThreshold: 3 + httpGet: + path: /status + port: 19779 + scheme: HTTP + initialDelaySeconds: 40 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 + image: reg.vesoft-inc.com/vesoft-ent/nebula-storaged + logVolumeClaim: + resources: + requests: + storage: 2Gi + storageClassName: fast-disks + dataVolumeClaim: + resources: + requests: + storage: 2Gi + storageClassName: fast-disks + replicas: 3 + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 500m + memory: 500Mi + version: v3.1.3 + enableAutoBalance: true diff --git a/comps/third_parties/nebula/src/__init__.py b/comps/third_parties/nebula/src/__init__.py new file mode 100644 index 0000000000..916f3a44b2 --- /dev/null +++ b/comps/third_parties/nebula/src/__init__.py @@ -0,0 +1,2 @@ +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 diff --git a/tests/third_parties/test_third_parties_nebula.sh b/tests/third_parties/test_third_parties_nebula.sh new file mode 100644 index 0000000000..dbe3d31e0a --- /dev/null +++ b/tests/third_parties/test_third_parties_nebula.sh @@ -0,0 +1,118 @@ +#!/bin/bash +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +set +e +set -x + +WORKPATH=$(dirname "$PWD") +LOG_PATH="$WORKPATH/tests" +export STORAGE_CLASS_NAME=$(kubectl get storageclass -o jsonpath='{.items[0].metadata.name}') + +if [ -n "$STORAGE_CLASS_NAME" ]; then + echo "Using StorageClass: $STORAGE_CLASS_NAME" +else + echo "No StorageClass found." + exit 1 +fi + +function deploy_and_start_service() { + stop_service + sleep 60s + + cd $WORKPATH/comps/third_parties/nebula/deployment/kubernetes + kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.9.1/cert-manager.yaml + sleep 60s + + kubectl create namespace nebula-operator-system + helm repo add nebula-operator https://vesoft-inc.github.io/nebula-operator/charts + helm repo update + helm install nebula-operator nebula-operator/nebula-operator --namespace=nebula-operator-system --version=1.1.0 + sleep 60s + + #kubectl create -f community_edition.yaml + envsubst < community_edition.yaml | kubectl create -f - + sleep 120s +} + +function validate_database() { + cluster_ip=$(kubectl get service | grep nebula-graphd-svc | awk '/nebula-graphd-svc/ {print $3}') + + if [ -n "$cluster_ip" ]; then + echo "Using cluster_ip: $cluster_ip" + else + echo "No cluster_ip found." + exit 1 + fi + + kubectl delete pod nebula-console --ignore-not-found + # test create space + echo "[ test create ] creating space.." + query="CREATE SPACE my_space(partition_num=10, replica_factor=1, vid_type=FIXED_STRING(32)); USE my_space; CREATE TAG person(name string, age int);" + + create_response=$(kubectl run -ti --rm --image vesoft/nebula-console --restart=Never -- nebula-console -addr "$cluster_ip" -port 9669 -u root -p vesoft -e "$query" 2>&1) + + if [[ $? -eq 0 ]]; then + echo "[ test create ] create space succeed" + echo $create_response >> ${LOG_PATH}/nebulagraph_create_space.log + else + echo "[ test create ] create space failed" + echo $create_response >> ${LOG_PATH}/nebulagraph_create_space.log + exit 1 + fi + + sleep 30s + + # test insert data + echo "[ test insert ] inserting data.." + query="USE my_space; INSERT VERTEX person(name, age) VALUES 'person1':('Alice', 30); INSERT VERTEX person(name, age) VALUES 'person2':('Bob', 25);" + + insert_response=$(kubectl run -ti --rm --image vesoft/nebula-console --restart=Never -- nebula-console -addr "$cluster_ip" -port 9669 -u root -p vesoft -e "$query" 2>&1) + + if [[ $? -eq 0 ]]; then + echo "[ test insert ] insert data succeed" + echo $insert_response >> ${LOG_PATH}/nebulagraph_insert_data.log + else + echo "[ test insert ] insert data failed" + echo $insert_response >> ${LOG_PATH}/nebulagraph_insert_data.log + exit 1 + fi + + sleep 30s + + # test search data + echo "[ test search ] searching data.." + query="USE my_space; MATCH (p:person) RETURN p;" + + search_response=$(kubectl run -ti --rm --image vesoft/nebula-console --restart=Never -- nebula-console -addr "$cluster_ip" -port 9669 -u root -p vesoft -e "$query" 2>&1) + + if [[ $? -eq 0 ]]; then + echo "[ test search ] search data succeed" + echo $search_response >> ${LOG_PATH}/nebulagraph_search_data.log + else + echo "[ test search ] search data failed" + echo $search_response >> ${LOG_PATH}/nebulagraph_search_data.log + exit 1 + fi +} + +function stop_service() { + cd $WORKPATH/comps/third_parties/nebula/deployment/kubernetes + kubectl delete pod nebula-console --ignore-not-found + kubectl delete -f community_edition.yaml + helm uninstall nebula-operator --namespace nebula-operator-system + kubectl delete crd nebulaclusters.apps.nebula-graph.io + kubectl delete namespace nebula-operator-system +} + +function main() { + + deploy_and_start_service + + validate_database + + stop_service + +} + +main