1 第一章
1.1 微服务概述
微服务的核心要义在于基于面向服务的思想,对传统大型应用系统进行功能分解,推动细粒度服务的使用。其基本思想是将传统的单体应用按业务功能拆分为一系列可被独立设计、开发、部署、运维的软件服务单元,服务间彼此配合、相互协作以实现最终价值。实际上,微服务可看作面向服务体系结构(Service-Oriented Architecture,SOA)的一种具体实现。<br /> 微服务架构 (MicroServices Architecture,MSA)则指根据应用系统的业务需求,通过对预定义的微服务进行重组而形成企业级应用的分布式体系结构。它主要将传统概念上的单体应用在功能、数据等方面进行分解,划分为多个具有明确边界并可被自由重组的小规模子服务。这些子服务间采用轻量级通信方式实现交互、协作,每个服务都有自己的数据库并可在独立进程中被部署、运行等,服务之间保持技术异构性,可由不同的团队选择合适的工具、语言进行开发。<br /> 与单体架构相比,微服务架构的优势在于:<br /> (1)微服务按业务功能划分,每个服务都具备特定的功能,易于开发、维护等;<br /> (2)每个独立的微服务可以由不同的语言基于不同的平台开发,灵活性较好;<br /> (3)子服务可独立部署,能够实现可持续集成及交付;<br /> (4)容错能力强大,单个微服务出现问题不会影响系统其他服务的运行;<br /> (5)可实现动态按需实时扩展等。<br /> 目前,微服务体系结构的思想已被应用于很多大型公司的分布式应用系统中,较典型的有Amazon、Netflix、Uber等公司。
1.2 微服务的历史演变
1.传统单体架构模式
单体架构就是单点应用,早期的SSM和SSH整合项目就是单点应用。即分层架构模式,数据库访问层、业务逻辑层、控制层、前后端的交互都是一个人写的。
优点:开发简单、运维简单。适合个人或者小团队开发。
缺点:代码耦合度高、项目可用性差,容易崩溃。不适合团队模式协同开发。
2.垂直拆分
随着业务规模的越来越庞大,系统设计就越来越复杂,大的系统就开始进行业务的垂直拆分。比如:有专门做商品秒杀的部门,有专门做生鲜商品的部门,有专门做超市的部门,等等,当然这是根据部门天生划分的,也有根据业务需求进行系统划分的。
优点:垂直拆分,系统独立部署和维护,每个系统在自己进程内执行,分而治之。
缺点:拆分越多,存储越复杂,系统间重复的东西也越多,单个系统还是单体模式。
3.SOA面向服务架构模式
SOA(Service-OrientedArchitecture)基于分布式架构演变,俗称服务化,也就是面向接口开发(服务开发),将共同存在的业务逻辑抽取成一个公共的服务,提供给其他结构实现调用,服务与服务之间采用rpc远程调用技术。
优点:传输协议采用SOAP协议(http/https+XML)实现传输,在高并发情况下实现通讯该协议存在大量的冗余性传输,非常占用带宽。所以微服务架构使用json代替了xml。SOA架构模式实现方案WebService或者ESB企业服务总线,底层采用SOAP协议传输
缺点: SOAP协议实现通讯,xml传输非常重,效率比较低。服务化管理和治理设施不够完善。依赖于中心服务发现机制不适合前后端分离架构模式
1.3 主流的微服务框架
1.Spring Cloud
Spring Cloud是一个系列框架的合计,基于HTTP(s)的RETS服务构建服务体系,SpringCloud能够帮助架构师构建一整套完整的微服务架构技术生态链。Spring Cloud为开发者提供了快速构建分布式系统的通用模型的工具(包括配置管理,服务发现,熔断器,智能路由,微代理,控制总线,一次性令牌,全局锁,领导选举,分布式会话,集群状态等)。主要项目包括Spring Cloud Netflix、Spring Cloud Config、Spring Cloud Stream、Spring Cloud Security、Spring Cloud Zookeeper、Spring Cloud Eureka等。
2.Dubbo
Dubbo是由阿里巴巴开源的分布式服务化治理框架,通过RPC请求方式访问。Dubbo是在阿里巴巴的电商平台中逐渐探索演进所形成的,经历过复杂业务的高并发挑战,比Spring Cloud的开源时间还要早。目前阿里、京东、当当、携程、去哪等一些企业都在使用Dubbo。
Dubbo致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。其核心部分包含:
- 远程通讯: 提供对多种基于长连接的NIO框架抽象封装,包括多种线程模型,序列化,以及“请求-响应”模式的信息交换方式。
- 集群容错: 提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持。
- 自动发现: 基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器。
3.Dropwizard
DropWizard是由Yammer开发团队贡献的一个后台服务开发框架,其集成了Java生态系统中各个问题域中最优秀的组件,帮助开发者快速地打造一个Rest风格的后台服务。对开发者来说,使用DropWizard有如下好处:
- 和Maven集成良好,也就是说和Gradle集成也很良好。
- 开发迅速,部署简单。
- 代码结构好,可读性高。
- 自动为服务提供OM框架。
- 让开发者自然的把一个应用拆分为一个个的小服务。
4.Akka
Akka是一个构建在JVM上,基于Actor模型的并发框架。它是一个用Scala编写的库,可以用在有简化编写容错、高可伸缩性的Java和Scala的Actor模型。Akka处理并发的方法基于Actor模型,Actor之间通信的唯一机制就是消息传递。Akka的特点如下:
- 对并发模型进行了更高的抽象。
- 是异步、非阻塞、高性能的事件驱动编程模型。
- 是轻量级事件处理(1GB内存可容纳百万级别个Actor)。
- 它提供了一种称为Actor的并发模型,其粒度比线程更小,你可以在系统中启用大量的Actor。
- Akka既可以在单机上构建高并发程序,也可以在网络中构建分布式程序,并提供位置透明的Actor定位服务。
1.4 搭建微服务所需的软件资源
1.Docker
当我们使用了微服务架构后,我们将一个原本完整的系统,按照业务逻辑拆分成一个个可独立运行的子系统。为了降低系统间的耦合度,我们希望这些子系统能够运行在独立的环境中,这些环境之间能够相互隔离。在Docker出现之前,若使用虚拟机来实现运行环境的相互隔离的话成本较高,虚拟机会消耗较多的计算机硬件/软件资源。 Docker不仅能够实现运行环境的隔离,而且能极大程度的节约计算机资源,它成为一种轻量级的“虚拟机”。
2.Jenkins
当使用微服务架构后,随着业务的逐渐发展,系统之间的依赖关系会日益复杂,而且各个模块的构建顺序都有所讲究。对于一个小型系统来说,也许只有几个模块,那么你每次采用人肉构建的方式也许并不感觉麻烦。但随着系统业务的发展,系统之间的依赖关系日益复杂,子系统也逐渐增多,每次构建一下都要非常小心谨慎,稍有不慎整个服务都无法正常启动。而且这些构建的工作很low,但却需要消耗大量的精力,这无疑降低了开发的效率。Jenkins就是来帮助解决这个问题的。
3.Maven
在实际开发中,系统往往有多套环境构成,如:开发环境、测试环境、预发环境、生产环境。而不同环境的配置各不相同。如果只有一套配置,那么当系统从一个环境迁移到另一个环境的时候,就需要通过修改代码来更换配置,这样无疑增加了工作的复杂度,而且易于出错。此时可以用Maven提供的profile功能解决这一个问题。1.5 市面上的微服务产品
- 腾讯微服务平台
腾讯微服务平台(Tencent Service Framework,TSF)是一个围绕着应用和微服务的 PaaS 平台,提供应用全生命周期管理、数据化运营、立体化监控和服务治理等功能。TSF拥抱 Spring Cloud 、Service Mesh 微服务框架,帮助企业客户解决传统集中式架构转型的困难,打造大规模高可用的分布式系统架构,实现业务、产品的快速落地。针对原生 Spring Cloud 应用与 Mesh 方式零成本接入。
TSF 以腾讯云中间件团队多款成熟的分布式产品为核心基础组件,提供秒级推送的分布式配置服务、链路追踪等高可用稳定性组件。此外,TSF与腾讯云 API 网关和消息队列打通,帮助企业轻松构建大型分布式系统。
2. 网易轻舟微服务
轻舟微服务拥有业内领先的无侵入式微服务治理技术,覆盖 Spring Cloud、Dubbo、Service Mesh 等主流微服务开发技术选型。提供服务开放、服务治理、分布式事务管理、全链路监控等诸多能力,帮助企业高效率、低成本实现微服务技术改造升级,平滑、安全、渐进的演进至云原生技术架构。2 第二章
2.1 服务网格概念
Service Mesh 又译作 “服务网格”,作为服务间通信的基础设施层。Buoyant公司的 CEO Willian Morgan 对什么是服务网格以及为什么云原生应用需要服务网格作出了解释:服务网格(ServiceMesh)是处理服务间通信的基础设施层。它负责构成现代云原生应用程序的复杂服务拓扑来可靠地交付请求。在实践中,Service Mesh 通常以轻量级网络代理阵列的形式实现,这些代理与应用程序代码部署在一起,对应用程序来说无需感知代理的存在。
用一句话来解释什么是 Service Mesh,可以将它比作是应用程序或者说微服务间的 TCP/IP,负责服务之间的网络调用、限流、熔断和监控。对于编写应用程序来说一般无须关心 TCP/IP 这一层(比如通过 HTTP 协议的 RESTful 应用),使用 Service Mesh 也就无须关心服务之间的那些原本通过服务框架实现的事情,比如 Spring Cloud、Netflix OSS 和其他中间件,现在只要交给 Service Mesh 就可以了。
Service Mesh 有如下几个特点:
- 应用程序间通信的中间层
- 轻量级网络代理
- 应用程序无感知
- 解耦应用程序的重试/超时、监控、追踪和服务发现
服务网格的架构如下图所示。服务网格作为 sidecar 运行,对应用程序来说是透明,所有应用程序间的流量都会通过它,所以对应用程序流量的控制都可以在serivce mesh 中实现。
2.2 服务网格技术框架
服务网格技术框架主要包括Envoy、Istio、Linkerd、Kuma、Consul、Maesh等几种。
- Envoy是专为大型现代SOA(面向服务架构)架构设计的 L7 代理和通信总线。是许多服务网格框架的核心组件,是一个通用的开源代理,常被用于Pod内的sidecar以拦截流量。也有服务网格使用另外的代理方案。
- Istio是基于Envoy构建的一个可扩展的开源服务网格。开发团队可以通过它连接、加密、管控和观察应用服务。Istio的关键特性包括负载均衡、流量路由、策略创建、可度量性及服务间认证。Istio有两个部分组成:数据平面和控制平面。数据平面负责处理流量管理,通过 Envoy 的 sidecar 代理来实现流量路由和服务间调用。控制平面是主要由开发者用来配置路由规则和观测指标。与其他服务网格相比,Istio胜在其平台成熟度以及通过其Dashbaord。
- Linkerd是一个轻量级、安全优先的 Kubernetes 服务网格。Linkerd并没有采用基于 Envoy 的构建方案。而是使用了一个基于 Rust 的高性能代理 linkerd2-proxy,这个代理是专门为 Linkerd服务网格编写的。使用Linkerd服务网格,应用服务可以增强其可靠性、可观测性及其在 Kubernetes 上部署的安全性。举个例子,可观测性的增强可以帮助用户解决服务间的延迟问题。使用Linkerd不要求用户做很多代码调整或是花费大量时间写 YAML 配置文件。
- Kuma 是一个基于 Envoy 的平台的控制平面。 Kuma 提供了安全、观测、路由等网络特性,同时增强了服务间的连通性。可以通过一个统一控制面板来运维管理多个互相隔离独立的服务网格。这项能力可以满足安全要求高的使用场景。既符合隔离的要求,又实现集中控制。
- Consul 是来自HashiCorp的服务网格,专注于路由和分段,通过应用级的 sidecar 代理来提供服务间的网络特性。 Consult 侧重于应用安全,提供应用间的双向 TLS 连接以实现授权和加密。
- Consult 独特的一点是提供了两种代理模式。一种是它内建的代理,同时它还支持 Envoy 方案。Connect强调可观测性,集成了例如 Prometheus 这样的工具来监控来自 sidecar 代理的数据。Consul可以灵活地满足开发者使用需求。比如,它提供了多种方式注册服务:可以从编排系统注册,可以通过配置文件,通过 API 调用,或是命令行工具
Maesh是来自Containous的容器原生的服务网格,标榜自己是比市场其它服务网格更轻量级更易用的方案。和很多基于 Envoy 构建的服务网格不同,Maesh采用了Traefik, 一个开源的反向代理和负载均衡器。Maesh并没有采用 sidecar 的方式进行代理,而是在每个节点部署一个代理终端。这样做的好处是不需要去编辑 Kubernetes 对象,同时可以让用户有选择性地修改流量,Maesh相比其他服务网格侵入性更低。Maesh支持的配置方式:在用户服务对象上添加注解或是在服务网格对象上添加注解来实现配置。
2.3 服务网格实现模式
服务网格目前的主流实现模式为基于Sidecar(边车)的模式。
Sidecar模式的含义:将本该属于应用程序的功能拆分成单独的进程,这个进程可以被理解为Sidecar。Sidecar原意是摩托车的边车,用到软件架构中,就是Sidecar应用是连接到父应用,并为其扩展或增强功能。Sidecar应用于主应用程序松耦合。
- Sidecar模式的优势
- 通过抽象出与功能相关的共同基础设施到一个不同层,以降低微服务代码的复杂度。
- 应用不再需要编写相同的第三方组件配置文件和代码,降低了微服务架构中代码的复杂度。
- 降低了应用程序和底层平台的耦合度。
Sidecar模式如何工作:服务网格层可以存在于与应用程序一起运行的Sidecar容器中,每个应用程序旁边都附有相同的Sidecar副本。来自单个服务的所有传入和传出网络流量,都流经Sidecar代理。因此,Sidecar能够管理微服务之间的流量,可收集数据并实施相关策略。从某个角度来说,应用并不需要了解网路外部的系统,只需要知道附加的Sidecar代理,这就是Sidecar模式。Sidecar工作模式的本质是将网络依赖抽象为Sidecar。
2.4 搭建微服务所需的硬件资源
服务器:微服务生态系统的底层是硬件层。这一层是服务器物理机所在的层,它们是所有内部工具和微服务运行的基础。这些服务器被放置在数据中心的机架上,由供电系统供给电力,使用着昂贵的HVAC 冷却系统。这里有各种各样的服务器:有些专门用于运行数据库,有些专门处理CPU密集的任务。它们有些是某些公司私有的,有些是从所谓的“云服务提供商”那里租来的,比如Amazon Web Services Elastic Compute Cloud(AWS EC2)、Google Cloud Platform(GCP)或Microsoft Azure。硬件的选择取决于服务器的所有者。如果公司有自己的数据中心,硬件的选择就是自己的事情,完全可以根据实际需要来定制服务器。如果服务器是在云端(这种情况比较普遍),就没有太多的选择余地。
- 生态系统:使用哪种操作系统并没有一个标准的答案,这完全取决于要构建的应用程序、构建应用程序所使用的编程语言以及构建微服务所需要的软件包和工具。主流的微服务生态系统一般会使用Linux 的变形版本,比如CentOS、Debian 或Ubuntu,不过一个使用了.NET 平台的公司显然会有不同的选择。硬件层之上还可以有一些层,比如资源隔离、资源抽象(由Docker和Apache Mesos 提供的)和数据库(专门的或共享的)。
- 配置管理工具:操作系统的安装和硬件资源的配置是服务器的第一个层。每个主机必须被配置好,而且在安装好操作系统之后,必须提供一个配置管理工具(比如Ansible、Chef 或Puppet)来安装应用程序,并做好必要的配置。
主机级别的监控和日志:对主机进行主机级别的监控(使用Nagios)也是必要的,而且需要记录主机级别的日志。在主机出现异常(磁盘错误、网络错误或CPU 过载)时就可以方便地对它们进行诊断,有助于问题的解决。
2.5 服务网格有哪些产品
AWS App Mesh
AWS App Mesh 是由亚马逊云计算平台提供的服务网格,可提供应用程序级网络,让服务可以轻松跨多种类型的计算基础设施相互通信。
- 能够为应用程序提供端到端可见性和高可用性。
- 可以提供一致的可见性和网络流量控制。
- 无需更新应用程序代码即可变更监控数据的收集方式或服务间流量的路由方式。
- 会配置每个服务以导出监控数据,并在整个应用程序中实现一致的通信控制逻辑。
下图是AWS APP Mesh的工作原理图。
- 腾讯 Mesh 微服务平台:TSF Mesh
腾讯 Mesh 微服务平台(Tencent Service Mesh Framework,以下简称 TSF Mesh)是一个基础设施层,用于处理服务间的通信。TSF Mesh 是由一系列轻量级的网络代理组成,这些代理(又称Sidecar)与应用程序部署在一起,而应用程序不感知 Sidecar 的存在。TSF Mesh 是处于 TCP/IP 之上的一个抽象层。TCP解决了网络端点间字节传输问题,TSF Mesh 解决服务节点间请求的路由问题。
TSF Mesh 具有如下优势:
- 多编程语言应用兼容。
- 业务代码零侵入,代码无须改造。
红框中的内容是 TSF Mesh 提供的主要功能。
3 第三章
3.1 TSF 产品功能
- 微服务框架:支持Spring Cloud、Dubbo、ServiceMesh、TSF RPC等多种框架接入。
- 服务治理:提供服务注册与发现、服务鉴权、服务路由、服务调度等基础微服务治理能力。
- DEVOPS:提供敏捷开发到CICD全流程一站式解决方案,打通从开发到发布的各个环节。
- 数据化运营:提供多维度的数据化能力,整合后给业务方进行业务运营。
- 服务化能力支撑:提供连接其他资源的能力,比如整合CKV,分布式数据库中间件,分布式事务,CKAFKA,CMQ,提供统一能力输出到业务,快速打造技术中台。
- 致力于解决:
| 对比项 | TSF | Spring Cloud |
|---|---|---|
| 服务限流 | 支持多作用域规则的配置 | 不支持 |
| 服务路由 | 支持灵活的路由规则配置 | 不支持 |
| 服务鉴权 | 支持服务黑白名单和基于tag鉴权两种鉴权方式 | 不支持 |
| | 日志服务 | 提供采集、呈现、解析、检索的能力 | 自行搭建 | | 微服务API网关 | 提供微服务网关能力,支持负载均衡、熔断、限流等策略 | 使用ZULL等组件开发 | | 资源自动扩容 | 提供虚拟机集群和容器集群按照 CPU,内存使用率等指标实时自动扩缩容。 | 手动进行,无法做到实时,可扩展性差 |
3.3 TSF 应用场景
- 构建分布式服务系统
TSF 提供了 RESTful 调用方式和自研的高性能 RPC 框架,能够构建高可用、高性能的分布式系统。
TSF 系统地考虑了分布式服务发现、路由管理、安全、负载均衡等细节问题。
同时,TSF 已打通消息队列、API Gateway 等服务,满足用户多样化的需求。
- 应用发布和管理
相对于传统的应用发布需要运维人员登录到每一台服务器进行发布和部署,TSF 针对分布式系统的应用发布和管理,提供了简单易用的可视化控制台。
用户通过控制台可以发布应用,包括创建、部署、启动应用,也支持查看应用的部署状态。除此之外,用户可以通过控制台管理应用,包括回滚应用、扩容、缩容和删除应用。
- 数据化运营
通过对日志埋点的收集和分析,可以得到一次请求在各个服务间的调用链关系,有助于梳理应用的请求入口与服务的调用来源、依赖关系。当遇到请求耗时较长的情况,可以通过调用链分析调用瓶颈,快速定位异常。
- 服务治理
支持服务级别和 API 级别的服务治理能力,包括服务路由、服务限流、服务鉴权功能。
服务路由功能支持将请求按权重路由到不同版本的服务上。
3.4 TSF 使用限制
3.4.1 资源与部署相关
- 免费注册到注册中心的服务实例额度 ,20个
- 容器集群数量,最多5个
- 全局命名空间个数,1个
- 虚拟机集群导入云主机的操作系统:CentOS 7.5 、Ubuntu 18.04 LTS
- 程序包仓库存储容量,最多100GB
-
3.4.2 配置相关
应用/全局配置项的单个版本的大小,最大65535个字节
- 单个应用配置项 Key 数量,最多100个
-
3.4.3 服务治理相关
方法调用设置 tag 数量,单个租户下最多16个
- 全链路灰度发布规则数量,最多100条
- 单个服务下服务路由规则数量,最多10条
- 微服务网关 API Path 最长长度,128字符
-
3.4.4 日志与调用链相关
日志存储上限,基础版每个节点最大2.5GB,专业版每个节点最大4GB,铂金版每个节点最大20GB
- 日志存储天数,最多30天
- 单次日志查询的日志条数,最多10000条
- 日志配置项数量,最多200条
-
3.5 TSF 相关概念

