news 2026/9/12 11:39:12

使用 Tanka/Ksonnet 在 Kubernetes 上部署 Loki:微服务架构、多可用区 Ingester 与生产级配置详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用 Tanka/Ksonnet 在 Kubernetes 上部署 Loki:微服务架构、多可用区 Ingester 与生产级配置详解

使用 Tanka/Ksonnet 在 Kubernetes 上部署 Loki:微服务架构、多可用区 Ingester 与生产级配置详解

【免费下载链接】lokiLike Prometheus, but for logs.项目地址: https://gitcode.com/GitHub_Trending/lok/loki

导读:本文以 production/ksonnet/README.md 为核心,系统讲解如何基于 Tanka(Ksonnet 的继任者)以声明式 Jsonnet 方式在 Kubernetes 上部署 Loki。文章覆盖 Tanka 环境初始化、jb依赖安装、loki + gateway的完整配置清单(存储后端、TSDB Schema、认证网关)、微服务各组件资源规格,以及 README 中专门给出的多可用区(Multizone)Ingester 配置——这是面向生产环境高可用部署的关键能力。读完本文,你将掌握用tk apply一键交付整套 Loki 微服务集群,并理解multi_zone_ingester_*系列参数背后真实的调度、副本与迁移语义。

背景:从 Ksonnet 到 Tanka,为什么 Loki 官方仍然维护 ksonnet 目录

Loki 在production/ksonnet目录下保留了一套完整的Jsonnet 部署清单(loki.libsonnet),它由 Grafana Labs 以 Ksonnet 时代的 Jsonnet 库形式维护。虽然 Ksonnet 项目本身已停止维护,但官方 Tanka 安装文档 明确指出:Tanka 是 Ksonnet 的重新实现,并且被 Grafana Labs 用来在生产环境运行 Grafana Loki。因此这套 ksonnet 库是"Tanka 部署 Loki"的一等公民资源,而非历史遗留。

Tanka 部署的运行模式是microservices mode(微服务模式),即每个 Loki 组件(distributor、ingester、querier、query-frontend、query-scheduler、ruler、compactor、index-gateway 等)以独立 Deployment/StatefulSet 运行,与单二进制模式相对。从 loki.libsonnet 的组合顺序可以看到完整的服务拓扑:

(import 'distributor.libsonnet') + (import 'ingester.libsonnet') + (import 'querier.libsonnet') + (import 'query-frontend.libsonnet') + (import 'ruler.libsonnet') + (import 'query-scheduler.libsonnet') + (import 'memcached.libsonnet') + (import 'overrides-exporter.libsonnet') + (import 'index-gateway.libsonnet') + (import 'shipper.libsonnet') + (import 'compactor.libsonnet') + (import 'multi-zone.libsonnet') + (import 'memberlist.libsonnet') +

前置条件:Tanka 与 jsonnet-bundler 的安装

官方要求Tanka v0.31.0 或更高版本(用于tk env系列命令),以及jb(jsonnet-bundler)v0.6.0 或更高版本来拉取 Jsonnet 依赖。在配置仓库中初始化一个 Tanka 应用:

mkdir <application name> cd <application name> tk init tk env add environments/loki --namespace=loki --server=<Kubernetes API server>

