菜单
开源

在 AWS 上部署 Loki Helm Chart

本指南介绍了如何使用 Helm chart 在 AWS 上以微服务模式部署一个最小可用的 Loki。要完成本指南,您需要具备在 AWS 上部署资源的必要工具和权限,例如:

  • EKS (Amazon Elastic Kubernetes Service) 的完全访问权限
  • S3 (Amazon Simple Storage Service) 的完全访问权限
  • 创建 IAM (Identity Access Management) 角色和策略的足够权限

有两种方法可以将 Loki 认证并连接到 AWS S3。我们将引导您完成推荐的方法,即通过 IAM 角色授予访问权限。

注意事项

注意

本指南截至最近一次更新(2024 年 10 月 31 日)时是准确的。由于云提供商会频繁更新其服务和产品,因此最佳实践是在创建存储桶和分配角色之前,参考 AWS S3 文档

  • IAM 角色:本指南中创建的 IAM 角色是一个基本角色,允许 Loki 读取和写入 S3 存储桶。您可以根据您的需求添加更精细的权限。

  • 认证:Grafana Loki 带有一个基本的认证层。在此示例中,Loki 网关 (NGINX) 使用基本认证暴露在互联网上。NGINX 也可以替换为其他开源反向代理。更多信息请参阅认证

  • 数据保留:values.yaml 文件中,数据保留期设置为 28 天。您可以根据您的需求调整此设置。

  • 成本:在 AWS 上运行 Loki 将产生费用。请务必监控您的使用情况和成本,以避免任何意外账单。在本指南中,我们使用了一个包含 3 个节点和 m5.xlarge 实例的简单 EKS 集群。您可以根据您的工作负载调整实例类型和节点数量。

前提条件

  • Helm 3 或更高版本。请参阅安装 Helm。这应该安装在您的本地机器上。
  • 在 AWS 上运行的 Kubernetes 集群。一个简单的入门方法是使用 EKSctl。请参阅EKSctl 入门
  • Kubectl 安装在您的本地机器上。请参阅安装和设置 kubectl
  • (可选) AWS CLI 安装在您的本地机器上。请参阅安装 AWS CLI。如果您计划使用 EKSctl 创建 EKS 集群并在本地修改 IAM 角色和策略,则需要此工具。

EKS 最低要求

注意

这些 EKS 要求是使用本指南部署 Loki 所需的最低规格。您可以根据您的 AWS 环境和工作负载调整插件和实例类型。如果您选择这样做,我们无法保证此示例配置仍能满足您的需求。

在本指南中,我们使用 m5.xlarge 实例部署 Loki。这是在大多数场景下都适用的实例类型。但是,您可以根据您的具体需求修改实例类型和数量。

在 EKS 上部署 Loki 的最低要求是:

  • Kubernetes 版本 1.30 或更高。
  • EKS 集群需要 3 个节点。
  • 实例类型取决于您的工作负载。生产集群的良好起点是 m7i.2xlarge

本指南中使用的 EKSctl 集群配置文件如下:

yaml
# A simple example of ClusterConfig object:
---
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: <INSERT-CLUSTER-NAME>
  region: <INSERT-REGION-FOR-CLUSTER>
  version: "1.31"

iam:
  withOIDC: true

addons:
  - name: aws-ebs-csi-driver

managedNodeGroups:
  - name: loki-workers
    instanceType: m7i.2xlarge
    desiredCapacity: 3
    minSize: 2
    maxSize: 3
    amiFamily: AmazonLinux2023
    iam:
      withAddonPolicies:
        ebs: true
    volumeSize: 80
    volumeType: gp3
    ebsOptimized: true

EKS 集群中还必须安装以下插件:

  • Amazon EBS CSI Driver:使 Kubernetes 能够动态配置和管理 EBS 卷作为应用程序的持久存储。我们使用它为 Loki 提供节点卷。
  • CoreDNS:为 Kubernetes 集群提供内部 DNS 服务,确保服务和 Pod 可以使用 DNS 名称相互通信。
  • kube-proxy:维护节点上的网络规则,使集群内的 Pod 和服务能够相互通信。

您还必须在 EKS 集群上安装 OIDC (OpenID Connect) provider。这是 IAM 角色和策略正常工作所必需的。如果您使用 EKSctl,可以使用以下命令安装 OIDC provider:

