Spring Cloud 部署時如何使用 Kubernetes 作爲註冊中心和配置中心

一、Spring Cloud 支持的常見註冊中心和配置中心。

  • Spring Cloud 自帶的註冊中心Eureka以及config配置中心
  • Nacos,支持註冊中心和配置中心等,可以參考:https://www.cnblogs.com/laoqing/p/17797759.html
  • Zookeeper
  • Consul
  • Etcd
  • Kubernetes ,當Spring Cloud 服務都是通過Kubernetes 部署時,可以使用Kubernetes 作爲註冊中心和配置中心。

二、Spring Cloud 部署時如何使用 Kubernetes 作爲註冊中心和配置中心

Spring Cloud Kubernetes提供了使用Kubernete本地服務的Spring Cloud通用接口實現。該存儲庫中提供的項目的主要目標是促進在Kubernetes中運行的Spring Cloud和Spring Boot應用程序的集成。

在Springboot中,Starters 是一種方便的依賴描述符,可以包含在應用程序中。包括一個啓動器來獲取特性集的依賴項和Spring Boot自動配置。在使用Kubernetes 作爲註冊中心和配置中心時,需要集成如下的Starters 。

1、將服務名稱解析爲Kubernetes Services的發現客戶端實現。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-kubernetes</artifactId>
</dependency>

示例代碼:

@SpringBootApplication
@EnableDiscoveryClient
public class Application {
  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}
//Then you can inject the client in your code simply by autowiring it, as the following example shows:
@Autowired
private DiscoveryClient discoveryClient;

配置項:

spring:
  cloud:
    kubernetes:
      enabled: true
#      discovery:
#        all-namespaces: true
#        enabled: true

2、從Kubernetes ConfigMaps和Secrets加載應用程序屬性。ConfigMap或Secret更改時重新加載應用程序屬性。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-kubernetes-config</artifactId>
</dependency>

使用 Kubernetes 的ConfigMap或Secret作爲配置中心。

Kubernetes提供了一個名爲ConfigMap的資源,以鍵值對或嵌入式application.properties或application.yaml文件的形式將要傳遞給應用程序的參數外部化。Spring Cloud Kubernetes Config項目使Kubernete ConfigMap實例在應用程序引導期間可用,並在觀察到的ConfigMap實例上檢測到更改時觸發bean或Spring上下文的熱重新加載。
默認行爲是基於Kubernetes ConfigMap創建ConfigMapPropertySource,該ConfigMap的metadata.name值爲Spring應用程序的名稱(由其Spring.application.name屬性定義)或bootstrap.properties文件中定義的自定義名稱,位於以下鍵下:Spring.cloud.Kubernetes.config.name。
但是,可以使用多個ConfigMap實例進行更高級的配置。spring.cloud.kubernetes.config.sources列表使這成爲可能。例如,您可以定義以下ConfigMap實例:

spring:
  application:
    name: cloud-k8s-app
  cloud:
    kubernetes:
      config:
        name: default-name
        namespace: default-namespace
        sources:
         # Spring Cloud Kubernetes looks up a ConfigMap named c1 in namespace default-namespace
         - name: c1
         # Spring Cloud Kubernetes looks up a ConfigMap named default-name in whatever namespace n2
         - namespace: n2
         # Spring Cloud Kubernetes looks up a ConfigMap named c3 in namespace n3
         - namespace: n3
           name: c3

如果沒有設置spring.cloud.kubernetes.config.namespace,則將在應用程序運行的命名空間中查找名爲c1的ConfigMap。
找到的任何匹配的ConfigMap都將按如下方式進行處理:
應用各個配置屬性。
將任何名爲application.yaml的屬性的內容作爲yaml應用。
將任何名爲application.properties的屬性的內容作爲屬性文件應用。
上述流的唯一例外是ConfigMap包含單個鍵,該鍵指示文件是YAML或屬性文件。在這種情況下,鍵的名稱不必是application.yaml或application.properties(它可以是任何東西),並且屬性的值被正確處理。此功能有助於使用類似以下內容創建ConfigMap的用例:

kubectl create configmap game-config --from-file=/path/to/app-config.yaml

假設我們有一個名爲demo的Spring Boot應用程序,它使用以下屬性來讀取其線程池配置。
pool.size.core
pool.size.maximum
這可以外部化爲yaml格式的配置映射,如下所示:

kind: ConfigMap
apiVersion: v1
metadata:
  name: demo
data:
  pool.size.core: 1
  pool.size.max: 16

單個屬性在大多數情況下都可以正常工作。然而,有時,嵌入yaml更方便。在這種情況下,我們使用一個名爲application.yaml的屬性來嵌入我們的yaml,如下所示:

kind: ConfigMap
apiVersion: v1
metadata:
  name: demo
data:
  application.yaml: |-
    pool:
      size:
        core: 1
        max:16
kind: ConfigMap
apiVersion: v1
metadata:
  name: demo
data:
  custom-name.yaml: |-
    pool:
      size:
        core: 1
        max:16

您還可以根據讀取ConfigMap時合併在一起的活動配置文件,對Spring Boot應用程序進行不同的配置。您可以使用application.properties或application.yaml屬性爲不同的配置文件提供不同的屬性值,指定特定於配置文件的值,每個值都在自己的文檔中(由---序列表示),如下所示:

kind: ConfigMap
apiVersion: v1
metadata:
  name: demo
data:
  application.yml: |-
    greeting:
      message: Say Hello to the World
    farewell:
      message: Say Goodbye
    ---
    spring:
      profiles: development
    greeting:
      message: Say Hello to the Developers
    farewell:
      message: Say Goodbye to the Developers
    ---
    spring:
      profiles: production
    greeting:
      message: Say Hello to the Ops

要告訴Spring Boot應該在引導時啓用哪個配置文件,可以傳遞Spring_PROFILES_ACTIVE環境變量。爲此,您可以使用環境變量啓動Spring Boot應用程序,您可以在容器規範的PodSpec中定義該環境變量。部署資源文件,如下所示:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-name
  labels:
    app: deployment-name
spec:
  replicas: 1
  selector:
    matchLabels:
      app: deployment-name
  template:
    metadata:
      labels:
        app: deployment-name
    spec:
        containers:
        - name: container-name
          image: your-image
          env:
          - name: SPRING_PROFILES_ACTIVE
            value: "development"

使用ConfigMap實例的另一個選項是通過運行Spring Cloud Kubernetes應用程序並讓Spring Cloud Kubornetes從文件系統中讀取它們,將它們裝載到Pod中。此行爲由spring.cloud.kubernetes.config.paths屬性控制。您可以在前面描述的機制的基礎上使用它,也可以使用它來代替前面介紹的機制。可以使用、分隔符在spring.cloud.kubernetes.config.path中指定多個(精確的)文件路徑。

NameTypeDefaultDescription

spring.cloud.kubernetes.config.enabled

Boolean

true

Enable Secrets PropertySource

spring.cloud.kubernetes.config.name

String

${spring.application.name}

Sets the name of ConfigMap to look up

spring.cloud.kubernetes.config.namespace

String

Client namespace

Sets the Kubernetes namespace where to lookup

spring.cloud.kubernetes.config.paths

List

null

Sets the paths where ConfigMap instances are mounted

spring.cloud.kubernetes.config.enableApi

Boolean

true

Enable or disable consuming ConfigMap instances through APIs

