本文介紹如何使用 Docker 部署 Qdrant 向量資料庫,以及其相關的安全配置,並演示如何使用 .NET 透過 TLS 安全存取 Qdrant 向量資料庫。
1. 背景
隨著 AIGC 的發展,向量資料庫已經成為一個重要的資源,可以高效地儲存和檢索大量的向量數據。向量資料庫在需要相似性搜尋的各種套用中起著至關重要的作用,例如:作為推薦系統,基於內容的影像檢索和個人化搜尋。透過使用向量資料庫,我們可以有效地處理大規模的 Embedding 數據,從而支持各種AI和機器學習套用。Qdrant 是一個開源的向量資料庫,它提供了高效的向量索引和查詢功能,以及便捷的 API 介面和多種語言的客戶端庫,如 Python、Go、Rust、.NET 和 Java 等。
在實際套用中,我們通常需要保護向量資料庫的存取安全,以防止未經授權的存取和數據泄露。為了保護向量資料庫的存取安全,我們可以使用 TLS 協定對資料庫的存取進行加密。本文將介紹如何使用 Docker 部署 Qdrant 向量資料庫,以及其相關的安全配置,並演示如何使用 .NET 透過 TLS 安全存取 Qdrant 向量資料庫。
Qdrant 開源地址:https://github.com/qdrant/qdrant?wt.mc_id=DT-MVP-5005195
文件和相關介紹:https://qdrant.tech/
2. Qdrant 向量資料庫的部署
一般來說,我們可以使用 Docker 部署 Qdrant 向量資料庫。首先,我們需要安裝 Docker,然後使用以下命令拉取 Qdrant 的映像並啟動容器:
docker pull qdrant/qdrant
docker run -p 6333:6333 qdrant/qdrant
上面的命令將拉取 Qdrant 的映像並啟動容器,容器的 6333 埠將對映到主機的 6333 埠。這樣,我們就可以透過主機的 6333 埠存取 Qdrant 向量資料庫了。這對於一般的測試和開發環境來說是足夠的,對於生產環境如果僅在本機使用,也可以使用這種簡單的方式。但是,如果需要在生產環境中使用,我們通常需要對 Qdrant 向量資料庫進行一些安全配置。
2.1 Qdrant 向量資料庫的安全配置
在 Qdrant 的伺服端配置中,已經提供了相關的安全配置。我們可以透過配置檔
config.yaml
來配置 Qdrant 向量資料庫的安全選項。下面是安全相關的一些配置選項和建議:
1.
修改埠:預設情況下,Qdrant 向量資料庫的伺服端口是 http 6333 和 grpc 6334。我們可以透過配置檔中的
service.http_port
和
service.grpc_port
選項來修改伺服端口。
2.
啟用TLS:配置檔中的
service.enable_tls
和
cluster.p2p.enable_tls
預設為 false,這意味著服務和集群間的通訊都是不加密的。可以將兩個選項設定為 true,然後提供相應的證書檔路徑,以啟用安全的 TLS 通訊。需要在 tls 部份提供伺服器證書(cert)、伺服器私鑰(key)和證書頒發機構證書(ca_cert)。
3.
設定API金鑰:配置檔中的
service.api_key
和
service.read_only_api_key
,啟用後可以進行 API 認證。設定一個復雜的 API 金鑰,以便只有擁有金鑰的客戶端才能存取服務。這個金鑰分為讀寫金鑰和唯讀金鑰,可以根據需要進行設定。
4.
驗證HTTPS客戶端證書:配置檔中的
service.verify_https_client_certificate
也可以啟用,服務會驗證 HTTPS 客戶端的證書。這樣可以增加一個額外的安全層,伺服端會要求客戶端也提供一個有效的證書。
5.
限制CORS:配置檔中的
service.enable_cors
預設為 true,這可能會導致跨站請求偽造(CSRF)攻擊。如果條件允許則應該考慮限制 CORS,允許來自可信來源的請求。
6.
限制並行更新:配置檔中的
storage.performance.update_rate_limit
預設為 null,服務沒有限制並行更新的數量。正式環境應該設定一個合理的限制,以防止拒絕服務(DoS)攻擊。
7.
關閉遙測:配置檔中的
telemetry_disabled
預設為 false,服務會將使用統計資訊發送給開發者。出於私密考慮,可以將此選項設定為 true。
2.2 使用 Docker 部署安全的 Qdrant 向量資料庫
前面一小節介紹了 Qdrant 向量資料庫的安全配置,接下來我們將介紹如何使用 Docker 部署安全的 Qdrant 向量資料庫。演示中我們將使用 TLS 安全存取 Qdrant 向量資料庫,包括伺服端和客戶端的證書驗證。
2.2.1 準備證書檔
首先我們需要準備好證書檔,包括伺服器證書(cert)、伺服器私鑰(key)和證書頒發機構證書(ca_cert)以及客戶端證書(client_cert)和客戶端私鑰(client_key)。這裏我們可以使用 OpenSSL 工具生成自簽名的證書,這裏不再贅述。
演示這裏我使用的是自己搭建的私有證書頒發機構,生成的證書。這裏我使用了二級證書頒發機構,簽發的伺服器證書和客戶端證書都是由二級證書頒發機構簽發的。
對於客戶端證書,我們需要將客戶端證書和客戶端私鑰放在一個檔中,可以直接生成一個 pfx 檔:
openssl pkcs12 -export -out client.pfx -inkey client.key -in client.cer
根據提示輸入密碼,生成的 client.pfx 檔就是客戶端證書和客戶端私鑰的合並檔。
2.2.2 Docker 部署及配置
接下來我們需要規劃好 Qdrant 的配置檔
production.yaml
,並將數據目錄、證書檔和配置檔放到 Docker 容器中。首先我們將證書檔放到一個目錄中,然後將這個目錄掛載到 Docker 容器中。
這裏我的配置如下:
log_level: INFO
telemetry_disabled: true
service:
host: 0.0.0.0
http_port: 6333
grpc_port: 6334
enable_tls: true
verify_https_client_certificate: true
tls:
cert: ./tls/server.pem
key: ./tls/server.key
ca_cert: ./tls/cacert.pem
配置完成後,我們可以使用以下命令啟動 Qdrant 容器:
docker run -p 6333:6333 \
-v $(pwd)/path/to/data:/qdrant/storage \
-v $(pwd)/path/to/tls:/qdrant/tls \
-v $(pwd)/path/to/production.yaml:/qdrant/config/production.yaml \
qdrant/qdrant
註意修改
path/to/data
、
path/to/tls
和
path/to/production.yaml
為實際的路徑。
2.3 管理後台的存取
Qdrant 向量資料庫提供了一個簡單的管理後台,可以透過瀏覽器存取。預設情況下,管理後台的埠是 6333,我們可以透過配置檔中的
service.http_port
選項來修改埠。在瀏覽器中輸入
http://localhost:6333/dashboard
即可存取管理後台。
Qdrant 的 Web UI 是一個直觀高效的圖形界面,可以方便的檢視 Qdrant 集合、REST API 和數據點。這裏我們啟動的服務已經啟用了 TLS 安全存取,並要求客戶端提供有效的證書,所以我們需要使用
https
協定存取管理後台。
除了安裝並信任我們的證書,我們還需要在瀏覽器中匯入客戶端證書。如果沒有安裝客戶端證書,則會提示證書錯誤
ERR_BAD_SSL_CLIENT_AUTH_CERT
,無法存取管理後台。
此時我們需要雙擊開啟客戶端證書
client.pfx
,然後根據提示安裝證書,中間需要輸入密碼,其他一路預設即可:
安裝完成後,我們直接重新整理頁面,會提示選擇證書:
選擇證書確認後,即可存取管理後台。
3. 使用 .NET 透過 TLS 安全存取
雖然伺服端提供了API金鑰的方式,但仍然建議在客戶端與伺服端之間使用TLS加密。
3.1 證書驗證
以下是一些關於如何在.NET中使用TLS加密的建議:
首先,需要從證書檔中載入證書。可以使用
X509Certificate2
類來實作。例如,如果證書和私鑰都在一個 PKCS#12 檔(通常副檔名為 .pfx 或 .p12)中,可以這樣載入它:
var clientCert = new X509Certificate2("path/to/client.pfx", "password");
除了載入客戶端證書,我們還需要對伺服器證書進行驗證。可以使用
SocketsHttpHandler
類來實作。例如,可以使用以下程式碼來驗證伺服器證書:
stringCertificateThumbprint = "<certificate-thumbprint>";
var clientCertificate = new X509Certificate2("<path-to-your-certificate.pfx>", "<your-password>");
var channel = GrpcChannel.ForAddress("<your-server-address>", newGrpcChannelOptions
{
HttpHandler = newSocketsHttpHandler
{
SslOptions = newSslClientAuthenticationOptions
{
RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
{
if (sslPolicyErrors == SslPolicyErrors.None)
{
var x509Certificate = certificate as X509Certificate2;
if (x509Certificate != null)
{
return x509Certificate.Thumbprint.ToLower() == CertificateThumbprint;
}
}
returnfalse;
},
ClientCertificates = new X509CertificateCollection { clientCertificate }
}
}
});
在上面的程式碼中,我們使用
SocketsHttpHandler
類來實作對伺服器證書的驗證。我們可以在
RemoteCertificateValidationCallback
回呼函式中實作自訂的證書驗證邏輯。在這個回呼函式中,我們可以驗證伺服器證書的有效性,例如:驗證證書的頒發機構、證書的有效期、證書的主題等。如果伺服器證書驗證透過,我們可以返回
true
,否則返回
false
。
這裏參考了官方的驗證方式,使用
Thumbprint
內容來驗證伺服器證書的指紋。我們可以在
RemoteCertificateValidationCallback
回呼函式中將伺服器證書的指紋與預期的證書指紋進行比較,如果一致則返回
true
,否則返回
false
。
這裏的
x509Certificate.Thumbprint
獲取的是證書的 sha1 指紋資訊。對於證書的指紋,我們可以使用以下命令來獲取:
openssl x509 -fingerprint -sha1 -in server.cer
Edge 瀏覽器的證書資訊界面重新設計了,並且顯示的是 sha256 指紋,所以需要註意。不過該指紋資訊可以方面我們使用官方下面的案例時直接使用:
var channel = QdrantChannel.ForAddress("https://localhost:6334", newClientConfiguration
{
ApiKey = "<api key>",
CertificateThumbprint = "<certificate thumbprint>"
});
var grpcClient = newQdrantGrpcClient(channel);
var client = newQdrantClient(grpcClient);
當然,如果需要獲取 sha1 指紋資訊也可以下載證書檔,直接在電腦中開啟開啟,然後在詳細資訊中檢視指紋資訊。
3.2 使用 .NET 客戶端存取
完成了驗證的配置,剩下的就是使用 .NET 客戶端存取 Qdrant 向量資料庫了。我們直接參考官方的案例即可,以下是一個簡單的 .NET 客戶端存取 Qdrant 向量資料庫建立集合的範例:
var grpcClient = newQdrantGrpcClient(channel);
var client = newQdrantClient(grpcClient);
await client.CreateCollectionAsync("my_collection",
newVectorParams { Size = 100, Distance = Distance.Cosine });
4. 總結
本文介紹了如何使用 Docker 部署 Qdrant 向量資料庫,以及其相關的安全配置,並演示了如何使用 .NET 透過 TLS 安全存取 Qdrant 向量資料庫。透過本文的介紹,我們可以了解到如何在生產環境中安全地部署 Qdrant 向量資料庫,並使用 .NET 客戶端透過 TLS 安全存取 Qdrant 向量資料庫。