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
並通過在類中使用@Autowired
將DiscoveryClient
注入到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
文件,將username
和password
編碼為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 username
和password
:
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.
的數據庫上創建具有用戶username
和password
的用戶admin.
6.3。在旅行社服務上設置MongoDB
更新應用程序屬性以添加數據庫相關信息很重要。雖然我們可以自由指定數據庫名稱admin
,但是在這裡我們隱藏了最敏感的信息,例如username
和password
:
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上找到。