后端架构师必知必会系列:容器编排与服务注册

发布于:2023-09-27 ⋅ 阅读:(96) ⋅ 点赞:(0)

作者:禅与计算机程序设计艺术

1.简介

在互联网开发中,无论前端、后端或者移动端都需要用到各种各样的工具进行开发和部署,这些工具往往都是开源免费的。在这些开源工具中,一个重要的角色就是用来做容器编排与服务发现的工具。今天,我将通过对容器编排与服务注册这两个关键技术的阐述和剖析,给大家带来一份实用的技术博客。

作为一名后端工程师,本文旨在帮助读者了解什么是容器编排(Orchestration)、为什么要使用它?以及如何使用一些常见的开源编排工具如Kubernetes、Docker Swarm等。同时,文章还将介绍这些工具如何与分布式系统中的其他组件集成,比如服务注册中心。

阅读完本文,你还可以掌握以下知识点:

1.理解容器编排是什么,为什么要使用它,以及哪些编排工具比较流行;

2.知道什么是Kubernetes、Docker Swarm等开源编排工具,它们之间有什么不同,并能够比较方便地对比其特性和优缺点;

3.了解编排工具的基本配置方式,能够快速上手使用编排工具;

4.了解服务注册中心是什么,以及为什么要使用它;

5.学习到如何在现有的基础设施中部署和管理编排工具,并最终打造出可靠的生产环境。

6.能够用最简单的话术向同龄人传达自己的理解,并且借助图表、表格、插图等形式,为人们提供更加直观的学习体验。

2.基本概念术语说明

2.1 什么是容器编排

容器编排(Orchestration)是一个定义良好的任务,能够自动化执行管理平台上的应用程序部署、扩展和维护的过程。它提供了一种用于资源调配和编排容器化工作负载的抽象层,使得容器部署在一个集群或服务器组上变得透明和易于管理。它主要解决的问题包括:

1.资源管理:自动分配计算资源、存储资源、网络资源;

2.服务发现与负载均衡:动态发现容器、虚拟机或机器所提供的服务;

3.配置管理:集中管理容器配置信息,实现一致性;

4.自我修复能力:在节点故障时,自动重启容器或迁移应用副本;

5.可伸缩性:根据业务需求自动扩容或缩容集群规模;

6.弹性可靠性:确保应用运行中出现故障时,自动进行回滚或容错处理。

2.2 为什么要使用容器编排

使用容器编排最显著的原因就是可以简化开发流程。由于容器不再依赖于主机操作系统,因此在不同的环境下部署相同的应用程序变得更加容易。而且,容器编排还具有如下几个好处:

1.资源共享:容器间共享宿主机内核,节省资源,提升性能;

2.弹性伸缩:当容器集群中的容器资源超过预期时,自动添加更多容器,提高可用性;

3.敏捷发布:只需更新镜像,即可快速发布新版本应用;

4.无状态服务:容器化的微服务可以实现无状态服务的部署和水平扩展;

5.跨数据中心部署:可以在多个数据中心之间复制容器集群,实现业务连续性。

2.3 什么是Kubernetes

Kubernetes(k8s),它是一个开源的,用于自动化容器部署、扩展和管理的容器集群管理系统。它的前身是 Google 公司内部使用的Borg系统,随着时间的推移,Kubernetes越来越受欢迎。它是一个基于容器的集群管理系统,能够自动部署、扩展和管理容器化的应用,支持动态弹性伸缩、横向扩展,并提供全面的监控和日志记录功能。

2.4 Kubernetes的优点

1.自动部署、扩展和管理:Kubernetes 提供了声明式 API,让用户可以通过简单的命令或者 YAML 文件来描述所需的部署内容,然后 Kubernetes 会自动完成部署和管理工作;

2.服务发现和负载均衡:Kubernetes 能够根据实际情况动态发现服务,并且支持多种负载均衡策略;

3.资源分配和管理:Kubernetes 可以针对每个容器指定 CPU 和内存的请求量和限制,并且会自动为容器调配资源;

4.健康检查和滚动升级:Kubernetes 支持对部署的容器进行健康检查,当检测失败时,会自动停止并重启容器;

5.持久存储:Kubernetes 提供了一套完整的存储方案,包括本地存储、云端存储和网络文件系统 (NFS) ,并且支持多种卷类型,包括 ConfigMap、Secret、PersistentVolumeClaim、StorageClass、CSI 插件等;

6.弹性伸缩:Kubernetes 提供了 horizonal pod autoscaling (HPA) 机制,可以根据应用负载变化自动调整 Pod 的数量,这对部署海量容器应用非常有用;

7.密钥和证书管理:Kubernetes 提供了一套密钥和证书管理机制,可以自动生成、更新和分发 TLS 凭证和私钥,这对于 HTTPS 服务来说尤为重要;

8.存储调度:Kubernetes 可以利用存储类(StorageClass)来选择适合 Pod 使用的存储,这极大的提高了灵活性和可用性;