集群是计算资源的管理维度。TSF 中的集群分为虚拟机集群和容器集群。使用虚拟机或者容器计算资源时,用户需要提前先将云主机导入集群中,才能进行应用的部署。
- 命名空间对微服务之间的调用起到隔离作用。同一命名空间下,微服务可以直接相互调用。不同命名空间中运行的微服务不能直接相互调用,需要通过公网或者网关来相互连通。通常情况下,命名空间可以起到环境隔离的作用(如隔离开发、测试环境)或服务分组的作用。
- 应用就是用户的业务应用
- 服务是用户线上运行的微服务。一个应用注册到注册中心后,会注册成为一个(如 Spring Cloud 或者 Mesh 的做法)或多个(如 Dubbo 的做法)微服务。TSF 通过用户应用程序包中声明的服务名来注册微服务。
- 部署组是状态相同的节点的最小集合。同一个部署组运行了相同的程序包、相同的配置、使用相同的启动参数。用户在某一个应用下创建部署组,使用应用下某一个程序包,使用集群中的云主机或者容器资源,将应用部署在某一个环境(命名空间)中。
- 节点、实例、服务实例三个都是指一台虚拟机或者一个容器的 pod。
4 第四章
4.1 环境规划
4.1.1 k8s集群类型
- Kubernetes集群大致分为两类:一主多从和多主多从。
- 一主多从:一个Master节点和多台Node节点,搭建简单,但是有单机故障风险,适合用于测试环境。
- 多主多从:多台Master和多台Node节点,搭建麻烦,安全性高,适合用于生产环境。

