英文:
How can I connect my springboot application to my redis server within the same kubernetes namespace?
问题
我的Kubernetes命名空间同时托管了我的Spring Boot应用程序和Redis服务。然而,当我运行Spring Boot应用程序时,我收到了以下错误:
org.springframework.data.redis.RedisConnectionFailureException: Cannot get Jedis connection; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
...
Caused by: redis.clients.jedis.exceptions.JedisConnectionException: Failed connecting to localhost:6379
我将发布应用程序和Redis服务器的清单YAML如下:
以下是成功部署我的应用程序到命名空间并可以从URL访问的清单:
这个清单成功地将我的应用程序部署到了命名空间,并且我可以从URL访问它。
以下是我的Spring Boot应用程序的配置文件:
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public JedisConnectionFactory redisConnectionFactory() {
return new JedisConnectionFactory(new RedisStandaloneConfiguration("127.0.0.1", 6379));
}
@Bean
public RedisTemplate<String, Object> redisTemplate(JedisConnectionFactory jedisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setDefaultSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setConnectionFactory(jedisConnectionFactory);
return redisTemplate;
}
}
我的Redis服务器是否正确部署?我是否需要以某种方式将Spring Boot应用程序绑定到我的Redis服务器?
您的Redis服务器似乎已正确部署到命名空间中。但是,根据错误消息和您的Spring Boot应用程序配置来看,应用程序正在尝试连接到本地主机(localhost)的6379端口,而这似乎不适用于Kubernetes环境。
在Kubernetes中,容器之间通常无法直接访问本地主机。您应该使用服务名称来引用Redis服务,而不是直接使用本地主机。
在您的Spring Boot应用程序的配置文件中,将以下行:
return new JedisConnectionFactory(new RedisStandaloneConfiguration("127.0.0.1", 6379));
更改为引用Redis服务的名称,如下所示:
return new JedisConnectionFactory(new RedisStandaloneConfiguration("redis-service", 6379));
这将允许您的Spring Boot应用程序在Kubernetes中正确连接到Redis服务。确保在应用程序部署清单中也正确设置了环境变量或配置,以指向Redis服务的名称。
英文:
I have a kubernetes namespace that hosts both my springboot application and the redis service. However when I run the springboot app I get error
org.springframework.data.redis.RedisConnectionFailureException: Cannot get Jedis connection; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
...
Caused by: redis.clients.jedis.exceptions.JedisConnectionException: Failed connecting to localhost:6379
Ill post both the manifest yaml for the application and redis server below.
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-deployment
namespace: spring-poc
labels:
app: spring
spec:
replicas: 1
selector:
matchLabels:
app: spring
template:
metadata:
labels:
app: spring
spec:
containers:
- name: spring
image: spring-application
resources:
requests:
memory: 1G
cpu: "500m"
limits:
memory: 1G
cpu: 1
ports:
- name: http
containerPort: 8080
securityContext:
runAsUser: 1000
imagePullSecrets:
- name: prod.secret
---
apiVersion: v1
kind: Service
metadata:
name: spring-service
namespace: spring-poc
labels:
app: spring-service
spec:
selector:
app: spring
type: ClusterIP
ports:
- name: http
port: 8080
targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: spring-ingress
namespace: spring-poc
spec:
rules:
- host: spring.url.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: spring-service
port:
number: 8080
tls:
- hosts:
- spring.url.com
This manifest successfully deploys my app to the namespace and I can access it from the url.
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-deployment
namespace: spring-poc
labels:
app: redis
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis
resources:
requests:
memory: 1G
cpu: "500m"
limits:
memory: 1G
cpu: 1
ports:
- name: redis
containerPort: 6379
securityContext:
runAsUser: 1000
imagePullSecrets:
- name: prod.secret
---
apiVersion: v1
kind: Service
metadata:
name: redis-service
namespace: spring-poc
labels:
app: redis
spec:
selector:
app: redis
type: ClusterIP
ports:
- name: redis
port: 6379
targetPort: 6379
This manifest successfully deploys a redis server to my namespace. If I kubectl exec -it redis-deployment -- redis-cli
and run ping
it returns pong
.
Below is my configuration file for the springboot application
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* The type Cache config.
*/
@Configuration
@EnableCaching
public class CacheConfig {
/**
* Redis connection factory jedis connection factory.
*
* @return the jedis connection factory
*/
@Bean
public JedisConnectionFactory redisConnectionFactory() {
return new JedisConnectionFactory(new RedisStandaloneConfiguration("127.0.0.1", 6379));
}
/**
* Redis template.
*
* @param jedisConnectionFactory the jedis connection factory
* @return the redis template
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(JedisConnectionFactory jedisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setDefaultSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setConnectionFactory(jedisConnectionFactory);
return redisTemplate;
}
}
Is my redis server deployed correctly? Do I need to bind the springboot application to my redis server somehow?
答案1
得分: 1
你正在创建一个使用本地主机(127.0.0.1
)的 RedisStandaloneConfiguration
。Pods(Redis 和你的 Spring 应用程序)是分开的,无法以这种方式通信。
因此,你需要将 127.0.0.1
替换为 redis-service.spring-poc
,如下所示:
[...]
@Bean
public JedisConnectionFactory redisConnectionFactory() {
return new JedisConnectionFactory(new RedisStandaloneConfiguration("redis-service.spring-poc", 6379));
}
[...]
最佳实践是从环境变量或应用程序配置中获取这些信息,这样你仍然可以在工作站上使用 localhost
进行测试。
解释:
Kubernetes 提供了开箱即用的 DNS。你可以使用 <service-name>.<namespace-name>
查询每个 Pod。你可以将其类比为类似于 google.de
的域名。因此,你可以通过这种方式连接到每个 Pod。在你的示例中,Redis 服务被称为 redis-service
,它需要与部署在同一命名空间中,即 spring-poc
(尽管你的清单中写着 namespace: 48713-poc
,但这不会起作用)。因此,要从 Spring 连接到 Redis,你需要连接到 redis-service.spring-poc:6379
。
从技术上讲,redis-service:6379
也可以工作,但我建议更加详细。还可以查看有关 Pod 之间通信的 DNS 文档。
英文:
You're creating a RedisStandaloneConfiguration
with localhost (127.0.0.1
). The pods (redis and your spring app) are separated and can't communicate like that.
So you need to replace 127.0.0.1
with redis-service.spring-poc
, like this:
[...]
@Bean
public JedisConnectionFactory redisConnectionFactory() {
return new JedisConnectionFactory(new RedisStandaloneConfiguration("redis-service.spring-poc", 6379));
}
[...]
Best practice would be to get that from environment variables or application config, so you can still use localhost
for testing on your workstation.
Explanation:
Kubernetes provides out-of-the-box dns. You can query every pod with <service-name>.<namespace-name>
. You can think of it similar to a domain like google.de
. So you can connect to every pod via it's service by that. In your example the redis service is called redis-service
and it needs to be in the same namespace as the deployment, which is spring-poc
(though your manifest says namespace: 48713-poc
which wouldn't work). So to connect from spring to redis you need to connect to redis-service.spring-poc:6379
.
Technically redis-service:6379
would also work, but I'd recommend to be verbose. Also check out the docs about dns for pod to pod communication.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论