使用Spring Boot和Kubernetes构建微服务架构

“我喜欢编写身份验证和授权代码。” 〜从来没有Java开发人员。 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权和多因素身份验证。

在本教程中,您将使用Kubernetes将Spring Boot微服务架构部署到Google Cloud,特别是Google Kubernetes Engine(GKE)。 您还将使用Istio创建服务网格层并创建公共网关。 整个事情将使用Okta OAuth JWT身份验证进行保护。

那是一堆烂话。 我们将不在这里深入解释微服务。 简而言之,微服务是一种设计模式,可将较大的单片服务拆分为较小的独立“微”服务。 这些服务通过网络松散耦合。 这种体系结构的好处是,每个服务都变得可测试,可维护且可独立部署。 在互联网规模上,在像Amazon和Netflix这样的大型公司中,这种架构都很棒,因为它允许公司将小型团队的职责分配给可管理的,离散的功能单元。 而不是拥有成千上万的人监督巨大的整体代码块。 不利之处是复杂性和基础架构的高昂初始成本,这对于无法规模化的较小项目可能没有意义。

Kubernetes是用于部署容器化服务的平台。 您可以将其视为Docker容器的容器协调器(这是一种简化,但是可以使用)。 这将使我们能够编写YAML脚本,以自动将微服务架构部署到我们选择的平台GKE。 这是一个庞大的项目,需要深入研究。 看看他们的文档以了解更多信息。

Istio在Kubernetes的基础上又增加了一层功能,增加了一些出色的监视,安全性,访问控制和负载平衡功能。 查看他们的网站以获取更多信息。

微服务架构的最后一部分是Google Cloud和GKE 。 这是您将用于部署微服务的平台。 本教程中未介绍的另一个选项是Minikube。 Minikube在您的计算机上本地运行,可能对某些人有用。 我发现Google Kubernetes Engine更易于使用且性能更高。

我们假设您熟悉Spring Boot和Java。 如果不是这样,请查看教程末尾的一些链接以帮助您入门。

Spring Boot和Kubernetes的要求

HTTPie :从他们的网站安装HTTPie,以便我们可以轻松地从终端运行HTTP请求。

Docker :如果尚未安装Docker Desktop,请从其网站下载并安装。

kubectl :这是Kubernetes的命令行界面。 有关安装说明,请参见其网站 。

Google Cloud :您需要一个启用了计费功能的Google Cloud帐户。 有一个免费试用版,其中应包括足够的学分和时间,以帮助您完成本教程。 转到Google Cloud网站并注册。

developer.okta.com :我们在开发人员网站上提供免费的开发人员帐户。 请立即注册一个。 您将在本教程结束时使用它。

gcloud :这是Google Cloud CLI。 按照其网站上的说明进行安装。 。 完成此操作后,您需要通过运行以下命令来安装gcloud kubectl组件:

gcloud components install kubectl

我是否提到微服务的初始复杂性成本很高?

使用Istio创建一个Google Kubernetes Engine项目

您现在应该拥有一个启用了结算功能的Google Cloud帐户。 同样,您实际上不需要花任何钱,但是如果不付款,您将无法访问免费试用版。

创建一个新项目。 将其命名为spring-boot-gke (或任何您想使用的名称,但是您需要各种命令的项目ID)。 等待项目创建。

项目名称的结尾可能会带有一个ID号,例如spring-boot-gke-232934 。 您将需要几次该项目名称,因此请继续将其存储在shell变量中并记下它。

PROJECT_NAME=<your project name and ID>

项目准备就绪后,打开项目仪表板,打开导航菜单,然后单击Kubernetes Engine 。 单击启用帐单按钮(如果尚未启用帐单),然后选择一个帐单帐户。

单击创建集群

微服务架构

在左侧面板中,选择您的第一个集群

将集群命名为“ spring-boot-cluster”。

选择区域“ us-west1-a”。

单击集群配置面板底部的“ 高级选项”链接以显示高级选项。 向下滚动到底部,然后选中Enable Istio(beta)复选框。 这将自动在群集上安装Istio。

微服务架构

在底部,单击创建以创建集群。 喝咖啡或休息一下; 创建集群将需要几分钟。

同时,如果尚未安装,请继续运行以下命令来初始化gcloud CLI:

gcloud init

在初始化过程中,可以将新项目设置为默认项目,并将项目区域设置为默认区域。

部署集群后,您需要使用以下命令将本地gcloudkubectl CLI连接到该集群:

gcloud container clusters get-credentials {yourClusterName} --zone us-west1-a --project {yourProjectId}

如果您使用了其他项目名称,则需要更改命令以反映该名称。

注意:如果单击Google Cloud Platform仪表板右侧的“ 连接”按钮,您将看到正确的命令,可输入:

微服务架构

结果,您应该看到类似以下的内容:

Fetching cluster endpoint and auth data.
kubeconfig entry generated for spring-boot-cluster.

您还需要为自己赋予集群管理员权限:

kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=$(gcloud config get-value core/account)