为了测试方便,本次搭建的是一主多从类型的集群。
4.1.2 安装方式
kubernetes有多种部署方式,目前主流的方式有kubeadm、minikube、二进制包。
① minikube:一个用于快速搭建单节点的kubernetes工具。
- ② kubeadm:一个用于快速搭建kubernetes集群的工具。
- ③ 二进制包:从官网上下载每个组件的二进制包,依次去安装,此方式对于理解kubernetes组件更加有效。
- 我们需要安装kubernetes的集群环境,但是又不想过于麻烦,所以选择kubeadm方式。
4.1.3 主机规划
| 角色 | IP地址 | 操作系统 | 配置 |
|---|---|---|---|
| Master | 192.168.24.31 | CentOS7.9,基础设施服务器 | 6核CPU,16G内存,50G硬盘 |
| Node1 | 192.168.24.32 | CentOS7.9,基础设施服务器 | 6核CPU,16G内存,50G硬盘 |
| Node2 | 192.168.24.33 | CentOS7.9,基础设施服务器 | 6核CPU,16G内存,50G硬盘 |
4.2 k8s环境搭建
4.2.1 前言
- 本次环境搭建需要三台CentOS服务器(一主二从),然后在每台服务器中分别安装Docker(18.06.3)、kubeadm(1.22.4)、kubectl(1.22.4)和kubelet(1.22.4)。
没有特殊说明,就是三台机器都需要执行。
4.2.2 环境初始化
4.2.2.1 检查操作系统的版本
- 检查操作系统的版本(要求操作系统的版本至少在7.5以上):
cat /etc/redhat-release

