前言

TKEx-CSIG 是基于腾讯公有云 TKE 和 EKS 容器服务开发的内部上云容器服务平台,为解决公司内部容器上云提供云原生平台,以兼容云原生、适配自研业务、开源协同为最大特点。

业务容器上云过程中,会遇到一些问题,有的需要业务进行容器化改造,有的需要平台赋能。平台赋能的部分,有一类问题是 CVM 场景下已经有解决方案的,而因运维方式不同在 Kubernetes 平台上不兼容的,比如 Pod 预授权的问题。我们希望用云原生的方式解决这一类问题并提供平台化的能力,让每一位用户都能够在平台上便捷的部署和管理自己的业务。

背景

新部署业务或者扩容,如何对新设备进行预授权?相信大家对这个问题并不陌生,基于安全考虑,公司内部往往重要组件、存储都会对访问请求进行来源控制,常见的如 CDB 的 IP 访问授权,OIDB、VASKEY 命令字的模块授权等。它们或者有自己的授权 WEB 可以让用户提单申请,或者提供授权 API 可以让运维平台调用。而路由系统往往在发现注册时需要准确获取 IP 设备的地域信息以提供就近访问的能力,这就需要预注册 CMDB。

在以前使用 CVM/TVM 部署业务时,这个问题可以较容易的处理,因为我们是预先拿到了一台虚拟机,已经分配好了 IP 注册好了 CMDB,业务要做的就是用这个 IP 去提单授权,部署业务程序,在一切完备后加上路由上线,这个过程是可以用运维平台的流水线能力做成自动化。

区别于 VM 的拿到可用设备后的步骤型过程化部署,Kubernetes管理的是 Pod 从生产、IP 分配、业务容器启动、路由维护的整个生命周期,由多个系统 Controller 的 Control Loop 做自动化的管理,基于镜像的部署提供了业务实例的伸缩一致性保障,Pod 的销毁重建变成常态,IP 也并非能固定下来。

业务往往面对多种预授权的需要,授权均值时间从秒级到几分钟不等,授权 API 大多并没有设计为承载高 QPS,有一定的复杂性。我们需要能找到一种方法,在 Pod IP 分配后,业务容器起来前处理授权,阻塞住并保障成功后再进行后续过程,并且控制重建过程对授权API的压力。

经过设计与迭代优化,TKEx-CSIG 平台提供给了业务易用的产品能力化的授权能力,方便应对这类 Pod 预授权的问题。

架构和能力解析

架构

上图所示是授权系统的架构,核心思路是使用 init Container 先于业务容器执行的特性,实现在业务 Pod 启动前进行复杂的逻辑预处理。官方对 init Container 的定义如下

  1. This page provides an overview of init containers: specialized containers that run before app containers in a Pod. Init containers can contain utilities or setup scripts not present in an app image

如果是小规模或单个业务的解决方案,我们是可以做的很简单,在业务 Worklooad yaml 中注入 init Container,调用需要的授权 API 实现即可,而要做成平台产品化的能力,还需要考虑以下几点:

  • 易用与可维护

    需要充分考虑业务使用上的效率和可管理性,将权限作为一项资源由平台记录管理,减小变更对业务的侵入性影响。

  • 限频与自愈

    权限 API 往往并没有对高 QPS 的设计,需要限制调用保护下游。

  • 权限收敛

    安全性,Pod 的销毁重建可能导致 IP 变化,考虑主动回收已经过期的权限

授权过程产品能力化

业务仅需在平台 WEB 控制台上登记需要的权限资源,配置权限组,关联权限组到 Workload,平台自动进行 init Container 的配置注入,通过 ENV 传递授权配置索引和相关信息,在 Pod 创建时进行授权过程。授权过程涉及的几个组件功能设计如下:

  • init-action-client

    init Container,仅作一个触发装置,仅做一件事,就是发起 HTTP 调用请求,保持不可变,这样当功能迭代时不必修改业务的 yaml,主逻辑后移处理

  • init-action-server

    deployment 部署可横向扩展,执行预处理逻辑,预注册 CMDB 等操作,并发起流水线调用,启动权限的申请过程并轮询查询,将过程信息关联 POD 暴露出来方便业务自查和管理员定位问题。后文提到的退避重试和断路器逻辑也在这里实现。

  • PermissionCenter

    平台管控组件,位于集群外,负责权限资源的存储和实际申请。包含一个权限资源中心,存储业务登记的权限详情参数方便复用,提供权限 Set 组管理,简化授权过程中的参数传递;使用生产者/消费者模式,基于 Pipline 实现授权 API 的调用和结果查询。