现在,您需要检查并确保Istio服务已安装并正在运行。 有两种检查方法。 首先,在您的Google Cloud Platform Kubernetes Engine仪表板中,单击“ 服务”按钮。 您应该在spring-boot-cluster看到Istio服务的列表。 它们的状态列下都应有绿色的“确定”。

在此期间,请注意类型为LoadBalancer名为istio-ingressgateway的服务。 这是群集的公共负载平衡器,该条目显示公共IP和开放端口。

微服务架构

另一种检查方法是使用kubectl CLI。

要检查服务,请使用以下命令: kubectl get services --all-namespaces 。 必须使用--all-namespaces才能显示istio-system命名空间中的Istio服务。

$ kubectl get services --all-namespaces
NAMESPACE      NAME                     TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)                                                                                                                   AGE
default        kubernetes               ClusterIP      10.31.240.1     <none>           443/TCP                                                                                                                   5m
istio-system   istio-citadel            ClusterIP      10.31.252.214   <none>           8060/TCP,9093/TCP                                                                                                         3m
istio-system   istio-egressgateway      ClusterIP      10.31.247.186   <none>           80/TCP,443/TCP                                                                                                            3m
istio-system   istio-galley             ClusterIP      10.31.249.131   <none>           443/TCP,9093/TCP                                                                                                          3m
istio-system   istio-ingressgateway     LoadBalancer   10.31.244.186   35.185.213.229   80:31380/TCP,443:31390/TCP,31400:31400/TCP,15011:30675/TCP,8060:31581/TCP,853:32460/TCP,15030:30998/TCP,15031:31606/TCP   3m
istio-system   istio-pilot              ClusterIP      10.31.251.44    <none>           15010/TCP,15011/TCP,8080/TCP,9093/TCP                                                                                     3m
istio-system   istio-policy             ClusterIP      10.31.246.176   <none>           9091/TCP,15004/TCP,9093/TCP                                                                                               3m
istio-system   istio-sidecar-injector   ClusterIP      10.31.240.214   <none>           443/TCP                                                                                                                   3m
istio-system   istio-telemetry          ClusterIP      10.31.247.23    <none>           9091/TCP,15004/TCP,9093/TCP,42422/TCP                                                                                     3m
istio-system   promsd                   ClusterIP      10.31.246.88    <none>           9090/TCP                                                                                                                  3m
kube-system    default-http-backend     NodePort       10.31.250.134   <none>           80:31955/TCP                                                                                                              4m
kube-system    heapster                 ClusterIP      10.31.250.242   <none>           80/TCP                                                                                                                    4m
kube-system    kube-dns                 ClusterIP      10.31.240.10    <none>           53/UDP,53/TCP                                                                                                             4m
kube-system    metrics-server           ClusterIP      10.31.245.127   <none>           443/TCP

要检查Kubernetes Pod,请使用: kubectl get pods --all-namespaces

$ kubectl get pods --all-namespaces
NAMESPACE      NAME                                                      READY     STATUS      RESTARTS   AGE
istio-system   istio-citadel-7c4864c9d5-7xq9x                            1/1       Running     0          10m
istio-system   istio-cleanup-secrets-ghqbl                               0/1       Completed   0          10m
istio-system   istio-egressgateway-c7f44ff8-tz7br                        1/1       Running     0          10m
istio-system   istio-galley-698f5c74d6-hmntq                             1/1       Running     0          10m
istio-system   istio-ingressgateway-774d77cb7c-qvhkb                     1/1       Running     0          10m
istio-system   istio-pilot-6bd6f7cdb-gb2gd                               2/2       Running     0          10m
istio-system   istio-policy-678bd4cf9-r8p6z                              2/2       Running     0          10m
istio-system   istio-sidecar-injector-6555557c7b-99c6k                   1/1       Running     0          10m
istio-system   istio-telemetry-5f4cfc5b6-vj8cf                           2/2       Running     0          10m
istio-system   promsd-ff878d44b-hlkpg                                    2/2       Running     1          10m
kube-system    heapster-v1.6.0-beta.1-8c76f98c7-2b4dm                    2/2       Running     0          9m
kube-system    kube-dns-7549f99fcc-z5trl                                 4/4       Running     0          10m
kube-system    kube-dns-autoscaler-67c97c87fb-m52vb                      1/1       Running     0          10m
kube-system    kube-proxy-gke-spring-boot-cluster-pool-1-b6988227-p09h   1/1       Running     0          10m
kube-system    l7-default-backend-7ff48cffd7-ppvnn                       1/1       Running     0          10m
kube-system    metrics-server-v0.2.1-fd596d746-njws2                     2/2       Running     0          10m

各个Pod的状态都必须为CompletedRunning 。 我遇到了几次问题,其中自动配置不起作用,并且某些吊舱从未达到Running状态,并停留在ContainerCreating 。 我必须删除群集并重新安装它才能正常工作。

如果发生这种情况,您可以使用describe pods命令查看发生了什么: kubectl describe pods -n istio-system 。 这将为您提供有关istio-system名称空间中所有Pod的istio-system ,这些信息是使用-n选项指定的。

