> ## Documentation Index
> Fetch the complete documentation index at: https://hilt.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 在 Kata Containers 上部署

> 通过安装器 initContainer 和入口点包装（entrypoint wrapper）将 Hilt 采集器部署到 VM 隔离的 Kubernetes Pod（Kata Containers）中 — 无需重建镜像。

Kata Containers（以及类似的 micro-VM 运行时）将每个 Pod 运行在一个带有独立客户机内核（guest kernel）的轻量级虚拟机中。以 DaemonSet 形式部署的主机级 eBPF 采集器无法跨越这个 VM 边界观测系统调用——这与 ECS Fargate 的约束完全相同。因此答案也相同：工作负载内（in-workload）采集器**在客户机内部**运行，包装在你的应用外层。

## 工作原理

采集器二进制文件就是 ECS Fargate 上使用的同一个 `dag-fargate-agent`；它在启动时自动识别出自己运行在 Kubernetes Pod 中而不是 Fargate 任务中。它作为**应用容器内的 PID 1** 运行，安装一个 seccomp-BPF 过滤器，仅拦截 Hilt 关心的约 20 个系统调用（`execve`、`open`、`unlink`、`rename`、`chmod`、`connect` 等），然后 `fork`+`exec` 你的原始应用程序。每个子进程都会继承该过滤器；其余部分都以原生速度运行，不受任何插桩影响。所有这些都发生在 Pod 的客户机 VM 内部——不需要任何东西跨越虚拟化边界。

你**不需要**重建应用镜像。一个 **initContainer**（与 Fargate 使用同一个安装器镜像）会在你的应用启动前，把代理二进制文件复制到一个 Pod 范围的 `emptyDir` 卷中；容器的 `command` 会被重写为先启动代理，再由代理启动你的原始命令。

