Spring Cloud Kubernetes指南

1.概述

當我們構建微服務解決方案時,Spring Cloud和Kubernetes都是最佳解決方案,因為它們提供了解決最常見挑戰的組件。但是,如果我們決定選擇Kubernetes作為我們解決方案的主要容器管理器和部署平台,我們仍然可以主要通過Spring Cloud Kubernetes項目使用Spring Cloud的有趣功能。

無疑,這個相對較新的項目為Spring Boot應用程序提供了與Kubernetes的輕鬆集成。在開始之前,研究一下如何在Minikube(本地Kubernetes環境)上部署Spring Boot應用程序可能會有所幫助.

在本教程中,我們將:

  • 在我們的本地機器上安裝Minikube
  • 用兩個獨立的Spring Boot應用程序通過REST通信來開發微服務架構示例
  • 使用Minikube在單節點群集上設置應用程序
  • 使用YAML配置文件部署應用程序

2.場景

在我們的示例中,我們使用旅行社向客戶提供各種交易的場景,這些客戶將不時查詢旅行社服務。我們將使用它來演示:

  • 通過Spring Cloud Kubernetes發現服務
  • 配置管理並使用Spring Cloud Kubernetes Config將Kubernetes ConfigMap和秘密注入應用程序Pod
  • 使用Spring Cloud Kubernetes Ribbon進行負載平衡

3.環境設置

首先,我們需要在本地計算機上安裝Minikube ,最好在VM驅動程序(例如VirtualBox)上安裝。在執行此環境設置之前,還建議先查看Kubernetes及其主要功能。

讓我們啟動本地單節點Kubernetes集群:

minikube start --vm-driver=virtualbox

此命令創建一個使用VirtualBox驅動程序運行Minikube群集的虛擬機。現在, kubectl的默認上下文將是minikube 。但是,為了能夠在上下文之間切換,我們使用:

kubectl config use-context minikube

啟動Minikube之後,我們可以連接到Kubernetes儀表板以訪問日誌並輕鬆監視我們的服務,pod,ConfigMap和Secrets:

minikube dashboard

3.1。部署方式

首先,讓我們從GitHub中獲取示例。

在這一點上,我們可以從父文件夾運行“ deployment-travel-client.sh”腳本,也可以逐個執行每條指令以很好地理解該過程:

### build the repository

 mvn clean install



 ### set docker env

 eval $(minikube docker-env)



 ### build the docker images on minikube

 cd travel-agency-service

 docker build -t travel-agency-service .

 cd ../client-service

 docker build -t client-service .

 cd ..



 ### secret and mongodb

 kubectl delete -f travel-agency-service/secret.yaml

 kubectl delete -f travel-agency-service/mongo-deployment.yaml



 kubectl create -f travel-agency-service/secret.yaml

 kubectl create -f travel-agency-service/mongo-deployment.yaml



 ### travel-agency-service

 kubectl delete -f travel-agency-service/travel-agency-deployment.yaml

 kubectl create -f travel-agency-service/travel-agency-deployment.yaml



 ### client-service

 kubectl delete configmap client-service

 kubectl delete -f client-service/client-service-deployment.yaml



 kubectl create -f client-service/client-config.yaml

 kubectl create -f client-service/client-service-deployment.yaml



 # Check that the pods are running

 kubectl get pods

4.服務發現

該項目為我們提供了Kubernetes中ServiceDiscovery接口的實現。在微服務環境中,通常有多個Pod運行同一服務。 Kubernetes將服務公開為端點的集合,可以從在同一Kubernetes集群中的pod中運行的Spring Boot Application中獲取和訪問這些端點

例如,在我們的示例中,我們有旅行社服務的多個副本,可從我們的客戶服務以http://travel-agency-service:8080 。但是,這在內部將轉換為訪問不同的pod,例如travel-agency-service-7c9cfff655-4hxnp

