SpringBoot集成kubernetes-client升级k8s后初始化失败问题

文章讲述了在SpringBoot应用中,将kubernetes-client从1.16升级到1.26时遇到初始化失败的问题,主要原因是证书算法不一致。通过debug和调整配置,作者发现读取不同来源的配置导致了客户端密钥算法的不同,最终给出了在配置文件和Nacos中处理该问题的两种解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SpringBoot集成kubernetes-client升级k8s后初始化失败问题

1.问题描述

程序以前使用的k8s版本是1.16,fabric8.kubernetes-client的版本是4.10.2,springboot版本是2.3.5。由于环境切换,这次需要升级k8s的版本,现在将k8s版本升级到了1.26,程序中使用了新配置的certificate-authority-data,client-certificate-data等。程序中原本初始化写法如下:

config = new ConfigBuilder().withMasterUrl(server)
        .withCaCertData(certificateAuthorityData)
        .withClientCertData(clientCertificateData)
        .withClientKeyData(clientKeyData)
        .build();
LogUtil.info(LogEnum.BIZ_K8S, "config信息为{}", JSON.toJSONString(config));
client = new DefaultKubernetesClient(config);

但是程序启动缺出现了问题,问题如下:

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.dubhe.k8s.utils.K8sUtils]: Factory method 'k8sUtils' threw exception; nested exception is io.fabric8.kubernetes.client.KubernetesClientException: An error has occurred.
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.2.10.RELEASE.jar:5.2.10.RELEASE]
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:650) ~[spring-beans-5.2.10.RELEASE.jar:5.2.10.RELEASE]
	... 61 common frames omitted
Caused by: io.fabric8.kubernetes.client.KubernetesClientException: An error has occurred.
	at io.fabric8.kubernetes.client.KubernetesClientException.launderThrowable(KubernetesClientException.java:64) ~[kubernetes-client-4.10.2.jar:na]
	at io.fabric8.kubernetes.client.KubernetesClientException.launderThrowable(KubernetesClientException.java:53) ~[kubernetes-client-4.10.2.jar:na]
	at io.fabric8.kubernetes.client.utils.HttpClientUtils.createHttpClient(HttpClientUtils.java:234) ~[kubernetes-client-4.10.2.jar:na]
	at io.fabric8.kubernetes.client.utils.HttpClientUtils.createHttpClient(HttpClientUtils.java:63) ~[kubernetes-client-4.10.2.jar:na]
	at io.fabric8.kubernetes.client.BaseClient.<init>(BaseClient.java:51) ~[kubernetes-client-4.10.2.jar:na]
	at io.fabric8.kubernetes.client.DefaultKubernetesClient.<init>(DefaultKubernetesClient.java:133) ~[kubernetes-client-4.10.2.jar:na]
	at org.dubhe.k8s.utils.K8sUtils.<init>(K8sUtils.java:93) ~[classes/:na]
	at org.dubhe.k8s.config.K8sConfig.k8sUtils(K8sConfig.java:91) ~[classes/:na]
	at org.dubhe.k8s.config.K8sConfig$$EnhancerBySpringCGLIB$$77270501.CGLIB$k8sUtils$10(<generated>) ~[classes/:na]
	at org.dubhe.k8s.config.K8sConfig$$EnhancerBySpringCGLIB$$77270501$$FastClassBySpringCGLIB$$1f42aed6.invoke(<generated>) ~[classes/:na]
	at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) ~[spring-core-5.2.10.RELEASE.jar:5.2.10.RELEASE]
	at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) ~[spring-context-5.2.10.RELEASE.jar:5.2.10.RELEASE]
	at org.dubhe.k8s.config.K8sConfig$$EnhancerBySpringCGLIB$$77270501.k8sUtils(<generated>) ~[classes/:na]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_321]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_321]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_321]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_321]
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.2.10.RELEASE.jar:5.2.10.RELEASE]
	... 62 common frames omitted
