<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>koala bear</title>
    <description></description>
    <link>http://wsfdl.com/</link>
    <atom:link href="http://wsfdl.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Wed, 24 Jul 2024 16:38:03 +0000</pubDate>
    <lastBuildDate>Wed, 24 Jul 2024 16:38:03 +0000</lastBuildDate>
    <generator>Jekyll v3.9.5</generator>
    
      <item>
        <title>再读《聪明的投资者》—— Review 近 3 年观点</title>
        <description>&lt;h2 id=&quot;id-2021-年初认知与判断&quot;&gt;2021 年初认知与判断&lt;/h2&gt;

&lt;p&gt;上次阅读《聪明的投资者》时，那是在 2021 年初，基于一些认知和假设，形成一些措施和判断。&lt;/p&gt;

&lt;p&gt;认知和假设&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;基于世界工厂、优质劳动力、人口优势、基础设施和勤奋的特点，得出持续有力发展的假设&lt;/li&gt;
  &lt;li&gt;楼市和股市是普遍大众可以享受国运发展的红利的工具，长期应该定投&lt;/li&gt;
  &lt;li&gt;信息技术依旧是最朝阳的行业&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;判断与措施&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;道琼斯、S&amp;amp;P 500、沪深 300 等指数值得持续定投；BRK 增加持仓。&lt;/li&gt;
  &lt;li&gt;长三角、珠三角一二线的城市值得持续持续购买。&lt;/li&gt;
  &lt;li&gt;计算机依旧是最具有增长的行业，从业人员不值得所谓副业；如果有唯一的副业，那就是做好存量资本增值。&lt;/li&gt;
  &lt;li&gt;需要关注生活本身，赋予生命的多样性：家庭、工作、生活、爱好和社交。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;如果从《聪明的投资者》来看，结论应该是作为一个防御的投资者，只需执行如下操作&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;债券和 S&amp;amp;P 500 指数&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;id-2024-年初的回顾&quot;&gt;2024 年初的回顾&lt;/h2&gt;

&lt;p&gt;时至今日，有些判断逻辑不够严谨&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;人口优势、勤奋是发展有利条件，但不是充分条件，“法治”、“自由”、“公平”是效率持续创新的基础条件。&lt;/li&gt;
  &lt;li&gt;关于楼市股市是发展的红利工具本身没有错，但是得考虑租售比和市盈率等要素。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;有些措施没有很好的得到执行，有些错误没有得到及时的纠正&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;美股指数持续的定投没有得到落实，BRK 只闻其名，一路看着它涨，一路错过；而对于中丐股，则在期待回调中一路加仓，一路亏损，甚至动用杠杆。&lt;/li&gt;
  &lt;li&gt;房市年化 1.x% 租金收益率，完全不值得投资甚至拥有；它日回到 3~4% 租金收益是更好的持有选择。近 3 年最正确操作就是没有买房子，特别是没有购买学区房。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;让我们从实际收益数字来看，近 3 年来：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;道琼斯指数增长近 30%，S&amp;amp;P 500 增长 40%，BRK 增长近 80%；CSI 300 下跌 40%，美股的中丐更是下跌 60%-80%。考虑到汇率的变化，其差异性将进一步放大。&lt;/li&gt;
  &lt;li&gt;一二线城市，普遍跌幅近 20-30%，个别学区房近 50%。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;值得一提的是，2023 年中进行 Review，再次阅读此书籍，针对债券、基金、股票、房地产、Reits 等投资的收益进行统计分析，从长期收益率、市盈率、流动性和风险等，对于过去的错误进行纠正。经过半年多的实践，得到市场良好的肯定。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;当前合适的市盈率下，持续定投 SReits，5~6% 的分红，加上几个点的增值，8+% 年化回报率符合预期。&lt;/li&gt;
  &lt;li&gt;持续购买中长期国债，锁住 5% 基本无风险的年后收益。&lt;/li&gt;
  &lt;li&gt;小尝试市盈率很、长期营收稳健、长期分红，股息率近 8% 公共事业股，持有后收益很符合预期。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;一些正确的认知需要持续落实。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;信息技术依旧是最朝阳的行业，最大的精细之处是 AI 在模型和应用持续百花齐放，过往很多在计算视觉的算法全部被神经网络所替代，值得持续期的投入。&lt;/li&gt;
  &lt;li&gt;追求生活的幸福感，追求多样性和可能性。&lt;/li&gt;
  &lt;li&gt;在长期持有的耐心上，基本得到肯定。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;id-2024-年观点与措施&quot;&gt;2024 年观点与措施&lt;/h2&gt;

&lt;p&gt;鉴于深刻教训，调整认知和假设，得出的结论是做一个傻瓜，做一个虔诚的信徒，跟着大师。具体实操上又回到大师经典的观点。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;头部重点定投好债券与 S&amp;amp;P 指数和 BRK，并定期调整比例；小部分试试低风险、收益合理的资产。&lt;/li&gt;
  &lt;li&gt;房产在合适价格出手；新加坡 HDB 具备良好属性。&lt;/li&gt;
  &lt;li&gt;追求生活的幸福感，追求多样性和可能性。&lt;/li&gt;
&lt;/ol&gt;
</description>
        <pubDate>Sun, 31 Mar 2024 00:00:00 +0000</pubDate>
        <link>http://wsfdl.com/%E7%BC%96%E7%A8%8B%E9%9A%8F%E6%83%B3/2024/03/31/the-intelligent-investor-again.html</link>
        <guid isPermaLink="true">http://wsfdl.com/%E7%BC%96%E7%A8%8B%E9%9A%8F%E6%83%B3/2024/03/31/the-intelligent-investor-again.html</guid>
        
        
        <category>编程随想</category>
        
      </item>
    
      <item>
        <title>The tail at large scale 阅读笔记</title>
        <description>&lt;p&gt;本人曾支持业务优化大规模服务容量，长尾请求是优化的最大瓶颈之一。本文结合论文和经验做小结沉淀：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;构建模型分析长尾请求对服务的影响、衡量消除长尾请求的收益。&lt;/li&gt;
  &lt;li&gt;针对 Paper 的观点，谈谈工程领域具体实现方案，以及方案适用条件和优缺点。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;注：本文很多经验来自不同团队，本人整理用于个人学习。&lt;/p&gt;

&lt;h2 id=&quot;id-模型分析&quot;&gt;模型分析&lt;/h2&gt;

&lt;p&gt;业务采用 SLI、Latency 黄金指标衡量服务稳定性，SLI 计算如下：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;QPS_success = QPS_total - QPS_error&lt;/p&gt;

  &lt;p&gt;SLI = QPS_success / QPS_total&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;通常大部分错误请求为超时的长尾请求。&lt;/p&gt;

&lt;h3 id=&quot;id-服务-sli-成本模型&quot;&gt;服务 SLI 成本模型&lt;/h3&gt;

&lt;p&gt;服务 SLI 和营收有密切关系，SLI 过低通常对业务有损，表现为用户的体验下降甚至直接影响营收；其次大量 SLI 告警影响研发同学效率。&lt;/p&gt;

&lt;p&gt;增加硬件资源通常可以提升服务的 SLI，一个典型微服务的 SLI 和服务 CPU 利用率关系如下，在资源固定的情况，随着服务请求上涨，CPU 利用率近乎线性上升，服务 SLI 缓慢下降，直到某个临界点服务 SLI 急剧降低：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://wsfdl.oss-cn-qingdao.aliyuncs.com/tail-at-large-scale-sli.png&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;SLI 99% 时，服务 CPU 平均利用率为 60%&lt;/li&gt;
  &lt;li&gt;SLI 99.9% 时，服务 CPU 平均利用率为 50%&lt;/li&gt;
  &lt;li&gt;SLI 99.99% 时，服务 CPU 平均利用率约为 20%&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This content is only supported in a Feishu Docs
每提升服务 SLI 一个 9，需要付出越来越大资源成本，单业务收益呈现指数递减，因此服务 SLO 本质资源开销和业务收益的权衡。我们优化的目标是在给定资源下，通过多种手段降低因长尾导致的错误请求，提升 SLI，为业务优化容量奠定基础；进而在满足 SLO 的条件下，通过缩容降低资源成本，最终提升资源效率。&lt;/p&gt;

&lt;h3 id=&quot;id-服务-sli-稳定性模型&quot;&gt;服务 SLI 稳定性模型&lt;/h3&gt;

&lt;p&gt;如 Paper 所言，造成长尾请求的因素多种，单机维度因素占主要部分。针对某个服务，假定每个节点请求的成功率为 p，它需要依赖会汇聚来自 n 个节点的请求，简化版的服务层面请求的成功率(SLI)为：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;SLI = f(p)，其中f(p) =  p^n&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;id-引起长尾因素&quot;&gt;引起长尾因素&lt;/h2&gt;

&lt;p&gt;造成长尾请求的因素有多种，本人所见和 Paper 大体相似，如下为一些典型场景：
节点层面&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;机器故障：机器故障导致问题，在百万节点的系统中，每天故障机器的数量非常可观。&lt;/li&gt;
  &lt;li&gt;硬件差异：不同的机型在磁盘、CPU、网卡的能力不同，差机型更容易成为瓶颈。&lt;/li&gt;
  &lt;li&gt;资源共享：超售和混部导致资源竞争，比如 CPU 受限、磁盘和网卡打满，影响服务稳定性。&lt;/li&gt;
  &lt;li&gt;流量差异：服务框架层(mesh)流量不均，造成部分实例热点问题。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;非节点层面&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;网络拓扑问题，如交换机网卡故障或者网络打满。&lt;/li&gt;
  &lt;li&gt;业务自身问题。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;id-方案&quot;&gt;方案&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;it advantageous to develop tail-tolerant techniques that mask or work around temporary latency pathologies, instead of trying to eliminate them altogether.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;非常认同 Paper 如上观点，长尾问题持续困扰研发同学，并且多个团队持续投入了大量精力优化。手段可以分为两类：1. 持续提升节点请求的成功率 p；2. 优化稳定性模型，给定 p 下提升服务的 SLI。&lt;/p&gt;

&lt;h3 id=&quot;id-提升请求成功率-p&quot;&gt;提升请求成功率 p&lt;/h3&gt;

&lt;h4 id=&quot;id-事前消除潜在风险&quot;&gt;事前消除潜在风险&lt;/h4&gt;

&lt;p&gt;解决或者缓解导致长尾的因素是最直接的手段，其思路在于找出根因和从根本上解决问题。影响节点请求成功率的因素原因多种多样而难以穷举，很难提前预测与防范，通常由问题驱动，分锅到家，往往耗费巨大的人力用于定位问题、分析原因、提供方案和 A/B 验证效果，如下是常见的问题，每一类问题都可以展开非常大的篇幅进行讨论。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;单机稳定性：超售、混部等环境下，资源竞争和较低隔离能力造成大量的单机抖动问题。&lt;/li&gt;
  &lt;li&gt;流量均衡问题：因框架原因导致热点实例流量过高而引起的问题。&lt;/li&gt;
  &lt;li&gt;硬件能力：老旧机型算力差、HDD 磁盘、故障率高导致老旧机型成为木桶短板。&lt;/li&gt;
  &lt;li&gt;业务问题。&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;id-事后降低影响范围&quot;&gt;事后降低影响范围&lt;/h4&gt;

&lt;p&gt;单机因素导致实例异常时，异常通常会持续较长一段的时间。通过引入反馈机制，该机制快速鉴别异常实例，实施措施，降低异常实例影响时间，从而提升请求成功率 p。&lt;/p&gt;

&lt;p&gt;该措施依赖如下约束：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;指标系统：一套描述服务实例指标，一套实时、稳定的指标存储、索引系统。&lt;/li&gt;
  &lt;li&gt;异常规则：定义异常的指标规则。&lt;/li&gt;
  &lt;li&gt;实施措施：通过移除或者重建异常实例，降低异常实例的影响时间。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;具体落地上，可实施的系统为：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;服务框架：基于业务实例的 SLI、时延和持续时间等指标，采用限流和熔断措施降低异常实例的影响。&lt;/li&gt;
  &lt;li&gt;运营系统：基于机器和实例的基础指标，如 load (可引入业务指标)，识别和下线异常机器，驱逐和异地重建异常实例。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;反馈机制属于事后规避，其实时性和准确性受指标链路、异常规则的影响；而通用性是其优点。从实际经验来看，反馈机制是落地难度较低，效果良好。&lt;/p&gt;

&lt;h3 id=&quot;id-优化容错模型&quot;&gt;优化容错模型&lt;/h3&gt;

&lt;h4 id=&quot;id-对冲请求&quot;&gt;对冲请求&lt;/h4&gt;