9.监控和日志:Kubernetes 提供了一整套监控和日志解决方案,包括 Prometheus、Heapster、Fluentd、EFK Stack、 Elasticsearch、 Kibana 等,可以帮助集群管理员收集和分析集群运行状态、监控集群中容器的资源使用率和异常行为,并通过统一的日志查看系统快速定位问题。

2.5 Docker Swarm

另一种类似的编排工具叫做 Docker Swarm。它也是 Docker 公司推出的一种编排工具,用于在 Docker 引擎(CE 或 EE)上构建和管理容器集群。虽然 Docker Swarm 和 Kubernetes 有很多相似之处,但也有一些不同之处。比如,Kubernetes 更注重于长期稳定性和生产环境的要求,而 Docker Swarm 更加关注轻量级、实验性质的应用场景。

总的来说,Kubernetes 是当前最主流的开源容器编排工具,已经成为容器管理领域事实上的标准。

3.核心算法原理和具体操作步骤以及数学公式讲解

3.1 编排系统概览

作为容器编排系统的入口,Kubernetes集群的架构由两部分组成。第一部分是控制面板,也就是API Server和etcd数据库。API Server接收客户端提交的RESTful API请求,并验证调用者身份。第二部分是数据面板,由三个主要组件构成。第一个组件是调度器(Scheduler),它负责决定将Pod调度到哪个节点上。第二个组件是控制器(Controller),它对集群的当前状态进行监控,并确保集群处于预期的状态。第三个组件是节点(Node),它是集群的基础,每个节点都会运行 kubelet 代理来管理容器。

整个系统的工作流程可以总结为以下四个步骤:

1.用户提交定义Pod的YAML文件,发送至API Server;

2.API Server将Pod的定义转换成集群内部的对象资源,并保存至etcd数据库;

3.调度器监听Pod创建事件,并根据当前集群状态及Pod资源需求,决定将Pod调度到哪个节点上;

4.控制器监听Pod调度事件,并根据集群状态和当前定义的控制器规则,完成集群的管理。控制器会对集群进行各种维度的指标监控,并根据当前集群状态和集群定义的期望值,修改集群中的资源。

3.2 Kubernetes工作原理详解

3.2.1 对象模型

Kubernetes对集群中的对象进行抽象,将集群的状态建模为一组资源,这些资源被序列化存储至etcd数据库中。资源由三部分组成:

1.Metadata:元数据信息,用于标识和分类对象;

2.Specification:定义了对象的属性和特征,它是一个键值对的集合;

3.Status:状态信息,反映了对象的最新状态。

例如,一个Pod资源的Metadata可能包含名称、标签和命名空间等信息;而其Specification包含Pod的镜像名称、启动命令、端口等信息;它的Status则包含Pod的实际运行状态、主机IP地址、容器状态等信息。

3.2.2 Control Plane组件

Kubernetes的控制面板由API Server、Scheduler和Controller Manager三个组件组成。

API Server

API Server是Kubernetes的入口,所有集群内交互都需要经过它。它是一个RESTful HTTP服务器,对外提供API接口,接收并处理外部请求。它的主要职责包括:

1.存储集群资源:API Server 负责将集群内部的对象资源存储至etcd数据库中;

2.集群认证与鉴权:API Server 对每一次请求进行认证和鉴权,判断是否有权限对该资源进行访问;

  1. RESTful API:API Server 提供了一组RESTful API,对外提供集群资源的增删改查操作。
Scheduler

Scheduler是一个独立的组件,主要负责决定将Pod调度到哪个节点上。它监听Pod创建事件,并根据当前集群状态及Pod资源需求,决定将Pod调度到哪个节点上。为了实现这个目标,Scheduler会考虑集群中各项资源的容量,以及各个节点上的Pod的利用率、QoS保证等因素。

Controller Manager

Controller Manager是一个独立的守护进程,管理着集群中的控制器。它的主要职责包括:

1.管理控制器的生命周期:控制器通常会周期性地对集群资源进行检查和重新同步;

2.提供集群范围内的共识:控制器会协同工作,确保集群处于预期的状态;

3.触发扩展事件:控制器在集群资源满足预期后,可能会触发扩容、回收等扩展事件。

3.2.3 Kubernetes组件的通信机制

Kubernetes中各个组件之间存在很多的相互依赖关系,因此它们之间的通信机制也非常重要。Kubernetes采用了基于RESTful HTTP协议的远程通信机制。除此之外,还有两种常见的通信机制:

1.Endpoint(EndpointSlice):Endpoint 是 Kubernetes 用来对 Service 提供服务的一种抽象。每个 Endpoint 代表 Kubernetes 集群中某个具体的服务 IP 和端口的组合,表示了 Service 的一个可用端点。EndpointSlice 是集群内服务地址列表的聚合,包含了每个 Service 的 Endpoints 集合。这个机制可以提高 Service 的可用性和减少网络开销。