Spring Cloud Kubernetes Ribbon使用此功能在服務的不同端點之間實現負載平衡。

通過在客戶端應用程序上添加spring-cloud-starter-kubernetes依賴項,我們可以輕鬆使用Service Discovery:

<dependency>

 <groupId>org.springframework.cloud</groupId>

 <artifactId>spring-cloud-starter-kubernetes</artifactId>

 </dependency>

另外,我們應該添加@EnableDiscoveryClient並通過在類中使用@AutowiredDiscoveryClient注入到ClientController中:

@SpringBootApplication

 @EnableDiscoveryClient

 public class Application {

 public static void main(String[] args) {

 SpringApplication.run(Application.class, args);

 }

 }
@RestController

 public class ClientController {

 @Autowired

 private DiscoveryClient discoveryClient;

 }

5. ConfigMaps

通常,微服務需要某種配置管理。例如,在Spring Cloud應用程序中,我們將使用Spring Cloud Config Server。

但是,我們可以通過使用Kubernetes提供的ConfigMap來實現此目的-前提是我們打算將其僅用於不敏感,未加密的信息。或者,如果我們要共享的信息很敏感,那麼我們應該選擇使用Secrets

在我們的示例中,我們在client-service Spring Boot應用程序上使用ConfigMaps。讓我們創建一個client-config. yaml文件,用於定義client-service的ConfigMap:

apiVersion: v1 by d

 kind: ConfigMap

 metadata:

 name: client-service

 data:

 application.properties: |-

 bean.message=Testing reload! Message from backend is: %s <br/> Services : %s

重要的是,ConfigMap的名稱必須與“ application.properties”文件中指定的應用程序名稱相匹配。在這種情況下,它是client-service 。接下來,我們應該在Kubernetes上為client-service創建ConfigMap:

kubectl create -f client-config.yaml

現在,讓我們使用@Configuration@ConfigurationProperties創建一個配置類ClientConfig並註入到ClientController

@Configuration

 @ConfigurationProperties(prefix = "bean")

 public class ClientConfig {



 private String message = "Message from backend is: %s <br/> Services : %s";



 // getters and setters

 }
@RestController

 public class ClientController {



 @Autowired

 private ClientConfig config;



 @GetMapping

 public String load() {

 return String.format(config.getMessage(), "", "");

 }

 }

如果我們不指定ConfigMap,那麼我們應該期望看到默認消息,該消息在類中設置。但是,當我們創建ConfigMap時,該默認消息將被該屬性覆蓋。

此外,每次我們決定更新ConfigMap時,頁面上的消息都會相應更改:

kubectl edit configmap client-service

6.Secrets

讓我們通過查看示例中的MongoDB連接設置的規範來了解Secrets的工作方式。我們將在Kubernetes上創建環境變量,然後將其註入到Spring Boot應用程序中。

6.1。創建一個Secret

第一步是創建一個secret.yaml文件,將usernamepassword編碼為Base 64

apiVersion: v1

 kind: Secret

 metadata:

 name: db-secret

 data:

 username: dXNlcg==

 password: cDQ1NXcwcmQ=

讓我們在Kubernetes集群上應用Secret配置:

kubectl apply -f secret.yaml

6.2。創建一個MongoDB服務

現在,我們應該創建MongoDB服務和部署travel-agency-deployment.yaml文件。特別是,在部署部分,我們將使用之前定義的Secret usernamepassword

apiVersion: extensions/v1beta1

 kind: Deployment

 metadata:

 name: mongo

 spec:

 replicas: 1

 template:

 metadata:

 labels:

 service: mongo

 name: mongodb-service

 spec:

 containers:

 - args:

 - mongod

 - --smallfiles

 image: mongo:latest

 name: mongo

 env:

 - name: MONGO_INITDB_ROOT_USERNAME

 valueFrom:

 secretKeyRef:

 name: db-secret

 key: username

 - name: MONGO_INITDB_ROOT_PASSWORD

 valueFrom:

 secretKeyRef:

 name: db-secret

 key: password