Caused by: java.io.IOException: Invalid DER: object is not integer
	at io.fabric8.kubernetes.client.internal.PKCS1Util$Asn1Object.getInteger(PKCS1Util.java:125) ~[kubernetes-client-4.10.2.jar:na]
	at io.fabric8.kubernetes.client.internal.PKCS1Util.next(PKCS1Util.java:55) ~[kubernetes-client-4.10.2.jar:na]
	at io.fabric8.kubernetes.client.internal.PKCS1Util.decodePKCS1(PKCS1Util.java:46) ~[kubernetes-client-4.10.2.jar:na]
	at io.fabric8.kubernetes.client.internal.CertUtils.handleOtherKeys(CertUtils.java:175) ~[kubernetes-client-4.10.2.jar:na]
	at io.fabric8.kubernetes.client.internal.CertUtils.loadKey(CertUtils.java:135) ~[kubernetes-client-4.10.2.jar:na]
	at io.fabric8.kubernetes.client.internal.CertUtils.createKeyStore(CertUtils.java:113) ~[kubernetes-client-4.10.2.jar:na]
	at io.fabric8.kubernetes.client.internal.CertUtils.createKeyStore(CertUtils.java:245) ~[kubernetes-client-4.10.2.jar:na]
	at io.fabric8.kubernetes.client.internal.SSLUtils.keyManagers(SSLUtils.java:128) ~[kubernetes-client-4.10.2.jar:na]
	at io.fabric8.kubernetes.client.internal.SSLUtils.keyManagers(SSLUtils.java:122) ~[kubernetes-client-4.10.2.jar:na]
	at io.fabric8.kubernetes.client.utils.HttpClientUtils.createHttpClient(HttpClientUtils.java:120) ~[kubernetes-client-4.10.2.jar:na]
	... 77 common frames omitted
2.问题分析

然后就上网去查找资料,但是搜索了很多,都没有找到有用的信息。只好自己一点点debug去查看源代码。debug的时候看到build的时候会先去读配置文件,这让我想到了之前做的一个项目,那个项目使用的是io.kubernetes client-java这个依赖包。我再开发的时候会将config文件放在系统路径下。又换了一种创建方式:

Config config = new ConfigBuilder().build();

于是按照这种方式也将config放在相应的路径下,程序果然可以去建立连接,自测创建pod也是成功的。

由于一个读取的是配置文件,一个读取的是配置在nacos配置中心的配置,两个的配置信息毫无差别,但是执行结果就是不一样。然后再去debug去看两中配置问题到底有何不一样。最后发现Config中的clientKeyAlgo中赋值不同,读取nacos中的配置产生的算法是RSA,读取config配置文件产生的是EC。

然后我将系统路径下的config文件移除,将原本程序改为:

Config config = new ConfigBuilder().withMasterUrl(server)         .withCaCertData(certificateAuthorityData)         .withClientCertData(clientCertificateData)         .withClientKeyData(clientKeyData)         .withClientKeyAlgo("EC")         .build();

发现也成功了。由于时间关系,就没有仔细去看为什么读取nacos中的配置产生的是RSA,读取config配置文件产生的是EC。

3.解决办法

最终解决方案是:

1.在程序启动的包设置config环境变量,让程序读取config文件;设置了config文件后,就可以用Config config = new ConfigBuilder().build();这种方式创建。

2.依然去读取nacos中的配置(certificate-authority-data,client-certificate-data),在程序Builder时手动设置ClientKeyAlgo。