提示

如果您使用上面的 EKSctl 配置文件创建集群,则无需运行此命令。OIDC provider 会自动安装。

bash
eksctl utils associate-iam-oidc-provider --cluster loki --approve

创建 S3 存储桶

警告

请勿使用默认存储桶名称;chunkruleradmin。为每个存储桶选择一个唯一的名称。更多信息请参阅以下安全更新

在部署 Loki 之前,您需要创建两个 S3 存储桶;一个用于存储日志(块),另一个用于存储警报规则。您可以使用 AWS 管理控制台或 AWS CLI 创建存储桶。存储桶名称必须是全局唯一的。

注意

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

bash
aws s3api create-bucket --bucket  <YOUR CHUNK BUCKET NAME e.g. `loki-aws-dev-chunks`> --region <S3 region your account is on, e.g. `eu-west-2`> --create-bucket-configuration LocationConstraint=<S3 region your account is on, e.g. `eu-west-2`> \
aws s3api create-bucket --bucket  <YOUR RULER BUCKET NAME e.g. `loki-aws-dev-ruler`> --region <S3 REGION your account is on, e.g. `eu-west-2`> --create-bucket-configuration LocationConstraint=<S3 REGION your account is on, e.g. `eu-west-2`>

请务必将 regionbucket 名称替换为您期望的值。稍后在本指南中,我们将再次讨论存储桶策略。

定义 IAM 角色和策略

将 Loki 连接到 AWS S3 的推荐方法是使用 IAM 角色。这种方法比在 Loki 配置中直接存储访问密钥和 secret 密钥更安全。可以使用 AWS CLI 或 AWS 管理控制台创建角色和策略。以下步骤展示了如何使用 AWS CLI 创建角色和策略。

  1. 创建一个新目录并导航到该目录。请确保在此目录中创建文件。本指南中的所有命令都假定您位于此目录中。

  2. 创建一个名为 loki-s3-policy.json 的文件,内容如下:

    json
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "LokiStorage",
                "Effect": "Allow",
                "Action": [
                    "s3:ListBucket",
                    "s3:PutObject",
                    "s3:GetObject",
                    "s3:DeleteObject"
                ],
                "Resource": [
                    "arn:aws:s3:::< CHUNK BUCKET NAME >",
                    "arn:aws:s3:::< CHUNK BUCKET NAME >/*",
                    "arn:aws:s3:::< RULER BUCKET NAME >",
                    "arn:aws:s3:::< RULER BUCKET NAME >/*"
                ]
            }
        ]
    }

    请确保将占位符替换为您之前创建的存储桶名称。

  3. 使用 AWS CLI 创建 IAM 策略

    bash
    aws iam create-policy --policy-name LokiS3AccessPolicy --policy-document file://loki-s3-policy.json
  4. 创建一个名为 trust-policy.json 的信任策略文档,内容如下:

    json
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Principal": {
                    "Federated": "arn:aws:iam::< ACCOUNT ID >:oidc-provider/oidc.eks.<INSERT REGION>.amazonaws.com/id/< OIDC ID >"
                },
                "Action": "sts:AssumeRoleWithWebIdentity",
                "Condition": {
                    "StringEquals": {
                        "oidc.eks.<INSERT REGION>.amazonaws.com/id/< OIDC ID >:sub": "system:serviceaccount:loki:loki",
                        "oidc.eks.<INSERT REGION>.amazonaws.com/id/< OIDC ID >:aud": "sts.amazonaws.com"
                    }
                }
            }
        ]
    }

    请务必将占位符替换为您的 AWS 帐户 ID、区域以及 OIDC ID(您可以在 EKS 集群配置中找到)。

  5. 使用 AWS CLI 创建 IAM 角色

    bash
    aws iam create-role --role-name LokiServiceAccountRole --assume-role-policy-document file://trust-policy.json
  6. 将策略附加到角色

    bash
    aws iam attach-role-policy --role-name LokiServiceAccountRole --policy-arn arn:aws:iam::<Account ID>:policy/LokiS3AccessPolicy

    请务必将占位符替换为您的 AWS 帐户 ID。

部署 Helm Chart

