Skip to content

Commit f0bd7e3

Browse files
committed
initial commit
1 parent 7485f4e commit f0bd7e3

11 files changed

+541
-1
lines changed

README.md

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,29 @@
1-
# terraform-kubernetes-qdrant
1+
# Qdrant Terraform Module
2+
3+
[![Terraform Registry URL](https://img.shields.io/badge/terraform-%235835CC.svg?style=for-the-badge&logo=terraform&logoColor=white)](https://registry.terraform.io/modules/ilert/qdrant/kubernetes/latest)
4+
5+
Terraform module to deploy Qdrant vector DB on kubernetes
6+
7+
## Usage
8+
9+
> Make sure you have Terraform installed
10+
11+
Create a `main.tf` file with the following content:
12+
13+
```terraform
14+
module "qdrant" {
15+
source = "ilert/qdrant/kubernetes"
16+
version = "0.1.0"
17+
name = "qdrant"
18+
namespace = "default"
19+
storage_size = "10Gi"
20+
}
21+
```
22+
23+
Then run the following commands:
24+
25+
```sh
26+
terraform init
27+
terraform apply
28+
```
29+

config.tf

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
resource "kubernetes_config_map" "this" {
2+
metadata {
3+
name = var.name
4+
namespace = var.namespace
5+
6+
labels = {
7+
app = var.name
8+
}
9+
}
10+
11+
data = {
12+
"initialize.sh" = file("${path.module}/initialize.sh")
13+
"entrypoint.sh" = file("${path.module}/entrypoint.sh")
14+
"production.yaml" = file("${path.module}/production.yaml")
15+
}
16+
}

entrypoint.sh

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/bin/bash
2+
set -xe
3+
echo 'connect-timeout = 5' > $HOME/.curlrc
4+
echo 'retry = 5' >> $HOME/.curlrc
5+
echo 'retry-all-errors' >> $HOME/.curlrc
6+
7+
if [ -d /mnt/secrets/certs ]; then
8+
cp /mnt/secrets/certs/ca.pem /usr/share/pki/trust/anchors/private-ca.pem
9+
update-ca-certificates
10+
fi
11+
12+
QDRANT_COLLECTION="test_collection"
13+
echo "Connecting to qdrant.default:6333"
14+
QDRANT_URL="http://qdrant.default:6333"
15+
API_KEY_HEADER=""
16+
API_KEY_HEADER="Api-key: true"
17+
18+
# Delete collection if exists
19+
curl -X DELETE -H "${API_KEY_HEADER}" $QDRANT_URL/collections/${QDRANT_COLLECTION}
20+
21+
# Create collection
22+
curl -X PUT \
23+
-H 'Content-Type: application-json' \
24+
-d '{"vectors":{"size":4,"distance":"Dot"}}' \
25+
-H "${API_KEY_HEADER}" \
26+
$QDRANT_URL/collections/${QDRANT_COLLECTION} --fail-with-body
27+
28+
# Insert points
29+
curl -X PUT \
30+
-H 'Content-Type: application-json' \
31+
-d '{"points":[
32+
{"id":1,"vector":[0.05, 0.61, 0.76, 0.74],"payload":{"city":"Berlin"}},
33+
{"id":2,"vector":[0.19, 0.81, 0.75, 0.11],"payload":{"city":"London"}},
34+
{"id":3,"vector":[0.36, 0.55, 0.47, 0.94],"payload":{"city":"Moscow"}},
35+
{"id":4,"vector":[0.18, 0.01, 0.85, 0.80],"payload":{"city":"New York"}},
36+
{"id":5,"vector":[0.24, 0.18, 0.22, 0.44],"payload":{"city":"Beijing"}},
37+
{"id":6,"vector":[0.35, 0.08, 0.11, 0.44],"payload":{"city":"Mumbai"}}
38+
]}' \
39+
-H "${API_KEY_HEADER}" \
40+
$QDRANT_URL/collections/${QDRANT_COLLECTION}/points --fail-with-body
41+
42+
# Run query
43+
curl -X POST \
44+
-H 'Content-Type: application-json' \
45+
-d '{"vector":[0.2, 0.1, 0.9, 0.7],"limit":3}' \
46+
-H "${API_KEY_HEADER}" \
47+
$QDRANT_URL/collections/${QDRANT_COLLECTION}/points/search --fail-with-body

