<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Kubernetes 实践入门指南 on GoClub</title><link>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/</link><description>Recent content in Kubernetes 实践入门指南 on GoClub</description><generator>Hugo</generator><language>zh-cn</language><atom:link href="https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/index.xml" rel="self" type="application/rss+xml"/><item><title>00 为什么我们要学习 Kubernetes 技术</title><link>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/001/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/001/</guid><description>&lt;div class="goclub-source-note"&gt;来源：&lt;a href="https://study.disign.me/document/Kubernetes%20%e5%ae%9e%e8%b7%b5%e5%85%a5%e9%97%a8%e6%8c%87%e5%8d%97/00%20%e4%b8%ba%e4%bb%80%e4%b9%88%e6%88%91%e4%bb%ac%e8%a6%81%e5%ad%a6%e4%b9%a0%20Kubernetes%20%e6%8a%80%e6%9c%af.md" target="_blank" rel="noopener noreferrer"&gt;技术书栈原文&lt;/a&gt;。本页按授权迁移至 GoClub。&lt;/div&gt;
&lt;h1 id="00-为什么我们要学习-kubernetes-技术"&gt;00 为什么我们要学习 Kubernetes 技术&lt;/h1&gt;
&lt;p&gt;Kubernetes 是谷歌开源的分布式容器编排和资源管理系统。因为它的英文术语字数太长，社区专门给它定义了一个缩写单词：K8s。从 2014 年发布至今，已经成为 GitHub 社区中最炙手可热的开源项目。因为以 K8s 为核心的云原生技术已经成为业界企业数字化转型的事实标准技术栈。国内企业纷纷效仿并开始计划落地 K8s 集群作为企业应用发布的默认基础设施，但是具体怎么落实这项云原生技术其实并没有特别好实施的工具，大部分情况下我们必须结合现有企业的实际情况来落地企业应用。当然，这个说起来容易，真正开始落地的时候，技术人员就会发现遇到一点问题能在网上查到的都是一些碎片化的知识，很难系统的解决实际应用发布和部署问题。所以，笔者借着这个场景机会，秉着布道云原生技术的信心带着大家来一起探讨 &lt;strong&gt;K8s 落地的各项技术细节和实际的决策思路&lt;/strong&gt;，让 K8s 的用户可以从容自如的应对落地容器集群编排技术。&lt;/p&gt;
&lt;p&gt;在学习 K8s 技术之前，我想给大家梳理下当前社区在学习 K8s 过程中遇到的几个问题：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;选择多：&lt;/strong&gt; K8s 系统是一套专注容器应用管理的集群系统，它的组件一般按功能分别部署在主控节点（master node）和计算节点(agent node)。对于主控节点，主要包含有 etcd 集群，controller manager 组件，scheduler 组件，api-server 组件。对于计算节点，主要包含 kubelet 组件和 kubelet-proxy 组件。初学者会发现其实 &lt;strong&gt;K8s 的组件并不是特别多，为什么给人的印象就是特别难安装呢？&lt;/strong&gt; 这里需要特别强调的是，即使到了 2020 年，我们基础软硬件设施并不能保证装完就是最优的配置，仍然需要系统工程师解决一些兼容性问题。所以当你把这些 K8s 系统组件安装到物理机、虚拟机中，并不能保证就是最优的部署配置。因为这个原因，当你作为用户在做一份新的集群部署的方案的时候，需要做很多选择题才能调优到最优解。&lt;/p&gt;
&lt;p&gt;另外，企业业务系统的发布，并不止依赖于 K8s，它还需要包括网络、存储等。我们知道容器模型是基于单机设计的，当初设计的时候并没有考虑大规模的容器在跨主机的情况下通信问题。Pod 和 Pod 之间的网络只定义了接口标准，具体实现还要依赖第三方的网络解决方案。一直发展到今天，你仍然需要面对选择，选择适合的网络方案和网络存储。&lt;/p&gt;
&lt;p&gt;这里特别强调的是，目前容器网络并没有完美方案出现，它需要结合你的现有环境和基础硬件的情况来做选择。但是，当前很多书籍资料只是介绍当前最流行的开源解决方案，至于这个方案是否能在你的系统里面跑的更好是不承担责任的。这个给系统运维人员带来的痛苦是非常巨大的。一直到现在，我遇到很多维护 K8s 系统的开发运维还是对这种选择题很头疼。是的，开源社区的方案是多头驱动并带有竞争关系的，我们不能拍脑袋去选择一个容器网络之后就不在关心它的发展的。今天的最优网络方案可能过半年就不是最优的了。同理这种问题在应对选择容器存储解决方案过程中也是一样的道理。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;排错难：&lt;/strong&gt; 当前 K8s 社区提供了各种各样的 K8s 运维工具，有 ansible 的，dind 容器化的，有 mac-desktop 桌面版本的，还有其他云原生的部署工具。每种工具都不是简单的几行代码就能熟悉，用户需要投入很大的精力来学习和试用。因为各种底层系统的多样性，你会遇到各种各样的问题，比如容器引擎 Docker 版本低，时间同步组件 ntp 没有安装，容器网络不兼容底层网络等。任何一个点出了问题，你都需要排错。加上企业的系统环境本来就很复杂，很多场景下都是没有互联网可以查资料的，对排错来说即使所有的日志都收集起来做分析也很难轻易的排错。&lt;/p&gt;</description></item><item><title>01 重新认识 Kubernetes 的核心组件</title><link>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/002/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/002/</guid><description>&lt;div class="goclub-source-note"&gt;来源：&lt;a href="https://study.disign.me/document/Kubernetes%20%e5%ae%9e%e8%b7%b5%e5%85%a5%e9%97%a8%e6%8c%87%e5%8d%97/01%20%e9%87%8d%e6%96%b0%e8%ae%a4%e8%af%86%20Kubernetes%20%e7%9a%84%e6%a0%b8%e5%bf%83%e7%bb%84%e4%bb%b6.md" target="_blank" rel="noopener noreferrer"&gt;技术书栈原文&lt;/a&gt;。本页按授权迁移至 GoClub。&lt;/div&gt;
&lt;h1 id="01-重新认识-kubernetes-的核心组件"&gt;01 重新认识 Kubernetes 的核心组件&lt;/h1&gt;
&lt;p&gt;本篇我们开始介绍 Kubernetes 的核心组件，为了方便大家提前在脑中建立起完整的 Kubernetes 架构印象，笔者整理出核心组件的介绍如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;kube-apiserver，提供了 Kubernetes 各类资源对象（Pod、RC、Service 等）的增删改查及 watch 等 HTTP REST 接口，是整个系统的管理入口。&lt;/li&gt;
&lt;li&gt;kube-controller-manager，作为集群内部的管理控制中心，负责集群内的 Node、Pod 副本、服务端点（Endpoint）、命名空间（Namespace）、服务账号（ServiceAccount）、资源定额（ResourceQuota）等对象管理。&lt;/li&gt;
&lt;li&gt;kube-scheduler，集群调度器，提供了策略丰富，弹性拓扑能力。调度实现专注在业务可用性、性能和容量等能力上。&lt;/li&gt;
&lt;li&gt;kube-proxy，提供南北向流量负载和服务发现的反向代理。&lt;/li&gt;
&lt;li&gt;kubelet，是工作节点的管理 Pod 的控制程序，专门来调度启动 Pod 容器组。&lt;/li&gt;
&lt;li&gt;etcd，是集群数据集中存储的分布式键值服务，用来存储 Kubernetes 集群中所有数据和状态的数据库。&lt;/li&gt;
&lt;li&gt;cni-plugins，容器网络工作组维护的标准网络驱动如 fannel、ptp、host-local、portmap、tuning、vlan、sample、dhcp、ipvlan、macvlan、loopback、bridge 等网络插件供业务需求使用。这层 Overlay 网络只能包含一层，无法多层网络的互联互通。&lt;/li&gt;
&lt;li&gt;runc，运行单个容器的容器运行时进程，遵循 OCI（开放容器标准）。&lt;/li&gt;
&lt;li&gt;cri-o，容器运行时管理进程，类似 Docker 管理工具 containerd，国内业界普遍使用 containerd。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我们可以用如下一张架构设计图更能深刻理解和快速掌握 Kubernetes 的核心组件的布局：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://go.botsarena.tech/pictures/study-disign/92099e99319eed3d3f7d.webp" alt="1-1-k8s-arch"&gt;&lt;/p&gt;
&lt;p&gt;通过以上的介绍，核心组件的基本知识就这么多。从最近几年落地 Kubernetes 云原生技术的用户反馈来看，大家仍然觉得这套系统太复杂，不太好管理，并且随时担心系统给业务带来致命性的影响。&lt;/p&gt;
&lt;p&gt;那么 Kubernetes 的组件是为分布式系统设计的，为什么大家还是担心它会影响业务系统的稳定性呢？从笔者接触到的用户来讲，业界并没有统一的可以直接参考的解决方案。大家在落地过程中，只能去摸石头过河，一点一点总结经验并在迭代中不断地改进实施方案。因为业务规模的不同，Kubernetes 实施的架构也完全不同，你很难让基础设施的一致性在全部的商业企业 IT 环境中保持一致性。业务传播的都是最佳实践，在 A 用户这里可以行的通，不代表在 B 用户可以实施下去。&lt;/p&gt;
&lt;p&gt;当然，除了客观的限制因素之外，我们应用 Kubernetes 的初衷是尽量的保持企业的 IT 基础设施的一致性，并随着企业业务需求的增长而弹性扩展。毕竟 Kubernetes 是谷歌基于内部 Borg 应用管理系统成功经验的基础之上开源的容器编排系统，它的发展积累了整个业界的经验精华，所以目前企业在做数字转型的阶段，都在无脑的切换到这套新的环境中，生怕技术落后影响了业务的发展。&lt;/p&gt;</description></item><item><title>02 深入理解 Kubernets 的编排对象</title><link>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/003/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/003/</guid><description>&lt;div class="goclub-source-note"&gt;来源：&lt;a href="https://study.disign.me/document/Kubernetes%20%e5%ae%9e%e8%b7%b5%e5%85%a5%e9%97%a8%e6%8c%87%e5%8d%97/02%20%e6%b7%b1%e5%85%a5%e7%90%86%e8%a7%a3%20Kubernets%20%e7%9a%84%e7%bc%96%e6%8e%92%e5%af%b9%e8%b1%a1.md" target="_blank" rel="noopener noreferrer"&gt;技术书栈原文&lt;/a&gt;。本页按授权迁移至 GoClub。&lt;/div&gt;
&lt;h1 id="02-深入理解-kubernets-的编排对象"&gt;02 深入理解 Kubernets 的编排对象&lt;/h1&gt;
&lt;p&gt;Kubernetes 系统是一套分布式容器应用编排系统，当我们用它来承载业务负载时主要使用的编排对象有 Deployment、ReplicaSet、StatefulSet、DaemonSet 等。读者可能好奇的地方是 Kubernetes 管理的对象不是 Pod 吗？为什么不去讲讲如何灵活配置 Pod 参数。其实这些对象都是对 Pod 对象的扩展封装。并且这些对象作为核心工作负载 API 固化在 Kubernetes 系统中了。所以 ，我们有必要认真的回顾和理解这些编排对象，依据生产实践的场景需要，合理的配置这些编排对象，让 Kubernetes 系统能更好的支持我们的业务需要。本文会从实际应用发布的场景入手，分析和梳理具体场景中需要考虑的编排因素，并整理出一套可以灵活使用的编排对象使用实践。&lt;/p&gt;
&lt;h3 id="常规业务容器部署策略"&gt;常规业务容器部署策略&lt;/h3&gt;
&lt;h4 id="策略一-强制运行不少于-2-个容器实例副本"&gt;&lt;strong&gt;策略一：强制运行不少于 2 个容器实例副本&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;在应对常规业务容器的场景之下，Kubernetes 提供了 Deployment 标准编排对象，从命令上我们就可以理解它的作用就是用来部署容器应用的。Deployment 管理的是业务容器 Pod，因为容器技术具备虚拟机的大部分特性，往往让用户误解认为容器就是新一代的虚拟机。从普通用户的印象来看，虚拟机给用户的映象是稳定可靠。如果用户想当然地把业务容器 Pod 也归类为稳定可靠的实例，那就是完全错误的理解了。容器组 Pod 更多的时候是被设计为短生命周期的实例，它无法像虚拟机那样持久地保存进程状态。因为容器组 Pod 实例的脆弱性，每次发布的实例数一定是多副本，默认最少是 2 个。&lt;/p&gt;
&lt;p&gt;部署多副本示例：&lt;/p&gt;
&lt;h4 id="策略二-采用节点亲和-pod-间亲和-反亲和确保-pod-实现高可用运行"&gt;&lt;strong&gt;策略二：采用节点亲和，Pod 间亲和/反亲和确保 Pod 实现高可用运行&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;当运维发布多个副本实例的业务容器的时候，一定需要仔细注意到一个事实。Kubernetes 的调度默认策略是选取最空闲的资源主机来部署容器应用，不考虑业务高可用的实际情况。当你的集群中部署的业务越多，你的业务风险会越大。一旦你的业务容器所在的主机出现宕机之后，带来的容器重启动风暴也会即可到来。为了实现业务容错和高可用的场景，我们需要考虑通过 Node 的亲和性和 Pod 的反亲和性来达到合理的部署。这里需要注意的地方是，Kubernetes 的调度系统接口是开放式的，你可以实现自己的业务调度策略来替换默认的调度策略。我们这里的策略是尽量采用 Kubernetes 原生能力来实现。&lt;/p&gt;
&lt;p&gt;为了更好地理解高可用的重要性，我们深入探讨一些实际的业务场景。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;首先，Kubernetes 并不是谷歌内部使用的 Borg 系统&lt;/strong&gt;，大部分中小企业使用的 Kubernetes 部署方案都是人工扩展的私有资源池。当你发布容器到集群中，集群不会因为资源不够能自动扩展主机并自动负载部署容器 Pod。即使是在公有云上的 Kubernetes 服务，只有当你选择 Serverlesss Kubernetes 类型时才能实现资源的弹性伸缩。很多传统企业在落地 Kubernetes 技术时比较关心的弹性伸缩能力，目前只能折中满足于在有限静态资源的限制内动态启停容器组 Pod，实现类似的业务容器的弹性。用一个不太恰当的比喻就是房屋中介中，从独立公寓变成了格子间公寓，空间并没有实质性扩大。在实际有限资源的情况下，Kubernetes 提供了打标签的功能，你可以给主机、容器组 Pod 打上各种标签，这些标签的灵活运用，可以帮你快速实现业务的高可用运行。&lt;/p&gt;</description></item><item><title>03 DevOps 场景下落地 K8s 的困难分析</title><link>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/004/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/004/</guid><description>&lt;div class="goclub-source-note"&gt;来源：&lt;a href="https://study.disign.me/document/Kubernetes%20%e5%ae%9e%e8%b7%b5%e5%85%a5%e9%97%a8%e6%8c%87%e5%8d%97/03%20DevOps%20%e5%9c%ba%e6%99%af%e4%b8%8b%e8%90%bd%e5%9c%b0%20K8s%20%e7%9a%84%e5%9b%b0%e9%9a%be%e5%88%86%e6%9e%90.md" target="_blank" rel="noopener noreferrer"&gt;技术书栈原文&lt;/a&gt;。本页按授权迁移至 GoClub。&lt;/div&gt;
&lt;h1 id="03-devops-场景下落地-k8s-的困难分析"&gt;03 DevOps 场景下落地 K8s 的困难分析&lt;/h1&gt;
&lt;p&gt;Kubernetes 是用于自动部署，扩展和管理容器化应用程序的开源系统，一般被 DevOps 团队用来解决在 CI/CD（也就是持续集成、持续发布）场景下遇到的工具链没法统一，构建过程没法标准化等痛点。DevOps 团队在落地 Kubernetes 的过程中发现，在安装、发布、网络、存储、业务滚动升级等多个环节都会遇到一些不可预期的问题，并且官方的参考资料并没有确定性的方案来解决。很多 DevOps 因为需要快速迭代，都不得不采用现有的经验临时解决遇到的问题，因为场景限制，各家的问题又各有各的诉求，让很多经验无法真正的传承和共享。本文旨在直面当前的 DevOps 痛点，从源头梳理出核心问题点，并结合业界最佳的实践整理出一些可行的方法论，让 DevOps 团队在日后落地可以做到从容应对，再也不用被 Kubernetes 落地难而困扰了。&lt;/p&gt;
&lt;h3 id="kubernetes-知识体系的碎片化问题"&gt;Kubernetes 知识体系的碎片化问题&lt;/h3&gt;
&lt;p&gt;很多 DevOps 团队在落地 Kubernetes 系统时会时常借助互联网上分享的业界经验作为参考，并期望自己少点趟坑。但是当真落地到具体问题的时候，因为环境的不一致，场景需求的不一致等诸多因素，很难在现有的方案中找到特别合适的方案。&lt;/p&gt;
&lt;p&gt;另外还是更加糟糕的情况是，网上大量的资料都是过期的资料，给团队的知识体系建设带来了很多障碍。虽然团队可以借助外部专家的指导、专业书籍的学习等多种方法，循序渐进地解决知识的盲点。我们应该避免 Kubernetes 爆炸式的知识轰炸，通过建立知识图谱有效地找到适合自己团队的学习路径，让 Kubernetes 能支撑起你的业务发展。以下就是笔者为你提供的一份知识图谱的参考图例：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://go.botsarena.tech/pictures/study-disign/91d580789fd29a5eec4f.webp" alt="img"&gt;&lt;/p&gt;
&lt;p&gt;有了图谱，你就有了一张知识导航图，帮助你在需要的时候全局了解团队的 Kubernetes 能力。&lt;/p&gt;
&lt;h3 id="容器网络的选择问题"&gt;容器网络的选择问题&lt;/h3&gt;
&lt;p&gt;容器网络的选择难题一直是 DevOps 团队的痛点。Kubernetes 集群设计了 2 层网络，第一层是服务层网络，第二层是 Pod 网络。Pod 网络可以简单地理解为东西向容器网络，和常见的 Docker 容器网络是一致的设计。服务层网络是 Kubernetes 对外暴露服务的网络，简单地可以理解为南北向容器网络。Kubernetes 官方部署的常见网络是 Flannel，它是最简化的 Overlay 网络，因为性能不高只能在开发测试环境中使用。为了解决网络问题，社区提供了如 Calico、Contiv、Cilium、Kube-OVN 等诸多优秀的网络插件，让用户在选择时产生困惑。&lt;/p&gt;
&lt;p&gt;首先企业在引入 Kubernetes 网络时，仅仅把它作为一套系统网络加入企业网络。企业网络一般设计为大二层网络，对于每一套系统的网络规划都是固定的。这样的规划显然无法满足 Kubernetes 网络的发展。为了很好地理解和解决这样的难题，我们可以先把大部分用户的诉求整理如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;第一 ，由于容器实例的绝对数量剧增，如果按照实例规划 IP 数量，显然不合理。&lt;/li&gt;
&lt;li&gt;第二、我们需要像虚拟机实例一样，给每一个容器实例配置固定的 IP 地址。&lt;/li&gt;
&lt;li&gt;第三、容器网络性能不应该有损耗，最少应该和物理网络持平。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在这样的需求下，网络性能是比较关键的指标。查阅网上推荐的实践，可以看到一些结论：Calico 的虚拟网络性能是接近物理网络的，它配置简化并且还支持 NetworkPolicy，它是最通用的方案。在物理网络中，可以采用 MacVlan 来获得原生网络的性能，并且能打通和系统外部网络的通信问题。&lt;/p&gt;</description></item><item><title>04 微服务应用场景下落地 K8s 的困难分析</title><link>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/005/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/005/</guid><description>&lt;div class="goclub-source-note"&gt;来源：&lt;a href="https://study.disign.me/document/Kubernetes%20%e5%ae%9e%e8%b7%b5%e5%85%a5%e9%97%a8%e6%8c%87%e5%8d%97/04%20%e5%be%ae%e6%9c%8d%e5%8a%a1%e5%ba%94%e7%94%a8%e5%9c%ba%e6%99%af%e4%b8%8b%e8%90%bd%e5%9c%b0%20K8s%20%e7%9a%84%e5%9b%b0%e9%9a%be%e5%88%86%e6%9e%90.md" target="_blank" rel="noopener noreferrer"&gt;技术书栈原文&lt;/a&gt;。本页按授权迁移至 GoClub。&lt;/div&gt;
&lt;h1 id="04-微服务应用场景下落地-k8s-的困难分析"&gt;04 微服务应用场景下落地 K8s 的困难分析&lt;/h1&gt;
&lt;p&gt;近些年企业应用开发架构发生了细微的变化，根据康威定律，由于企业组织架构的变化，导致微服务应用体系开始在企业应用开发过程中流行起来。微服务是最近几年企业数字化转型过程中，在技术团队技术选型中比较常见的架构升级方案之一。在这个背景下，DevOps 团队为了应对企业架构的变化，迫切需要使用一套统一的基础设施来维护微服务应用的整个生命周期，这就给我们带来了新的挑战——如何应对微服务应用场景，平稳快速的落地 Kubernetes 集群系统。&lt;/p&gt;
&lt;h3 id="基于-kubernetes-下的微服务注册中心的部署问题"&gt;基于 Kubernetes 下的微服务注册中心的部署问题&lt;/h3&gt;
&lt;p&gt;经典的微服务体系都是以注册中心为核心，通过 CS 模式让客户端注册到注册中心服务端，其它微服务组件才能互相发现和调用。当我们引入 Kubernetes 之后，因为 Kubernetes 提供了基于 DNS 的名字服务发现，并且提供 Pod 级别的网格，直接打破了原有物理网络的单层结构，让传统的微服务应用和 Kubernetes 集群中的微服务应用无法直接互联互通。为了解决这个问题，很多技术团队会采用如下两种方式来打破解决这种困境。&lt;/p&gt;
&lt;h4 id="创建大二层网络-让-pod-和物理网络互联互通"&gt;&lt;strong&gt;创建大二层网络，让 Pod 和物理网络互联互通&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;这个思路主要的目的是不要改变现有网络结构，让 Kubernetes 的网络适应经典网络。每一个 Pod 分配一个可控的网络段 IP。常用的方法有 macvlan、Calico BGP、Contiv 等。这样的做法直接打破了 Kubernetes 的应用架构哲学，让 Kubernetes 成为了一个运行 Pod 的资源池，而上面的更多高级特性 Service，Ingress、DNS 都无法配合使用。随着 Kubernetes 版本迭代，这种阉割功能的 Kubernetes 架构就越来越食之无味弃之可惜了。&lt;/p&gt;
&lt;h4 id="注册中心部署到-kubernetes-集群中-外网服务直接使用-ip-注册"&gt;&lt;strong&gt;注册中心部署到 Kubernetes 集群中，外网服务直接使用 IP 注册&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;这种思路是当前最流行的方式，也是兼顾历史遗留系统的可以走通的网络部署结构。采用 StatefulSet 和 Headless Service，我们可以轻松地搭建 AP 类型的注册中心集群。当 Client 端连接 Server 端时，如果在 Kubernetes 内部可以采用域名的方式。例如：&lt;/p&gt;
&lt;p&gt;对于集群外部的微服务，可以直接采用 IP 直连 Servicer 端的 NodeIP，例如：&lt;/p&gt;</description></item><item><title>05 解决 K8s 落地难题的方法论提炼</title><link>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/006/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/006/</guid><description>&lt;div class="goclub-source-note"&gt;来源：&lt;a href="https://study.disign.me/document/Kubernetes%20%e5%ae%9e%e8%b7%b5%e5%85%a5%e9%97%a8%e6%8c%87%e5%8d%97/05%20%e8%a7%a3%e5%86%b3%20K8s%20%e8%90%bd%e5%9c%b0%e9%9a%be%e9%a2%98%e7%9a%84%e6%96%b9%e6%b3%95%e8%ae%ba%e6%8f%90%e7%82%bc.md" target="_blank" rel="noopener noreferrer"&gt;技术书栈原文&lt;/a&gt;。本页按授权迁移至 GoClub。&lt;/div&gt;
&lt;h1 id="05-解决-k8s-落地难题的方法论提炼"&gt;05 解决 K8s 落地难题的方法论提炼&lt;/h1&gt;
&lt;p&gt;做过技术落地的读者应该有所体会，任何技术经过一段时间的积累都会形成一套约定成熟的方法论，包括 Kubernetes 也不例外。在这些落地实践中比较突出的问题，有构建集群的问题、CI/CD 如何构建的问题、资源租户管理的问题，还有安全问题最为突出。本文为了让使用 Kubernetes 的后来者能少走弯路，通过总结前人经验的方式给大家做一次深度提炼。&lt;/p&gt;
&lt;h3 id="构建弹性集群策略"&gt;构建弹性集群策略&lt;/h3&gt;
&lt;p&gt;Kubernetes 集群架构是为单数据中心设计的容器管理集群系统。在企业落地的过程中，因为场景、业务、需求的变化，我们已经演化出不同的集群部署方案，大概分类为统一共享集群、独立环境多区集群、应用环境多区集群、专用小型集群：&lt;/p&gt;
&lt;p&gt;通过以上的对比分析，显然当前最佳的方式是，以环境为中心或以应用为中心部署多集群模式会获得最佳的收益。&lt;/p&gt;
&lt;h3 id="构建弹性-ci-cd-流程的策略"&gt;构建弹性 CI/CD 流程的策略&lt;/h3&gt;
&lt;p&gt;构建 CI/CD 流程的工具很多，但是我们无论使用何种工具，我们都会困 惑如何引入 Kubernetes 系统。通过实践得知，目前业界主要在采用 GitOps 工作流与 Kubernetes 配合使用可以获得很多的收益。这里我们可以参考业界知名的 CI/CD 工具 JenkinsX 架构图作为参考：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://go.botsarena.tech/pictures/study-disign/e067cf2e5847e56645dc.webp" alt="5-1-jenkinsx_arch"&gt;&lt;/p&gt;
&lt;p&gt;GitOps 配合 Jenkins 的 Pipeline 流水线，可以创建业务场景中需要的流水线，可以让业务应用根据需要在各种环境中切换并持续迭代。这种策略的好处在于充分利用 Git 的版本工作流控制了代码的集成质量，并且依靠流水线的特性又让持续的迭代能力可以得到充分体现。&lt;/p&gt;
&lt;h3 id="构建弹性多租户资源管理策略"&gt;构建弹性多租户资源管理策略&lt;/h3&gt;
&lt;p&gt;Kubernetes 内部的账号系统有 User、Group、ServiceAccount，当我们通过 RBAC 授权获得资源权限之后，其实这 3 个资源的权限能力是一样的。因为使用场景的不同，针对人的权限，我们一般会提供 User、Group 对象。当面对 Pod 之间，或者是外部系统服务对 Kubernetes API 的调用时，一般会采用 ServiceAccount。在原生 Kubernetes 环境下，我们可以通过 Namespace 把账号和资源进行绑定，以实现基于 API 级别的多租户。但是原生的多租户配置过于繁琐，一般我们会采用一些辅助的开源多租户工具来帮助我们，例如 Kiosk 多租户扩展套件：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://go.botsarena.tech/pictures/study-disign/1b2b1f62d6319b6a21a8.webp" alt="5-1-kiosk-workflow"&gt;&lt;/p&gt;
&lt;p&gt;通过 Kiosk 的设计流程图，我们可以清晰地定义每一个用户的权限，并配置合理的资源环境。让原来繁琐的配置过程简化成默认的租户模板，让多租户的配置过程变得更标准。&lt;/p&gt;</description></item><item><title>06 练习篇：K8s 核心实践知识掌握</title><link>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/007/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/007/</guid><description>&lt;div class="goclub-source-note"&gt;来源：&lt;a href="https://study.disign.me/document/Kubernetes%20%e5%ae%9e%e8%b7%b5%e5%85%a5%e9%97%a8%e6%8c%87%e5%8d%97/06%20%e7%bb%83%e4%b9%a0%e7%af%87%ef%bc%9aK8s%20%e6%a0%b8%e5%bf%83%e5%ae%9e%e8%b7%b5%e7%9f%a5%e8%af%86%e6%8e%8c%e6%8f%a1.md" target="_blank" rel="noopener noreferrer"&gt;技术书栈原文&lt;/a&gt;。本页按授权迁移至 GoClub。&lt;/div&gt;
&lt;h1 id="06-练习篇-k8s-核心实践知识掌握"&gt;06 练习篇：K8s 核心实践知识掌握&lt;/h1&gt;
&lt;p&gt;经过前面章节的介绍，我们把 Kubernetes 的核心组件、应用编排落地 Kubernetes、DevOps 场景落地 Kubernetes、微服务场景落地 Kubernetes 等主要的知识点给大家讲解了一遍。考虑到读者从拿来知识的角度看总觉得浅，不如通过一篇实战讲解来熟练掌握 Kubernetes 的主要技术能力。&lt;/p&gt;
&lt;p&gt;很多读者在安装高可用的 Kubernetes 的集群开始的时候就会遇到很多挫折，虽然网上可以参考的资料非常多，但真正容易上手并能完整提供连续性的项目还没有真正的官方推荐。虽然用户遇到碰壁后会很疼，但参考 CNCF 基金会提供的认证 Kubernetes 管理员的知识范围里面，安装集群的知识反而并不是重点，实际考察的是用 kubectl 这个命令行工具来把集群熟练用起来。这个知识误区放很多入门用户把精力放在了并不是最重要的知识点上。毕竟咱们业务场景中最重要的是解决知道如何使用，而不是探究它底层的技术实现。&lt;/p&gt;
&lt;p&gt;切记，我们需要把主要精力放在 80% 的如何使用 Kubernetes 的知识面上更能带来业绩，20% 的底层技术实现相关的知识涉及面广需要慢慢体会和学习，并且和前面的 Kubernetes 的使用方面的知识也是相得映彰，不熟悉很难理解底层技术实现能带来的收益。&lt;/p&gt;
&lt;h3 id="练习-1-使用命令行运行-pod-容器"&gt;练习-1：使用命令行运行 Pod 容器&lt;/h3&gt;
&lt;p&gt;使用命令行工具 Kubectl 执行如下命令：&lt;/p&gt;
&lt;p&gt;运行成功后，就要看看有没有运行起来，执行如下命令：&lt;/p&gt;
&lt;p&gt;为了更清楚地理解 Pod 运行的过程，我们还经常会运行如下命令来查看：&lt;/p&gt;
&lt;p&gt;如上面返回的结果中，Events 项的事件日志信息是我们快速定位 Pod 运行情况的最重要的信息，可以快速了解 Pod 生命周期的运行过程。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;作者建议：&lt;/strong&gt;kubectl 有很多命令参数很多，请务必参考 Kubernetes Docs 网站提供的 &lt;a href="https://kubernetes.io/docs/reference/kubectl/cheatsheet/" rel="nofollow noreferrer noopener"&gt;Kubectl Cheat Sheet&lt;/a&gt;，正好可以作为练习题来熟练你需要的命令行技能。&lt;/p&gt;
&lt;h3 id="练习-2-给组内每一位成员分配独立独有资源"&gt;练习-2：给组内每一位成员分配独立独有资源&lt;/h3&gt;
&lt;p&gt;配置安装完成 Kubernetes 集群后，系统会给我们提供一个 Kubeconfig 文件，里面默认配置了一个 cluster-admin 账号来全局管理所有集群资源，并且它是超级管理员权限。这个账号和集群直接是通过企业证书的认证方式来进入系统的，我们没办法像传统业务系统一样简单地更改密码来避免文件公用的安全分险，所以我们一般需要给每一位开发提供一个独立的账号和命名资源空间来隔离资源的使用。kubeconfig 文件一般配置如下：&lt;/p&gt;
&lt;p&gt;当我们要把一个用户加入配置，使用如下命令：&lt;/p&gt;
&lt;p&gt;如果要删除用户，可以运行：&lt;/p&gt;
&lt;p&gt;当然，我们还要在集群里面给这个用户账号提供 RBAC 的配置，那个过程相当复杂，其实并不适合在实际工作中采用。既然这个配置繁琐，我们有没有现成的工具来帮助我们实现多用户的配置呢？答案是有的，它就是 Kiosk 多租户管理套件：&lt;/p&gt;</description></item><item><title>07 容器引擎 containerd 落地实践</title><link>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/008/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/008/</guid><description>&lt;div class="goclub-source-note"&gt;来源：&lt;a href="https://study.disign.me/document/Kubernetes%20%e5%ae%9e%e8%b7%b5%e5%85%a5%e9%97%a8%e6%8c%87%e5%8d%97/07%20%e5%ae%b9%e5%99%a8%e5%bc%95%e6%93%8e%20containerd%20%e8%90%bd%e5%9c%b0%e5%ae%9e%e8%b7%b5.md" target="_blank" rel="noopener noreferrer"&gt;技术书栈原文&lt;/a&gt;。本页按授权迁移至 GoClub。&lt;/div&gt;
&lt;h1 id="07-容器引擎-containerd-落地实践"&gt;07 容器引擎 containerd 落地实践&lt;/h1&gt;
&lt;p&gt;Docker 公司从 2013 年发布容器引擎 Docker 后，就被全球开发者使用并不断改进它的功能。随着容器标准的建立，Docker 引擎架构也从单体走向微服务结构，剥离出 dontainerd 引擎。它在整个容器技术架构中的位置如下：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://go.botsarena.tech/pictures/study-disign/94286123e2b0be68d06c.webp" alt="containerd-arch"&gt;&lt;/p&gt;
&lt;p&gt;图 6-1 containerd 架构图，版权源自 &lt;a href="https://containerd.io/" rel="nofollow noreferrer noopener"&gt;https://containerd.io/&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="containerd-使用初体验"&gt;containerd 使用初体验&lt;/h3&gt;
&lt;p&gt;从官方仓库可以下载最新的 containerd 可执行文件，因为依赖 runc，所以需要一并下载才能正常使用：&lt;/p&gt;
&lt;p&gt;containerd 提供了默认的配置文件 config.toml，默认放在 /etc/containerd/config.toml：&lt;/p&gt;
&lt;p&gt;containerd 服务一般采用后台守护进程方式运行，在 Linux 中使用 systemd 运行：&lt;/p&gt;
&lt;p&gt;至此，containerd 的使用流程就体验完成了。&lt;/p&gt;
&lt;h3 id="通过客户端深入了解-containerd"&gt;通过客户端深入了解 containerd&lt;/h3&gt;
&lt;p&gt;containerd 启动后，我们需要使用客户端命令行工具来了解下容器运行的情况。这个时候，我们手上有 2 个工具可以使用。一个是 crictl 这个是 Kubernetes 社区提供的操作容器接口标准的客户端工具，另外一个是 ctr 这是 containerd 自带的客户端工具，ctr 是测试使用的工具，在日常工作中推荐使用 crictl 工具来管理容器。&lt;/p&gt;
&lt;p&gt;ctr 工具运行如下：&lt;/p&gt;
&lt;p&gt;crictl 运行命令如下：&lt;/p&gt;
&lt;p&gt;从 2 个命令参数对比参照可以得知，crictl 的功能是比 ctr 要丰富很多的。为了日常使用方便，这里我把 crictl 和 Docker 命令做一个对比，方便大家参照使用：&lt;/p&gt;</description></item><item><title>08 K8s 集群安装工具 kubeadm 的落地实践</title><link>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/009/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/009/</guid><description>&lt;div class="goclub-source-note"&gt;来源：&lt;a href="https://study.disign.me/document/Kubernetes%20%e5%ae%9e%e8%b7%b5%e5%85%a5%e9%97%a8%e6%8c%87%e5%8d%97/08%20K8s%20%e9%9b%86%e7%be%a4%e5%ae%89%e8%a3%85%e5%b7%a5%e5%85%b7%20kubeadm%20%e7%9a%84%e8%90%bd%e5%9c%b0%e5%ae%9e%e8%b7%b5.md" target="_blank" rel="noopener noreferrer"&gt;技术书栈原文&lt;/a&gt;。本页按授权迁移至 GoClub。&lt;/div&gt;
&lt;h1 id="08-k8s-集群安装工具-kubeadm-的落地实践"&gt;08 K8s 集群安装工具 kubeadm 的落地实践&lt;/h1&gt;
&lt;p&gt;kubeadm 是 Kubernetes 项目官方维护的支持一键部署安装 Kubernetes 集群的命令行工具。使用过它的读者肯定对它仅仅两步操作就能轻松组建集群的方式印象深刻：kubeadm init 以及 kubeadm join 这两个命令可以快速创建 Kubernetes 集群。当然这种便捷的操作并不能在生产环境中直接使用，我们要考虑组件的高可用布局，并且还需要考虑可持续的维护性。这些更实际的业务需求迫切需要我们重新梳理一下 kubeadm 在业界的使用情况，通过借鉴参考前人的成功经验可以帮助我们正确的使用好 kubeadm。&lt;/p&gt;
&lt;p&gt;首先，经典的 Kubernetes 高可用集群的架构图在社区官方文档中定义如下：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://go.botsarena.tech/pictures/study-disign/45f62d1f089d33a6b376.webp" alt="7-1-kubeadm-k8s-ha-arch"&gt;&lt;/p&gt;
&lt;p&gt;从上图架构中可知，Kubernetes 集群的控制面使用 3 台节点把控制组件堆叠起来，形成冗余的高可用系统。其中 etcd 系统作为集群状态数据存储的中心，采用 Raft 一致性算法保证了业务数据读写的一致性。细心的读者肯定会发现，控制面节点中 apiserver 是和当前主机 etcd 组件进行交互的，这种堆叠方式相当于把流量进行了分流，在集群规模固定的情况下可以有效的保证组件的读写性能。&lt;/p&gt;
&lt;p&gt;因为 etcd 键值集群存储着整个集群的状态数据，是非常关键的系统组件。官方还提供了外置型 etcd 集群的高可用部署架构：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://go.botsarena.tech/pictures/study-disign/f4a4b124bc40687f3271.webp" alt="7-2-ha-kube-etcd-external-arch"&gt;&lt;/p&gt;
&lt;p&gt;kubeadm 同时支持以上两种技术架构的高可用部署，两种架构对比起来，最明显的区别在于外置型 etcd 集群模式需要的 etcd 数据面机器节点数量不需要和控制面机器节点数量一致，可以按照集群规模提供 3 个或者 5 个 etcd 节点来保证业务高可用能力。社区的开发兴趣小组 k8s-sig-cluster-lifecycle 还发布了 etcdadm 开源工具来自动化部署外置 etcd 集群。&lt;/p&gt;
&lt;h3 id="安装前的基准检查工作"&gt;安装前的基准检查工作&lt;/h3&gt;
&lt;p&gt;集群主机首要需要检查的就是硬件信息的唯一性，防止集群信息的冲突。确保每个节点上 MAC 地址和 product_uuid 的唯一性。检查办法如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;您可以使用命令 ip link 或 ifconfig -a 来获取网络接口的 MAC 地址&lt;/li&gt;
&lt;li&gt;可以使用 sudo cat /sys/class/dmi/id/product_uuid 命令对 product_uuid 校验&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;检查硬件信息的唯一性，主要是为了应对虚拟机模板创建后产生的虚拟机环境重复导致，通过检查就可以规避。&lt;/p&gt;</description></item><item><title>09 南北向流量组件 IPVS 的落地实践</title><link>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/010/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/010/</guid><description>&lt;div class="goclub-source-note"&gt;来源：&lt;a href="https://study.disign.me/document/Kubernetes%20%e5%ae%9e%e8%b7%b5%e5%85%a5%e9%97%a8%e6%8c%87%e5%8d%97/09%20%e5%8d%97%e5%8c%97%e5%90%91%e6%b5%81%e9%87%8f%e7%bb%84%e4%bb%b6%20IPVS%20%e7%9a%84%e8%90%bd%e5%9c%b0%e5%ae%9e%e8%b7%b5.md" target="_blank" rel="noopener noreferrer"&gt;技术书栈原文&lt;/a&gt;。本页按授权迁移至 GoClub。&lt;/div&gt;
&lt;h1 id="09-南北向流量组件-ipvs-的落地实践"&gt;09 南北向流量组件 IPVS 的落地实践&lt;/h1&gt;
&lt;p&gt;我们知道 Kubernetes 工作节点的流量管理都是由 kube-proxy 来管理的。kube-proxy 利用了 iptables 的网络流量转换能力，在整个集群的数据层面创建了一层集群虚拟网络，也就是大家在 Service 对象中会看到的术语 ClusterIP，即集群网络 IP。既然 iptables 已经很完美的支持流量的负载均衡，并能实现南北向流量的反向代理功能，为什么我们还要让用户使用另外一个系统组件 IPVS 来代替它呢？&lt;/p&gt;
&lt;p&gt;主要原因还是 iptables 能承载的 Service 对象规模有限，超过 1000 个以上就开始出现性能瓶颈了。目前 Kubernetes 默认推荐代理就是 IPVS 模式，这个推荐方案迫使我们需要开始了解 IPVS 的机制，熟悉它的应用范围和对比 iptables 的优缺点，让我们能有更多的精力放在应用开发上。&lt;/p&gt;
&lt;h3 id="一次大规模的-service-性能评测引入的-ipvs"&gt;一次大规模的 Service 性能评测引入的 IPVS&lt;/h3&gt;
&lt;p&gt;iptables 一直是 Kubernetes 集群依赖的系统组件，它同时也是 Liinux 的内核模块，一般实践过程中我们都不会感知到它的性能问题。社区中有华为的开发者在 KuberCon 2018 中引入了一个问题：&lt;/p&gt;
&lt;p&gt;通过测试数据发现，答案是否定的。在 Pod 实例规模达到上万个实例的时候，iptables 就开始对系统性能产生影响了。我们需要知道哪些原因导致 iptables 不能稳定工作。&lt;/p&gt;
&lt;p&gt;首先，IPVS 模式 和 iptables 模式同样基于 Netfilter，在生成负载均衡规则的时候，IPVS 是基于哈希表转发流量，iptables 则采用遍历一条一条规则来转发，因为 iptables 匹配规则需要从上到下一条一条规则的匹配，肯定对 CPU 消耗增大并且转发效率随着规则规模的扩大而降低。反观 IPVS 的哈希查表方案，在生成 Service 负载规则后，查表范围有限，所以转发性能上直接秒杀了 iptables 模式。&lt;/p&gt;</description></item><item><title>10 东西向流量组件 Calico 的落地实践</title><link>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/011/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/011/</guid><description>&lt;div class="goclub-source-note"&gt;来源：&lt;a href="https://study.disign.me/document/Kubernetes%20%e5%ae%9e%e8%b7%b5%e5%85%a5%e9%97%a8%e6%8c%87%e5%8d%97/10%20%e4%b8%9c%e8%a5%bf%e5%90%91%e6%b5%81%e9%87%8f%e7%bb%84%e4%bb%b6%20Calico%20%e7%9a%84%e8%90%bd%e5%9c%b0%e5%ae%9e%e8%b7%b5.md" target="_blank" rel="noopener noreferrer"&gt;技术书栈原文&lt;/a&gt;。本页按授权迁移至 GoClub。&lt;/div&gt;
&lt;h1 id="10-东西向流量组件-calico-的落地实践"&gt;10 东西向流量组件 Calico 的落地实践&lt;/h1&gt;
&lt;p&gt;Kubernetes 网络并没有原生的方案，它从一开始就给我们送来了一个选择题。到底选哪种网络方案才是最佳的方案呢？网络问题一直让社区用户很困惑，以至于在早期，不同场景下的方案如雨后春笋般涌现出来。其中比较优秀的就是今天选择给大家介绍的网络组件 Calico。这里我们要强调的是，Calico 方案并不是唯一方案，我们在社区仍然能看到很多优秀的方案比如 Cilium、OvS、Contiv、Flannel 等，至于选择它来讲解东西向流量的组件落地，实在是当前国内业界大部分的方案都是以 Cailico 实践为主，介绍它可以起到一个案例示范的作用。&lt;/p&gt;
&lt;h3 id="容器网络路由的原理"&gt;容器网络路由的原理&lt;/h3&gt;
&lt;p&gt;众所周知容器原生网络模型基于单机的 veth 虚拟网桥实现，无法跨主机互联互通。如果想让容器跨主机互联互通，需要支持以下 3 点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;网络控制面需要保证容器 IP 的唯一性&lt;/li&gt;
&lt;li&gt;两个容器需要放在一个数据平面&lt;/li&gt;
&lt;li&gt;需要工具来自动解决容器网络地址转换
这里我们通过一个原生网络路由的例子来帮助大家理解容器网络互联互通的基本原理：&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://go.botsarena.tech/pictures/study-disign/7e6b44ac991dd900109e.webp" alt="9-1-hosts-container-network"&gt;&lt;/p&gt;
&lt;p&gt;图：Docker 19.03.12 版本直接路由模式图例&lt;/p&gt;
&lt;h4 id="分别对主机-1-和主机-2-上的-docker0-进行配置-重启-docker-服务生效"&gt;&lt;strong&gt;分别对主机 1 和主机 2 上的 docker0 进行配置，重启 docker 服务生效&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;编辑主机 1 上的 /etc/docker/daemon.json 文件，添加内容：“bip” : “ip/netmask”。&lt;/p&gt;
&lt;p&gt;编辑主机 2 上的 /etc/docker/daemon.json 文件，添加内容：“bip” : “ip/netmask”。&lt;/p&gt;
&lt;p&gt;主机 1 和主机 2 上均执行如下命令，重启 Docker 服务以使修改后的 docker0 网段生效。&lt;/p&gt;
&lt;h4 id="添加路由规则"&gt;&lt;strong&gt;添加路由规则&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;主机 1 上添加路由规则如下：&lt;/p&gt;
&lt;p&gt;主机 2 上添加路由规则如下：&lt;/p&gt;
&lt;p&gt;理论上配置完路由后应该从主机 1 可以连接到主机 2 的 docker0，实际场景下因为交换机会检查 docker0 的 mac 地址，并把这个非法的地址下的数据包直接 DROP 掉，让跨主机的容器无法想通，但这个并不妨碍我们理解原理。Calico 网络路由原理和以上示范静态路由原理是一致的，那么它是如何实现连通的呢？&lt;/p&gt;</description></item><item><title>11 服务发现 DNS 的落地实践</title><link>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/012/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/012/</guid><description>&lt;div class="goclub-source-note"&gt;来源：&lt;a href="https://study.disign.me/document/Kubernetes%20%e5%ae%9e%e8%b7%b5%e5%85%a5%e9%97%a8%e6%8c%87%e5%8d%97/11%20%e6%9c%8d%e5%8a%a1%e5%8f%91%e7%8e%b0%20DNS%20%e7%9a%84%e8%90%bd%e5%9c%b0%e5%ae%9e%e8%b7%b5.md" target="_blank" rel="noopener noreferrer"&gt;技术书栈原文&lt;/a&gt;。本页按授权迁移至 GoClub。&lt;/div&gt;
&lt;h1 id="11-服务发现-dns-的落地实践"&gt;11 服务发现 DNS 的落地实践&lt;/h1&gt;
&lt;p&gt;DNS 服务是 Kubernetes 内置的服务发现组件，它方便容器服务可以通过发布的唯一 App 名字找到对方的端口服务，再也不需要维护服务对应的 IP 关系。这个对传统企业内部的运维习惯也是有一些变革的。一般传统企业内部都会维护一套 CMDB 系统，专门来维护服务器和 IP 地址的对应关系，方便规划管理好应用服务集群。当落地 K8s 集群之后，因为应用容器的 IP 生命周期短暂，通过 App 名字来识别服务其实对运维和开发都会更方便。所以本篇就是结合实际的需求场景给大家详细介绍 DNS 的使用实践。&lt;/p&gt;
&lt;h3 id="coredns-介绍"&gt;CoreDNS 介绍&lt;/h3&gt;
&lt;p&gt;Kubernetes 早期的 DNS 组件叫 KubeDNS。CNCF 社区后来引入了更加成熟的开源项目 CoreDNS 替换了 KubeDNS。所以我们现在提到 KubeDNS，其实默认指代的是 CoreDNS 项目。在 Kubernetes 中部署 CoreDNS 作为集群内的 DNS 服务有很多种方式，例如可以使用官方 Helm Chart 库中的 Helm Chart 部署，具体可查看 &lt;a href="https://github.com/helm/charts/tree/master/stable/coredns" rel="nofollow noreferrer noopener"&gt;CoreDNS Helm Chart&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;查看 coredns 的 Pod，确认所有 Pod 都处于 Running 状态：&lt;/p&gt;
&lt;p&gt;测试一下 DNS 功能是否好用：&lt;/p&gt;
&lt;h3 id="服务发现规则"&gt;服务发现规则&lt;/h3&gt;
&lt;p&gt;DNS 支持的服务发现是支持 Service 和 Pod 的。它的规则如下。&lt;/p&gt;</description></item><item><title>12 练习篇：K8s 集群配置测验</title><link>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/013/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/013/</guid><description>&lt;div class="goclub-source-note"&gt;来源：&lt;a href="https://study.disign.me/document/Kubernetes%20%e5%ae%9e%e8%b7%b5%e5%85%a5%e9%97%a8%e6%8c%87%e5%8d%97/12%20%e7%bb%83%e4%b9%a0%e7%af%87%ef%bc%9aK8s%20%e9%9b%86%e7%be%a4%e9%85%8d%e7%bd%ae%e6%b5%8b%e9%aa%8c.md" target="_blank" rel="noopener noreferrer"&gt;技术书栈原文&lt;/a&gt;。本页按授权迁移至 GoClub。&lt;/div&gt;
&lt;h1 id="12-练习篇-k8s-集群配置测验"&gt;12 练习篇：K8s 集群配置测验&lt;/h1&gt;
&lt;p&gt;第二部分的内容围绕 Kubernetes 核心组件的安装配置一一给大家拆解了一遍，当前集群组件最主流的配置就是这些：containerd、kubeadm、IPVS、Calico、kube-dns。读者通过官方文档就可以独立配置一套集群，只是笔者发现，因为集群配置的过度复杂，能获得的环境也是千差万别，很难得到统一的认知。本篇测验的目的就是带着大家一起校验一遍我们学习到的经验，一起搭建一套集群的全过程，以此来校验我们掌握的集群知识。&lt;/p&gt;
&lt;h3 id="环境"&gt;环境&lt;/h3&gt;
&lt;p&gt;从第一天接触容器技术之后，我们想解决的问题就是环境依赖问题。因为 Docker 是让环境包裹这应用一起制作成镜像分发的。等我们配置 Kubernetes 集群的时候，我们操作的最小单元是 Pod，你可以理解为是一个容器组，这个容器组并不是简单的把一组容器放一起就完事了。它的设计巧妙之处在于以 pause 为核心的基础容器把相关应用的所有环境依赖都掌握在自己的运行时里面。其它相关业务容器只是加入到这个运行时里面，这些业务容器出现问题并不会破坏环境。这是 Kubernetes 构建业务集群的核心设计，非常巧妙的解决了应用服务的可用性问题。&lt;/p&gt;
&lt;p&gt;现在我们要选择操作系统的版本了。你会发现并没有任何官方文档说过，哪一个版本是指定的。其实官方并没有这样的约定。因为容器的目的就是解决环境的依赖，但是这么多年的演进，说的更清楚一点，我们仍然有一个核心依赖就是 Kernel 依赖搞不定。Kernel 的特性会决定容器的特性，我们一般在选择上会参考 Docker 的版本来定，主流的有 18.09、19.03 等。你发现没有，你并不能保证在特定的环境下这些 Docker 版本没有问题，这就是我们在配置生产环境中出现问题自己埋下的坑。&lt;/p&gt;
&lt;p&gt;如果你是企业内部使用，最好的办法是建立基准线，明确版本号，在大量实践的基础上投入人力来维护这个版本的稳定性。因为容器技术发展很快，现在 Kubernetes 已经和 Docker 越来越规避，都在使用 containerd 来支持底层容器运行时的管理，作为用户我们是无法回避这个。这里又突显一个问题，因为组件的变革，我到底应该选择哪个版本呢，它们稳定吗？因为 Kubernetes 是开源社区推动的软件，我们一定要遵循开源的方式来使用这些软件才能得到正确的经验。&lt;/p&gt;
&lt;p&gt;我总结出来的经验如下，方便大家参考：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. x86-64 仍然是当前对容器最好的系统架构体系&lt;/strong&gt;，目前主流的系统聚集在 redhat/centos 7.x 系列，Ubuntu 16.04 系列。对于内核红帽系主要在 3.10 以上，Ubuntu 能到 4.4 以上。有些用户会通过开源 kernel 仓库把红帽系的 Kernel 升级到 4.4，也比较常见。升级内核的代价就是引入很多未知的模块，让系统变得不稳定。ARM 系统架构会对整个 Kubernetes 组件的文件格式产生兼容性要求，在选择适配的时候，一定要注意有没有准备好 Kubernetes 相应的组件。总结下来，主流的操作系统主要是红帽的 7.x 系列和 Ubuntu LTS 系列 16.04。升级大版本操作系统对 Kubernetes 来说，需要做很多适配工作，目前开源社区是不太可能帮用户做的。一定注意。&lt;/p&gt;</description></item><item><title>13 理解对方暴露服务的对象 Ingress 和 Service</title><link>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/014/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/014/</guid><description>&lt;div class="goclub-source-note"&gt;来源：&lt;a href="https://study.disign.me/document/Kubernetes%20%e5%ae%9e%e8%b7%b5%e5%85%a5%e9%97%a8%e6%8c%87%e5%8d%97/13%20%e7%90%86%e8%a7%a3%e5%af%b9%e6%96%b9%e6%9a%b4%e9%9c%b2%e6%9c%8d%e5%8a%a1%e7%9a%84%e5%af%b9%e8%b1%a1%20Ingress%20%e5%92%8c%20Service.md" target="_blank" rel="noopener noreferrer"&gt;技术书栈原文&lt;/a&gt;。本页按授权迁移至 GoClub。&lt;/div&gt;
&lt;h1 id="13-理解对方暴露服务的对象-ingress-和-service"&gt;13 理解对方暴露服务的对象 Ingress 和 Service&lt;/h1&gt;
&lt;p&gt;Kubernetes 中的服务（Service）可以理解为对外暴露服务的最小单元对象，这个和 Pod 对象还是有不同的。例如用户通过发布服务对象 Deployment 发布应用，当在容器集群中启动后，ReplicaSet 副本对象会帮我们维持 Pod 实例的副本数。Pod 使用的容器网络默认会选择构建在主机网络上的覆盖网络（Overlay），默认外网是无法直接访问这些 Pod 实例服务的。为了能有效对接容器网络，Kubernetes 创建了另外一层虚拟网络 ClusterIP，即 Service 对象。从实现上来看，它借助 iptables 调用底层 netfilter 实现了虚拟 IP，然后通过相应的规则链把南北向流量准确无误的接入后端 Pod 实例。随着需求的衍生，后来扩展的 Ingress 对象则是借助第三方代理服务如 HAProxy、Nginx 等 7 层引流工具打通外部流量和内部 Service 对象的通路。Ingress 对象的目的就是为了解决容器集群中需要高性能应用网关接入的需求。&lt;/p&gt;
&lt;h3 id="service-的思考"&gt;Service 的思考&lt;/h3&gt;
&lt;p&gt;Service 定义的网络基于 iptables 编排 netfilter 规则来支持虚拟 IP。Service 对象被设计为反向代理模式，支持南北向流量的负载均衡，通过 DNAT 把流量转到后端的具体业务的 Pod 中。为了劫持接入流量和 NAT 转换，Kubernetes 创建了两条自定义链规则 PREROUTING 和 OUTPUT。如：&lt;/p&gt;
&lt;p&gt;PREROUTING 主要处理从外部引入的流量和来自 Pod 容器网络的引入流量，OUTPUT 主要处理流出到外部网络的流量和流出到 Pod 容器网络的流量。&lt;/p&gt;
&lt;p&gt;因为发布的服务肯定需要对外暴露服务，所以 Kubernetes 创建了一个自定义规则链 KUBE-SERVICE 来支持集群级别的服务发现，即 ClusterIP 和 LoadBalancer 类型，最后通过另外一条自定义规则链 KUBE-NODEPORTS 来对外暴露服务，案例如下：&lt;/p&gt;</description></item><item><title>14 应用网关 OpenResty 对接 K8s 实践</title><link>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/015/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/015/</guid><description>&lt;div class="goclub-source-note"&gt;来源：&lt;a href="https://study.disign.me/document/Kubernetes%20%e5%ae%9e%e8%b7%b5%e5%85%a5%e9%97%a8%e6%8c%87%e5%8d%97/14%20%e5%ba%94%e7%94%a8%e7%bd%91%e5%85%b3%20OpenResty%20%e5%af%b9%e6%8e%a5%20K8s%20%e5%ae%9e%e8%b7%b5.md" target="_blank" rel="noopener noreferrer"&gt;技术书栈原文&lt;/a&gt;。本页按授权迁移至 GoClub。&lt;/div&gt;
&lt;h1 id="14-应用网关-openresty-对接-k8s-实践"&gt;14 应用网关 OpenResty 对接 K8s 实践&lt;/h1&gt;
&lt;p&gt;当前云原生应用网关有很多选择，例如：Nginx/OpenResty、Traefik、Envoy 等，从部署流行度来看 OpenResty 毋容置疑是最流行的反向代理网关。本篇探讨的就是 Kubernetes 为了统一对外的入口网关而引入的 Ingress 对象是如何利用 OpenResty 来优化入口网关的能力的。&lt;/p&gt;
&lt;h3 id="为什么需要-openresty"&gt;为什么需要 OpenResty&lt;/h3&gt;
&lt;p&gt;原生 Kubernetes Service 提供对外暴露服务的能力，通过唯一的 ClusterIP 接入 Pod 业务负载容器组对外提供服务名（附注：服务发现使用，采用内部 kube-dns 解析服务名称）并提供流量的软负载均衡。缺点是 Service 的 ClusterIP 地址只能在集群内部被访问，如果需要对集群外部用户提供此 Service 的访问能力，Kubernetes 需要通过另外两种方式来实现此类需求，一种是 &lt;strong&gt;NodePort&lt;/strong&gt;，另一种是 &lt;strong&gt;LoadBalancer&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://go.botsarena.tech/pictures/study-disign/933b62f4e1245857e5e5.webp" alt="nodeport"&gt;&lt;/p&gt;
&lt;p&gt;当容器应用采用 NodePort 方式来暴露 Service 并让外部用户访问时会有如下困扰：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;外部访问服务时需要带 NodePort&lt;/li&gt;
&lt;li&gt;每次部署服务后，NodePort 端口会改变&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://go.botsarena.tech/pictures/study-disign/dd4f9b3ddac35499e204.webp" alt="loadbalancer"&gt;&lt;/p&gt;
&lt;p&gt;当容器应用采用 LoadBalancer 方式时，主要应用场景还是对接云厂商提供负载均衡上，当然云厂商都提供对应的负载均衡插件方便 Kubernetes 一键集成。&lt;/p&gt;
&lt;p&gt;对于大部分场景下，我们仍然需要采用私有的入口应用网关来对外提供服务暴露。这个时候通过暴露七层 Web 端口把外部流量挡在外面访问。同时对于用户来讲屏蔽了 NodePort 的存在，频繁部署应用的时候用户是不需要关心 NodePort 端口占用的。&lt;/p&gt;
&lt;p&gt;在早期 Kubernetes 引入的 ingress controller 的方案是采用的 Nginx 作为引擎的，它在使用中有一些比较突出的问题：&lt;/p&gt;</description></item><item><title>15 Service 层引流技术实践</title><link>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/016/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/016/</guid><description>&lt;div class="goclub-source-note"&gt;来源：&lt;a href="https://study.disign.me/document/Kubernetes%20%e5%ae%9e%e8%b7%b5%e5%85%a5%e9%97%a8%e6%8c%87%e5%8d%97/15%20Service%20%e5%b1%82%e5%bc%95%e6%b5%81%e6%8a%80%e6%9c%af%e5%ae%9e%e8%b7%b5.md" target="_blank" rel="noopener noreferrer"&gt;技术书栈原文&lt;/a&gt;。本页按授权迁移至 GoClub。&lt;/div&gt;
&lt;h1 id="15-service-层引流技术实践"&gt;15 Service 层引流技术实践&lt;/h1&gt;
&lt;p&gt;Kubernetes 引入的 Service 层给集群带来了两样特性：第一是 ClusterIP，通过集群 DNS 分配的服务别名，服务可以获得一个稳定的服务名字，例如：foo.bar.svc.cluster.local。第二是反向代理，通过 iptables/IPVS/eBPF 等各种网络数据转换技术把流量负载到上游的 Pod 容器组中。到这里，其实 Service 层的基本技术已经给大家介绍了，但是从实践的角度再次分析，发现其中还有很多最新的进展需要给大家讲解以下，并从中我们能总结出技术发展过程中如何优化的策略总结。&lt;/p&gt;
&lt;h3 id="ingress-的误解"&gt;Ingress 的误解？&lt;/h3&gt;
&lt;p&gt;在社区文档中介绍的 Ingress 资源，我们知道它是应对 HTTP(S) Web 流量引入到集群的场景创建的资源对象。一般介绍中我们会说它不支持 L4 层的引流。如果想支持其它网络协议，最好用 Service 的另外两种形式 ServiceType=NodePort 或者 ServiceType=LoadBalancer 模式来支持。&lt;/p&gt;
&lt;p&gt;首先，Ingress 资源对象能不能支持 L4 层，并不是完全由这个资源对象能把控，真正承载引流能力的是独立部署的 Ingress-Nginx 实例，也就是 Nginx 才能决定。我们知道 Nginx 本身就是支持 L4 层的。所以，Ingress 通过变相增加参数的方式可以提供支持：&lt;/p&gt;
&lt;p&gt;同理，UDP 协议也可以支持，在此不再赘述。从实践角度来讲，这种依赖 Nginx 的在其它 Ingress 控制器中会有不同的支持，你需要详细查阅开发文档来确认。&lt;/p&gt;
&lt;p&gt;另外，Ingress-Nginx 在介绍中都是直接通过 Service 来把流量负载均衡到 Pod 容器组，连很多架构图都是这么画的：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://go.botsarena.tech/pictures/study-disign/fe7de11760ab506ef4cd.webp" alt="img"&gt;&lt;/p&gt;
&lt;p&gt;在工程代码实现上默认 Ingress-Nginx 是不经过 Service，也不经过 kube-proxy 访问 Pod，而且通过 Service 找到对应的 Endpoint，然后直接把请求分发到对应的 Pod IP 和端口。这样做的目的是规避了 Service 这层的 DNAT 转换，缺点就是没有了反向代理能力，接入流量服务也不是高可用的 SLA。为了能把 Service 这层反向代理能力重新启用，可以加入注解参数：&lt;/p&gt;</description></item><item><title>16 Cilium 容器网络的落地实践</title><link>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/017/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/017/</guid><description>&lt;div class="goclub-source-note"&gt;来源：&lt;a href="https://study.disign.me/document/Kubernetes%20%e5%ae%9e%e8%b7%b5%e5%85%a5%e9%97%a8%e6%8c%87%e5%8d%97/16%20Cilium%20%e5%ae%b9%e5%99%a8%e7%bd%91%e7%bb%9c%e7%9a%84%e8%90%bd%e5%9c%b0%e5%ae%9e%e8%b7%b5.md" target="_blank" rel="noopener noreferrer"&gt;技术书栈原文&lt;/a&gt;。本页按授权迁移至 GoClub。&lt;/div&gt;
&lt;h1 id="16-cilium-容器网络的落地实践"&gt;16 Cilium 容器网络的落地实践&lt;/h1&gt;
&lt;p&gt;随着越来越多的企业采用 Kubernetes，围绕多云、安全、可见性和可扩展性等新要求，可编程数据平面的需求用例范围越来越广。此外，服务网格和无服务器等新技术对 Kubernetes 底层提出了更多的定制化要求。这些新需求都有一些共同点：它们需要一个更可编程的数据平面，能够在不牺牲性能的情况下执行 Kubernetes 感知的网络数据操作。&lt;/p&gt;
&lt;p&gt;Cilium 项目通过引入扩展的伯克利数据包过滤器（eBPF）技术，在 Linux 内核内向网络栈暴露了可编程的钩子。使得网格数据包不需要在用户和内核空间之间来回切换就可以通过上下文快速进行数据交换操作。这是一种新型的网络范式，它也是 Cilium 容器网络项目的核心思想。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://go.botsarena.tech/pictures/study-disign/1e04a4ddadd348945beb.webp" alt="14-1-cilium-cni"&gt;&lt;/p&gt;
&lt;h3 id="为什么需要落地-cilium-容器网络"&gt;为什么需要落地 Cilium 容器网络？&lt;/h3&gt;
&lt;p&gt;Kubernetes 的容器网络方案发展至今，一直是百家争鸣，各有特色。之前因为 CNI 网络方案不成熟，大家用起来都是战战兢兢，时刻提防容器网络给业务带来不可接受的效果，随即就把容器网络替换成主机网络。随着时间的磨砺，当前主流的容器网络方案如 Calico 等已经经历成百上千次生产环境的应用考验，大部分场景下都可以达到用户可以接受的网络性能指标。因为成功经验开始增多，用户也开始大规模启用容器网络的上线了。随着业务流量的引入越来越大，用户对 Kubernetes 网络的认知也趋于一致。大致分为两大类，一类是 Cluster IP，是一层反向代理的虚拟网络；一类是 Pod IP，是容器间交互数据的网络数据平面。对于反向代理虚拟网络的技术实现，早期 kube-proxy 是采用 iptables，后来引入 IPVS 也解决了大规模容器集群的网络编排的性能问题。这样的实现结构你从顶端俯瞰会明显感知到 Kubernetes 网络数据平台非常零散，并没有实现一套体系的网络策略编排和隔离。显然，这样的技术结构也无法引入数据可视化能力。这也是 Istio 服务网格引入后，通过增加 envoy sidecar 来实现网络流量可视化带来了机会。但是这种附加的边界网关毕竟又对流量增加了一层反向代理，让网络性能更慢了。Cilium 原生通过 eBPF 编排网络数据，让可视化更简单。&lt;/p&gt;
&lt;p&gt;Cilium 还有一个强项就是通过 eBPF 是可以自定义隔离策略的，这样就可以在非信任的主机环境编排更多的容器网络隔离成多租户环境，让用户不在担心数据的泄露，可以更专注在数据业务的连通性上。因为 eBPF 的可编程性，我们还能依据业务需求，增加各种定制化插件，让数据平台可以更加灵活安全。&lt;/p&gt;
&lt;h3 id="cilium-cni-实现"&gt;Cilium CNI 实现&lt;/h3&gt;
&lt;p&gt;Cilium Agent、Cilium CLI Client 和 CNI Plugin 运行在集群中的每一个节点上（以守护进程的形式部署）。Cilium CNI 插件执行所有与网络管道有关的任务，如创建链接设备（veth 对），为容器分配 IP，配置 IP 地址，路由表，sysctl 参数等。Cilium Agent 编译 BPF 程序，并使内核在网络栈的关键点上运行这些程序。&lt;/p&gt;</description></item><item><title>17 应用流量的优雅无损切换实践</title><link>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/018/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/018/</guid><description>&lt;div class="goclub-source-note"&gt;来源：&lt;a href="https://study.disign.me/document/Kubernetes%20%e5%ae%9e%e8%b7%b5%e5%85%a5%e9%97%a8%e6%8c%87%e5%8d%97/17%20%e5%ba%94%e7%94%a8%e6%b5%81%e9%87%8f%e7%9a%84%e4%bc%98%e9%9b%85%e6%97%a0%e6%8d%9f%e5%88%87%e6%8d%a2%e5%ae%9e%e8%b7%b5.md" target="_blank" rel="noopener noreferrer"&gt;技术书栈原文&lt;/a&gt;。本页按授权迁移至 GoClub。&lt;/div&gt;
&lt;h1 id="17-应用流量的优雅无损切换实践"&gt;17 应用流量的优雅无损切换实践&lt;/h1&gt;
&lt;p&gt;Kubernetes 的部署基本上都是默认滚动式的，并且保证零宕机，但是它是有一个前置条件的。正是这个前置条件让零宕机部署表现为一个恼人的问题。为了实现 Kubernetes 真正的零宕机部署，不中断或不丢失任何一个运行中的请求，我们需要深入应用部署的运行细节并找到根源进行深入的根源分析。本篇的实践内容继承之前的知识体系，将更深入的总结零宕机部署方法。&lt;/p&gt;
&lt;h3 id="刨根问底"&gt;刨根问底&lt;/h3&gt;
&lt;h4 id="滚动更新"&gt;&lt;strong&gt;滚动更新&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;我们首先来谈谈滚动更新的问题。根据默认情况，Kubernetes 部署会以滚动更新策略推动 Pod 容器版本更新。该策略的思想就是在执行更新的过程中，至少要保证部分老实例在此时是启动并运行的，这样就可以防止应用程序出现服务停止的情况了。在这个策略的执行过程中，新版的 Pod 启动成功并已经可以引流时才会关闭旧 Pod。&lt;/p&gt;
&lt;p&gt;Kubernetes 在更新过程中如何兼顾多个副本的具体运行方式提供了策略参数。根据我们配置的工作负载和可用的计算资源，滚动更新策略可以细调超额运行的 Pods（maxSurge）和多少不可用的 Pods （maxUnavailable）。例如，给定一个部署对象要求包含三个复制体，我们是应该立即创建三个新的 Pod，并等待所有的 Pod 启动，并终止除一个 Pod 之外的所有旧 Pod，还是逐一进行更新？下面的代码显示了一个名为 Demo 应用的 Deployment 对象，该应用采用默认的 RollingUpdate 升级策略，在更新过程中最多只能有一个超额运行的 Pods（maxSurge）并且没有不可用的 Pods。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://go.botsarena.tech/pictures/study-disign/7d20f0334d52b6e8dd24.gif" alt="15-1-rolling-udpate.gif"&gt;&lt;/p&gt;
&lt;p&gt;此部署对象将一次创建一个带有新版本的 Pod，等待 Pod 启动并准备好后触发其中一个旧 Pod 的终止，并继续进行下一个新 Pod，直到所有的副本都被更新。下面显示了 kubectl get pods 的输出和新旧 Pods 随时间的变化。&lt;/p&gt;
&lt;h4 id="应用可用性的理想和现实之间的差距"&gt;&lt;strong&gt;应用可用性的理想和现实之间的差距&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;通过上面的案例看执行效果可知，从旧版本到新版本的滚动更新看起来确实是平滑更新的。然而不希望发生的事情还是发生了，从旧版本到新版本的切换并不总是完美平滑的，也就是说应用程序可能会丢失一些客户端的请求。这是不可以接受的情况。&lt;/p&gt;
&lt;p&gt;为了真正测试当一个实例被退出服务时，请求是否会丢失。我们不得不对我们的服务进行压力测试并收集结果。我们感兴趣的主要一点是我们的传入的 HTTP 请求是否被正确处理，包括 HTTP 连接是否保持活着。&lt;/p&gt;
&lt;p&gt;这里可以使用简单的 Fortio 负载测试工具，用一连续的请求访问 Demo 的 HTTP 端点。例子种配置包括 50 个并发连接 /goroutine，每秒请求比率为 500，测试超时 60 秒。&lt;/p&gt;</description></item><item><title>18 练习篇：应用流量无损切换技术测验</title><link>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/019/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/019/</guid><description>&lt;div class="goclub-source-note"&gt;来源：&lt;a href="https://study.disign.me/document/Kubernetes%20%e5%ae%9e%e8%b7%b5%e5%85%a5%e9%97%a8%e6%8c%87%e5%8d%97/18%20%e7%bb%83%e4%b9%a0%e7%af%87%ef%bc%9a%e5%ba%94%e7%94%a8%e6%b5%81%e9%87%8f%e6%97%a0%e6%8d%9f%e5%88%87%e6%8d%a2%e6%8a%80%e6%9c%af%e6%b5%8b%e9%aa%8c.md" target="_blank" rel="noopener noreferrer"&gt;技术书栈原文&lt;/a&gt;。本页按授权迁移至 GoClub。&lt;/div&gt;
&lt;h1 id="18-练习篇-应用流量无损切换技术测验"&gt;18 练习篇：应用流量无损切换技术测验&lt;/h1&gt;
&lt;p&gt;经过连续 5 篇相关应用流量引流相关的技术探讨，相信大家已经对 Kubernetes 的服务引流架构有了更深入的了解。常言道好记性不如烂笔头，笔者在反复练习这些参数的过程中，也是费劲了很大的一段时间才对 Kubernetes 的集群引流技术有了一些运用。以下的练习案例都是笔者认为可以加固自身知识体系的必要练习，还请大家跟随我的记录一起练习吧。&lt;/p&gt;
&lt;h3 id="练习-1-deployment-下实现无损流量应用更新"&gt;练习 1：Deployment 下实现无损流量应用更新&lt;/h3&gt;
&lt;p&gt;我们在更新应用的时候，往往会发现即使发布应用的时候 Kubernetes 采用了滚动更新的策略，应用流量还是会秒断一下。这个困惑在于官方文档资料的介绍中这里都是重点说可以平滑更新的。注意这里，它是平滑更新，并不是无损流量的更新。所以到底问题出在哪里呢。笔者查阅了资料，发现核心问题是 Pod 生命周期中应用的版本更新如下图，关联对象资源如 Pod、Endpoint、IPVS、Ingress/SLB 等资源的更新操作都是异步执行的。往往流量还在处理中，Pod 容器就有可能给如下图：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://go.botsarena.tech/pictures/study-disign/5d874375020bbba68587.webp" alt="3a-sync-flow"&gt;&lt;/p&gt;
&lt;p&gt;依据 Pod 容器进程生命周期流程图中，容器进程的状态变更都是异步的，如果应用部署对象 Deployment 不增加 lifecycle 参数 preStop 的配置，即使南北向流量关闭了，进程仍然还需要几秒钟处理正在执行中的会话数据，才可以优雅退出。以下为应用部署 Deployment 对象的声明式配置：&lt;/p&gt;
&lt;p&gt;就绪探测器（readinessProbe）可以知道容器什么时候准备好了并可以开始接受请求流量， 当一个 Pod 内的所有容器都准备好了，才能把这个 Pod 看作就绪。 这种信号的一个用途就是控制哪个 Pod 作为 Service 的后端。 在 Pod 还没有准备好的时候，会从 Service 的负载均衡器中剔除 Pod。periodSeconds 字段指定了 kubelet 每隔 3 秒执行一次存活探测。initialDelaySeconds 字段告诉 kubelet 在执行第一次探测前应该等待 15 秒。&lt;/p&gt;
&lt;p&gt;kubectl 工具手动删除某个特定的 Pod，而该 Pod 的优雅终止限期默认值是 30 秒。preStop 回调所需要的时间长于默认的优雅终止限期，你必须修改 terminationGracePeriodSeconds 属性值来使其正常工作。&lt;/p&gt;</description></item><item><title>19 使用 Rook 构建生产可用存储环境实践</title><link>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/020/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/020/</guid><description>&lt;div class="goclub-source-note"&gt;来源：&lt;a href="https://study.disign.me/document/Kubernetes%20%e5%ae%9e%e8%b7%b5%e5%85%a5%e9%97%a8%e6%8c%87%e5%8d%97/19%20%e4%bd%bf%e7%94%a8%20Rook%20%e6%9e%84%e5%bb%ba%e7%94%9f%e4%ba%a7%e5%8f%af%e7%94%a8%e5%ad%98%e5%82%a8%e7%8e%af%e5%a2%83%e5%ae%9e%e8%b7%b5.md" target="_blank" rel="noopener noreferrer"&gt;技术书栈原文&lt;/a&gt;。本页按授权迁移至 GoClub。&lt;/div&gt;
&lt;h1 id="19-使用-rook-构建生产可用存储环境实践"&gt;19 使用 Rook 构建生产可用存储环境实践&lt;/h1&gt;
&lt;p&gt;Rook 是基于 Kubernetes 之上构建的存储服务框架。它支持 Ceph、NFS 等多种底层存储的创建和管理。帮助系统管理员自动化维护存储的整个生命周期。存储的整个生命周期包括部署、启动、配置、申请、扩展、升级、迁移、灾难恢复、监控和资源管理等，看着就让笔者觉得事情不少，Rook 的目标就是降低运维的难度，让 Kubernetes 和 Rook 来帮你托管解决这些任务。&lt;/p&gt;
&lt;h3 id="rook-管理-ceph-集群"&gt;Rook 管理 Ceph 集群&lt;/h3&gt;
&lt;p&gt;Ceph 分布式存储是 Rook 支持的第一个标记为 Stable 的编排存储引擎，在笔者验证 Rook 操作 Ceph 的过程中发现，其社区文档、脚本都放在一起，初次新手很难知道如何一步一步体验 Rook 搭建 Ceph 的过程。这从一个侧面反应了分布式存储的技术难度和兼容性是一个长期的迭代过程，Rook 的本意是为了降低部署管理 Ceph 集群的难度，但是事与愿违，初期使用的过程并不友好，有很多不知名的问题存在官方文档中。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://go.botsarena.tech/pictures/study-disign/67d8e47c4d3fa7320866.webp" alt="16-1-rook-arch.png"&gt;&lt;/p&gt;
&lt;p&gt;在安装 Ceph 前要注意，目前最新的 Ceph 支持的存储后端 BlueStore 仅支持裸设备，不支持在本地文件系统之上建立存储块。因为 Rook 文档的混乱，一开始我们需要自己找到安装脚本目录，它在&lt;/p&gt;
&lt;p&gt;Ceph 的问题很多，经常需要使用工具箱查看一些情况，按照如下步骤部署：&lt;/p&gt;
&lt;p&gt;使用 Dashboard 查看 Ceph 运行情况：&lt;/p&gt;
&lt;p&gt;访问地址是 31955，&lt;a href="https://master_ip:31955" rel="nofollow noreferrer noopener"&gt;https://master_ip:31955&lt;/a&gt; 就可以访问。账号是 admin，密码可以在线查到：&lt;/p&gt;
&lt;p&gt;清空 Ceph：&lt;/p&gt;
&lt;h3 id="用-rook-管理-nfs-文件系统"&gt;用 Rook 管理 NFS 文件系统&lt;/h3&gt;
&lt;p&gt;NFS 文件系统目前在国内企业还是很常见的一种存储方案。用 Rook 来管理 NFS 文件系统可以极大的方便开发者的存储环境。安装 rook 之前需要先安装 NFS Client 安装包。在 CentOS 节点上安装 nf-utils，在 Ubuntu 节点上安装 nf-common。然后就可以安装 Rook 了。步骤如下：&lt;/p&gt;</description></item><item><title>20 有状态应用的默认特性落地分析</title><link>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/021/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/021/</guid><description>&lt;div class="goclub-source-note"&gt;来源：&lt;a href="https://study.disign.me/document/Kubernetes%20%e5%ae%9e%e8%b7%b5%e5%85%a5%e9%97%a8%e6%8c%87%e5%8d%97/20%20%e6%9c%89%e7%8a%b6%e6%80%81%e5%ba%94%e7%94%a8%e7%9a%84%e9%bb%98%e8%ae%a4%e7%89%b9%e6%80%a7%e8%90%bd%e5%9c%b0%e5%88%86%e6%9e%90.md" target="_blank" rel="noopener noreferrer"&gt;技术书栈原文&lt;/a&gt;。本页按授权迁移至 GoClub。&lt;/div&gt;
&lt;h1 id="20-有状态应用的默认特性落地分析"&gt;20 有状态应用的默认特性落地分析&lt;/h1&gt;
&lt;p&gt;一直以来跑在 Kubernetes 的应用都是无状态的应用，所有数据都是不落盘的，应用死掉之后，应用状态也不复存在，比如 Nginx 作为反向代理的场景。如果你的应用涉及业务逻辑，一般都会涉及把数据在本地放一份。如果应用实例死掉了可以再拉起一个新应用实例继续服务当前的连接请求。那么有状态应用在 Kubernetes 场景下又有哪些特性需要我们记住呢？请随着笔者的章节一步一步了解它。&lt;/p&gt;
&lt;h3 id="statefulset-对象"&gt;StatefulSet 对象&lt;/h3&gt;
&lt;p&gt;当我们使用 Deployment 对象部署应用容器实例的时候，一定会注意到 Pod 实例后缀总是带有随机字符串，这是无状态应用区分实例的一种策略。现实应用中，对于分布式系统的编排，随机的字符串标识是无法应用的。它要求在启动 Pod 之前，就能明确标记应用实例，这个场景下 StatefulSet 对象应景而生。如下 Pod 例子中显示顺序索引如下：&lt;/p&gt;
&lt;p&gt;当你在终端中把所有 Pod 删掉后，StatefulSet 会自动重启它们：&lt;/p&gt;
&lt;p&gt;使用 kubectl exec 和 kubectl run 查看 Pod 的主机名和集群内部的 DNS 项如下：&lt;/p&gt;
&lt;p&gt;Pod 的序号、主机名、SRV 条目和记录名称都没有改变，但和 Pod 相关联的 IP 地址却发生了变更。这个现象说明即使是有状态的容器实例，它的 IP 也是变化的。因为传统遗留的系统很多，很多遗留系统在迁到云原生平台的时候期望能固定 Pod IP，虽然从场景上来讲合理。但毕竟这是遗留系统的设计，它已经不是云原生架构推荐的设计方式了，所以默认 Kubernetes 是没有这个特性的。如果想支持这个特性，就需要在 CNI 上做好扩展才行。开源网络方案 Calico 就提供这种特性，请参考：&lt;/p&gt;
&lt;p&gt;以下是腾讯云提供的注解例子来支持固定 IP 特性：&lt;/p&gt;
&lt;h3 id="有状态存储"&gt;有状态存储&lt;/h3&gt;
&lt;p&gt;StatefulSet 大部分情况下还会挂盘启动。因为 Kubernetes 从 1.13 版本开始已经全面拥抱 CSI 接口标准，默认流程主要是先创建 StorageClass, 然后使用 PersistentVolumeClaim 对象动态申请存储资源。底层 PersistentVolume 对象会驱动 StorageClass 调用指定的存储驱动来创建存储设备。因为每个存储驱动的设计复杂度也不太一样，建议读者可以先从 NFS 存储开始不断积累经验。&lt;/p&gt;</description></item><item><title>21 案例：分布式 MySQL 集群工具 Vitess 实践分析</title><link>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/022/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/022/</guid><description>&lt;div class="goclub-source-note"&gt;来源：&lt;a href="https://study.disign.me/document/Kubernetes%20%e5%ae%9e%e8%b7%b5%e5%85%a5%e9%97%a8%e6%8c%87%e5%8d%97/21%20%e6%a1%88%e4%be%8b%ef%bc%9a%e5%88%86%e5%b8%83%e5%bc%8f%20MySQL%20%e9%9b%86%e7%be%a4%e5%b7%a5%e5%85%b7%20Vitess%20%e5%ae%9e%e8%b7%b5%e5%88%86%e6%9e%90.md" target="_blank" rel="noopener noreferrer"&gt;技术书栈原文&lt;/a&gt;。本页按授权迁移至 GoClub。&lt;/div&gt;
&lt;h1 id="21-案例-分布式-mysql-集群工具-vitess-实践分析"&gt;21 案例：分布式 MySQL 集群工具 Vitess 实践分析&lt;/h1&gt;
&lt;p&gt;对于 Kubernetes 的有状态应用部署来说，当然最有挑战的例子就是拿 MySQL 集群部署最为经典。在近 10 年的数据库流行度来讲，每一个开发者接触到最多的就是 MySQL 数据库了。几乎人人都知道 MySQL Master/Slave 方式的集群搭建方式，其架构的复杂度可想而知。当我们技术把 MySQL 集群搭建到 Kubernetes 集群的时候就不得不考虑如何利用云原生特性把集群搭建起来。这里笔者并不想去分析如何徒手分解安装 MySQL 集群的 YAML，而是通过有过成功迁移云原生集群工具 Vitess 来总结真实的实践过程。&lt;/p&gt;
&lt;h3 id="vitess-工具介绍"&gt;Vitess 工具介绍&lt;/h3&gt;
&lt;p&gt;Vitess 号称可以水平扩展 MySQL 数据库集群管理工具。最早被我们熟知的新闻就是京东在 618 大促中全面采用云原生技术，其中数据库分片集群管理这块就是采用的 Vitess。接下来我们首先快速体验一下在 Kubernetes 下使用 Vitess 的过程。&lt;/p&gt;
&lt;h4 id="初始化环境"&gt;&lt;strong&gt;初始化环境&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;采用单机部署，在 AWS 上启动一台内存大于 8G 的虚拟机，通过安装 K3s 快速构建一套 Kubernetes 环境。&lt;/p&gt;
&lt;p&gt;为了方便连接 Vitess 这个 proxy，需要初始化一下端口转发的环境：&lt;/p&gt;
&lt;p&gt;加载数据库表结构：&lt;/p&gt;
&lt;p&gt;通过 MySQL 连接 Vitess Proxy 访问 MySQL Server：&lt;/p&gt;
&lt;p&gt;至此，我们的体验和安装一套本地的 MySQL Server 是一样的。这种透明的体验值得我们接下来持续挖掘更高级的特性。&lt;/p&gt;
&lt;p&gt;下图说明了 Vitess 的组件架构，我们需要熟悉这些术语：&lt;/p&gt;</description></item><item><title>22 存储对象 PV、PVC、Storage Classes 的管理落地实践</title><link>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/023/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/023/</guid><description>&lt;div class="goclub-source-note"&gt;来源：&lt;a href="https://study.disign.me/document/Kubernetes%20%e5%ae%9e%e8%b7%b5%e5%85%a5%e9%97%a8%e6%8c%87%e5%8d%97/22%20%e5%ad%98%e5%82%a8%e5%af%b9%e8%b1%a1%20PV%e3%80%81PVC%e3%80%81Storage%20Classes%20%e7%9a%84%e7%ae%a1%e7%90%86%e8%90%bd%e5%9c%b0%e5%ae%9e%e8%b7%b5.md" target="_blank" rel="noopener noreferrer"&gt;技术书栈原文&lt;/a&gt;。本页按授权迁移至 GoClub。&lt;/div&gt;
&lt;h1 id="22-存储对象-pv-pvc-storage-classes-的管理落地实践"&gt;22 存储对象 PV、PVC、Storage Classes 的管理落地实践&lt;/h1&gt;
&lt;p&gt;谈到 Kubernetes 存储对象的管理，大多数读者使用最多的就是 Local、NFS 存储类型。因为基于本地卷的挂载使用很少出现问题，并不会出现有什么困难的场景需要用心学习整理。但是从我这里出发想带领读者一起，往更深层的对象实现细节和云原生的存储运维角度出发，看看我们能怎么管理这些资源才是落地的实践。&lt;/p&gt;
&lt;h3 id="了解-pv-pvc-storageclass"&gt;了解 PV、PVC、StorageClass&lt;/h3&gt;
&lt;p&gt;StorageClass 是描述存储类的方法。 不同的类型可能会映射到不同的服务质量等级或备份策略，或是由集群管理员制定的任意策略。 Kubernetes 本身并不清楚各种类代表的是什么。这个类的概念在其他存储系统中有时被称为“配置文件”。&lt;/p&gt;
&lt;p&gt;每个 StorageClass 都包含 provisioner、parameters 和 reclaimPolicy 字段，这些字段会在 StorageClass 需要动态分配 PersistentVolume 时会使用到。&lt;/p&gt;
&lt;p&gt;StorageClass 对象的命名很重要，用户使用这个命名来请求生成一个特定的类。当创建 StorageClass 对象时，管理员设置 StorageClass 对象的命名和其他参数，一旦创建了对象就不能再对其更新。参考范例如下：&lt;/p&gt;
&lt;p&gt;持久卷（PersistentVolume，PV）是集群中的一块存储，可以由管理员事先供应，或者使用存储类（StorageClass）来动态供应。 持久卷是全局集群资源，就像 Node 也是全局集群资源一样，没有 Namespace 隔离的概念。PV 持久卷和普通的 Volumes 一样，也是使用卷插件来实现的，只是它们拥有自己独立的生命周期。 此 API 对象中记述了存储的实现细节，无论其背后是 NFS、iSCSI 还是特定于云平台的存储系统。&lt;/p&gt;
&lt;p&gt;持久卷申领（PersistentVolumeClaim，PVC）表达的是用户对存储的请求。概念上与 Pod 类似。 Pod 会耗用节点资源，而 PVC 申领会消耗 PV 资源。Pod 可以请求特定数量的资源（CPU 和内存）；同样 PVC 申领也可以请求特定 PV 的大小和访问模式。&lt;/p&gt;
&lt;p&gt;尽管 PersistentVolumeClaim 允许用户消耗抽象的存储资源，常见的情况是针对不同的用户需要提供具有不同属性（如性能）的 PersistentVolume 卷。 集群管理员需要能够提供不同性质的 PersistentVolume，并且这些 PV 卷之间的差别不仅限于卷大小和访问模式，同时又不能将卷是如何实现的这些细节暴露给用户。 为了满足这类需求，就有了存储类（StorageClass）资源。&lt;/p&gt;</description></item><item><title>23 K8s 集群中存储对象灾备的落地实践</title><link>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/024/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/024/</guid><description>&lt;div class="goclub-source-note"&gt;来源：&lt;a href="https://study.disign.me/document/Kubernetes%20%e5%ae%9e%e8%b7%b5%e5%85%a5%e9%97%a8%e6%8c%87%e5%8d%97/23%20K8s%20%e9%9b%86%e7%be%a4%e4%b8%ad%e5%ad%98%e5%82%a8%e5%af%b9%e8%b1%a1%e7%81%be%e5%a4%87%e7%9a%84%e8%90%bd%e5%9c%b0%e5%ae%9e%e8%b7%b5.md" target="_blank" rel="noopener noreferrer"&gt;技术书栈原文&lt;/a&gt;。本页按授权迁移至 GoClub。&lt;/div&gt;
&lt;h1 id="23-k8s-集群中存储对象灾备的落地实践"&gt;23 K8s 集群中存储对象灾备的落地实践&lt;/h1&gt;
&lt;p&gt;谈到存储对象的灾备，我们可以想象成当你启动了挂载卷的 Pod 的时候，突然集群机器宕机的场景，我们应该如何应对存储对象的容错能力呢？应用的高可用固然最好，但是灾备方案一直都是最后一道门槛，在很多极限情况下，容错的备份是你安心提供服务的保障。&lt;/p&gt;
&lt;p&gt;在虚拟机时代，我们通过控制应用平均分配到各个虚拟机中和定期计划执行的数据备份，让业务可靠性不断地提高。现在升级到 Kubernetes 时代，所有业务都被 Kubernetes 托管，集群可以迅速调度并自维护应用的容器状态，随时可以扩缩资源来应对突发情况。&lt;/p&gt;
&lt;p&gt;听笔者这么说，感觉好像并不需要对存储有多大的担心，只要挂载的是网络存储，即使应用集群坏了，数据还在么，好像也没有多大的事情，那么学这个存储对象的灾备又有什么意义呢？&lt;/p&gt;
&lt;p&gt;笔者想说事情远没有想象中那么简单，我们需要带入接近业务的场景中，再来通过破坏集群状态，看看读存储对象是否有破坏性。&lt;/p&gt;
&lt;p&gt;因为我们从虚拟机时代升级到 Kubernetes 时代，我们的目的是利用动态扩缩的资源来减少业务中断的时间，让应用可以随需扩缩，随需自愈。所以在 Kubernetes 时代，我们要的并不是数据丢不丢的问题，而是能不能有快速保障让业务恢复时间越来越短，甚至让用户没有感知。这个可能实现吗？&lt;/p&gt;
&lt;p&gt;笔者认为 Kubernetes 通过不断丰富的资源对象已经快接近实现这个目标了。所以笔者这里带着大家一起梳理一遍各种存储对象的灾备在 Kubernetes 落地的实践经验，以备不时之需。&lt;/p&gt;
&lt;h3 id="nfs-存储对象的灾备落地经验"&gt;NFS 存储对象的灾备落地经验&lt;/h3&gt;
&lt;p&gt;首先我们应该理解 PV/PVC 创建 NFS 网络卷的配置方法，注意 mountOptions 参数的使用姿势。如下例子参考：&lt;/p&gt;
&lt;p&gt;在这个例子中，PersistentVolume 是 NFS 类型的，因此需要辅助程序 /sbin/mount.nfs 来支持挂载 NFS 文件系统。&lt;/p&gt;
&lt;p&gt;执行一个 Pod 挂载 NFS 卷：&lt;/p&gt;
&lt;p&gt;当你在一个 Pod 里面挂载了 NFS 卷之后，就需要考虑如何把数据备份出来。&lt;a href="https://github.com/vmware-tanzu/velero" rel="nofollow noreferrer noopener"&gt;velero&lt;/a&gt; 作为云原生的备份恢复工具出现了，它可以帮助我们备份持久化数据对象。velero 案例如下：&lt;/p&gt;
&lt;p&gt;注意 velero 默认没法备份卷，所以它集成了开源组件 &lt;a href="https://github.com/restic/restic" rel="nofollow noreferrer noopener"&gt;restic&lt;/a&gt; 支持了存储卷的支持。因为目前还处于试验阶段，注意请不要在生产环境中使用。&lt;/p&gt;
&lt;h3 id="ceph-数据备份及恢复"&gt;Ceph 数据备份及恢复&lt;/h3&gt;
&lt;p&gt;Rook 是管理 Ceph 集群的云原生管理系统，在早前的课程中我已经和大家实践过使用 Rook 创建 Ceph 集群的方法。现在假设 Ceph 集群瘫痪了应该如何修复它。是的，我们需要手工修复它。步骤如下：&lt;/p&gt;</description></item><item><title>24 练习篇：K8s 集群配置测验</title><link>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/025/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://go.botsarena.tech/docs/resources/cloud-native-web3-fulltext/kubernetes-practice-guide/025/</guid><description>&lt;div class="goclub-source-note"&gt;来源：&lt;a href="https://study.disign.me/document/Kubernetes%20%e5%ae%9e%e8%b7%b5%e5%85%a5%e9%97%a8%e6%8c%87%e5%8d%97/24%20%e7%bb%83%e4%b9%a0%e7%af%87%ef%bc%9aK8s%20%e9%9b%86%e7%be%a4%e9%85%8d%e7%bd%ae%e6%b5%8b%e9%aa%8c.md" target="_blank" rel="noopener noreferrer"&gt;技术书栈原文&lt;/a&gt;。本页按授权迁移至 GoClub。&lt;/div&gt;
&lt;h1 id="24-练习篇-k8s-集群配置测验"&gt;24 练习篇：K8s 集群配置测验&lt;/h1&gt;
&lt;p&gt;第二部分的内容围绕 Kubernetes 核心组件的安装配置一一给大家拆解了一遍，当前集群组件最主流的配置就是这些：Containerd、kubeadm、IPVS、Calico、kube-dns。读者通过官方文档就可以独立配置一套集群，只是笔者发现，因为集群配置的过度复杂，能获得的环境也是千差万别，很难得到统一的认知。本篇测验的目的就是带着大家一起校验一遍我们学习到的经验，一起搭建一套集群的全过程，以此来校验我们掌握的集群知识。&lt;/p&gt;
&lt;h3 id="环境"&gt;环境&lt;/h3&gt;
&lt;p&gt;从第一天接触容器技术之后，我们想解决的问题就是环境依赖问题。因为 Docker 是让环境包裹这应用一起制作成镜像分发的。等我们配置 Kubernetes 集群的时候，我们操作的最小单元是 Pod，你可以理解为是一个容器组，这个容器组并不是简单的把一组容器放一起就完事了。它的设计巧妙之处在于以 pause 为核心的基础容器把相关应用的所有环境依赖都掌握在自己的运行时里面。其它相关业务容器只是加入到这个运行时里面，这些业务容器出现问题并不会破坏环境。这是 Kubernetes 构建业务集群的核心设计，非常巧妙地解决了应用服务的可用性问题。&lt;/p&gt;
&lt;p&gt;现在我们要选择操作系统的版本了。你会发现并没有任何官方文档说过，哪一个版本是指定的。其实官方并没有这样的约定。因为容器的目的就是解决环境的依赖，但是这么多年的演进，说得更清楚一点，我们仍然有一个核心依赖就是 Kernel 依赖搞不定。Kernel 的特性会决定容器的特性，我们一般在选择上会参考 Docker 的版本来定，主流的有 18.09、19.03 等。&lt;/p&gt;
&lt;p&gt;你发现没有，你并不能保证在特定的环境下这些 Docker 版本没有问题，这就是我们在配置生产环境中出现问题自己埋下的坑。如果你是企业内部使用，最好的办法是建立基准线，明确版本号，在大量实践的基础上投入人力来维护这个版本的稳定性。因为容器技术发展很快，现在 Kubernetes 已经和 Docker 越来越规避，都在使用 containerd 来支持底层容器运行时的管理，作为用户我们是无法回避这个。&lt;/p&gt;
&lt;p&gt;这里又突显一个问题，因为组件的变革，我到底应该选择哪个版本呢，它们稳定吗？因为 Kubernetes 是开源社区推动的软件，我们一定要遵循开源的方式来使用这些软件才能得到正确的经验。我总结出来的经验如下，方便大家参考：&lt;/p&gt;
&lt;p&gt;x86-64 仍然是当前对容器最好的系统架构体系，目前主流的系统聚集在 RedHat/CentOS 7.x 系列、Ubuntu 16.04 系列。对于内核红帽系主要在 3.10 以上，Ubuntu 能到 4.4 以上。有些用户会通过开源 Kernel 仓库把红帽系的 Kernel 升级到 4.4，也比较常见。升级内核的代价就是引入很多未知的模块，让系统变得不稳定。ARM 系统架构会对整个 Kubernetes 组件的文件格式产生兼容性要求，在选择适配的时候，一定要注意有没有准备好 Kubernetes 相应的组件。总结下来，主流的操作系统主要是红帽的 7.x 系列和 Ubuntu LTS 系列 16.04。升级大版本操作系统对 Kubernetes 来说，需要做很多适配工作，目前开源社区是不太可能帮用户做的。一定注意。&lt;/p&gt;
&lt;p&gt;Kubernetes 的版本更新很快，整个社区会维护 3 个主线版本，如现在主要为 1.16.x、1.17.x、1.18.x。这个 x 版本号差不多 2 周就一个迭代，主要是修复 Bug。很多团队在使用上总结了一些技巧，比如取奇数版本或者偶数版本作为自己的主力版本，这个做法的目的就是规避最新版本带来的不稳定性。并不是说奇数版本好或者是偶数版本稳定，这是纯属瞎猜。作为开源软件，它的质量是社区在维护，落实到用户这里，就是大家都是小白鼠，需要在自己的环境试验验证组件的可靠性。总结下来，主流的环境还是选择比最新版本低 1 个或者 2 个子版本作为周期来当做自己的软件来维护。维护开源软件不是免费的，它是通过大家的努力才能保证组件的使用可靠性的。&lt;/p&gt;</description></item></channel></rss>