默認情況下, mongo:latest映像將在名為admin.的數據庫上創建具有用戶usernamepassword的用戶admin.

6.3。在旅行社服務上設置MongoDB

更新應用程序屬性以添加數據庫相關信息很重要。雖然我們可以自由指定數據庫名稱admin ,但是在這裡我們隱藏了最敏感的信息,例如usernamepassword

spring.cloud.kubernetes.reload.enabled=true

 spring.cloud.kubernetes.secrets.name=db-secret

 spring.data.mongodb.host=mongodb-service

 spring.data.mongodb.port=27017

 spring.data.mongodb.database=admin

 spring.data.mongodb.username=${MONGO_USERNAME}

 spring.data.mongodb.password=${MONGO_PASSWORD}

現在,讓我們看一下travel-agency-deployment屬性文件,以使用連接到mongodb-service所需的用戶名和密碼信息更新服務和部署。

這是文件的相關部分,其中一部分與MongoDB連接有關:

env:

 - name: MONGO_USERNAME

 valueFrom:

 secretKeyRef:

 name: db-secret

 key: username

 - name: MONGO_PASSWORD

 valueFrom:

 secretKeyRef:

 name: db-secret

 key: password

7.與功能區通信

在微服務環境中,我們通常需要將服務複製到的Pod列表,以執行負載平衡。這是通過使用Spring Cloud Kubernetes Ribbon提供的機制來完成的。此機制可以自動發現並到達特定服務的所有端點,隨後,它會使用有關端點的信息填充Ribbon ServerList

首先,將spring-cloud-starter-kubernetes-ribbon依賴項添加到我們的client-service pom.xml文件中:

<dependency>

 <groupId>org.springframework.cloud</groupId>

 <artifactId>spring-cloud-starter-kubernetes-ribbon</artifactId>

 </dependency>

下一步是將註釋@RibbonClient添加到我們的client-service應用程序中:

@RibbonClient(name = "travel-agency-service")

當填充端點列表時,Kubernetes客戶端將搜索與使用@RibbonClient註釋定義的服務名稱匹配的,位於當前名稱空間/項目中的已註冊端點。

我們還需要在應用程序屬性中啟用功能區客戶端:

ribbon.http.client.enabled=true

8.附加功能

8.1。 Hystrix

Hystrix**幫助構建容錯和彈性的應用程序。**其主要目標是快速失敗和快速恢復。

特別地,在我們的示例中,我們使用Hystrix通過使用@EnableCircuitBreaker註釋Spring Boot應用程序類在client-server上實現斷路器模式。

此外,我們通過使用@HystrixCommand()註釋TravelAgencyService.getDeals()方法來使用後備功能。這意味著如果發生後備, getFallBackName()調用getFallBackName()並返回“ Fallback”消息:

@HystrixCommand(fallbackMethod = "getFallbackName", commandProperties = {

 @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000") })

 public String getDeals() {

 return this.restTemplate.getForObject("http://travel-agency-service:8080/deals", String.class);

 }



 private String getFallbackName() {

 return "Fallback";

 }

8.2。Pod健康指標

我們可以利用Spring Boot HealthIndicator和Spring Boot Actuator向用戶展示與健康相關的信息。

特別地,Kubernetes健康指標提供:

  • Pod名稱
  • IP地址
  • 命名空間
  • 服務帳號
  • 節點名稱
  • 一個標誌,指示Spring Boot應用程序在Kubernetes內部還是外部

9.結論

在本文中,我們提供了Spring Cloud Kubernetes項目的全面概述。

那麼為什麼要使用它呢?如果我們以Kubernetes為微服務平台而紮根,但仍然欣賞Spring Cloud的功能,那麼Spring Cloud Kubernetes可以為我們提供兩全其美的優勢。

該示例的完整源代碼可在GitHub上找到