ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Dapr 1.4.2 修复解析:sidecar-injector 准入 Webhook 阻断 Pod 创建的根因与排查方案

Dapr 1.4.2 修复解析:sidecar-injector 准入 Webhook 阻断 Pod 创建的根因与排查方案 Dapr 1.4.2 修复解析sidecar-injector 准入 Webhook 阻断 Pod 创建的根因与排查方案【免费下载链接】daprDapr is a portable runtime for building distributed applications across cloud and edge, combining event-driven architecture with workflow orchestration.项目地址: https://gitcode.com/GitHub_Trending/da/dapr导读Dapr 1.4.2 是一个专注于修复 Sidecar 注入器sidecar-injector准入 Webhook 误伤问题的补丁版本。此前当 Pod 由未在允许的控制器账号名单中的组件创建例如 Tekton CICD 控制器创建 TaskRun Pod时sidecar-injector.dapr.io会直接拒绝该 Pod 的准入请求导致 Pod 无法创建、CI 流水线整体失败。本文以 docs/release_notes/v1.4.2.md 为主线结合仓库中注入器服务的源码实现pkg/injector/service与 Helm 配置charts/dapr/charts/dapr_sidecar_injector/values.yaml剖析该问题的根因、1.4.2 的修复策略以及如何通过ALLOWED_SERVICE_ACCOUNTS配置自定义放行规则帮助你在部署 Dapr 或接入 CI/CD 时快速定位同类准入错误。背景Sidecar 注入器与准入 Webhook在 Kubernetes 上启用 Dapr 后dapr-sidecar-injector服务以MutatingAdmissionWebhook的形式运行任何带有dapr.io/enabled: true注解的 Pod 在创建时其 AdmissionReview 请求都会被转发到注入器由注入器判断是否需要注入 Dapr sidecar并返回 JSON Patch 供 API Server 应用。这一入口逻辑位于 handler.go 的handleRequest中处理链路依次为校验请求体的 Content-Type 与 AdmissionReview 解码仅处理Kind Pod的请求通过 podHasDaprEnabled 判断 Pod 是否带有dapr.io/enabled注解非 Dapr Pod 直接放行respondWithAllowed对 Dapr Pod 执行请求方身份校验isAuthorizedUser通过后调用getPodPatchOperations生成注入补丁。也就是说注入器既是注入器也是 Pod 准入链路上的一个关卡——这正是 1.4.1/1.4.2 修复风暴的舞台。问题现象Pod 创建被 Webhook 直接拒绝v1.4.2 的发布说明中明确指出修复了问题 #3709Sidecar-injector.dapr.io was blocking Pod admissions if sidecar could not be injected.当某个控制器Controller代表工作负载创建 Pod、而注入器因身份校验无法为其注入 Dapr sidecar 时Webhook 不是跳过注入而是整体拒绝准入最终导致 Pod 根本无法创建。发布说明给出的真实场景是使用Tekton CICD部署任务时的报错- lastTransitionTime: 2021-09-24T07:48:19Z message: - failed to create task run pod function-sample-builder-cgmn8-buildrun-nfkb8-nlbjs: admission webhook sidecar-injector.dapr.io denied the request: service account system:serviceaccount:tekton-pipelines:tekton-pipelines-controller not on the list of allowed controller accounts. Maybe invalid TaskSpec reason: CouldntGetTask status: False type: Succeeded这个报错的几个关键信息请求方身份system:serviceaccount:tekton-pipelines:tekton-pipelines-controller即 Tekton Pipeline 控制器在集群内使用的 ServiceAccountKubernetes 的UserInfo.Username格式拒绝原因not on the list of allowed controller accounts即该 ServiceAccount 不在注入器内置的允许的控制器账号名单中业务影响TaskRun Pod 无法创建Task 状态变为CouldntGetTaskSucceededFalse流水线失败。问题的由来1.4.1 修复 #3699 时引入了过度收紧要理解 1.4.2 修复什么必须先看 1.4.1。在 docs/release_notes/v1.4.1.md 中1.4.1 修复了问题 #3699使用kubectl debug调试节点例如kubectl debug node/node -it --image...时请求同样会触发注入器并报出admission webhook sidecar-injector.dapr.io denied the request: service account xxxxxxx not on the list of allowed controller accounts。1.4.1 的修复方式是引入允许的控制器账号白名单机制注入器只信任来自白名单控制器如 deployment-controller、statefulset-controller 等或系统管理员组system:masters的准入请求。但白名单天然存在覆盖不全的问题任何不在名单内的控制器Tekton、Argo、GitHub Actions Runner 等 CI 控制器创建的 Pod 都会被误拒这就是 #3709 的由来。1.4.2 正是在 1.4.1 允许注入 Dapr sidecar修复 #3699的基础上把误伤导致的 Pod 创建阻断一并解决。根因剖析allowed controller accounts 机制与身份校验链允许名单的源码定义当前仓库中内置的允许名单定义在 injector.govar AllowedServiceAccountInfos []string{ kube-system:replicaset-controller, kube-system:replication-controller, kube-system:deployment-controller, kube-system:cronjob-controller, kube-system:job-controller, kube-system:statefulset-controller, kube-system:daemon-set-controller, openshift-operator-lifecycle-manager:olm-operator-serviceaccount, tekton-pipelines:tekton-pipelines-controller, //nolint:misspell mirrord:mirrord-operator, }注意其中的tekton-pipelines:tekton-pipelines-controller——这正是 1.4.2 针对 #3709 场景补充的条目Tekton 控制器创建的 PodTaskRun Pod现在被视为合法请求方不会再被拒绝。从中也可以看出 Dapr 后续版本持续在为各类控制器扩展这份名单如 OpenShift OLM、mirrord。身份校验的完整调用链请求方校验发生在handleRequest的这段逻辑handler.goif !i.isAuthorizedUser(ar.Request) { log.Errorf(service account %s not on the list of allowed controller accounts, ar.Request.UserInfo.Username) diagAppID : getAppIDFromRequest(ar.Request) respondWithAllowed(w, ar, gvk) RecordFailedSidecarInjectionCount(diagAppID, pod_patch) return }isAuthorizedUserhandler.go采用三重放行策略func (i *injector) isAuthorizedUser(req *admissionv1.AdmissionRequest) bool { return i.allowServiceAccountUser(req.UserInfo.Username) || utils.Contains(i.authUIDs, req.UserInfo.UID) || utils.Contains(req.UserInfo.Groups, systemGroup) }按 ServiceAccount 名称匹配allowServiceAccountUser会先从Username中剥离system:serviceaccount:前缀常量serviceAccountUserInfoPrefix见 injector.go取出namespace:name后交给namespaceNameMatcher匹配按 UID 匹配authUIDs是启动时通过 AllowedControllersServiceAccountUID 从集群中查询白名单 ServiceAccount 的真实 UID 集合getServiceAccount会调用 Kubernetes API 列出 ServiceAccount 并解析其 UID见 injector.go作为名称匹配之外的第二道防线defense-in-depth按用户组匹配请求方若属于system:masterssystemGroup则直接放行这是管理员操作的兜底通道。关键点拒绝与放行但不注入的差异值得对比的是当前仓库代码在身份校验失败时调用的是respondWithAllowed返回Allowed: true但不附带任何 Patch同时记录一条RecordFailedSidecarInjectionCount指标。也就是说注入器演进后的行为是放行 Pod、跳过注入而非拒绝准入——这与 1.4.2 修复前的denied the request行为不同。这一点印证了 1.4.2 修复的核心方向注入失败不应阻断业务 Pod 的生命周期Dapr 应该选择性地放弃注入而不是成为准入链路上的硬故障点。匹配机制演进从精确名单到 Glob 模式1.4.2 时代的问题本质是精确白名单覆盖不全。当前仓库中该机制已演进为基于 Gopath.Match的 Glob 匹配器实现位于 serviceaccountmatcher.go每个模式必须是namespace:name形式且恰好包含一个冒号多于一个或缺少冒号都会报错命名空间与名称两个部分都支持 Glob 语法*匹配任意字符序列、?匹配单个字符、[...]匹配字符集合空字符串模式会被静默跳过没有任何有效模式时返回一个恒为false的匹配器多个模式之间是或的关系任一命中即放行。该行为在 serviceaccountmatcher_test.go 中有大量用例覆盖例如模式请求方namespace:name结果ns:sans:sa放行精确匹配ns:sans:sa-extra拒绝不做子串匹配ns-*:sa-*ns-foo:sa-bar放行前缀通配ns-?:sans-A:sa放行?匹配单字符ns-?:sans-AB:sa拒绝?不匹配多字符ns:sa-[abc]ns:sa-b放行字符类ns:sa-[abc]ns:sa-d拒绝字符类不命中修复方案落地如何配置自定义允许的控制器账号1.4.2 修复的核心是把 Tekton 等已知 CI 控制器补进内置名单而面对自建控制器或私有 CIDapr 提供了可配置的扩展点。环境变量方式注入器通过 config.go 中的envconfig读取环境变量ALLOWED_SERVICE_ACCOUNTS以逗号分隔的额外允许 ServiceAccount 列表格式为namespace:name当前版本支持 Glob 通配ALLOWED_SERVICE_ACCOUNTS_PREFIX_NAMES已弃用Deprecated其尾缀*前缀匹配语义已被ALLOWED_SERVICE_ACCOUNTS的 Glob 能力取代若仍配置会打印ALLOWED_SERVICE_ACCOUNTS_PREFIX_NAMES is deprecated; use ALLOWED_SERVICE_ACCOUNTS instead的警告日志见 injector.go。这两项环境变量与内置AllowedServiceAccountInfos会在NewInjector中被合并为同一批匹配模式injector.go。Helm 方式在 Helm 安装时可通过dapr_sidecar_injector子 chart 的 values 配置values.yamldapr_sidecar_injector: allowedServiceAccounts: allowedServiceAccountsPrefixNames: 对应模板会将值注入 Deployment 环境变量dapr_sidecar_injector_deployment.yamlchart 的 README.md 给出了三种典型写法my-ns:my-sa精确匹配单个 ServiceAccountmy-ns:*放行某命名空间下的全部 ServiceAccountteam-*:deploy-*前缀通配匹配多个团队/多个部署账号。例如为自建的 GitLab Runner命名空间gitlab放行dapr_sidecar_injector: allowedServiceAccounts: gitlab:gitlab-runner或放行某个命名空间下所有控制器账号dapr_sidecar_injector: allowedServiceAccounts: ci-runners:*匹配失败时的降级行为结合 handler_test.go 中的用例如TestSidecarInjectUserInfoNotMatchesServiceAccountPrefix、TestSidecarInjectDefaultServiceAccountNearMissDenied可以确认以下行为细节精确名单不做子串匹配kube-system:deployment-controller放行但kube-system:deployment-controller-extra会被视为未授权见TestSidecarInjectDefaultServiceAccountNearMissDeniedhandler_test.go未授权请求虽然 HTTP 返回 200、Pod 被放行但不会注入 sidecar并计入失败注入指标RecordFailedSidecarInjectionCount便于通过 Prometheus 监控发现该注入而未注入的 Pod注入器指标定义见 metrics.go。测试与验证如何在仓库中复现与确认仓库内已为这套机制准备了完整的单元测试可作为验证与回归依据handler_test.go通过httptest直接向handleRequest发起 AdmissionReview 请求覆盖成功注入、错误 Content-Type、非 Pod 类型、组不匹配、UID 匹配/不匹配、ServiceAccount 前缀匹配、内置名单精确匹配与近似名拒绝等十余个场景injector_test.goTestAllowedControllersServiceAccountUID使用 fake Kubernetes Client 创建tekton-pipelines:tekton-pipelines-controller等 ServiceAccount验证 UID 白名单的查询与解析逻辑含配置有效/无效账号的用例serviceaccountmatcher_test.go针对 Glob 匹配器本身的纯函数测试覆盖通配符、字符类、非法模式报错、空模式恒拒绝等边界情况。若要亲手验证可在仓库根目录执行go test ./pkg/injector/service/...升级与排障建议围绕 #3709 这类准入 Webhook 误伤给出如下实操建议遇到denied the request: service account ... not on the list of allowed controller accounts时先定位请求方身份报错中的system:serviceaccount:namespace:name即为创建 Pod 的控制器账号确认该控制器是否需要创建 Dapr 注入的 Pod区分两类诉求若该控制器创建的 Pod 根本不需要 Dapr无dapr.io/enabled注解则注入器本应直接放行若确实需要注入则应将账号加入ALLOWED_SERVICE_ACCOUNTS优先使用通配而非逐个枚举对于 CI 这类控制器账号动态变化的场景ci-*:runner-*之类的 Glob 模式比维护精确名单更稳健升级到包含本修复的版本1.4.2 将tekton-pipelines:tekton-pipelines-controller纳入内置允许名单同时保持 1.4.1 对kubectl debug#3699的修复不回归后续版本进一步将拒绝行为调整为放行但不注入从机制上消除了单点故障风险监控注入失败指标即使 Pod 被放行也要通过RecordFailedSidecarInjectionCount对应的注入失败指标关注静默未注入的 Pod避免业务在无 sidecar 状态下运行。总结Dapr 1.4.2 通过将 Tekton Pipeline 控制器账号纳入 Sidecar 注入器允许名单解决了 #3709 中准入 Webhook 阻断 Pod 创建的问题是 1.4.1 引入白名单机制后的一次重要收敛。围绕这一修复本文从 pkg/injector/service/injector.go、handler.go、serviceaccountmatcher.go 出发还原了允许名单、身份校验链与 Glob 匹配机制的实现全貌并给出了通过ALLOWED_SERVICE_ACCOUNTS/allowedServiceAccounts自定义放行规则的完整配置路径。理解这条准入链路的判定逻辑是你在任何集群化 CI/CD 场景下排查 Dapr sidecar 注入问题的基础。【免费下载链接】daprDapr is a portable runtime for building distributed applications across cloud and edge, combining event-driven architecture with workflow orchestration.项目地址: https://gitcode.com/GitHub_Trending/da/dapr创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表