如果到此为止没有问题,那么现在您已经在安装了Istio的GKE上部署了Kubernetes集群! 很甜

如果您遇到问题,Google和Istio都会提供一些非常有用的文档。 查看Google GKE文档和Istio GKE文档以获得进一步的支持。

为您的微服务创建Spring Boot项目

现在转到Spring Initializer并创建您的启动项目。

  • 将构建工具从Maven更改为Gradle
  • 使用Java和Spring Boot版本2.1.3
  • 更新为: com.okta.spring
  • 使用工件springbootkbe
  • 添加三个依赖项Reactive WebReactive MongoDBLombok
微服务架构

单击生成项目并下载项目。 将项目解压缩到本地计算机上的某个位置,然后在您喜欢的IDE或编辑器中将其打开。

Spring Initializer已创建了带有MongoDB支持的准系统响应式Webflux项目,供您扩展。

与我的其他一些教程一样,并且由于我喜欢皮划艇,因此您将构建一个简单的反应式REST服务,该服务维护皮艇条目的数据库。 它实际上只是为了演示基本的CRUD功能(创建,读取,更新和删除),并且可以推广到任何类型的资源。

src/main/java下的com.okta.spring.springbootkbe包中,创建一个名为Kayak.java的文档类,并将以下内容粘贴到其中。 这是您的反应性数据模型文档。

package com.okta.spring.springbootkbe;import lombok.AllArgsConstructor;  
import lombok.Data;  
import lombok.NoArgsConstructor;  
import org.springframework.data.mongodb.core.mapping.Document;  @Document  
@Data  
@AllArgsConstructor  
@NoArgsConstructor  
public class Kayak {  private String name;  private String owner;  private Number value;  private String makeModel;  
}

现在,在相同的包KayakRepository.java创建另一个文件。

package com.okta.spring.springbootkbe;  import org.springframework.data.mongodb.repository.ReactiveMongoRepository;  public interface KayakRepository extends ReactiveMongoRepository<Kayak, Long> {  
}

在本教程中,我不会对这里发生的事情进行过多的详细介绍。 Spring Boot在这两个文件之间进行了大量自动匹配,以创建功能齐全的反应式Mongo文档。

接下来,您需要添加一个控制器以允许访问Kayak文档数据模型。 在com.okta.spring.springbootkbe包中创建一个名为KayakController的文件。

package com.okta.spring.springbootkbe;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;@Controller
@RequestMapping(path = "/kayaks")
public class KayakController {private final KayakRepository kayakRepository;public KayakController(KayakRepository kayakRepository) {this.kayakRepository = kayakRepository;}@PostMapping()public @ResponseBodyMono<Kayak> addKayak(@RequestBody Kayak kayak) {return kayakRepository.save(kayak);}@GetMapping()public @ResponseBodyFlux<Kayak> getAllKayaks() {Flux<Kayak> result = kayakRepository.findAll();return result;}}

该控制器向/kayaks端点添加了两种方法,即POST和GET端点,它们分别添加了一个新的皮划艇并列出了所有的皮划艇。

最后,添加一个简单的根控制器RootController

package com.okta.spring.springbootkbe;  import org.springframework.stereotype.Controller;  
import org.springframework.web.bind.annotation.*;  
import reactor.core.publisher.Flux;  @Controller  
public class RootController {  @GetMapping("/")  @ResponseBody  public Flux<String> getRoot() {  return Flux.just("Alive");  }
}

此控制器是必需的,因为Kuberenetes在我们服务的根端点上执行运行状况检查,并且需要返回响应,否则群集将认为您的服务已关闭。 实际的端点是可配置的,但您现在可以将其留在根目录下。

要将一些示例数据引导到我们的数据库中,请更新SpringbootkbeApplication类定义以匹配以下内容。

package com.okta.spring.springbootkbe;  import org.springframework.boot.ApplicationRunner;  
import org.springframework.boot.SpringApplication;  
import org.springframework.boot.autoconfigure.SpringBootApplication;  
import org.springframework.context.annotation.Bean;  
import reactor.core.publisher.Flux;  @SpringBootApplication  
public class SpringbootkbeApplication {public static void main(String[] args) {SpringApplication.run(SpringbootkbeApplication.class, args);}@BeanApplicationRunner init(KayakRepository repository) {Object[][] data = {{"sea", "Andrew", 300.12, "NDK"},{"creek", "Andrew", 100.75, "Piranha"},{"loaner", "Andrew", 75, "Necky"}};return args -> {repository.deleteAll().thenMany(Flux.just(data).map(array -> {return new Kayak((String) array[0], (String) array[1], (Number) array[2], (String) array[3]);}).flatMap(repository::save)).thenMany(repository.findAll()).subscribe(kayak -> System.out.println("saving " + kayak.toString()));};}
}

至此,您将拥有一个功能全面的Spring Boot应用程序(减去MongoDB服务器)。 要测试您的应用,请将以下依赖项添加到build.gradle文件中。

compile 'de.flapdoodle.embed:de.flapdoodle.embed.mongo'

