news 2026/9/12 3:08:46

fhevm Listener Helm Chart 深度实战:多链区块链监听器与 eRPC 代理的 Kubernetes 部署指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
fhevm Listener Helm Chart 深度实战:多链区块链监听器与 eRPC 代理的 Kubernetes 部署指南

fhevm Listener Helm Chart 深度实战:多链区块链监听器与 eRPC 代理的 Kubernetes 部署指南

【免费下载链接】fhevmFHEVM, a full-stack framework for integrating Fully Homomorphic Encryption (FHE) with blockchain applications项目地址: https://gitcode.com/GitHub_Trending/fh/fhevm

导读

本文围绕 fhevm 仓库中的 Listener Helm Chart(charts/listener/)展开,系统讲解如何在 Kubernetes 上为每条区块链部署一个独立的 fhevm 区块链监听器(listener)实例,并通过共享的 PostgreSQL、Redis/RabbitMQ 基础设施与可选的 eRPC 代理组成一套完整的多链索引服务。读完本文,你将掌握:Listener Chart 的"三层深合并"配置体系(symlink +mergeOverwrite)、新增链的完整操作步骤、eRPC 代理的三种配置方式(profile 基底、局部覆盖、整体替换),以及 Secrets 的 External Secrets Operator 与 fallback 双模式接入方法,能够直接在生产或测试环境复制落地。

说明:本文所述配置文件、模板与默认值均以当前仓库实际内容为准。文中所有仓库相对路径均可直接点击跳转到源码。


一、架构总览:一链一实例,共享存储与消息队列

Listener Chart 的核心设计是每条链一个独立的 listener 实例,同时共享同一套后端基础设施。其部署拓扑如下:

+------------------+ | eRPC proxy | | (optional) | +--------+---------+ | +-------------------+-------------------+ | | +--------v---------+ +----------------v--------+ | listener:ethereum | | listener:base-sepolia | +--------+---------+ +----------------+--------+ | | +-------------------+-------------------+ | +--------------+--------------+ | | +--------v--------+ +--------v----------+ | PostgreSQL | | Redis / RabbitMQ | +-----------------+ +-------------------+