2.CRD:Custom Resource Definition(CRD)是 Kubernetes 提供的一种扩展机制,允许用户创建自定义的资源类型。Kubelet 只会在运行时才会感知 CRD,不会影响其他 Kubernetes 组件。目前 Kubernetes 中支持的 CRD 类型有 Deployment、ReplicaSet、StatefulSet、DaemonSet、Job、CronJob、Ingress、Service、Endpoints、ConfigMap、Secret 等。

3.2.4 网络插件

Kubernetes提供的网络模型是建立在 CNI(Container Network Interface)规范之上的,CNI 定义了容器的网络模型和配置方法。Kubernetes 集群中的所有 Pod 在创建的时候,都需要绑定一个唯一的网络命名空间,因此 Kubernetes 中的网络插件一般会创建一个新的命名空间,通过 CNI 配置 Pod 的网络接口。

Kubernetes默认情况下并没有启用任何网络插件,只能使用kubenet这种手动创建网络的方式。另外,如果需要为容器设置固定 IP 地址,可以使用 Weave Net 这样的网络插件。Weave Net 是由 weaveworks 团队开发的一款开源网络插件。

4.具体代码实例和解释说明

通过上述的介绍,读者应该对容器编排系统有了一个初步的了解,下面我们结合例子,来进一步熟悉一下Kubernetes的使用。假设有一个应用,它的功能是接收HTTP请求,并返回相应的内容。这个应用的Dockerfile如下:

FROM python:3.7-slim
WORKDIR /app/
COPY../
CMD ["python", "server.py"]

这个应用使用的Python版本为3.7-slim。我们准备了一个名为configmap.yaml的文件,其中包含了一个名为config.ini的文件,里面有一个参数message,值为"Hello World!"。这个文件的作用是在容器启动时读取配置文件的内容。

我们准备了一个名为deployment.yaml的文件,其中包含一个Deployment资源定义。该资源定义指定了镜像名称(python:3.7-slim)、启动命令(python server.py)、Pod模板(从Dockerfile生成)、副本数(3)等。这里需要注意的是,要把configmap.yaml的名字写入Deployment的volumes部分,这样就可以将配置文件映射到Pod里了。Deployment资源定义的代码如下:

apiVersion: apps/v1beta2 # for versions before 1.9.0 use apps/v1beta1
kind: Deployment
metadata:
  name: my-webservice
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-webservice
  template:
    metadata:
      labels:
        app: my-webservice
    spec:
      containers:
      - image: python:3.7-slim
        name: webservice
        command: [ "python", "server.py" ]
        ports:
          - containerPort: 5000
            protocol: TCP
        volumeMounts:
        - name: config-volume
          mountPath: "/etc/config/"
      volumes:
      - name: config-volume
        configMap:
          name: my-config-map
---
apiVersion: v1
data:
  message: Hello World!
kind: ConfigMap
metadata:
  name: my-config-map

这个例子中,我们创建了一个Deployment资源,指定了镜像名称为python:3.7-slim,启动命令为python server.py,Pod模板中包含一个容器,容器名为webservice。我们把配置文件/etc/config/挂载到了容器内,并使用ConfigMaps来管理配置文件。由于配置文件的内容是固定的,所以我们只需要创建一个单独的配置文件即可。

最后,我们准备了一个service.yaml文件,其中包含一个Service资源定义。该资源定义指定了服务类型(ClusterIP)、端口映射(5000->5000)、选择器(使用Deployment的标签选择Pod)。Service资源定义的代码如下:

apiVersion: v1
kind: Service
metadata:
  name: my-webservice
spec:
  type: ClusterIP
  ports:
  - port: 5000
    targetPort: 5000
  selector:
    app: my-webservice

这段代码创建一个名为my-webservice的Service资源,类型为ClusterIP,端口映射为5000->5000。选择器使用Deployment的标签选择Pod。

最后,把以上三个文件合并成一个yaml文件,放在一起,并命名为all-in-one.yaml,然后保存到本地。接下来,我们就可以通过kubectl命令来部署我们的应用了,命令如下:

$ kubectl create -f all-in-one.yaml
deployment.apps/my-webservice created
service/my-webservice created

上面命令创建了一个Deployment资源,指定的镜像名称为python:3.7-slim,启动命令为python server.py,副本数为3,使用了名为my-config-map的ConfigMap资源,将/etc/config/目录挂载到了容器内。然后创建一个名为my-webservice的Service资源,类型为ClusterIP,端口映射为5000->5000,选择器使用Deployment的标签选择Pod。

然后,我们可以通过访问http://<node_ip>:<node_port>的方式来测试我们的应用是否正常工作。具体的访问地址取决于Kubernetes集群的部署环境,可能是localhost:3000110.10.0.2:30002192.168.1.10:30003等。由于我们创建了一个Deployment资源,所以Kubernetes会自动创建3个Pod实例,并通过Service暴露服务。通过浏览器打开访问地址,页面上应该显示Hello World!这个字符串。


网站公告

今日签到

点亮在社区的每一天
去签到