initialize.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/bin/bash
2+
set -e
3+
SET_INDEX=${HOSTNAME##*-}
4+
echo "Starting initializing for pod $SET_INDEX"
5+
if [ "$SET_INDEX" = "0" ]; then
6+
exec ./entrypoint.sh --uri 'http://qdrant-0.qdrant-headless:6335'
7+
else
8+
exec ./entrypoint.sh --bootstrap 'http://qdrant-0.qdrant-headless:6335' --uri 'http://qdrant-'"$SET_INDEX"'.qdrant-headless:6335'
9+
fi

pdb.tf

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
resource "kubernetes_pod_disruption_budget_v1" "this" {
2+
metadata {
3+
name = var.name
4+
namespace = var.namespace
5+
}
6+
7+
spec {
8+
max_unavailable = 1
9+
selector {
10+
match_labels = {
11+
app = kubernetes_stateful_set.this.metadata[0].name
12+
}
13+
}
14+
}
15+
}

production.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
cluster:
2+
consensus:
3+
tick_period_ms: 100
4+
enabled: true
5+
p2p:
6+
port: 6335

secret.tf

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
resource "random_password" "qdrant-api-key" {
2+
length = 128
3+
special = false
4+
min_lower = 3
5+
min_numeric = 3
6+
min_upper = 3
7+
}
8+
9+
resource "random_password" "qdrant-read-only-api-key" {
10+
length = 128
11+
special = false
12+
min_lower = 3
13+
min_numeric = 3
14+
min_upper = 3
15+
}
16+
17+
resource "kubernetes_secret" "this" {
18+
metadata {
19+
name = var.name
20+
namespace = var.namespace
21+
}
22+
23+
data = {
24+
"api-key" = random_password.qdrant-api-key.result
25+
"read-only-api-key" = random_password.qdrant-read-only-api-key.result
26+
"local.yaml" = <<EOL
27+
service:
28+
api_key: ${random_password.qdrant-api-key.result}
29+
read_only_api_key: ${random_password.qdrant-read-only-api-key.result}
30+
EOL
31+
}
32+
33+
type = "Opaque"
34+
}

service-account.tf

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
resource "kubernetes_service_account" "this" {
2+
metadata {
3+
name = var.name
4+
namespace = var.namespace
5+
}
6+
automount_service_account_token = true
7+
}

service.tf

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
resource "kubernetes_service" "this-headless" {
2+
metadata {
3+
name = "${var.name}-headless"
4+
namespace = var.namespace
5+
}
6+
7+
spec {
8+
selector = {
9+
app = var.name
10+
}
11+
12+
session_affinity = "ClientIP"
13+
cluster_ip = "None"
14+
publish_not_ready_addresses = true
15+
16+
port {
17+
name = "http"
18+
protocol = "TCP"
19+
port = 6333
20+
target_port = 6333
21+
}
22+
23+
port {
24+
name = "grpc"
25+
protocol = "TCP"
26+
port = 6334
27+
target_port = 6334
28+
}
29+
30+
port {
31+
name = "p2p"
32+
protocol = "TCP"
33+
port = 6335
34+
target_port = 6335
35+
}
36+
37+
type = "ClusterIP"
38+
}
39+
}
40+
41+
resource "kubernetes_service" "this" {
42+
metadata {
43+
name = var.name
44+
namespace = var.namespace
45+
}
46+
47+
spec {
48+
selector = {
49+
app = var.name
50+
}
51+
52+
session_affinity = "ClientIP"
53+
54+
port {
55+
name = "http"
56+
protocol = "TCP"
57+
port = 6333
58+
target_port = 6333
59+
}
60+
61+
port {
62+
name = "grpc"
63+
protocol = "TCP"
64+
port = 6334
65+
target_port = 6334
66+
}
67+
68+
port {
69+
name = "p2p"
70+
protocol = "TCP"
71+
port = 6335
72+
target_port = 6335
73+
}
74+
75+
type = "ClusterIP"
76+
}
77+
}

0 commit comments

Comments
 (0)