从 Helm 模板的实现看,这个架构图与代码完全对应:

  • values.yaml中的每个listeners[]条目会在 deployment.yaml 中各生成一个 Deploymentreplicas: 1),并在 configmap.yaml 中生成对应的 ConfigMap;
  • 所有 listener 实例共享同一套 PostgreSQL 数据库与 Redis/RabbitMQ 消息代理(broker);
  • eRPC 作为可选的 RPC 负载均衡/故障转移/缓存代理,位于所有 listener 之前,为其提供统一的上游 RPC 入口(如http://listener-erpc:4000/listener-indexer/evm/1)。

该 Chart 的版本信息见 Chart.yaml:version: 0.2.0appVersion: "0.2.0"type: application


二、前置条件与快速开始

2.1 环境要求

  • Helm 3.x
  • Kubernetes 1.24+

2.2 三步部署

helm dependency update charts/listener helm install listener charts/listener -n listener --create-namespace

第一步会拉取 Chart.yaml 中声明的子图表依赖(PostgreSQL、Redis、RabbitMQ 等 Bitnami 子图表);第二步在新建的listener命名空间中完成部署。由于values.yamllisteners默认为空列表,直接安装只会拉起基础设施与可选组件,实际监听链必须通过--set或自定义 values 文件添加listeners[]条目(详见第四节)。

2.3 命名规则

每个 listener 实例的 Deployment 与 ConfigMap 命名遵循<release>-<chart>-<listener.name>的拼接规则(超长时截断到 63 字符以保证 DNS 兼容),该逻辑定义在 _helpers.tpl 的listener.instanceName模板中。这意味着name字段直接决定了资源名,同一 Chart 内不可重复。


三、核心机制:symlink + 深合并(Config merge strategy)

Listener 与 eRPC 的配置都采用symlink + deep-merge模式,这是理解整个 Chart 的钥匙。

3.1 规范配置文件与符号链接

Listener 的规范配置文件(canonical config)存放在仓库根目录的 listener/config/ 下(例如 listener-default.yaml、erpc-base.yaml、erpc-public.yaml),并被符号链接进charts/listener/configs/

charts/listener/configs/ listener-default.yaml -> config/listener-default.yaml erpc-base.yaml -> config/erpc-base.yaml erpc-public.yaml -> config/erpc-public.yaml

当前仓库的 charts/listener/configs/ 目录下确实存在这三个文件。这个设计的价值在于:只要应用配置发生变化,Helm Chart 一定感知得到(因为打包的是同一份文件内容),从而强制要求 Chart 版本随配置同步递增。

3.2 模板如何加载配置

在 configmap.yaml 中可以看到完整的加载逻辑:

{{- $defaultConfig := .Files.Get "configs/listener-default.yaml" | fromYaml }} {{- $common := .Values.commonConfig | default dict }} ... {{- $perListener := $listener.config | default dict }} {{- $nameOverride := dict "name" $listener.name }} {{- $merged := mergeOverwrite (deepCopy $defaultConfig) $common $perListener $nameOverride }} {{- toYaml $merged | nindent 4 }}

核心是 Helm 内置的mergeOverwrite:依次将commonConfiglisteners[].config深合并到listener-default.yaml的默认值之上(后者覆盖前者,即 last wins),最后强制注入name字段,确保 listener 名称永远与实际条目一致、不会漂移。最终的 ConfigMap 数据挂载为/config/config.yaml,Deployment 通过args: ["--config", "/config/config.yaml"]传入 Rust 应用。

3.3 为什么要深合并而不是整体覆盖

从 config.rs 的Settings结构可以看出,Listener 的 Rust 配置是一个多层嵌套结构databasebrokerblockchaintelemetrylog),每个子结构又有大量字段。如果用简单的 YAML 替换,那么任何一层缺失都会导致整份配置失效;深合并允许只写"与默认值不同的键",其余自动继承——这正是 Helm 模板使用mergeOverwrite的根源。

补充:除了 YAML 文件,Rust 应用还支持环境变量覆盖,格式为APP_SECTION__FIELD(双下划线分隔),例如APP_DATABASE__DB_URLAPP_BROKER__BROKER_URL。见 config.rs 中Settings::new的实现,以及第五节 Secrets 的应用方式。


四、Listener 配置详解:三层深合并

Listener 配置由3 层深合并组成(后层覆盖前层):

层级来源作用
1. 基础默认值configs/listener-default.yaml对应 RustSettings结构体所有字段的默认值
2. 公共覆盖values.yamlcommonConfig面向所有 listener 的运维级覆盖(如 broker 类型)
3. 单链覆盖values.yamllisteners[].config链级专属值(chain_id、rpc_url 等)

其中第 1 层的 listener-default.yaml 内容非常完整,是配置的"单一事实来源",关键默认值如下:

name: listener http_port: 8080 database: db_url: "placeholder-overridden-by-env" migration_max_attempts: 5 iam_auth: # IAM 认证,enabled=false 时使用 db_url enabled: false ssl_ca_path: "placeholder-overridden-by-env" pool: max_connections: 12 min_connections: 2 acquire_timeout_secs: 30 idle_timeout_secs: 600 max_lifetime_secs: 1800 broker: broker_type: amqp # 默认 amqp,Chart 的 commonConfig 会覆盖为 redis broker_url: "placeholder-overridden-by-env" ensure_publish: false blockchain: type: evm chain_id: 1 rpc_url: "http://placeholder" network: placeholder finality_depth: 64 finality_tag: true # 使用节点 finalized 区块标签;false 时 final = head - finality_depth finality_active: true strategy: automatic_startup: true block_start_on_first_start: "current" range_size: 100 loop_delay_ms: 1000 max_parallel_requests: 50 block_fetcher: block_receipts batch_receipts_size_range: 10 compute_block: false compute_block_allow_skipping: true max_exponential_backoff_ms: 20000 catchup: prefetch: 5 claim_min_idle_secs: 3600 catchup_max_sub_range: 100 range_prefetch: 1 telemetry: enabled: true metrics_port: 9090 log: format: json show_file_line: false show_thread_ids: true show_timestamp: true show_target: true show_constants: true level: info