4.2.2.2 关闭防火墙和禁止防火墙开机启动
- 关闭防火墙:
systemctl stop firewalld
- 禁止防火墙开机启动:
systemctl disable firewalld

4.2.2.3 设置主机名
- 设置主机名:
hostnamectl set-hostname <hostname>
- 设置192.168.24.31的主机名:
hostnamectl set-hostname k8s-master
- 设置192.168.24.32的主机名:
hostnamectl set-hostname k8s-node1
- 设置192.168.24.33的主机名:
hostnamectl set-hostname k8s-node2
4.2.2.4 主机名解析
- 为了方便后面集群节点间的直接调用,需要配置一下主机名解析,企业中推荐使用内部的DNS服务器。
cat >> /etc/hosts << EOF
192.168.24.31 k8s-master
192.168.24.32 k8s-node1
192.168.24.33 k8s-node2
EOF
4.2.2.5 时间同步
- kubernetes要求集群中的节点时间必须精确一致,所以在每个节点上添加时间同步:
yum install ntpdate -y
ntpdate time.windows.com
4.2.2.6 关闭selinux
- 查看selinux是否开启:
getenforce
- 永久关闭selinux,需要重启:
sed -i 's/enforcing/disabled/' /etc/selinux/config
- 临时关闭selinux,重启之后,无效:
setenforce 0
4.2.2.7 关闭swap分区
- 永久关闭swap分区,需要重启:
sed -ri 's/.*swap.*/#&/' /etc/fstab
- 临时关闭swap分区,重启之后,无效::
swapoff -a
4.2.2.8 将桥接的IPv4流量传递到iptables的链
- 在每个节点上将桥接的IPv4流量传递到iptables的链:
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
vm.swappiness = 0
EOF
# 加载br_netfilter模块
modprobe br_netfilter
# 查看是否加载
lsmod | grep br_netfilter
# 生效
sysctl --system
4.2.2.9 开启ipvs
- 在kubernetes中service有两种代理模型,一种是基于iptables,另一种是基于ipvs的。ipvs的性能要高于iptables的,但是如果要使用它,需要手动载入ipvs模块。
- 在每个节点安装ipset和ipvsadm:
yum -y install ipset ipvsadm
- 在所有节点执行如下脚本:
cat > /etc/sysconfig/modules/ipvs.modules <<EOF
#!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4
EOF
- 授权、运行、检查是否加载:
chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules && lsmod | grep -e ip_vs -e nf_conntrack_ipv4
- 检查是否加载:
lsmod | grep -e ipvs -e nf_conntrack_ipv4
4.2.2.10 重启三台机器
- 重启三台Linux机器:
reboot
4.2.3 每个节点安装Docker、kubeadm、kubelet和kubectl
4.2.3.1 安装Docker
- 安装Docker:
wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
yum -y install docker-ce
systemctl enable docker && systemctl start docker
docker version
- 设置Docker镜像加速器:
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"exec-opts": ["native.cgroupdriver=systemd"],
"registry-mirrors": ["https://du3ia00u.mirror.aliyuncs.com"],
"live-restore": true,
"log-driver":"json-file",
"log-opts": {"max-size":"500m", "max-file":"3"},
"storage-driver": "overlay2"
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
4.2.3.2 添加阿里云的YUM软件源
- 由于kubernetes的镜像源在国外,非常慢,这里切换成国内的阿里云镜像源:
cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
4.2.3.3 安装kubeadm、kubelet和kubectl
- 由于版本更新频繁,这里指定版本号部署:
yum install -y kubelet-1.22.4 kubeadm-1.22.4 kubectl-1.22.4
- 为了实现Docker使用的cgroup drvier和kubelet使用的cgroup drver一致,建议修改”/etc/sysconfig/kubelet”文件的内容:
vim /etc/sysconfig/kubelet
# 修改
KUBELET_EXTRA_ARGS="--cgroup-driver=systemd"
KUBE_PROXY_MODE="ipvs"
- 设置为开机自启动即可,由于没有生成配置文件,集群初始化后自动启动:
systemctl enable kubelet
4.2.4 查看k8s所需镜像
- 查看k8s所需镜像:
kubeadm config images list

