海雀

实现一个MutatingAdmissionWebhook

官方文档 概述 在 Kubernetes 中,准入控制是保障 API 请求安全和合规性的重要机制。它在 API 请求流程中扮演着关键角色,拦截即将发送到 Kubernetes APIServer的请求,在持久化之前,但在身份验证和授权之后。其位置如下图所示: 图片来源https://sysdig.com/blog/kubernetes-admission-controllers/ 准入控制器适用于创建、删除或修改对象的请求,同时也可以阻止自定义动作。读操作会绕过准入控制层,不会受到准入控制器的影响。当有多个准入控制器存在时,它们会依次被调用,只要其中一个准入控制器拒绝请求,整个请求就会被立即驳回。 准入控制常常被用来自动化设置默认资源请求和限制、应用标签和注释以及强制命名约定等管理任务。 准入控制分两个阶段: 变更准入控制器,用于在请求处理过程中对对象进行修改。 验证准入控制器,负责验证请求是否符合特定规则。 需要注意的是,部分控制器兼具变更准入和验证准入的功能。 启用准入 1 kube-apiserver --enable-admission-plugins=NamespaceLifecycle,LimitRanger ... 关闭准入 1 kube-apiserver --disable-admission-plugins=PodNodeSelector,AlwaysDeny ... 准入的两种类型: 静态准入:由 Kubernetes 内置提供,无需额外配置。 动态准入:允许用户根据自身需求进行扩展。 动态准入控制器: MutatingAdmissionWebhook 此准入控制器调用任何与请求匹配的变更(Mutating) Webhook。匹配的 Webhook 将被顺序调用 ValidatingAdmissionWebhook 此准入控制器调用与请求匹配的所有验证性 Webhook。 匹配的 Webhook 将被并行调用。如果其中任何一个拒绝请求,则整个请求将失败。 该准入控制器仅在验证(Validating)阶段运行 ValidatingAdmissionPolicy 验证准入策略使用通用表达语言 (Common Expression Language,CEL) 来声明策略的验证规则,是一种声明式的、进程内的验证准入 Webhook 方案 MutatingAdmissionPolicy 提供了一种声明式的、进程内的方案, 可以用来替代变更性准入 Webhook 实现 步骤概览 实现一个 MutatingAdmissionWebhook 主要包括以下几个步骤: 生成证书,Kubernetes 和 Webhook 服务使用 TLS 加密通信 APIServer对Webhook的认证 Webhook对APIServer的认证(可选) 实现一个接口,接收AdmissionReview请求,解析并填充response字段,响应相同版本的AdmissionReview 部署上面接口,集群内外都可以 注册准入控制器 监控 Admission Webhook 以下面需求为例: ...

June 18, 2024 · 7 min · 1454 words · erpan

client-go SharedInformer

在client-go中,informer是一个核心的概念,用于从Kubernetes API服务器中读取对象。它可以监视一个或多个API对象,并在对象发生变化时自动更新本地缓存。 Informer主要组成部分: SharedInformerFactory SharedInformerFactory是创建并管理一组 informer 的入口。它会根据资源类型复用同一个 SharedIndexInformer,避免同一资源重复创建多个 informer。 Reflector Reflector负责和 Kubernetes API Server 交互。它会先执行一次 List 拉取当前对象集合,然后进入 Watch 循环持续监听变更。它把 List/Watch 的结果包装成 Delta,并交给后续的 FIFO 缓存。 DeltaFIFO DeltaFIFO是一个带去重和顺序处理能力的队列,用来缓存 Reflector 产生的增删改事件。它会把对象的变化状态按 Delta 组织起来,供 controller 处理。 SharedIndexInformer SharedIndexInformer是 informer 的核心实现。它负责把 Reflector 的结果落到本地缓存中,并把变化事件分发给注册的事件处理器。它内部通常包含一个 controller、一个 store/indexer,以及一个 sharedProcessor。 Indexer/Store Indexer 是 informer 本地缓存的核心抽象,底是一个线程安全的 store。它可以按对象名和索引进行查询,供 lister 和 handler 使用。 ResourceEventHandler ResourceEventHandler 是事件处理器接口,实现是 cache.ResourceEventHandlerFuncs,其中包含 AddFunc、UpdateFunc、DeleteFunc。它用于接收 informer 分发出来的对象变化事件。 ListerWatcher ListerWatcher 是 informer 用来执行 List/Watch 的接口,底层通常由 clientset 对应的资源 client 实现。 在运行时,Reflector 负责从 API Server 拿到变化,DeltaFIFO 负责缓存和去重,SharedIndexInformer 再把这些变化写入 Indexer,并通过 sharedProcessor 分发给注册的事件处理器。处理链路是:Reflector -> DeltaFIFO -> SharedIndexInformer -> SharedProcessor -> ResourceEventHandler。 ...

November 15, 2021 · 11 min · 2333 words · erpan

K8s网络原理基础精简梳理