&lt;p&gt;Paper 中对冲请求指的是针对每个请求，当该请求在一定时间(如 p99)未完成，那么再发送一个请求。从服务 SLI 稳定性模型来看，此时 SLI 和 p 的关系如下：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;f(p) =（p + p&lt;em&gt;(1-p)）^n ；其中 p + p&lt;/em&gt;(1-p) &amp;gt; p&lt;/p&gt;

  &lt;p&gt;举例来看，假定 p 为 0.99，n 为 1，通过额外发送 1% 的请求，可以将成功率提升至 0.9999。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;大规模的实施对冲请求存在很多客观约束，具体落地上，合适实施的系统为框架层或者 Mesh。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;指标系统：一套描述服务实例的指标，一套实时、稳定性的指标存储、索引系统。&lt;/li&gt;
  &lt;li&gt;时延评估：服务时延是一个动态的指标，它随着请求量而上下波动，也随着业务需求和服务迭代而动态变化，二次&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;请求的阈值需要精准的评估标准。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;标准化的服务框架：归类时延错误，封装和抽象重试触发条件和操作。&lt;/li&gt;
  &lt;li&gt;服务幂等的规范性：重试仅仅适用幂等操作，用户需要在幂等性上规范。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;理论上对冲请求付出较低资源开销，即可良好地消除长尾问题。它的缺点是：1. 依赖标准的框架和规范的接口，同时要求精确的设定时延阈值；2. 提升链路追踪的复杂度；3. 极端情况或加剧雪崩。&lt;/p&gt;

&lt;p&gt;Paper 还提到“Tied Requests”概念，即发送两个请求，当其中一个请求被处理时，该请求和会向另外一个请求发送一个取消的指令。该思路大大增加系统交互的复杂度，笔者其通用性表示质疑。&lt;/p&gt;

&lt;h4 id=&quot;id-分级思想&quot;&gt;分级思想&lt;/h4&gt;

&lt;p&gt;Paper 简单的提及服务分级，并在一些系统中优先处理高级别的服务。从模型上来看，既然平均请求的成功率是一定的，可以通过牺牲低优服务的成功率，提升高优服务的成功率，从而优化服务的整体质量。&lt;/p&gt;

&lt;p&gt;分级的思想在很多个层面会用到，比如在容灾上对业务进行分级，当出现大规模资源故障，或者流量突发时，通常保证有限的资源供给给高优的服务，对低优的服务进行降级，保障系统的整体运行。在在离线混部，我们会对资源进行分级，针对不同级别的资源提供不同的 QoS 能力，这些能力贯穿 CPU、内存、网络和磁盘 IO。&lt;/p&gt;

&lt;p&gt;分级的难点在落实级别的定义，以及针对每个级别，多个系统需要提供的 QoS 具体的如何，各个系统的 QoS 是否具备良好的协同等等。&lt;/p&gt;

&lt;h4 id=&quot;id-业务兜底&quot;&gt;业务兜底&lt;/h4&gt;

&lt;p&gt;在一些 feed 流系统上，为了获取最佳的排序效果，一个请求可能会依赖非常多的下游做出最佳的排序，而不少下游服务是 nice to have 的，因此针对此类场景。业务侧可以提供多个层次的兜底措施，请求时延和请求结果上进行权衡。从模型来看，业务兜底本质降低了对 n 的依赖，从而在 p 一定的条件下提升服务整体的 SLI。&lt;/p&gt;

&lt;p&gt;业务兜底的具体实现因场景而异，诸如兜底的级别、策略等等。常见于 feed 流系统，比如视频、广告、商品等业务场景的排序，而 feed 流通常是非常核心的系统，因此通常会引入多个层次的兜底手段，保证系统的高可靠性。&lt;/p&gt;
</description>
        <pubDate>Tue, 05 Mar 2024 00:00:00 +0000</pubDate>
        <link>http://wsfdl.com/architecture/2024/03/05/tail-at-large-scale.html</link>
        <guid isPermaLink="true">http://wsfdl.com/architecture/2024/03/05/tail-at-large-scale.html</guid>
        
        
        <category>Architecture</category>
        
      </item>
    
      <item>
        <title>坡岛杂记一</title>
        <description>&lt;p&gt;当飞机降落在 changyi 机场后，相比温馨而富丽堂皇的机场内饰，肤色和语言的多元化更是它与众不同之处。作为世界的“十字路口”之一，changyi 机场无疑是繁忙的，繁忙的同时保持着良好的秩序，鲜有黑压压万人空巷之感。每座城市都有它的内涵，每个人因自身的经历对每座城市都会形成认知的标签，生活半年后，“多元”和“秩序”是这座城市给我于最深刻的印象。&lt;/p&gt;

&lt;p&gt;城市即是国家，国家即是城市，700 多平方公里的国土面积，500 多万的人口，因此在一些大陆朋友口中又调皮的称为 “坡岛”、“坡县”，但是人均 GDP 和发达程度乃至世界翘楚。&lt;/p&gt;

&lt;p&gt;新加坡没有四季，四季如夏，比较科学的方式是分为两个季候风季节，1/2 月的雨季，7/8 月的旱季。作为在四季分明生活数十年的人来说，雨季和旱季其实没啥区别，相近的温度，相近的日照时间，通常是早上晴朗，中午起云，下午几声惊雷来把雨，一个有趣的习惯是几乎没有带过伞。云销雨霁之后，晚霞依旧，此时若躺在 Marina south pier 的堤坝上，听涛声依旧，惬意不过如此。没有四季的轮转，时间总是白驹过隙的毫无征兆，唯有月份的数字猛然提醒：哦，原来过了一个季度了；妈呀，咋又半年过去了。常年 27-30 度的气温，虽然如同夏季，却又比大陆大部分城市的 7/8 月份舒适很多，蚊子是夏季最惹人烦怨生物，但是在这里是不存在的，女士可以开开心心的穿着裙子短裤，尽显风姿。也许如候鸟一样，飘来飞去是一种不错的生活方式 —— 春秋在杭州，冬夏在新加坡。&lt;/p&gt;

&lt;p&gt;多样的肤色和语言，融合了多样的菜系。从大陆海南、潮州、福建等流传的粿条、菜头粿、鱼肉丸、海南鸡饭、烧腊、各类面食等等；马来的炒饭、沙爹（一种酱汁腌制过的烧烤）、椰浆饭等；印度的万料之王——咖喱；南洋咖啡、娘惹菜系是本土的特色，结合了多个民族的特点；不仅东方，这里也汇聚了西方的美食，恕我对西餐不知，故不细说。不变的四季如一如既往的应季水果，榴莲、凤梨、甘蔗，还有它们鲜榨加冰的果汁。如零星点缀散落在各地的“小食阁”是各类餐食的集大成者，在物价惊人大背景下，仅用 20-30 人民币即可用填饱肚子，也实属惊奇。有人说，相比于欧美，新加坡是美食的天堂；相比于中国大陆，又显得有几份普通。作为习惯了杭帮菜、湘川菜的人来说，对于以酱汁为灵魂的食物，显得总有几份不适。有趣的是，无论是吃的，还是喝的，包括饮用水，绝大部分从国外进口；此外这里的食物也通常是很小一份，“一份差点饱，两份吃撑了”，所以这边的男性女性肥胖相对少见。&lt;/p&gt;

&lt;p&gt;“住”绝对是新加坡的一大特色，“居者有其屋”背景下诞生的 HDB 绝对值得用另外一篇文章娓娓道来。新加坡的住宅可以分为大致两大类(不做严格细分)：80% 祖屋(HDB)和 20% 公寓，祖屋相当于政府的福利性分房，新加坡公民用等同大陆三线城市的价格即可购买；公寓类似于商品房，购买的群体限制性稍小，颜值和小区的配套设施更好些，价格介于一线和二线城市之间。在疫情和中美竞争加剧的背景下，新加坡成了受益者，无论是资金还是人才，都源源不断的流入新加坡，带来了楼市的飞涨，包括房价和租金。总体来说，目前的租售比是非常的吃香，4-5% 的年华收益率。新加坡的交通整体比较便利，只是打车昂贵，由于公交和地铁并不拥挤，冷气十足，鲜有异味，所以整体体感不错。&lt;/p&gt;

&lt;p&gt;“我们大部分人本科毕业就工作了，很少有人读硕士和博士。”，“专业上第一考虑的是医学，其次是金融、律师，接着是计算机，不过在几年前，计算机属于冷门专业。”，上述几句出自本土的小伙伴们之口，在学历和就业选择上和中国的差异存在较大的理念差异。“精英”和“务实”在其教育体系中体系的淋漓尽致，也包括在产业的转型上。几年前，作为本土的信息技术企业，被誉为东南亚的 “小腾讯” Sea 在游戏和电商业绩斐然，同时在各个大陆信息技术企业出海的大背景下，新加坡的信息技术迎来了爆炸式的增长。当然，还有 web3 和数字货币，眼看他起朱楼，眼看他宴宾客，眼看他楼塌了！&lt;/p&gt;

&lt;p&gt;“勤奋”和“居安思危”似乎是华人两大特点，新加坡也不例外，润是万万不可能的。应该说新加坡提供了一种可能性，一种体验城市，一种体验国家，一种体验生活，一种丰富经历的机会，有人喜欢，有人不适，有人哭，有人笑，如生活百态，适合自己，方是最好。&lt;/p&gt;

</description>
        <pubDate>Sun, 11 Jun 2023 00:00:00 +0000</pubDate>
        <link>http://wsfdl.com/%E7%BC%96%E7%A8%8B%E9%9A%8F%E6%83%B3/2023/06/11/sg-life.html</link>
        <guid isPermaLink="true">http://wsfdl.com/%E7%BC%96%E7%A8%8B%E9%9A%8F%E6%83%B3/2023/06/11/sg-life.html</guid>
        
        
        <category>编程随想</category>
        
      </item>
    
      <item>
        <title>KubeZoo 的核心理念 —— 协议转换（二）</title>
        <description>&lt;blockquote&gt;
  &lt;p&gt;注：KubeZoo 是本人参与的项目，此文主要由本人撰写，遂同步到个人博客。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;本文是 KubeZoo 系列技术文章的第二篇，将重点介绍 KubeZoo 的核心理念和关键实现 —— 协议转换。&lt;/p&gt;

&lt;p&gt;KubeZoo 的项目地址请见：https://github.com/kubewharf/kubezoo&lt;/p&gt;

&lt;h2 id=&quot;id-理念简介&quot;&gt;理念简介&lt;/h2&gt;

&lt;p&gt;从租户的视角来看，无论是 namespace scope 还是 cluster scope 的资源，用户都有完整和独立的视角，比如租户 A 拥有名字为 foo 的 namespace，租户 B 也可以拥有名字为 foo 的 namespace，而且这两个 namespace 只是名字一样，其资源和权限实际上是互相隔离的。但是从 Kubernetes 的视角来看，其对 namespace 的资源要求在 namespace 内是命名唯一的，对于 cluster scope 的资源，其要求在全局上是命名唯一的。&lt;/p&gt;

&lt;p&gt;当所有的租户都共享同一个 Kubernetes 时，为了解决多个租户具备完整独立视角和 Kubernetes 要求在 namespace/scope cluster 不同层次命名的唯一性的矛盾，我们提出了协议转换的理念，从而解决命名唯一性的问题。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://wsfdl.oss-cn-qingdao.aliyuncs.com/kubezooovervie2.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;如上图所示，由于每个租户的名字/Id 是全局唯一的，因此如果在相关的资源名字上增加租户的标志，也就间接保证了在实际的 Kubernetes 控制面上保证了资源全局的唯一性；从租户的视角来看，如果我们对租户呈现其资源时，将相关的前缀剥离，即保证了租户的真实呈现视角和隔离性。以 namespace 视角为例，比如租户 tenant2 有 default 和 prod 两个 namespace，其在上游的真实 namespace 则是加上了租户的前缀，故为 tenant2-default 和 tenant2-prod。因此 KubeZoo 在租户和上游的 Kubernetes 集群充当了中间的转换适配层，接受租户的请求和上游 Kubernetes 的返回，并根据不同类型的资源进行不同的处理。&lt;/p&gt;

&lt;h2 id=&quot;id-核心实现&quot;&gt;核心实现&lt;/h2&gt;

&lt;p&gt;KubeZoo 基于“协议转换”核心理念实现控制面多租户功能，通过在资源的 name/namespace 等字段上增加租户的唯一标志，从而解决不同租户的同名资源在同一个上游物理的 K8s 冲突问题，该思想和 Linux 内存管理有如出一辙之处。&lt;/p&gt;

&lt;p&gt;K8s 原生 API 大致可以被划分为如下 4 类：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Namespace scope：如 pod, pvc, statefulset, deployment etc；&lt;/li&gt;
  &lt;li&gt;Cluster scope：如 pv, namespace etc；&lt;/li&gt;
  &lt;li&gt;Custom：用户定义的资源；&lt;/li&gt;
  &lt;li&gt;Non-resource：如 openapi / healthz / livez / readyz 以及日志监控等 etc。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;通过对上述 API 采取对应的协议转换方案，最终为绝大部分的 API 提供多租户能力，经分析检验， KubeZoo 的一致性测试通过率高达 86%。&lt;/p&gt;