4.2.5 部署k8s的Master节点
- 部署k8s的Master节点(192.168.24.31):
# 由于默认拉取镜像地址k8s.gcr.io国内无法访问,这里需要指定阿里云镜像仓库地址
kubeadm init \
--apiserver-advertise-address=192.168.24.31 \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.22.4 \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16


- 根据提示消息,在Master节点上使用kubectl工具:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
4.2.6 部署k8s的Node节点
- 根据提示,在192.168.24.32和192.168.24.33上添加如下的命令(token和discovery-token-ca-cert-hash在init完成后会提供相应的,请按照系统所给的来完成):
kubeadm join 192.168.24.31:6443 --token jv039y.bh8yetcpo6zeqfyj \
--discovery-token-ca-cert-hash sha256:3c81e535fd4f8ff1752617d7a2d56c3b23779cf9545e530828c0ff6b507e0e26

- 默认的token有效期为24小时,当过期之后,该token就不能用了,这时可以使用如下的命令创建token:
kubeadm token create --print-join-command
# 生成一个永不过期的token
kubeadm token create --ttl 0 --print-join-command
4.2.7 部署CNI网络插件
- 根据提示,在Master节点上使用kubectl工具查看节点状态:
kubectl get nodes

- kubernetes支持多种网络插件,比如flannel、calico、canal等,任选一种即可,本次选择flannel,如果网络不行,可以使用undefined.undefined,当然,也可以安装calico,请点这里undefined.undefined,推荐安装calico。
- 在Master节点上获取flannel配置文件(可能会失败,如果失败,请下载到本地,然后安装):
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
- 使用配置文件启动flannel:
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
- 查看部署CNI网络插件进度:
kubectl get pods -n kube-system

