spring-cloud-kubernetes 与 SpringCloud Gateway

本篇概览

  • 本文是《spring-cloud-kubernetes 实战系列》的第五篇,主要内容是在 kubernetes 上部署一个 SpringCloud Gateway 应用,该应用使用了 spring-cloud-kubernetes 框架,可以将请求转发到 kubernetes 环境中的其他服务上;

本文大纲

  • 接下来的内容由以下几部分组成:

  1. 什么是 SpringCloud Gateway

  2. SpringCloud Gateway 实战参考

  3. kubernetes 上的 SpringCloud Gateway

  4. 实战环境信息

  5. 实战源码下载

  6. 开发 webdemo

  7. 开发 k8sgatewaydemo

  8. 解决权限问题

  9. 最后一个疑问

什么是 SpringCloud Gateway

  • SpringCloud Gateway 是 SpringCloud 技术栈下的网关服务框架,在基于 SpringCloud 的微服务环境中,外部请求会到达 SpringCloud Gateway 应用,该应用对请求做转发、过滤、鉴权、熔断等前置操作,一个典型的请求响应流程如下所示:

SpringCloud Gateway 实战参考

  • 如果您之前没有使用过 SpringCloud Gateway,推荐您阅读《速体验 SpringCloud Gateway》,有时间的话动手实战效果更佳,只需编写少量代码就能快速熟悉这个 SpringCloud 技术栈中非常重要的功能;

kubernetes 上的 SpringCloud Gateway

  • 注意以下两个知识点:

  1. SpringCloud Gateway 之所以能将外部请求路由到正确的后台服务上,是因为注册中心的存在,SpringCloud Gateway 可以在注册中心取得所有服务的信息,因此它可以根据路径和服务的对应关系,将请求转发到对应的服务上;

  2. 如果您看过本系列的上一篇 《spring-cloud-kubernetes的服务发现和轮询实战(含熔断)》 ,您就知道 spring-cloud-kubernetes 框架可以获取 kubernetes 环境内的所有服务(这里说的服务就是 kubernetes 的 service);

  • 将以上两个知识点结合起来,于是可以推测: 运行在 kubernetes 环境的 SpringCloud Gateway 应用,如果使用了 spring-cloud-kubernetes 框架就能得到 kubernetes 的 service 列表,因此可以承担网关的角色,将外部请求转发至 kubernetes 内的 service 上,最终到达对应的 Pod;

  • 架构如下图所示,请注意黄色背景的对话框,里面标识了关键操作:

  • 至此,理论分析已经完成,我们来实战验证这个理论,接下来我们开发两个 java 应用:

  1. 先开发一个普通的 web 服务,名为 webdemo,提供一个 http 接口;

  2. 再开发一个 SpringCloud Gateway 应用,名为 k8sgatewaydemo;

环境信息

  • 本次实战的环境和版本信息如下:

  1. 操作系统:CentOS Linux release 7.6.1810

  2. minikube:1.1.1

  3. Java:1.8.0_191

  4. Maven:3.6.0

  5. fabric8-maven-plugin 插件:3.5.37

  6. spring-cloud-kubernetes:1.0.1.RELEASE

  7. spring cloud:Greenwich.SR2

  8. springboot:2.1.6.RELEASE

源码下载

  • 如果您不打算写代码,也可以从 GitHub 上下载本次实战的源码,地址和链接信息如下表所示:

  • 这个 git 项目中有多个文件夹,本章的两个应用分别在 webdemo 和 k8sgatewaydemo 文件夹下;

  • 下图红框中是 webdemo 应用的源码:

  • 下图红框中是 k8sgatewaydemo 应用的源码:

  • 下面是详细的编码过程;

开发 webdemo

  • webdemo 是个极其普通的 spring boot 应用, 和 SpringCloud 没有任何关系 ;

  1. 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")                + "]";    }}

复制代码

  1. 启动类 WebdemoApplication.java:

@SpringBootApplicationpublic class WebdemoApplication {    public static void main(String[] args) {        SpringApplication.run(WebdemoApplication.class, args);    }}