<think>好的,我现在需要解决用户的问题:寻找在Java中使用Nacos监听Kubernetes服务(特别是名为w-task-agent的服务)启动事件的示例代码。首先,我需要明确用户的具体需求。用户可能希望在Kubernetes环境中,当某个服务(如w-task-agent)启动时,通过Nacos进行服务发现,并触发相应的Java代码执行。这可能涉及到Nacos的事件监听机制,以及如何在Kubernetes集成Nacos。 接下来,我需要回忆Nacos的相关功能。Nacos作为服务发现和配置管理平台,支持服务注册与发现。在Java应用中,通常使用Nacos的客户端SDK来订阅服务变化事件。当服务实例上线、下线或元数据变更时,Nacos客户端可以接收到通知。 然后,考虑Kubernetes环境的特殊性。在K8s中,服务的生命周期可能由Pod的启动和终止来控制。因此,需要确保Nacos客户端能够正确注册服务,并监听服务实例的变化。可能需要结合Kubernetes的探针机制,确保服务在完全启动后再注册到Nacos,避免出现未就绪的服务被访问的情况。 用户提到的示例代码,可能需要包括以下几个部分: 1. 引入Nacos客户端依赖,比如使用Spring Cloud Alibaba。 2. 配置Nacos服务器地址和应用信息。 3. 编写服务注册逻辑,确保服务启动时自动注册到Nacos。 4. 实现事件监听器,监听特定服务(w-task-agent)的实例变化。 5. 处理服务上线事件,执行自定义逻辑。 此外,用户提供的引用中提到Nacos集群启动时的错误(CODE:503),这可能与集群初始化未完成有关,所以在代码中需要考虑重试机制或等待Nacos就绪后再进行注册和监听。引用中的Docker相关配置可能提示用户在使用容器化部署,需要确保Nacos客户端配置正确,能够连接到Nacos服务器。 可能的代码结构: - 使用@EnableDiscoveryClient启用服务发现。 - 使用NamingService来订阅服务变化。 - 在事件回调中过滤出w-task-agent服务的事件,并处理实例启动的情况。 还需要注意,Kubernetes中的服务发现可能与Nacos的服务发现机制有所不同,需要确认服务如何注册到Nacos。例如,可能需要通过sidecar模式或者服务网格来同步Kubernetes服务到Nacos,或者直接在应用启动时通过Nacos客户端注册。 最后,需要验证示例代码的正确性,确保事件监听能够被正确触发,并处理可能的异常情况,如网络问题或Nacos服务不可用。</think>以下是一个基于Java的示例代码,演示如何在Spring Cloud Alibaba框架中使用Nacos监听Kubernetes服务(w-task-agent)的启动事件: ```java import com.alibaba.nacos.api.naming.NamingService; import com.alibaba.nacos.api.naming.listener.Event; import com.alibaba.nacos.api.naming.listener.EventListener; import com.alibaba.nacos.api.naming.listener.NamingEvent; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import javax.annotation.PostConstruct; @SpringBootApplication @EnableDiscoveryClient public class NacosListenerApplication { @Autowired private NamingService namingService; public static void main(String[] args) { SpringApplication.run(NacosListenerApplication.class, args); } @PostConstruct public void init() throws Exception { // 监听指定服务名的实例变化 String serviceName = "w-task-agent"; namingService.subscribe(serviceName, new EventListener() { @Override public void onEvent(Event event) { if (event instanceof NamingEvent) { NamingEvent namingEvent = (NamingEvent) event; // 获取当前可用实例列表 List<Instance> instances = namingEvent.getInstances(); // 判断服务是否启动 if (!instances.isEmpty()) { System.out.println("服务已启动,当前实例数量: " + instances.size()); // TODO: 执行自定义业务逻辑 } } } }); } } ``` ### 关键配置项(application.yml) ```yaml spring: cloud: nacos: discovery: server-addr: ${NACOS_HOST:localhost}:8848 namespace: public service: your-service-name ``` ### 实现要点说明 1. **依赖引入**:需在pom.xml中添加Spring Cloud Alibaba依赖 ```xml <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>2021.0.5.0</version> </dependency> ``` 2. **事件触发条件**:当w-task-agent服务有新的实例注册到Nacos时触发事件[^1] 3. **Kubernetes集成**: - 需要确保Pod配置了正确的Nacos服务地址 - 建议添加就绪探针,确保服务完全启动后再注册到Nacos ```yaml readinessProbe: httpGet: path: /actuator/health port: 8080 initialDelaySeconds: 30 periodSeconds: 10 ``` 4. **注意事项**: - 需要处理Nacos集群启动时的503错误(参考引用[^3]) - 建议添加重试机制和超时处理 - 需要确保网络策略允许Pod访问Nacos服务器 ### 部署建议 1. 使用Docker部署时参考引用[^2]的配置模板 2. 集群环境下需要配置多个Nacos节点地址 3. 建议配合Sentinel实现熔断保护[^1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值