> [!NOTE]
>
> 此机制适用于 `runtimeClassName` 将其置于客户机内核之后的 Pod（Kata，以及由此延伸的其他 VM 隔离运行时）。同一集群上的普通 `runc` Pod 应继续使用 [eBPF DaemonSet](https://hilt.ai/docs/zh/linux-collector/deploy-kubernetes.md)——它的覆盖范围严格更大。两者可以共存：DaemonSet 只是看不到 Kata Pod，而工作负载内代理恰好填补这个空缺。

## 前提条件

* 一个带有 Kata 运行时类（例如 `runtimeClassName: kata`）的 Kubernetes 集群，`x86_64` 或 `arm64`
* 一个可访问的 Hilt 摄取端点（`DAG_SHIP_URL`，在入驻过程中提供）
* Hilt 在入驻时提供的安装器镜像 URI（与 ECS Fargate 使用同一个 `dag-fargate-installer` 镜像）。节点必须有权限拉取该镜像。

## 会对 Pod 规约注入哪些内容

| 改动 | 详情 |
| :- | :- |
| 共享卷 | 一个 Pod 范围的 `emptyDir`（`dag-volume`），挂载在 `/dag` |
| initContainer | `dag-fargate-installer` —— 将代理二进制文件复制到共享卷后退出（相当于 ECS `dependsOn: COMPLETE` 门槛的 Kubernetes 原生等价物） |
| 应用容器 command | 重写为 `command: ["/dag/dag-fargate-agent", "--"]`，你的原始入口点/命令放入 `args` |
| 应用容器卷挂载 | `/dag`，只读 |
| 应用容器能力（capability） | 新增 `SYS_PTRACE` —— 此机制所需的唯一能力 |
| 应用容器环境变量 | `DAG_SHIP_URL`、`DAG_FARGATE_MODE`、`DAG_CLUSTER_ID`，以及 downward API 身份字段（见下文） |

如果运行时出现任何附加失败，代理会**故障开放（fail open）**：无论是否有遥测数据，你的应用始终会启动并正常运行。

## 安装

目前的注入方式是文档化的 Pod 模板补丁（基于 `runtimeClassName: kata` 的变更准入 Webhook 已在规划中——如果你需要更早获得自动注入，请联系你的 Hilt 对接人）。

**1. 添加卷和 initContainer**

在你的 Pod 模板中（Deployment、StatefulSet、Job——任何产生 Pod 规约的资源）：

```yaml theme={null}
spec:
  runtimeClassName: kata
  volumes:
    - name: dag-volume
      emptyDir: {}
  initContainers:
    - name: dag-fargate-installer
      image: <INSTALLER_IMAGE_URI>
      volumeMounts:
        - name: dag-volume
          mountPath: /dag
```

**2. 包装容器的入口点**

重写应用容器的 `command`，让代理先启动。如果你的镜像依赖其默认的 `ENTRYPOINT`/`CMD`，请把它们显式写出来——Kubernetes 的 `command`/`args` 是替换语义，从不追加。

```yaml theme={null}
  containers:
    - name: app
      command: ["/dag/dag-fargate-agent", "--"]
      args: ["<你的原始入口点>", "<参数1>", "<参数2>"]
      securityContext:
        capabilities:
          add: ["SYS_PTRACE"]
      volumeMounts:
        - name: dag-volume
          mountPath: /dag
          readOnly: true
```

**3. 添加环境变量和身份信息**

客户机 VM 内部没有元数据端点，因此由 Pod 规约通过 downward API 将坐标信息交给代理：

```yaml theme={null}
      env:
        - name: DAG_SHIP_URL
          value: "https://<name>-ingest.hilt.ai/ingest"
        - name: DAG_CLUSTER_ID
          value: "<你的集群名称>"
        - name: DAG_RUNTIME_CLASS
          value: "kata"
        - name: DAG_POD_NAME
          valueFrom:
            fieldRef: { fieldPath: metadata.name }
        - name: DAG_POD_NAMESPACE
          valueFrom:
            fieldRef: { fieldPath: metadata.namespace }
        - name: DAG_POD_UID
          valueFrom:
            fieldRef: { fieldPath: metadata.uid }
        - name: DAG_NODE_NAME
          valueFrom:
            fieldRef: { fieldPath: spec.nodeName }
        - name: DAG_SERVICE_ACCOUNT
          valueFrom:
            fieldRef: { fieldPath: spec.serviceAccountName }
```

代理从不访问 Kubernetes API server——身份完全由环境变量驱动，因此不需要 serviceaccount 令牌或 RBAC。

**4. 滚动发布并验证**

应用变更后，查看被包装容器的日志：在你的应用自身输出之前，stderr 上会出现一行 `kata: identity loaded — host_id=<pod-uid> host_type=kata …`。

一个完整可运行的参考 Pod 维护在 [`deploy/kata/pod-reference.yaml`](https://github.com/hilt-ai/hilt/blob/main/data-access-governance/deploy/kata/pod-reference.yaml)。

## 配置

| 变量 | 说明 | 默认值 |
| :- | :- | :- |
| `DAG_SHIP_URL` | Hilt 摄取端点 URL | （必填） |
| `DAG_FARGATE_MODE` | `full` 或 `metadata` —— 与 [Fargate](https://hilt.ai/docs/zh/linux-collector/deploy-fargate.md#模式) 相同的模式 | `full` |
| `DAG_CLUSTER_ID` | 集群分组（Kubernetes 不向 Pod 暴露集群名称——请设置此项） | （空） |
| `DAG_HOST_TYPE` | 主机类型标签；用于其他 VM 隔离运行时时可覆盖 | `kata` |
| `DAG_TAGS` | 额外主机标签，`key=value,key=value` | （空） |
| `DAG_FLUSH_INTERVAL_MS` / `DAG_BATCH_THRESHOLD` / `DAG_MAX_BATCH` | 传输调优，与 Fargate 相同 | — |

## 覆盖范围

与 [ECS Fargate 采集器](https://hilt.ai/docs/zh/linux-collector/deploy-fargate.md)一致——full 模式下通过 seccomp+ptrace 精确采集 exec/文件/网络生命周期事件，以及 `metadata` 熔断模式——但有一项 Kata 特有差异：**网络字节计数不可用**。`sock_diag` 字节采样依赖为 Pod 提供服务的内核中的 `INET_DIAG`，而 Kata 默认的客户机内核在构建时未启用它，因此在 Kata 上代理会报告网络连接生命周期（谁在何时连接到哪里），但没有字节量。如果你的 Kata 部署使用了带 `CONFIG_INET_DIAG` 的自定义客户机内核，字节采样会自动生效。数据流血缘（data-flow lineage）、cgroup 生命周期事件和延迟探针是 eBPF 采集器的功能，在 VM 隔离的 Pod 内不可用。可见范围限定为被包装容器的进程子树——每个被包装的容器一个代理。

## 身份映射

| 字段 | 在 Kata 上的取值 | 仪表盘行为 |
| :- | :- | :- |
| Host ID | Pod UID | 每个 Pod 显示为独立的主机实体 |
| Host type | `kata` | 在机群视图中与 Kubernetes 节点、VM 和 Fargate 任务区分开 |
| Boot ID | 客户机内核的真实 boot ID（每个 Pod-VM 生命周期一个） | 重启检测与 VM 上的行为一致 |
| 集群分组 | `DAG_CLUSTER_ID` | Pod 归组到所属集群下 |
| 标签 | `pod_name`、`namespace`、`pod_uid`、`node_name`、`service_account`、`runtime_class` | 显示在主机卡片上 |

> [!NOTE]
>
> Kata Pod 与 Fargate 任务一样短暂。机群视图中的更替是预期行为；`namespace` 和 `pod_name` 标签（以及你自己的 `DAG_TAGS`）可以在 Pod 重启之间提供稳定的分组。

## 验证

部署后，在[采集器](https://hilt.ai/docs/dashboard/collectors.md)页面上确认：

* Pod 以 `host_type` = `kata` 出现
* 它被归组到正确的 `DAG_CLUSTER_ID` 下
* `pod_name`、`namespace` 和 `runtime_class` 标签存在
* exec 和网络事件正在到达

## 升级

更新安装器镜像标签并滚动发布工作负载。代理二进制文件在每次 Pod 启动时都会从 initContainer 重新复制，因此新 Pod 总是使用最新的代理。

## 卸载

从 Pod 模板中移除注入的部分（initContainer、`emptyDir` 卷、command 重写、`SYS_PTRACE` 能力以及 `DAG_*` 环境变量），然后滚动发布工作负载。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.