Spring Cloud Kubernetes服務發現

banq發表於2019-01-07

Geecon 2018年, Mauricio Salatino談到了Spring Cloud Kubernetes專案。這個專案有很多好主意。令人印象最深刻的是Spring Cloud K8如何進行服務發現。它的工作原理如下:
  • 在K8s叢集中,沒有必要擁有Eureka。K8s中的ETCD擁有所有必要的資訊。
  • 您的應用程式將透過指定的K8s服務名稱聯絡K8s API伺服器以獲取端點資訊。
  • 然後可以透過Feign呼叫返回的服務。
  • 要讓DiscoveryClient正常執行,您需要做的 就是將Kubernetes服務名稱與spring.application.name屬性對齊。

聽起來很簡單,所以讓我們測試吧!

服務發現,相同的名稱空間不同的pod
讓我們看看那一個Spring Cloud Application:

package com.example.service2.mvc;

    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;

    @RestController
    public class Controller {

        @GetMapping(path = "/service2")
        public String respondPoint() {
            return "Hello I'm service2";
        }
    }


配置中:spring.application.name.

spring.application.name=service2-chart
server.port=8081


現在讓我們構建並將應用程式安裝到Kubernetes叢集中。 為了使它變得美觀和流暢,準備了helm chart.
  • $ eval $(minikube docker-env)
  • $ mvn clean install
  • $ helm install -n service2-chart service2-chart-0.1.0.tgz

helm chart應該安裝一切,但讓我們檢查一下服務:

$ kubectl -n default get services
NAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes       ClusterIP   10.96.0.1       <none>        443/TCP          58d
service2-chart   NodePort    10.100.48.206   <none>        8081:30467/TCP   18s


好的,我們將Kubernetes服務名稱與spring.application.name對齊。 

準備另外一個Spring Boot呼叫service2-chart app/K8s service.
首先,使用Feign客戶端,請注意我們只需要知道K8s服務名稱,就是這樣:

 package com.example.service1.mvc;

    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.GetMapping;

    @FeignClient(name = "service2-chart")
    public interface Service2Client {

        @GetMapping("/service2")
        String invokeService2();
    }


現在呼叫這個 service2-chart K8s 遠端服務:

  package com.example.service1.mvc;

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;

    @RestController 
    public class Controller {

        @Autowired
        private Service2Client service2Client;

        @GetMapping(path = "/service1")
        public String respondPoint() {
            final String service2Output = service2Client.invokeService2();
            return "Hello I'm Service1 ->"+service2Output;
        }
    }


一切準備就緒,讓我們測試一下:
  • $ eval $(minikube docker-env)
  • $ mvn clean install
  • $ helm install -n service1-chart service1-chart-0.1.0.tgz


Helm應該再次安裝所有內容,這是所需的輸出:

$ kubectl -n default get services  
NAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes       ClusterIP   10.96.0.1       <none>        443/TCP          58d
service1-chart   NodePort    10.101.7.4      <none>        8082:32391/TCP   3m
service2-chart   NodePort    10.100.48.206   <none>        8081:30467/TCP   17h


Helm charts 已經安裝:

$ helm list
NAME            REVISION    UPDATED                     STATUS      CHART                   APP VERSION NAMESPACE
service1-chart  1           Sun Dec 23 18:03:30 2018    DEPLOYED    service1-chart-0.1.0    1.0         default  
service2-chart  1           Sun Dec 23 01:05:17 2018    DEPLOYED    service2-chart-0.1.0    1.0         default


現在呼叫/service1 端點,這個端點會呼叫service2-chart K8s服務:

$ minikube service service1-chart --url
http://192.168.99.100:32391

tomask79:spring-service1 tomask79$ curl http://192.168.99.100:32391/service1
{"timestamp":"2018-12-23T19:57:12.020+0000",
"status":500,"error":"Internal Server Error",
"message":"Error creating bean with name 'ribbhttps://github.com/fabric8io/kubernetes-client]fabric8 kubernetes客戶端[/url] 無法在預設名稱空間中檢索端點資料。
要理解為什麼讓我們重複關於Kubernetes的基本規則:
<ul>
<li>在pod內執行的每個程式都在[url=https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/]服務帳戶[/url]標識下執行。
<li>如果未指定,則每個pod都在“default”服務賬戶下執行。
<li>為了使pod獲得K8s端點後設資料,對應的預設服務賬戶的特權 需要獲得至少是“view”clusterrole。 
</ul>
只要"view" readonly [url=https://kubernetes.io/docs/reference/access-authn-authz/rbac/user-facing-roles]clusterrole[/url] 就好:

<p class="indent">[code]$ kubectl create rolebinding default-view-binding --clusterrole=view --serviceaccount=default:default --namespace=default
rolebinding.rbac.authorization.k8s.io/default-view-binding created


再次curl呼叫/service1 端點:

$ curl http://192.168.99.100:32391/service1
Hello I'm Service1 ->Hello I'm service2


成功,我們透過一個K8s服務的名字呼叫在同一名稱空間內的服務!

服務發現,不同的名稱空間,不同的pods
這一次讓我們透過知道它的名字來嘗試呼叫生活在分離名稱空間中的kubernetes服務 。只需很少的編碼更改即可支援此功能!

首先讓我們建立名為“test”的新名稱空間:

 $ kubectl create namespace test


現在讓我們將service2-chart安裝到新的名稱空間中(這裡你需要helm ):

$ helm install -n service2-chart --namespace test service2-chart-0.1.0.tgz


下一步是告訴service1中的ribbon在哪裡查詢剛剛安裝的service2-chart服務。 
預設情況下,它列出當前名稱空間中的端點。要告訴他在另一個名稱空間中搜尋service2-chart, 您需要將以下屬性新增到application.properties中:

service2-chart.ribbon.KubernetesNamespace=test


現在讓我們重建並重新安裝service1應用程式到K8s叢集,預設名稱空間:
  • $ mvn clean install
  • $ helm package ./service1-chart --debug
  • $ helm install -n service1-chart service1-chart-0.1.0.tgz

這是測試之前所需的輸出(注意名稱空間):

$ helm list
NAME            REVISION    UPDATED                     STATUS      CHART                   APP VERSION NAMESPACE
service1-chart  1           Sun Dec 23 22:45:24 2018    DEPLOYED    service1-chart-0.1.0    1.0         default  
service2-chart  1           Sun Dec 23 22:09:00 2018    DEPLOYED    service2-chart-0.1.0    1.0         test


好的,讓我們嘗試呼叫service1-chart服務,該服務在另一個名稱空間中呼叫service2-chart:

$ minikube service service1-chart --url
http://192.168.99.100:30176
tomask79:spring-service1 tomask79$ curl http://192.168.99.100:30176/service1
{"timestamp":"2018-12-23T21:47:00.649+0000","status":500,"error":"Internal Server Error",
"message":"Error creating bean with name 'ribbview --serviceaccount=default:default
clusterrolebinding.rbac.authorization.k8s.io/test-view created


現在讓我們再次呼叫service1-chart:

$ curl http://192.168.99.100:30176/service1
Hello I'm Service1 ->Hello I'm service2



好的,這次我們透過知道它的名字來呼叫生活在分離名稱空間中的kubernetes服務 。我喜歡這種方法,因為您可以在不更改程式碼的情況下將您的微服務服務發現機制遷移 到kubernetes。

點選標題見原文!

相關文章