Spring Cloud kubernetes not loading config map - spring

I have created the 2 config map named personservice and personservice-dev.
I am running spring boot application with profile dev but it is not loading the right config map. This is what I see in logs of the pod which gets crashed.
2019-11-05 16:29:37.336 INFO [personservice,,,] 7 --- [ main] b.c.PropertySourceBootstrapConfiguration : Located property source: CompositePropertySource {name='composite-configmap', propertySources=[ConfigMapPropertySource {name='configmap.personservice.default'}]}
2019-11-05 16:29:37.341 INFO [personservice,,,] 7 --- [ main] b.c.PropertySourceBootstrapConfiguration : Located property source: SecretsPropertySource {name='secrets.personservice.default'}
2019-11-05 16:29:37.445 INFO [personservice,,,] 7 --- [ main] c.person.PersonMicroServiceApplication : The following profiles are active: kubernetes,dev
Kubectl get configmaps
Deployment file:
apiVersion: apps/v1
kind: Deployment
metadata:
name: personservice
labels:
app: personservice
spec:
replicas: 1
selector:
matchLabels:
app: personservice
template:
metadata:
labels:
app: personservice
spec:
containers:
- name: personservice
image: microservice-k8s/personmicroservice-k8s:1.0
ports:
- containerPort: 8080
env:
- name: PROFILE
value: "dev"
- name: SERVER_PORT
value: "8080"
- name: ZIPKIN_URI
value: "http://172.19.27.145:9411"
Bootstrap:
spring:
application:
name: personservice

You confused things. Your configmap is named personservice-dev and your application's name is personservice not personservice-dev, by default Spring Cloud K8S looks for configmap with name equals to spring.application.name and not spring.application.name-{profile}.
You have 2 ways to solve your problem:
1-Remove personservice-dev and in your personservice configmap:
kind: ConfigMap
apiVersion: v1
metadata:
name: personservice
data:
application.yml: |-
p1:
pa: blabla
---
spring:
profiles: dev
p1:
pa: blibli
---
spring:
profiles: prod
p1:
pa: blublu
2-Keep personservice-dev and personservice and define this in bootstrap.yml:
spring:
cloud:
kubernetes:
config:
name: ${spring.application.name} #This is optional
sources:
- name: ${spring.application.name}-${PROFILE} # Here you get your `personservice-dev` configmap

Related

Spring Profiles Deprecated

How to use inheritance in application.yml settings now?
I have updated to Spring Boot 2.6.7 and notice
spring.profiles is Deprecated
What changes should I make?
...
---
spring:
profiles: <--- Deprecated
default:
- "actuator"
- "swagger"
group:
default:
- "actuator"
- "swagger"
local:
- "local"
- "actuator"
- "logger"
- "swagger"
staging:
- "staging"
- "actuator"
- "logger"
- "swagger"
integration:
- "integration"

Spring Config Server : get secrets from vault with specific path

I am trying to get my microservices configuration from a config server connected to 2 sources : git and vault (for secrets). I have the config bellow:
in the config-server:
server:
port: 8888
spring:
profiles:
active: git, vault
cloud:
config:
server:
vault:
port: 8200
host: 127.0.0.1
kvVersion: 2
git:
order: 2
uri: git#gitlab.git
and in the client side in the bootstrap.yml:
spring:
application:
name: my-service-name
cloud:
config:
uri: http://localhost:8888
token: //token
label: dev
But in my vault i have the path like this :
secret/cad
|--my-service-name
When i make my secret directly in /secret/my-service-name i can access my secrets, but how can i configure acces to secrets in : /secret/cad/my-service-name
Thank you.
You can create your Custom configuration Class that implements VaultConfigurer where you can override to your custom path
#Configuration
Public class CustomVaultConfiguraton implements VaultConfigurer {
#override
public void addSecretsBackends(SecretBackendConfigurer configures){
configures.add("customPath");
}
}
add above configuration class in spring.factories
org.springframework.cloud.bootstrap.BootstrapConfiguration=\packagename.CustomVaultConfiguration

Pass URL from K8s-ConfigMap to SpringBoot Application

