anchore/k8s-inventory

GitHub: anchore/k8s-inventory

anchore-k8s-inventory 是一个 Kubernetes 集群镜像清单采集工具,定期轮询集群 API 将当前运行中的容器和镜像信息上报给 Anchore Enterprise。

Stars: 70 | Forks: 15

# Anchore Kubernetes 清单 [![Go Report Card](https://goreportcard.com/badge/github.com/anchore/k8s-inventory)](https://goreportcard.com/report/github.com/anchore/k8s-inventory) [![GitHub release](https://img.shields.io/github/release/anchore/k8s-inventory.svg)](https://github.com/anchore/k8s-inventory/releases/latest) [![License: Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/anchore/k8s-inventory/blob/main/LICENSE) `anchore-k8s-inventory` 会定期轮询 Kubernetes API,以检索当前正在使用的镜像。 它可以在集群内部(在 Service Account 下)或集群外部(通过任何提供的 kubeconfig)运行。 ## 快速开始 [安装二进制文件](#installation)或下载 [Docker 镜像](https://hub.docker.com/r/anchore/k8s-inventory/tags) ## 安装说明 `anchore-k8s-inventory` 可以作为 CLI、Docker 容器或 Helm Chart 运行 默认情况下,当作为 CLI 运行时,`anchore-k8s-inventory` 会在主目录中查找 kubeconfig 以进行身份验证。 ### CLI ``` $ anchore-k8s-inventory --verbose-inventory-reports { "cluster_name": "docker-desktop", "containers": [ { "id": "docker://911d2cf6351cbafc349f131aeef1b1fb295a889504d38c89a065da1a91d828b9", "image_digest": "sha256:76049887f07a0476dc93efc2d3569b9529bf982b22d29f356092ce206e98765c", "image_tag": "docker.io/kubernetesui/metrics-scraper:v1.0.8", "name": "dashboard-metrics-scraper", "pod_uid": "c5b40099-20a5-4b46-8062-cf84f9d6ac23" }, { "id": "docker://a9cd75ad99dd4363bbd882b40e753b58c62bfd7b03cabeb764c1dac97568ad26", "image_digest": "sha256:2e500d29e9d5f4a086b908eb8dfe7ecac57d2ab09d65b24f588b1d449841ef93", "image_tag": "docker.io/kubernetesui/dashboard:v2.7.0", "name": "kubernetes-dashboard", "pod_uid": "72ba7e4e-6e35-48c0-bff7-558a525074d5" }, ..... ], "namespaces": [ { "labels": { "kubernetes.io/metadata.name": "kube-public" }, "name": "kube-public", "uid": "dd561bf1-11ff-4381-8a1f-f156c206fe13" }, { "labels": { "kubernetes.io/metadata.name": "kube-system" }, "name": "kube-system", "uid": "012ebe67-dd49-4fd9-b604-258385df3957" }, ..... ], "nodes": [ { "annotations": { "kubeadm.alpha.kubernetes.io/cri-socket": "unix:///var/run/cri-dockerd.sock", "node.alpha.kubernetes.io/ttl": "0", "volumes.kubernetes.io/controller-managed-attach-detach": "true" }, "arch": "arm64", "container_runtime_version": "docker://20.10.23", "kernel_version": "5.15.49-linuxkit", "kube_proxy_version": "v1.26.1", "kubelet_version": "v1.26.1", "labels": { "beta.kubernetes.io/arch": "arm64", "beta.kubernetes.io/os": "linux", "kubernetes.io/arch": "arm64", "kubernetes.io/hostname": "minikube", "kubernetes.io/os": "linux", "minikube.k8s.io/commit": "ddac20b4b34a9c8c857fc602203b6ba2679794d3", "minikube.k8s.io/name": "minikube", "minikube.k8s.io/primary": "true", "minikube.k8s.io/updated_at": "2023_04_11T11_20_54_0700", "minikube.k8s.io/version": "v1.29.0", "node-role.kubernetes.io/control-plane": "", "node.kubernetes.io/exclude-from-external-load-balancers": "" }, "name": "minikube", "operating_system": "linux", "uid": "b8334e25-68a5-4cbc-bf7a-fc188f2c6023" } ], "pods": [ { "annotations": { "seccomp.security.alpha.kubernetes.io/pod": "runtime/default" }, "labels": { "k8s-app": "dashboard-metrics-scraper", "pod-template-hash": "5c6664855" }, "name": "dashboard-metrics-scraper-5c6664855-s8lpc", "namespace_uid": "c1d98ff5-6689-4016-aef3-8802790c3b10", "node_uid": "b8334e25-68a5-4cbc-bf7a-fc188f2c6023", "uid": "c5b40099-20a5-4b46-8062-cf84f9d6ac23" }, { "labels": { "gcp-auth-skip-secret": "true", "k8s-app": "kubernetes-dashboard", "pod-template-hash": "55c4cbbc7c" }, "name": "kubernetes-dashboard-55c4cbbc7c-6p28m", "namespace_uid": "c1d98ff5-6689-4016-aef3-8802790c3b10", "node_uid": "b8334e25-68a5-4cbc-bf7a-fc188f2c6023", "uid": "72ba7e4e-6e35-48c0-bff7-558a525074d5" }, ..... ], "serverVersionMetadata": { "major": "1", "minor": "26", "gitVersion": "v1.26.1", "gitCommit": "8f94681cd294aa8cfd3407b8191f6c70214973a4", "gitTreeState": "clean", "buildDate": "2023-01-18T15:51:25Z", "goVersion": "go1.19.5", "compiler": "gc", "platform": "linux/arm64" }, "timestamp": "2023-05-03T12:34:13Z" } ``` ### 容器 为了将 `anchore-k8s-inventory` 作为容器运行,它需要一个 kubeconfig ``` ~ docker run -it --rm -v ~/.kube/config:/.kube/config anchore/k8s-inventory:latest --verbose-inventory-reports ``` ### Helm Chart Anchore-k8s-inventory 是 Anchore Enterprise 的 Runtime Inventory 功能的基础。通过 Helm 运行 anchore-k8s-inventory 是检索 Kubernetes 镜像清单的绝佳方式,无需向 Anchore 提供 Cluster 凭据。 Anchore-k8s-inventory 在其部署的集群中作为只读 Service Account 运行。 为了将清单报告给 Anchore,anchore-k8s-inventory 确实需要 Anchore Enterprise 部署的身份验证材料。 anchore-k8s-inventory 的 helm chart 会根据您使用的 values 文件自动为 Anchore 密码创建一个 Kubernetes secret。例如: ``` anchore-k8s-inventory: anchore: password: foobar ``` 它会基于此设置以下环境变量:`ANCHORE_K8S_INVENTORY_ANCHORE_PASSWORD=foobar`。 如果您不想在 values 文件中存储您的 Anchore 密码,您可以自己创建一个 secret 来实现: ``` apiVersion: v1 kind: Secret metadata: name: anchore-k8s-inventory-anchore-password type: Opaque stringData: ANCHORE_K8S_INVENTORY_ANCHORE_PASSWORD: foobar ``` 然后通过 values 文件将其提供给 helm chart: ``` anchore-k8s-inventory: existingSecret: anchore-k8s-inventory-anchore-password ``` anchore-k8s-inventory 的 helm chart 是 [charts.anchore.io](https://charts.anchore.io) 仓库的一部分。您可以通过以下方式安装它: ``` helm repo add anchore https://charts.anchore.io helm install -f anchore/k8s-inventory ``` 您始终可以[在此处](https://github.com/anchore/anchore-charts/tree/main/stable/k8s-inventory/values.yaml)找到基础的 values 文件 ## 作为 Enterprise 集成的 anchore-k8s-inventory agent 在 Enterprise 的 `v5.11.0` 版本中,Enterprise 提供了让 k8s-inventory 注册并提供健康状态报告的功能。这使得 Enterprise 能够跟踪 agent 的状态,并将该信息暴露给管理员。 在 Enterprise 为此功能提供的 API 中,这些实体被称为 Integrations。因此,anchore-k8s-inventory agent 是一种类型的 Integration。 在 agent 开始发送健康状态报告之前,它需要向 Enterprise 进行注册。这是一个 agent 向 Enterprise 展示自身的握手过程。注册包含诸如集成类型、其名称、启动时间、运行时间、发送健康报告的频率等信息。其中一些属性是可选的,例如 'description' 属性。 当 agent 注册时,Enterprise 会为其分配一个 integration uuid。随后,该 uuid 将用于针对该特定集成实例的所有 API 操作。因此,当 agent 向 Enterprise 发送其健康报告时,它会向包含该 integration uuid 的 URL 发起 REST API 调用。 ### 注册为集成 当 agent 向 Enterprise 注册时,注册信息将包含一个 `registration_id` 和一个 `registration_instance_id`。Enterprise 使用它们来查找该 agent 的 integration uuid。 如果是首次注册 agent,将不存在任何 integration `uuid`,因此 Enterprise 将创建一个,并在其数据库中存储该 integration uuid 与 `` 之间的关联。对于随后的重新注册(例如,如果 agent pod 被重启),此关联将允许 Enterprise 返回在早期注册中创建的 integration `uuid`。因此,只要 `` 对保持不变,Enterprise 就会将其视为相同的集成实例。之所以需要值对,是因为像 `anchore_k8s_inventory` agent 这样的集成可以被部署为多个副本(在 K8s Deployment 的情况下)。Enterprise 必须能够区分不同的 agent 副本实例。具有合理选定值的的值对使其成为可能。 可以通过配置来设置 `registration_id`(参见下面的配置部分)。 只有 agent 自身才能设置 `registration_instance_id` 值。它会将其设置为 agent 运行的 hostname(或者如果其为空,则生成一个 uuid 并使用该值)。 ### 向后兼容性 ## 配置 ``` # 与 -q 相同;抑制所有输出(清单结果除外) quiet: false log: # use structured logging structured: false # the log level; note: detailed logging suppress the ETUI level: "debug" # location to write the log file (default is not to have a log file) file: "./anchore-k8s-inventory.log" # 启用/禁用启动时检查应用更新 check-for-app-update: true kubeconfig: path: cluster: docker-desktop cluster-cert: server: # ex. https://kubernetes.docker.internal:6443 user: type: # valid: [private_key, token] client-cert: private-key: token: # 启用/禁用将清单报告打印到 stdout verbose-inventory-reports: false ``` ### 集成注册 配置将 agent 注册为 Integration 的值。 如果使用 Anchore helm charts 的 `k8s-inventory v0.5.0` 或更高版本,最好将 `registration_id` 留空。 如果在配置中显式设置,建议使用一些能够生成 uuid 的工具来确保唯一性。 ``` anchore-registration: # The id to register the agent as with Enterprise, so Enterprise can map the agent to its integration uuid. # If left unspecified, the agent will attempt to set registration-id to the uid of the K8s Deployment for the agent. # If that fails (e.g., if the agent is not deployed on K8s), the agent will generate a UUID to use as registration-id. registration-id: # The name that the agent should have. If left unspecified, the agent will attempt to set it to the name of the K8s # Deployment for the agent. If that fails it will be empty. integration-name: # A short description for the agent integration-description: ``` ### Namespace 选择 配置 anchore-k8s-inventory 应该搜索哪些 namespace。 * `include` 部分 * 一个显式字符串列表,用于详细说明要从中捕获镜像数据的 namespace 列表。 * 如果留空为 `[]`,则将搜索所有 namespace * 示例: ``` namespace-selectors: include: - default - kube-system - prod-app ``` * `exclude` 部分 * 用于排除 namespace 的显式字符串和/或正则表达式模式的列表。 * 如果字符串不符合标准 DNS 名称要求,则将其判定为正则表达式。 * 示例: ``` namespace-selectors: exclude: - default - ^kube-* - ^prod-* ``` ``` # 要搜索或排除的 namespaces。 namespace-selectors: # Namespaces to include as explicit strings, not regex # NOTE: Will search ALL namespaces if left as an empty array include: [] # List of namespaces to exclude, can use explicit strings and/or regexes. # For example # # list: # - default # - ^kube-* # # Will exclude the default, kube-system, and kube-public namespaces exclude: [] # If true then namespaces containing 0 pods will be omitted from the report sent to Anchore Enterprise ignore-empty: false ``` ### 账户路由 以下配置选项可以决定将清单报告发送到哪个 Anchore 账户。如果没有以下任何配置,则将使用 `anchore` 部分中设置的账户。 如果混合使用静态账户路由和按 namespace label 进行的账户路由,则 k8s-inventory 配置中配置的静态账户路由将优先于 namespace label 指定的任何账户。 #### 静态账户路由配置 设置账户列表以及应将哪些 namespace 的清单发送到该账户。您可以在每个账户的基础上覆盖默认凭据,如果未设置,则将使用 `anchore` 部分中设置的全局凭据。 ``` account-routes: # : # (this is the name of the anchore account e.g. admin) # user: # password: # namespaces: # Can be a list of explicit namespaces matches or regex patterns # - # - # # Example # admin: # user: username # password: password # namespaces: # - default # - ^kube-* ``` #### 按 namespace label 进行账户路由 在此模式下,使用设置在 Kubernetes namespace 上的 label 来确定该 namespace 的清单数据应发送到哪个 Anchore 账户。假定在 `anchore` 部分中设置的凭据可以向所有账户发送数据。 ``` # 通过 namespace 上的 label 将 namespaces 路由到 anchore accounts account-route-by-namespace-label: # The name of the namespace label that will be used to route the contents of # that namespace to the Anchore account matching the value of the label key: # e.g anchore.io/account.name # The name of the account to route inventory to for a namespace that is # missing the label or if the anchore account is not found. # If not set then it will default to the account specified in the anchore credentials default-account: # e.g. admin # If true will exclude inventorying namespaces that are missing the specified label ignore-namespace-missing-label: false ``` ### Kubernetes API 参数 本部分将允许用户调整 anchore-k8s-inventory 与 Kubernetes API server 交互的方式。 ``` # Kubernetes API 配置参数(通常无需调整) kubernetes: # Sets the request timeout for kubernetes API requests request-timeout-seconds: 60 # Sets the number of objects to iteratively return when listing resources request-batch-size: 100 # Worker pool size for collecting pods from namespaces. Adjust this if the api-server gets overwhelmed worker-pool-size: 100 ``` ### anchore-k8s-inventory 的操作模式 ``` # 可以是 adhoc 或 periodic 之一(默认为 adhoc) mode: adhoc # 仅在 mode 为 periodic 时生效 polling-interval-seconds: 300 ``` ### 缺失 Tag 策略 在某些情况下,Kubernetes 中的镜像没有关联的 tag - 例如当使用 digest 部署镜像时。 ``` kubectl run python --image=python@sha256:f0a210a37565286ecaaac0529a6749917e8ea58d3dfc72c84acfbfbe1a64a20a ``` Anchore Enterprise 将使用镜像 digest 来处理镜像,但它仍然需要与镜像关联的 tag。`missing-tag-policy` 允许您配置在您的环境中处理缺少 tag 的边缘情况的最佳方式。 **digest** 将使用镜像 digest 作为虚拟 tag。 ``` { "tag": "alpine:4ed1812024ed78962a34727137627e8854a3b414d19e2c35a1dc727a47e16fba", "repoDigest": "sha256:4ed1812024ed78962a34727137627e8854a3b414d19e2c35a1dc727a47e16fba" } ``` **insert** 将使用由 `missing-tag-policy.tag` 配置的虚拟 tag ``` { "tag": "alpine:UNKNOWN", "repoDigest": "sha256:4ed1812024ed78962a34727137627e8854a3b414d19e2c35a1dc727a47e16fba" } ``` **drop** 将直接忽略没有 tag 的镜像。 ``` # 处理 tag 缺失的情况。例如 - 通过 digest 指定的 images missing-tag-policy: # One of the following options [digest, insert, drop]. Default is 'digest' # # [digest] will use the image's digest as a dummy tag. # # [insert] will insert a default tag in as a dummy tag. The dummy tag is # customizable under missing-tag-policy.tag # # [drop] will drop images that do not have tags associated with them. Not # recommended. policy: digest # Dummy tag to use. Only applicable if policy is 'insert'. Defaults to UNKNOWN tag: UNKNOWN ``` ### 忽略尚未处于 Running 状态的镜像 ``` # 忽略未处于 Running 状态的 pods 中的 images ignore-not-running: true ``` ### 批量发送清单报告 为发送到 Anchore Enterprise 的单个清单报告 POST 设置包含内容的上限。如果清单数据大于限制,则清单报告将被分成小于等于指定限制大小的多个请求。 ``` inventory-report-limits: namespaces: 0 # default of 0 means no limit ``` ### 元数据配置 每种资源类型仅包含部分 annotations/labels,或者完全禁用元数据 ``` metadata-collection: nodes: annotations: [] # List of annotations to include (explicit or regex) labels: [] # List of labels to include (explicit or regex) disable: false # Remove all optional node metadata from the inventory report namespaces: annotations: [] # List of annotations to include (explicit or regex) labels: [] # List of labels to include (explicit or regex) disable: false # Remove all optional namespace metadata from the inventory report pods: annotations: [] # List of annotations to include (explicit or regex) labels: [] # List of labels to include (explicit or regex) disable: false # Remove all optional pod metadata from the inventory report ``` ### Anchore API 配置 使用此部分配置 Anchore Enterprise API endpoint ``` anchore: url: user: password: $ANCHORE_K8S_INVENTORY_ANCHORE_PASSWORD account: http: insecure: true timeout-seconds: 10 ``` ## 行为变更 (v1.7.0) 请注意,从 k8s-inventory >= v1.7.0 开始,/version/ endpoint 必须通过提供的 Anchore Enterprise URL 路由到 API 服务。/version/ endpoint 必须返回在以下 JSON payload 中找到的版本字段: ``` { "api": { "version": "2" }, "db": { "schema_version": "5260" }, "service": { "commit_sha": "c81dec015833e7705338ab082c8aa21c94ebfa9a", "image_build_dt": "2026-03-31T13:21:56.051468Z", "version": "5.26.0" } } ``` ## 行为变更 (v0.5.0)(原名 KAI) 在低于 v0.5.0 版本的 anchore-k8s-inventory 中,默认行为是每次生成清单报告时将其输出到 stdout。anchore-k8s-inventory v0.5.0 更改了此行为,除非在配置文件中设置了 `verbose-inventory-reports: true` 或在调用 anchore-k8s-inventory 时使用了 `--verbose-inventory-reports` 标志,否则它不会打印到 stdout。 ## 配置变更 (v0.2.2 -> v0.3.0)(原名 KAI) 从 v0.2.2 到 v0.3.0 有一些配置发生了变化 #### `kubernetes-request-timeout-seconds` Kubernetes API 的请求超时时间已从 ``` kubernetes-request-timeout-seconds: 60 ``` 更改为 ``` kubernetes: request-timeout-seconds: 60 ``` anchore-k8s-inventory 仍然会沿用旧配置。在旧配置参数完全从配置中移除之前,它将优先使用旧配置参数。放弃旧配置而使用新配置是安全的。 #### `namespaces` namespace 配置已从 ``` namespaces: - all ``` 更改为 ``` namespace-selectors: include: [] exclude: [] ``` 添加 `namespace-selectors` 最终是为了取代 `namespaces`,以同时支持 include 和 exclude 配置。如果 `namespace-selectors.include` 为空,则将沿用旧的 `namespaces` 数组。完全放弃 `namespaces` 而使用 `namespace-selectors` 是安全的 ## 开发 ### 构建 **注意:** 这会将二进制文件放置在 `./snapshot/` 目录中 **在 Mac 上** ``` make mac-binary ``` **在 Linux 上** ``` make linux-binary ``` ### 测试 Makefile 中内置了测试功能。要进行单元测试,只需运行 ``` make unit ``` ### Docker 要构建 Docker 镜像,您需要提供一个 kubeconfig。 注意:Docker 构建要求文件必须位于 Docker 构建上下文中 ``` docker build -t localhost/anchore-k8s-inventory:latest --build-arg KUBECONFIG=./kubeconfig . ``` ### Shell 自动补全 anchore-k8s-inventory 附带了用于指定 namespace 的 shell 自动补全功能,可以按如下方式启用。运行带有 `--help` 命令的程序以获取适合您所使用的 shell 的说明 ``` anchore-k8s-inventory completion ``` ### 使用 Skaffold 您可以使用 skaffold 进行开发。'bootstrap-skaffold' make 目标会将 chart 克隆到当前目录中,以便为 skaffold 配置它以供使用。要触发重新部署,您需要运行 `make linux-binary`,然后 skaffold 将重新构建镜像并更新 helm release。 ``` make bootstrap-skaffold make linux-binary skaffold dev ``` ## 发布 要创建 anchore-k8s-inventory 的发布,需要创建一个 tag,指向 `main` 中我们要发布的 commit。该 tag 应为以 `v` 为前缀的 semver,例如 `v0.2.7`。 这将触发 GitHub Action 来创建发布。 成功创建发布后,请确保在 Enterprise 和 [anchore-charts](https://github.com/anchore/anchore-charts) 中的 anchore-k8s-inventory Helm Chart 中指定更新的版本。
标签:EVTX分析, 子域名突变, 日志审计, 请求拦截