复制代码

  1. 要注意的是 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>

复制代码

  1. 以上就是 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] ------------------------------------------------------------------------

复制代码

  1. 查看 service 和 pod,确认一切正常:

[root@minikube webdemo]# kubectl get serviceNAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGEkubernetes       ClusterIP   10.96.0.1       <none>        443/TCP          29dwebdemo          NodePort    10.106.98.137   <none>        8080:30160/TCP   115m[root@minikube webdemo]# kubectl get podNAME                              READY   STATUS    RESTARTS   AGEwebdemo-c9f774b9-gsbgx            1/1     Running   0          3m13s

复制代码

  1. 使用 minikube 命令取得 webdemo 服务对外暴露的地址:

[root@minikube webdemo]# minikube service webdemo --urlhttp://192.168.121.133:30160

复制代码

  • 可见外部通过地址:http://192.168.121.133:30160 即可访问到 webdemo 应用;

  1. 在浏览器输入地址:http://192.168.121.133:30160/hello/time ,即可验证 webdemo 的 http 接口是否正常,如下图,由于 header 中没有 extendtag 属性,因此返回的 extendtag 为 null:

  • 至此,webdemo 在 minikue 上已经正常运行,该开发 gateway 应用了;

开发 k8sgatewaydemo

  1. 基于 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: {}

复制代码

  1. 开发 SpringCloud Gateway 的启动类 K8sgatewaydemoApplication.java,里面也包含了网关路由配置的实例化,除了配置路径和转发服务的关系,还在请求的 header 中添加了 extendtag 属性,请注意注释的内容:

@SpringBootApplication@EnableDiscoveryClientpublic 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 实现路由逻辑;

  1. 配置文件 application.yml 的内容:

spring:  application:    name: gateway  cloud:    gateway:      discovery:        locator:          enabled: true          lowerCaseServiceId: true

复制代码

  1. 以上就是 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] ------------------------------------------------------------------------

复制代码

  1. 查看 service 和 pod,确认一切正常:

[root@minikube k8sgatewaydemo]# clear[root@minikube k8sgatewaydemo]# kubectl get serviceNAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGEk8sgatewaydemo   NodePort    10.97.94.238    <none>        8080:31352/TCP   129mkubernetes       ClusterIP   10.96.0.1       <none>        443/TCP          29dwebdemo          NodePort    10.106.98.137   <none>        8080:30160/TCP   145m[root@minikube k8sgatewaydemo]# kubectl get podNAME                              READY   STATUS    RESTARTS   AGEk8sgatewaydemo-6fbb79885c-r2jfn   1/1     Running   0          33swebdemo-c9f774b9-gsbgx            1/1     Running   0          32m

复制代码

  1. 使用 minikube 命令取得 webdemo 服务对外暴露的地址:

[root@minikube k8sgatewaydemo]# minikube service k8sgatewaydemo --urlhttp://192.168.121.133:31352

复制代码

  • 可见外部通过地址:http://192.168.121.133:31352 即可访问到 k8sgatewaydemo 应用;

  1. 在浏览器输入地址: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 cycleio.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 对象,步骤如下:

  1. 创建名为 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/v1beta1kind: ClusterRoleBindingmetadata:  name: fabric8-rbacsubjects:  - kind: ServiceAccount    # Reference to upper's `metadata.name`    name: default    # Reference to upper's `metadata.namespace`    namespace: defaultroleRef:  kind: ClusterRole  name: cluster-admin  apiGroup: rbac.authorization.k8s.io

复制代码

  1. 执行以下命令即可创建 ServiceAccount 对象:

kubectl apply -f fabric8-rbac.yaml

复制代码

  1. 再在浏览器上继续刚才的验证,可以操作成功;

