菜单
开源

在 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 创建资源组

bash
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 集群

bash
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 集群,可以使用以下命令启用这些功能

bash
az aks update \
  --resource-group <MY_RESOURCE_GROUP_NAME> \
  --name <MY_AKS_CLUSTER_NAME> \
  --enable-workload-identity \
  --enable-oidc-issuer

Azure CLI 还允许您将 AKS 集群绑定到 kubectl。您可以通过运行以下命令来完成此操作

bash
az aks get-credentials --resource-group <MY_RESOURCE_GROUP_NAME> --name <MY_AKS_CLUSTER_NAME>

配置 Azure Blob Storage

提示

考虑使用唯一的存储桶名称,而不是:chunkruleradmin。尽管 Azure Blob Storage 不直接受此安全更新的影响,但为存储桶使用唯一的容器名称是一种最佳实践。

在部署 Loki 之前,您需要创建两个 Azure 存储容器;一个用于存储日志(chunk),第二个用于存储告警规则。您可以使用 Azure CLI 创建容器。容器必须存在于存储帐户中。

注意

GEL 客户将需要第三个容器来存储管理数据。OSS 用户不需要此容器。

  1. 创建一个存储帐户

    bash
    az storage account create \
    --name <NAME> \
    --location <REGION> \
    --sku Standard_ZRS \
    --encryption-services blob \
    --resource-group <MY_RESOURCE_GROUP_NAME>

    将占位符替换为您期望的值。

  2. 为 chunk 和 ruler 创建容器

    bash
    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 读取和写入。

  1. 找到 OpenID Connect (OIDC) 颁发者 URL

    bash
    az aks show \
    --resource-group <MY_RESOURCE_GROUP_NAME> \
    --name <MY_AKS_CLUSTER_NAME> \
    --query "oidcIssuerProfile.issuerUrl" \
    -o tsv

    此命令将返回 OIDC 颁发者 URL。您将需要此 URL 来创建联合身份凭证。

  2. 生成一个包含以下内容的 credentials.json 文件

    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。

  3. 请务必在继续之前保存 credentials.json 文件。

  4. 接下来生成一个 Azure 目录 app。我们将使用此应用来分配我们的联合身份凭证

    bash
     az ad app create \
     --display-name loki \
     --query appId \
     -o tsv

    这将返回应用 ID。保存此 ID 以备后用。如果您稍后需要查找应用 ID,可以运行以下命令

    bash
    az ad app list --display-name loki --query "[].appId" -o tsv
  5. 该应用需要一个服务主体来与 Azure AD 进行身份验证。为该应用创建服务主体

    bash
    az ad sp create --id <APP-ID>

    <APP-ID> 替换为您在上一步中生成的应用 ID。

  6. 接下来将联合身份凭证分配给该应用

    bash
    az ad app federated-credential create \
      --id <APP-ID> \
      --parameters credentials.json 

    <APP-ID> 替换为您在上一步中生成的应用 ID。

  7. 最后为该应用添加角色分配

    bash
    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

以下步骤需要使用 helmkubectl。确保您已运行 az 命令将您的 AKS 集群绑定到 kubectl

bash
az aks get-credentials --resource-group <MY_RESOURCE_GROUP_NAME> --name <MY_AKS_CLUSTER_NAME>

在部署 Loki Helm Chart 之前,我们需要将 Grafana Chart 仓库添加到 Helm 中。此仓库包含 Loki Helm Chart。

  1. 将 Grafana Chart 仓库添加到 Helm

    bash
    helm repo add grafana https://grafana.github.io/helm-charts
  2. 更新 Chart 仓库

    bash
    helm repo update
  3. 为 Loki 创建一个新的命名空间

    bash
    kubectl create namespace loki

Loki 基本身份验证

Loki 默认不带任何身份验证。由于我们将在 Azure 上部署 Loki 并将网关暴露到互联网,我们建议至少添加基本身份验证。在本指南中,我们将为 Loki 设置用户名和密码

  1. 首先,我们需要使用用户名和密码创建一个 .htpasswd 文件。您可以使用 htpasswd 命令创建该文件

    提示

    如果您没有安装 htpasswd 命令,可以根据您的操作系统使用 brewapt-getyum 进行安装。

    bash
    htpasswd -c .htpasswd <username>

    这将创建一个名为 auth 的文件,用户名为 loki。系统将提示您输入密码。

  2. 使用 .htpasswd 文件创建一个 Kubernetes Secret

    bash
    kubectl create secret generic loki-basic-auth --from-file=.htpasswd -n loki

    这将在 loki 命名空间中创建一个名为 loki-basic-auth 的 Secret。我们将在 Loki Helm Chart 配置中引用此 Secret。

  3. 为 Canary 创建一个 canary-basic-auth Secret

    bash
    kubectl 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 文件示例。

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。

  1. 使用新创建的 values.yaml 文件进行部署

    bash
    helm install --values values.yaml loki grafana/loki -n loki --create-namespace

    创建一个名为 loki 的命名空间非常重要,因为我们的联合身份凭证是使用值 system:serviceaccount:loki:loki 生成的。这对应于 loki 命名空间中的 loki 服务帐户。这是可配置的,但请务必先更新联合身份凭证文件。

  2. 验证部署

    bash
    kubectl get pods -n loki

    您应该看到 Loki pod 正在运行。

    console
    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 网关服务,请运行以下命令

bash
kubectl get svc -n loki

您应该看到带有外部 IP 地址的 Loki 网关服务。这是您用于写入和查询 Loki 的地址。

console
  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,请按照以下步骤操作

  1. 在您的本地机器上安装带有 Loki 扩展的 k6。请参阅安装 k6 和 xk6-loki 扩展

  2. 创建一个包含以下内容的 azure-test.js 文件

    JavaScript
     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 分钟内以随机格式查询日志。

  3. 运行测试

    bash
    ./k6 run azure-test.js

    这将运行测试并输出结果。您应该看到测试正在向 Loki 写入日志并从 Loki 查询日志。

现在您已在 Microsoft Azure 上成功以微服务模式部署了 Loki,您可能希望探索以下内容