K8s 基石下的云原生微服务实践

点击上方蓝色字体,选择“设为星标”

回复”云原生“获取基础架构实践

935f7cc3e2c73f02263049c67816745b.jpeg

前言

微服务架构已经火了很多年了,如:Dubbo、Spring Cloud,再到后来的 Spring Cloud Alibaba,但都是仅限于 Java 语言的瓶颈,如何让各种语言之间的微服务更加有效、快速的通讯,这是当前很多企业需要面临的问题,因为一个企业中,不只是基于单纯的某一种语言开发,这就涉及到多语言服务之间的访问。以 Kubernetes(k8s) 为核心的容器技术掀起的云原生浪潮仍在席卷全球,在轰轰烈烈的数字化转型技术变革中,先行者们开始思考新的技术体系究竟能给行业与社会带来什么,以及如何把 DevOps 等先进的开发管理模型带入各行各业,让更多的企业享受到云原生以及 AI、IoT 等前沿技术革新带来的红利。本专栏的创作重点,则是在于讲述在巨多语言的情况下,该如何设计微服务架构,以及云原生时代的微服务的高可用、自动化等等。

微服务架构

微服务发展史

在微服务到来之前,一切都是单个服务,当然单体应用程序的存在,暴露的缺点也是不少的,主要有:

  • 复杂性高

  • 团队协作开发成本高

  • 扩展性差

  • 部署效率低下

  • 系统很差的高可用性

复杂性,体现在:随着业务的不断迭代,项目的代码量急剧的增多,项目模块也会随着而增加,整个项目就会变成的非常复杂。

开发成本高,体现在:团队开发几十个人在修改代码,然后一起合并到同一地址分支,打包部署,测试阶段只要有一小块功能有问题,就得重新编译打包部署,重新测试,所有相关的开发人员都得参与其中,效率低下,开发成本极高。

扩展性差,体现在:在新增功能业务的时候,代码层面会考虑在不影响现有的业务基础上编写代码,提高了代码的复杂性。

部署效率低,体现在:当单体应用的代码越来越多,依赖的资源越来越多时,应用编译打包、部署测试一次,需要花费的时间越来越多,导致部署效率低下。

高可用差,体现在:由于所有的业务功能最后都部署到同一个文件,一旦某一功能涉及的代码或者资源有问题,那就会影响到整个文件包部署的功能。举个特别鲜明的示例:上世纪八、九十年代,很多的黄页以及延伸到后来的网站中,很多的展示页面与获取数据的后端都是在一个服务模块中。这就造成一个很不好的影响:如果只是修改极小部分的页面展示或图片展示,则需要把整个服务模块进行打包部署,这样会导致时间的严重浪费以及成本的增加。更加糟糕的是,给用户带来非常不好的体验,用户无法理解的是:只是换个网站的某块微小的展示区,导致了整个网站在那一时刻无法正常的访问。当然,也许,对于那个时候互联网的不发达,人们对于这样的体验,已经算是一种幸福的享受了。

由于单体应用具有以上的种种缺点,导致了一个新名词、新概念的诞生——微服务

其实,从早年间的单体应用,到 2014 年起,得益于以 Docker 为代表的容器化技术的成熟以及 DevOps 文化的兴起,服务化的思想进一步演化,演变为今天我们所熟知的微服务。那么,微服务到底是啥?

微服务,英文名:microservice,百度百科上将其定义为:SOA 架构的一种变体。微服务(或微服务架构)是一种将应用程序构造为一组低耦合的服务。

微服务有着一些鲜明的特点:

  • 功能单一

  • 服务粒度小

  • 服务间独立性强

  • 服务间依赖性弱

  • 服务独立维护

  • 服务独立部署

微服务将原来耦合在一起的复杂业务拆分为单个服务,规避了原本复杂度无止境的积累,每一个微服务专注于单一功能,并通过定义良好的接口清晰表述服务边界。

由于微服务具备独立的运行进程,所以每个微服务可以独立部署。当业务迭代时只需要发布相关服务的迭代即可,降低了测试的工作量同时也降低了服务发布的风险。

在微服务架构下,当某一组件发生故障时,故障会被隔离在单个服务中。如通过限流、熔断等方式降低错误导致的危害,保障核心业务的正常运行。

微服务发展到现在,带有以下标志:高内聚、低耦合以业务为中心自治和高可用

微服务划分的粒度

服务的划分,可以从水平的功能划分,也可从垂直的业务划分,粒度的大小,可以根据当前的产品需求来定位,最关键的是要做到:高内聚、低耦合

如电商系统为例,如下图:

38922747b1d95239a9d2f832b0e27559.png
电商系统架构图

电商中涉及到业务很可能是最多的,商品、库存、订单、促销、支付、会员、购物车、发票、店铺等等,这个是根据业务的不同来进行模块的划分。微服务划分的粒度一定是要有明确性的,不能因为含糊而新增一个服务模块,这样会导致功能接口的可复用性差。一个好的架构设计,肯定是可复用性很强的结构模式。我喜欢这样的一句话:**微服务的边界 (粒度) 是 "决策", 而不是个 "标准答案"**。即应该将各微服务划分的方式,深度思考,周全的考量各方面的因素下,所作出的一个”最适合”的架构决策,而不是一个人芸亦芸的”标准答案“。

容器化技术

什么是容器

什么是容器呢?自然界的解释:容器是指用以容纳物料并以壳体为主的基本装置。但今天讲的容器也是一个容纳物质的载体。那计算机所指的容器(Container)到底是什么呢?容器是镜像(Image)的运行时实例。正如从虚拟机模板上启动 VM 一样,用户也同样可以从单个镜像上启动一个或多个容器。虚拟机和容器最大的区别是容器更快并且更轻量级,与虚拟机运行在完整的操作系统之上相比,容器会共享其所在主机的操作系统/内核。

