You are looking at the documentation of a prior release. To read the documentation of the latest release, please
visit here.
New to KubeDB? Please start here.
Configure TLS/SSL for Milvus
This guide will show you how to deploy a Milvus database with TLS/SSL enabled from the start, using cert-manager.
Before You Begin
Install cert-manager in your cluster.
You should be familiar with the following
KubeDBconcepts:Complete the dependency setup from Prepare Dependencies. It installs MinIO, creates the
my-release-miniosecret, and installs the etcd operator required by Milvus.
Note: The yaml files used in this tutorial are stored in docs/guides/milvus/tls/yamls folder in GitHub repository kubedb/docs.
Create a cert-manager Issuer
KubeDB uses cert-manager to issue the Milvus certificates. First create a self-signed CA secret, then an Issuer (or ClusterIssuer) backed by it.
$ openssl genrsa -out ca.key 2048
$ openssl req -x509 -new -nodes -key ca.key -subj "/CN=milvus-ca/O=kubedb" -days 3650 -out ca.crt
$ kubectl create secret tls milvus-ca --cert=ca.crt --key=ca.key -n demo
secret/milvus-ca created
issuer.yaml
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: milvus-issuer
namespace: demo
spec:
ca:
secretName: milvus-ca
$ kubectl apply -f https://github.com/kubedb/docs/raw/v2026.7.10/docs/guides/milvus/tls/yamls/issuer.yaml
issuer.cert-manager.io/milvus-issuer created
$ kubectl get issuer -n demo
NAME READY AGE
milvus-issuer True 5s
A
ClusterIssuerworks the same way; a samplecluster-issuer.yaml(backed by secretmilvus-cluster-ca) is included in theyamlsfolder. With aClusterIssuer, setspec.tls.issuerRef.kind: ClusterIssuer.
Deploy a TLS-Secured Standalone Milvus
The standalone manifest enables TLS via spec.tls:
apiVersion: kubedb.com/v1alpha2
kind: Milvus
metadata:
name: milvus-standalone
namespace: demo
spec:
version: "2.6.11"
topology:
mode: Standalone
objectStorage:
configSecret:
name: "my-release-minio"
storageType: Durable
storage:
accessModes:
- ReadWriteOnce
storageClassName: local-path
resources:
requests:
storage: 1Gi
tls:
issuerRef:
name: milvus-issuer
kind: Issuer
apiGroup: "cert-manager.io"
external:
mode: mTLS
internal:
mode: TLS
spec.tls.external.mode: mTLSrequires clients to present a certificate.spec.tls.internal.mode: TLSencrypts inter-component traffic.
$ kubectl apply -f https://github.com/kubedb/docs/raw/v2026.7.10/docs/guides/milvus/tls/yamls/standalone.yaml
milvus.kubedb.com/milvus-standalone created
Wait until it is Ready.
Verify TLS
Certificate Secrets
KubeDB requests the server and client certificates and stores them in secrets:
$ kubectl get secret -n demo | grep -E 'milvus-standalone-(server|client)-cert'
milvus-standalone-client-cert kubernetes.io/tls 4 91s
milvus-standalone-server-cert kubernetes.io/tls 3 91s
TLS Files Mounted in the Pod
The certificates and CA are mounted at /milvus/tls:
$ kubectl exec -n demo milvus-standalone-0 -c milvus -- ls -l /milvus/tls
ca.pem
client.key
client.pem
server.key
server.pem
Rendered Configuration
The rendered milvus.yaml wires the certificates into Milvus:
$ kubectl get secret <config-secret> -n demo -o jsonpath='{.data.milvus\.yaml}' | base64 -d | grep -A4 internaltls
internaltls:
caPemPath: /milvus/tls/ca.pem
serverKeyPath: /milvus/tls/server.key
serverPemPath: /milvus/tls/server.pem
sni: milvus-standalone
AppBinding Scheme
Because TLS is enabled, the AppBinding connection scheme is https:
$ kubectl get appbinding milvus-standalone -n demo -o jsonpath='{.spec.clientConfig.service.scheme}'
https
Connect Through External mTLS
This guide uses spec.tls.external.mode: mTLS, so clients must present the client certificate.
Extract the CA and client certificate
$ kubectl get secret milvus-standalone-server-cert -n demo \
-o jsonpath='{.data.ca\.crt}' | base64 -d > /tmp/ca.crt
$ kubectl get secret milvus-standalone-client-cert -n demo \
-o jsonpath='{.data.tls\.crt}' | base64 -d > /tmp/client.crt
$ kubectl get secret milvus-standalone-client-cert -n demo \
-o jsonpath='{.data.tls\.key}' | base64 -d > /tmp/client.key
$ PASSWORD=$(kubectl get secret milvus-standalone-auth -n demo -o jsonpath='{.data.password}' | base64 -d)
Port-forward the REST port
Run this in a separate terminal:
$ kubectl port-forward svc/milvus-standalone -n demo 8080:8080
Forwarding from 127.0.0.1:8080 -> 8080
Create a collection over HTTPS
$ curl -s -X POST "https://localhost:8080/v2/vectordb/collections/create" \
--cacert /tmp/ca.crt \
--cert /tmp/client.crt \
--key /tmp/client.key \
-H "Authorization: Bearer root:${PASSWORD}" \
-H "Content-Type: application/json" \
-d '{
"collectionName": "tls_test_collection",
"dbName": "default",
"dimension": 4,
"metricType": "L2"
}' | jq .
Insert and search sample vectors
$ curl -s -X POST "https://localhost:8080/v2/vectordb/entities/insert" \
--cacert /tmp/ca.crt \
--cert /tmp/client.crt \
--key /tmp/client.key \
-H "Authorization: Bearer root:${PASSWORD}" \
-H "Content-Type: application/json" \
-d '{
"collectionName": "tls_test_collection",
"dbName": "default",
"data": [
{"id": 1, "vector": [0.9, 0.8, 0.7, 0.6]},
{"id": 2, "vector": [0.5, 0.4, 0.3, 0.2]}
]
}' | jq .
$ curl -s -X POST "https://localhost:8080/v2/vectordb/entities/search" \
--cacert /tmp/ca.crt \
--cert /tmp/client.crt \
--key /tmp/client.key \
-H "Authorization: Bearer root:${PASSWORD}" \
-H "Content-Type: application/json" \
-d '{
"collectionName": "tls_test_collection",
"dbName": "default",
"data": [[0.5, 0.4, 0.3, 0.2]],
"topK": 2,
"metricType": "L2"
}' | jq .
If you omit --cert and --key, the request should fail because client certificate authentication is required.
TLS-Secured Distributed Milvus
The distributed manifest enables TLS the same way. The server/client certificates are issued once and propagated to every distributed role (mixcoord, datanode, querynode, streamingnode, proxy).
apiVersion: kubedb.com/v1alpha2
kind: Milvus
metadata:
name: milvus-cluster
namespace: demo
spec:
version: "2.6.11"
objectStorage:
configSecret:
name: "my-release-minio"
topology:
mode: Distributed
distributed:
streamingnode:
storageType: Durable
storage:
accessModes:
- ReadWriteOnce
storageClassName: local-path
resources:
requests:
storage: 1Gi
tls:
issuerRef:
name: milvus-issuer
kind: Issuer
apiGroup: "cert-manager.io"
external:
mode: mTLS
internal:
mode: TLS
After it becomes Ready, the certificate secrets exist, the certificates are mounted into every role’s pods, and the AppBinding scheme is https:
$ kubectl get secret -n demo | grep -E 'milvus-cluster-(server|client)-cert'
milvus-cluster-client-cert kubernetes.io/tls 4 4m
milvus-cluster-server-cert kubernetes.io/tls 3 4m
$ kubectl exec -n demo milvus-cluster-mixcoord-0 -c milvus -- ls /milvus/tls
ca.pem
client.key
client.pem
server.key
server.pem
$ kubectl get appbinding milvus-cluster -n demo -o jsonpath='{.spec.clientConfig.service.scheme}'
https
Verify internal TLS between distributed roles
You can verify inter-component TLS from the proxy pod:
$ kubectl exec -it milvus-cluster-proxy-0 -n demo -- \
openssl s_client \
-connect milvus-cluster-querynode.demo.svc.cluster.local:21123 \
-CAfile /milvus/tls/ca.pem \
-servername milvus-cluster \
-brief
You should see a successful TLS handshake.
Cleaning up
$ kubectl delete milvus.kubedb.com -n demo milvus-standalone
$ kubectl delete issuer -n demo milvus-issuer
$ kubectl delete secret -n demo milvus-ca
$ kubectl delete ns demo
Next Steps
- Add, rotate or remove TLS on a running database with Reconfigure TLS.
- Detail concepts of Milvus object.
- Want to hack on KubeDB? Check our contribution guidelines.