值得注意的实现细节:block_start_on_first_start支持"current"字符串或数字两种形式,这在 Rust 侧由BlockStartConfig枚举反序列化处理,见 config.rs 中的单元测试test_block_start_config_from_u64test_block_start_config_from_string_current;而StrategyConfig的默认值(range_size: 100max_parallel_requests: 50block_fetcher: BlockReceipts等)同样有test_strategy_config_defaults测试锚定,与 YAML 完全一致。

4.1 添加一条新链

values.yamllisteners[]中新增一个条目即可,只需声明与默认值不同的字段

listeners: - name: polygon config: blockchain: chain_id: 137 rpc_url: http://listener-erpc:4000/listener-indexer/evm/137 network: polygon-mainnet strategy: block_start_on_first_start: 70000000 range_size: 50 env: []

数据库、broker、连接池、策略等其余配置全部从基础文件 +commonConfig继承。

4.2 覆盖全局共享配置(commonConfig)

所有listener 生效的配置放在commonConfig,只需写与config/listener-default.yaml不同的键:

commonConfig: broker: broker_type: redis # 将默认 amqp 覆盖为 redis database: pool: max_connections: 20 # 高吞吐集群下提升连接池

values.yaml中默认的commonConfig正是{broker: {broker_type: redis}}——这也是生产环境最常用的"切换 broker 类型"场景。

4.3 单链局部覆盖(listeners[].config)

config块使用与 Rust 配置文件完全相同的嵌套结构,listener-default.yaml 中的任意字段都可按链覆盖。例如为 ethereum 主网开启消息持久化并调整最终性深度与拉取策略:

listeners: - name: ethereum config: broker: ensure_publish: true # 仅此链开启持久化投递 blockchain: chain_id: 1 rpc_url: http://listener-erpc:4000/listener-indexer/evm/1 network: ethereum-mainnet finality_depth: 128 strategy: block_start_on_first_start: 24572795 range_size: 10 max_parallel_requests: 10

4.4 单链资源与调度覆盖

每个 listener 可以独立覆盖资源配额、安全上下文与调度约束:

listeners: - name: ethereum config: { ... } resources: requests: cpu: "2" memory: 2Gi nodeSelector: dedicated: blockchain tolerations: - key: dedicated value: blockchain effect: NoSchedule

模板层面,Deployment 通过default $.Values.xxx $listener.xxx实现"per-listener 优先、否则继承根级"的语义(见 deployment.yaml),支持覆盖的字段包括resourcespodSecurityContextsecurityContextnodeSelectortolerationsaffinity以及env。其中环境变量的合并策略为:per-listener env 优先,同名字段覆盖根级 env,由 _helpers.tpl 中的listener.mergedEnv模板实现,且所有 value 均经过tpl渲染(因此可在 value 中引用如{{ .Values.secretName }})。

4.5 新增一个配置字段的标准流程

当 Rust 的Settings结构体新增字段时,Chart 侧需要同步的步骤为:

  1. config/listener-default.yaml中带上默认值新增该字段(这是config.rs之外的第二份权威声明);
  2. Helm Chart 通过 symlink 自动感知到该字段,无需修改模板;
  3. 由于结构相同,per-listener 覆盖立即生效;
  4. 递增Chart.yamlversion(当前为0.2.0)。

这条流程之所以顺畅,正是因为模板中的 3 层合并对字段的增删是透明的——mergeOverwrite只关心键路径,不关心字段清单。

4.6 部署回滚保障:配置校验和

deployment.yaml 中为每个 listener Pod 注入了checksum/config注解:

checksum/config: {{ printf "%s%s%s" (default文件) (commonConfig) (listener.config) | sha256sum }}

