基于Kubernetes和Docker构建微服务之路

随着本文逐步学习使用Kubernetes开源平台和Docker创建用于构建微服务的持续交付配置。

在我之前的一篇文章中,描述了一个用Docker和Jenkins构建微服务的持续交付配置的例子。 这是一个简单的配置,只使用Docker Pipeline Plugin来构建和运行带有微服务的容器。 这个解决方案有一个很大的缺点 - 我们不得不链接所有的容器,以提供部署在这些容器内的微服务之间的通信。 今天,我将向您展示一个聪明的解决方案,帮助我们避免这个问题 - Kubernetes。

原理

Kubernetes是一个最初是由Google设计的开源平台,用于在主机集群之间自动部署、扩展和运行应用程序容器,提供以容器为中心的基础架构。 它具有许多对于在生产中运行的应用程序特别有用的功能,如服务命名和发现、负载均衡、应用程序运行状况检查、横向弹性伸缩和滚动更新等。 在进入例子之前,我们应该知道Kubernetes的几个重要概念。

Pod - Kubernetes的基本单元。 它可以由一个或多个容器组成,这些容器在同一个物理主机内,并共享相同的资源。 在pod内部署的所有容器都可以通过localhost看到其他容器。 每个Pod在集群中具有唯一的IP地址。

Service - 一组一起工作的Pod。 默认情况下,Service在集群内部公开,但也可以暴露在集群外部的外部IP地址上。 我们可以使用以下四种方式之一来暴露它:ClusterIP、NodePort、LoadBalancer和ExternalName。

Replication Controller (RC)- 一种特定类型的Kubernetes控制器。 它通过在集群中运行指定数目的pod副本来处理复制和扩展。 如果底层节点发生故障,它也负责替换失败Pod。

Kubernetes集群的高可用配置不是一件容易的任务。 幸运的是,有一个工具可以让本地运行Kubernetes更简单 - Minikube。 Minikube可以在虚拟机内部运行单节点集群,这对于想要尝试的开发人员来说非常重要。 开始真的很简单,对于Windows上的例子,您必须下载minikube.exe和kubectl.exe,并将它们添加到PATH环境变量中。 然后,您可以使用minikube start命令从命令行启动它,并通过调用kubectl命令来使用几乎所有的Kubernetes功能。 命令行选项的另一种选择是Kubernetes Dashboard。 它可以通过调用minikube仪表板命令启动。 我们可以从UI仪表板创建,更新或删除部署,还可以列出并查看所有Pod、Service、Ingress、RC等的配置。如下图所示是Kubernetes Dashboard,其中包含例子的部署列表:

应用

我们的例子中的微服务体系结构的概念与我在本文开头提到的有关Docker和Jenkins的持续交付的文章中的概念非常相似。 例子也有Account和Customer的微服务, Customer Service在搜索Customer帐户的同时与Customer Service进行交互。 我们不使用网关(Zuul)和发现(Eureka)Spring Boot服务,因为我们在Kubernetes中内置这些机制。 这是一张图解说明所提出解决方案的架构。 每个微服务的pod由两个容器组成:第一个是微服务应用程序,第二个是Mongo数据库。 Account和Customer的微服务都有自己的数据库存储所有的数据。 每个Pod都是作为服务暴露的,并且可以通过在Kubernetes上的名字进行搜索。 我们还配置Kubernetes Ingress,它充当我们微服务的网关。

此例子的源代码在GitHub上提供。 它由两个模块组成:Account Service和Customer Service。 它基于Spring Boot框架,但不使用除Feign客户端之外的任何Spring云项目。 这里是Account Service的dockerfile。 我们使用一个小的openjdk image - alpine。 因此,使用标准的openjdk作为base image时,我们的结果image大约有120MB而不是〜650MB。

FROM openjdk:alpine

ADD target/account-service.jar account-service.jar

ENTRYPOINT ["java", "-jar", "/account-service.jar"]

EXPOSE 2222

为了启用MongoDB支持,我将spring-boot-starter-data-mongodb依赖关系添加到了pom.xml中。 我们还必须提供连接数据到application.yml并用@Document注释实体类。 最后,声明存储库接口扩展MongoRepository,其中实现了基本的CRUD方法。 我们添加两个自定义查找方法:

public interface AccountRepository extends MongoRepository {

public Account findByNumber(String number);

public List findByCustomerId(String customerId);

}

在Customer Service中,我们打算从Account Service调用API方法。 这是声明式REST客户端@FeignClient声明。 所有具有Account Service的Pod在服务名称和默认服务端口2222下均可用。此类设置是Kubernetes上服务配置的结果。 我将在下一节中对其进行描述。

@FeignClient(name = "account-service", url = "http://account-service:2222")

public interface AccountClient {

@RequestMapping(method = RequestMethod.GET, value = "/accounts/customer/")

List getAccounts(@PathVariable("customerId") String customerId);

}