断路器和退避重试机制

可能导致授权过程的异常状况不少,例如权限参数错误的配置,授权 API 服务质量下降或不可用,甚至是网络原因导致的接口错误、超时等。授权 API 往往也并没有设计支持高 QPS,我们采用超时重试,加断路器和指数退避重试去做一个容错性。

  • 超时重试

    体现在接口调用和异步任务的超时设置与重试机制,应对瞬时故障,init-action-client 容器非正常退出也会进行重建,每次创建就是新一轮的重试。

  • 断路器

    使用一个 Configmap 专门记录集群里 Pod 权限申请的失败次数,3次即断路不给申请。并提供一个重置能力,暴露给前端,让用户和管理员可以便捷进行重试。

  • 指数退避

    断路器模式可以阻断用户配置错误这类永远也不可能授权成功的案例,但是无法应对长时间的瞬时故障。比如裁撤期,授权 API 后端可能会有一段时间的拒绝服务,10分钟到几小时,此时会有大量 Pod 授权命中断路器规则无法继续授权,人为处理时效性差也繁琐。我们为每个 Pod 添加了一个带抖动的指数退避器并记录最近的失败时间戳,能够在一段时间后允许尝试一次,如果成功就重置对指定 Pod 的退避,如若不成功更新时间戳重新计时,参数如下,

  1. bk := &PodBreaker{
  2. NamespacePod: namespacePod,
  3. LastRequestFailTime: time.Now(),
  4. Backoff: wait.Backoff{
  5. Duration: 2 * time.Minute,
  6. Factor: 2.0,
  7. Jitter: 1.0,
  8. Steps: 5,
  9. Cap: 1 * time.Hour,
  10. },
  11. }

Finalizer 收敛权限

权限的收敛问题往往被忽略,但是也是安全需要考虑的,Pod 的销毁重建可能是常态,IP 指不准也动态变化,长时间可能产生大量垃圾权限,或者已经授权过的 IP 分配到别的业务 Pod,产生安全风险。我们做了一个 Finalizer 控制器来在 Pod 销毁前进行权限回收,回收动作是幂等性的,而且是尽力而为的,因为回收的能力也依赖于权限方是否具备回收能力,我们对新对接的权限都会考虑这一点,比如腾讯云 MySQL 的 IP 自动授权。

为了减少打 Finalizer 的动作,尽可能不影响非授权关心的 Pod,我们只在 Pod 进行了变更事件时识别有授权 init Container 的 Pod,Patch 上 Finalizer 标记,在这些 Pod 缩容销毁时进行权限的回收并删除 Finalizer,随后 GC 会删除这个 Pod。

  1. kind: Pod
  2. metadata:
  3. annotations:
  4. ~
  5. creationTimestamp: "2020-11-13T09:16:52Z"
  6. finalizers:
  7. - stke.io/podpermission-protection

总结

本文解决的是业务使用容器平台时,在业务进程启动前的预处理如自动化授权的一类问题。使用 init Container 实现业务容器启动前的预处理,并将授权特性产品能力化让业务能较为方便的管理和申请权限资源,断路器和退避重试机制提供容错性,使用 Finalizer 提供一个回收的能力防止权限扩散。

参考文章

Init Containers

[译] 重试、超时和退避

Using Finalizers

【腾讯云原生】云说新品、云研新术、云游新活、云赏资讯,扫码关注同名公众号,及时获取更多干货!!

