本文大綱
接下來的內容由以下幾部分組成:
- 什麼是SpringCloud Gateway
- SpringCloud Gateway實戰參考
- kubernetes上的SpringCloud Gateway
- 實戰環境信息
- 實戰源碼下載
- 開發webdemo
- 開發k8sgatewaydemo
- 解決權限問題
- 最後一個疑問
什麼是SpringCloud Gateway
SpringCloud Gateway是SpringCloud技術棧下的網關服務框架,在基於SpringCloud的微服務環境中,外部請求會到達SpringCloud Gateway應用,該應用對請求做轉發、過濾、鑑權、熔斷等前置操作,一個典型的請求響應流程如下所示:
SpringCloud Gateway實戰參考
如果您之前沒有使用過SpringCloud Gateway,推薦您閱讀《速體驗SpringCloud Gateway》,有時間的話動手實戰效果更佳,只需編寫少量代碼就能快速熟悉這個SpringCloud技術棧中非常重要的功能;
kubernetes上的SpringCloud Gateway
注意以下兩個知識點:
- SpringCloud Gateway之所以能將外部請求路由到正確的後臺服務上,是因爲註冊中心的存在,SpringCloud Gateway可以在註冊中心取得所有服務的信息,因此它可以根據路徑和服務的對應關係,將請求轉發到對應的服務上;
- 如果您看過本系列的上一篇 《spring-cloud-kubernetes的服務發現和輪詢實戰(含熔斷)》,您就知道spring-cloud-kubernetes框架可以獲取kubernetes環境內的所有服務(這裏說的服務就是kubernetes的service);
將以上兩個知識點結合起來,於是可以推測:運行在kubernetes環境的SpringCloud Gateway應用,如果使用了spring-cloud-kubernetes框架就能得到kubernetes的service列表,因此可以承擔網關的角色,將外部請求轉發至kubernetes內的service上,最終到達對應的Pod;
架構如下圖所示,請注意黃色背景的對話框,裏面標識了關鍵操作:
至此,理論分析已經完成,我們來實戰驗證這個理論,接下來我們開發兩個java應用:
- 先開發一個普通的web服務,名爲webdemo,提供一個http接口;
- 再開發一個SpringCloud Gateway應用,名爲k8sgatewaydemo;
環境信息
本次實戰的環境和版本信息如下:
- 操作系統:CentOS Linux release 7.6.1810
- minikube:1.1.1
- Java:1.8.0_191
- Maven:3.6.0
- fabric8-maven-plugin插件:3.5.37
- spring-cloud-kubernetes:1.0.1.RELEASE
- spring cloud:Greenwich.SR2
- springboot:2.1.6.RELEASE
源碼下載
如果您不打算寫代碼,也可以從GitHub上下載本次實戰的源碼,地址和鏈接信息如下表所示:
名稱 |
鏈接 |
備註 |
---|---|---|
項目主頁 |
https://github.com/zq2599/blog_demos
|
該項目在GitHub上的主頁 |
git倉庫地址(https) |
https://github.com/zq2599/blog_demos.git |
該項目源碼的倉庫地址,https協議 |
git倉庫地址(ssh) |
[email protected]:zq2599/blog_demos.git |
該項目源碼的倉庫地址,ssh協議 |
這個git項目中有多個文件夾,本章的兩個應用分別在webdemo和k8sgatewaydemo文件夾下; 下圖紅框中是webdemo應用的源碼:
下圖紅框中是k8sgatewaydemo應用的源碼:
下面是詳細的編碼過程;
開發webdemo
webdemo是個極其普通的spring boot應用,和SpringCloud沒有任何關係;
- webdemo提供一個http接口,將請求header中名爲extendtag的參數返回給請求方,controller類如下:
@RestController @RequestMapping("/hello") public class HelloController { @RequestMapping(value = "time", method = RequestMethod.GET) public String hello(HttpServletRequest request){ return "hello, " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + ", extendtag [" + request.getHeader("extendtag") + "]"; } }
- 啓動類WebdemoApplication.java:
@SpringBootApplication public class WebdemoApplication { public static void main(String[] args) { SpringApplication.run(WebdemoApplication.class, args); } }
- 要注意的是pom.xml,裏面通過名爲fabric8-maven-plugin的maven插件,將webdemo快速部署到minikube環境:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.bolingcavalry</groupId> <artifactId>webdemo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>webdemo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-boot.version>2.1.6.RELEASE</spring-boot.version> <fabric8.maven.plugin.version>3.5.37</fabric8.maven.plugin.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${spring-boot.version}</version> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> <plugin> <!--skip deploy --> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> <version>${maven-deploy-plugin.version}</version> <configuration> <skip>true</skip> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>${maven-surefire-plugin.version}</version> <configuration> <skipTests>true</skipTests> <!-- Workaround for https://issues.apache.org/jira/browse/SUREFIRE-1588 --> <useSystemClassLoader>false</useSystemClassLoader> </configuration> </plugin> <plugin> <groupId>io.fabric8</groupId> <artifactId>fabric8-maven-plugin</artifactId> <version>${fabric8.maven.plugin.version}</version> <executions> <execution> <id>fmp</id> <goals> <goal>resource</goal> </goals> </execution> </executions> </plugin> </plugins> </build> <profiles> <profile> <id>kubernetes</id> <build> <plugins> <plugin> <groupId>io.fabric8</groupId> <artifactId>fabric8-maven-plugin</artifactId> <version>${fabric8.maven.plugin.version}</version> <executions> <execution> <id>fmp</id> <goals> <goal>resource</goal> <goal>build</goal> </goals> </execution> </executions> <configuration> <enricher> <config> <fmp-service> <type>NodePort</type> </fmp-service> </config> </enricher> </configuration> </plugin> </plugins> </build> </profile> </profiles> </project>
- 以上就是webdemo應用的內容了,接下來要編譯、構建、部署到minikube環境,在pom.xml執行以下命令即可:
mvn clean install fabric8:deploy -Dfabric8.generator.from=fabric8/java-jboss-openjdk8-jdk -Pkubernetes
部署完成後終端輸出類似如下成功信息:
[INFO] [INFO] <<< fabric8-maven-plugin:3.5.37:deploy (default-cli) < install @ webdemo <<< [INFO] [INFO] [INFO] --- fabric8-maven-plugin:3.5.37:deploy (default-cli) @ webdemo --- [INFO] F8: Using Kubernetes at https://192.168.121.133:8443/ in namespace default with manifest /usr/local/work/k8s/webdemo/target/classes/META-INF/fabric8/kubernetes.yml [INFO] Using namespace: default [INFO] Updating a Service from kubernetes.yml [INFO] Updated Service: target/fabric8/applyJson/default/service-webdemo.json [INFO] Using namespace: default [INFO] Updating Deployment from kubernetes.yml [INFO] Updated Deployment: target/fabric8/applyJson/default/deployment-webdemo.json [INFO] F8: HINT: Use the command `kubectl get pods -w` to watch your pods start up [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 11.804 s [INFO] Finished at: 2019-07-07T21:32:26+08:00 [INFO] ------------------------------------------------------------------------
- 查看service和pod,確認一切正常:
[root@minikube webdemo]# kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 29d webdemo NodePort 10.106.98.137 <none> 8080:30160/TCP 115m [root@minikube webdemo]# kubectl get pod NAME READY STATUS RESTARTS AGE webdemo-c9f774b9-gsbgx 1/1 Running 0 3m13s
- 使用minikube命令取得webdemo服務對外暴露的地址:
[root@minikube webdemo]# minikube service webdemo --url http://192.168.121.133:30160
可見外部通過地址:http://192.168.121.133:30160 即可訪問到webdemo應用; 7. 在瀏覽器輸入地址:http://192.168.121.133:30160/hello/time ,即可驗證webdemo的http接口是否正常,如下圖,由於header中沒有extendtag屬性,因此返回的extendtag爲null:
至此,webdemo在minikue上已經正常運行,該開發gateway應用了;
開發k8sgatewaydemo
- 基於maven創建一個名爲k8sgatewaydemo的springboot應用,pom.xml內容如下:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.bolingcavalry</groupId> <artifactId>k8sgatewaydemo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>k8sgatewaydemo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-boot.version>2.1.6.RELEASE</spring-boot.version> <maven-checkstyle-plugin.failsOnError>false</maven-checkstyle-plugin.failsOnError> <maven-checkstyle-plugin.failsOnViolation>false</maven-checkstyle-plugin.failsOnViolation> <maven-checkstyle-plugin.includeTestSourceDirectory>false</maven-checkstyle-plugin.includeTestSourceDirectory> <maven-compiler-plugin.version>3.5</maven-compiler-plugin.version> <maven-deploy-plugin.version>2.8.2</maven-deploy-plugin.version> <maven-failsafe-plugin.version>2.18.1</maven-failsafe-plugin.version> <maven-surefire-plugin.version>2.21.0</maven-surefire-plugin.version> <fabric8.maven.plugin.version>3.5.37</fabric8.maven.plugin.version> <springcloud.kubernetes.version>1.0.1.RELEASE</springcloud.kubernetes.version> <spring-cloud.version>Greenwich.SR2</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-kubernetes-core</artifactId> <version>${springcloud.kubernetes.version}</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-kubernetes-discovery</artifactId> <version>${springcloud.kubernetes.version}</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-kubernetes-ribbon</artifactId> <version>${springcloud.kubernetes.version}</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-commons</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${spring-boot.version}</version> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> <plugin> <!--skip deploy --> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> <version>${maven-deploy-plugin.version}</version> <configuration> <skip>true</skip> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>${maven-surefire-plugin.version}</version> <configuration> <skipTests>true</skipTests> <!-- Workaround for https://issues.apache.org/jira/browse/SUREFIRE-1588 --> <useSystemClassLoader>false</useSystemClassLoader> </configuration> </plugin> <plugin> <groupId>io.fabric8</groupId> <artifactId>fabric8-maven-plugin</artifactId> <version>${fabric8.maven.plugin.version}</version> <executions> <execution> <id>fmp</id> <goals> <goal>resource</goal> </goals> </execution> </executions> </plugin> </plugins> </build> <profiles> <profile> <id>kubernetes</id> <build> <plugins> <plugin> <groupId>io.fabric8</groupId> <artifactId>fabric8-maven-plugin</artifactId> <version>${fabric8.maven.plugin.version}</version> <executions> <execution> <id>fmp</id> <goals> <goal>resource</goal> <goal>build</goal> </goals> </execution> </executions> <configuration> <enricher> <config> <fmp-service> <type>NodePort</type> </fmp-service> </config> </enricher> </configuration> </plugin> </plugins> </build> </profile> </profiles> </project>
上述pom文件中有以下幾點需要注意: 第一、 依賴spring-cloud-kubernetes-core和spring-cloud-kubernetes-discovery,這樣能用到spring-cloud-kubernetes提供的服務發現能力; 第二、依賴spring-cloud-starter-gateway,這樣能用上SpringCloud的gateway能力; 第三、不要依賴spring-boot-starter-web,會和spring-cloud-starter-gateway衝突,啓動時拋出以下異常:
2019-07-06 08:12:09.188 WARN 1 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'routeDefinitionRouteLocator' defined in class path resource [org/springframework/cloud/gateway/config/GatewayAutoConfiguration.class]: Unsatisfied dependency expressed through method 'routeDefinitionRouteLocator' parameter 1; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'modifyRequestBodyGatewayFilterFactory' defined in class path resource [org/springframework/cloud/gateway/config/GatewayAutoConfiguration.class]: Unsatisfied dependency expressed through method 'modifyRequestBodyGatewayFilterFactory' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.http.codec.ServerCodecConfigurer' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
- 開發SpringCloud Gateway的啓動類K8sgatewaydemoApplication.java,裏面也包含了網關路由配置的實例化,除了配置路徑和轉發服務的關係,還在請求的header中添加了extendtag屬性,請注意註釋的內容:
@SpringBootApplication @EnableDiscoveryClient public class K8sgatewaydemoApplication { public static void main(String[] args) { SpringApplication.run(K8sgatewaydemoApplication.class, args); } @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { return builder.routes() //增加一個path匹配,以"/customize/hello/"開頭的請求都在此路由 .route(r -> r.path("/customize/hello/**") //表示將路徑中的第一級參數刪除,用剩下的路徑與webdemo的路徑做拼接, //這裏就是"lb://webdemo/hello/",能匹配到webdemo的HelloController的路徑 .filters(f -> f.stripPrefix(1) //在請求的header中添加一個key&value .addRequestHeader("extendtag", "geteway-" + System.currentTimeMillis())) //指定匹配服務webdemo,lb是load balance的意思 .uri("lb://webdemo") ).build(); } }
從上述代碼可見,K8sgatewaydemoApplication與普通環境下的SpringCloud Gateway並無差別,都是通過EnableDiscoveryClient註解獲取服務列表,配置RouteLocator實現路由邏輯; 3. 配置文件application.yml的內容:
spring: application: name: gateway cloud: gateway: discovery: locator: enabled: true lowerCaseServiceId: true
- 以上就是k8sgatewaydemo應用的內容了,接下來要編譯、構建、部署到minikube環境,在pom.xml執行以下命令即可:
mvn clean install fabric8:deploy -Dfabric8.generator.from=fabric8/java-jboss-openjdk8-jdk -Pkubernetes
部署完成後終端輸出類似如下成功信息:
[INFO] [INFO] <<< fabric8-maven-plugin:3.5.37:deploy (default-cli) < install @ k8sgatewaydemo <<< [INFO] [INFO] [INFO] --- fabric8-maven-plugin:3.5.37:deploy (default-cli) @ k8sgatewaydemo --- [INFO] F8: Using Kubernetes at https://192.168.121.133:8443/ in namespace default with manifest /usr/local/work/k8s/k8sgatewaydemo/target/classes/META-INF/fabric8/kubernetes.yml [INFO] Using namespace: default [INFO] Updating a Service from kubernetes.yml [INFO] Updated Service: target/fabric8/applyJson/default/service-k8sgatewaydemo.json [INFO] Using namespace: default [INFO] Updating Deployment from kubernetes.yml [INFO] Updated Deployment: target/fabric8/applyJson/default/deployment-k8sgatewaydemo.json [INFO] F8: HINT: Use the command `kubectl get pods -w` to watch your pods start up [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 16.538 s [INFO] Finished at: 2019-07-07T22:04:48+08:00 [INFO] ------------------------------------------------------------------------
- 查看service和pod,確認一切正常:
[root@minikube k8sgatewaydemo]# clear [root@minikube k8sgatewaydemo]# kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE k8sgatewaydemo NodePort 10.97.94.238 <none> 8080:31352/TCP 129m kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 29d webdemo NodePort 10.106.98.137 <none> 8080:30160/TCP 145m [root@minikube k8sgatewaydemo]# kubectl get pod NAME READY STATUS RESTARTS AGE k8sgatewaydemo-6fbb79885c-r2jfn 1/1 Running 0 33s webdemo-c9f774b9-gsbgx 1/1 Running 0 32m
- 使用minikube命令取得webdemo服務對外暴露的地址:
[root@minikube k8sgatewaydemo]# minikube service k8sgatewaydemo --url http://192.168.121.133:31352
可見外部通過地址:http://192.168.121.133:31352 即可訪問到k8sgatewaydemo應用; 7. 在瀏覽器輸入地址:http://192.168.121.133:31352/customize/hello/time ,即可驗證k8sgatewaydemo作爲網關應用,能否將路徑中帶有customize的請求轉發到webdemo應用,並且在請求header中添加名爲entendtag的屬性,如下圖,瀏覽器展示的內容是webdemo的http接口返回的,並且extendtag的內容也不爲空了,而是k8sgatewaydemo在轉發前寫入的:
上述結果表明已可以證明我們之前的推測是正確的:SpringCloud Gateway應用在使用了spring-cloud-kubernetes提供的註冊發現能力後,可以將請求轉發到kubernetes環境中的服務上; 也就是說,藉助spring-cloud-kubernetes框架,你在SpringCloud環境開發的SpringCloud Gateway應用,可以以很小的代價遷移到kubernetes環境,與kubernetes環境中的service可以很好的交互,而原有的eureka註冊中心也可以不用了;
解決權限問題
如果您的spring-cloud-kubernetes在向webdemo轉發請求時拋出以下錯誤,那是因爲遇到了kubernetes的權限問題:
2019-07-06 04:46:40.042 WARN 1 --- [erListUpdater-1] c.n.l.PollingServerListUpdater : Failed one update cycle io.fabric8.kubernetes.client.KubernetesClientException: Failure executing: GET at: https://10.96.0.1/api/v1/namespaces/default/endpoints/account-service. Message: Forbidden!Configured service account doesn't have access. Service account may have been revoked. endpoints "account-service" is forbidden: User "system:serviceaccount:default:default" cannot get resource "endpoints" in API group "" in the namespace "default". at io.fabric8.kubernetes.client.dsl.base.OperationSupport.requestFailure(OperationSupport.java:476) ~[kubernetes-client-4.1.0.jar!/:na] at io.fabric8.kubernetes.client.dsl.base.OperationSupport.assertResponseCode(OperationSupport.java:413) ~[kubernetes-client-4.1.0.jar!/:na] at io.fabric8.kubernetes.client.dsl.base.OperationSupport.handleResponse(OperationSupport.java:381) ~[kubernetes-client-4.1.0.jar!/:na] at io.fabric8.kubernetes.client.dsl.base.OperationSupport.handleResponse(OperationSupport.java:344) ~[kubernetes-client-4.1.0.jar!/:na] at io.fabric8.kubernetes.client.dsl.base.OperationSupport.handleGet(OperationSupport.java:313) ~[kubernetes-client-4.1.0.jar!/:na] at io.fabric8.kubernetes.client.dsl.base.OperationSupport.handleGet(OperationSupport.java:296) ~[kubernetes-client-4.1.0.jar!/:na] at io.fabric8.kubernetes.client.dsl.base.BaseOperation.handleGet(BaseOperation.java:794) ~[kubernetes-client-4.1.0.jar!/:na] at io.fabric8.kubernetes.client.dsl.base.BaseOperation.getMandatory(BaseOperation.java:210) ~[kubernetes-client-4.1.0.jar!/:na] at io.fabric8.kubernetes.client.dsl.base.BaseOperation.get(BaseOperation.java:177) ~[kubernetes-client-4.1.0.jar!/:na] at org.springframework.cloud.kubernetes.ribbon.KubernetesServerList .getUpdatedListOfServers(KubernetesServerList.java:75) ~[spring-cloud-kubernetes-ribbon-1.0.1.RELEASE.jar!/:1.0.1.RELEASE] at com.netflix.loadbalancer.DynamicServerListLoadBalancer.updateListOfServers(DynamicServerListLoadBalancer.java:240) ~[ribbon-loadbalancer-2.3.0.jar!/:2.3.0] at com.netflix.loadbalancer.DynamicServerListLoadBalancer$1.doUpdate(DynamicServerListLoadBalancer.java:62) ~[ribbon-loadbalancer-2.3.0.jar!/:2.3.0] at com.netflix.loadbalancer.PollingServerListUpdater$1.run(PollingServerListUpdater.java:116) ~[ribbon-loadbalancer-2.3.0.jar!/:2.3.0] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_191] at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) [na:1.8.0_191] at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_191] at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) [na:1.8.0_191] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_191] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_191] at java.lang.Thread.run(Thread.java:748) [na:1.8.0_191]
處理方法是創建ServiceAccount對象,步驟如下:
- 創建名爲fabric8-rbac.yaml的文件,內容如下:
# NOTE: The service account `default:default` already exists in k8s cluster. # You can create a new account following like this: #--- #apiVersion: v1 #kind: ServiceAccount #metadata: # name: <new-account-name> # namespace: <namespace> --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: fabric8-rbac subjects: - kind: ServiceAccount # Reference to upper's `metadata.name` name: default # Reference to upper's `metadata.namespace` namespace: default roleRef: kind: ClusterRole name: cluster-admin apiGroup: rbac.authorization.k8s.io
- 執行以下命令即可創建ServiceAccount對象:
kubectl apply -f fabric8-rbac.yaml
- 再在瀏覽器上繼續剛纔的驗證,可以操作成功;
最後一個疑問
再回顧一下k8sgatewaydemo的開發過程,您會發現除了依賴spring-cloud-kubernetes對應的maven庫,我們並沒有顯式調用spring-cloud-kubernetes相關的API或者做相關配置,就獲取了所在kubernetes環境的原生服務,這是怎麼回事呢?爲何成本如此的低? 答案就在《spring-cloud-kubernetes背後的三個關鍵知識點》一文中,推薦您回顧一下此文。
至此,spring-cloud-kubernetes框架下的SpringCloud Gateway開發實戰就完成了,希望本文能幫助您更好的理解和使用spring-cloud-kubernetes,更加高效的將應用向容器化遷移。