From ee08594651c7ef1fa0facabaa5ac5516ca658d49 Mon Sep 17 00:00:00 2001 From: whg517 Date: Mon, 24 Aug 2026 16:39:03 +0800 Subject: [PATCH 1/2] docs(core-concepts): write the authentication page Replaces a one-line placeholder. Taken from operator-go's pkg/apis/authentication/v1alpha1 for the CRD and every provider's fields and defaults, and from trino-operator for the product-side shape and for which providers are actually implemented. Covers AuthenticationClass being cluster-scoped, the five providers, and per-provider detail: the static Secret indirection, LDAP bind credentials (user/password keys) with the ldapFieldNames defaults and the note that Active Directory needs them overridden, OIDC with its required principalClaim and providerHint, and the client credentials (CLIENT_ID/CLIENT_SECRET) that belong to the product rather than the class. Two things the schema does not tell you, both documented: Nothing enforces one provider per class. All five fields are optional and there is no XValidation, so a class setting both oidc and ldap is accepted; products take the first match in a fixed order and ignore the rest. Trino's order is oidc, static, ldap. Product support is a subset of the API. Trino implements oidc, static and ldap; a class whose provider is tls or kerberos yields no authenticator at all, and nothing rejects it at apply time. Co-Authored-By: Claude Opus 5 --- docs/core-concepts/security/authentication.md | 248 +++++++++++++++++- .../core-concepts/security/authentication.md | 241 ++++++++++++++++- 2 files changed, 485 insertions(+), 4 deletions(-) diff --git a/docs/core-concepts/security/authentication.md b/docs/core-concepts/security/authentication.md index 662cbac2..96c3866a 100644 --- a/docs/core-concepts/security/authentication.md +++ b/docs/core-concepts/security/authentication.md @@ -1,3 +1,247 @@ -# Authentication +--- +title: Authentication +--- -TODO +Authentication in Kubedoop is split in two. An `AuthenticationClass` describes *how* to +authenticate — an LDAP server, an OIDC issuer, a static list of users — once, for the whole +cluster. A product then names the class it wants to use. The identity provider is configured in one +place, and any number of clusters point at it. + +## AuthenticationClass + +`AuthenticationClass` belongs to the `authentication.kubedoop.dev/v1alpha1` API group and is +**cluster-scoped**, so it has no namespace and is visible to every product in the cluster. Its short +name is `authclass`: + +```bash +kubectl get authclass +``` + +The spec is a single `provider` block naming one mechanism: + +```yaml +apiVersion: authentication.kubedoop.dev/v1alpha1 +kind: AuthenticationClass +metadata: + name: ldap +spec: + provider: + ldap: + hostname: openldap.default.svc.cluster.local + port: 389 + searchBase: ou=users,dc=example,dc=com + bindCredentials: + secretClass: ldap-bind +``` + +| Provider | Describes | +|----------|-----------| +| `static` | A Secret holding user credentials | +| `ldap` | An LDAP or Active Directory server | +| `oidc` | An OpenID Connect issuer | +| `tls` | Client-certificate authentication | +| `kerberos` | A Kerberos realm | + +### Set exactly one provider + +All five fields are optional in the schema and **nothing rejects a class that sets several, or +none**. Products resolve the provider by checking fields in a fixed order and taking the first +match, so a class with both `oidc` and `ldap` authenticates via OIDC and silently ignores the LDAP +block. Trino, for example, checks `oidc`, then `static`, then `ldap`. + +Treat "exactly one provider per class" as a rule you enforce yourself. Two mechanisms means two +classes. + +### Not every product supports every provider + +The API defines five providers; a given operator implements the subset that makes sense for its +product. Trino handles `oidc`, `static` and `ldap`. Pointing a Trino cluster at a class whose +provider is `tls` or `kerberos` yields no authenticator at all, without a rejection at apply time. + +Check the operator's own documentation before assuming a provider is wired up. + +## Referencing a class from a product + +Products take the class by name. Trino accepts a list, so a cluster can offer more than one method: + +```yaml +apiVersion: trino.kubedoop.dev/v1alpha1 +kind: TrinoCluster +metadata: + name: trino +spec: + clusterConfig: + authentication: + - authenticationClass: ldap +``` + +Because the class is cluster-scoped, `authenticationClass` is just a name — there is no namespace to +qualify. + +## static + +The simplest provider: a Secret in the product's namespace holding user credentials. + +```yaml +spec: + provider: + static: + userCredentialsSecret: + name: trino-users +``` + +The keys inside that Secret are **product-specific** — each product reads the format its own +authentication mechanism expects, so consult the operator's documentation for the layout. The +`AuthenticationClass` only carries the Secret's name. + +## ldap + +```yaml +spec: + provider: + ldap: + hostname: openldap.default.svc.cluster.local + port: 389 + searchBase: ou=users,dc=example,dc=com + searchFilter: "" + bindCredentials: + secretClass: ldap-bind + ldapFieldNames: + uid: uid + group: memberof + email: mail + givenName: givenName + surname: sn +``` + +| Field | Required | Default | +|-------|----------|---------| +| `hostname` | yes | — | +| `port` | no | `389`, or `636` when `tls` is set | +| `bindCredentials` | yes | — | +| `searchBase` | no | `""` | +| `searchFilter` | no | `""` | +| `ldapFieldNames` | no | see below | +| `tls` | no | — | + +`bindCredentials.secretClass` names a SecretClass whose Secret must contain two keys: + +| Key | Meaning | +|-----|---------| +| `user` | Bind DN, for example `cn=admin,dc=example,dc=com` | +| `password` | Bind password | + +`ldapFieldNames` maps Kubedoop's notion of a user attribute onto your directory's schema. The +defaults suit a standard OpenLDAP layout: + +| Field | Default | +|-------|---------| +| `uid` | `uid` | +| `group` | `memberof` | +| `email` | `mail` | +| `givenName` | `givenName` | +| `surname` | `sn` | + +Active Directory uses different attribute names — `sAMAccountName` rather than `uid`, typically — +so an AD-backed class will need these set explicitly. + +## oidc + +```yaml +spec: + provider: + oidc: + hostname: keycloak.default.svc.cluster.local + port: 8080 + rootPath: /realms/kubedoop + principalClaim: preferred_username + providerHint: keycloak + scopes: + - openid + - email +``` + +| Field | Required | Default | +|-------|----------|---------| +| `hostname` | yes | — | +| `port` | no | — | +| `principalClaim` | yes | — | +| `providerHint` | yes | — | +| `rootPath` | no | `/` | +| `scopes` | no | — | +| `tls` | no | — | + +`principalClaim` is the claim in the ID token the product treats as the username. + +**`providerHint` currently accepts only `keycloak`.** It is a required field with an enumerated +value, so any other issuer is rejected at apply time. Keycloak is the supported OIDC issuer today. + +### Client credentials live with the product, not the class + +The `AuthenticationClass` describes the issuer. The client ID and secret belong to the individual +cluster, so they are supplied where the class is referenced: + +```yaml +spec: + clusterConfig: + authentication: + - authenticationClass: keycloak + oidc: + clientCredentialsSecret: trino-oidc-client + extraScopes: + - profile +``` + +That Secret must contain: + +| Key | +|-----| +| `CLIENT_ID` | +| `CLIENT_SECRET` | + +They are passed into the pod as environment variables. + +## tls and kerberos + +```yaml +spec: + provider: + tls: + clientCertSecretClass: trino-client-tls +``` + +```yaml +spec: + provider: + kerberos: + kerberosStorageClass: kerberos +``` + +`tls` authenticates clients by the certificate they present, issued by the named SecretClass. +`kerberos` points at the StorageClass backing Kerberos credential delivery. Support for both is +product-dependent — see the note above. + +## TLS verification + +`ldap` and `oidc` both accept a `tls` block, and when present its `verification` is **required**: + +```yaml +tls: + verification: + server: + caCert: + secretClass: tls +``` + +| `verification` | Behaviour | +|----------------|-----------| +| `server.caCert.secretClass` | Verify against the CA published by that SecretClass | +| `server.caCert.webPki: {}` | Verify against the system's public CA bundle | +| `none: {}` | Do not verify the certificate | + +Setting `tls` on an LDAP provider also moves the default port from 389 to 636. + +## Related + +- [Roles and role groups](../common-configuration-mechanisms/roles-and-role-groups.md) +- [S3](../resources/s3.md) diff --git a/i18n/zh/docusaurus-plugin-content-docs/current/core-concepts/security/authentication.md b/i18n/zh/docusaurus-plugin-content-docs/current/core-concepts/security/authentication.md index 662cbac2..05d24df5 100644 --- a/i18n/zh/docusaurus-plugin-content-docs/current/core-concepts/security/authentication.md +++ b/i18n/zh/docusaurus-plugin-content-docs/current/core-concepts/security/authentication.md @@ -1,3 +1,240 @@ -# Authentication +--- +title: 认证 +--- -TODO +Kubedoop 把认证拆成两半。`AuthenticationClass` 描述**怎么认证**——一个 LDAP 服务器、一个 OIDC +签发方、一份静态用户名单——在整个集群范围内只定义一次。产品则指名它要用哪个 class。 +身份提供方只配置在一处,任意多个集群都可以指向它。 + +## AuthenticationClass + +`AuthenticationClass` 属于 `authentication.kubedoop.dev/v1alpha1` API 组,是**集群级**资源, +因此没有命名空间,对集群里所有产品可见。它的简称是 `authclass`: + +```bash +kubectl get authclass +``` + +spec 就是一个 `provider` 块,指明一种认证机制: + +```yaml +apiVersion: authentication.kubedoop.dev/v1alpha1 +kind: AuthenticationClass +metadata: + name: ldap +spec: + provider: + ldap: + hostname: openldap.default.svc.cluster.local + port: 389 + searchBase: ou=users,dc=example,dc=com + bindCredentials: + secretClass: ldap-bind +``` + +| Provider | 描述 | +|----------|------| +| `static` | 存放用户凭据的 Secret | +| `ldap` | LDAP 或 Active Directory 服务器 | +| `oidc` | OpenID Connect 签发方 | +| `tls` | 客户端证书认证 | +| `kerberos` | Kerberos 域 | + +### 请只设置一个 provider + +五个字段在 schema 里都是可选的,**同时设置多个或一个都不设,都不会被拒绝**。产品按固定顺序检查 +字段并取第一个命中项,所以同时写了 `oidc` 和 `ldap` 的 class 会走 OIDC,而 LDAP 块被静默忽略。 +以 Trino 为例,它的检查顺序是 `oidc` → `static` → `ldap`。 + +请把"每个 class 只配一个 provider"当成需要自己遵守的纪律。两种机制就建两个 class。 + +### 并非每个产品都支持全部 provider + +API 定义了五种 provider,具体某个 Operator 只实现对该产品有意义的子集。Trino 支持 `oidc`、 +`static` 和 `ldap`。把 Trino 集群指向一个 provider 为 `tls` 或 `kerberos` 的 class, +结果是完全拿不到认证器,而且 apply 时不会报错。 + +在假定某个 provider 已接通之前,请先查阅对应 Operator 的文档。 + +## 在产品中引用 class + +产品按名字引用 class。Trino 接受一个列表,因此一个集群可以同时提供多种认证方式: + +```yaml +apiVersion: trino.kubedoop.dev/v1alpha1 +kind: TrinoCluster +metadata: + name: trino +spec: + clusterConfig: + authentication: + - authenticationClass: ldap +``` + +由于 class 是集群级资源,`authenticationClass` 只是一个名字——不需要也无法加命名空间限定。 + +## static + +最简单的 provider:产品所在命名空间里一个存放用户凭据的 Secret。 + +```yaml +spec: + provider: + static: + userCredentialsSecret: + name: trino-users +``` + +该 Secret 内部的键是**因产品而异**的——每个产品按自己认证机制期望的格式去读, +具体结构请查阅对应 Operator 的文档。`AuthenticationClass` 只负责携带这个 Secret 的名字。 + +## ldap + +```yaml +spec: + provider: + ldap: + hostname: openldap.default.svc.cluster.local + port: 389 + searchBase: ou=users,dc=example,dc=com + searchFilter: "" + bindCredentials: + secretClass: ldap-bind + ldapFieldNames: + uid: uid + group: memberof + email: mail + givenName: givenName + surname: sn +``` + +| 字段 | 必填 | 默认值 | +|------|------|--------| +| `hostname` | 是 | — | +| `port` | 否 | `389`,设置了 `tls` 时为 `636` | +| `bindCredentials` | 是 | — | +| `searchBase` | 否 | `""` | +| `searchFilter` | 否 | `""` | +| `ldapFieldNames` | 否 | 见下 | +| `tls` | 否 | — | + +`bindCredentials.secretClass` 指向的 SecretClass,其 Secret 必须包含两个键: + +| 键 | 含义 | +|----|------| +| `user` | 绑定 DN,例如 `cn=admin,dc=example,dc=com` | +| `password` | 绑定密码 | + +`ldapFieldNames` 把 Kubedoop 认知中的用户属性映射到你的目录 schema 上。默认值适配标准 +OpenLDAP 布局: + +| 字段 | 默认值 | +|------|--------| +| `uid` | `uid` | +| `group` | `memberof` | +| `email` | `mail` | +| `givenName` | `givenName` | +| `surname` | `sn` | + +Active Directory 使用的属性名不同——通常是 `sAMAccountName` 而非 `uid`—— +因此对接 AD 的 class 需要显式设置这些字段。 + +## oidc + +```yaml +spec: + provider: + oidc: + hostname: keycloak.default.svc.cluster.local + port: 8080 + rootPath: /realms/kubedoop + principalClaim: preferred_username + providerHint: keycloak + scopes: + - openid + - email +``` + +| 字段 | 必填 | 默认值 | +|------|------|--------| +| `hostname` | 是 | — | +| `port` | 否 | — | +| `principalClaim` | 是 | — | +| `providerHint` | 是 | — | +| `rootPath` | 否 | `/` | +| `scopes` | 否 | — | +| `tls` | 否 | — | + +`principalClaim` 指定 ID token 中哪个 claim 被产品当作用户名。 + +**`providerHint` 目前只接受 `keycloak`。** 它是必填且带枚举约束的字段,因此填其他签发方会在 +apply 阶段直接被拒绝。当前受支持的 OIDC 签发方就是 Keycloak。 + +### 客户端凭据属于产品,不属于 class + +`AuthenticationClass` 描述的是签发方。客户端 ID 和 secret 属于具体集群, +因此在引用 class 的地方提供: + +```yaml +spec: + clusterConfig: + authentication: + - authenticationClass: keycloak + oidc: + clientCredentialsSecret: trino-oidc-client + extraScopes: + - profile +``` + +该 Secret 必须包含: + +| 键 | +|----| +| `CLIENT_ID` | +| `CLIENT_SECRET` | + +它们会以环境变量的形式注入 Pod。 + +## tls 与 kerberos + +```yaml +spec: + provider: + tls: + clientCertSecretClass: trino-client-tls +``` + +```yaml +spec: + provider: + kerberos: + kerberosStorageClass: kerberos +``` + +`tls` 通过客户端出示的证书完成认证,证书由指定的 SecretClass 签发; +`kerberos` 指向承载 Kerberos 凭据分发的 StorageClass。两者的支持情况都取决于产品,参见上文提醒。 + +## TLS 校验 + +`ldap` 和 `oidc` 都接受 `tls` 块,且一旦出现,其中的 `verification` 是**必填**的: + +```yaml +tls: + verification: + server: + caCert: + secretClass: tls +``` + +| `verification` | 行为 | +|----------------|------| +| `server.caCert.secretClass` | 用该 SecretClass 提供的 CA 校验 | +| `server.caCert.webPki: {}` | 用系统内置的公共 CA 集校验 | +| `none: {}` | 完全不校验证书 | + +在 LDAP provider 上设置 `tls`,同时会把默认端口从 389 改为 636。 + +## 相关内容 + +- [角色和角色组](../common-configuration-mechanisms/roles-and-role-groups.md) +- [S3](../resources/s3.md) From 88452334af16a9166e5e77ed6675bbf2c3a2e9ee Mon Sep 17 00:00:00 2001 From: whg517 Date: Mon, 24 Aug 2026 16:39:44 +0800 Subject: [PATCH 2/2] docs(core-concepts): write the logging page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces a one-line placeholder. Taken from commons/v1alpha1's logging_types.go and config_types.go, the log path constants in pkg/constant, and pkg/vector for the aggregator discovery contract. Covers where containers write (/kubedoop/log//), the containers/loggers/console/file structure under config.logging, the level enum, and the Vector agent. Explains why level has no CRD default: unset means inherit, so a role group writing an empty `console: {}` does not silently override a DEBUG set at the role level. A default would be filled by the API server as soon as the enclosing object existed and the role's value could never win. Also documents the level mapping for non-Java products, where TRACE and DEBUG collapse together. For Vector, documents the indirection — vectorAggregatorConfigMapName names a ConfigMap carrying an ADDRESS key, so the aggregator can move without editing product clusters — and quotes the errors raised when the agent is enabled with no aggregator configured, or with one that cannot be resolved. Those failures are loud on purpose: a silently mis-wired log pipeline looks healthy until you need the logs. Co-Authored-By: Claude Opus 5 --- docs/core-concepts/observability/logging.md | 146 +++++++++++++++++- .../core-concepts/observability/logging.md | 138 ++++++++++++++++- 2 files changed, 282 insertions(+), 2 deletions(-) diff --git a/docs/core-concepts/observability/logging.md b/docs/core-concepts/observability/logging.md index b921bbe5..018bc69b 100644 --- a/docs/core-concepts/observability/logging.md +++ b/docs/core-concepts/observability/logging.md @@ -1 +1,145 @@ -# Logging +--- +title: Logging +--- + +Kubedoop gives every product the same logging controls: per-container log levels that you set on a +role or a single role group, and an optional [Vector](https://vector.dev/) agent that ships the +resulting files to an aggregator. + +## Where logs go + +Containers write under `/kubedoop/log/`, one directory per container: + +```text +/kubedoop/log//. +``` + +The suffix depends on the logging framework the product uses. Both the console stream and these +files are produced, and they are configured independently — see below. + +## Configuring log levels + +Logging lives under `config`, so it can be set on a role and refined per role group: + +```yaml +apiVersion: trino.kubedoop.dev/v1alpha1 +kind: TrinoCluster +metadata: + name: trino +spec: + coordinator: + config: + logging: + containers: + trino: + console: + level: INFO + file: + level: DEBUG + loggers: + io.trino.server: + level: DEBUG + roleGroups: + default: + replicas: 1 +``` + +The structure is: + +| Key | Meaning | +|-----|---------| +| `containers.` | The container these settings apply to | +| `containers..console.level` | Threshold for the console (stdout) appender | +| `containers..file.level` | Threshold for the file appender | +| `containers..loggers..level` | Threshold for one named logger | +| `enableVectorAgent` | Whether to inject the Vector sidecar | + +Every `level` takes one of: + +```text +FATAL ERROR WARN INFO DEBUG TRACE +``` + +### Unset means inherit + +`level` has no default in the CRD, deliberately. Leaving it out means "inherit": + +- a role group that omits it takes the role's value +- when nobody sets it, the product's own default applies — root logger at `INFO`, with no threshold + on the appender + +This is why writing an empty `console: {}` in a role group does not quietly override a `DEBUG` you +set at the role level. If the field carried a CRD default, the API server would fill it as soon as +the enclosing object existed, and the role's value could never win. + +### Levels are mapped for non-Java products + +Kubedoop's level names follow the Java convention. Products whose logging framework uses different +names get them mapped: + +| Kubedoop | Mapped to | +|----------|-----------| +| `FATAL` | `CRITICAL` | +| `ERROR` | `ERROR` | +| `WARN` | `WARNING` | +| `INFO` | `INFO` | +| `DEBUG` | `DEBUG` | +| `TRACE` | `DEBUG` | + +`TRACE` and `DEBUG` collapse onto the same level for those products, so asking for `TRACE` will not +get you more than `DEBUG` there. + +## Shipping logs with Vector + +Setting `enableVectorAgent: true` injects a Vector sidecar that tails the log directory and forwards +to an aggregator you run: + +```yaml +spec: + clusterConfig: + vectorAggregatorConfigMapName: vector-aggregator-discovery + coordinator: + config: + logging: + enableVectorAgent: true +``` + +The aggregator's address is not written in the cluster resource. Instead +`vectorAggregatorConfigMapName` names a ConfigMap in the same namespace holding a single key: + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: vector-aggregator-discovery +data: + ADDRESS: http://vector-aggregator.default.svc.cluster.local:6000 +``` + +This indirection means the aggregator can move without editing every product cluster. + +### Enabling the agent without an aggregator fails loudly + +If the Vector agent is enabled and the product actually produces logs, but +`vectorAggregatorConfigMapName` is empty, reconciliation fails rather than shipping a sidecar with +nowhere to send: + +```text +vector agent is enabled but vectorAggregatorConfigMapName is not configured (role "coordinator", group "default") +``` + +A named ConfigMap that cannot be resolved fails the same way, and the message says which check +failed: + +```text +configmap default/vector-aggregator-discovery missing "ADDRESS" key +configmap default/vector-aggregator-discovery has empty "ADDRESS" value +``` + +This is deliberate. A silently mis-wired log pipeline looks healthy right up until you need the +logs. + +## Related + +- [Roles and role groups](../common-configuration-mechanisms/roles-and-role-groups.md) +- [Configuration overrides](../common-configuration-mechanisms/overrides.md) diff --git a/i18n/zh/docusaurus-plugin-content-docs/current/core-concepts/observability/logging.md b/i18n/zh/docusaurus-plugin-content-docs/current/core-concepts/observability/logging.md index 65c2dbdd..669d8ae9 100644 --- a/i18n/zh/docusaurus-plugin-content-docs/current/core-concepts/observability/logging.md +++ b/i18n/zh/docusaurus-plugin-content-docs/current/core-concepts/observability/logging.md @@ -1 +1,137 @@ -# 日志 +--- +title: 日志 +--- + +Kubedoop 为所有产品提供同一套日志控制:可以按角色或单个角色组设置的容器级日志级别, +以及一个可选的 [Vector](https://vector.dev/) agent,负责把产生的日志文件发送到聚合器。 + +## 日志写在哪 + +容器把日志写在 `/kubedoop/log/` 下,每个容器一个目录: + +```text +/kubedoop/log//. +``` + +后缀取决于产品使用的日志框架。控制台输出和这些文件会同时产生,两者独立配置——见下文。 + +## 配置日志级别 + +日志配置位于 `config` 下,因此可以在角色上设置,再按角色组细化: + +```yaml +apiVersion: trino.kubedoop.dev/v1alpha1 +kind: TrinoCluster +metadata: + name: trino +spec: + coordinator: + config: + logging: + containers: + trino: + console: + level: INFO + file: + level: DEBUG + loggers: + io.trino.server: + level: DEBUG + roleGroups: + default: + replicas: 1 +``` + +结构如下: + +| 键 | 含义 | +|----|------| +| `containers.` | 这些设置作用于哪个容器 | +| `containers..console.level` | 控制台(stdout)输出的阈值 | +| `containers..file.level` | 文件输出的阈值 | +| `containers..loggers..level` | 某个具名 logger 的阈值 | +| `enableVectorAgent` | 是否注入 Vector sidecar | + +所有 `level` 取值范围: + +```text +FATAL ERROR WARN INFO DEBUG TRACE +``` + +### 不设置意味着继承 + +`level` 在 CRD 里刻意没有默认值。不填写它表示"继承": + +- 角色组没填时,取角色上的取值 +- 都没有设置时,走产品自身的默认——根 logger 为 `INFO`,输出端不设阈值 + +这正是为什么在角色组里写一个空的 `console: {}` 不会悄悄覆盖你在角色级设的 `DEBUG`。 +如果该字段带了 CRD 默认值,API server 会在其外层对象一存在时就把它填上, +角色级的取值就永远赢不了。 + +### 非 Java 产品会做级别映射 + +Kubedoop 的级别名沿用 Java 惯例。日志框架使用不同命名的产品会得到一层映射: + +| Kubedoop | 映射为 | +|----------|--------| +| `FATAL` | `CRITICAL` | +| `ERROR` | `ERROR` | +| `WARN` | `WARNING` | +| `INFO` | `INFO` | +| `DEBUG` | `DEBUG` | +| `TRACE` | `DEBUG` | + +在这类产品上 `TRACE` 和 `DEBUG` 会塌缩到同一级别,所以请求 `TRACE` 并不会比 `DEBUG` 拿到更多信息。 + +## 用 Vector 发送日志 + +设置 `enableVectorAgent: true` 会注入一个 Vector sidecar,它会跟踪日志目录并转发到你自己运行的 +聚合器: + +```yaml +spec: + clusterConfig: + vectorAggregatorConfigMapName: vector-aggregator-discovery + coordinator: + config: + logging: + enableVectorAgent: true +``` + +聚合器的地址并不写在集群资源里。`vectorAggregatorConfigMapName` 指向同命名空间下的一个 +ConfigMap,其中只有一个键: + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: vector-aggregator-discovery +data: + ADDRESS: http://vector-aggregator.default.svc.cluster.local:6000 +``` + +这层间接的意义在于:聚合器迁移时不必逐个修改产品集群资源。 + +## 启用 agent 却没有聚合器会直接报错 + +如果 Vector agent 已启用、产品也确实产生日志,但 `vectorAggregatorConfigMapName` 为空, +调谐会直接失败,而不是发出一个无处投递的 sidecar: + +```text +vector agent is enabled but vectorAggregatorConfigMapName is not configured (role "coordinator", group "default") +``` + +指定了但无法解析的 ConfigMap 会以同样方式失败,并且报错会指出是哪一项检查没通过: + +```text +configmap default/vector-aggregator-discovery missing "ADDRESS" key +configmap default/vector-aggregator-discovery has empty "ADDRESS" value +``` + +这是刻意设计。一条接错了却不报错的日志链路,看起来一切正常,直到你真正需要日志的那一刻。 + +## 相关内容 + +- [角色和角色组](../common-configuration-mechanisms/roles-and-role-groups.md) +- [配置覆盖](../common-configuration-mechanisms/overrides.md)