在 Azure 上部署 Loki Helm Chart
本指南将介绍如何使用 Helm Chart 在 Azure 上部署一个最简可用的微服务模式 Loki。为了成功完成本指南,您必须具备在 Azure 上部署资源所需的工具和权限,例如
- 完全访问 AKS (Azure Kubernetes Service)
- 完全访问 Azure Blob Storage
- 足够的权限在 Azure AD (Active Directory) 中创建联合身份凭证和角色
将 Loki 与 Azure 进行身份验证主要有三种方法
- 硬编码连接字符串 - 这是最简单的方法,但不建议在生产环境中使用。
- 托管标识
- 联合令牌
在本指南中,我们将使用联合令牌方法在 Azure 上部署 Loki。此方法比硬编码连接字符串更安全,更适合生产环境。
注意事项
注意
本指南在 2025 年 1 月 8 日 最后更新时是准确的。由于云提供商会频繁更新其服务和产品,作为最佳实践,您在创建存储帐户和分配角色之前,应参考Azure 文档。
AD 角色:在本教程中,我们将在 Azure Active Directory (Azure AD) 中创建一个角色,允许 Loki 从 Azure Blob Storage 读取和写入。此角色将分配给 Loki 服务帐户。您可能需要根据您的要求调整权限。
身份验证: Grafana Loki 带有一个基本的身份验证层。在此示例中,Loki 网关 (NGINX) 使用基本身份验证暴露到互联网。NGINX 也可以替换为其他开源反向代理。有关更多信息,请参阅身份验证。
保留策略:在
values.yaml
文件中,保留期设置为 28 天。您可能希望根据您的要求调整此设置。成本:在 Azure 上运行 Loki 会产生费用。请务必监控您的使用情况和费用,避免产生意外账单。在本指南中,我们使用了包含 3 个节点和
Standard_E2ds_v5
实例的简单 AKS 集群。您可能需要根据您的工作负载调整实例类型和节点数量。
先决条件
- Helm 3 或更高版本。请参阅安装 Helm。应安装在您的本地机器上。
- Kubectl 已安装在您的本地机器上。请参阅安装和设置 kubectl。
- Azure CLI 已安装在您的本地机器上。请参阅安装 Azure CLI。这是遵循本指南的要求,因为所有资源都将使用 Azure CLI 创建。
AKS 最低要求
在 Azure 中创建 AKS 集群之前,您需要创建一个资源组。您可以使用 Azure CLI 创建资源组
az group create --name <INSERT-NAME> -location <INSERT-AZURE-REGION>
注意
这些 AKS 要求是使用本指南部署 Loki 所需的最低规范。您可能需要根据您的 Azure 环境和工作负载调整实例类型。如果您选择这样做,我们无法保证此示例配置仍能满足您的需求。
在本指南中,我们使用
Standard_E2ds_v5
实例部署 Loki。这是为了确保我们在 Azure 的免费层级限制范围内。这允许我们在一个区域内最多部署 10 个 vCPU。对于大型生产工作负载,我们建议将这些节点扩展到Standard_D4_v5
。
在 AKS 上部署 Loki 的最低要求是
- Kubernetes 版本
1.30
或更高。 - AKS 集群需要
3
个节点。 - 实例类型取决于您的工作负载。对于免费层级中的生产集群,一个好的起点是
Standard_E2ds_v5
实例,而对于大型生产工作负载则是Standard_D4_v5
实例。
以下是如何创建满足最低要求的 AKS 集群
az aks create \
--resource-group <MY_RESOURCE_GROUP_NAME> \
--name <MY_AKS_CLUSTER_NAME> \
--node-count 3 \
--node-vm-size Standard_E2ds_v5 \
--generate-ssh-keys \
--enable-workload-identity \
--enable-oidc-issuer
请注意,在上述命令中,我们已启用工作负载身份和 OIDC 颁发者。这是 Loki 服务帐户与 Azure AD 进行身份验证所必需的。如果您已经创建了 AKS 集群,可以使用以下命令启用这些功能
az aks update \
--resource-group <MY_RESOURCE_GROUP_NAME> \
--name <MY_AKS_CLUSTER_NAME> \
--enable-workload-identity \
--enable-oidc-issuer
Azure CLI 还允许您将 AKS 集群绑定到 kubectl。您可以通过运行以下命令来完成此操作
az aks get-credentials --resource-group <MY_RESOURCE_GROUP_NAME> --name <MY_AKS_CLUSTER_NAME>
配置 Azure Blob Storage
提示
考虑使用唯一的存储桶名称,而不是:
chunk
、ruler
和admin
。尽管 Azure Blob Storage 不直接受此安全更新的影响,但为存储桶使用唯一的容器名称是一种最佳实践。
在部署 Loki 之前,您需要创建两个 Azure 存储容器;一个用于存储日志(chunk),第二个用于存储告警规则。您可以使用 Azure CLI 创建容器。容器必须存在于存储帐户中。
注意
GEL 客户将需要第三个容器来存储管理数据。OSS 用户不需要此容器。
创建一个存储帐户
az storage account create \ --name <NAME> \ --location <REGION> \ --sku Standard_ZRS \ --encryption-services blob \ --resource-group <MY_RESOURCE_GROUP_NAME>
将占位符替换为您期望的值。
为 chunk 和 ruler 创建容器
az storage container create --account-name <STORAGE-ACCOUNT-NAME> --name <CHUNK-BUCKET-NAME> --auth-mode login && \ az storage container create --account-name <STORAGE-ACCOUNT-NAME> --name <RULER-BUCKET-NAME> --auth-mode login
确保
--account-name
与您刚刚创建的帐户匹配
创建存储帐户和容器后,您现在可以继续创建 Azure AD 角色和联合身份凭证。
创建 Azure AD 角色和联合身份凭证
将 Loki 与 Azure Blob Storage 进行身份验证的推荐方法是使用联合身份凭证。此方法比将连接字符串直接硬编码到 Loki 配置中更安全。在下一节中,我们将为 Loki 创建一个 Azure AD 角色和联合身份凭证,以允许它从 Azure Blob Storage 读取和写入。
找到 OpenID Connect (OIDC) 颁发者 URL
az aks show \ --resource-group <MY_RESOURCE_GROUP_NAME> \ --name <MY_AKS_CLUSTER_NAME> \ --query "oidcIssuerProfile.issuerUrl" \ -o tsv
此命令将返回 OIDC 颁发者 URL。您将需要此 URL 来创建联合身份凭证。
生成一个包含以下内容的
credentials.json
文件{ "name": "LokiFederatedIdentity", "issuer": "<OIDC-ISSUER-URL>", "subject": "system:serviceaccount:loki:loki", "description": "Federated identity for Loki accessing Azure resources", "audiences": [ "api://AzureADTokenExchange" ] }
将
<OIDC-ISSUER-URL>
替换为您在上一步中找到的 OIDC 颁发者 URL。请务必在继续之前保存
credentials.json
文件。接下来生成一个 Azure 目录
app
。我们将使用此应用来分配我们的联合身份凭证az ad app create \ --display-name loki \ --query appId \ -o tsv
这将返回应用 ID。保存此 ID 以备后用。如果您稍后需要查找应用 ID,可以运行以下命令
az ad app list --display-name loki --query "[].appId" -o tsv
该应用需要一个服务主体来与 Azure AD 进行身份验证。为该应用创建服务主体
az ad sp create --id <APP-ID>
将
<APP-ID>
替换为您在上一步中生成的应用 ID。接下来将联合身份凭证分配给该应用
az ad app federated-credential create \ --id <APP-ID> \ --parameters credentials.json
将
<APP-ID>
替换为您在上一步中生成的应用 ID。最后为该应用添加角色分配
az role assignment create \ --role "Storage Blob Data Contributor" \ --assignee <APP-ID> \ --scope /subscriptions/<SUBSCRIPTION-ID>/resourceGroups/<RESOURCE-GROUP>/providers/Microsoft.Storage/storageAccounts/<STORAGE-ACCOUNT-NAME>
将占位符替换为您的实际值。
现在您已创建了 Azure AD 角色和联合身份凭证,可以继续使用 Helm Chart 部署 Loki。
部署 Helm Chart
以下步骤需要使用 helm
和 kubectl
。确保您已运行 az
命令将您的 AKS 集群绑定到 kubectl
az aks get-credentials --resource-group <MY_RESOURCE_GROUP_NAME> --name <MY_AKS_CLUSTER_NAME>
在部署 Loki Helm Chart 之前,我们需要将 Grafana Chart 仓库添加到 Helm 中。此仓库包含 Loki Helm Chart。
将 Grafana Chart 仓库添加到 Helm
helm repo add grafana https://grafana.github.io/helm-charts
更新 Chart 仓库
helm repo update
为 Loki 创建一个新的命名空间
kubectl create namespace loki
Loki 基本身份验证
Loki 默认不带任何身份验证。由于我们将在 Azure 上部署 Loki 并将网关暴露到互联网,我们建议至少添加基本身份验证。在本指南中,我们将为 Loki 设置用户名和密码
首先,我们需要使用用户名和密码创建一个
.htpasswd
文件。您可以使用htpasswd
命令创建该文件提示
如果您没有安装
htpasswd
命令,可以根据您的操作系统使用brew
、apt-get
或yum
进行安装。htpasswd -c .htpasswd <username>
这将创建一个名为
auth
的文件,用户名为loki
。系统将提示您输入密码。使用
.htpasswd
文件创建一个 Kubernetes Secretkubectl create secret generic loki-basic-auth --from-file=.htpasswd -n loki
这将在
loki
命名空间中创建一个名为loki-basic-auth
的 Secret。我们将在 Loki Helm Chart 配置中引用此 Secret。为 Canary 创建一个
canary-basic-auth
Secretkubectl create secret generic canary-basic-auth \ --from-literal=username=<USERNAME> \ --from-literal=password=<PASSWORD> \ -n loki
我们创建一个字面 Secret,其中包含 Loki Canary 用于与 Loki 网关进行身份验证的用户名和密码。请务必将占位符替换为您期望的用户名和密码。
Loki Helm Chart 配置
创建一个 values.yaml
文件,选择最符合您要求的配置选项。下面是一个微服务模式下 Loki Helm Chart 的 values.yaml
文件示例。
loki:
podLabels:
"azure.workload.identity/use": "true" # Add this label to the Loki pods to enable workload identity
schemaConfig:
configs:
- from: "2024-04-01"
store: tsdb
object_store: azure
schema: v13
index:
prefix: loki_index_
period: 24h
storage_config:
azure:
account_name: "<INSERT-STORAGE-ACCOUNT-NAME>"
container_name: "<CHUNK-CONTAINER-NAME>" # Your actual Azure Blob Storage container name (loki-azure-dev-chunks)
use_federated_token: true # Use federated token for authentication
ingester:
chunk_encoding: snappy
pattern_ingester:
enabled: true
limits_config:
allow_structured_metadata: true
volume_enabled: true
retention_period: 672h # 28 days retention
compactor:
retention_enabled: true
delete_request_store: azure
ruler:
enable_api: true
storage:
type: azure
azure:
account_name: <INSERT-STORAGE-ACCOUNT-NAME>
container_name: <RULER-CONTAINER-NAME> # Your actual Azure Blob Storage container name (loki-azure-dev-ruler)
use_federated_token: true # Use federated token for authentication
alertmanager_url: http://prom:9093 # The URL of the Alertmanager to send alerts (Prometheus, Mimir, etc.)
querier:
max_concurrent: 4
storage:
type: azure
bucketNames:
chunks: "<CHUNK-CONTAINER-NAME>" # Your actual Azure Blob Storage container name (loki-azure-dev-chunks)
ruler: "<RULER-CONTAINER-NAME>" # Your actual Azure Blob Storage container name (loki-azure-dev-ruler)
# admin: "admin-loki-devrel" # Your actual Azure Blob Storage container name (loki-azure-dev-admin)
azure:
accountName: <INSERT-STORAGE-ACCOUNT-NAME>
useFederatedToken: true # Use federated token for authentication
# Define the Azure workload identity
serviceAccount:
name: loki
annotations:
"azure.workload.identity/client-id": "<APP-ID>" # The app ID of the Azure AD app
labels:
"azure.workload.identity/use": "true"
deploymentMode: Distributed
ingester:
replicas: 3
zoneAwareReplication:
enabled: false
querier:
replicas: 3
maxUnavailable: 2
queryFrontend:
replicas: 2
maxUnavailable: 1
queryScheduler:
replicas: 2
distributor:
replicas: 3
maxUnavailable: 2
compactor:
replicas: 1
indexGateway:
replicas: 2
maxUnavailable: 1
ruler:
replicas: 1
maxUnavailable: 1
# This exposes the Loki gateway so it can be written to and queried externaly
gateway:
service:
type: LoadBalancer
basicAuth:
enabled: true
existingSecret: loki-basic-auth
# Since we are using basic auth, we need to pass the username and password to the canary
lokiCanary:
extraArgs:
- -pass=$(LOKI_PASS)
- -user=$(LOKI_USER)
extraEnv:
- name: LOKI_PASS
valueFrom:
secretKeyRef:
name: canary-basic-auth
key: password
- name: LOKI_USER
valueFrom:
secretKeyRef:
name: canary-basic-auth
key: username
# Enable minio for storage
minio:
enabled: false
backend:
replicas: 0
read:
replicas: 0
write:
replicas: 0
singleBinary:
replicas: 0
注意
请务必将占位符替换为您的实际值。
定义一个有效的 values.yaml
文件对于 Loki 部署至关重要。为了消除配置错误的风险,让我们分解在部署到 Azure 时需要记住的配置选项
Loki Config vs. Values Config
values.yaml
文件包含一个名为loki
的部分,其中直接表示 Loki 配置文件的内容。- 此部分定义了 Loki 的配置,包括 schema、存储和查询器配置。
- 针对 chunk 需要重点关注的关键配置是
storage_config
部分,您在此定义 Azure 容器名称和存储帐户。这指示 Loki 将 chunk 存储在哪里。 ruler
部分定义了 ruler 的配置,包括 Azure 容器名称和存储帐户。这指示 Loki 将告警和记录规则存储在哪里。- 有关完整的 Loki 配置,请参阅Loki 配置文档。
存储
- 定义 Helm Chart 存储数据的位置。
- 由于我们使用 Azure Blob Storage,请将类型设置为
azure
。 - 配置 chunk 和 ruler 的容器名称,使其与之前创建的容器匹配。
azure
部分指定了存储帐户名称,并将useFederatedToken
设置为true
。这指示 Loki 使用联合身份凭证进行身份验证。
服务帐户
serviceAccount
部分用于定义 Loki 将用于与 Azure AD 进行身份验证的联合工作负载身份。- 我们将
azure.workload.identity/client-id
注解设置为 Azure AD 应用的应用 ID。
网关
- 定义 Loki 网关的暴露方式。
- 在此配置中,我们使用的是
LoadBalancer
服务类型。
部署 Loki
现在您已经创建了 values.yaml
文件,可以使用 Helm Chart 部署 Loki。
使用新创建的
values.yaml
文件进行部署helm install --values values.yaml loki grafana/loki -n loki --create-namespace
创建一个名为
loki
的命名空间非常重要,因为我们的联合身份凭证是使用值system:serviceaccount:loki:loki
生成的。这对应于loki
命名空间中的loki
服务帐户。这是可配置的,但请务必先更新联合身份凭证文件。验证部署
kubectl get pods -n loki
您应该看到 Loki pod 正在运行。
NAME READY STATUS RESTARTS AGE loki-canary-crqpg 1/1 Running 0 10m loki-canary-hm26p 1/1 Running 0 10m loki-canary-v9wv9 1/1 Running 0 10m loki-chunks-cache-0 2/2 Running 0 10m loki-compactor-0 1/1 Running 0 10m loki-distributor-78ccdcc9b4-9wlhl 1/1 Running 0 10m loki-distributor-78ccdcc9b4-km6j2 1/1 Running 0 10m loki-distributor-78ccdcc9b4-ptwrb 1/1 Running 0 10m loki-gateway-5f97f78755-hm6mx 1/1 Running 0 10m loki-index-gateway-0 1/1 Running 0 10m loki-index-gateway-1 1/1 Running 0 10m loki-ingester-zone-a-0 1/1 Running 0 10m loki-ingester-zone-b-0 1/1 Running 0 10m loki-ingester-zone-c-0 1/1 Running 0 10m loki-querier-89d4ff448-4vr9b 1/1 Running 0 10m loki-querier-89d4ff448-7nvrf 1/1 Running 0 10m loki-querier-89d4ff448-q89kh 1/1 Running 0 10m loki-query-frontend-678899db5-n5wc4 1/1 Running 0 10m loki-query-frontend-678899db5-tf69b 1/1 Running 0 10m loki-query-scheduler-7d666bf759-9xqb5 1/1 Running 0 10m loki-query-scheduler-7d666bf759-kpb5q 1/1 Running 0 10m loki-results-cache-0 2/2 Running 0 10m loki-ruler-0 1/1 Running 0 10m
查找 Loki 网关服务
Loki 网关服务是一个负载均衡器服务,将 Loki 网关暴露到互联网。这是您写入日志和查询日志的位置。默认情况下,NGINX 用作网关。
注意
Loki 网关服务暴露到互联网。在本教程中,我们使用用户名和密码提供基本身份验证。有关更多信息,请参阅身份验证文档。
要查找 Loki 网关服务,请运行以下命令
kubectl get svc -n loki
您应该看到带有外部 IP 地址的 Loki 网关服务。这是您用于写入和查询 Loki 的地址。
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
loki-gateway LoadBalancer 10.100.201.74 134.236.21.145 80:30707/TCP 46m
恭喜!您已成功使用 Helm Chart 在 Azure 上部署 Loki。在结束之前,让我们测试一下部署。
测试您的 Loki 部署
k6 是测试 Loki 部署的最快方法之一。这将使您能够写入和查询 Loki 中的日志。要开始使用 k6,请按照以下步骤操作
在您的本地机器上安装带有 Loki 扩展的 k6。请参阅安装 k6 和 xk6-loki 扩展。
创建一个包含以下内容的
azure-test.js
文件import {sleep, check} from 'k6'; import loki from 'k6/x/loki'; /** * URL used for push and query requests * Path is automatically appended by the client * @constant {string} */ const username = '<USERNAME>'; const password = '<PASSWORD>'; const external_ip = '<EXTERNAL-IP>'; const credentials = `${username}:${password}`; const BASE_URL = `http://${credentials}@${external_ip}`; /** * Helper constant for byte values * @constant {number} */ const KB = 1024; /** * Helper constant for byte values * @constant {number} */ const MB = KB * KB; /** * Instantiate config and Loki client */ const conf = new loki.Config(BASE_URL); const client = new loki.Client(conf); /** * Define test scenario */ export const options = { vus: 10, iterations: 10, }; export default () => { // Push request with 10 streams and uncompressed logs between 800KB and 2MB var res = client.pushParameterized(10, 800 * KB, 2 * MB); // Check for successful write check(res, { 'successful write': (res) => res.status == 204 }); // Pick a random log format from label pool let format = randomChoice(conf.labels["format"]); // Execute instant query with limit 1 res = client.instantQuery(`count_over_time({format="${format}"}[1m])`, 1) // Check for successful read check(res, { 'successful instant query': (res) => res.status == 200 }); // Execute range query over last 5m and limit 1000 res = client.rangeQuery(`{format="${format}"}`, "5m", 1000) // Check for successful read check(res, { 'successful range query': (res) => res.status == 200 }); // Wait before next iteration sleep(1); } /** * Helper function to get random item from array */ function randomChoice(items) { return items[Math.floor(Math.random() * items.length)]; }
将
<EXTERNAL-IP>
替换为 Loki 网关服务的外部 IP 地址。此脚本将向 Loki 写入日志并从 Loki 查询日志。它将以 800KB 到 2MB 之间的随机格式写入日志,并在最近 5 分钟内以随机格式查询日志。
运行测试
./k6 run azure-test.js
这将运行测试并输出结果。您应该看到测试正在向 Loki 写入日志并从 Loki 查询日志。
现在您已在 Microsoft Azure 上成功以微服务模式部署了 Loki,您可能希望探索以下内容