在部署 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 默认不带任何认证。由于我们将在 AWS 上部署 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:
   schemaConfig:
     configs:
       - from: "2024-04-01"
         store: tsdb
         object_store: s3
         schema: v13
         index:
           prefix: loki_index_
           period: 24h
   storage_config:
     aws:
       region: <S3 BUCKET REGION> # for example, eu-west-2  
       bucketnames: <CHUNK BUCKET NAME> # Your actual S3 bucket name, for example, loki-aws-dev-chunks
       s3forcepathstyle: false
   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: s3
   ruler:
    enable_api: true
    storage:
      type: s3
      s3:
        region: <S3 BUCKET REGION> # for example, eu-west-2
        bucketnames: <RULER BUCKET NAME> # Your actual S3 bucket name, for example, loki-aws-dev-ruler
        s3forcepathstyle: false
      alertmanager_url: http://prom:9093 # The URL of the Alertmanager to send alerts (Prometheus, Mimir, etc.)

   querier:
      max_concurrent: 4

   storage:
      type: s3
      bucketNames:
        chunks: "<CHUNK BUCKET NAME>" # Your actual S3 bucket name (loki-aws-dev-chunks)
        ruler: "<RULER BUCKET NAME>" # Your actual S3 bucket name (loki-aws-dev-ruler)
        # admin: "<Insert s3 bucket name>" # Your actual S3 bucket name (loki-aws-dev-admin) - GEL customers only
      s3:
        region: <S3 BUCKET REGION> # eu-west-2
        #insecure: false
      # s3forcepathstyle: false

serviceAccount:
 create: true
 annotations:
   "eks.amazonaws.com/role-arn": "arn:aws:iam::<Account ID>:role/LokiServiceAccountRole" # The service role you created

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

注意

请确保将占位符替换为您的实际值。

为 Loki 部署定义有效的 values.yaml 文件至关重要。为了消除配置错误的风险,让我们分解一下在部署到 AWS 时需要注意的配置选项:

  • Loki 配置 vs Values 配置

    • values.yaml 文件包含一个名为 loki 的部分,该部分直接表示 Loki 配置文件。
    • 此部分定义了 Loki 配置,包括 schema、存储和 querier 配置。
    • 对于 chunks 而言,需要关注的关键配置是 storage_config 部分,您可以在其中定义 S3 存储桶区域和名称。这会告诉 Loki 存储 chunks 的位置。
    • ruler 部分定义了 ruler 的配置,包括 S3 存储桶区域和名称。这会告诉 Loki 存储警报和记录规则的位置。
    • 有关完整的 Loki 配置,请参阅Loki 配置文档。
  • 存储

    • 定义 Helm chart 存储数据的位置。
    • 将类型设置为 s3,因为我们使用的是 Amazon S3。
    • 配置 chunks 和 ruler 的存储桶名称以匹配之前创建的存储桶。
    • s3 部分指定了存储桶的区域。
  • Service Account

    • serviceAccount 部分用于定义 Loki service account 的 IAM 角色。
    • 这是链接之前创建的 IAM 角色的地方。
  • 网关

    • 定义 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 的命名空间很重要,因为我们的信任策略设置为允许 loki 命名空间中的 loki service account 使用该 IAM 角色。这是可配置的,但请务必更新您的 service account。

  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 网关服务是一个 LoadBalancer 服务,它将 Loki 网关暴露给互联网。您将在这里写入日志和查询日志。默认使用 NGINX 作为网关。

注意

Loki 网关服务已暴露到互联网。在本教程中,我们使用用户名和密码提供了基本认证。更多信息请参阅认证文档。

要查找 Loki 网关服务,请运行以下命令:

bash
kubectl get svc -n loki

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

console
  NAME                             TYPE           CLUSTER-IP       EXTERNAL-IP                                                               PORT(S)              AGE
loki-gateway                     LoadBalancer   10.100.201.74    12345678975675456-1433434453245433545656563.eu-west-2.elb.amazonaws.com   80:30707/TCP         46m

恭喜!您已成功使用 Helm Chart 在 AWS 上部署了 Loki。在结束之前,让我们测试一下部署。

测试您的 Loki 部署

k6 是测试 Loki 部署的最快方法之一。它允许您向 Loki 写入日志并查询日志。要开始使用 k6,请按照以下步骤操作:

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

  2. 创建一个名为 aws-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 aws-test.js

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

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