- 再次在Master节点使用kubectl工具查看节点状态:
kubectl get nodes

- 查看集群健康状况:
kubectl get cs

kubectl cluster-info

4.3 服务部署
4.3.1 前言
- 在Kubernetes集群中部署一个Nginx程序,测试下集群是否正常工作。
4.3.2 步骤
- 部署Nginx:
kubectl create deployment nginx --image=nginx:1.14-alpine
- 暴露端口:
kubectl expose deployment nginx --port=80 --type=NodePort
- 查看服务状态:
kubectl get pods,svc
4.4 kubernetes中kubectl命令自动补全
yum install -y bash-completion
source /usr/share/bash-completion/bash_completion
source <(kubectl completion bash)
echo “source <(kubectl completion bash)” >> ~/.bashrc
vim /root/.bashrc
source /usr/share/bash-completion/bash_completion
source <(kubectl completion bash)
4.5 启动系统防火墙并设置相应的规则
因为之前安装的时候关闭了系统防火墙,生产环境下需要启动系统防火墙
- 开启防火墙:
systemctl start firewalld
- 启动防火墙开机启动:
systemctl enable firewalld
k8s基础组件端口如下
举例:输入如下命令对31693端口进行放行
firewall-cmd --permanent --zone=public --add-port=31693/tcp
如果无法连接到一些微服务,可能是系统的防火墙端口未放行,也需要根据情况自行添加。
第五章
5.1 istio安装
5.1.1 下载istio
转到 Istio 发布 页面,下载针对你操作系统的安装文件, 或用自动化工具下载并提取最新版本:
curl -L https://istio.io/downloadIstio | sh -跳转到 Istio 包目录
cd istio-1.12.1安装目录包含:
- samples/ 目录下的示例应用程序
- bin/ 目录下的 istioctl 客户端二进制文件 .
- 将 istioctl 客户端加入搜索路径:
export PATH=$PWD/bin:$PATH5.1.2 安装istio
对于本次安装,我们采用 demo 配置组合。 选择它是因为它包含了一组专为测试准备的功能集合,另外还有用于生产或性能测试的配置组合。
给命名空间添加标签,指示 Istio 在部署应用的时候,自动注入 Envoy 边车代理:istioctl install --set profile=demo -ykubectl label namespace default istio-injection=enabled5.2 Bookinfo应用
Bookinfo 应用分为四个单独的微服务:
- productpage. 这个微服务会调用 details 和 reviews 两个微服务,用来生成页面。
- details. 这个微服务中包含了书籍的信息。
- reviews. 这个微服务中包含了书籍相关的评论。它还会调用 ratings 微服务。
- ratings. 这个微服务中包含了由书籍评价组成的评级信息。
reviews 微服务有 3 个版本:
- v1 版本不会调用 ratings 服务。
- v2 版本会调用 ratings 服务,并使用 1 到 5 个黑色星形图标来显示评分信息。
- v3 版本会调用 ratings 服务,并使用 1 到 5 个红色星形图标来显示评分信息。
下图展示了这个应用的端到端架构。
Bookinfo Application without Istio
Bookinfo 应用中的几个微服务是由不同的语言编写的。 这些服务对 Istio 并无依赖,但是构成了一个有代表性的服务网格的例子:它由多个服务、多个语言构成,并且 reviews 服务具有多个版本。
5.2.1 启动应用
- 进入 Istio 安装目录。
Istio 默认自动注入 Sidecar. 请为 default 命名空间打上标签 istio-injection=enabled:
$ kubectl label namespace default istio-injection=enabled使用 kubectl 部署应用:
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml上面的命令会启动全部的四个服务,其中也包括了 reviews 服务的三个版本(v1、v2 以及 v3)。
确认所有的服务和 Pod 都已经正确的定义和启动:
kubectl get services kubectl get pods要确认 Bookinfo 应用是否正在运行,请在某个 Pod 中用 curl 命令对应用发送请求,例如 ratings
kubectl exec -it $(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}') -c ratings -- curl productpage:9080/productpage | grep -o "<title>.*</title>"5.2.2 设置目标规则
在使用 Istio 控制 Bookinfo 版本路由之前,您需要在目标规则中定义好可用的版本,命名为 subsets ```yaml destination-rule-all.yaml apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: productpage spec: host: productpage subsets:
- name: v1 labels: version: v1
apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: reviews spec: host: reviews subsets:
- name: v1 labels: version: v1
- name: v2 labels: version: v2
- name: v3 labels: version: v3
apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: ratings spec: host: ratings subsets:
- name: v1 labels: version: v1
- name: v2 labels: version: v2
- name: v2-mysql labels: version: v2-mysql
- name: v2-mysql-vm labels: version: v2-mysql-vm
apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: details spec: host: details subsets:
- name: v1 labels: version: v1
- name: v2 labels: version: v2
**运行以下命令为 Bookinfo 服务创建的默认的目标规则:**
```yaml
kubectl apply -f samples/bookinfo/networking/destination-rule-all.yaml
5.2.3 对外开放应用程序
此时,BookInfo 应用已经部署,但还不能被外界访问。 要开放访问,你需要创建 Istio 入站网关(Ingress Gateway), 它会在网格边缘把一个路径映射到路由。
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: bookinfo-gateway
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- "*"
gateways:
- bookinfo-gateway
http:
- match:
- uri:
exact: /productpage
- uri:
prefix: /static
- uri:
exact: /login
- uri:
exact: /logout
- uri:
prefix: /api/v1/products
route:
- destination:
host: productpage
port:
number: 9080
把应用关联到 Istio 网关:
kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml确保配置文件没有问题:
istioctl analyze5.3 流量管理
Istio Bookinfo 示例包含四个独立的微服务,每个微服务都有多个版本。其中一个微服务 reviews 的三个不同版本已经部署并同时运行。
要仅路由到一个版本,请应用为微服务设置默认版本的 Virtual Service。在这种情况下,Virtual Service 将所有流量路由到每个微服务的 v1 版本。
virtual-service-all-v1.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: productpage
spec:
hosts:
- productpage
http:
- route:
- destination:
host: productpage
subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- route:
- destination:
host: ratings
subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: details
spec:
hosts:
- details
http:
- route:
- destination:
host: details
subset: v1
---
运行以下命令以应用 Virtual Service:
kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml
使用以下命令显示已定义的路由:
kubectl get virtualservices -o yaml
5.3.2 基于用户身份的路由
在这种情况下,来自名为 Jason 的用户的所有流量将被路由到服务 reviews:v2。
请注意,Istio 对用户身份没有任何特殊的内置机制。事实上,productpage 服务在所有到 reviews 服务的 HTTP 请求中都增加了一个自定义的 end-user 请求头,从而达到了本例子的效果。
virtual-service-reviews-test-v2.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- match:
- headers:
end-user:
exact: Jason
route:
- destination:
host: reviews
subset: v2
- route:
- destination:
host: reviews
subset: v1
运行以下命令以启用基于用户的路由
kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml确认规则已创建:
kubectl get virtualservice reviews -o yaml在 Bookinfo 应用程序的 /productpage 上,以用户 jason 身份登录。刷新浏览器。您看到了什么?星级评分显示在每个评论旁边。
以其他用户身份登录(选择您想要的任何名称)。刷新浏览器。现在星星消失了。这是因为除了 Jason 之外,所有用户的流量都被路由到 reviews:v1。
5.3.3 流量转移
在 Istio 中,您可以通过配置一系列规则来实现此目标。这些规则将一定比例的流量路由到一个或另一个服务。在本任务中,您将会把 50% 的流量发送到 reviews:v1,另外,50% 的流量发送到 reviews:v3。接着,再把 100% 的流量发送到 reviews:v3 来完成迁移。
virtual-service-reviews-50-v3.yaml apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: reviews spec: hosts: - reviews http: - route: - destination: host: reviews subset: v1 weight: 50 - destination: host: reviews subset: v3 weight: 50使用下面的命令把 50% 的流量从 reviews:v1 转移到 reviews:v3:
kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-50-v3.yaml刷新浏览器中的 /productpage 页面,大约有 50% 的几率会看到页面中带 红色 星级的评价内容。这是因为 reviews 的 v3 版本可以访问带星级评价,但 v1 版本不能。
5.3.4 安全网关
生成客户端和服务器证书和密钥
创建用于服务签名的根证书和私钥:
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example.com.key -out example.com.crt为 httpbin.example.com 创建证书和私钥:
openssl req -out httpbin.example.com.csr -newkey rsa:2048 -nodes -keyout httpbin.example.com.key -subj "/CN=httpbin.example.com/O=httpbin organization" openssl x509 -req -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 0 -in httpbin.example.com.csr -out httpbin.example.com.crt配置单机TLS入口网关
为 Ingress Gateway 创建 Secret:
kubectl create -n istio-system secret tls httpbin-credential --key=httpbin.example.com.key --cert=httpbin.example.com.crt为端口443定义一个带有 servers: 部分的网关,并将 credentialName 的值指定为 httpbin-credential。这些值与 Secret 名称相同。 TLS 模式的值应为 SIMPLE。
cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: mygateway spec: selector: istio: ingressgateway # use istio default ingress gateway servers: - port: number: 443 name: https protocol: HTTPS tls: mode: SIMPLE credentialName: httpbin-credential # must be the same as secret hosts: - httpbin.example.com EOF配置网关的入口流量路由,定义相应的虚拟服务。
cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: httpbin spec: hosts: - "httpbin.example.com" gateways: - mygateway http: - match: - uri: prefix: /status - uri: prefix: /delay route: - destination: port: number: 8000 host: httpbin EOF发送 HTTPS 请求访问 httpbin 服务:
curl -v -HHost:httpbin.example.com --resolve "httpbin.example.com:$SECURE_INGRESS_PORT:$INGRESS_HOST" \ --cacert example.com.crt "https://httpbin.example.com:$SECURE_INGRESS_PORT/status/418"删除网关的 secret,并创建一个新的 secret 来修改入口网关的凭据。
kubectl -n istio-system delete secret httpbin-credentialmkdir new_certificates openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout new_certificates/example.com.key -out new_certificates/example.com.crt openssl req -out new_certificates/httpbin.example.com.csr -newkey rsa:2048 -nodes -keyout new_certificates/httpbin.example.com.key -subj "/CN=httpbin.example.com/O=httpbin organization" openssl x509 -req -days 365 -CA new_certificates/example.com.crt -CAkey new_certificates/example.com.key -set_serial 0 -in new_certificates/httpbin.example.com.csr -out new_certificates/httpbin.example.com.crt kubectl create -n istio-system secret tls httpbin-credential \ --key=new_certificates/httpbin.example.com.key \ --cert=new_certificates/httpbin.example.com.crtcurl 使用新证书链访问 httpbin 服务:
curl -v -HHost:httpbin.example.com --resolve "httpbin.example.com:$SECURE_INGRESS_PORT:$INGRESS_HOST" \ --cacert new_certificates/example.com.crt "https://httpbin.example.com:$SECURE_INGRESS_PORT/status/418"如果使用先前的证书链访问httpbin,将返回失败。
curl -v -HHost:httpbin.example.com --resolve "httpbin.example.com:$SECURE_INGRESS_PORT:$INGRESS_HOST" \ --cacert example.com.crt "https://httpbin.example.com:$SECURE_INGRESS_PORT/status/418"