K8s 平台可以如何处理 Pod 预授权问题的更多相关文章

  1. 微服务架构 - 离线部署k8s平台并部署测试实例

    一般在公司部署或者真实环境部署k8s平台,很有可能是内网环境,也即意味着是无法连接互联网的环境,这时就需要离线部署k8s平台.在此整理离线部署k8s的步骤,分享给大家,有什么不足之处,欢迎指正. 1. ...

  2. 云平台将故障Pod流量下线通用思路与OpenShift操作实战

    1 写在前边 自从公司项目前年上了 OpenShift 3.9 私有云平台,更新部署程序的确变得更加容易了.但是带来了很多复杂性,运维实施人员的学习曲线也陡然上升. 上云之前:在项目没上容器云的早期, ...

  3. k8s运维之pod排错

    k8s运维之pod排错 K8S是一个开源的,用于管理云平台中多个主机上的容器化应用,Kubernetes的目标是让部署容器化变得简单并且高效 K8S的核心优势: 1,基于yaml文件实现容器的自动创建 ...

  4. k8s核心资源之Pod概念&入门使用讲解(三)

    目录 1. k8s核心资源之Pod 1.1 什么是Pod? 1.2 Pod如何管理多个容器? 1.3 Pod网络 1.4 Pod存储 1.5 Pod工作方式 1.5.1 自主式Pod 1.5.2 控制 ...

  5. k8s集群Job Pod 容器可能因为多种原因失效,想要更加稳定的使用Job负载,有哪些需要注意的地方?

    k8s集群Job Pod 容器可能因为多种原因失效,想要更加稳定的使用Job负载,有哪些需要注意的地方? 面试官:"计数性Job默认完成模式是什么?Indexed模式如何发布自定义索引呢?& ...

  6. 使用Port Forwarding连接k8s集群的pod(redis、mysql等)

    一. 创建Redis的deployment和service 1. 创建Redis deployment redis-master-deployment.yaml  apiVersion: apps/v ...

  7. linux运维、架构之路-K8s通过Service访问Pod

    一.通过Service访问Pod 每个Pod都有自己的IP地址,当Controller用新的Pod替换发生故障的Pod时,新Pod会分配到新的IP地址,例如:有一组Pod对外提供HTTP服务,它们的I ...

  8. kubeadm搭建K8s集群及Pod初体验

    基于Kubeadm 搭建K8s集群: 通过上一篇博客,我们已经基本了解了 k8s 的基本概念,也许你现在还是有些模糊,说真的我也是很模糊的.只有不断地操作去熟练,强化自己对他的认知,才能提升境界. 我 ...

  9. 12.深入k8s:kubelet创建pod流程源码分析

    转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com 源码版本是1.19 在上一篇中,我们知道在kubelet中,工作核心就是围绕着整个syn ...

随机推荐

  1. 双端口RAM和多模块存储器

    目录 双端口RAM 存取周期 双端口RAM 多模块存储器 普通存储器 单体多字存储器 多体并行的存储器 高位交叉编址的多体存储器 低位交叉编址的多提存储器 为什么要这么弄? 高位 低位 流水线(考试常 ...

  2. db2常用操作

    1. db2建立远程节点编目及删除 db2 catalog tcpip node nodeName remote remoteIp server remotePort db2 list node di ...

  3. ADF 第五篇:转换数据

    映射数据流(Mapping Data Flow)的核心功能是转换数据,数据流的结构分为Source.转换和Sink(也就是Destination),这种结构非常类似于SSIS的数据流. 在数据流中,数 ...

  4. vue第十七单元(电商项目逻辑处理,电商划分)

    第十七单元(电商项目逻辑处理,电商划分) #课程目标 1.什么是电商项目 2.什么是B2B,B2C,C2C模式,常见的电商项目 3.移动端电商项目常见的逻辑处理 4.[知识扩展]传统系统架构及分布式系 ...

  5. 一劳永逸,解决基于 keep-alive 的后台多级路由缓存问题

    用过 vue-element-admin 的同学一定很清楚,路由的配置直接关系侧边栏导航菜单的展示,也得益于这种设计思路,几乎大部分后台框架都采用这个方案,当然也包括了我写的 Fantastic-ad ...

  6. Asp.Net Core使用MongoDB

    MongoDB 是一个基于分布式且面向文档存储的开源 NoSql数据库系统 MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的.它支持的数据结构 ...

  7. Asp.Net Core仓储模式+工作单元

    仓储模式+工作单元 仓储模式 仓储(Repository)模式自2004年首次作为领域驱动模型DDD设计的一部分引入,仓储本质上是提供提供数据的抽象,以便应用程序可以使用具有接口的相似的简单抽象集合. ...

  8. ASP.NET Core 3.1使用 AutoMapper

    多层架构中存在多种模型,如视图模型ViewModel,数据传输对你DTO,ORM对象等,这些数据在层与层之间进行传输必须涉及类型之间的转换. AutoMapper是一个对象-对象映射器,作用是通过设置 ...

  9. 关于yaml文件格式和bootstrap文件

    yaml文件格式简洁层次分明 语法规则如下 大小写敏感 使用缩进表示层次关系 在缩进时不允许使用tab键,只允许使用空格 缩进的空格不重要,只要相同层级的元素左侧对齐即可(相同缩进为同一级) serv ...

  10. 利用 Watermill 实现 Golang CQRS

    CQRS CQRS 的意思是"命令-查询责任隔离".我们分离了命令(写请求)和查询(读请求)之间的责任.写请求和读请求由不同的对象处理. 就是这样.我们可以进一步分割数据存储,使用 ...