只要三层配置中的任何一层发生变化,Pod 模板的注解随之变化,Kubernetes 会自动滚动重建 listener Pod,确保配置变更不会"静默失效"。


五、eRPC 代理:可选的 RPC 网关

eRPC 是一个可选组件,为 listener 提供 RPC 负载均衡、故障转移与缓存能力。Chart 内联部署一个 eRPC Deployment(官方并无独立 Helm Chart),相关模板见 deployment.yaml 后半部分与 configmap.yaml。

5.1 配置 Profile

eRPC 通过erpc.baseConfig字段选择基础配置文件,当前 Chart 内置两个 profile:

Profile文件适用场景
erpc-base.yamlconfigs/erpc-base.yaml最小化默认配置,面向通用应用的独立 eRPC(默认值)
erpc-public.yamlconfigs/erpc-public.yaml面向 listener 集群调优、使用公共 RPC 节点
erpc: enabled: true baseConfig: erpc-base.yaml # 或改用 erpc-public.yaml

两个 profile 的定位差异在内容上体现得很明显:

  • erpc-base.yaml 只包含 server、metrics、rate limiters 与一个通用projects[0].id: main骨架,networks: []为空,由使用者自行补充网络与上游;
  • erpc-public.yaml 则是一份高度调优的"公共节点专供"配置:logLevel: warnserver.maxTimeout: 20s(需覆盖 ethereum receipts 的 3 上游 × 5s 预算)、全部走 eRPC 公共端点仓库、按方法(eth_blockNumbereth_getBlockByNumbereth_getBlockReceipts等)细分 timeout/retry/hedge/circuitBreaker 策略,并为 avalanche/binance/ethereum/polygon/base/sepolia/fuji/bsc-testnet/amoy/base-sepolia 预置了网络定义、评分权重与 selectionPolicy 过滤函数(如 sepolia 与 base-sepolia 用 metrics 实时剔除 errorRate/ throttledRate/blockHeadLag 超限的上游)。

5.2 新增一个 eRPC Profile

# 1. 在仓库根目录 config/ 下创建配置文件 # config/erpc-<profile>.yaml # 2. 建立符号链接(在仓库根目录执行) ln -s ../../../config/erpc-<profile>.yaml charts/listener/configs/erpc-<profile>.yaml # 3. 部署时通过 --set 指定 helm install listener charts/listener --set erpc.baseConfig=erpc-<profile>.yaml

5.3 局部覆盖(Partial overrides)

erpc.config会在基础 profile 之上做深合并,不会整体替换基础配置:

erpc: baseConfig: erpc-public.yaml config: logLevel: info server: maxTimeout: 60s

对应模板逻辑为mergeOverwrite $base $overrides(见 configmap.yaml)。

5.4 整体替换(Full replacement)

需要完全绕过基础 profile 与erpc.config时,使用--set-file传入完整配置文件:

helm install listener charts/listener \ --set-file erpc.configFile=path/to/custom-erpc.yaml

5.5 禁用 eRPC

erpc: enabled: false

禁用后,listener 的rpc_url应直接指向你自己的 RPC 服务商端点,例如https://eth-mainnet.example.com,而不再走http://listener-erpc:4000/...

5.6 eRPC 启动参数

一个易踩的坑:eRPC 镜像的入口是erpc,其配置文件路径以位置参数传入。Chart 默认传入args: ["/config/erpc.yaml"](指向 ConfigMap 挂载点),否则 eRPC 会去搜索内置的硬编码路径列表(如/home/nonroot/erpc.yaml/erpc.yaml等),导致挂载的配置被静默忽略、代理以默认公共端点启动。相关注释与默认值均记录在 values.yaml 的erpc.args处。


六、Secrets:敏感信息注入的两种模式

数据库 URL、broker URL 等敏感值通过环境变量引用 Kubernetes Secret注入(对应 config.rs 的环境变量覆盖机制)。Chart 支持两种模式。

6.1 使用 External Secrets Operator(默认)