&lt;h3 id=&quot;id-namespace-scope-资源&quot;&gt;Namespace Scope 资源&lt;/h3&gt;

&lt;p&gt;K8s 大概有 40 多种 namespace scope 的资源，比如 deployment / statefulset / pod / configmap 等。通过在每个资源的 namespace 字段关联租户信息，从而实现 namespace scope 资源的多租户能力。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://wsfdl.oss-cn-qingdao.aliyuncs.com/kubezoonamescope.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;对于租户不同类型的请求，KubeZoo 首先从请求的证书中解析租户信息，之后具体转换如下:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;POST：在 request body 的 namespace 和 request url 的 namespace(如果有的话) 字段添加租户前缀，然后将请求转发至上游 K8s 完成资源创建；对于 response body，删除 namespace 中的租户前缀，最后把请求返回给租户。&lt;/li&gt;
  &lt;li&gt;GET
    &lt;ul&gt;
      &lt;li&gt;查询/监听 某个资源：在 request url 的 namespace 字段增加租户前缀，然后将请求转发至上游 K8s 完成资源查询；对于 response body，去除 namespace 中的租户前缀，最后把请求返回给租户；&lt;/li&gt;
      &lt;li&gt;罗列/监听 ns 的资源：在 request url 的 namespace 字段增加租户前缀，调整 label selector 中涉及 namespace 相关的值，然后将请求转发至上游 K8s 完成资源查询；对于 response body，去除 namespace 中的租户前缀，最后把请求返回给租户；&lt;/li&gt;
      &lt;li&gt;罗列/监听 租户的资源：查询上游 K8s所有此类资源，KubeZoo 根据 namespace 的租户前缀匹配本租户的所有此类资源；同时去除 namespace 中的租户前缀，最后把请求返回给租户。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;PUT：在 request body 的 namespace 和 request url 的 namespace(如果有的话) 字段添加租户前缀，然后将请求转发至上游 K8s 完成资源更新；对于 response body，去除 namespace 中的租户前缀，最后将请求返回给租户。&lt;/li&gt;
  &lt;li&gt;DELETE
    &lt;ul&gt;
      &lt;li&gt;删除某个资源：在 request url 的 namespace 字段增加租户前缀，然后将请求转发至上游 K8S 完成资源删除；对于 response body，去除 namespace 中的租户前缀，最后将请求返回给租户；&lt;/li&gt;
      &lt;li&gt;删除某些资源：在 request url 的 namespace 字段增加租户前缀，调整 label selector 涉及 namespace 相关的值，然后罗列符合要求的资源，对于属于本租户的资源，逐个删除；对于 response body，去除 namespace 中的租户前缀，最后把请求返回给租户。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;对于 POST / GET / PUT 操作的协议转换过程，所依赖的 ownerReference 资源名字也需要做相关处理，对于 Cluster Scope 的资源名字，其处理逻辑请见下节“Cluster Scope Resource”；对于 Custom Resouce 的资源名字，其处理逻辑等请见下文“Custom Resource”。ownerReference 的命名转换是普遍适用的场景，不仅适用于本节 namespace scope resource，还包括 cluster scope resource 和 custom resource 等，后文不再累述。&lt;/p&gt;

&lt;h3 id=&quot;id-cluster-scope-资源&quot;&gt;Cluster Scope 资源&lt;/h3&gt;

&lt;p&gt;K8s 大概有 20 多种 cluster scope 的资源，比如 pv / namespace / storageclass 等等。通过在 name 关联租户信息，从而实现 cluster scope 资源的多租户能力。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://wsfdl.oss-cn-qingdao.aliyuncs.com/kubezooclusterscope.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;对于租户不同类型的请求，KubeZoo 首先从请求的证书中解析租户信息，之后具体转换如下:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;POST：在 request body 的 name 字段添加租户前缀，然后将请求转发至上游 K8S 完成资源创建；对于 response body，去除 name 中的租户前缀，最后把请求返回给租户。&lt;/li&gt;
  &lt;li&gt;GET
    &lt;ul&gt;
      &lt;li&gt;查询/监听 某个资源：在 request url 的 name 字段增加租户前缀，然后将请求转发至上游 K8s 完成资源查询；对于 response body，去除 name 中的租户前缀，最后把请求返回给租户；&lt;/li&gt;
      &lt;li&gt;罗列/监听 租户的资源：查询上游 K8s 所有此类资源，KubeZoo 根据 name 匹配的租户前缀匹配本租户的所有此类资源；同时去除 name 中的租户前缀，最后把请求返回给租户。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;PUT：在 request body 的 name 和 request url 的 name（如果有的话）字段添加租户前缀，然后将请求转发至上游 K8s 完成资源更新；对于 response body，去除 name 中的租户前缀，最后将请求返回给租户。&lt;/li&gt;
  &lt;li&gt;DELETE
    &lt;ul&gt;
      &lt;li&gt;删除某个资源：在 request url 的 name 字段增加租户前缀，然后将请求转发至上游 K8s 完成资源删除；对于 response body，去除 name 中的租户前缀，最后将请求返回给租户；&lt;/li&gt;
      &lt;li&gt;删除某些资源：罗列符合要求的资源，对于属于本租户的资源，逐个删除；对于 response body，去除 name 中的租户前缀，最后把请求返回给租户。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;对于 node 类型的资源，由于 KubeZoo 方案是倾向由弹性容器提供数据面多租户的能力，因此上游集群不会纳管实际的计算节点，故实现上采取屏蔽 node 类型的资源的做法。&lt;/p&gt;

&lt;h3 id=&quot;id-custom-资源&quot;&gt;Custom 资源&lt;/h3&gt;

&lt;p&gt;Custom Resource Definition（CRD）是一种特殊的 cluster scope 资源，由于其 name 由 group + plural 组成，我们选择在 group 前缀关联租户信息，除此处细节差异外，其它的逻辑则和上述 “cluster scope resource” 基本保持一致，详情如下图所示。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://wsfdl.oss-cn-qingdao.aliyuncs.com/kubezoocustom.png&quot; alt=&quot;Image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Custom Resource（CR）可以分为 namespace scope 和 cluster scope，我们以 namespace scope 的 CR 的请求为例，KubeZoo 从证书解析租户信息后，具体的转换逻辑如下：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;POST： 往 request url 的 group / namespace 和 request body 的 group / namespace 字段添加租户前缀，然后将请求转发至上游 K8s 完成资源创建；对于 response body，去除 group / namespace 中的租户前缀，最后将请求返回给租户。&lt;/li&gt;
  &lt;li&gt;GET
    &lt;ul&gt;
      &lt;li&gt;查询/监听 某个资源：向 request url 的 group / namespace 字段增加租户前缀，然后将请求转发至上游 K8s 完成资源查询；对于 response body，去除 group / namespace 中的租户前缀，最后把请求返回给租户。&lt;/li&gt;
      &lt;li&gt;罗列/监听 ns 的资源：在 request url 的 group / namespace 字段增加租户前缀，调整 label selector 中和 namespace 相关的值，然后将请求转发至上游 K8S 完成资源查询；对于 response body，去除 namespace / group 中的租户前缀，最后把请求返回给租户。&lt;/li&gt;
      &lt;li&gt;罗列/监听 租户的资源：查询上游 K8S 所有此类 CR，KubeZoo 根据 group 匹配的租户前缀匹配本租户的所有此类资源；对于 response body，去除 namespace / group 中的租户前缀，最后把请求返回给租户。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;PUT：往 request url 的 group / namespace 和 request body 的 group / namespace  字段添加租户前缀，然后将请求转发至上游 K8s 完成资源更新；对于 response body，去除 group / namespace 中的租户前缀 ，最后把请求返回给租户。&lt;/li&gt;
  &lt;li&gt;DELETE
    &lt;ul&gt;
      &lt;li&gt;删除某个资源：向 request url 的 group / namespace 字段正确的注入租户信息，然后将请求转发至上游 K8s 完成资源删除；对于 response body，去除 group / namespace 中的租户前缀，最后将请求返回给租户。&lt;/li&gt;
      &lt;li&gt;删除某些资源：在 request url 的 group / namespace 字段增加租户前缀，调整 label selector 涉及 namespace 相关的值，然后罗列符合要求的资源，对于属于本租户的资源，逐个删除；对于 response body，去除 group / namespace 中的租户前缀，最后把请求返回给租户。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;对于 cluster scope 的 CR，结合上述逻辑易于推导，此处不再详述。&lt;/p&gt;

&lt;h3 id=&quot;id-cross-reference-资源&quot;&gt;Cross Reference 资源&lt;/h3&gt;

&lt;p&gt;需要注意的是，同一租户的不同类型的资源 Spec 中的字段可能会存在资源引用的依赖情况，pvc 的 spec.volumeName 为对应的 pv，大体上可以将引用分为两类：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;namespace 内引用：例如 pod 引用 pvc / configmap / serviceaccount 等，此类上下游资源为 namespace scope 资源，且同属一个 namespace，因此不需要做任何处理。&lt;/li&gt;
  &lt;li&gt;namespace 与 cluster 之间引用： pvc 引用 cluster scope pv，serviceaccount 引用 clusterrolebinding 等。对于此类的资源，需要准确理解其资源字段的含义，并在 KubeZoo 解析其 Body，完成资源名字的准确转换。
以 pvc 具体 case 为例，租户视角的 pvc：&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mypvc
  namespace: default
  ......
spec:
  volumeName: pv-cb23c200-f249-11ea-9039-3497f65a8415
  ......
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;上游 K8s 视角的 pvc：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mypvc
  namespace: foofoo-default
  ......
spec:
  volumeName: foofoo-pv-cb23c200-f249-11ea-9039-3497f65a8415
  ......
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;常见涉及 namespace 和 cluster 之间交叉依赖的资源如下：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;clusterrole&lt;/li&gt;
  &lt;li&gt;clusterrolebinding&lt;/li&gt;
  &lt;li&gt;endpoint&lt;/li&gt;
  &lt;li&gt;endpointslice&lt;/li&gt;
  &lt;li&gt;pv&lt;/li&gt;
  &lt;li&gt;pvc&lt;/li&gt;
  &lt;li&gt;role&lt;/li&gt;
  &lt;li&gt;rolebinding&lt;/li&gt;
  &lt;li&gt;tokenreview&lt;/li&gt;
  &lt;li&gt;volumeattachment&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;id-non-resource-资源&quot;&gt;Non-resource 资源&lt;/h3&gt;

&lt;p&gt;除了上述核心资源以外，K8s 还有一部分 Non-resource API，主要包括监控、日志、Doc 等等。&lt;/p&gt;

&lt;p&gt;对于 readyz / healthz / livez / version 等类型近 60 个 GET 类型的 API，这些 API 主要用于表示 master / etcd / poststarthook 各类 controller 的健康状况、版本信息等。因此对于此类 API KubeZoo 只需要将请求转发至下游 K8S 即可。&lt;/p&gt;

&lt;p&gt;对于 /openapi/v2 API，KubeZoo 首先需要从上游 K8s 获取其支持的 openapi 资源，并从相关的资源过滤出租户的 CRD，然后合并原生 API 资源，最终返回给租户。&lt;/p&gt;

&lt;p&gt;对于 /metrics API，这些 metrics 信息无法从租户粒度进行区分，且对于托管版本的 Serverless K8S 用户作用相对有限，因此暂不考虑支持详细的租户级别的 metrics。&lt;/p&gt;

&lt;p&gt;对于 /logs API，由于其仅简单展示访问的审计信息，因此暂未支持详细的租户级别的 logs。从实现的角度可以在 KubeZoo 侧提供记录和审计能力，并将审计信息存储到 KubeZoo 的存储中。&lt;/p&gt;

&lt;h2 id=&quot;id-小结&quot;&gt;小结&lt;/h2&gt;

&lt;p&gt;本文详细介绍了 KubeZoo 的核心理念和详细设计，从而保证了资源隔离的视图和逻辑的准确性；由于不同类型的资源存在一些差异，因此针对 namespace scope、cluster scope、custom 和 non-resource 等类型的资源做了分别的处理，既提供了隔离能力，又保证了准确性。&lt;/p&gt;
</description>
        <pubDate>Tue, 16 Aug 2022 00:00:00 +0000</pubDate>
        <link>http://wsfdl.com/kubernetes/2022/08/16/kubezoo_2.html</link>
        <guid isPermaLink="true">http://wsfdl.com/kubernetes/2022/08/16/kubezoo_2.html</guid>
        
        
        <category>Kubernetes</category>
        
      </item>
    
      <item>
        <title>Kubernetes 多租户 KubeZoo 简介（一）</title>
        <description>&lt;blockquote&gt;
  &lt;p&gt;注：KubeZoo 是本人参与的项目，此文主要由本人撰写，首发于&lt;a href=&quot;https://mp.weixin.qq.com/s?__biz=Mzk0NDMzNjkxNw==&amp;amp;mid=2247484226&amp;amp;idx=1&amp;amp;sn=74cb05f2f1ce8a0abecd4806694bac9d&amp;amp;chksm=c3277a38f450f32e6b938483edb8ef765582cb7a32a6b42e66ba45b4cafe44ca86010063f0ca&amp;amp;scene=21&quot;&gt;公众号&lt;/a&gt;，遂同步到个人博客。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;KubeZoo 是为 K8S 轻量级多租户项目，它基于协议转换的核心理念在一个物理的 K8S Master 上虚拟多个租户，具备轻量级、兼容原生 API 、无侵入等特点，是一种打造 Serverless K8S 底座的优良方案。&lt;/p&gt;