这会将嵌入式MongoDB数据库添加到您的项目。 在部署到集群之前,您需要删除此依赖项,但是它将允许您在本地运行Spring Boot应用程序。

使用以下gradle bootRun运行Spring Boot应用程序: gradle bootRun

您应该看到一堆以结尾的输出:

2019-02-14 19:29:34.941  INFO 35982 --- [ntLoopGroup-2-4] org.mongodb.driver.connection            : Opened connection [connectionId{localValue:5, serverValue:5}] to localhost:61858
2019-02-14 19:29:34.946  INFO 35982 --- [ntLoopGroup-2-3] org.mongodb.driver.connection            : Opened connection [connectionId{localValue:4, serverValue:4}] to localhost:61858
saving Kayak(name=sea, owner=Andrew, value=300.12, makeModel=NDK)
saving Kayak(name=loaner, owner=Andrew, value=75, makeModel=Necky)
saving Kayak(name=creek, owner=Andrew, value=100.75, makeModel=Piranha)

使用HTTPie测试应用程序: http :8080 (这会在默认的Spring Boot端口上运行get请求)。

HTTP/1.1 200 OK
Content-Type: text/plain;charset=UTF-8
transfer-encoding: chunkedAlive

并使用以下命令获取/kayaks端点: http :8080/kayaks

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
transfer-encoding: chunked
[{"makeModel": "NDK","name": "sea","owner": "Andrew","value": 300.12},{"makeModel": "Necky","name": "loaner","owner": "Andrew","value": 75},{"makeModel": "Piranha","name": "creek","owner": "Andrew","value": 100.75}
]

假设一切正常,请删除嵌入的Mongo依赖项 。 您将使用Mongo Kubernetes Pod,这种依赖性将导致集群部署出现问题。

compile 'de.flapdoodle.embed:de.flapdoodle.embed.mongo'

为您的Spring Boot App部署MongoDB Kubernetes Pod

Kubernetes通过使用YAML部署脚本部署Docker容器来工作(大致概括和简化)。

在项目的根目录中创建一个名为deployment-mongo.yml的文件。

apiVersion: apps/v1  
kind: Deployment  
metadata:  name: mongodb  labels:  appdb: mongodb  
spec:  replicas: 1  selector:  matchLabels:  appdb: mongodb  template:  metadata:  labels:  appdb: mongodb  spec:  containers:  - name: mongodb  image: mongo:3.6.6  ports:  - containerPort: 27017  
---  
apiVersion: v1  
kind: Service  
metadata:  name: mongodb  labels:  app: mongodb  
spec:  ports:  - port: 27017  protocol: TCP  selector:  appdb: mongodb

这定义了在集群上创建Mongo数据库所需的MongoDB Kubernetes DeploymentService 。 我不会尝试完全解释这些对象在这里,但是您可以阅读Kubernetes 部署文档和服务文档 。 粗略地说,部署定义了在已部署的Pod中运行的微应用程序,而服务则提供了总体抽象,该抽象定义了Pod中对应用程序的访问点。 这种抽象提供了必要的连续性,因为Pod可能会被杀死并重新启动,并且可能有多个Pod运行一项服务。

现在有些激动! 您将把Mongo数据库部署和服务部署到GKE集群。

使用以下命令:

kubectl apply -f deployment-mongo.yml

您应该看到:

deployment.apps "mongodb" created
service "mongodb" created

通过运行以下命令来检查Pod:

$ kubectl get pods

您应该看到:

NAME                      READY     STATUS    RESTARTS   AGE
mongodb-c5b8bf947-rkw5f   1/1       Running   0          21s

如果状态列为ContainerCreating ,请稍等片刻,然后再次运行命令。 如果它在ContainerCreating停留超过几分钟,则可能出现了问题。 您可以使用kubectl describe podskubectl get events命令来了解正在发生的事情。

这使用标准docker映像mongo:3.6.6配置了在端口27017上运行的Mongo数据库。

太好了吧? 下一站,火箭科学!

将Spring Boot App部署到集群

在根目录中添加一个名为Dockerfile的文件:

FROM openjdk:8-jdk-alpine  
ENV APP_FILE springbootkbe-0.1.0-SNAPSHOT.jar  
ENV APP_HOME /usr/app  
EXPOSE 8000  
COPY build/libs/*.jar $APP_HOME/  
WORKDIR $APP_HOME  
ENTRYPOINT ["sh", "-c"]  
CMD ["exec java -jar $APP_FILE"]

更新src/main/resources/application.properties

server.port=8000
spring.data.mongodb.host=mongodb
spring.data.mongodb.port=27017

Dockerfile您的Spring Boot端口配置为要在Dockerfile公开的端口,并配置MongoDB主机和端口。 默认情况下,主机将是群集中服务的名称。

再次构建您的应用程序(您确实删除了flapdoodle依赖项,对吗?):

gradle clean build

在根项目目录中创建另一个名为deployment.yml Kubernetes部署脚本:

apiVersion: v1  
kind: Service  
metadata:  name: kayak-service  labels:  app: kayak-service  
spec:  ports:  - name: http  port: 8000  selector:  app: kayak-service  
---  
apiVersion: extensions/v1beta1  
kind: Deployment  
metadata:  name: kayak-service  
spec:  replicas: 1  template:  metadata:  labels:  app: kayak-service  version: v1  spec:  containers:  - name: kayak-app  image: gcr.io/spring-boot-gke-/kayak-app:1.0  imagePullPolicy: IfNotPresent  env:  - name: MONGODB_HOST  value: mongodb  ports:  - containerPort: 8000  livenessProbe:  httpGet:  path: /  port: 8000  initialDelaySeconds: 5  periodSeconds: 5

注意:请仔细查看gcr.io/spring-boot-gke/kayak-app:1.0的行。 中间部分是Google Cloud项目名称。 这需要与您使用的项目名称以及分配的ID号(例如spring-boot-gke-43234spring-boot-gke-43234

gcr.io为美国的gcr.io指定了Google Cloud主机。 可以指定其他位置。 有关更多信息,请参见Google Container Registry文档 。

即将发生的事情的简要摘要,因为其中有很多活动的部分。 Spring Boot应用程序将进行docker化:内置于docker映像中。 在群集上运行部署脚本时,它将尝试从Google Container注册表中提取此映像。 因此,您需要将映像推送到容器注册表并对其进行标记,以便Kubernetes可以找到正确的映像。

如果您使用的是本地Docker桌面,请继续启动并等待其启动。

在做任何事情之前,您需要配置Google Cloud和docker以便一起玩:

gcloud auth configure-docker

构建docker映像:

docker build -t kayak-app:1.0 .

标记图像并将其推送到Google容器注册表(再次注意Google Cloud项目名称):

docker tag kayak-app:1.0 gcr.io/$PROJECT_NAME/kayak-app:1.0;  
docker push gcr.io/$PROJECT_NAME/kayak-app:1.0

现在应用deployment.yml文件复制到GKE集群:

kubectl apply -f deployment.yml

检查以确保Pod正确部署:

kubectl get pods
NAME                             READY     STATUS    RESTARTS   AGE
kayak-service-7df4fb9c88-srqkr   1/1       Running   0          56s
mongodb-c5b8bf947-dmghb          1/1       Running   0          16m

但是,此时您的集群还没有准备好。 它不是公开可用的。

创建一个名为istio-gateway.yml的文件

apiVersion: networking.istio.io/v1alpha3  
kind: Gateway  
metadata:  name: kayak-gateway  
spec:  selector:  istio: ingressgateway # use Istio default gateway implementation  servers:  - port:  name: http  number: 80  protocol: HTTP  hosts:  - '*'  
---  
apiVersion: networking.istio.io/v1alpha3  
kind: VirtualService  
metadata:  name: kayak-service  
spec:  hosts:  - "*"  gateways:  - kayak-gateway  http:  - match:  - uri:  prefix: /  route:  - destination:  port:  number: 8000  host: kayak-service

并应用:

kubectl apply -f istio-gateway.yml

您应该得到:

gateway.networking.istio.io "kayak-gateway" created
virtualservice.networking.istio.io "kayak-service" created

测试已部署的Google Kubernetes Engine + Spring Boot App

既然您已成功将Spring Boot应用程序部署到Google Kubernetes集群并创建了将服务链接到外部世界的网关,您将需要测试端点。

Istio网站上有一些关于入口流量的优秀文档,这些文档具有很多很好的信息。 下面是从该页面复制的一些命令,这些命令将确定面向公众的主机/ ip地址和端口并将其保存到shell变量中

export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}');
export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}');

在您的配置中, INGRESS_PORT可能只是HTTP的默认80(无SSL)。

运行以下命令以查看主机和端口:

echo "$INGRESS_HOST, HTTP PORT=$INGRESS_PORT";

也可以通过在Cloud Platform仪表板-> Kubernetes Engine->服务中查看负载均衡器IP地址来找到公共IP地址。 寻找类型LoadBalancer的 istio-ingressgateway服务。

测试应用程序!

http $INGRESS_HOST:$INGRESS_PORT/

您应该看到:

HTTP/1.1 200 OK
content-type: text/plain;charset=UTF-8
...Alive

并点击/kayaks端点:

http $INGRESS_HOST:$INGRESS_PORT/kayaks

您应该看到:

HTTP/1.1 200 OK
content-type: application/json;charset=UTF-8
...
[{"makeModel": "NDK","name": "sea","owner": "Andrew","value": 300.12},{"makeModel": "Piranha","name": "creek","owner": "Andrew","value": 100.75},{"makeModel": "Necky","name": "loaner","owner": "Andrew","value": 75}
]

欢迎来到微服务的世界!

显然,GKE和Istio可以完成更多工作。 在实践中,微服务通常管理大型服务网格和已部署的Pod,可以根据需要进行扩展和缩小,并且可以在不同部分之间以及与外部世界一起管理复杂的安全体系结构。 本教程将不涉及更多内容,但是还需要再走一步:使用Okta添加JSON Web令牌身份验证。

在Okta上创建OpenID Connect应用程序

登录到您的developer.okta.com帐户(您确实注册了他们的免费开发者帐户之一,对吗?如果不是,请前往developer.okta.com )。

单击应用程序顶部菜单,然后单击添加应用程序按钮。

选择应用程序类型Web

微服务架构

单击下一步

为应用命名。 我将其命名为“ Spring Boot GKE”。

登录重定向URI下,添加https://oidcdebugger.com/debug

在底部,在允许的授予类型下 ,选中隐式(混合)框。

微服务架构

单击完成

让页面保持打开状态,并记下Client IDClient Secret 。 使用OIDC调试器生成JSON Web令牌时,一分钟之内将需要它们。

更新OAuth 2.0的Spring Boot微服务

将以下依赖项添加到您的build.gradle

compile 'org.springframework.security:spring-security-oauth2-client'
compile 'org.springframework.security:spring-security-oauth2-resource-server'

您还需要将以下内容添加到src/main/resources/application.properties文件中(填写您自己的Oktadeveloper URL,类似于dev-123456.okta.com):

spring.security.oauth2.resourceserver.jwt.issuer-uri=https://{yourOktaDomain}/oauth2/default

这告诉Spring需要在什么地方对即将生成的JSON Web令牌(JWT)进行身份验证。

最后,您需要添加一个名为SecurityConfiguration.java的新Java类:

package com.okta.spring.springbootkbe;  import org.springframework.context.annotation.Bean;  
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;  
import org.springframework.security.config.web.server.ServerHttpSecurity;  
import org.springframework.security.web.server.SecurityWebFilterChain;  @EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class SecurityConfiguration {@Beanpublic SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {http.authorizeExchange().pathMatchers("/").permitAll().anyExchange().authenticated().and().oauth2ResourceServer().jwt();return http.build();}
}

此文件将项目配置为允许根端点上的所有事务,但授权所有其他事务。

构建一个新的Docker映像并推送到GKE集群

现在您有了一个新的,启用了身份验证的Spring Boot应用程序,您需要对其进行构建,将其打包在Docker容器中,将其推送到Google Cloud Docker注册表中,然后将新的部署应用于Kubernetes集群。

从您的外壳转到项目根目录。

使用身份验证更新构建Spring Boot应用程序:

gradle clean build

构建新的Docker映像。 注意新的映像名称(包括-auth )。 另外:确保您的Docker桌面正在运行。

docker build -t kayak-app-auth:1.0 .

标记您的Docker映像并将其推送到Google Cloud容器注册表。 如有必要,请在回购路径中更改项目名称。

docker tag kayak-app-auth:1.0 gcr.io/$PROJECT_NAME/kayak-app-auth:1.0;  
docker push gcr.io/$PROJECT_NAME/kayak-app-auth:1.0;

删除集群上已部署的Pod:

kubectl delete -f deployment.yml

更新deployment.yml文件以反映新的映像名称(文件中的第28行):

spec:  containers:  - name: kayak-app  image: gcr.io/spring-boot-gke/kayak-app-auth:1.0

重新部署更新的Kubernetes部署:

kubectl apply -f deployment.yml

使用kubectl get pods检查pod的状态。 完全更新将需要几秒钟。 准备就绪后,测试/端点。

http $INGRESS_HOST:$INGRESS_PORT/
HTTP/1.1 200 OK
...Alive

/kayaks端点,应该对其进行保护:

$ http $INGRESS_HOST:$INGRESS_PORT/kayaks
HTTP/1.1 401 Unauthorized
...

很近! 您需要做的最后一件事是使用OIDC调试器工具生成令牌并测试JWT身份验证。

生成一个JWT并测试OAuth 2.0

转到OIDC调试器 。 您需要从Okta OIDC应用程序中获取客户ID

  • 填写授权URI: https://{yourOktaDomain} /oauth2/default/v1/authorize
  • 填写客户ID
  • abcdefstate
  • 点击底部的发送请求

复制生成的令牌,并将其存储在shell变量中以方便使用:

TOKEN=eyJraWQiOiI4UlE5REJGVUJOTnJER0VGaEExekd6bWJqREp...

再次在/kayaks端点上运行GET,这次使用令牌:

http $INGRESS_HOST:$INGRESS_PORT/kayaks Authorization:"Bearer $TOKEN"

注意双引号! 单引号不起作用,因为该变量不会在字符串中扩展。

您应该得到:

HTTP/1.1 200 OK
cache-control: no-cache, no-store, max-age=0, must-revalidate
content-type: application/json;charset=UTF-8
...
[{"makeModel": "NDK","name": "sea","owner": "Andrew","value": 300.12},{"makeModel": "Piranha","name": "creek","owner": "Andrew","value": 100.75},{"makeModel": "Necky","name": "loaner","owner": "Andrew","value": 75}
]

使用Spring Boot微服务和Kubernetes向前发展

而已! 您已经在这里盖了一吨土地。 您使用Istio在Google Cloud上使用Google Kubernetes创建了Kubernetes集群。 您已将本地系统配置为使用gcloudkubectl与集群进行kubectl 。 您创建了一个使用MongoDB后端的Spring Boot应用,对其进行了docker化处理,并将其推送到Google Cloud注册表中,然后将其部署到您的集群中。 您还向应用程序添加了OIDC身份验证。

您可以在oktadeveloper / okta-spring-boot-microservice-kubernetes的 GitHub上找到此示例的源代码。

如果您喜欢微服务和Spring Boot,那么您可能也喜欢这些帖子:

  • 构建Spring微服务并对其进行Dockerize生产
  • 使用HTTPS和OAuth 2.0保护服务到服务的Spring微服务
  • 使用Spring Boot 2.0和OAuth 2.0构建并保护微服务

如果您对此帖子有任何疑问,请在下面添加评论。 有关更多精彩内容, 请在Twitter上关注@oktadev , 在Facebook上关注我们,或订阅我们的YouTube频道 。

“ 使用Spring Boot和Kubernetes构建微服务架构 ”最初于2019年4月1日发布在Okta开发者博客上。

“我喜欢编写身份验证和授权代码。” 〜从来没有Java开发人员。 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权和多因素身份验证。

翻译自: https://www.javacodegeeks.com/2019/04/build-microservice-architecture-spring-boot-kubernetes.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/342473.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

物联网串口服务器的功能和作用

一、串口服务器是什么&#xff1f; 串口服务器提供串口转网络功能&#xff0c;能够将RS-232/485/422串口转换成TCP/IP网络接口,实现RS-232/485/422串口与TCP/IP网络接口的数据双向透明传输。使得串口设备能够立即具备TCP/IP网络接口功能,连接网络进行数据通信,极大的扩展串口设…

[渝粤教育] 三峡大学 电力电子技术(Ⅱ) 参考 资料

教育 -电力电子技术&#xff08;Ⅱ&#xff09;-章节资料考试资料-三峡大学【】 第一章 单元测试 1、【单选题】整流是以下哪两种电能形式之间的转换&#xff1f; A、AC-AC B、AC-DC C、DC-AC D、DC-DC 参考资料【 】 2、【单选题】充电宝在给手机锂电池充电的时候采用了以下哪…

为什么说无线数传电台和增益天线是相辅相成关系?

最近我司数传电台客户在使用超宽频&#xff08;410-493MHz&#xff09;25W数传电台和433MHz天线的过程中遇到模块失配天线的问题&#xff0c;下面我们不妨再来聊聊这个话题。 问题&#xff1a;客户在使用这个数传电台的时候&#xff0c;配备某些天线的时候不能够正常工作&#…

什么是安防工业交换机,其光口、电口,如何实现电、光转化

对于从事安防传输设备行业的朋友们来说&#xff0c;相信大家对安防工业交换机应该都不陌生吧。我们深知安防工程要的不仅是交换机产品&#xff0c;更需要的是匹配应用需求特点的高性价比。而客户在购买工业交换机时&#xff0c;很多客户都会要几光几电的交换机&#xff0c;那么…

[渝粤教育] 三峡大学 自动控制理论 参考 资料

教育 -自动控制理论-章节资料考试资料-三峡大学【】 第1周作业 第一章综合测验 1、【单选题】通过测量输出量&#xff0c;产生一个与输出信号存在确定函数比例关系值的元件称为( ) A、比较元件 B、给定元件 C、反馈元件 D、放大元件 参考资料【 】 2、【单选题】如果被调量随着…

433M数传电台窄带无线通讯技术手册

一、模块介绍 1.1特点介绍 E3A-DTU-500 是 一款 频率 433M 无 线数传电 台 &#xff08; 同时 具有RS232/RS485 接口&#xff09;&#xff0c;透明传输方式&#xff0c;工作在 425~450.5MHz 频段&#xff08;默认433MHz&#xff09;&#xff0c;工作电压范围 8V~28V。 模块具有…

飞畅科技告诉你什么是集成串口服务器POE交换机?

飞畅科技FCM系列工业POE交换机&#xff0c;提供7个百兆自适应RJ45端口3个千兆SFP上联光口插槽1路RS-485数据端口1路RS232数据端口&#xff0c;其中1-7口支持IEEE 802.3af/at标准PoE供电&#xff0c;单端口PoE功率达30W&#xff0c;整机最大PoE输出功率为240W。该系列产品是针对…

[渝粤教育] 三江学院 数字电子技术 参考 资料

教育 -数字电子技术-章节资料考试资料-三江学院【】 第一章作业 第一章测验 1、【单选题】在二进制计数系统中&#xff0c;每个变量的取值为&#xff08;&#xff09;。 A、0和1 B、0~7 C、0~9 D、0~F 参考资料【 】 2、【单选题】二进制数的权值为&#xff08;&#xff09;。 …

E820-DTU模拟量无线数传电台:物联网工业现场无线数传应用

为帮助用户在使用本公司产品时&#xff0c;能轻松快速的了解产品的使用方法&#xff0c;故写下E820-DTU工业现场无线变送应用手册&#xff0c;在此&#xff0c;读者需要了解本应用手册所针对的设备型号为我公司的E820-DTU(2I2-433L)&#xff0c;以下均简称为E820&#xff0c;或…

【lora模块技术无线数传电台】E90-DTU产品高防护等级的体现

E90-DTU-SL系列采用最新一代军工级LoRa调制技术&#xff0c;在原来的基础上距离更远&#xff0c;功耗更低&#xff0c;无疑为物联网的建设注入了新的力量&#xff0c;而亿佰特在E90-DTU-SL系列的基础又加上了P&#xff1b;引起了大家的注意&#xff0c;那么P到底是什么意思呢&a…

[渝粤教育] 上海交通大学 流体力学 参考 资料

教育 -流体力学-章节资料考试资料-上海交通大学【】 单元作业 单元测验 1、【单选题】一个物体微元的变形大小与所受切应力相关&#xff0c;这个物体可以是&#xff1a; A、刚体 B、弹性体 C、流体 D、无 参考资料【 】 2、【单选题】一个物体微元的变形速度大小与所受切应力成…

为什么5G物联网无线通信数传设备必须进行OTA更新

成都亿佰特电子科技有限公司一家集研发、生产、销售一体&#xff0c;具备完整产业链的高新技术企业。产品涵盖LoRa、WiFi、蓝牙、ZigBee、4G/5G/NB/DTU/GPRS无线模块及无线感知设备、数传电台、工业路由器、串口服务器等通信设备。公司拥有数百项发明和实用新型专利&#xff0c…

LoRa无线通信模块在运动安全上的物联网运用

5月22日中午1点左右&#xff0c;第四届黄河石林山地马拉松百公里越野赛的高海拔赛段突遇极端天气&#xff0c;多名参赛人员出现身体不适、失温等情况&#xff0c;据统计已有21人不幸遇难&#xff0c;其中超半数为马拉松顶尖高手。相比于城市马拉松&#xff0c;山地越野马拉松具…

亿佰特WiFi无线通信模块在物联网智慧农场应用案例

随着传感器、无线数传设备、应用方案的不断发展和成熟&#xff0c;也在不断推动着工业应用、智慧家居、智慧安防、智慧交通、智慧环保、智慧农业的发展&#xff1b;智慧农业也是近年来发展非常好的方向&#xff0c;尤其温室大棚等越来越智能化、现代化&#xff1b;我们某客户就…

【lora无线数传通信模块】亿佰特E22串口模块用于物联网地震预警传感通信方案

物联网地震预警项目介绍&#xff1a; 地震&#xff0c;俗称地动。它像平常的刮风下雨一样&#xff0c;是一种常见的自然现象&#xff0c;是地壳运动的一种表现&#xff0c;即地球内部缓慢积累的能量突然释放而引起的地球表层的振动。据统计&#xff0c;5级以上地震就能够造成破…

什么是以太网交换机?以太网交换机的工作原理详解!

以太网交换机是基于以太网传输数据的交换机&#xff0c;以太网采用共享总线型传输媒体方式的局域网。以太网交换机的结构是每个端口都直接与主机相连&#xff0c;并且一般都工作在全双工方式。交换机能同时连通许多对端口&#xff0c;使每一对相互通信的主机都能像独占通信媒体…

有关Drools业务规则引擎的完整教程

与往常一样&#xff0c;我们在配套存储库EmailSchedulingRules中共享本教程中提供的代码。 业务规则很好地表现了某些领域的逻辑。 它们之所以有效&#xff0c;是因为它们可以直观直观地接近许多类型的领域专家的思维方式 。 其原因在于它们允许分解单个组件中的大问题。 这样…

[渝粤教育] 中国人民解放军陆军工程大学 机械基础 参考 资料

教育 -机械基础-章节资料考试资料-中国人民解放军陆军工程大学【】 第1章测试 1、【单选题】机器中&#xff0c;将其他形式的能转化为机械能的部分称为&#xff08; &#xff09;。 A、传动部分 B、动力部分 C、工作部分 D、控制部分 参考资料【 】 2、【单选题】具有确定的相对…

物联网无线数传通信模块:工业级高精度电源模块

电源模块是可以直接贴装在印刷电路板上的电源供应器&#xff0c;其特点是可为专用集成电路&#xff08;ASIC&#xff09;、数字信号处理器 (DSP)、微处理器、存储器、现场可编程门阵列 (FPGA) 及其他数字或模拟负载提供供电。一般来说&#xff0c;这类模块称为负载 (POL) 电源供…

[渝粤教育] 中国农业大学 大学计算机基础 参考 资料

教育 -大学计算机基础-章节资料考试资料-中国农业大学【】 第1单元测验 - 信息技术与计算机 1、【单选题】计算思维是运用计算机科学的( )进行问题求解、系统设计、以及人类行为理解等涵盖计算机科学之广度的一系列思维活动。 A、基础概念 B、思维方式 C、程序设计原理 D、操作…