mirror of
https://github.com/zhwei820/learn.lianglianglee.com.git
synced 2025-09-25 04:36:41 +08:00
253 lines
22 KiB
HTML
253 lines
22 KiB
HTML
<!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>00 为什么我们要学习 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 class="current-tab" href="/专栏/Kubernetes 实践入门指南/00 为什么我们要学习 Kubernetes 技术.md.html">00 为什么我们要学习 Kubernetes 技术</a>
|
||
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Kubernetes 实践入门指南/01 重新认识 Kubernetes 的核心组件.md.html">01 重新认识 Kubernetes 的核心组件</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Kubernetes 实践入门指南/02 深入理解 Kubernets 的编排对象.md.html">02 深入理解 Kubernets 的编排对象</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Kubernetes 实践入门指南/03 DevOps 场景下落地 K8s 的困难分析.md.html">03 DevOps 场景下落地 K8s 的困难分析</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Kubernetes 实践入门指南/04 微服务应用场景下落地 K8s 的困难分析.md.html">04 微服务应用场景下落地 K8s 的困难分析</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Kubernetes 实践入门指南/05 解决 K8s 落地难题的方法论提炼.md.html">05 解决 K8s 落地难题的方法论提炼</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Kubernetes 实践入门指南/06 练习篇:K8s 核心实践知识掌握.md.html">06 练习篇:K8s 核心实践知识掌握</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Kubernetes 实践入门指南/07 容器引擎 containerd 落地实践.md.html">07 容器引擎 containerd 落地实践</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Kubernetes 实践入门指南/08 K8s 集群安装工具 kubeadm 的落地实践.md.html">08 K8s 集群安装工具 kubeadm 的落地实践</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Kubernetes 实践入门指南/09 南北向流量组件 IPVS 的落地实践.md.html">09 南北向流量组件 IPVS 的落地实践</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Kubernetes 实践入门指南/10 东西向流量组件 Calico 的落地实践.md.html">10 东西向流量组件 Calico 的落地实践</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Kubernetes 实践入门指南/11 服务发现 DNS 的落地实践.md.html">11 服务发现 DNS 的落地实践</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Kubernetes 实践入门指南/12 练习篇:K8s 集群配置测验.md.html">12 练习篇:K8s 集群配置测验</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Kubernetes 实践入门指南/13 理解对方暴露服务的对象 Ingress 和 Service.md.html">13 理解对方暴露服务的对象 Ingress 和 Service</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Kubernetes 实践入门指南/14 应用网关 OpenResty 对接 K8s 实践.md.html">14 应用网关 OpenResty 对接 K8s 实践</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Kubernetes 实践入门指南/15 Service 层引流技术实践.md.html">15 Service 层引流技术实践</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Kubernetes 实践入门指南/16 Cilium 容器网络的落地实践.md.html">16 Cilium 容器网络的落地实践</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Kubernetes 实践入门指南/17 应用流量的优雅无损切换实践.md.html">17 应用流量的优雅无损切换实践</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Kubernetes 实践入门指南/18 练习篇:应用流量无损切换技术测验.md.html">18 练习篇:应用流量无损切换技术测验</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Kubernetes 实践入门指南/19 使用 Rook 构建生产可用存储环境实践.md.html">19 使用 Rook 构建生产可用存储环境实践</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Kubernetes 实践入门指南/20 有状态应用的默认特性落地分析.md.html">20 有状态应用的默认特性落地分析</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Kubernetes 实践入门指南/21 案例:分布式 MySQL 集群工具 Vitess 实践分析.md.html">21 案例:分布式 MySQL 集群工具 Vitess 实践分析</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Kubernetes 实践入门指南/22 存储对象 PV、PVC、Storage Classes 的管理落地实践.md.html">22 存储对象 PV、PVC、Storage Classes 的管理落地实践</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Kubernetes 实践入门指南/23 K8s 集群中存储对象灾备的落地实践.md.html">23 K8s 集群中存储对象灾备的落地实践</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/Kubernetes 实践入门指南/24 练习篇:K8s 集群配置测验.md.html">24 练习篇:K8s 集群配置测验</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>00 为什么我们要学习 Kubernetes 技术</h1>
|
||
<p>Kubernetes 是谷歌开源的分布式容器编排和资源管理系统。因为它的英文术语字数太长,社区专门给它定义了一个缩写单词:K8s。从 2014 年发布至今,已经成为 GitHub 社区中最炙手可热的开源项目。因为以 K8s 为核心的云原生技术已经成为业界企业数字化转型的事实标准技术栈。国内企业纷纷效仿并开始计划落地 K8s 集群作为企业应用发布的默认基础设施,但是具体怎么落实这项云原生技术其实并没有特别好实施的工具,大部分情况下我们必须结合现有企业的实际情况来落地企业应用。当然,这个说起来容易,真正开始落地的时候,技术人员就会发现遇到一点问题能在网上查到的都是一些碎片化的知识,很难系统的解决实际应用发布和部署问题。所以,笔者借着这个场景机会,秉着布道云原生技术的信心带着大家来一起探讨 <strong>K8s 落地的各项技术细节和实际的决策思路</strong>,让 K8s 的用户可以从容自如的应对落地容器集群编排技术。</p>
|
||
<p>在学习 K8s 技术之前,我想给大家梳理下当前社区在学习 K8s 过程中遇到的几个问题:</p>
|
||
<p><strong>选择多:</strong> K8s 系统是一套专注容器应用管理的集群系统,它的组件一般按功能分别部署在主控节点(master node)和计算节点(agent node)。对于主控节点,主要包含有 etcd 集群,controller manager 组件,scheduler 组件,api-server 组件。对于计算节点,主要包含 kubelet 组件和 kubelet-proxy 组件。初学者会发现其实 <strong>K8s 的组件并不是特别多,为什么给人的印象就是特别难安装呢?</strong> 这里需要特别强调的是,即使到了 2020 年,我们基础软硬件设施并不能保证装完就是最优的配置,仍然需要系统工程师解决一些兼容性问题。所以当你把这些 K8s 系统组件安装到物理机、虚拟机中,并不能保证就是最优的部署配置。因为这个原因,当你作为用户在做一份新的集群部署的方案的时候,需要做很多选择题才能调优到最优解。</p>
|
||
<p>另外,企业业务系统的发布,并不止依赖于 K8s,它还需要包括网络、存储等。我们知道容器模型是基于单机设计的,当初设计的时候并没有考虑大规模的容器在跨主机的情况下通信问题。Pod 和 Pod 之间的网络只定义了接口标准,具体实现还要依赖第三方的网络解决方案。一直发展到今天,你仍然需要面对选择,选择适合的网络方案和网络存储。</p>
|
||
<p>这里特别强调的是,目前容器网络并没有完美方案出现,它需要结合你的现有环境和基础硬件的情况来做选择。但是,当前很多书籍资料只是介绍当前最流行的开源解决方案,至于这个方案是否能在你的系统里面跑的更好是不承担责任的。这个给系统运维人员带来的痛苦是非常巨大的。一直到现在,我遇到很多维护 K8s 系统的开发运维还是对这种选择题很头疼。是的,开源社区的方案是多头驱动并带有竞争关系的,我们不能拍脑袋去选择一个容器网络之后就不在关心它的发展的。今天的最优网络方案可能过半年就不是最优的了。同理这种问题在应对选择容器存储解决方案过程中也是一样的道理。</p>
|
||
<p><strong>排错难:</strong> 当前 K8s 社区提供了各种各样的 K8s 运维工具,有 ansible 的,dind 容器化的,有 mac-desktop 桌面版本的,还有其他云原生的部署工具。每种工具都不是简单的几行代码就能熟悉,用户需要投入很大的精力来学习和试用。因为各种底层系统的多样性,你会遇到各种各样的问题,比如容器引擎 Docker 版本低,时间同步组件 ntp 没有安装,容器网络不兼容底层网络等。任何一个点出了问题,你都需要排错。加上企业的系统环境本来就很复杂,很多场景下都是没有互联网可以查资料的,对排错来说即使所有的日志都收集起来做分析也很难轻易的排错。</p>
|
||
<p>你可能会觉得这是公司的基础设施没有建设好,可以考虑专家看看。用户倒是想解决这个问题,但是不管是商业方案还是开源方案都只是片面的考虑到 K8s 核心组件的排错,而真正企业关心的应用容器,集群,主机,网络,存储,监控日志,持续集成发布等方面的排错实践就只能靠自己摸索,你很难系统的学习到。还有,K8s 集群的版本是每个季度有一个大版本的更新。对于企业用户来说<strong>怎么才能在保证业务没有影响的情况下平滑更新 K8s 组件呢?</strong> 头疼的问题就是这么出来的。一旦发生不可知问题,如何排错和高效的解决问题呢。这就是本系列专栏和大家探讨的问题。</p>
|
||
<p><strong>场景多:</strong> 在早期的应用编排场景,主要是为了削峰填谷,高效利用浪费的主机资源。一个不公开的企业运维秘密就是生产中主机资源平均利用率不超过 20%。这不是因为运维傻,这是因为如果遇到峰值,主机系统需要能平滑应对,需要给业务容量留有余地。因为容器的引入让原来主机仅可以部署 3-4 个进程的系统,现在可以充分利用容器进程隔离的技术在主机上部署 20-40 个进程系统,并且各自还不受影响。这就是容器应用的最大好处。</p>
|
||
<p>社区里面有好学习的技术架构师也曾经说过,在介绍什么是容器时,就拿租房过程中,单身公寓和打隔断的群租房来对比形容,特别形象。随着应用场景的多样性,在应对突发流量的时候,K8s 编排系统就是作为一种弹性伸缩的工具,快速提高进程的数量来承载流量。在解决微服务应用编排上,除了传统的微服务部署需求之外,还有混合部署需要的 Service Mesh 技术也对 K8s 提出了流量编排的新要求。另外还有 Serverless 场景下的 FaaS 框架 Openfaas 也对 K8s 带来了新的机会和应用难点。还有很多有状态中间件服务,如数据库集群等也都在大量的迁入到 K8s 集群中,并获得了很好的实践反馈。</p>
|
||
<p>现在 K8s 已经成为企业数字化转型中应用发布管理的标准基础设施方案,面对这么多场景需求,我们用一套容器编排集群能把所有需求都解决吗?显然是不可以的。实际情况下很多应用集群为了管理和优化上的考虑,都是多套集群系统。多套集群在多个区域部署,给运维带来了不少麻烦。这也是多场景下多集群治理带来的烦恼。</p>
|
||
<p>以上这些问题仅仅是笔者这些年来遇到的客户在和我交流过程中积累下的重点问题。实际过程中,我们还会遇到很多不是 K8s 的问题,但是我们为了落地容器编排集群不得不做的折中选择。这些都是我们在学习过程中需要注意和总结的经验。</p>
|
||
<h3>专栏特色</h3>
|
||
<ul>
|
||
<li>从实践场景出发,按照使用者的角度来梳理技术细节</li>
|
||
<li>通过完整的知识体系为 K8s 用户提供了使用依据</li>
|
||
<li>各章节切入点考虑普适性,让更多人能有理有据的选择适合自己的问题解决方案</li>
|
||
</ul>
|
||
<h3>你将获得什么</h3>
|
||
<p>通过本专栏的学习,你将<strong>全方位的理解 K8s 组件的原理技术</strong>,并结合云原生开源思想,学习到分布式系统的组合过程。为了解决日常场景中可能的问题,你也可以分章节获得<strong>独家的实践理解和解决思路过程</strong>,让你可以推演并学习到一些架构思维模型。并且笔者也给大家精选了 K8s 组件的详细讲解,可以让好奇的使用者,不断可以知道这些组件的原理,还能知道它们内部的实现,让你可以更准确的把握这些组件,相信你也有机会参与 K8s 的开发并写出更多的组件代替它们。</p>
|
||
<h3>专栏结构</h3>
|
||
<p>我在编写此系列文章的过程中,尽量避免复制网络上大量的参考资料,通过自身搭建的系统帮助大家从零搭建起生产落地的经验。因为涉及的内容太分散,容易让读者失焦。所以我重点把生产落地中遇到的几个点给大家重点讲讲。</p>
|
||
<p>第一部分,我就想讲讲 K8s 组件的优化和安装步骤过程中需要注意的问题。这块,有很多书都讲的很细了。但是我看到的书籍中都是讲过程,不讲为什么是这样设计的。这个在当年我学习 K8s 的过程中就非常的痛苦。这次我想帮大家扫清这块的学习障碍。</p>
|
||
<p>第二部分,我们需要讲配置。一套复杂的系统本身最重要的就是熟悉各种组件的配置信息。配置错了,大家怎么调试也不会有好的结果,所以这块的各个选项的理解也是很重要的。虽然这块很枯燥但是还必须掌握。我尽量通过 kubectl 来描述这块的内容。</p>
|
||
<p>第三部分,是对网络流量的架构分享,我想这块的内容也是大量 用户特别关心的地方。因为每一种网络方案还要涉及配置,压测,选择,还是有很多需要注意的地方。</p>
|
||
<p>第四部分,就是业务应用的存储选择了。网络存储方案发展至今,最出名的就是 Ceph 了。但是如果你不合时宜的直接上马 Ceph 方案,马上就会掉入运维 Ceph 的坑里面。其实容器存储的方案有很多种,你要结合你的需求,选择合适的方案。当然在企业内部,大家都需要有那种统一的方案,什么需求都可以支持的容器存储,我觉得这个就是对业务理解的偏差。更友好的选择应该是专项专用。这样肯定会带来各种各样的方案,这个也不是不能解决,使用 K8s 来编排管理各种存储也是业务发展的必然。</p>
|
||
<p>第五部分,我们会重点关注 K8s 集群的安全配置工作。安装 K8s 算是一个中型大小的任务,对 K8s 的安全配置和调优更是业务重心。这方面的开源工具层出不穷,我们需要学习和掌握核心方法论,梳理出自己需要的工具链,来应对容器安全落地实践。</p>
|
||
<p>最后,我希望大家能尽快入坑 K8s 的学习过程中,让我们一起探讨和落地安全可靠的 K8s 容器应用编排集群。</p>
|
||
<h3>专栏作者</h3>
|
||
<p>肖德时,企业级容器技术的布道师,Docker/Kubernetes/Openshift 等多项国际顶级开源项目社区开发者。前容器云创业公司数人云 CTO。目前对容器技术、Kubernetes 等分布式系统等领域进行技术研究和布道。</p>
|
||
<h3>适宜人群</h3>
|
||
<p>所有运维开发工程师、系统工程师、DevOps 工程师和想掌握容器和技术的IT工程师都可以来看一看。因为云原生技术已经在中国企业广泛应用,我们需要学习并更深入的学习这项技术,为了更准确的理解这项技术,本系列最适合各应用阶段的企业员工和技术爱好者。</p>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
|
||
<div style="float: right">
|
||
<a href="/专栏/Kubernetes 实践入门指南/01 重新认识 Kubernetes 的核心组件.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":"7099725b2c923d60","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>
|