&lt;h2 id=&quot;id-背景&quot;&gt;背景&lt;/h2&gt;

&lt;p&gt;从 2014 年开源至今，Kubernetes 已经成为容器编排领域的事实标准，为开发者进行应用编排、提高资源利用率提供了极大便利。但面对集群管理，如何提升多租户集群管理能力仍是困扰开发者和企业的一个关键问题。&lt;/p&gt;

&lt;p&gt;以私有云为例。在这类环境中，企业的云原生基础设施大多被微服务平台、大数据、机器学习和存储云原生等平台占据，它们对上层用户屏蔽 Kubernetes 的细节，呈现的是各自的接口和体验。&lt;/p&gt;

&lt;p&gt;虽然屏蔽底层有助于开发人员更专注于业务本身，但现实中仍有不少业务需要独立的 Kubernetes 构建其系统所运行的环境设施，这些业务通常形态各异，资源体量小，但是却要求独占和完整的 Kubernetes。如何提供和管理这些小 Kubernetes 集群成为一个痛点，Cluster API 提供了集群自动化管理的能力，但是对基础设施成熟度有较高的要求。&lt;/p&gt;

&lt;p&gt;无独有偶，在公有云上，各大云供应商托管着客户成千上万的集群，但是超过 100 个 ECS 节点的集群寥寥无几。事实上，绝大部分 Kubernetes 集群的规格都非常之小，几十核、上百核是常态。相比计算资源，托管版的 Kubernetes 的控制面占据了一定的资源，如高可靠的 Master 和 etcd 等等，这些免费的组件占据了相当比例的成本。&lt;/p&gt;

&lt;p&gt;因此，增强 K8s 集群控制面的多租户能力已经成了一个现实问题：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;从运维视角来看，即使 Kubernetes 具备自动化的集群生命周期管理，但是各项控制面组件的维护、升级，和周边庞杂设施的交互，对开发人员来说仍是棘手的问题。&lt;/li&gt;
  &lt;li&gt;随着机器学习任务、大数据平台接入云原生基础设施，基于 Kubernetes 打造的系统底座需要提供更快速、更低成本、更高效的管理 Kubernetes 集群的能力。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;id-kubernetes-多租户模型简介&quot;&gt;Kubernetes 多租户模型简介&lt;/h2&gt;

&lt;p&gt;伴随云原生技术的发展和推广，社区内已经先后涌现出多种方案，提供了不同层次的多租户能力，并在特定场景下具备一定优势。此前社区 Kubernetes Multi-Tenancy Working Group 曾进行了梳理归纳，定义了如下 3 种 Kubernetes 多租户模型。&lt;/p&gt;

&lt;h3 id=&quot;id-namespace-as-a-servicenaas&quot;&gt;Namespace as a Service（NaaS）&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;https://wsfdl.oss-cn-qingdao.aliyuncs.com/nameasaservice.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Namespace 是 Kubernetes 原生的资源，提供了原生的基于命名空间的多租户能力。众所周知，Kubernetes 的对象分为两种类型：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;第一种是 namespace scope，比如常见的 deployment、pod 和 pvc 等，这类资源通常比较常用，为一般的用户所使用。&lt;/li&gt;
  &lt;li&gt;第二种是 cluster scope，比如 pv、clusterrole 等，这类资源通常需要更高的权限，一般由管理员管理。&lt;/li&gt;
  &lt;li&gt;由于这些比较通用的资源可以划分到某个 namespace 下，而 namespace 具备一定的权限和视图隔离能力，管理员可以通过为不同的租户分配不同的 namespace，并合理的设定租户的 RBAC、Network Policy 和 Quota，实现租户之间资源和视图一定程度的隔离。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;这种方案的优点是不同租户共享相同的控制面和计算资源池，运维成本低、管理高效，比较适合仅依赖 namespace scope API 的私有云场景；缺点则是多个租户共享一个 K8s 集群，每个租户被限定在自己的 namespace，租户一般只能访问 namespace scope 的资源，通常不具备 cluster scope 的权限，故 API 访问很受限。&lt;/p&gt;

&lt;h3 id=&quot;id-cluster-as-a--servicecaas&quot;&gt;Cluster as a  Service（CaaS）&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;https://wsfdl.oss-cn-qingdao.aliyuncs.com/caas.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;顾名思义，Cluster as a Service 则是为每个租户分配一个完整的集群，包括独占的控制面和数据面。如此每个租户都有独立的 Master 和计算节点，该 Master 可以通过 Cluster API 等方式完成租户 Master 的生命周期管理。&lt;/p&gt;

&lt;p&gt;在实现上，Master 可以容器化部署，也可以部署在虚拟机或者物理机上；而计算节点通常为虚拟机或者物理机。如此每个租户拥有一套独立的控制面组件（apiserver, controller-manager, scheduler, etcd），租户间完全隔离，互相不干扰，安全性和隔离性得到绝对的保障；缺点为每个租户的管理成本和资源成本较高。&lt;/p&gt;

&lt;h3 id=&quot;id-control-planes-as-a-servicecpaas&quot;&gt;Control Planes as a Service（CPaaS）&lt;/h3&gt;

&lt;p&gt;不难看出，NaaS 多租户之间完全共享控制面和数据面，而 CaaS 的控制面和数据面是完全隔离的。那么有没有一种介于此的中间形态，在隔离性和灵活性之间能得到良好的权衡？&lt;/p&gt;

&lt;p&gt;这就是社区提出的第三种模式：Control Planes as a Service，在此形态下每个租户拥有独立的 Master（又称为 virtual cluster），因而它们在控制面上是独占和隔离的，也可以拥有灵活的 K8s 版本；但是在数据面上，各个租户共享相同的资源池。&lt;/p&gt;

&lt;p&gt;这种形态典型的代表是 Virtual Cluster 项目，它在一个名为 supercluster 的 K8s 集群上容器化部署租户的控制面，因而各个租户拥有完整而隔离的 Kubernetes Master，可以自主的管理 namespace scope 和 cluster scope 的各类资源；但是在计算资源上，各个租户共享 supercluster 的计算资源池，虽然在数据面未达到彻底隔离的形态，但是胜在共享统一的资源池，利于提升资源效率和灵活性。&lt;/p&gt;

&lt;h3 id=&quot;id-小结&quot;&gt;小结&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt; &lt;/th&gt;
      &lt;th&gt;NaaS&lt;/th&gt;
      &lt;th&gt;CaaS&lt;/th&gt;
      &lt;th&gt;CPaaS&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;资源成本&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;高(需要多副本 master/etcd)&lt;/td&gt;
      &lt;td&gt;高(需要多副本 master/etcd)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;运维成本&lt;/td&gt;
      &lt;td&gt;低，管理 namespace&lt;/td&gt;
      &lt;td&gt;高，管理大量的 master 和计算资源池&lt;/td&gt;
      &lt;td&gt;中，管理大量的 master&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;创建效率&lt;/td&gt;
      &lt;td&gt;高，毫秒级创建&lt;/td&gt;
      &lt;td&gt;低，十分钟级别创建&lt;/td&gt;
      &lt;td&gt;中，分钟级创建&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;API 的兼容性&lt;/td&gt;
      &lt;td&gt;低，cluster scope 资源受限&lt;/td&gt;
      &lt;td&gt;高，兼容所有的 API&lt;/td&gt;
      &lt;td&gt;高，支持绝大部分 API&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;隔离安全&lt;/td&gt;
      &lt;td&gt;低&lt;/td&gt;
      &lt;td&gt;高&lt;/td&gt;
      &lt;td&gt;高&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;场景说明&lt;/td&gt;
      &lt;td&gt;私有云场景&lt;/td&gt;
      &lt;td&gt;公有云场景&lt;/td&gt;
      &lt;td&gt;私有云/公有云场景&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;综上深入分析，不难发现不同多租户方案各有侧重的场景，都尝试在成本、效率和安全之间进行权衡。上述方案一定程度提供了路径手段，但是依旧不够完美。&lt;/p&gt;

&lt;p&gt;在公司业务发展过程中，由 K8s 集群控制面的多租户功能带来的诸多困扰同样存在，基础架构团队期望近乎零成本、兼容 Kubernetes 原生 API 的多租户能力：一方面，它要具备极低的资源和运维成本、秒级的生命周期管理、原生的 API 和安全能力，能稳定支撑业务发展；另一方面，它也能面向团队技术演进方向 Serverless 展开设计，更好地兼容未来。&lt;/p&gt;

&lt;p&gt;为了达成这个目标，我们推出了轻量级多租户解决方案 KubeZoo，并把它开放给社区。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://wsfdl.oss-cn-qingdao.aliyuncs.com/overviewkubezoo.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;id-kubezoo-简介&quot;&gt;KubeZoo 简介&lt;/h2&gt;

&lt;p&gt;本章重点介绍 KubeZoo 的架构和核心思想，包括总体架构、租户管理、控制面多租户（协议转换）和数据面多租户等等。&lt;/p&gt;

&lt;h3 id=&quot;id-理念简介&quot;&gt;理念简介&lt;/h3&gt;

&lt;p&gt;KubeZoo 基于“协议转换”核心理念实现控制面多租户功能，通过在资源的 name/namespace 等字段上增加租户的唯一标志，从而解决不同租户的同名资源在同一个上游物理的 K8s 冲突问题。&lt;/p&gt;

&lt;p&gt;如前文所述，Kubernetes 的资源大致可以分为两大类型：namespace scope 和 cluster scope。其中，对于 namespace scope 的资源，同一种资源在相同的 namespace 下命名唯一；对于 cluster scope 类型的资源，同一种资源的命名全局唯一，不可重复。&lt;/p&gt;

&lt;p&gt;在同一个 Kubernetes 下，开发人员可以在 namespace scope 资源的 namespace 上增加租户的前缀，在 cluster scope 资源的 name 上增加前缀，通过保证不同租户的前缀不一样，最终解决不同租户在资源命名重复冲突的问题，这种思想和 Linux 内存管理有些异曲同工之妙。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://wsfdl.oss-cn-qingdao.aliyuncs.com/kubezooarch.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;id-架构概览&quot;&gt;架构概览&lt;/h3&gt;

&lt;p&gt;KubeZoo 作为一个独立的服务部署于 Kubernetes 前端，对用户提供统一的访问入口，它接受用户的请求，并将请求经过处理后转发给后端的 Kubernetes，进而由上游的集群真正完成资源的表达，最终将结果返回给用户。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://wsfdl.oss-cn-qingdao.aliyuncs.com/kubezooarch1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;在具体结构上，KubeZoo 由一个 kubezoo-server 进程和 etcd 组成，其中 KubeZoo 作为无状态组件，可以以多主的形式部署，具备良好的横向扩容能力，etcd 主要提供租户的元信息的存储，就数据体量上非常轻，同时访问频率也较低，理论上不存在性能相关瓶颈。&lt;/p&gt;

&lt;p&gt;KubeZoo 重点提供了控制面的隔离，对数据面的实现并没有相关的约束。如果数据面为常规的 Kubernetes 节点池，那么数据是共享的，隔离性等同 CPaaS；如果数据面采用云上的弹性容器服务，如 AWS Fargate、Aliyun ECI、火山引擎 VCI 等，则可以借用公有云的基础设施完成计算、存储和网络的隔离和表达能力，同时具备良好的弹性能力，这也是本文推荐的后端数据面载体。&lt;/p&gt;

&lt;h3 id=&quot;id-租户管理&quot;&gt;租户管理&lt;/h3&gt;

&lt;p&gt;KubeZoo 内置 Tenant 对象，用于描述租户的基本信息，相关的结构体如下。其中 name 是必须字段，全局唯一，长度固定 6 位字符串（包括字符或者数字），理论上可以管理 2176782336 个租户（36 ^ 6），Tenant 对象存储于 KubeZoo 的 etcd 中：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://wsfdl.oss-cn-qingdao.aliyuncs.com/kubezootenantyml.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;KubeZoo 提供证书签发的功能，管理员拥有 Tenant 生命周期管理的能力。每当管理员创建租户后，即为该租户签发一份 X509 证书，证书中包含了租户的信息，如名字等等，并写入 annotations；同时将每个租户内置的 namespace、rbac 等同步到上游的 K8s 中。&lt;/p&gt;

&lt;p&gt;每当管理员删除租户时，会触发租户资源回收，KubeZoo 删除上游 K8s 该租户的所有资源，并清理 KubeZoo 侧的元信息。&lt;/p&gt;