其中--server指向 Kube API Server 地址(如https://localhost:6443)。tk env add会生成environments/loki/环境目录,后续所有 Jsonnet 清单都写在这个目录下的main.jsonnet中。

认证提示:Loki 本身不内置任何认证层(官方文档明确说明)。必须在前置部署一个反向代理做认证(如 nginx),防止未授权访问。ksonnet 库中的gateway模块正是为这一目的设计的,详见下文"网关(gateway)模块"。

拉取 Loki 模块依赖

jb init # 如果已经执行过 tk init 则可跳过 jb install github.com/grafana/loki/production/ksonnet/loki@main

jb install会把 Loki 的 ksonnet 库及其传递依赖(ksonnet-util、kausal 库、consul mixin、jaeger-agent-mixin 等,见 production/ksonnet/loki/jsonnetfile.json)安装到vendor/目录。

最小可用配置:loki + gateway 组合

编辑environments/loki/main.jsonnet,将官方示例作为起点。下面是与 Tanka 官方文档一致的完整清单,并补充了各字段的取值说明:

local gateway = import 'loki/gateway.libsonnet'; local loki = import 'loki/loki.libsonnet'; loki + gateway { _config+:: { namespace: 'loki', htpasswd_contents: 'loki:$apr1$H4yGiGNg$ssl5/NymaGFRUvxIV1Nyr.', // 使用 TSDB shipper using_tsdb_shipper: true // 对象存储后端三选一:'s3'、'gcs'、'azure' storage_backend: 's3', // S3 变量(storage_backend = 's3' 时使用) s3_access_key: 'key', s3_secret_access_key: 'secret access key', s3_address: 'url', s3_bucket_name: 'loki-chunks', s3_bucket_region: 'us-east-1', s3_path_style: false, // GCS 变量(storage_backend = 'gcs' 时使用) // gcs_bucket_name: 'loki-chunks', // Azure 变量(storage_backend = 'azure' 时使用) // azure_container_name: 'loki-chunks', // azure_account_name: 'account', // azure_account_key: 'key', // TSDB 索引存储配置 loki+: { schema_config: { configs: [{ from: 'YYYY-MM-DD', store: 'tsdb', object_store: $._config.storage_backend, schema: 'v13', index: { prefix: '%s_index_' % $._config.table_prefix, period: '%dh' % $._config.index_period_hours, }, }], }, }, replication_factor: 3, memberlist_ring_enabled: true, }, }

关键配置项的语义

配置项默认值 / 取值范围说明
namespace必填(config.libsonnet 中error 'must define namespace'Kubernetes 命名空间,也是 Service DNS 名的组成部分
storage_backend必填,s3/gcs/azure决定object_store_configthanos_object_store_config的生成分支(见 config.libsonnet)
s3_path_stylefalse是否使用 path-style 访问 S3(自建 MinIO 等兼容对象存储通常需设为true
replication_factor默认3Ingester ring 副本因子,直接注入loki.ingester.lifecycler.ring.replication_factor
memberlist_ring_enabled默认false为所有 ring 启用 memberlist 而不再依赖 Consul,详见下文
using_tsdb_shippertrueTSDB shipper 模式,同时自动将 querier 切换为有状态部署(shipper.libsonnet 中stateful_queriers强制为true
index_period_hours默认24索引表周期(1 天),schema_configperiod字段由它生成
table_prefix默认取namespace索引表名前缀

关于from日期的生产建议

Tanka 官方文档特别强调:schema_config.configs[0].from表示该 schema 生效的第一天,建议设置为当前日期前 7 天以内(例如今天2021-01-15就设2021-01-08。原因是 Loki 默认只接受过去 1 周(168h)内的日志(由reject_old_samples_max_age控制,见 config.libsonnet 中的reject_old_samples: truereject_old_samples_max_age: '168h')。同时官方建议新装环境统一采用 TSDB(store: tsdbschema: v13)。

对象存储配置的三套后端

config.libsonnet 根据storage_backend自动生成object_store_config

  • S3:拼接s3://<access_key>:<secret>@<address>/<bucket>形式的 endpoint URL;若s3_access_key为空则生成无凭证 URL;s3_bucket_region非空时附带regions3forcepathstyles3_path_style控制。
  • GCSgcs.bucket_name来自gcs_bucket_name,且该字段在 config.libsonnet 中声明为必填(error 'must specify GCS bucket name')。
  • Azureazure.container_name/account_name必填,account_key非空才写入,官方注释建议通过环境变量注入密钥而非明文写入清单。

若设置use_thanos_objstore: true,则会额外生成thanos_object_store_config并注入storage_config.object_store,这也是 config.libsonnet 中use_thanos_objstore分支的用途。

部署、预览与清理

配置完成后执行:

tk show environments/loki # 渲染出即将部署的全部 Kubernetes 清单 tk apply environments/loki # 部署到集群 tk delete environments/loki # 从集群删除环境

tk show可先输出 YAML 供审查;所有清单由loki.libsonnet组合出的组件(gateway Deployment、distributor/querier Deployment、ingester StatefulSet、各 Service、PDB、ConfigMap、memcached、consul/memberlist 等)构成。

微服务组件的资源规格与高可用设计

各组件清单直接给出生产级默认参数,可结合源码核对:

  • ingester(ingester.libsonnet):StatefulSet 3 副本,挂载ingester-data(默认10GifastStorageClass)与ingester-wal(默认150Gi)两块 PVC;请求1 CPU/7Gi、限制2 CPU/14GiTerminationGracePeriodSeconds = 4800(80 分钟)以保障 TSDB block 与 WAL 落盘;readiness 探针走/ready
  • distributor(distributor.libsonnet):Deployment 3 副本,请求500m/2500Mi;默认启用 TopologySpreadConstraints(kubernetes.io/hostname,maxSkew=1,ScheduleAnyway)均匀打散;PDBmaxUnavailable=1
  • querier(querier.libsonnet):默认 Deployment 3 副本;在 TSDB shipper 模式下由 shipper.libsonnet 强制转为 StatefulSet,并为/data/tsdb-index/data/tsdb-cache挂载querier-dataPVC。
  • query-frontend / query-scheduler / ruler / compactor / index-gateway / memcached:分别由 query-frontend.libsonnet、query-scheduler.libsonnet、ruler.libsonnet、compactor.libsonnet、index-gateway.libsonnet、memcached.libsonnet 定义。缓存默认接入 memcached(chunk cache 与 query-range results cache 均指向memcached.<namespace>.svc.cluster.local)。

多可用区 Ingester(Multizone Ingesters):README 的核心专题

production/ksonnet/README.md 除指向 Tanka 安装文档外,专门给出多可用区 Ingester 的配置片段。这是 ksonnet 库面向生产高可用场景的核心能力:将 ingester 拆分为zone-azone-bzone-c三个分区,实现可用区感知复制(zone-aware replication)——当单个可用区故障时,写入与查询仍可通过其余区完成。

官方给出的配置片段

_config+: { multi_zone_ingester_enabled: false, multi_zone_ingester_migration_enabled: false, multi_zone_ingester_replicas: 0, multi_zone_ingester_max_unavailable: 25, }

(注意:README 中的数值为示意/默认态——enabled: false表示默认关闭该特性;启用时请按下文语义显式设置。)

参数语义与源码实现(multi-zone.libsonnet)

参数默认值语义
multi_zone_ingester_enabledfalse是否启用多可用区 ingester。启用后默认ingester_statefulset/ingester_service被移除,替换为三个 zone 的 StatefulSet
multi_zone_ingester_migration_enabledfalse迁移模式。为true时保留默认ingesterStatefulSet 与 Service,且 PDB 被设为maxUnavailable=0(迁移期间不允许 Kubernetes 终止任何 ingester 副本)
multi_zone_ingester_replicas3三个 zone 的副本总数,每个 zone 实际副本数 =ceil(replicas / 3)(见newIngesterZoneStatefulSet
multi_zone_ingester_max_unavailablemax(1, floor(replicas/9))滚动发布时允许的最大不可用副本数,写入rollout-max-unavailableannotation,由 rollout-operator 消费
multi_zone_ingester_replication_write_path_enabled/..._read_path_enabledtrue分别控制写入(distributor/ruler)与读取(querier)路径是否注入distributor.zone-awareness-enabled: true,开启 zone-aware 复制
multi_zone_ingester_use_topology_spreadfalse为 zone StatefulSet 添加 TopologySpreadConstraints(kubernetes.io/hostname,maxSkew=multi_zone_ingester_topology_spread_max_skew,whenUnsatisfiable=multi_zone_ingester_topology_spread_when_unsatisfiable
multi_zone_ingester_name_prefix'ingester-zone'zone StatefulSet 命名前缀,生成ingester-zone-a/b/c
multi_zone_ingester_exclude_defaultfalsetrue时向 distributor/ruler 注入distributor.excluded-zones: zone-default,将默认 zone 排除在复制之外
multi_zone_default_ingester_zonefalsetrue时给默认 ingester 容器注入ingester.availability-zone: zone-default

三个 zone 的生成逻辑

从 multi-zone.libsonnet 的源码结构可以看到:

  • 每个 zone(a/b/c)生成三件套:StatefulSetingester-zone-<zone>)、headless ServiceClusterIP: None,仅为提供 StatefulSet 的网络身份)、容器(通过ingester.availability-zone: zone-<zone>标志区分)。
  • zone StatefulSet 使用updateStrategy.type: OnDelete+rollout-group: ingester标签 +rollout-max-unavailableannotation,并配套ingester-rollout-pdbmaxUnavailable=1),交由rollout-operator做滚动发布管理(rollout-operator.libsonnet 中 DeploymentMaxSurge=0 / MaxUnavailable=1,保证同一时刻只有一个 operator 在运行)。
  • 默认启用 podAntiAffinity:同 zone 的多个副本可以调度到同一节点,但不同 zone 的副本不允许同节点(matchExpressions:rollout-group in [ingester]name notin [当前zone名],topologyKey 为 hostname)。这样单节点故障只影响一个 zone。
  • 启用 zone-aware 复制后,distributor/querier/ruler 均注入distributor.zone-awareness-enabled: true(对应 Loki 的distributor.zone-awareness-enabled配置,实现复制时优先选择不同 zone 的 ingester 副本)。

迁移路径:从单区到多可用区

multi-zone.libsonnet 对ingester_statefulsetingester_serviceingester_pdb的覆盖逻辑给出了清晰的迁移语义:

  1. 初始状态:multi_zone_ingester_enabled: false,运行默认ingesterStatefulSet。
  2. 开启迁移:multi_zone_ingester_enabled: truemulti_zone_ingester_migration_enabled: true—— 旧ingesterStatefulSet/Service 继续保留,PDB 强制maxUnavailable=0,同时三个 zone 的 StatefulSet 开始创建,数据逐步复制。
  3. 迁移完成:multi_zone_ingester_migration_enabled: false—— 默认ingesterStatefulSet/Service/PDB 被移除,流量完全由三个 zone 接管。

Ring 后端:memberlist 与 Consul 的选择

config.libsonnet 默认使用 Consul 作为所有 ring(ingester/distributor/ruler/pattern-ingester)的 KV store;当memberlist_ring_enabled: true时,memberlist.libsonnet 会将所有 ring 切换为 memberlist,并:

  • 通过 headless Servicegossip-ring.<namespace>.svc.cluster.local:7946(DNS+SRV)发现 gossip 成员;
  • 为 distributor/ingester/querier/ruler/compactor/query-scheduler/index-gateway 追加gossip-ring端口(7946)与loki_gossip_member: true标签;
  • 提供memberlist_cluster_label(默认<cluster>.<namespace>)与校验开关,防止跨集群 gossip 串扰;
  • 若未启用 migration,则彻底移除 consul 的 Deployment/Service/ConfigMap/RBAC 资源。

若从 Consul 平滑迁移到 memberlist,memberlist.libsonnet 还内置了multikv_migration_enabled/multikv_primary/multikv_secondary/multikv_mirror_enabled等参数,支持 primary-secondary 双 KV 存储的五步滚动迁移(先 multi 镜像、再交换主从、最后拆除)。

网关(gateway)模块:认证与路由

gateway.libsonnet 生成一个基于nginx:1.15.1-alpine的 3 副本 Deployment(gateway-secret 存放 htpasswd,gateway-config 渲染 nginx.conf),负责对外统一入口并完成 Basic Auth 与租户头注入:

  • location = /api/prom/pushlocation = /loki/api/v1/pushdistributor(写入路径);
  • location = /api/prom/taillocation = /loki/api/v1/tailquerier(WebSocket 升级支持);
  • 其余~ /api/prom/.*~ /loki/api/.*query-frontend(查询路径);
  • 每个请求注入X-Scope-OrgID(默认租户1,可用gateway_tenant_id覆盖),支持gateway_server_snippet追加自定义 server 指令。

日志采集:Grafana Alloy

Tanka 文档推荐的日志采集组件是 Grafana Alloy(替代已归档的 promtail)。在 Kubernetes 中安装 Alloy 后,将采集到的日志通过 gateway 的/loki/api/v1/push(或/api/prom/push)推送到本部署的 distributor 即可,具体安装步骤参见 Tanka 文档中引用的 Alloy 安装指南。

生产落地清单(Checklist)

  1. namespacestorage_backend(s3/gcs/azure)必须显式设置,否则 Jsonnet 求值直接报错(见 config.libsonnet 中的error断言)。
  2. 新装环境使用 TSDB:store: tsdbschema: v13,并设置using_tsdb_shipper: true
  3. schema_config.configs[0].from设为当前日期 7 天内,与reject_old_samples_max_age: 168h保持一致。
  4. 生产开启memberlist_ring_enabled: true免去 Consul 运维负担;如已有 Consul 依赖,按 memberlist 迁移五步走。
  5. 多可用区需求:置multi_zone_ingester_enabled: true,按需调multi_zone_ingester_replicasmulti_zone_ingester_max_unavailable,先以migration_enabled: true过渡再切换。
  6. 前置反向代理认证(gateway 已内置 htpasswd + nginx),牢记 Loki 无内置认证。

参考资源(仓库内)

  • 官方 Tanka 安装文档:docs/sources/setup/install/tanka.md
  • ksonnet 入口组合:production/ksonnet/loki/loki.libsonnet
  • 全局配置与默认值:production/ksonnet/loki/config.libsonnet
  • 多可用区实现:production/ksonnet/loki/multi-zone.libsonnet
  • Ring/memberlist 迁移:production/ksonnet/loki/memberlist.libsonnet
  • 网关 nginx 配置:production/ksonnet/loki/gateway.libsonnet
  • 组件规格:ingester / querier / distributor 见 production/ksonnet/loki/ingester.libsonnet、production/ksonnet/loki/querier.libsonnet、production/ksonnet/loki/distributor.libsonnet

【免费下载链接】lokiLike Prometheus, but for logs.项目地址: https://gitcode.com/GitHub_Trending/lok/loki

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 11:38:35

Python文件式与交互式编程模式详解及实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 11:37:02

从VSCode扩展到独立桌面应用:Electron + Vue 3架构改造实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 11:35:06

办公Agent实测:QwenWork与ChatGPT、Claude、扣子横向对比

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 11:33:41

安灯系统:制造业可视化管理与智能升级关键技术解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 11:33:33

Ansys与Comsol力磁耦合仿真技术对比与应用

1. 力磁耦合仿真技术概述 力磁耦合现象广泛存在于工程材料和结构中&#xff0c;特别是在铁磁材料中表现得尤为显著。当铁磁材料受到机械应力作用时&#xff0c;其磁化状态会发生变化&#xff1b;反之&#xff0c;当材料处于磁场环境中时&#xff0c;其力学性能也会受到影响。这…

作者头像 李华