最后一个疑问

  • 再回顾一下 k8sgatewaydemo 的开发过程,您会发现除了依赖 spring-cloud-kubernetes 对应的 maven 库,我们并没有显式调用 spring-cloud-kubernetes 相关的 API 或者做相关配置,就获取了所在 kubernetes 环境的原生服务,这是怎么回事呢?为何成本如此的低?

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
微服务是什么?微服务是用于构建应用程序的架构风格,一个大的系统可由一个或者多个微服务组成,微服务架构可将应用拆分成多个核心功能,每个功能都被称为一项服务,可以单独构建和部署,这意味着各项服务在工作和出现故障的时候不会相互影响。为什么要用微服务?单体架构下的所有代码模块都耦合在一起,代码量大,维护困难,想要更新一个模块的代码,也可能会影响其他模块,不能很好的定制化代码。微服务中可以有java编写、有Python编写的,他们都是靠restful架构风格统一成一个系统的,所以微服务本身与具体技术无关、扩展性强。大型电商平台微服务功能图为什么要将SpringCloud项目部署到k8s平台?SpringCloud只能用在SpringBoot的java环境中,而kubernetes可以适用于任何开发语言,只要能被放进docker的应用,都可以在kubernetes上运行,而且更轻量,更简单。SpringCloud很多功能都跟kubernetes重合,比如服务发现,负载均衡,配置管理,所以如果把SpringCloud部署到k8s,那么很多功能可以直接使用k8s原生的,减少复杂度。Kubernetes作为成熟的容器编排工具,在国内外很多公司、世界500强等企业已经落地使用,很多中小型公司也开始把业务迁移到kubernetes中。kubernetes已经成为互联网行业急需的人才,很多企业都开始引进kubernetes技术人员,实现其内部的自动化容器云平台的建设。对于开发、测试、运维、架构师等技术人员来说k8s已经成为的一项重要的技能,下面列举了国内外在生产环境使用kubernetes的公司: 国内在用k8s的公司:阿里巴巴、百度、腾讯、京东、360、新浪、头条、知乎、华为、小米、富士康、移动、银行、电网、阿里云、青云、时速云、腾讯、优酷、抖音、快手、美团等国外在用k8s的公司:谷歌、IBM、丰田、iphone、微软、redhat等整个K8S体系涉及到的技术众多,包括存储、网络、安全、监控、日志、DevOps、微服务等,很多刚接触K8S的初学者,都会感到无从下手,为了能让大家系统地学习,克服这些技术难点,推出了这套K8S架构师课程。Kubernetes的发展前景 kubernetes作为炙手可热的技术,已经成为云计算领域获取高薪要掌握的重要技能,在招聘网站搜索k8s,薪资水平也非常可观,为了让大家能够了解k8s目前的薪资分布情况,下面列举一些K8S的招聘截图: 讲师介绍:  先超容器云架构师、IT技术架构师、DevOps工程师,曾就职于世界500强上市公司,拥有多年一线运维经验,主导过上亿流量的pv项目的架构设计和运维工作;具有丰富的在线教育经验,对课程一直在改进和提高、不断的更新和完善、开发更多的企业实战项目。所教学员遍布京东、阿里、百度、电网等大型企业和上市公司。课程学习计划 学习方式:视频录播+视频回放+全套源码笔记 教学服务:模拟面试、就业指导、岗位内推、一对一答疑、远程指导 VIP终身服务:一次购买,终身学习课程亮点:1. 学习方式灵活,不占用工作时间:可在电脑、手机观看,随时可以学习,不占用上班时间2.老师答疑及时:老师24小时在线答疑3. 知识点覆盖全、课程质量高4. 精益求精、不断改进根据学员要求、随时更新课程内容5. 适合范围广,不管你是0基础,还是拥有工作经验均可学习:0基础1-3年工作经验3-5年工作经验5年以上工作经验运维、开发、测试、产品、前端、架构师其他行业转行做技术人员均可学习课程部分项目截图   课程大纲 k8s+SpringCloud全栈技术:基于世界500强的企业实战课程-大纲第一章 开班仪式老师自我介绍、课程大纲介绍、行业背景、发展趋势、市场行情、课程优势、薪资水平、给大家的职业规划、课程学习计划、岗位内推第二章 kubernetes介绍Kubernetes简介kubernetes起源和发展kubernetes优点kubernetes功能kubernetes应用领域:在大数据、5G、区块链、DevOps、AI等领域的应用第三章  kubernetes中的资源对象最小调度单元Pod标签Label和标签选择器控制器Replicaset、Deployment、Statefulset、Daemonset等四层负载均衡器Service第四章 kubernetes架构和组件熟悉谷歌的Borg架构kubernetes单master节点架构kubernetes多master节点高可用架构kubernetes多层架构设计原理kubernetes API介绍master(控制)节点组件:apiserver、scheduler、controller-manager、etcdnode(工作)节点组件:kube-proxy、coredns、calico附加组件:prometheus、dashboard、metrics-server、efk、HPA、VPA、Descheduler、Flannel、cAdvisor、Ingress     Controller。第五章 部署多master节点的K8S高可用集群(kubeadm)第六章 带你体验kubernetes可视化界面dashboard在kubernetes中部署dashboard通过token令牌登陆dashboard通过kubeconfig登陆dashboard限制dashboard的用户权限在dashboard界面部署Web服务在dashboard界面部署redis服务第七章 资源清单YAML文件编写技巧编写YAML文件常用字段,YAML文件编写技巧,kubectl explain查看帮助命令,手把手教你创建一个Pod的YAML文件第八章 通过资源清单YAML文件部署tomcat站点编写tomcat的资源清单YAML文件、创建service发布应用、通过HTTP、HTTPS访问tomcat第九章  kubernetes Ingress发布服务Ingress和Ingress Controller概述Ingress和Servcie关系安装Nginx Ingress Controller安装Traefik Ingress Controller使用Ingress发布k8s服务Ingress代理HTTP/HTTPS服务Ingress实现应用的灰度发布-可按百分比、按流量分发第十章 私有镜像仓库Harbor安装和配置Harbor简介安装HarborHarbor UI界面使用上传镜像到Harbor仓库从Harbor仓库下载镜像第十一章 微服务概述什么是微服务?为什么要用微服务?微服务的特性什么样的项目适合微服务?使用微服务需要考虑的问题常见的微服务框架常见的微服务框架对比分析第十二章 SpringCloud概述SpringCloud是什么?SpringCloud和SpringBoot什么关系?SpringCloud微服务框架的优缺点SpringCloud项目部署到k8s的流程第十三章 SpringCloud组件介绍服务注册与发现组件Eureka客户端负载均衡组件Ribbon服务网关Zuul熔断器HystrixAPI网关SpringCloud Gateway配置中心SpringCloud Config第十四章 将SpringCloud项目部署到k8s平台的注意事项如何进行服务发现?如何进行配置管理?如何进行负载均衡?如何对外发布服务?k8s部署SpringCloud项目的整体流程第十五章 部署MySQL数据库MySQL简介MySQL特点安装部署MySQL在MySQL数据库导入数据对MySQL数据库授权第十六章 将SpringCLoud项目部署到k8s平台SpringCloud的微服务电商框架安装openjdk和maven修改源代码、更改数据库连接地址通过Maven编译、构建、打包源代码在k8s中部署Eureka组件在k8s中部署Gateway组件在k8s中部署前端服务在k8s中部署订单服务在k8s中部署产品服务在k8s中部署库存服务第十七章 微服务的扩容和缩容第十八章 微服务的全链路监控什么是全链路监控?为什么要进行全链路监控?全链路监控能解决哪些问题?常见的全链路监控工具:zipkin、skywalking、pinpoint全链路监控工具对比分析第十九章 部署pinpoint服务部署pinpoint部署pinpoint agent在k8s中重新部署带pinpoint agent的产品服务在k8s中重新部署带pinpoint agent的订单服务在k8s中重新部署带pinpoint agent的库存服务在k8s中重新部署带pinpoint agent的前端服务在k8s中重新部署带pinpoint agent的网关和eureka服务Pinpoint UI界面使用第二十章 基于Jenkins+k8s+harbor等构建企业级DevOps平台第二十一章 基于Promethues+Alert+Grafana搭建企业级监控系统第二十二章 部署智能化日志收集系统EFK 

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值