&lt;p&gt;由于租户的生命周期管理本质上是 Tenant 对象元信息的管理、证书签发和资源同步，因而过程简洁，无需创建物理的 Master / etcd 和计算资源池，因而其具备轻量级、秒级的海量租户生命周期管理能力。&lt;/p&gt;

&lt;h3 id=&quot;id-安全设计&quot;&gt;安全设计&lt;/h3&gt;

&lt;h4 id=&quot;id-认证&quot;&gt;认证&lt;/h4&gt;

&lt;p&gt;KubeZoo 支持证书（X509）和 ServiceAccount 两种类型的凭据。这两种凭据均属于 PKI（Public key infra）token，故 KubeZoo 只需要和上游 K8s Master 共用相同的 CA 即可实现凭据的认证功能，并提取出租户信息。&lt;/p&gt;

&lt;p&gt;对于管理员签发的 X509 证书，每当创建租户时，会将 Subject.OrganizationalUnit 字段设置为租户名称，进而完成证书的签发。每当 KubeZoo 收到租户的请求时，首先认证证书的有效性，进而解析证书中 OrganizationalUnit 字段，判断租户的真实性。&lt;/p&gt;

&lt;p&gt;对于租户签发的 Service Account(SA) 证书，由于其本质上是 jwt token，解析后包含了 namespace 字段，因为上游 K8s 集群中租户的 namespace 已经包含了租户信息前缀，故租户签发的 SA 同样包含了租户信息，KubeZoo 首先认证 jwt token 的有效性，进而从 namespace 中解析出租户信息，进而判断租户的真实性。&lt;/p&gt;

&lt;h4 id=&quot;id-流量管理&quot;&gt;流量管理&lt;/h4&gt;

&lt;p&gt;KubeZoo 基于令牌桶的原理实现租户的流控管理，包括租户流量隔离，即租户互不干扰，恶意租户（短时间内发送大量 API 请求）不会影响其他租户；租户流量加权，即允许管理员为不同租户设置不同权重，允许高优租户发送更多并发请求。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://wsfdl.oss-cn-qingdao.aliyuncs.com/limittraffic.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;管理员创建租户时通过在 Tenant annotation 中的 tce.kubezoo/max-requests-inflight 字段设置来自该租户请求的最大并发数。KubeZoo 会统计当前租户的并发数（令牌数），每当收到来自某个租户的请求时，KubeZoo 会查看该租户下的 bucket 是否有令牌，如果有，则拿取一个并处理相关的需求，请求结束后归还令牌；如果并发数超过上限，即令牌为空，则拒绝该请求。&lt;/p&gt;

&lt;h2 id=&quot;id-总结&quot;&gt;总结&lt;/h2&gt;

&lt;p&gt;本文 KubeZoo 基于协议转换的理念为 Kubernetes 多租户提供了一种新的思路，相比已有的方案，它具备轻量级、兼容原生 API 、无侵入等特点，或是一种打造 Serverless K8s 底座的优良方案。&lt;/p&gt;
</description>
        <pubDate>Sat, 30 Jul 2022 00:00:00 +0000</pubDate>
        <link>http://wsfdl.com/kubernetes/2022/07/30/kubezoo_1.html</link>
        <guid isPermaLink="true">http://wsfdl.com/kubernetes/2022/07/30/kubezoo_1.html</guid>
        
        
        <category>Kubernetes</category>
        
      </item>
    
      <item>
        <title>Borg: the Next Generation 阅读笔记</title>
        <description>&lt;p&gt;本文是 Borg(2020) 的阅读笔记，主要梳理要点，并联系实践谈谈一些感受。&lt;/p&gt;

&lt;h1 id=&quot;id-intro&quot;&gt;Intro&lt;/h1&gt;

&lt;p&gt;和 2015 年论文相比，Borg 近几年扩展不少功能和优化性能，进一步提升了资源利用率。有趣的是，从 Parent-child dependencies(DAG)、新增 Batch 调度器、BE 贡献了大部分新增资源利率等现象推断，Borg 重点加大了对离线业务的支持。&lt;/p&gt;

&lt;p&gt;近几年是云原生化高歌猛进的几年，也是深度学习、大数据体系拥抱云原生的重要年份。和不少业内同行交流下来有趣的是：不少公司的深度学习已经实现云原生化，而在线服务体系却停留在虚拟机时代。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The 2019 trace has several new features.
    &lt;ul&gt;
      &lt;li&gt;allocations&lt;/li&gt;
      &lt;li&gt;parent-child dependencies&lt;/li&gt;
      &lt;li&gt;additional placement constraints&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;The workload mix has changed: free tier -&amp;gt; best-effort batch.&lt;/li&gt;
  &lt;li&gt;The scheduling rate is higher: 3.7X Job, 7X task.&lt;/li&gt;
  &lt;li&gt;A very heavy-tailed distribution of job sizes.&lt;/li&gt;
  &lt;li&gt;Vertical autoscaling is effective.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;id-a-quick-summary-of-borg&quot;&gt;A quick summary of Borg&lt;/h1&gt;

&lt;p&gt;主要进一步扩展了资源的类型，大大提升了 Priority 的表达空间。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Free tier: incur no internal charges, and have no Service Level&lt;/li&gt;
  &lt;li&gt;Best-effort Batch (beb) tier: managed by the batch scheduler and incur low internal charges&lt;/li&gt;
  &lt;li&gt;Mid-tier: jobs in this category offer SLOs weaker than those offered to production tier workloads&lt;/li&gt;
  &lt;li&gt;Production tier：jobs in this category require high availability&lt;/li&gt;
  &lt;li&gt;Monitoring tier&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;主要是为了解决什么问题呢？其次这些类型的资源应该 Mapping 到什么类型任务比较合适呢？&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;id-comparing-the-2011-and-2019-traces&quot;&gt;Comparing the 2011 and 2019 traces&lt;/h1&gt;

&lt;p&gt;本章节主要介绍了 2011 年到 2019 年的主要变化：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Job priority values.&lt;/li&gt;
  &lt;li&gt;Normalized CPU units: to help its users better handle machine heterogeneity, Borg has switched to using abstract Google Compute Units (GCUs) instead of physical CPU cores, and the trace follows suite. An allocation of 1 GCU should provide about the same amount of computational power on any machine in the fleet, and Borg maps that onto the appropriate number of physical CPU cores&lt;/li&gt;
  &lt;li&gt;Alloc sets: these allow users to reserve resources on machines into which jobs can later be scheduled.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;场景从何而来？&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;Job dependencies.&lt;/li&gt;
  &lt;li&gt;Batch queuing: supports multiple schedulers, including a batch scheduler that manages.
the aggregate batch job workload for throughput.&lt;/li&gt;
  &lt;li&gt;Vertical scaling: Autopilot.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;从本人理解来看，Borg 单集群规模基本保持不变，每个集群的节点数量在 1W 左右；但是单个节点的规格增加许多，其次机房规模更加庞大。从功能的视角来看主要丰富了 Batch Scheduling / VPA / Job Dependency / Alloc Sets 等特性，而这些特性重点专注于离线的场景。Normalized CPU units 是非常有趣的话题，大厂每年均会采购数量不菲的机器，而机器的寿命通常在 3-4 年，因此很容易存在大量不同规格且不同代际的硬件资源，造成 task 之间的能力参差不齐，最终因木桶效应而影响 Job 的整体性能。Borg 采用了对算力归一化的做法，提供了算力公平性的分配的一种可行思路。&lt;/p&gt;

&lt;h1 id=&quot;id-resource-utilization&quot;&gt;Resource utilization&lt;/h1&gt;

&lt;p&gt;Borg 的资利用率提升了近 50%，其中 BE 类型资源贡献了大部分利用率的提升：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;CPU：40 -&amp;gt; 60%，其中在线部分带来 25 % -&amp;gt; 30%，BE + Mid Tier 3% -&amp;gt; 23%。&lt;/li&gt;
  &lt;li&gt;Mem：40 -&amp;gt; 60%，在线少量增加，BE + Free + Mid Tier 贡献 20+%。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;此外超售更加激进，利用率的衡量上增加了方差指标，客观上反应算力和任务的更加合理的匹配，降低热点效应。&lt;/p&gt;

&lt;h1 id=&quot;id-evolution-in-the-scheduling-load&quot;&gt;Evolution in the scheduling load&lt;/h1&gt;

&lt;p&gt;如下是 Scheduler 的吞吐变化，在上万节点的集群规模下，1K Pod/s 吞吐对 K8S 而言挑战不小。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;964 jobs/hour -&amp;gt; 3360 jobs/hour&lt;/li&gt;
  &lt;li&gt;166 tasks/s -&amp;gt; 1162 tasks/s&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;id-vertical-scaling&quot;&gt;Vertical scaling&lt;/h1&gt;

&lt;p&gt;AutoPilot 是 Vertical Scaling 具体实现，感兴趣可以参考相关论文。从个人经验来看，VPA 的落地场景挑战比较大，放眼业内大规模的实践实乃凤毛麟角。&lt;/p&gt;

&lt;h1 id=&quot;id-lessons-learned-from-trace-generation&quot;&gt;Lessons learned from trace generation&lt;/h1&gt;

&lt;p&gt;8 年过去了，Borg 坚持面向自助式的思路，提供丰富的文档介绍、技术工具基于自助式的排查。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Exposing enough details without losing focus&lt;/li&gt;
  &lt;li&gt;Providing explanations for unreasonable cases&lt;/li&gt;
  &lt;li&gt;Automated validation&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;id-research-directions&quot;&gt;Research directions&lt;/h1&gt;

&lt;p&gt;Gang Scheduler 的引入容易带来额外的计算开销、各个集群直接的指标方差、大客户和长尾客户的权衡也是各个调度系统在实践过程中常见的问题。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Explainable scheduling.&lt;/li&gt;
  &lt;li&gt;How far can overcommittment be pushed.&lt;/li&gt;
  &lt;li&gt;Gang scheduling.&lt;/li&gt;
  &lt;li&gt;Inter-cell variations.&lt;/li&gt;
  &lt;li&gt;Scheduling to combat heavy tails.&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Tue, 03 May 2022 00:00:00 +0000</pubDate>
        <link>http://wsfdl.com/architecture/2022/05/03/borg-2020.html</link>
        <guid isPermaLink="true">http://wsfdl.com/architecture/2022/05/03/borg-2020.html</guid>
        
        
        <category>Architecture</category>
        
      </item>
    
      <item>
        <title>Large-scale cluster management at Google with Borg 阅读笔记</title>
        <description>&lt;p&gt;本文是阅读 Borg 的笔记，主要梳理其概要，并联系实践谈谈一些感受。&lt;/p&gt;

&lt;h1 id=&quot;id-guide&quot;&gt;Guide&lt;/h1&gt;

&lt;p&gt;Guide 章节 High Level 概括其如何实现高利用率和高可靠的能力，熟悉 K8S 同学对此不会陌生。&lt;/p&gt;

&lt;p&gt;It achieves high utilization by combining:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Admission control.&lt;/li&gt;
  &lt;li&gt;Efficient task-packing(scheduling).&lt;/li&gt;
  &lt;li&gt;Over-commitment.&lt;/li&gt;
  &lt;li&gt;Machine sharing with process-level performance isolation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It supports high-availability applications with runtime features that minimize:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Fault-recovery time.&lt;/li&gt;
  &lt;li&gt;Scheduling policies that reduce the probability of correlated failures.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;id-introduction&quot;&gt;Introduction&lt;/h1&gt;

&lt;p&gt;本章节简要介绍其特点，它们在 K8S 中体现的淋漓尽致:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Hides the details of resource management and failure handling so its users can
focus on application development instead&lt;/li&gt;
  &lt;li&gt;Operates with very high reliability and availability, and supports applications that do the same;&lt;/li&gt;
  &lt;li&gt;Lets us run workloads across tens of thousands of machines effectively&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;id-the-user-perspective&quot;&gt;The User Perspective&lt;/h1&gt;

&lt;h3 id=&quot;id-业务类型&quot;&gt;业务类型&lt;/h3&gt;

&lt;p&gt;Borg 将业务分为两大类型，即 Prod(基本为在线) 和 Non-Prod(基本为离线)；从资源量上来说，不少互联网公司的在离线资源比例也大概在 2:1 左右。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Prod: 70% Alloc, 60% Usage&lt;/li&gt;
  &lt;li&gt;Non-Prod: 30% Alloc, 40% Usage&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;id-机房拓扑&quot;&gt;机房拓扑&lt;/h3&gt;

&lt;p&gt;从业内实践来看，很少见跨机房建设 K8S 集群；进一步而言，可以结合网络拓扑来更加的规范集群的建设，如此有利于容灾和弱化不同层次交换机网络亲和性的调度诉求。从规模上而言，规模化的 K8S 集群在数千台节点级别，少部分公司可达上万节点。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The machines in a cell belong to a single cluster, defined by the high-performance datacenter-scale network fabric that connects them.&lt;/li&gt;
  &lt;li&gt;A cluster lives inside a single datacenter building, hosts one large cell with 10k.&lt;/li&gt;
  &lt;li&gt;Borg isolates users from most of these differences by determining where in a cell to run tasks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;id-任务的属性&quot;&gt;任务的属性&lt;/h3&gt;