为什么要用容器呢?假设你在使用一台电脑开发一个应用,而且开发环境具有特定的配置。其他开发人员身处的环境配置可能稍有不同。你正在开发的应用不止依赖于您当前的配置,还需要某些特定的库、依赖项和文件。与此同时,你的企业还拥有标准化的开发和生产环境,有着自己的配置和一系列支持文件。你希望尽可能多在本地模拟这些环境,而不产生重新创建服务器环境的开销。这时候,就会需要容器来模拟这些环境。

我们常见的容器启动方式是 Docker,Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何 Linux 机器上,也可以实现虚拟化。

5ba76d67adfd6c5da19a48467010b471.jpeg
Kubernetes

Google 多年来一直使用容器作为交付应用程序的一种重要方式,且运行有一款名为 Borg 的编排工具。Google、RedHat 等公司为了对抗以 Docker 公司为核心的容器商业生态,他们一起成立了 CNCF(Cloud Native Computing Foundation)。当谷歌于 2014 年 3 月开始开发 Kubernetes 时,很明智的选择当时最流行的容器,没错,就是 Docker。Kubernetes 对 Docker 容器运行时的支持,迎来了大量的使用用户。Kubernetes 于 2014 年 6 月 6 日首次发布。这便有了容器编排工具 Kubernetes 的诞生。另外,CNCF 的目的是以开源的 K8S 为基础,使得 K8S 能够在容器编排方面能够覆盖更多的场景,提供更强的能力。K8S 必须面临 Swarm 和 Mesos 的挑战。Swarm 的强项是和 Docker 生态的天然无缝集成,Mesos 的强项是大规模集群的管理和调度。K8S 是 Google 基于公司已经使用了十多年的 Borg 项目进行了沉淀和升华才提出的一套框架。它的优点就是有一套完整的全新的设计理念,同时有 Google 的背书,而且在设计上有很强的扩展性,所以,最终 K8S 赢得了胜利,成为了容器生态的行业标准。

K8s 为什么会成为微服务的基础架构

为什么 K8s 是下一代微服务架构基础

微服务出现后,同样面临着一个重要的话题:高可用。所谓高可用:英文缩写 HA(High Availability),是指当某个服务或服务所在节点出现故障时,其对外的功能可以转移到该服务其他的副本或该服务在其他节点的副本,从而在减少停工时间的前提下,满足业务的持续性,这两个或多个服务构成了服务高可用。同时,这种高可用需要考虑到服务的性能压力,即服务的负载均衡。

我们知道对于服务的高可用,或者说服务的负载来说,有很多方式来解决这些问题。比如:

  • 主从方式,其工作原理是:主机处于工作状态,备机处于监控、准备状态,当主机出现宕机的情况下,备机可以接管主机的一切工作,等到主机恢复正常后,将会手动或自动的方式将服务切换到主机上运行,数据的一致性通过共享存储来实现。

  • 集群方式,其工作原理是:多台机器同时运行一个或几个服务,当其中的某个节点出现宕机时,这时该节点的服务将无法提供业务功能,可以选择根据一定的机制,将服务请求转移到该服务所在的其他节点上,这样可以让逻辑持续的执行下去,即消除软件单点故障。这其实就涉及到负载均衡策略。

对于微服务的高可用,涉及到的其中一个就是其服务的负载均衡。在微服务中,负载均衡的前提是,同一个服务需要被发现多个,或者说多个副本,这样才能实现负载均衡以及服务的高可用。

同时,服务发现后,其实面临的是一个主要的问题就是应该访问哪一个?因为发现了某个服务的多个实例,最终只会访问其中某一个,这就涉及到服务的负载均衡了。

负载均衡在微服务中是一个很常见的话题,实现负载均衡的插件也越来越多。netflix 开源的 Zuul、Gateway 等等。

但这样的微服务,带来的好处就是高度自治,但同时也会带来一定的副作用:所用到的技术栈太过复杂,整个系统看起来很繁重。

K8s 是如何解决这些问题的呢?在 K8s 中提供了一套服务注册与发现的机制:Kubernetes 为服务和 Pod 创建 DNS 记录。您可以使用一致的 DNS 名称而不是 IP 地址联系服务。集群中定义的每个服务(包括 DNS 服务器本身)都分配了一个 DNS 名称。默认情况下,客户端 Pod 的 DNS 搜索列表包括 Pod 自己的命名空间和集群的默认域。DNS 查询可以使用 pod 的 /etc/resolv.conf. Kubelet 为每个 pod 设置这个文件。例如,对查询 data 可以扩展为 test.default.svc.cluster.local。该 search 选项的值用于扩展查询:

apiVersion: v1
kind: Service
metadata:
  name: test
spec:
  selector:
    app: MyApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

该规范创建了一个名为“test”的新服务对象,其目标是任何带有 app=MyApp 标签的 Pod 上的 TCP 端口 9376 。

同时,K8s 提供一种资源 Configmap,可以编写一个 spec 引用 ConfigMap 的 Pod ,并根据 ConfigMap 中的数据配置该 Pod 中的容器。Pod 和 ConfigMap 必须在同一个命名空间:

kind: ConfigMap
apiVersion: v1
metadata:
  name: rest-service
  namespace: system-server
data:
  application.yaml: |-
    greeting:
      message: Say Hello to the World
    ---
    spring:
      profiles: dev
    greeting:
      message: Say Hello to the Developers
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值