我正试图在基于Spring Boot的微服务中利用Spring Cloud Kubernetes,即自动配置和服务发现。
然而,在初始化过程中,我收到了一条错误消息(等待informers缓存准备就绪超时,kubernetes服务是否启动?(,以及高度的冗长性,这两种情况我都无法在线找到信息来帮助我查明原因。下面详细介绍了错误消息和过多的日志消息。很抱歉没有上下文,但我也很困惑!
应用程序在default
服务帐户中运行,该帐户具有文档中指定的所有权限:
$ kubectl describe serviceaccount default
Name: default
Namespace: joaomlneto
Labels: <none>
Annotations: <none>
Image pull secrets: devspace-auth-rg-nl-ams-scw-cloud
Mountable secrets: default-token-2sxvc
Tokens: default-token-2sxvc
Events: <none>
$ kubectl describe rolebinding namespace-reader-binding
Name: namespace-reader-binding
Labels: <none>
Annotations: <none>
Role:
Kind: Role
Name: namespace-reader
Subjects:
Kind Name Namespace
---- ---- ---------
ServiceAccount default joaomlneto
$ kubectl describe role namespace-reader
Name: namespace-reader
Labels: <none>
Annotations: <none>
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
configmaps [] [] [list watch get]
endpoints [] [] [list watch get]
pods [] [] [list watch get]
secrets [] [] [list watch get]
services [] [] [list watch get]
configmaps.apps [] [] [list watch get]
endpoints.apps [] [] [list watch get]
pods.apps [] [] [list watch get]
secrets.apps [] [] [list watch get]
services.apps [] [] [list watch get]
configmaps.extensions [] [] [list watch get]
endpoints.extensions [] [] [list watch get]
pods.extensions [] [] [list watch get]
secrets.extensions [] [] [list watch get]
services.extensions [] [] [list watch get]
我使用的是Spring Boot 2.4;Spring Cloud Kubernetes 2.0.2。我的pom.xml
:
<properties>
<java.version>11</java.version>
<spring-cloud.version>2020.0.2</spring-cloud.version>
<spring-cloud-kubernetes.version>2.0.2</spring-cloud-kubernetes.version>
<graphql-java-kickstart.version>11.0.0</graphql-java-kickstart.version>
<lombok.version>1.18.20</lombok.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-client-all</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>${graphql-java-kickstart.version}</version>
</dependency>
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-spring-boot-starter-test</artifactId>
<version>${graphql-java-kickstart.version}</version>
<scope>test</scope>
</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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-kubernetes-dependencies</artifactId>
<version>${spring-cloud-kubernetes.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>
<configuration>
<excludeDevtools>false</excludeDevtools>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>central</id>
<name>Maven Central</name>
<url>https://repo1.maven.org/maven2</url>
</repository>
<repository>
<id>supersecret</id>
<name>A Super Secret Repo</name>
<url>https://example.com/1</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<distributionManagement>
<repository>
<id>supersecret2</id>
<name>Another Super Secret Repo</name>
<url>https://example.com/2</url>
</repository>
</distributionManagement>
然而,在应用程序成功启动一分钟后,我收到以下错误:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'kubernetesInformerDiscoveryClient' defined in class path resource [org/springframework/cloud/kubernetes/client/discovery/KubernetesDiscoveryClientAutoConfiguration$KubernetesInformerDiscoveryConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Timeout waiting for informers cache to be ready, is the kubernetes service up?
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1786) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:602) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.5.jar:5.3.5]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.5.jar:5.3.5]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144) ~[spring-boot-2.4.4.jar:2.4.4]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:769) ~[spring-boot-2.4.4.jar:2.4.4]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:761) ~[spring-boot-2.4.4.jar:2.4.4]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426) ~[spring-boot-2.4.4.jar:2.4.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:326) ~[spring-boot-2.4.4.jar:2.4.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1313) ~[spring-boot-2.4.4.jar:2.4.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302) ~[spring-boot-2.4.4.jar:2.4.4]
at myorg.myapp.Application.main(Application.java:9) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.4.4.jar:2.4.4]
Caused by: java.lang.IllegalStateException: Timeout waiting for informers cache to be ready, is the kubernetes service up?
at org.springframework.cloud.kubernetes.client.discovery.KubernetesInformerDiscoveryClient.afterPropertiesSet(KubernetesInformerDiscoveryClient.java:221) ~[spring-cloud-kubernetes-client-discovery-2.0.2.jar:2.0.2]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1845) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1782) ~[spring-beans-5.3.5.jar:5.3.5]
... 22 common frames omitted
我还每秒记录以下消息(无论是在错误发生之前还是之后,都是无限的(:
2021-04-18 16:19:12.585 INFO 224 --- [pool-9-thread-1] .k.c.d.KubernetesInformerDiscoveryClient : Waiting for the cache of informers to be fully loaded..
2021-04-18 16:19:12.935 INFO 224 --- [s.V1Endpoints-1] i.k.c.informer.cache.ReflectorRunnable : class io.kubernetes.client.openapi.models.V1Endpoints#Start listing and watching...
2021-04-18 16:19:12.950 INFO 224 --- [els.V1Service-1] i.k.c.informer.cache.ReflectorRunnable : class io.kubernetes.client.openapi.models.V1Service#Start listing and watching...
我使用Fabric8客户端而不是官方客户端,成功地消除了错误消息。这个简单的改变就足以解决我的问题。
这是通过将pom.xml
中的依赖关系从spring-cloud-starter-kubernetes-client-all
更改为spring-cloud-starter-kubernetes-fabric8-all
来实现的。
由于这似乎不是预期的行为,我在GitHub上打开了一个关于Spring Cloud Kubernetes项目的错误报告。
2022年1月编辑:错误报告已标记为已解决,尽管有些人仍会遇到此问题。我仍然在使用Fabric8,没有遇到任何问题。没有回头
您还没有发布yaml
配置以及如何应用它,所以我无法指导您的情况到底出了什么问题。但是,问题的一个可能原因可能是服务帐户的令牌错误。
阅读文档的"Kubernetes内部的安全配置"部分,我们看到以下引文:
对于Kubernetes(1.3+(,pod可以使用名称空间服务帐户机密的一部分,并由自动检测客户端
这意味着,如果pod使用的服务帐户的秘密由于任何原因导致命名空间配置错误,kubernetes客户端将默默忽略该错误,并继续尝试在错误的命名空间中列出服务/端点,而实际上并没有授予访问权限。
您可以使用在名称空间joaomlneto
中列出机密
kubectl get secrets --namespace joaomlneto
然后,您可以使用检查相同命名空间的default
服务帐户令牌的命名空间
kubectl get secret/default-token-..... --template='{{.data.namespace}}' --namespace joaomlneto
base64编码的输出应该解码为joaomlneto
。否则,您将遇到权限问题。若要修复此问题,您可以删除服务帐户,然后重新创建,并在这次对其进行正确配置。
您需要向您的spring应用程序授予必要的权限,并且您正在使用依赖项spring-cloud-starter-kubernetes-fabric8-all
,您需要授予这些权限:"configmaps"吊舱"服务"端点"秘密";。
以下是Spring Cloud文档中的一个示例:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: YOUR-NAME-SPACE
name: namespace-reader
rules:
- apiGroups: ["", "extensions", "apps"]
resources: ["configmaps", "pods", "services", "endpoints", "secrets"]
verbs: ["get", "list", "watch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: namespace-reader-binding
namespace: YOUR-NAME-SPACE
subjects:
- kind: ServiceAccount
name: default
apiGroup: ""
roleRef:
kind: Role
name: namespace-reader
apiGroup: ""
链接:https://docs.spring.io/spring-cloud-kubernetes/docs/current/reference/html/index.html