&lt;p&gt;如下是 Borg 任务携带的属性：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;processor architecture, OS version, or an external IP address, resource requirements((CPU cores, RAM, disk space, disk access rate, TCP ports). we don’t impose fixed-sized buckets or slots.&lt;/li&gt;
  &lt;li&gt;Owner, binary, config etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;id-alloc&quot;&gt;Alloc&lt;/h3&gt;

&lt;p&gt;A Borg alloc (short for allocation) is a reserved set of resources on a machine.&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;What’s alloc?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;id-priority-quota-and-admission-control&quot;&gt;Priority, quota, and admission control&lt;/h3&gt;

&lt;p&gt;资源类型上，Borg 提供更丰富的层次，并且定义其抢占策略和准入逻辑。K8S 也继承了资源的等级思想，并且针对不同等级的资源在调度、单机管控上拥有不同的优先级。从业内实践来看，大部分玩家对此类特性并不关注，本质是对它们而言，在从虚拟机迈入容器化时代的过程中，需要保证业务的平滑体验和稳定性。只有少量成熟且拥有海量资源的玩家，对优先级、抢占等特性十分关注，因为这是提升资源利用率的重要手段。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Monitoring, production, batch, and best effort.&lt;/li&gt;
  &lt;li&gt;We disallow tasks in the production priority band to preempt one another.&lt;/li&gt;
  &lt;li&gt;Quota-checking is part of admission control, not scheduling: jobs with insufficient quota are immediately rejected upon submission.&lt;/li&gt;
  &lt;li&gt;A low-priority job may be admitted but remain pending (unscheduled) due to insufficient resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;id-naming-and-monitoring&quot;&gt;Naming and monitoring&lt;/h3&gt;

&lt;p&gt;BNS 命名的体系携带集群的标志，推测其服务治理体系大概率和集群信息挂钩，对于集群维度的容灾等有一定的收益，K8S 在服务治理体系基本是不太关注集群信息。关于状态检查和 Event 事件，K8S 也大同小异；从运维经验来看，如果可以详细记录 K8S 管控面和数据面的各类重要信息，并存入 ES 等引擎中，将大大提升运维效率。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Borg name service (BNS) name for each task that includes the cell name, job name, and task number.&lt;/li&gt;
  &lt;li&gt;Health-check.&lt;/li&gt;
  &lt;li&gt;If a job is not running Borg provides a “why pending?” annotation, together with
guidance on how to modify the job’s resource requests to better fit the cell.&lt;/li&gt;
  &lt;li&gt;Borg records all job submissions and task events, as well as detailed per-task resource usage information in infrastore.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;id-borg-architecture&quot;&gt;Borg architecture&lt;/h1&gt;

&lt;h3 id=&quot;id-arch&quot;&gt;Arch&lt;/h3&gt;

&lt;p&gt;Borg 的架构和 K8S 总体比较类似，其中 BorgMaster 计算和存储是融合的，而 K8S 将计算和存储分离，采用 Etcd 完成数据的存储。Borg 另一个重要的特色是构建 Fauxmaster 以模拟验证，其中 Simulator 是衡量调度能力的重要一环，也是值得投入优化之处，在验证 Cell Compaction 方面具有重要的作用。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Master
    &lt;ul&gt;
      &lt;li&gt;BorgMaster / Store&lt;/li&gt;
      &lt;li&gt;Scheduer&lt;/li&gt;
      &lt;li&gt;Fauxmaster: simulator / Capacity Planning / Sanity Check.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;BorgLet&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;id-scheduler&quot;&gt;Scheduler&lt;/h3&gt;

&lt;p&gt;Scheduler 模块和 K8S 也非常相近，调度的粒度是 task，调度流程如出一辙，具体如下：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;queue pririoty -&amp;gt; feasible checking -&amp;gt; score&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;其中在 Score 上，其做了如下侧重，重点是可抢占任务的打散、镜像缓存和容灾考虑；在 MostRequest(减少碎片、增加毛刺) 和 LeastRequest(减少毛刺、增大碎片)上做了权衡:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Minimizing the number and priority of preempted tasks,&lt;/li&gt;
  &lt;li&gt;Picking machines that already have a copy of the task’s packages,&lt;/li&gt;
  &lt;li&gt;Spreading tasks across power and failure domains&lt;/li&gt;
  &lt;li&gt;Packing quality including putting a mix of high and low priority
E-PVM for scoring&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;调度的性能指标：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;10000 tasks / minute&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Borg 在优化性能方面和 K8S 有较大的差异，K8S 为每个 Pod 打分，而 Borg 采取了精度换效率的做法：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Score Caching: Cache Scores Until the  Property of machine/task change.&lt;/li&gt;
  &lt;li&gt;Equivalence classes: feasibility and scoring for one task per equivalence class.&lt;/li&gt;
  &lt;li&gt;Relax Randomization.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;id-availability&quot;&gt;Availability&lt;/h1&gt;

&lt;p&gt;Borg 支持业务达到 99.99% 的可用性，和 K8S 思路非常类似：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;By spreading tasks of a job across failure domains such as machines, racks, and power domains.&lt;/li&gt;
  &lt;li&gt;PDB.&lt;/li&gt;
  &lt;li&gt;Reschedule.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;id-utilization&quot;&gt;Utilization&lt;/h1&gt;

&lt;h3 id=&quot;id-evaluation&quot;&gt;Evaluation&lt;/h3&gt;

&lt;p&gt;和资源利用率指标相比，Borg 提出 Cell Compaction 作为衡量标准：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;given a workload, we found out how small a cell it could be fitted into by removing machines until the workload no longer fitted&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;此衡量标准非常新颖，从客观的视角回答了如果要支持所需要的 workload，最佳条件下需要多少机器(成本)。结合  Faux 等模拟能力，将很好的回答如下问题：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;当前的调度状态和理论最佳的状态差异性如何？&lt;/li&gt;
  &lt;li&gt;机器的选型是否有优化空间，是否最佳的适配了 workload？&lt;/li&gt;
  &lt;li&gt;如何衡量 workload 的必须性？&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;id-cell-share&quot;&gt;Cell Share&lt;/h3&gt;

&lt;p&gt;本节突出在 prod 和 non-prod 融合并池的重要性，二者的割裂将而外增加 20-30% 的资源。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Segregating prod and non-prod work would need 20–30% more machines in the median cell to run our workload. That’s because prod jobs usually reserve resources to handle rare workload spikes, but don’t use these resources most of the time. Borg reclaims the unused resources to run much of the non-prod work。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;id-large-cell&quot;&gt;Large Cell&lt;/h3&gt;

&lt;p&gt;本节突出大集群大池子对资源成本的优化效果，采用割裂的小集群将额外增加 20-150% 的资源成本。事实上，不少云原生团队开展业务时，为了避免业务之间的互相影响，通常倾向采用独占节点或者集群这类简单而粗暴的方式解决隔离的问题，但是不利于长期的维护效率和优化资源利用率。因此在建设 K8S 集群时，长期需要避免将业务和某个集群/某些节点进行绑定，应当完善单机层面的隔离能力，最终实现统一而共享的资源池。&lt;/p&gt;

&lt;h3 id=&quot;id-fine-grained-resource&quot;&gt;Fine-Grained Resource&lt;/h3&gt;

&lt;p&gt;应该采用精细粒度的资源分配，如果取整到 0.5Core 和 1GB 的粒度将带来 30% 的额外开销。X Core Y GB 是 IaaS 时代浓厚的经验习惯，对用户体验友好。在建设精细化的资源配置之前，需要完善资源诊断和建议的能力，即根据应用的历史数据，为客户推荐合适的精细化的资源配置。&lt;/p&gt;

&lt;h3 id=&quot;id-resource-reclaim&quot;&gt;Resource Reclaim&lt;/h3&gt;

&lt;p&gt;如果禁止 Resource Reclaim，将增加 20% 的资源开销。&lt;/p&gt;

&lt;h1 id=&quot;id-isolation&quot;&gt;Isolation&lt;/h1&gt;

&lt;p&gt;关于隔离方面，熟悉 Docker 对此应不陌生；如果具备对内核、网络具备更强的掌控能力，还可以定制更多维度和更强的计算、存储和网络的隔离能力。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Security Isolation: Chroot.&lt;/li&gt;
  &lt;li&gt;Performance Isolation: Post-hoc, Cgroup.&lt;/li&gt;
  &lt;li&gt;CFS + CPUSetd.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;id-lessons-and-future-work&quot;&gt;Lessons and future work&lt;/h1&gt;

&lt;h3 id=&quot;id-the-bad&quot;&gt;The bad&lt;/h3&gt;

&lt;p&gt;在总结经验的过程中，Borg 提到三个教训:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Jobs are restrictive as the only grouping mechanism for tasks(label selector).&lt;/li&gt;
  &lt;li&gt;One IP address per machine complicates things(hostNetwork).&lt;/li&gt;
  &lt;li&gt;Optimizing for power users at the expense of casual ones.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;针对 1，K8S 抽象 label 以解决；针对 2，K8S 通过支持 CNI，为每个 Pod 分配独立的 IP。 关于问题 3 中的 2/8 效应，不仅仅是 Borg，也是 Mesos/Yarn/K8S 在各自大规模场景中均会碰到的问题，即少量的头部在线服务/离线服务将占据主体的资源。以在线应用为例，副本数 10000 和 10 的服务在发布必然在效率、稳定性和成本方便不不同的考量；以离线业务为例，点击率预估的深度学习训练和短平快的 Spark SQL Batch 任务必然也大相径庭。&lt;/p&gt;

&lt;h3 id=&quot;id-the-good&quot;&gt;The good&lt;/h3&gt;

&lt;p&gt;Borg 亦归纳了 4 个心得：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Allocs are useful.&lt;/li&gt;
  &lt;li&gt;Cluster management is more than task management.&lt;/li&gt;
  &lt;li&gt;The master is the kernel of a distributed system.&lt;/li&gt;
  &lt;li&gt;Introspection is vital: An important design decision in Borg was to surface debugging information to all users rather than hiding it: Borg has thousands of users, so “self-help”has to be the first step in debugging.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;其中第 4 点，关于 Infra 对业务呈现形式上，两种不同的思路：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;面向产品化的建设，致力抽象底层架构和细节，给用户以最小的感知和使用成本，公有云通常采用此方案。&lt;/li&gt;
  &lt;li&gt;面向自助式的思路，提供丰富的文档介绍、技术工具基于自助式的排查，Borg 采用此思路。&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Mon, 02 May 2022 00:00:00 +0000</pubDate>
        <link>http://wsfdl.com/architecture/2022/05/02/borg-2015.html</link>
        <guid isPermaLink="true">http://wsfdl.com/architecture/2022/05/02/borg-2015.html</guid>
        
        
        <category>Architecture</category>
        
      </item>
    
      <item>
        <title>Twine: A Unified Cluster Management System for Shared Infrastructure 阅读笔记</title>
        <description>&lt;p&gt;Twine 是在充满众多“烟筒”下艰难形成的，携带着深厚的历史和业务定制包袱，因而侧重在“下层”如硬件与运维体系解决资源(集群)管理、容灾的能力。个人的感受是理论基础不够扎实(移动 job vs 移动机器)、架构庞杂、缺乏单机层面隔离、资源利用率效果上不如 Borg，生态上偏离主流；但是在机器流转和定制方面有一定的借鉴之处。&lt;/p&gt;

&lt;p&gt;截至论发表时，Twine 已经支持 Frontend / ML / Backend / Streaming / Stateful Service 等业务(不支持持久化存储)。下图是 Twine 的成长历史，本人认为大致可以分为三个阶段：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://wsfdl.oss-cn-qingdao.aliyuncs.com/twine-grow.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;2013-2015：艰难前行，几经胎死腹中。&lt;/li&gt;
  &lt;li&gt;2015-2018：可能获得某些个大客户的支持，迅速上量到 8%，经历近 3 年的迭代和打磨。而有趣的是，2015 年推出 Kubernetes 大行其道，Twine 竟然坚强的挺过来了。&lt;/li&gt;
  &lt;li&gt;2018-至今：上线 TaskControl(类似 K8S CRD/Operator)、Host Profile 等对各类业务更灵活的支持，托管最核心的在线服务后，快速的起量并一举占据半壁资源。&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;id-introduction&quot;&gt;Introduction&lt;/h1&gt;

&lt;p&gt;Existing systems, however, still have limitations in supporting large-scale shared infrastructure&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;They usually focus on isolated clusters, with limited support for cross-cluster management as an afterthought.&lt;/li&gt;
  &lt;li&gt;They rarely consult an application about its lifecycle management operations.&lt;/li&gt;
  &lt;li&gt;They rarely allow an application to provide its preferred custom hardware and OS settings to shared machines.&lt;/li&gt;
  &lt;li&gt;They usually prefer big machines with more CPUs and memory in order to stack workloads and increase utilization.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;上述是 Twine 造轮子的原因，其中 1 和 3 有一定的道理；而 2 和 4 不太站得住脚，比如 K8S 的 Operator 支持灵活自定义的任务编排能力；且硬件上总体是往大规格不断发展的。而如下更像是 Twine 形成的原因：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;Infrastructure management is disaggregated, each BU and even team own their own private pools.&lt;/li&gt;
    &lt;li&gt;2/8 effect, the top 50 services consume 70% resource and have various customization requirements.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Twine packages applications into Linux containers and manages the lifecycle of machines, containers, and applications. A task is one instance of an application deployed in a container, and a job is a group of tasks of the same application.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;和大部分集群管理系统一样，对任务的抽象上分为 job 和 task。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Twine 自称特色如下：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A single control plane to manage one million machines&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;吐槽点：Although none of our regions host one million machines yet, we are close and anticipate reaching that scale in the near future&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;Collaborative lifecycle management&lt;/li&gt;
  &lt;li&gt;Host-level customization&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;Host profile，定制硬件和内核参数，具有一定的场景。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;Power-efficient machines&lt;/li&gt;
  &lt;li&gt;Shared infrastructure.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;Shared 的粒度为 Machine 级别，客观上统一资源池，优化了 Buffer，加速资源流转；不过粒度上存在很大优化空间。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;id-twine-design-and-implementation&quot;&gt;Twine Design and Implementation&lt;/h1&gt;

&lt;p&gt;The Capacity Portal allows users to request or modify entitlements, which associate capacity quotas with business units defined in the service. With a granted entitlement, a user deploys jobs through the front end. The scheduler manages job and task lifecycle. If a job has a TaskController, the scheduler coordinates with the TaskController to make decisions. The allocator assigns machines to entitlements and assigns tasks to machines. ReBalancer runs asynchronously and continuously to improve the allocator’s decisions. Resource Broker (RB) stores machine information and unavailability events that track hardware failures and planned maintenance. The Health Check Service (HCS) monitors machines and updates their status in RB. The agent runs on every machine to manage tasks. Sidekick switches host profiles as needed. Service Resource Manager (SRM) autoscales jobs in response to load changes. Conveyor is our continuous delivery system.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://wsfdl.oss-cn-qingdao.aliyuncs.com/twine-arch.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;相比论文的架构图，私认为更易于理解的架构图如下：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://wsfdl.oss-cn-qingdao.aliyuncs.com/twine-arch2.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Twine 是一个 Region 级别的集群管理系统，某种意义上更像 K8S 的 Cluster API，同时具备基础的调度和编排能力:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;用户可以申请集群(Entitlement)，同一个集群下的机器通常是同类型的，Twine 为此集群动态的分配机器。&lt;/li&gt;
  &lt;li&gt;提供基本的任务抽象和生命周期管理能力，允许用户在其集群中自定义生命周期管理的逻辑。&lt;/li&gt;
  &lt;li&gt;提供基础的粗粒度调度能力，即根据用户诉求将机器分配给集群；允许用户在其集群中扩展调度器，比如 Batch Scheduler。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;类比 K8S，本人认为 Allocator 更像是一个调度器，它接受申请机器的请求并且根据约束条件将机器分配到合适的集群上；Rebalancer 更像是 Rescheduler / Descheduler；Service Resource Manager 更像是 HPA。&lt;/p&gt;

&lt;p&gt;Twine Scheduler 其实更像是一个任务的生命周期管控模块，可类比 K8S Controller。它根据任务状态、硬件状态、业务约束等输入管控其生命周期，并联动服务发现，从而应对异常可提供高可靠的能力。&lt;/p&gt;

&lt;p&gt;Task Controller 更像是 Kubernetes 的 Operator，允许用户定义符合业务要求的编排能力，从而为 Twine 托管各类业务奠定基础。Application-Level Scheduler 允许业务自定义调度能力，Facebook 中的有状态服务、批式计算、流式处理、机器学习和视频处理均有业务自定义的调度器；以 Batch Scheduler 为例，用户从 Twine 申请集群批发一大比资源后，job/task 和节点的匹配关系完全交由业务的 Batch Scheduler 进行调度，Twine 的 Scheduler / Allocator 对此并不感知。&lt;/p&gt;

&lt;h1 id=&quot;id-scability--availability&quot;&gt;Scability &amp;amp; Availability&lt;/h1&gt;

&lt;p&gt;关于 Scability，Twine 的核心理念是 Sharding，并且以 entitlements 作为主要 sharding 对象。&lt;/p&gt;

&lt;p&gt;关于 Availability，其设计原则为：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;All components are sharded&lt;/li&gt;
  &lt;li&gt;All components are replicated&lt;/li&gt;
  &lt;li&gt;Tasks keep running&lt;/li&gt;
  &lt;li&gt;Rate-limit destructive operations&lt;/li&gt;
  &lt;li&gt;Network redundancy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;从业务容灾视角而言：Twine spreads tasks of the same job across DCs and MSBs.&lt;/p&gt;

&lt;h1 id=&quot;id-evaluation&quot;&gt;Evaluation&lt;/h1&gt;

&lt;p&gt;此章节乏善可陈，大致是：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;TaskControl works well for sharding manager.
    &lt;ul&gt;
      &lt;li&gt;Offer 16 TaskControllers to support thousands of services.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Autoscaling frees up to 25% of the web tier’s machines during off-peak hours.&lt;/li&gt;
  &lt;li&gt;Host profiles improve performance and the overhead of switching host profiles is small.
    &lt;ul&gt;
      &lt;li&gt;Offer 17 host profiles.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;twshared’s average memory and CPU utilization are ≈40% and ≈30%.
    &lt;ul&gt;
      &lt;li&gt;Capacity buffer consolidation improved 3%.&lt;/li&gt;
      &lt;li&gt;Turbo Boost improved 2%.&lt;/li&gt;
      &lt;li&gt;Autoscaling improved 2%.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;事实上 30% 的资源利用率并非很出色，相比 Borg 等有很大的提升空间。但是值得一提的是 Host Profile 的切换还是很迅速的，绝大部分在 4min 以内，相比之下不少公司的装机运维流程的效率和成功率还有很大的提升空间。&lt;/p&gt;

&lt;h1 id=&quot;id-experience&quot;&gt;Experience&lt;/h1&gt;

&lt;p&gt;Path to Shared Infrastructure&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Make Twine capable of supporting a large shared pool&lt;/li&gt;
  &lt;li&gt;Publicize the growth and health of twshared&lt;/li&gt;
  &lt;li&gt;Set a strong example for others to follow&lt;/li&gt;
  &lt;li&gt;Make migration mandatory&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lessons Learned&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Entitlements:  杂糅一个集群和 Quota 的概念，导致用户申请了太多的小集群。&lt;/li&gt;
  &lt;li&gt;Customizations：we permitted some customizations that appeared useful initially, but later became barriers for fleet-wide optimizations.&lt;/li&gt;
  &lt;li&gt;Supporting Global Services: We are replacing global Twine deployments with a new Federation system built a top regional Twine deployments to provide stronger capacity guarantees and more holistic support for a global-service abstraction.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;id-总体看法&quot;&gt;总体看法&lt;/h1&gt;

&lt;h2 id=&quot;id-move-machine-vs-move-job&quot;&gt;Move Machine vs Move Job&lt;/h2&gt;

&lt;p&gt;Twine 本质上更像是一个具备一定编排和调度能力的 Cluster API，它倾向在不同的业务之间腾挪机器构建集群，是一种机器适配 Job 的管理思想；而 Borg/K8S 的理念是在固定的资源池上，根据约束条件将 Job/Task 调度到最佳的机器上。&lt;/p&gt;

&lt;p&gt;从一般效率上说，移动 Job 的效率肯定大大高于移动机器；其次从整体生命周期来看，机器的生命周期是缓慢的，而 Job/Task 的生命周期变动频率要高许多。因此针对超大规模私有云场景，我更倾向构建固定和统一的资源池，通过调度和隔离的手段来实现 Job 和机器的最佳匹配。&lt;/p&gt;

&lt;h2 id=&quot;id-unified-scheduling-system--sharing-pool--isolation&quot;&gt;Unified Scheduling System &amp;amp; Sharing Pool &amp;amp; Isolation&lt;/h2&gt;

&lt;p&gt;我认为 Twine 的统一资源池更多体现在运维层面，即资源统一的管理、运维，可以在各个集群中比较高效的流转。事实上，不同集群之间的资源是隔离的，隔离能力是欠缺的，在节点维度未实现多样的任务共享。正如其所坦诚：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Our legacy large services were optimized for utilizing entire machines running in private pools.&lt;/li&gt;
  &lt;li&gt;Our stacking technology needed to mature and improve support for performance isolation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;事实上，如果没有在集群维度和单机维度实现运行多样的任务，特别是在线和离线业务，其资源利用率很难再更上一个台阶。&lt;/p&gt;

&lt;p&gt;其次在调度上未形成统一的调度能力，Allocator 和 Application-Level Scheduler 之间是相对割裂的，未
能从全局和统一调度视角去看待调度最佳方案。&lt;/p&gt;

&lt;p&gt;最后在资源类型未明显的提到分级，也不支持 overcommit，这也将大大影响其成本。&lt;/p&gt;

&lt;h2 id=&quot;id-global-wide-federation&quot;&gt;Global wide federation&lt;/h2&gt;

&lt;p&gt;当谈论 Region 粒度的 Scalibility 的时候，Twine 抨击了一波 Federation 的实现，表示其不如 Twine 简单优雅。但是到了 Lessons Learned 章节，又坦言：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Global Twine deployments did not provide the right abstraction for managing global services.  We are replacing global Twine deployments with a new Federation system built a top regional Twine deployments.&lt;/p&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Sat, 30 Apr 2022 00:00:00 +0000</pubDate>
        <link>http://wsfdl.com/architecture/2022/04/30/twine-read.html</link>
        <guid isPermaLink="true">http://wsfdl.com/architecture/2022/04/30/twine-read.html</guid>
        
        
        <category>Architecture</category>
        
      </item>
    
      <item>
        <title>进程究竟用了多少内存</title>
        <description>&lt;p&gt;我们所接触的内存相关概念中，既有物理内存，又有虚拟内存；既有内核内存，又有用户态内存；既有进程专属内存，又有共享内存；分配的内存中既有可回收内存，又有不可回收内存；既有 mmap 分配的，又有 brk 调用分配的；内置内存管理的语言而言，既有 Runtime 已申请内存，又有实际被使用的内存。因此绝对准确的回答某个进程所占内存是一件困难之事。&lt;/p&gt;

&lt;h1 id=&quot;id-从一个-golang-内存困扰现象说起&quot;&gt;从一个 Golang 内存困扰现象说起&lt;/h1&gt;

&lt;h2 id=&quot;id-现象&quot;&gt;现象&lt;/h2&gt;

&lt;p&gt;对于采用 1.12-1.15 golang 编译器和 4.5 及以上内核的 go 应用来说，存在两个困扰的内存问题：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;从 Linux 视角看到的进程内存远远大于 go pprof 视角看到进程 inuse 内存，有时甚至相差十倍之多。&lt;/li&gt;
  &lt;li&gt;Linux 视角内存久居高位不下。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;id-分析&quot;&gt;分析&lt;/h2&gt;

&lt;p&gt;事实上，golang runtime 有诸多描述进程内存指标，详情请见 &lt;a href=&quot;https://github.com/golang/go/blob/master/src/runtime/mstats.go&quot;&gt;mstats.go&lt;/a&gt;，举例而言：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# golang 内存指标非常之多，如仅例举核心指标

# 从 OS 申请的内存，等于 sum(heap/stack/mspan sys)，基本等同于 linux VIRT 指标。
Sys = 46359864776
# Golang Runtime 已分配且未释放的内存，等同 HeapAlloc。
Alloc = 8606478720

# 从操作系统申请用于 heap 的内存
HeapSys = 44083806208
# heap 上已分配且未释放的内存
HeapAlloc = 8606478720
# heap 上用于 MSpan 的内存
HeapInuse = 10107944960
# heap 调用 madvise 归还给 OS 的内存，但是这部分内存还可以再次被申请。
HeapReleased = 32709271552
# heap 未被用于 MSpan 的内存，这部分可以归还给 OS。
HeapIdle = 33975861248

# StackInuse / StackSys，二者基本相等，表示 stack 所用资源。
Stack = 6717440 / 6717440

# 构建 MSpan 结构体使用的内存(MSpanInuse/MSpanSys)
MSpan = 216646912 / 460046336

# 下次 GC 触发的阈值(HeapAlloc) 
NextGC = 16474941344
......
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;top 的指标如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;VIRT: 46.458g
RSS:  0.028t                                                                                                                                   
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;故从 Golang 的视角来看：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Alloc 基本代表进程的实际运行所需要的内存。&lt;/li&gt;
  &lt;li&gt;Sys 表示从操作系统分配的内存，基本等同于 VIRT。&lt;/li&gt;
  &lt;li&gt;HeapReleased 则表示一种中间状态的内存，既可以被操作系统回收，也可以被 Runtime 再次申请的内存。正是内存大户 HeapReleased 带来了上述困扰。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;id-linux-madvise&quot;&gt;Linux madvise&lt;/h2&gt;

&lt;p&gt;从 &lt;a href=&quot;https://go.dev/src/runtime/mem_linux.go&quot;&gt;go memory runtime&lt;/a&gt; 不难发现，golang 通过 mmap 分配内存，通过 munmap 和 madvise 释放内存。而 munmap 封装在 runtime.sysFree 中，该函数被调度的场景通常在内存分配异常过程中，详细介绍如下：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;sysFree transitions a memory region from any state to None. Therefore, it returns memory unconditionally. It is used if an out-of-memory error has been detected midway through an allocation or to carve out an aligned section of the address space. It is okay if sysFree is a no-op only if sysReserve always returns a memory region aligned to the heap allocator’s alignment restrictions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;因此对于常态的内存释放，主要是通过 &lt;a href=&quot;https://man7.org/linux/man-pages/man2/madvise.2.html&quot;&gt;madvisor syscall&lt;/a&gt; 来完成，man 手册对 madvise 的详细介绍如下：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;int madvise(void *addr, size_t length, int advice);&lt;/p&gt;

  &lt;p&gt;The madvise() system call is used to give advice or directions to the kernel about the address range beginning at address addr and with size length bytes In most cases, the goal of such advice is to improve system or application performance.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;在 4.5 内核之后 advice 开始支持 MADV_FREE 参数，当完成 madvisor 调用后，内核会立刻回收 file pages，对于 anonymous page，内核仅在内存紧张时回收对应的内存，在实际回收之前，进程依旧可以使用这部分内存。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The application no longer requires the pages in the range specified by addr and len.  The kernel can thus free these pages, but the freeing could be delayed until memory pressure occurs.  For each of the pages that has been marked to be freed but has not yet been freed, the free operation will be canceled if the caller writes into the page.&lt;/p&gt;

  &lt;p&gt;MADV_FREE will unmap file pages. MADV_FREE on anonymous pages is interpreted as a signal that the application no longer needs the data in the pages, and they can be thrown away if the kernel needs the memory for something else.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;golang 在 1.12 之前和 1.16 及其以后采用 MADV_DONTNEED 选项，当完成 madvisor 调用后，内核马上回收 file page 和 anonymous pages 内存，RSS 显著下降。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The kernel is free to delay freeing the pages until an appropriate moment. The resident set size (RSS) of the calling process will be immediately reduced however.&lt;/p&gt;

  &lt;p&gt;MADV_DONTNEED will unmap file pages and free anonymous pages。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;对于 1.12-1.15 golang 在 4.5 及以上内核版本默认采用  MADV_FREE 参数，是一种以空间换性能的做法，同时给用户造成很大的困扰；用户可以配置 GODEBUG=madvdontneed=1 强制使用 MADV_DONTNEED。&lt;/p&gt;

&lt;h1 id=&quot;id-a-little-more&quot;&gt;A Little More&lt;/h1&gt;

&lt;p&gt;事实上，上节提到的 file-backed page 和 annoymous page 通常占据着进程的大部分内存，也是 /proc/memoinfo 的重要参数；tmpfs、slab 等等也是常见的概念；它们和 brk 和 mmap 系统调用分配的内存有什么关系呢？&lt;a href=&quot;https://techtalk.intersec.com/2013/07/memory-part-1-memory-types/&quot;&gt;这篇博文&lt;/a&gt;做了如下条理性总结：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt; &lt;/th&gt;
      &lt;th&gt;Private&lt;/th&gt;
      &lt;th&gt;Shared&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;anonymous&lt;/td&gt;
      &lt;td&gt;stack / malloc(brk/sbrk) / mmap(ANON, PRIVATE)&lt;/td&gt;
      &lt;td&gt;mmap(ANON, SHARED)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;file-backed&lt;/td&gt;
      &lt;td&gt;mmap(fd, PRIVATE) / binary / shared libraries&lt;/td&gt;
      &lt;td&gt;mmap(fd, SHARED) / shm&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;正如其字面意思，Private 和 Shared 非常好理解，所谓 Private 指内存独属某一个进程，大部分场景下所用的内存均为此；Shared 则表示内存可以被一个或者多个进程共享使用，比如 tmpfs，基于 mmap 的进程间通信。&lt;/p&gt;

&lt;p&gt;所谓的 Anonymous page，&lt;a href=&quot;https://www.kernel.org/doc/html/latest/admin-guide/mm/concepts.html#anonymous-memory&quot;&gt;内核&lt;/a&gt;的解释如下：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The anonymous memory or anonymous mappings represent memory that is not backed by a filesystem. Such mappings are implicitly created for program’s stack and heap or by explicit calls to mmap(2) system call. Usually, the anonymous mappings only define virtual memory areas that the program is allowed to access. The read accesses will result in creation of a page table entry that references a special physical page filled with zeroes. When the program performs a write, a regular physical page will be allocated to hold the written data. The page will be marked dirty and if the kernel decides to repurpose it, the dirty page will be swapped out.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;因此 Anonymous page 包括进程的堆、栈，由于 anonymouse 没有对应的文件，仅能交换到 swap 分区上，另外 anonymous page 实际的物理内存分配是发生在进程访问所分配内存时，因此会出现 top 命令中 VIRT 大于 RSS 的现象。&lt;/p&gt;

&lt;p&gt;对于 file-backed page，通常有硬盘的文件与之对应，包括进程的代码文件、mmap 映射的文件、内核中的 page cache 等等，当内存不足时，内核可以回收这些内存，并且将数据同步到文件中。&lt;/p&gt;

&lt;p&gt;无论是 file-backed page 还是 annoymous page，它们均可以分为 active 和 inactive，其中 active 表示活跃的内存，一般不可被回收，内核回收内存时，优先回收 inactive 的内存。&lt;/p&gt;

&lt;h1 id=&quot;id-参考资料&quot;&gt;参考资料&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;http://linuxperf.com/?p=142&lt;/li&gt;
  &lt;li&gt;https://www.kernel.org/doc/gorman/html/understand/understand007.html&lt;/li&gt;
  &lt;li&gt;https://www.sunliaodong.cn/2021/03/11/Linux-PageCache%E8%AF%A6%E8%A7%A3/&lt;/li&gt;
  &lt;li&gt;https://techtalk.intersec.com/2013/07/memory-part-1-memory-types/&lt;/li&gt;
  &lt;li&gt;http://linuxperf.com/?p=97&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Fri, 28 Jan 2022 00:00:00 +0000</pubDate>
        <link>http://wsfdl.com/linux/2022/01/28/memory_overview.html</link>
        <guid isPermaLink="true">http://wsfdl.com/linux/2022/01/28/memory_overview.html</guid>
        
        
        <category>Linux</category>
        
      </item>
    
      <item>
        <title>迈出量化交易折腾一小步</title>
        <description>&lt;h1 id=&quot;id-缘起&quot;&gt;缘起&lt;/h1&gt;

&lt;p&gt;当站在如今之刻回望工作乃至学习以来，迈入基础架构领域，实属校招工作分配的筛子，赖着云计算的高歌猛进算是押对了行业；然而对数字的和推理的追求，那是曾经无尽的兴趣所在，限于大脑一般的记性和视觉审美，唯觉简洁深度抽象乃是美的展现形式，本质所在。不幸之是，作为一般开发，基础架构对于数理之需求实乃不高，所谓用进废退，对数字与定理之敏感，已是退步许多。&lt;/p&gt;

&lt;p&gt;因机缘巧合触及机器学习云原生化，进而对应用/图像算法工程领域有皮毛的接触，三年前便知曾经人为发掘的特征或者算法，几乎为海量的数据和算力的深度学习所碾压。如今机缘巧合，感触到量化交易也展现雷同之势。我们建设机器学习平台，对于推广搜而言是带来多个点击率和 GMV 的提升；对于计算视觉而言是诸如车牌人脸识别提升多少个百分点，固然有很大的业务价值。但是当站在科技和金融的十字路口时，其团队和个人的业务价值或者可以更加体现。&lt;/p&gt;

&lt;p&gt;有时问起自己，从哪里来、到哪里去的哲学命题时，时间的维度便拉的很长，兴趣与个人的意义便被突出与放大，生而有涯学无涯，在有条件之余，给自己一个探索的机会，用一年的周期折腾一把量化交易。&lt;/p&gt;

&lt;h1 id=&quot;id-选型&quot;&gt;选型&lt;/h1&gt;

&lt;p&gt;折腾的选型因素主要考虑功能、生态；其次是快速的进行开发和实现第一笔实盘交易，形成流程的闭环，让飞轮的运转起来，进而在算法策略逐步迭代，在此约束下完成如下梳理和调研。&lt;/p&gt;

&lt;h2 id=&quot;id-功能&quot;&gt;功能&lt;/h2&gt;

&lt;p&gt;无论是平台还是开源项目，期望可以提供准确丰富的数据源、提供易用的开发环境，支持测回/模拟/实盘和交易后端。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;丰富的数据源：国内/国际期货、股票、外汇、数字货币等数据，准确和完整是核心诉求，越精细越好。&lt;/li&gt;
  &lt;li&gt;友好的算法开发和模拟：提供快速的算法策略开发环境，支持回测和分析；支持模拟和实盘。&lt;/li&gt;
  &lt;li&gt;丰富的交易后端：支持国内/国际券商/期货公司的交易后端为佳。其中 futu 提供了简易的交易入口，支持 A股/H/US 等，适配 futu 的成本非常低。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;id-生态&quot;&gt;生态&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;社区：文档 &amp;amp; 热度。&lt;/li&gt;
  &lt;li&gt;语言：必须以 Python 为主，核心能力上 Python 在数理统计分析、机器学习算法等生态丰富；周边能力上系统层面也具备较好的生态。&lt;/li&gt;
  &lt;li&gt;系统：稳定性 / 成熟度。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;id-开源项目&quot;&gt;开源项目&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;vnpy: 17.4k Star，基于 Python 的开源量化交易系统开发框架，在开源社区 7 年持续不断的贡献下一步步成长为全功能量化交易平台，社区活跃度高，支持丰富的后端，支持 ubuntu/windows 系统，代码风格一般。&lt;/li&gt;
  &lt;li&gt;Zipline：14.8k Star，基于事件触发的 Python 交易库，支持回测等等，用于在 Quantopian 社区(目前已关闭)，github 最近一年无 commit 记录，据网络信息表示米筐和聚宽参考了 Zipline 原形。&lt;/li&gt;
  &lt;li&gt;rqalpha：4.4k Star，RQAlpha 提供数据获取、算法交易、回测引擎、实盘模拟等能力，为程序化交易者提供了全套解决方案，对应的社区 Ricequant(米筐科技)，社区相对活跃。&lt;/li&gt;
  &lt;li&gt;QUANTAXIS：6.2k Star，提供股票/期货/期权/虚拟币的数据、回测、模拟、交易功能，社区相对活跃。&lt;/li&gt;
  &lt;li&gt;qlib：7.8k Star，微软开源的基于机器学习的量化交易项目，社区比较活跃。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;id-平台&quot;&gt;平台&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.ricequant.com/welcome/&quot;&gt;米筐科技&lt;/a&gt;：主导 rqalpha 开源项目，提供 SaaS 化的平台和数据能力。&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://quant.10jqka.com.cn/platform/html/home.html&quot;&gt;MindGo&lt;/a&gt;：同花顺。提供丰富的国内数据，不支持实盘，数据不支持下载。&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.joinquant.com/&quot;&gt;JoinQuant&lt;/a&gt;：提供免费的量化数据、工具和学习体系，其旗下的私募近年收益不错。
……&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;id-学习路径&quot;&gt;学习路径&lt;/h1&gt;

&lt;p&gt;方向上仅考虑中低频，并给予时间和耐心，跑通第一次回测、模拟和第一笔交易是首要任务，让迭代的飞轮运作起来，拿到可见的进步。量化交易的策略从简单到复杂逐步迭代，甚至短期内不考虑深度学习等场景，相关的专业名词、经济金融知识在迭代中积累，确认收益后再进行基础性系统性学习。&lt;/p&gt;

</description>
        <pubDate>Sun, 02 Jan 2022 00:00:00 +0000</pubDate>
        <link>http://wsfdl.com/quantitative/trading/2022/01/02/quantity_overview.html</link>
        <guid isPermaLink="true">http://wsfdl.com/quantitative/trading/2022/01/02/quantity_overview.html</guid>
        
        
        <category>Quantitative</category>
        
        <category>Trading</category>
        
      </item>
    
  </channel>
</rss>