I'm quite new to Kubernetes and started using MiniKube to experiment with K8s.
Explanation
This is the (very simple) scenario I want to realize:
PrintClient provides a http-endpoint: <url>/<stringToPrint>
PrintClient redirects <stringToPrint> to PrintServer
PrintServer just print out <stringToPrint> in console
The scenario is meant as a proof-of-concept, and will be the basis for a evaluation in the company I'm working at, therefore it needs to accomplish the following tasks:
both applications are running inside the MiniKube-cluster
PrintClient should have an ExternalService
PrintServer should have an InternalService
the URL for PrintServer should come from a ConfigMap using
PrintServer's InternalService
Code
Here are the relevant files for my scenario.
At first I show you the code of both applications:
PrintClient
PrintClientApplication.java
#SpringBootApplication
public class PrintClientApplication {
public static void main(String[] args) {
SpringApplication.run(PrintClientApplication.class, args);
}
#Bean
public RestTemplate getRestTemplate(RestTemplateBuilder builder) {
return builder.build();
}
}
Api.java
#RestController
public class Api {
#Autowired
private RestTemplate rs;
#Value("${PRINT_SERVER_URL}")
private String printServerUrl;
#GetMapping("/{string}")
public void print(#PathVariable("string")String string) {
System.out.println(printServerUrl);
rs.getForObject( printServerUrl + string, String.class);
}
}
application.properties
PRINT_SERVER_URL=thisIsJustAPlaceholder
Dockerfile
FROM java:8-jdk-alpine
COPY /target/print_client-0.0.1-SNAPSHOT.jar /usr/app/
ENV PRINT_SERVER_URL=blah
WORKDIR /usr/app/
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "print_client-0.0.1-SNAPSHOT.jar", "PRINT_SERVER_URL=${PRINT_SERVER_URL}"]
deployment+service
apiVersion: apps/v1
kind: Deployment
metadata:
name: print-client-deployment
spec:
selector:
matchLabels:
app: print-client-label
replicas: 1
template:
metadata:
labels:
app: print-client-label
spec:
containers:
- name: print-client
image: patrickshaikh/print_client:1
ports:
- containerPort: 8080
env:
- name: PRINT_SERVER_URL
valueFrom:
configMapKeyRef:
name: print-client-configmap
key: print_server_url
---
apiVersion: v1
kind: Service
metadata:
name: print-client-service
spec:
selector:
app: print-client-label
type: LoadBalancer
ports:
- protocol: TCP
port: 8080
targetPort: 8080
nodePort: 30001
configmap
apiVersion: v1
kind: ConfigMap
metadata:
name: print-client-configmap
data:
print_server_url: print-server-service
PrintServer
Api.java
#RestController
public class Api {
#GetMapping("/{string}")
public void hello(#PathVariable("string") String string) {
System.out.println(string);
}
}
deployment+service
apiVersion: apps/v1
kind: Deployment
metadata:
name: print-server-deployment
spec:
selector:
matchLabels:
app: print-server
replicas: 1
template:
metadata:
labels:
app: print-server
spec:
containers:
- name: print-server
image: patrickshaikh/print_server:1
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: print-server-service
spec:
selector:
app: print-server
type: LoadBalancer
ports:
- protocol: TCP
port: 8080
targetPort: 8080
nodePort: 30000
(It is an ExternalService for testing purpose, but will be internal later.)
I already checked if CoreDNS is running:
Misbehaviour
I used the name of the print-server-service in the ConfigMap but instead of resolving it to an URL before passing the value to the container on initialization, it treats it as a string (during a testiteration I printed the URL to console as well).
Using the IP of PrintServers InternalService results in a 404 while using the IP of its ExternalService works flawlessly.
Questions at answerers
Why can't it resolve the reference to the print-server-service to
its internal IP?
What would be the proper way of passing URLs to a container using
servicenames?
Is there anything else in terms of "best practice" in my scenario i
could adapt?
Thanks in advance

spring cloud unable to route to internal application