externalSecret: enabled: true # 假定名为 "listener-secrets" 的 Secret 已存在 secretName: listener-secrets

此模式下 Chart不渲染任何 Secret 资源,Pod 直接引用外部已存在的 Secret(无论是 ESO 创建还是手工创建)。values.yaml默认通过envvalueFrom.secretKeyRef注入APP_DATABASE__DB_URL

env: - name: APP_DATABASE__DB_URL valueFrom: secretKeyRef: name: "database-credentials" key: database-url

6.2 不使用 External Secrets Operator(fallback)

externalSecret: enabled: false fallbackSecret: name: listener-secrets data: database-url: "postgres://postgres:postgres@listener-postgresql:5432/listener" broker-url: "redis://listener-redis-master:6379"

此时 secret.yaml 模板会渲染一个Opaque类型的 Secret,将fallbackSecret.data作为stringData写入,供环境变量引用。两条判断逻辑可以在模板中验证:{{- if not .Values.externalSecret.enabled }}才渲染 fallback Secret。


七、子图表依赖(Sub-chart dependencies)

Chart 通过helm dependency管理三个可选基础设施子图表:

依赖默认关闭方式
PostgreSQL启用postgresql.enabled: false
Redis启用redis.enabled: false
RabbitMQ禁用rabbitmq.enabled: true

将对应子图表enabled: false后即可接入外部托管的同类型服务,此时只需保证fallbackSecret.data(或 ESO Secret)中的database-url/broker-url指向外部地址即可。子图表的具体配置项参考 Bitnami 官方 Chart 文档。


八、Values Reference 完整参考

下表完整继承自 README.md,并结合 values.yaml 的实际默认值做了校正与补充:

Key默认值说明
image.repositoryhub.zama.org/ghcr/zama-ai/fhevm/listener/listener-coreListener 容器镜像(README 中记载的ghcr.io/zama-ai/listener为历史值,以 values.yaml 实际值为准)
image.tag""(回退到 appVersion)镜像 tag 覆盖
commonConfig{broker: {broker_type: redis}}共享配置覆盖(在基础默认值之上合并)
listeners[](values.yaml 实际为空,README 示例含 ethereum、base-sepolia 两条)按链拆分的 listener 实例
listeners[].name-链名(决定 Deployment/ConfigMap 命名)
listeners[].config{}链级配置覆盖(与 Rust 配置结构一致)
listeners[].env[]单链环境变量覆盖
listeners[].resources继承根级resources单链资源覆盖
secretNamelistener-secrets存放敏感值的 K8s Secret 名称
envAPP_DATABASE__DB_URL引用database-credentials共享环境变量(合并进所有 listener Pod)
podSecurityContextrunAsNonRoot: true+runAsUser: 10000+seccompProfile: RuntimeDefaultPod 级安全上下文
securityContextreadOnlyRootFilesystem+capabilities.drop: [ALL]+seccompProfile: RuntimeDefault容器级安全上下文
resourcesrequests/limits 均为cpu: "1"memory: 1Gi默认资源配额
metrics.enabledtrue是否暴露 Prometheus 指标端口
metrics.path/metrics指标抓取路径
metrics.serviceMonitor.enabledfalse是否生成 ServiceMonitor(interval 30s、scrapeTimeout 10s)
erpc.enabledfalse(values.yaml 实际值;README 表格记为true是否部署 eRPC 代理
erpc.baseConfigerpc-base.yamleRPC 基础配置 profile
erpc.config{}在基础配置之上深合并的局部覆盖
erpc.configFile""整体替换配置(通过--set-file
erpc.replicas1eRPC 副本数
erpc.image.repository/tagghcr.io/erpc/erpc/0.0.63eRPC 镜像
erpc.args["/config/erpc.yaml"]eRPC 启动参数(指向挂载的 ConfigMap)
erpc.service.httpPort4000eRPC HTTP 端口
erpc.service.metricsPort4001eRPC Prometheus 指标端口
erpc.podSecurityContextnonroot +seccompProfile: RuntimeDefaulteRPC Pod 级安全上下文
erpc.securityContextreadOnlyRoot + capDropAll +seccompProfile: RuntimeDefaulteRPC 容器级安全上下文
erpc.resourcesrequests 250m/256Mi,limits 1/512MieRPC 资源配额
externalSecret.enabledtrue使用已存在的 Secret(ESO 或手工)
fallbackSecret.namelistener-secretsESO 禁用时渲染的 Secret 名称
fallbackSecret.data{}ESO 禁用时的 Secret 数据
postgresql.enabledtrue是否部署 PostgreSQL 子图表
redis.enabledtrue是否部署 Redis 子图表
rabbitmq.enabledfalse是否部署 RabbitMQ 子图表

安全上下文默认值说明:seccompProfile.type: RuntimeDefault是满足 Pod Security Standard "restricted (strict)" 级别以及 Kyvernorestrict-seccomp-strict策略的必要条件,相关设计注释详见 values.yaml。


九、与 fhevm 生态的衔接

Listener 是整个 fhevm 全栈框架(Fully Homomorphic Encryption + blockchain)中的数据入口组件之一。它与仓库中 listener/crates/ 下的 Rust 实现(listener_coresharedconsumer等 crate)一一对应:Chart 的每一层配置最终都会落到 RustSettings结构体(config.rs)的字段上,而strategy.block_fetcher: block_receiptsbatch_receipts_size_range等参数则直接控制着 listener 核心的区块拉取与回执处理逻辑。若需要深入理解参数背后的行为,可以沿着 listener-default.yaml 的每个键在 listener_core 中溯源对应实现。


十、部署后的验证与排障建议

  1. 校验渲染结果helm template listener charts/listener -f my-values.yaml可以离线检查三层合并后的最终 ConfigMap 与 Secret 内容是否符合预期;
  2. 确认配置生效:查看 listener Pod 挂载的/config/config.yaml是否为预期合并结果(合并逻辑见 configmap.yaml);
  3. 检查 Secret 引用:若使用 ESO 模式,务必先确认名为listener-secrets的 Secret 已存在,否则 Pod 将因secretKeyRef解析失败而无法启动;
  4. eRPC 配置是否被读取:确认 Deployment 的args包含/config/erpc.yaml,避免 eRPC 以默认配置静默启动(见 5.6 节);
  5. 观测指标:listener 的 metrics 端口来自配置合并链telemetry.metrics_port(默认 9090),由 _helpers.tpl 中的listener.metricsPort模板动态推导;eRPC 指标端口为 4001,均可通过 ServiceMonitor 接入 Prometheus。

以上所有配置项、模板逻辑与默认值均可在本仓库对应路径中逐一核对,建议结合自身链的区块高度、RPC 限流与最终性要求,在 listener-default.yaml 的默认值基础上做针对性调优。

【免费下载链接】fhevmFHEVM, a full-stack framework for integrating Fully Homomorphic Encryption (FHE) with blockchain applications项目地址: https://gitcode.com/GitHub_Trending/fh/fhevm

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

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

基于PyTorch全连接神经网络的温度回归预测实战

简介&#xff1a;面向天气温度回归预测这一典型连续值预测场景&#xff0c;该项目基于Pytorch构建全连接神经网络&#xff0c;采用Adam优化器完成模型训练与温度拟合。代码源自个人大作业&#xff0c;评审分达95分以上&#xff0c;经过严格调试可直接运行&#xff0c;适合有一定…

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

Godot 4.3.4安装汉化与首个2D场景实操指南

/* 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 3:05:45

Flutter跨平台开发实战:从小众景点App到鸿蒙适配全流程复盘

去年底我接了个挺有意思的项目&#xff1a;做一款专门挖掘城市周边小众景点的 App。需求听起来简单&#xff0c;但有个关键约束——除了 Android 和 iOS&#xff0c;客户还要求适配鸿蒙系统。团队里有人提议三个平台各写一套原生代码&#xff0c;我算了一笔账&#xff1a;三套代…

作者头像 李华