微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Spring Cloud Kubernetes:等待通知缓存准备好超时

如何解决Spring Cloud Kubernetes:等待通知缓存准备好超时

我正在尝试在基于 Spring Boot 的微服务(即自动配置和服务发现)中利用 Spring Cloud Kubernetes。

但是,我在初始化过程中收到一条错误消息(超时等待 Informers 缓存准备好,kubernetes 服务是否已启动?),以及高冗长,我无法在线查找信息以帮助我查明原因。错误消息和过多的日志消息详述如下。为缺乏上下文道歉,但我也很困惑!

应用程序在 default 服务帐户中运行,该帐户具有 documentation 中指定的所有权限:

$ 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;春云 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 来实现的。

由于这似乎不是预期的行为,我打开了一个 bug report on the Spring Cloud Kubernetes project on GitHub

,

您尚未发布您的 yaml 配置以及您如何应用它,因此我无法提供指导,您的情况究竟有什么问题。但是,您的问题的一个可能原因可能是服务帐户的令牌错误。

阅读文档的 Security Configurations Inside 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”、“pods”、“services”、“endpoints”,“秘密”。

以下是 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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。