I am using spring cloud to route application but unable to do so below are the details
Gateway configuration
port: 8080
debug: true
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true
lower-case-senstive: true
routes:
- id: product-composite
uri: localhost:7000
predicates:
- Path: /product-composite/**
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
server:
port: 8761
waitTimeInMsWhenSyncEmpty: 0
response-cache-update-interval: 5000
management.endpoints.web.exposure.include: '*'
Product Composite Service* (I am trying to call)
port: 7000
spring:
application:
name: product-composite
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
initialInstanceInfoReplicationIntervalSeconds: 5
registryFetchIntervalSeconds: 5
register-with-eureka: true
fetch-registery: true
instance:
leaseRenewalIntervalInSeconds: 5
leaseExpirationDurationInSeconds: 5
Path
#RestController
public class ProductCompositeServiceController {
#GetMapping
public String getString() {
return "Hello grom product CompositeController";
}
}
Can you help? If needed I can provide more details
Note: if product-composite-servcie is called without eureka I am getting response but with eureka I am getting
404 Resource not found
Edit
Below is the stacktrace I am getting so far:
2020-06-24 22:22:05.252 DEBUG 38876 --- [or-http-epoll-2] o.s.w.r.handler.SimpleUrlHandlerMapping : [63939523-1] Mapped to ResourceWebHandler ["classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"]
2020-06-24 22:22:05.255 DEBUG 38876 --- [or-http-epoll-2] o.s.w.r.resource.ResourceWebHandler : [63939523-1] Resource not found
2020-06-24 22:22:05.273 DEBUG 38876 --- [or-http-epoll-2] a.w.r.e.AbstractErrorWebExceptionHandler : [63939523-1] Resolved [ResponseStatusException: 404 NOT_FOUND] for HTTP GET /product-composite/
2020-06-24 22:22:05.281 DEBUG 38876 --- [or-http-epoll-2] o.s.http.codec.json.Jackson2JsonEncoder : [63939523-1] Encoding [{timestamp=Wed Jun 24 22:22:05 IST 2020, path=/product-composite/, status=404, error=Not Found, mess (truncated)...]
2020-06-24 22:22:05.299 DEBUG 38876 --- [or-http-epoll-2] o.s.w.s.adapter.HttpWebHandlerAdapter : [63939523-1] Completed 404 NOT_FOUND
I also tried to add path as
routes:
- id: product-composite
uri: localhost:7000
predicates:
- Path: /product-composite/**
filters:
- RewritePath: /product-composite/(?<segment>.*), /$\{segment}
You don't have a path in your controller. Try
#GetMapping("/product-composite")

Redis & Spring Boot integration with K8S error

I have the following docker file:
FROM openjdk:8-jdk-alpine
ENV PORT 8094
EXPOSE 8094
RUN mkdir -p /app/
COPY build/libs/fqdn-cache-service.jar /app/fqdn-cache-service.jar
WORKDIR /build
ENTRYPOINT [ "sh" "-c", "java -jar /app/fqdn-cache-service.jar" ]
docker-compose.yaml file:
version: '3'
services:
app:
build:
context: .
dockerfile: Dockerfile
image: fqdn-cache-service
ports:
- "8094:8094"
links:
- "db:redis"
db:
image: "redis:alpine"
#hostname: redis
ports:
- "6378:6378"
deployment.yaml file
apiVersion: apps/v1
kind: Deployment
metadata:
name: fqdn-cache-service
spec:
selector:
matchLabels:
run: spike
replicas: 1
template:
metadata:
labels:
app: redis
run: spike
spec:
containers:
- name: fqdn-cache-service
imagePullPolicy: Never
image: fqdn-cache-service:latest
ports:
- containerPort: 8094
protocol: TCP
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
spec:
selector:
matchLabels:
run: spike
replicas: 1
template:
metadata:
labels:
run: spike
spec:
hostname: redis
containers:
- name: redis
image: redis:alpine
ports:
- containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:
name: fqdn-cache-service
labels:
run: spike
spec:
type: NodePort
ports:
- port: 8094
nodePort: 30001
selector:
run: spike
---
apiVersion: v1
kind: Service
metadata:
name: redis
labels:
run: spike
app: redis
spec:
type: NodePort
ports:
- port: 6379
nodePort: 30002
selector:
run: spike
And the cluster info ip is 127.0.0.1.
I'm using microk8s over ubuntu OS.
If I request for get by and ID (127.0.0.1/webapi/users/1) I get the error:
Cannot get Jedis connection; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
Although on regular java application with redis or dockerize spring boot with redis it's working.
Any help why this is happened?
This is the configuration of the spring boot:
#Configuration
public class ApplicationConfig {
#Bean
JedisConnectionFactory jedisConnectionFactory() {
JedisConnectionFactory factory = new JedisConnectionFactory();
factory.setHostName("127.0.0.1");
factory.setPort(30001);
factory.setUsePool(true);
return factory;
}
#Bean
RedisTemplate redisTemplate() {
RedisTemplate<String, FqdnMapping> redisTemplate = new RedisTemplate<String, FqdnMapping>();
redisTemplate.setConnectionFactory(jedisConnectionFactory());
return redisTemplate;
}
}
The issue also happenes if the host name is localhost and\or the port is 6379...
Thanks!
When you're running in a container, 127.0.0.1 usually refers to the container itself, not to the host the container is running on. If you're trying to connect to a service, try using its name and port: "redis" on port 6379 and "fqdn-cache-service" on 8094.

Resources