learn.lianglianglee.com/文章/美团点评Kubernetes集群管理实践.md.html
2022-05-11 19:04:14 +08:00

657 lines
47 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<!-- saved from url=(0046)https://kaiiiz.github.io/hexo-theme-book-demo/ -->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
<link rel="icon" href="/static/favicon.png">
<title>美团点评Kubernetes集群管理实践.md.html</title>
<!-- Spectre.css framework -->
<link rel="stylesheet" href="/static/index.css">
<!-- theme css & js -->
<meta name="generator" content="Hexo 4.2.0">
</head>
<body>
<div class="book-container">
<div class="book-sidebar">
<div class="book-brand">
<a href="/">
<img src="/static/favicon.png">
<span>技术文章摘抄</span>
</a>
</div>
<div class="book-menu uncollapsible">
<ul class="uncollapsible">
<li><a href="/" class="current-tab">首页</a></li>
</ul>
<ul class="uncollapsible">
<li><a href="../">上一级</a></li>
</ul>
<ul class="uncollapsible">
<li>
<a href="/文章/AQS 万字图文全面解析.md.html">AQS 万字图文全面解析.md.html</a>
</li>
<li>
<a href="/文章/Docker 镜像构建原理及源码分析.md.html">Docker 镜像构建原理及源码分析.md.html</a>
</li>
<li>
<a href="/文章/ElasticSearch 小白从入门到精通.md.html">ElasticSearch 小白从入门到精通.md.html</a>
</li>
<li>
<a href="/文章/JVM CPU Profiler技术原理及源码深度解析.md.html">JVM CPU Profiler技术原理及源码深度解析.md.html</a>
</li>
<li>
<a href="/文章/JVM 垃圾收集器.md.html">JVM 垃圾收集器.md.html</a>
</li>
<li>
<a href="/文章/JVM 面试的 30 个知识点.md.html">JVM 面试的 30 个知识点.md.html</a>
</li>
<li>
<a href="/文章/Java IO 体系、线程模型大总结.md.html">Java IO 体系、线程模型大总结.md.html</a>
</li>
<li>
<a href="/文章/Java NIO浅析.md.html">Java NIO浅析.md.html</a>
</li>
<li>
<a href="/文章/Java 面试题集锦(网络篇).md.html">Java 面试题集锦(网络篇).md.html</a>
</li>
<li>
<a href="/文章/Java-直接内存 DirectMemory 详解.md.html">Java-直接内存 DirectMemory 详解.md.html</a>
</li>
<li>
<a href="/文章/Java中9种常见的CMS GC问题分析与解决.md.html">Java中9种常见的CMS GC问题分析与解决.md.html</a>
</li>
<li>
<a href="/文章/Java中9种常见的CMS GC问题分析与解决.md.html">Java中9种常见的CMS GC问题分析与解决.md.html</a>
</li>
<li>
<a href="/文章/Java中的SPI.md.html">Java中的SPI.md.html</a>
</li>
<li>
<a href="/文章/Java中的ThreadLocal.md.html">Java中的ThreadLocal.md.html</a>
</li>
<li>
<a href="/文章/Java线程池实现原理及其在美团业务中的实践.md.html">Java线程池实现原理及其在美团业务中的实践.md.html</a>
</li>
<li>
<a href="/文章/Java魔法类Unsafe应用解析.md.html">Java魔法类Unsafe应用解析.md.html</a>
</li>
<li>
<a href="/文章/Kafka 源码阅读笔记.md.html">Kafka 源码阅读笔记.md.html</a>
</li>
<li>
<a href="/文章/Kafka、ActiveMQ、RabbitMQ、RocketMQ 区别以及高可用原理.md.html">Kafka、ActiveMQ、RabbitMQ、RocketMQ 区别以及高可用原理.md.html</a>
</li>
<li>
<a href="/文章/MySQL · 引擎特性 · InnoDB Buffer Pool.md.html">MySQL · 引擎特性 · InnoDB Buffer Pool.md.html</a>
</li>
<li>
<a href="/文章/MySQL · 引擎特性 · InnoDB IO子系统.md.html">MySQL · 引擎特性 · InnoDB IO子系统.md.html</a>
</li>
<li>
<a href="/文章/MySQL · 引擎特性 · InnoDB 事务系统.md.html">MySQL · 引擎特性 · InnoDB 事务系统.md.html</a>
</li>
<li>
<a href="/文章/MySQL · 引擎特性 · InnoDB 同步机制.md.html">MySQL · 引擎特性 · InnoDB 同步机制.md.html</a>
</li>
<li>
<a href="/文章/MySQL · 引擎特性 · InnoDB 数据页解析.md.html">MySQL · 引擎特性 · InnoDB 数据页解析.md.html</a>
</li>
<li>
<a href="/文章/MySQL · 引擎特性 · InnoDB崩溃恢复.md.html">MySQL · 引擎特性 · InnoDB崩溃恢复.md.html</a>
</li>
<li>
<a href="/文章/MySQL · 引擎特性 · 临时表那些事儿.md.html">MySQL · 引擎特性 · 临时表那些事儿.md.html</a>
</li>
<li>
<a href="/文章/MySQL 主从复制 半同步复制.md.html">MySQL 主从复制 半同步复制.md.html</a>
</li>
<li>
<a href="/文章/MySQL 主从复制 基于GTID复制.md.html">MySQL 主从复制 基于GTID复制.md.html</a>
</li>
<li>
<a href="/文章/MySQL 主从复制.md.html">MySQL 主从复制.md.html</a>
</li>
<li>
<a href="/文章/MySQL 事务日志(redo log和undo log).md.html">MySQL 事务日志(redo log和undo log).md.html</a>
</li>
<li>
<a href="/文章/MySQL 亿级别数据迁移实战代码分享.md.html">MySQL 亿级别数据迁移实战代码分享.md.html</a>
</li>
<li>
<a href="/文章/MySQL 从一条数据说起-InnoDB行存储数据结构.md.html">MySQL 从一条数据说起-InnoDB行存储数据结构.md.html</a>
</li>
<li>
<a href="/文章/MySQL 地基基础:事务和锁的面纱.md.html">MySQL 地基基础:事务和锁的面纱.md.html</a>
</li>
<li>
<a href="/文章/MySQL 地基基础:数据字典.md.html">MySQL 地基基础:数据字典.md.html</a>
</li>
<li>
<a href="/文章/MySQL 地基基础:数据库字符集.md.html">MySQL 地基基础:数据库字符集.md.html</a>
</li>
<li>
<a href="/文章/MySQL 性能优化:碎片整理.md.html">MySQL 性能优化:碎片整理.md.html</a>
</li>
<li>
<a href="/文章/MySQL 故障诊断:一个 ALTER TALBE 执行了很久,你慌不慌?.md.html">MySQL 故障诊断:一个 ALTER TALBE 执行了很久,你慌不慌?.md.html</a>
</li>
<li>
<a href="/文章/MySQL 故障诊断:如何在日志中轻松定位大事务.md.html">MySQL 故障诊断:如何在日志中轻松定位大事务.md.html</a>
</li>
<li>
<a href="/文章/MySQL 故障诊断:教你快速定位加锁的 SQL.md.html">MySQL 故障诊断:教你快速定位加锁的 SQL.md.html</a>
</li>
<li>
<a href="/文章/MySQL 日志详解.md.html">MySQL 日志详解.md.html</a>
</li>
<li>
<a href="/文章/MySQL 的半同步是什么?.md.html">MySQL 的半同步是什么?.md.html</a>
</li>
<li>
<a href="/文章/MySQL中的事务和MVCC.md.html">MySQL中的事务和MVCC.md.html</a>
</li>
<li>
<a href="/文章/MySQL事务_事务隔离级别详解.md.html">MySQL事务_事务隔离级别详解.md.html</a>
</li>
<li>
<a href="/文章/MySQL优化优化 select count().md.html">MySQL优化优化 select count().md.html</a>
</li>
<li>
<a href="/文章/MySQL共享锁、排他锁、悲观锁、乐观锁.md.html">MySQL共享锁、排他锁、悲观锁、乐观锁.md.html</a>
</li>
<li>
<a href="/文章/MySQL的MVCC多版本并发控制.md.html">MySQL的MVCC多版本并发控制.md.html</a>
</li>
<li>
<a href="/文章/QingStor 对象存储架构设计及最佳实践.md.html">QingStor 对象存储架构设计及最佳实践.md.html</a>
</li>
<li>
<a href="/文章/RocketMQ 面试题集锦.md.html">RocketMQ 面试题集锦.md.html</a>
</li>
<li>
<a href="/文章/SnowFlake 雪花算法生成分布式 ID.md.html">SnowFlake 雪花算法生成分布式 ID.md.html</a>
</li>
<li>
<a href="/文章/Spring Boot 2.x 结合 k8s 实现分布式微服务架构.md.html">Spring Boot 2.x 结合 k8s 实现分布式微服务架构.md.html</a>
</li>
<li>
<a href="/文章/Spring Boot 教程:如何开发一个 starter.md.html">Spring Boot 教程:如何开发一个 starter.md.html</a>
</li>
<li>
<a href="/文章/Spring MVC 原理.md.html">Spring MVC 原理.md.html</a>
</li>
<li>
<a href="/文章/Spring MyBatis和Spring整合的奥秘.md.html">Spring MyBatis和Spring整合的奥秘.md.html</a>
</li>
<li>
<a href="/文章/Spring 帮助你更好的理解Spring循环依赖.md.html">Spring 帮助你更好的理解Spring循环依赖.md.html</a>
</li>
<li>
<a href="/文章/Spring 循环依赖及解决方式.md.html">Spring 循环依赖及解决方式.md.html</a>
</li>
<li>
<a href="/文章/Spring中眼花缭乱的BeanDefinition.md.html">Spring中眼花缭乱的BeanDefinition.md.html</a>
</li>
<li>
<a href="/文章/Vert.x 基础入门.md.html">Vert.x 基础入门.md.html</a>
</li>
<li>
<a href="/文章/eBay 的 Elasticsearch 性能调优实践.md.html">eBay 的 Elasticsearch 性能调优实践.md.html</a>
</li>
<li>
<a href="/文章/不可不说的Java“锁”事.md.html">不可不说的Java“锁”事.md.html</a>
</li>
<li>
<a href="/文章/互联网并发限流实战.md.html">互联网并发限流实战.md.html</a>
</li>
<li>
<a href="/文章/从ReentrantLock的实现看AQS的原理及应用.md.html">从ReentrantLock的实现看AQS的原理及应用.md.html</a>
</li>
<li>
<a href="/文章/从SpringCloud开始聊微服务架构.md.html">从SpringCloud开始聊微服务架构.md.html</a>
</li>
<li>
<a href="/文章/全面了解 JDK 线程池实现原理.md.html">全面了解 JDK 线程池实现原理.md.html</a>
</li>
<li>
<a href="/文章/分布式一致性理论与算法.md.html">分布式一致性理论与算法.md.html</a>
</li>
<li>
<a href="/文章/分布式一致性算法 Raft.md.html">分布式一致性算法 Raft.md.html</a>
</li>
<li>
<a href="/文章/分布式唯一 ID 解析.md.html">分布式唯一 ID 解析.md.html</a>
</li>
<li>
<a href="/文章/分布式链路追踪:集群管理设计.md.html">分布式链路追踪:集群管理设计.md.html</a>
</li>
<li>
<a href="/文章/动态代理种类及原理,你知道多少?.md.html">动态代理种类及原理,你知道多少?.md.html</a>
</li>
<li>
<a href="/文章/响应式架构与 RxJava 在有赞零售的实践.md.html">响应式架构与 RxJava 在有赞零售的实践.md.html</a>
</li>
<li>
<a href="/文章/大数据算法——布隆过滤器.md.html">大数据算法——布隆过滤器.md.html</a>
</li>
<li>
<a href="/文章/如何优雅地记录操作日志?.md.html">如何优雅地记录操作日志?.md.html</a>
</li>
<li>
<a href="/文章/如何设计一个亿级消息量的 IM 系统.md.html">如何设计一个亿级消息量的 IM 系统.md.html</a>
</li>
<li>
<a href="/文章/异步网络模型.md.html">异步网络模型.md.html</a>
</li>
<li>
<a href="/文章/当我们在讨论CQRS时我们在讨论些神马.md.html">当我们在讨论CQRS时我们在讨论些神马.md.html</a>
</li>
<li>
<a href="/文章/彻底理解 MySQL 的索引机制.md.html">彻底理解 MySQL 的索引机制.md.html</a>
</li>
<li>
<a href="/文章/最全的 116 道 Redis 面试题解答.md.html">最全的 116 道 Redis 面试题解答.md.html</a>
</li>
<li>
<a href="/文章/有赞权限系统(SAM).md.html">有赞权限系统(SAM).md.html</a>
</li>
<li>
<a href="/文章/有赞零售中台建设方法的探索与实践.md.html">有赞零售中台建设方法的探索与实践.md.html</a>
</li>
<li>
<a href="/文章/服务注册与发现原理剖析Eureka、Zookeeper、Nacos.md.html">服务注册与发现原理剖析Eureka、Zookeeper、Nacos.md.html</a>
</li>
<li>
<a href="/文章/深入浅出Cache.md.html">深入浅出Cache.md.html</a>
</li>
<li>
<a href="/文章/深入理解 MySQL 底层实现.md.html">深入理解 MySQL 底层实现.md.html</a>
</li>
<li>
<a href="/文章/漫画讲解 git rebase VS git merge.md.html">漫画讲解 git rebase VS git merge.md.html</a>
</li>
<li>
<a href="/文章/生成浏览器唯一稳定 ID 的探索.md.html">生成浏览器唯一稳定 ID 的探索.md.html</a>
</li>
<li>
<a href="/文章/缓存 如何保证缓存与数据库的双写一致性?.md.html">缓存 如何保证缓存与数据库的双写一致性?.md.html</a>
</li>
<li>
<a href="/文章/网易严选怎么做全链路监控的?.md.html">网易严选怎么做全链路监控的?.md.html</a>
</li>
<li>
<a href="/文章/美团万亿级 KV 存储架构与实践.md.html">美团万亿级 KV 存储架构与实践.md.html</a>
</li>
<li>
<a class="current-tab" href="/文章/美团点评Kubernetes集群管理实践.md.html">美团点评Kubernetes集群管理实践.md.html</a>
</li>
<li>
<a href="/文章/美团百亿规模API网关服务Shepherd的设计与实现.md.html">美团百亿规模API网关服务Shepherd的设计与实现.md.html</a>
</li>
<li>
<a href="/文章/解读《阿里巴巴 Java 开发手册》背后的思考.md.html">解读《阿里巴巴 Java 开发手册》背后的思考.md.html</a>
</li>
<li>
<a href="/文章/认识 MySQL 和 Redis 的数据一致性问题.md.html">认识 MySQL 和 Redis 的数据一致性问题.md.html</a>
</li>
<li>
<a href="/文章/进阶Dockerfile 高阶使用指南及镜像优化.md.html">进阶Dockerfile 高阶使用指南及镜像优化.md.html</a>
</li>
<li>
<a href="/文章/铁总在用的高性能分布式缓存计算框架 Geode.md.html">铁总在用的高性能分布式缓存计算框架 Geode.md.html</a>
</li>
<li>
<a href="/文章/阿里云PolarDB及其共享存储PolarFS技术实现分析.md.html">阿里云PolarDB及其共享存储PolarFS技术实现分析.md.html</a>
</li>
<li>
<a href="/文章/阿里云PolarDB及其共享存储PolarFS技术实现分析.md.html">阿里云PolarDB及其共享存储PolarFS技术实现分析.md.html</a>
</li>
<li>
<a href="/文章/面试最常被问的 Java 后端题.md.html">面试最常被问的 Java 后端题.md.html</a>
</li>
<li>
<a href="/文章/领域驱动设计在互联网业务开发中的实践.md.html">领域驱动设计在互联网业务开发中的实践.md.html</a>
</li>
<li>
<a href="/文章/领域驱动设计的菱形对称架构.md.html">领域驱动设计的菱形对称架构.md.html</a>
</li>
<li>
<a href="/文章/高效构建 Docker 镜像的最佳实践.md.html">高效构建 Docker 镜像的最佳实践.md.html</a>
</li>
</ul>
</div>
</div>
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
<div class="sidebar-toggle-inner"></div>
</div>
<script>
function add_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.add('show')
}
function remove_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.remove('show')
}
function sidebar_toggle() {
let sidebar_toggle = document.querySelector('.sidebar-toggle')
let sidebar = document.querySelector('.book-sidebar')
let content = document.querySelector('.off-canvas-content')
if (sidebar_toggle.classList.contains('extend')) { // show
sidebar_toggle.classList.remove('extend')
sidebar.classList.remove('hide')
content.classList.remove('extend')
} else { // hide
sidebar_toggle.classList.add('extend')
sidebar.classList.add('hide')
content.classList.add('extend')
}
}
function open_sidebar() {
let sidebar = document.querySelector('.book-sidebar')
let overlay = document.querySelector('.off-canvas-overlay')
sidebar.classList.add('show')
overlay.classList.add('show')
}
function hide_canvas() {
let sidebar = document.querySelector('.book-sidebar')
let overlay = document.querySelector('.off-canvas-overlay')
sidebar.classList.remove('show')
overlay.classList.remove('show')
}
</script>
<div class="off-canvas-content">
<div class="columns">
<div class="column col-12 col-lg-12">
<div class="book-navbar">
<!-- For Responsive Layout -->
<header class="navbar">
<section class="navbar-section">
<a onclick="open_sidebar()">
<i class="icon icon-menu"></i>
</a>
</section>
</header>
</div>
<div class="book-content" style="max-width: 960px; margin: 0 auto;
overflow-x: auto;
overflow-y: hidden;">
<div class="book-post">
<p id="tip" align="center"></p>
<div><h1>美团点评Kubernetes集群管理实践</h1>
<h2>背景</h2>
<p>作为国内领先的生活服务平台,美团点评很多业务都具有非常显著、规律的”高峰“和”低谷“特征。尤其遇到节假日或促销活动,流量还会在短时间内出现爆发式的增长。这对集群中心的资源弹性和可用性有非常高的要求,同时也会使系统在支撑业务流量时的复杂度和成本支出呈现指数级增长。而我们需要做的,就是利用有限的资源最大化地提升集群的吞吐能力,以保障用户体验。</p>
<p><strong>本文将介绍美团点评Kubernetes集群管理与使用实践包括美团点评集群管理与调度系统介绍、Kubernetes管理与实践、Kubernetes优化与改造以及资源管理与优化等。</strong></p>
<h2>美团点评集群管理与调度系统</h2>
<p>美团点评在集群管理和资源优化这条道路上已经“摸爬滚打”多年。2013年开始构建基于传统虚拟化技术的资源交付方式2015年7月开始建立完善的集群管理与调度系统——HULK目标是推动美团点评服务容器化2016年完成基于Docker容器技术自研实现了弹性伸缩能力来提升交付速度和应对快速扩缩容的需求实现弹性扩容、缩容提升资源利用率提升业务运维效率合理有效的降低企业IT运维成本2018年开始基于Kubernetes来进行资源管理和调度进一步提升资源的使用效率。</p>
<p><img src="assets/a020d924c766835536e71c5eed866b82209869.png" alt="美团点评集群管理与调度平台演进" /></p>
<p>美团点评集群管理与调度平台演进</p>
<p>最初美团点评通过基于Docker容器技术自研实现了弹性伸缩能力主要是为了解决基于虚拟化技术的管理及部署机制在应对服务快速扩容、缩容需求时存在的诸多不足。例如资源实例创建慢、无法统一运行环境、实例部署和交付流程长、资源回收效率低、弹性能力差等等。经过调研与测试结合业界的实践经验我们决定基于Docker容器技术自研集群管理与调度系统有效应对快速扩缩容的需求提升资源的利用效率。我们把它叫做”绿巨人”——HULK这个阶段可以看作是HULK1.0。</p>
<p>之后在生产环境中经过不断摸索和尝试我们逐渐意识到仅仅满足于集群的弹性伸缩能力是不够的成本和效率肯定是未来必将面临且更为棘手的问题。我们吸取了2年来HULK 1.0的开发和运维经验在架构和支撑系统层面做了进一步优化和改进并借助于生态和开源的力量来为HULK赋能即引入了开源的集群管理与调度系统Kubernetes期望能进一步提升集群管理、运行的效率和稳定性同时降低资源成本。所以我们从自研平台转向了开源的Kubernetes系统并基于Kubernetes系统打造了更加智能化的集群管理与调度系统——HULK2.0。</p>
<h3>架构全览</h3>
<p>在架构层面HULK2.0如何能与上层业务和底层Kubernetes平台更好地分层和解耦是我们在设计之初就优先考虑的问题。我们期望它既要能对业务使用友好又能最大限度地发挥Kubernetes的调度能力使得业务层和使用方毋需关注资源关系细节所求即所得同时使发布、配置、计费、负载等逻辑层与底层的Kubernetes平台解耦分层并保持兼容原生Kubernetes API来访问Kubernetes集群。从而可以借助于统一的、主流的、符合业界规范的标准来解决美团点评基础架构面临的复杂的、多样的、不统一的管理需求。</p>
<h3>架构介绍</h3>
<p><img src="assets/2ee9196f5b84267cad90bf2d816548c4518488.jpg" alt="HULK2.0架构图" /></p>
<p>HULK2.0架构图</p>
<p>自上而下来看美团集群管理与调度平台面向全公司服务有各个主要业务线、统一的OPS平台以及Portal平台HULK不可能针对每个平台定制化接口和解决方案所以需要将多样的业务和需求抽象收敛,最终统一通过HULK API来屏蔽HULK系统的细节做到HULK与上层业务方的解耦。HULK API是对业务层和资源需求的抽象是外界访问HULK的唯一途径。</p>
<p>解决了上层的问题后我们再来看与下层Kubernetes平台的解耦。HULK接到上层资源请求后首先要进行一系列的初始化工作包括参数校验、资源余量、IP和Hostname的分配等等之后向Kubernetes平台实际申请分配机器资源最终将资源交付给用户Kubernetes API进一步将资源需求收敛和转换让我们可以借助于Kubernetes的资源管理优势。Kubernetes API旨在收敛HULK的资源管理逻辑并与业界主流对齐。此外因为完全兼容Kubernetes API可以让我们借助社区和生态的力量共同建设和探索。</p>
<p>可以看到HULK API和Kubernetes API将我们整个系统分为三层这样可以让每一层都专注于各自的模块。</p>
<h2>Kubernetes管理与实践</h2>
<p>为什么会选择Kubernetes呢Kubernetes并不是市面上唯一的集群管理平台其他如Docker Swarm或Mesos之所以选择它除了它本身优秀的架构设计我们更加看重的是Kubernetes提供的不是一个解决方案而是一个平台和一种能力。这种能力能够让我们真正基于美团点评的实际情况来扩展同时能够依赖和复用多年来的技术积累给予我们更多选择的自由包括我们可以快速地部署应用程序而无须面对传统平台所具有的风险动态地扩展应用程序以及更好的资源分配策略。</p>
<p><img src="assets/a0d77d87ae6495b99b3d88f4303819e8155794.jpg" alt="HULK-Kubernetes架构图" /></p>
<p>HULK-Kubernetes架构图</p>
<p>Kubernetes集群作为整个HULK集群资源管理与平台的基础需求是稳定性和可扩展性风险可控性和集群吞吐能力。</p>
<h3>集群运营现状</h3>
<ul>
<li>集群规模10万+级别线上实例,多地域部署,还在不断快速增长中。</li>
<li>业务的监控告警集群对应用的启动和状态数据进行采集container-init自动集成业务监控信息业务程序毋需关注做到可插拔、可配置。</li>
<li>资源的健康告警:从资源的角度对 Node、Pod和 Container等重要数据监控采集及时发现它们的状态信息例如 Node不可用、Container不断重启等等。</li>
<li>定时巡检与对账每天自动对所有宿主机进行状态检查包括剩余磁盘量数据卷、D进程数量、宿主机状态等并对AppKey扩容数据和实际的Pod和容器数据同步校验及时发现不一致情况。</li>
<li>集群数据可视化对当前集群状态包括宿主机资源状态、服务数、Pod数、容器化率、服务状态、扩缩容数据等等可视化并提供了界面化的服务配置、宿主机下线以及Pod迁移操作入口。</li>
<li>容量规划与预测:提前感知集群资源状态,预先准备资源;基于规则和机器学习的方式感知流量和高峰,保证业务正常、稳定、高效地运行。</li>
</ul>
<h2>Kubernetes优化与改造</h2>
<h3>kube-scheduler性能优化</h3>
<p>我们有集群在使用1.6版本的调度器随着集群规模的不断增长旧版本的Kubernetes调度器1.10之前版本在性能和稳定性的问题逐渐凸显由于调度器的吞吐量低导致业务扩容超时失败在规模近3000台的集群上一次Pod的调度耗时在5s左右。Kubernetes的调度器是队列化的调度器模型一旦扩容高峰等待的Pod数量过多就会导致后面Pod的扩容超时。为此我们对调度器性能进行了大幅度的优化并取得了非常明显的提升根据我们的实际生产环境验证性能比优化前提升了400%以上。</p>
<p>Kubernetes调度器工作模型如下</p>
<p><img src="assets/e71ef5edcdbb390ab265e8371f0f19fd134181.jpg" alt="kube-scheduler示意图" /></p>
<p>kube-scheduler示意图</p>
<p>kubernetes调度器图片来源于网络</p>
<h3>预选失败中断机制</h3>
<p>一次调度过程在判断一个 Node是否可作为目标机器时主要分为三个阶段</p>
<ul>
<li>预选阶段:硬性条件,过滤掉不满足条件的节点,这个过程称为 Predicates。这是固定先后顺序的一系列过滤条件任何一个 Predicate不符合则放弃该 Node。</li>
<li>优选阶段:软性条件,对通过的节点按照优先级排序,称之为 Priorities。每一个Priority都是一个影响因素都有一定的权重。</li>
<li>选定阶段:从优选列表中选择优先级最高的节点,称为 Select。选择的Node即为最终部署Pod的机器。</li>
</ul>
<p><img src="assets/ef026e009a90602b853af323f58af5c3266174.jpg" alt="kube-scheduler调度过程" /></p>
<p>kube-scheduler调度过程</p>
<p>通过深入分析调度过程可以发现,调度器在预选阶段即使已经知道当前 Node不符合某个过滤条件仍然会继续判断后续的过滤条件是否符合。试想如果有上万台 Node节点这些判断逻辑会浪费很多计算时间这也是调度器性能低下的一个重要因素。</p>
<p>为此,我们提出了“预选失败中断机制”,即一旦某个预选条件不满足,那么该 Node即被立即放弃后面的预选条件不再做判断计算从而大大减少了计算量调度性能也大大提升。如下图所示</p>
<p><img src="assets/f0fbc86f4397e6b51a6546a53669cfbc181723.jpg" alt="kube-scheduler的Predicates过程" /></p>
<p>kube-scheduler的Predicates过程</p>
<p>我们把该项优化贡献给了 Kubernetes社区(详见<a href="https://github.com/kubernetes/kubernetes/pull/56926">PR</a>),增加了 alwaysCheckAllPredicates 策略选项,并在 Kubernetes1.10版本发布并开始作为默认的调度策略当然你也可以通过设置alwaysCheckAllPredicates=true使用原先的调度策略。</p>
<p>在实际测试中调度器至少可以提升40%的性能如果你目前在使用的Kube-scheduler的版本低于1.10,那么建议你尝试升级到新的版本。</p>
<h4>局部最优解</h4>
<p>对于优化问题尤其是最优化问题,我们总希望找到全局最优的解或策略,但是当问题的复杂度过高,要考虑的因素和处理的信息量过多时,我们往往会倾向于接受局部最优解,因为局部最优解的质量不一定都是差的。尤其是当我们有确定的评判标准,同时标明得出的解是可以接受的话,通常会接收局部最优的结果。这样,从成本、效率等多方面考虑,才是我们在实际工程中真正会采取的策略。</p>
<p><img src="https://p1.meituan.net/travelcube/d7f2d0a79afa25a373c1d8d055b36bba1299704.png" alt="kube-scheduler的局部最优解" /></p>
<p>kube-scheduler的局部最优解</p>
<p>(图片来源于网络)</p>
<p>当前调度策略中每次调度调度器都会遍历集群中所有的Node以便找出最优的节点这在调度领域称之为BestFit算法。但是在生产环境中我们是选取最优Node还是次优Node其实并没有特别大的区别和影响有时候我们还是会避免选取最优的Node例如我们集群为了解决新上线机器后频繁在该机器上创建应用的问题就将最优解随机化。换句话说找出局部最优解就能满足需求。</p>
<p>假设集群一共1000个Node一次调度过程PodA这其中有700个Node都能通过Predicates预选阶段那么我们就会把所有的Node遍历并找出这700个Node然后经过得分排序找出最优的Node节点NodeX。但是采用局部最优算法即我们认为只要能找出N个Node并在这N个Node中选择得分最高的Node即能满足需求比如默认找出100个可以通过Predicates预选阶段的Node即可最优解就在这100个Node中选择。当然全局最优解NodeX也可能不在这100个Node中但是我们在这100个Node中选择最优的NodeY也能满足要求。最好的情况是遍历100个Node就找出这100个Node也可能遍历了200个或者300个Node等等这样我们可以大大减少计算时间同时也不会对我们的调度结果产生太大的影响。</p>
<p>局部最优的策略是我们与社区合作共同完成的,这里面还涉及到如何做到公平调度和计算任务优化的细节(详见<a href="https://github.com/kubernetes/kubernetes/pull/66733">PR1</a>,<a href="https://github.com/kubernetes/kubernetes/pull/67555">PR2</a>)该项优化在Kubernetes 1.12版本中发布,并作为当前默认调度策略,可以大幅度提升调度性能,尤其在大规模集群中的提升,效果非常明显。</p>
<h3>kubelet改造</h3>
<h4>风险可控性</h4>
<p>前面提到稳定性和风险可控性对大规模集群管理来说非常重要。从架构上来看Kubelet是离真实业务最近的集群管理组件我们知道社区版本的Kubelet对本机资源管理有着很大的自主性试想一下如果某个业务正在运行但是Kubelet由于出发了驱逐策略而把这个业务的容器干掉了会发生什么这在我们的集群中是不应该发生的所以需要收敛和封锁Kubelet的自决策能力它对本机上业务容器的操作都应该从上层平台发起。</p>
<p><strong>容器重启策略</strong></p>
<p>Kernel升级是日常的运维操作在通过重启宿主机来升级Kernel版本的时候我们发现宿主机重启后上面的容器无法自愈或者自愈后版本不对这会引发业务的不满也造成了我们不小的运维压力。后来我们为Kubelet增加了一个重启策略Reuse同时保留了原生重启策略Rebuild保证容器系统盘和数据盘的信息都能保留宿主机重启后容器也能自愈。</p>
<p><strong>IP状态保持</strong></p>
<p>根据美团点评的网络环境我们自研了CNI插件并通过基于Pod唯一标识来申请和复用IP。做到了应用IP在Pod迁移和容器重启之后也能复用为业务上线和运维带来了不少的收益。</p>
<p><strong>限制驱逐策略</strong></p>
<p>我们知道Kubelet拥有节点自动修复的能力例如在发现异常容器或不合规容器后会对它们进行驱逐删除操作这对于我们来说风险太大我们允许容器在一些次要因素方面可以不合规。例如当Kubelet发现当前宿主机上容器个数比设置的最大容器个数大时会挑选驱逐和删除某些容器虽然正常情况下不会轻易发生这种问题但是我们也需要对此进行控制降低此类风险。</p>
<h4>可扩展性</h4>
<p><strong>资源调配</strong></p>
<p>在Kubelet的扩展性方面我们增强了资源的可操作性例如为容器绑定Numa从而提升应用的稳定性根据应用等级为容器设置CPUShare从而调整调度权重为容器绑定CPUSet等等。</p>
<p><strong>增强容器</strong></p>
<p>我们打通并增强了业务对容器的配置能力支持业务给自己的容器扩展ulimit、io limit、pid limit、swap等参数的同时也增强容器之间的隔离能力。</p>
<p><strong>应用原地升级</strong></p>
<p>大家都知道Kubernetes默认只要Pod的关键信息有改动例如镜像信息就会出发Pod的重建和替换这在生产环境中代价是很大的一方面IP和HostName会发生改变另一方面频繁的重建也给集群管理带来了更多的压力甚至还可能导致无法调度成功。为了解决该问题我们打通了自上而下的应用原地升级功能即可以动态高效地修改应用的信息并能在原地宿主机进行升级。</p>
<p><strong>镜像分发</strong></p>
<p>镜像分发是影响容器扩容时长的一个重要环节,我们采取了一系列手段来优化,保证镜像分发效率高且稳定:</p>
<ul>
<li>跨Site同步保证服务器总能从就近的镜像仓库拉取到扩容用的镜像减少拉取时间降低跨Site带宽消耗。</li>
<li>基础镜像预分发:美团点评的基础镜像是构建业务镜像的公共镜像。业务镜像层是业务的应用代码,通常比基础镜像小很多。在容器扩容的时候如果基础镜像已经在本地,就只需要拉取业务镜像的部分,可以明显的加快扩容速度。为达到这样的效果,我们会把基础镜像事先分发到所有的服务器上。</li>
<li>P2P镜像分发基础镜像预分发在有些场景会导致上千个服务器同时从镜像仓库拉取镜像对镜像仓库服务和带宽带来很大的压力。因此我们开发了镜像P2P分发的功能服务器不仅能从镜像仓库中拉取镜像还能从其他服务器上获取镜像的分片。</li>
</ul>
<h2>资源管理与优化</h2>
<p><img src="assets/adccb59a6b315ba4f6d239704e0920d4271107.png" alt="资源管理与优化" /></p>
<p>资源管理与优化</p>
<h3>优化关键技术</h3>
<ul>
<li>服务画像对应用的CPU、内存、网络、磁盘和网络 I/O 容量和负载画像,了解应用的特征、资源规格和应用类型以及不同时间对资源的真实使用,然后从服务角度和时间维度进行相关性分析,从而进行整体调度和部署优化。</li>
<li>亲和性和互斥性:哪些应用放在一起使整体计算能力比较少而吞吐能力比较高,它们就存在一定亲和性;反之如果应用之间存在资源竞争或相互影响,则它们之间就存在着互斥性。</li>
<li>场景优先美团点评的业务大都是基本稳定的场景所以场景划分很有必要。例如一类业务对延迟非常敏感即使在高峰时刻也不允许有太多的资源竞争产生这种场景就要避免和减少资源竞争引起的延迟保证资源充足一类业务在有些时间段需要的CPU资源可能会突破配置的上限我们通过CPU Set化的方式让这类业务共享这部分资源以便能够突破申请规格的机器资源限制不仅服务能够获得更高的性能表现同时也把空闲的资源利用了起来资源使用率进一步提升。</li>
<li>弹性伸缩:应用部署做到流量预测、自动伸缩、基于规则的高低峰伸缩以及基于机器学习的伸缩机制。</li>
<li>精细化资源调配基于资源共享和隔离技术做到了精细化的资源调度和分配例如Numa绑定、任务优先级、CPU Set化等等。</li>
</ul>
<h3>策略优化</h3>
<p>调度策略的主要作用在两方面,一方面是按照既定策略部署目标机器;二是能做到集群资源的排布最优。</p>
<ul>
<li>亲和性有调用关系和依赖的应用或哪些应用放在一起能使整体计算能力比较少、吞吐能力比较高这些应用间就存在一定亲和性。我们的CPU Set化即是利用了对CPU的偏好构建应用的亲和性约束让不同CPU偏好的应用互补。</li>
<li>互斥性:跟亲和性相对,主要是对有竞争关系或业务干扰的应用在调度时尽量分开部署。</li>
<li>应用优先级:应用优先级的划分是为我们解决资源竞争提供了前提。当前当容器发生资源竞争时,我们无法决策究竟应该让谁获得资源,当有了应用优先级的概念后,我们可以做到,在调度层,限制单台宿主机上重要应用的个数,减少单机的资源竞争,也为单机底层解决资源竞争提供可能;在宿主机层,根据应用优先级分配资源,保证重要应用的资源充足,同时也可运行低优先级应用。</li>
<li>打散性应用的打散主要是为了容灾在这里分为不同级别的打散。我们提供了不同级别的打散粒度包括宿主机、Tor、机房、Zone等等。</li>
<li>隔离与独占:这是一类特殊的应用,必须是独立使用一台宿主机或虚拟机隔离环境部署,例如搜索团队的业务。</li>
<li>特殊资源特殊资源是满足某些业务对GPU、SSD、特殊网卡等特殊硬件需求。</li>
</ul>
<h3>在线集群优化</h3>
<p>在线集群资源的优化问题,不像离线集群那样可以通过预知资源需求从而达到非常好的效果,由于未来需求的未知性,在线集群很难在资源排布上达到离线集群的效果。针对在线集群的问题,我们从上层调度到底层的资源使用都采取了一系列的优化。</p>
<ul>
<li>Numa绑定主要是解决业务侧反馈服务不稳定的问题通过绑定Numa将同一个应用的CPU和Memory绑定到最合适的Numa Node上减少跨Node访问的开销提升应用性能。</li>
<li>CPU Set化将一组特性互补的应用绑定在同一组CPU上从而让他们能充分使用CPU资源。</li>
<li>应用错峰基于服务画像数据为应用错开高峰减少资源竞争和相互干扰提升业务SLA。</li>
<li>重调度资源排布优化用更少的资源提升业务性能和SLA解决碎片问题提升资源的分配率。</li>
<li>干扰分析基于业务监控数据指标和容器信息判断哪些容器有异常提升业务SLA发现并处理异常应用。</li>
</ul>
<h2>结束语</h2>
<p>当前,在以下几个方面我们正在积极探索:</p>
<ul>
<li>在线-离线业务混合部署,进一步提升资源使用效率。</li>
<li>智能化调度业务流量和资源使用感知调度提升服务SLA。</li>
<li>高性能、强隔离和更安全的容器技术。</li>
</ul>
</div>
</div>
<div>
<div style="float: left">
<a href="/文章/美团万亿级 KV 存储架构与实践.md.html">上一页</a>
</div>
<div style="float: right">
<a href="/文章/美团百亿规模API网关服务Shepherd的设计与实现.md.html">下一页</a>
</div>
</div>
</div>
</div>
</div>
</div>
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
</div>
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"709980790d368b66","version":"2021.12.0","r":1,"token":"1f5d475227ce4f0089a7cff1ab17c0f5","si":100}' crossorigin="anonymous"></script>
</body>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NPSEEVD756"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'G-NPSEEVD756');
var path = window.location.pathname
var cookie = getCookie("lastPath");
console.log(path)
if (path.replace("/", "") === "") {
if (cookie.replace("/", "") !== "") {
console.log(cookie)
document.getElementById("tip").innerHTML = "<a href='" + cookie + "'>跳转到上次进度</a>"
}
} else {
setCookie("lastPath", path)
}
function setCookie(cname, cvalue) {
var d = new Date();
d.setTime(d.getTime() + (180 * 24 * 60 * 60 * 1000));
var expires = "expires=" + d.toGMTString();
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
}
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i].trim();
if (c.indexOf(name) === 0) return c.substring(name.length, c.length);
}
return "";
}
</script>
</html>