TCP/IP 底层基础 应用层数据如何被逐层封装 核心规则:从上往下,每一层都把上层整体当作自己的「Payload(载荷)」,加上本层头部;到接收端反向逐层解封装。 发送方的封装顺序(由上层至下层): 应用层 → 传输层(TCP/UDP)→ 网络层(IP)→ 数据链路层(以太网帧)→ 物理层(比特流) 平铺结构: 1 2 3 4 5 6 7 【应用层数据】 ↓ 交给传输层 【TCP头 / UDP头】 + 【应用层数据】 → 传输层报文段(TCP) / 数据报(UDP) ↓ 交给网络层 【IP头】 + 【TCP头+应用数据】 → IP报文(三层包) ↓ 交给数据链路层 【以太网头(DMAC+SMAC+EtherType)】 + 【IP报文】 + 【FCS校验】 → 以太网帧(二层帧) 其中: 应用 Payload:业务原始数据(HTTP 网页、MySQL 查询、JSON 等,纯业务字节,没有协议头) TCP/UDP 眼里,应用数据就是它的 payload IP 眼里,整个 TCP+应用数据都是 IP 的 payload 以太网帧里,整个 IP 报文都是帧的 payload 标准无隧道、普通以太网帧结构 1 2 3 4 ┌─────────┬─────────┬────────────┬──────────┬──────────────┬──────┐ │ DMAC │ SMAC │ EtherType │ IP Header│ TCP/UDP+Payload│ FCS │ │ 6B │ 6B │ 2B │ 20~60B │ 应用数据 │ 4B │ └─────────┴─────────┴────────────┴──────────┴──────────────┴──────┘ DMAC:目标 MAC SMAC:源 MAC EtherType:0x0800 = IPv4;0x86DD = IPv6;0x8100 = 带 VLAN 标签 后面就是三层 IP 头、传输层、应用层原始数据 FCS:Frame Check Sequence,帧校验序列,算法是CRC‑32(循环冗余校验),做差错校验,检查这个帧在传输过程中,字节有没有被干扰、比特发生翻转、传错、损坏 关于MAC 地址 ...

September 20, 2021 · 10 min · 1931 words · erpan

为普通用户授权生成kubeconfig

概述 开发同学用kubectl查看线上Kubernetes集群中的一些情况,如何生成kubeconfig? 对指定的用户赋予合适的权限,首先需要明确这里的授权对象(用户)、该对象的认证方式、授权权限大小及授权方式几个概念。 在k8s集群中,当一个请求到达APIServer时,会经过多个阶段以执行访问验证、控制的行为,阶段顺序依次是: 传输安全,一般我们APIServer只开启https端口,建立TLS连接以确保传输安全 认证,请求到达APIServer后会依次尝试每个认证模块,有一个认证通过即可 鉴权,认证通过后进入到鉴权阶段,即判断特定的用户对特定的对象进行特定的操作是否有相应的权限 准入,鉴权通过则进入准入阶段,准入模块可以对请求进行验证和修改,多个准入控制器会被依次调用。有一个准入失败则立即响应拒绝服务 下面概括了认证授权相关的概念 用户 Kubernetes集群中的用户有两类: 服务账户serviceaccount,由k8s管理,绑定到指定的名称空间,每个sa与一个secret关联用以保存相关凭据 普通用户,集群中没有对应的资源专门管理普通用户,一般是在集群外管理的。这里当然也有用户组的概念 认证策略 身份认证策略有下面几种: 客户端证书:传递给APIServer的--client-ca-file=SOMEFILE参数指定了一个或多个证书机构,用此证书机构验证客户端提供的证书,验证通过则表示认证通过 持有者令牌 静态令牌:给APIServer传递--token-auth-file=SOMEFILE选项以启用 启动引导令牌:动态管理的令牌,一般用作平滑启动引导新集群 服务账户令牌:sa关联的secret中保存APIServer公开的CA证书和一个已签名的JWT令牌。一般在pod内使用,当然也可以在集群外部使用 OpenID Connect令牌:OAuth2方式 webhook令牌:用回调机制来验证令牌,Webhook插件用POST请求发送一个JSON序列化的对象到远程服务 静态密码 HTTP基本认证 用户伪装 身份认证代理 匿名 鉴权 鉴权主要有下面四个模块: Node:限制kubelet对APIServer的请求 ABAC:基于属性的访问控制 RBAC:基于角色的访问控制 Webhook:http回调,查询外部的REST服务 生成kubeconfig 利用ssl工具一步步生成 一般我们给开发同学的权限是只读的,那如何给单个开发同学或者开发组生成对应的kubeconfig以只读权限访问集群? 在kubeconfig文件中,包含的信息有用户(组)、集群地址、客户端的数字证书(或Bearer token,或basic auth)等信息。由集群CA签名的有合法证书的用户都是通过认证的用户,Kubernetes使用证书中的subject的通用名称(Common Name)字段作为用户名,Organization字段作为用户组信息。 因此可以为指定用户或用户组生成集群CA机构签发的客户端证书,以证书认证的方式访问APIServer。 常用的证书生成工具有easyrsa、cfssl和openssl,这里以openssl为例: 1 2 3 4 5 6 7 8 9 mkdir developer; cd developer/ # 生成私钥 openssl genrsa -out developer.key # 生成签名请求文件,CN为developer,可指定organization字段值作为组名 openssl req -new -key developer.key -out developer.csr -subj "/CN=developer" # 查看csr openssl req -noout -text -in developer.csr # 通过签名请求文件、集群CA证书及其私钥生成客户端签名证书 openssl x509 -req -in developer.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out developer.crt -days 3650 有了用户(组),且通过了集群身份认证,开始对其授权。集群中内置了一些常用的role和clusterrole,可以作为参考或者直接拿来用。此处将developer用户和内置的view这个clusterrole进行绑定,也可以为生成数字证书的时候指定的Organization组绑定对应的role或clusterrole ...

November 9, 2020 · 4 min · 703 words · erpan