Kubernetes有Secrets的概念,用於存儲密碼、OAuth令牌等敏感數據。該項目提供了與Secrets集成,使Spring Boot應用程序可以訪問機密。您可以通過設置spring.cloud.kubernetes.secrets.enabled屬性來顯式啓用或禁用此功能。
啓用後,SecretsPropertySource從以下來源查找Kubernetes的Secrets:
從祕密裝載中遞歸讀取
以應用程序命名(由spring.application.name定義)
匹配一些標籤
請注意,默認情況下,由於安全原因,不會啓用通過API(上面第2點和第3點)使用Secrets。此外,我們建議容器通過裝入的卷共享機密。如果您啓用通過API消費機密,我們建議您使用[授權策略,如RBAC]來限制對機密的訪問(https://kubernetes.io/docs/concepts/configuration/secret/#best-實踐)。
如果發現了這些祕密,應用程序就可以使用它們的數據。
假設我們有一個名爲demo的spring-boot應用程序,它使用屬性讀取其數據庫配置。我們可以使用以下命令創建Kubernetes機密:

oc create secret generic db-secret --from-literal=username=user --from-literal=password=p455w0rd

前面的命令將創建以下機密(可以通過使用oc-get-secrets-db-secret-o yaml看到):

apiVersion: v1
data:
  password: cDQ1NXcwcmQ=
  username: dXNlcg==
kind: Secret
metadata:
  creationTimestamp: 2017-07-04T09:15:57Z
  name: db-secret
  namespace: default
  resourceVersion: "357496"
  selfLink: /api/v1/namespaces/default/secrets/db-secret
  uid: 63c89263-6099-11e7-b3da-76d6186905a8
type: Opaque

請注意,數據包含create命令提供的文本的Base64編碼版本。
然後您的應用程序可以使用此機密 — 例如,通過將機密的值導出爲環境變量:

apiVersion: v1
kind: Deployment
metadata:
  name: ${project.artifactId}
spec:
   template:
     spec:
       containers:
         - env:
            - name: DB_USERNAME
              valueFrom:
                 secretKeyRef:
                   name: db-secret
                   key: username
            - name: DB_PASSWORD
              valueFrom:
                 secretKeyRef:
                   name: db-secret
                   key: password

 

3、功能區客戶端負載均衡器,具有從Kubernetes端點獲得的服務器列表。

調用微服務的Spring Cloud客戶端應用程序應該對依賴客戶端負載平衡功能感興趣,以便自動發現它可以在哪個端點訪問給定的服務。這個機制已經在spring-cloud kubernetes ribbon項目中實現,其中kubernetes客戶端填充一個ribbon ServerList,其中包含有關這些端點的信息。
該實現是以下啓動器的一部分,您可以通過將其依賴項添加到pom文件中來使用它:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-kubernetes-ribbon</artifactId>
</dependency>

當填充端點列表時,Kubernetes客戶端通過匹配Ribbon客戶端註釋中定義的服務名稱來搜索當前命名空間或項目中的已註冊端點,如下所示:

@RibbonClient(name = "name-service")

您可以通過使用以下格式在application.properties中提供屬性(通過應用程序的專用ConfigMap)來配置Ribbon的行爲:<服務名稱>.bribbon<功能區配置鍵>,其中:
<服務的名稱>對應於您通過Ribbon訪問的服務名稱,如使用@RibbonClient註釋配置的(如前面示例中的名稱服務)。
<Ribbon configuration key>是Ribbon的CommonClientConfigKey類定義的Ribbon配置鍵之一。
此外,spring cloud kubernetes ribbon項目定義了兩個額外的配置鍵,以進一步控制ribbon與kubernetes的交互方式。特別是,如果一個端點定義了多個端口,則默認行爲是使用找到的第一個端口。要更具體地選擇要在多端口服務中使用的端口,可以使用PortName鍵。如果你想指定應該在哪個Kubernetes命名空間中查找目標服務,你可以使用KubernetsNamespace鍵,記住在這兩種情況下都要用你的服務名稱和功能區前綴作爲這些鍵的前綴,如前所述。

Property KeyTypeDefault Value

spring.cloud.kubernetes.ribbon.enabled

boolean

true

spring.cloud.kubernetes.ribbon.mode

KubernetesRibbonMode

POD

spring.cloud.kubernetes.ribbon.cluster-domain

string

cluster.local

spring.cloud.kubernetes.ribbon.mode支持POD和SERVICE模式。
POD模式是通過獲取Kubernetes的POD IP地址並使用Ribbon來實現負載平衡。POD模式使用Ribbon的負載平衡不支持Kubernetes的負載平衡,不支持Istio的流量策略。
SERVICE模式直接基於功能區的服務名稱。Get Kubernetes服務被連接到服務名稱中。{namespace}.svc。{cluster.domain}:{port},例如:demo1.default.svc.cluster.local:8080。SERVICE模式使用Kubernetes服務的負載平衡來支持Istio的流量策略。
spring.cloud.kubernetes.ribbon.cluster-domain設置自定義的kubernetes集羣域後綴。默認值爲:“cluster.local”

4、所有Spring Cloud Kubernetes功能,當選擇這個maven選項時,可以只加入這一個依賴

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-kubernetes-all</artifactId>
</dependency>

更多關於Spring Cloud如何同Kubernetes 進行結合,可以參考https://cloud.spring.io/spring-cloud-kubernetes/spring-cloud-kubernetes.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章