我们的微服务的docker image可以使用下面的命令来构建。 构建之后,您应该将该image推送到docker hub 或您的registry。 在下一节中,我将介绍如何在Kubernetes上使用它们。 所描述的微服务的Docker镜像也可以在我的Docker Hub公共存储库上用作piomin / account-service和piomin / customer-service。

docker build -t piomin/account-service .

docker push piomin/account-service

部署

您可以使用kubectl运行命令、Minikube dashboard或使用kubectl create命令的YAML配置文件在Kubernetes上创建部署。 我将向您展示如何从YAML配置文件创建所有资源,因为我们需要一步创建多容器部署。 这是Account Service的部署配置文件。 我们必须提供部署名称,image名称和暴露端口。 在副本属性中,我们正在设置创建的pod的请求数量。

apiVersion: extensions/v1beta1

kind: Deployment

metadata:

name: account-service

labels:

run: account-service

spec:

replicas: 1

template:

metadata:

labels:

run: account-service

spec:

containers:

- name: account-service

image: piomin/account-service

ports:

- containerPort: 2222

protocol: TCP

- name: mongo

image: library/mongo

ports:

- containerPort: 27017

protocol: TCP

我们正在通过运行下面的命令来创建新的部署。 相同的命令用于创建Service和ingress。 只有YAML文件格式不同:

kubectl create -f deployment-account.yaml

现在,我们来看看Service配置文件。 我们已经创建了部署。 如您所见,dashboard image已从Docker Hub中取出; pod和副本集已经创建。 现在,我们想在外面暴露我们的微服务。 这就是为什么需要Service。 我们还在其默认端口上公开Mongo数据库,以便能够连接数据库并从MongoDB客户端创建集合。

kind: Service

apiVersion: v1

metadata:

name: account-service

spec:

selector:

run: account-service

ports:

- name: port1

protocol: TCP

port: 2222

targetPort: 2222

- name: port2

protocol: TCP

port: 27017

targetPort: 27017

type: NodePort

在为Customer Service创建类似的配置后,我们已经暴露了我们的微服务。在Kubernetes内部,它们在默认端口(2222和3333)和服务名称上可见。这就是为什么在客户服务REST客户端(@FeignClient)中,我们声明了URL http:// account-service:2222。无论创建了多少个Pod,服务将始终在该URL上可用,并且请求在所有Pod之间进行负载均衡。如果我们希望访问Kubernetes以外的每个服务,例如,在Web浏览器中,我们需要使用在容器默认端口下方可见的端口来调用它 - 在该Account Service的示例中,它是31638端口,并且对于Customer Service, 31171端口。如果您在Windows上运行Minikube,则您的Kubernetes可能位于192.168.99.100地址下,因此您可以尝试使用URL http://192.168.99.100:31638/accounts呼叫帐户服务。在进行这样的测试之前,您需要在Mongo数据库和用户微型/微型(在application.yml中为该服务设置)上创建一个集合。

好了,我们在两个不同的端口下有两个微服务,这不完全是我们所需要的。 我们需要一些IP可用的网关,通过匹配请求路径来代理我们的请求,以及确切的服务。 幸运的是,Kubernetes也提供这样的选项。 这个解决方案是Ingress。 这里是YAML入口配置文件。 定义了两个规则,第一个是Account Service,第二个是Customer Service。 我们的网关在micro.allhost名称和默认HTTP端口下可用。

apiVersion: extensions/v1beta1

kind: Ingress

metadata:

name: gateway-ingress

spec:

backend:

serviceName: default-http-backend

servicePort: 80

rules:

- host: micro.all

http:

paths:

- path: /account

backend:

serviceName: account-service

servicePort: 2222

- path: /customer

backend:

serviceName: customer-service

servicePort: 3333

为了使网关能够正常工作,最后一件事就是将下列条目添加到系统主机文件(Linux的/ etc / hosts和windows的C: Windows System32 drivers etc hosts)中。 现在,您可以尝试从您的网络浏览器调用http://micro.all/accounts或http://micro.all/customers/ ,该帐户在后台也调用帐户服务。

[MINIKUBE_IP] micro.all

总之,Kubernetes是微服务集群管理和编排的好工具。 它在快速发展中,仍然是一个比较新的解决方案。 它可以与Spring Boot堆栈一起使用,或者作为Spring Cloud Netflix OSS(这似乎是目前最流行的微服务解决方案)的替代品。 它还有一个UIdashboard ,您可以在其中管理和监视所有资源。 生产级配置可能比使用Minikube的单一主机开发配置更复杂,但我不认为这是针对Kubernetes。

译者介绍:

楼炜 Jet,云技术社区金牌翻译,现任云星数据副总裁兼研发中心总监,业内资深的云计算专家, 10年云计算经验,7年+ IaaS、PaaS经验。著有: 《企业级IaaS架构的深度解析》、《企业级私有云构建的架构师阵型及架构策略》等文章

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180126G13EK700?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券