尽管这篇文章讨论了Spring Boot应用程序,但所讨论的概念适用于任何微服务应用程序。
您想知道如何在Kubernetes上部署微服务吗?Kubernetes是运行微服务应用程序最流行的选择?
让我们开始:
Kubernetes允许我们在公共、私有或混合云基础设施中部署容器化微服务应用程序。Kubernetes是一个开源容器编排平台。Kubernetes的一些重要特征是:
容器是将代码及其所有依赖项打包在一个标准单元中的可执行文件。因此,容器化应用程序可以从一个计算环境快速可靠地运行到另一个计算环境。Kubernetes上支持的一些容器运行时是Docker、containerd和CRI-O。
在本文中,我将使用Docker作为容器运行时。您可以在官方文档中查看有关安装Docker的说明。
假设已安装Docker,下一步是构建容器映像。为此,我们将使用 Dockerfile
。
Docker文件是一个文本文件,包含为Docker容器设置环境的说明。Docker可以通过读取Docker文件中的说明自动生成图像。
例如,product catalog microservice的 Dockerfile
是:
FROM openjdk:11-jre-slim RUN mkdir /app WORKDIR /app ADD ./build/libs/product-catalog-svc-0.0.1.jar /app/app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"]
FROM RUN WORKDIR ADD EXPOSE ENTRYPOINT
要从Dockerfile构建容器映像,我们需要遵循以下步骤。
1. 创建Spring Boot jar
要构建SpringBoot jar,请从根目录product catalog svc运行命令 gradlew clean build
。此命令将所有类和依赖项打包到一个jar中。这是由Spring Boot的Gradle插件实现的,该插件定义为:
plugins { id 'org.springframework.boot' version '2.5.3' }
要进行验证,请从根目录product catalog svc运行命令 java-jar build/libs/product-catalog-svc-0.0.1.jar
。这将在端口8080上启动产品目录microservice。您可以在Postman中测试API。
2. 创建Docker镜像
要创建docker镜像,请运行命令 docker build-tproduct-catalog:1.0.0 from product-catalog-svc
目录中的1.0.0。此命令创建标记为1.0.0的Docker image产品目录。您可以通过运行命令 docker image ls
来验证映像是否已成功创建。这显示了如下输出:
REPOSITORY TAG IMAGE ID CREATED SIZE product-catalog 1.0.0 1b3edac07100 9 minutes ago 261MB
或者,如果要验证映像是否可以成功运行,请运行命令 docker run-p 8080:8080 product catalog:1.0.0
。您应该看到一个SpringBoot应用程序正在启动。如果您愿意,您可以通过连接到 localhost:8080
通过Postman进行测试。
3. 将Docker容器发布到Docker Hub
容器注册表(如Docker Hub)允许您与其他人共享容器镜像。首先,您需要在Docker Hub创建一个帐户。在Docker Hub帐户中创建存储库后,可以将本地映像推送到该存储库。您可以在Docker Hub上找到有关创建存储库和将图像推送到存储库的完整说明。
要将镜像推送到Docker Hub,首先,我们必须使用Docker Hub存储库 techdozo/product catalog svc
标记本地 techdozo/product-catalog-svc
。这可以通过运行以下命令来完成:
docker tag product-catalog:1.0.0 techdozo/product-catalog-svc:1.0.0
标记镜像后,我们可以按如下方式推送镜像:
docker push techdozo/product-catalog-svc:1.0.0
在本文中,我们将在本地Kubernetes集群上部署产品目录微服务。尽管这篇文章介绍了本地部署,但最好了解微服务部署在生产环境中的情况。
微服务应用程序在Kubernetes上的参考部署如下所示:
部署由以下组件组成。
Kubernetes Cluster
要在Kubernetes上运行microservices应用程序,您需要一个Kubernetes集群。您可以选择Kubernetes集群作为托管服务,例如,AKS、GKE、Amazon EKS。此外,您还可以自己安装kubeadm、kubespray等。对于本地机器,您可以安装Kind、Minikub等。
Ingress
入口将HTTP(S)路由(称为入口)公开为RESTfulWebAPI。例如,入口规则路径 :/products
可以作为RESTFul API/产品在Kubernetes集群之外访问。入口控制器负责执行入口规则。
负载平衡器
负载平衡器将公共internet流量路由到入口。它配置了面向入口控制器的公共IP。DNS可以映射到负载平衡器的公共IP。这允许API消费者使用DNS调用API,例如—— https://example.com/products
.
数据库
几乎每个应用程序都需要一个数据库。在云部署中,您可以选择托管数据库。此外,您还可以选择自管理数据库。
实用服务和可观测性堆栈
除了应用程序服务外,您还可以运行其他实用程序服务。例如,容器安全应用程序(如Twistlock)、缓存(如Redis)等。
可观察性包括度量、跟踪和日志记录。可观测性堆栈帮助您收集和存储度量、日志和应用程序遥测。您可以选择云管理的可观测性堆栈。或者,您可以使用自我管理的可观测性工具。例如,您可以使用Elasticsearch存储应用程序日志,使用Prometheus存储应用程序度量,使用Grafana进行可视化,使用OpenTelemetry进行跟踪,等等。
容器注册表
容器注册表帮助您存储可部署在Kubernetes集群上的私有容器映像。大多数云提供商都有自己的容器注册表。
CI/CD pipeline
CI/CD管道(如Jenkins管道)可帮助您自动化构建和部署。
Helm
Helm是Kubernetes的软件包manager。它将Kubernetes对象捆绑到一个可以部署、版本控制和更新的单元中。
查看了microservice的参考生产部署之后,让我们看看本地部署是什么样子的。主要区别在于不需要配置负载平衡器和进行DNS映射,其余步骤保持不变。
要在本地Kubernetes群集上运行产品目录microservice,可以使用Kind。
要创建集群,请将以下代码保存在 kind-config.yaml
中,并运行命令 kind create cluster--config kind-config.yaml
。
apiVersion: kind.x-k8s.io/v1alpha4 kind: Cluster nodes: - role: control-plane kubeadmConfigPatches: - | kind: InitConfiguration nodeRegistration: kubeletExtraArgs: node-labels: "ingress-ready=true" extraPortMappings: - containerPort: 80 hostPort: 81 protocol: TCP - containerPort: 443 hostPort: 443 protocol: TCP - role: worker - role: worker
您可以通过运行命令 kind get clusters
来验证kind集群部署。此命令返回默认的集群名称种类。
至少,要部署微服务和公开RESTfulWebAPI,您需要了解三个Kubernetes概念。这些是:
我们的应用程序在本地Kubernetes集群中的部署架构如下所示:
让我们详细看看这些组件。
部署
发布Docker镜像后,可以在Kubernetes上以pod的形式运行该镜像。POD是我们可以在Kubernetes中创建和管理的最小可部署计算单元。Pod包含一个或多个容器,其中包含共享的存储和网络资源以及有关运行容器的规范。然而,大多数情况下,您不会直接创建pod,而是通过一个称为部署的更高级别构造来创建pod。
Kubernetes部署是一个更高级别的对象,它允许您向POD提供声明性更新。
声明性更新意味着什么?
Kubernetes对象可以通过在目录中存储对象配置文件(YAML清单文件)来创建和更新。然后,您可以使用命令 kubectl apply
,根据需要递归地创建和更新这些对象。
相反,在命令式方法中,您直接将命令馈送给Kubernetes。例如,要创建nginx的部署,请运行命令 kubectl create deployment nginx--image nginx
。
使用部署,您可以实现:
spec.strategy.type
要创建部署,请将以下代码保存在YAML文件中,比如deployment.YAML,然后运行命令 kubectl apply-f deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: product-catalog labels: app: product-catalog spec: replicas: 3 selector: matchLabels: app: product-catalog template: metadata: labels: app: product-catalog spec: containers: - name: product-catalog imagePullPolicy: IfNotPresent image: techdozo/product-catalog-svc:1.0.0
上面的命令创建了一个Kubernetes部署,其中包含三个与标签 app:product catalog
匹配的pod副本。运行上述命令后,Kubernetes从DockerHub存储库中提取Docker映像 techdozo/product catalog svc:1.0.0
并创建POD。
要进行验证,请运行命令 kubectl get pods
。您应该看到如下内容:
NAME READY STATUS RESTARTS AGE product-catalog-5fcb6cc8fb-6b45b 1/1 Running 0 43s product-catalog-5fcb6cc8fb-fp6dk 1/1 Running 0 43s product-catalog-5fcb6cc8fb-hdmf7 1/1 Running 0 43s
服务
在Kubernetes,pods是短暂的。创建和销毁POD以匹配部署中定义的副本。每个pod都有自己的IP地址,但这个IP地址不是永久的。
这导致了一个问题:如果某组POD(比如order microservice)需要与其他POD(比如product microservice)通信,order microservice如何跟踪product microservice的IP地址?这就是Kubernetes服务的用武之地。
Kubernetes服务是一种抽象,它定义了一组逻辑POD(通常由选择器确定)和访问它们的策略。
服务类型
Kubernetes服务有四种类型:
1. ClusterIP(默认) :服务类型ClusterIP公开集群内部IP上的服务。此服务只能在群集中访问。这是Kubernetes中最常用的方法。
2. NodePort :NodePort在静态端口的每个节点的IP上公开服务。NodePort使用
从集群外部访问服务。
3. LoadBalancer :该服务在云中创建一个外部负载平衡器(如Google cloud、Azure),并为该服务分配一个固定的外部IP。当您想要直接访问服务(例如,从外部集群)时,这是最常用的。
4. ExternalName :这种类型的服务将服务映射到 ExternalName
字段的内容。当您想要访问外部资源(例如,不属于集群的外部数据库)时,这非常有用。
服务清单
您可以将产品目录微服务的Kubernetes服务定义为:
apiVersion: v1 kind: Service metadata: name: product-catalog spec: type: ClusterIP selector: app: product-catalog ports: - port: 80 targetPort: 8080
targetPort是产品目录microservice Docker容器公开的端口,该端口是服务端口本身。
要创建Kubernetes服务,请在 service.yaml
中复制上述定义,并运行命令 kubectl apply-f service.yaml
。
要进行验证,请运行命令 kubectl get service
,该命令输出如下内容:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1443/TCP 15m product-catalog ClusterIP 10.96.19.115 80/TCP 19s
Ingress
简而言之,入口公开了从集群外部到集群内服务的HTTP(S)路由,如 /products
。您可以在Ingress资源中定义流量路由规则。入口控制器有责任遵守入口规则。请记住,Kubernetes中没有内置标准的入口控制器,因此必须安装一个兼容的入口控制器。
Ingress Resource
您可以将产品目录microservice的入口定义为:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: app-ingress spec: rules: - http: paths: - path: /products pathType: Prefix backend: service: name: product-catalog port: number: 80
入口规则包含以下信息:
example.com
),则规则适用于该特定主机。要创建入口,请在 ingres.yaml
中复制上述入口定义,并运行命令 kubectl apply-f ingres.yaml
要验证入口,请运行命令 kubectl get ingres
。
NAME CLASS HOSTS ADDRESS PORTS AGE app-ingress* 80 10s
Ingress Controller
Kubernetes入口控制器负责执行入口规则。要创建入口控制器,请遵循“种类入门:快速启动多节点本地Kubernetes群集”中提到的步骤。
安装ingress controller后,如果再次运行 kubectl get ingress
命令,则可以看到分配为localhost的地址。
NAME CLASS HOSTS ADDRESS PORTS AGE app-ingress* localhost 80 13m
或者,您可以使用Helm图表部署产品目录microservice。你可以在Github中找到( https://github.com/techdozo/microservices/tree/master/product-catalog-svc/kubernetes/helm/product-catalog )
在安装图表之前,您可以按以下方式进行试运行:
helm install product-catalog kubernetes\helm\product-catalog --dry-run
如果运行失败,您可能必须删除早期部署、服务和入口。您可以通过运行命令 kubectl delete
来实现这一点。例如,要删除服务,可以运行命令 kubectl delete service/product catalog
。
一旦您对试运行满意,您可以通过运行以下命令安装图表:
helm install product-catalog kubernetes\helm\product-catalog
部署应用程序后,可以在Postman中测试应用程序。为此,您需要将baseUrl变量更改为指向端口 81
,如下所示:
Kubernetes是一个开源容器编排平台,它允许我们在公共、私有或混合云基础设施中部署容器化的微服务应用程序。
要在Kubernetes中部署Spring Boot microservice应用程序,我们需要:
/products