DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • 7 Microservices Best Practices for Developers
  • Distributed Tracing System (Spring Cloud Sleuth + OpenZipkin)
  • Using Kong Ingress Controller with Spring Boot Services
  • Component Tests for Spring Cloud Microservices

Trending

  • Mastering Advanced Aggregations in Spark SQL
  • Enhancing Security With ZTNA in Hybrid and Multi-Cloud Deployments
  • Unlocking AI Coding Assistants: Generate Unit Tests
  • Medallion Architecture: Efficient Batch and Stream Processing Data Pipelines With Azure Databricks and Delta Lake
  1. DZone
  2. Software Design and Architecture
  3. Cloud Architecture
  4. Spring Cloud Config Server on Kubernetes (Part 1)

Spring Cloud Config Server on Kubernetes (Part 1)

Let's get your services up and running.

By 
Brian Hannaway user avatar
Brian Hannaway
·
May. 02, 21 · Tutorial
Likes (5)
Comment
Save
Tweet
Share
8.7K Views

Join the DZone community and get the full member experience.

Join For Free

This is the first of a two part article where I’ll show you how to use Spring Cloud Config Server to build centralised configuration for your microservices. In this first post we’ll create a Config Service that pulls its data from a Git repo and exposes it to other services. We’ll also create a consumer, a Config Consumer Service that pulls from the Config Service on startup. The diagram below shows how the services will interact.

Service Interactions

In part two of this article we’ll take the two services and deploy them to Kubernetes. We’ll initially deploy and test on a local Kubernetes cluster, before deploying on Azures manged Kubernetes Service, AKS.

The diagram below is a sneak peak of what we’ll eventually run on Kubernetes.

App running on Kubernetes

Source Code

The source code for this post and part two is available on Github. Feel free to pull it and have a dig around.

Creating the Config Service

Without further ado lets put Spring Cloud Config Server to work and create the first of our two services, the Config Service.

To turn a vanilla Spring Boot app into a Spring Cloud Config Server you’ll need spring-cloud-dependencies and spring-cloud-config-server in your POM.

XML
 




xxxxxxxxxx
1
56


 
1
<?xml version="1.0" encoding="UTF-8"?>
2
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4
  <modelVersion>4.0.0</modelVersion>
5
  <groupId>com.briansjavablog.microservices</groupId>
6
  <artifactId>config-server</artifactId>
7
  <version>0.0.1-SNAPSHOT</version>
8
  <packaging>jar</packaging>
9
  <name>config-server</name>
10
  <description>Demo config server provides centralised configuration for micro services</description>
11
  <parent>
12
    <groupId>org.springframework.boot</groupId>
13
    <artifactId>spring-boot-starter-parent</artifactId>
14
    <version>2.4.2</version>
15
    <relativePath/> <!-- lookup parent from repository -->
16
  </parent>
17
 
          
18
  <properties>
19
    <java.version>11</java.version>
20
    <spring-cloud.version>2020.0.0</spring-cloud.version>
21
  </properties>
22
 
          
23
  <dependencies>
24
    <dependency>
25
      <groupId>org.springframework.cloud</groupId>
26
      <artifactId>spring-cloud-config-server</artifactId>
27
    </dependency>
28
    <dependency>
29
      <groupId>org.springframework.boot</groupId>
30
      <artifactId>spring-boot-starter-test</artifactId>
31
      <scope>test</scope>
32
    </dependency>
33
  </dependencies>
34
 
          
35
  <dependencyManagement>
36
    <dependencies>
37
      <dependency>
38
        <groupId>org.springframework.cloud</groupId>
39
        <artifactId>spring-cloud-dependencies</artifactId>
40
        <version>${spring-cloud.version}</version>
41
        <type>pom</type>
42
        <scope>import</scope>
43
      </dependency>
44
    </dependencies>
45
  </dependencyManagement>
46
 
          
47
  <build>
48
    <plugins>
49
      <plugin>
50
        <groupId>org.springframework.boot</groupId>
51
        <artifactId>spring-boot-maven-plugin</artifactId>
52
      </plugin>
53
    </plugins>
54
  </build>
55
 
          
56
</project>



Next add the @EnableConfigServer annotation to the main application class.

Java
 




xxxxxxxxxx
1
14


 
1
package com.briansjavablog.microservices.configserver;
2
 
          
3
import org.springframework.boot.SpringApplication;
4
import org.springframework.boot.autoconfigure.SpringBootApplication;
5
import org.springframework.cloud.config.server.EnableConfigServer;
6
 
          
7
@EnableConfigServer
8
@SpringBootApplication
9
public class ConfigServerApplication {
10
 
          
11
  public static void main(String[] args) {
12
    SpringApplication.run(ConfigServerApplication.class, args);
13
  }
14
}



Service Configuration

The Config Service is going to use Git as its configuration repository. In order for the Config Service to pull the configuration, we’ll need to provide the details of the GIT repo in application.yml.

YAML
 




xxxxxxxxxx
1
21


 
1
spring:
2
  application:
3
    name: config-server
4
  cloud:
5
    config:
6
      server:
7
        git:
8
          # URI of GIT repo containing properties
9
          uri: https://github.com/briansjavablog/spring-config-server-on-kubernettes
10
          default-label: main
11
          search-paths: configuration
12
server:
13
  port: 8888
14
management:
15
  endpoint:
16
      health:
17
        show-details: always
18
  endpoints:
19
    web:
20
      exposure:
21
        include: "*"



The most important config here is lines 4 to 11.

  • uri: https://github.com/briansjavablog/spring-config-server-on-kubernettes is the URI of the repo that Config Service will clone.
  • default-label: main tells the Config Service to use the main branch of the repository
  • search-paths: configuration is the path of the properties in the repo.

These three attributes combined, will tell the Config Service to serve up configuration from https://github.com/briansjavablog/spring-config-server-on-kubernettes/tree/main/configuration

Lines 14 to 21 enable the actuator endpoints. We’re only really interested in the health endpoint as we’ll need it later when deploying to the Kubernetes cluster.

Defining a Dockerfile

Now that we’ve defined the Config Service, the next step is to containerise it with Docker. The Dockerfile below is pretty straight forward. It uses a JRE 11 base image, adds the packaged JAR and runs the JAR on startup via the command in ENRTYPOINT. I’ve also installed cURL as it can be handy for debugging connectivity issues between containers.

Dockerfile
 




xxxxxxxxxx
1


 
1
FROM openjdk:11-jre-slim-buster
2
MAINTAINER Brian Hannaway
3
RUN apt-get update
4
RUN apt-get -y install curl
5
WORKDIR /app
6
COPY /target/config-server-0.0.1-SNAPSHOT.jar /app/
7
ENTRYPOINT ["java", "-jar", "config-server-0.0.1-SNAPSHOT.jar"]



Now that we’ve defined the Config Service, its time to put it to work. Next we’ll create a consumer service that will pull its configuration from Config Service on startup.

Config Consumer Service

The Config Consumer service is a vanilla Spring Boot app with a simple REST endpoint. On startup the Config Consumer Service will call the Config Service to retrieve its configuration. The REST endpoint will return the config values loaded from the Configuration Service, allowing us to do a simple end to end test.

POM Definition

To consume config from the Confg Service we’ll need spring-cloud-starter-config in the POM. The full POM definition is shown below.

XML
 




xxxxxxxxxx
1
84


 
1
<?xml version="1.0" encoding="UTF-8"?>
2
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4
  <modelVersion>4.0.0</modelVersion>
5
  <groupId>com.briansjavablog.microservices</groupId>
6
  <artifactId>config-consumer-service</artifactId>
7
  <version>0.0.1-SNAPSHOT</version>
8
  <packaging>jar</packaging>
9
  <name>config-consumer-service</name>
10
  <parent>
11
    <groupId>org.springframework.boot</groupId>
12
    <artifactId>spring-boot-starter-parent</artifactId>
13
    <version>2.4.2</version>
14
    <relativePath/> <!-- lookup parent from repository -->
15
  </parent>
16
 
          
17
  <properties>
18
    &llt;java.version>11</java.version>
19
    <spring-cloud.version>2020.0.0</spring-cloud.version>
20
  </properties>
21
  <dependencies>
22
    <dependency>
23
      <groupId>org.springframework.boot</groupId>
24
      <artifactId>spring-boot-starter-actuator</artifactId>
25
    </dependency>
26
    <dependency>
27
      <groupId>org.springframework.boot</groupId>
28
      <artifactId>spring-boot-starter-web</artifactId>
29
    </dependency>
30
    <dependency>
31
      <groupId>org.springframework.cloud</groupId>
32
      <artifactId>spring-cloud-starter-config</artifactId>
33
    </dependency>
34
    <dependency>
35
      <groupId>org.projectlombok</groupId>
36
      <artifactId>lombok</artifactId>
37
      <optional>true</optional>
38
    </dependency>
39
    <dependency>
40
      <groupId>org.springframework.retry</groupId>
41
      <artifactId>spring-retry</artifactId>
42
    </dependency>
43
    <dependency>
44
      <groupId>org.springframework</groupId>
45
      <artifactId>spring-aspects</artifactId>
46
    </dependency>
47
    <dependency>
48
      <groupId>org.springframework.cloud</groupId>
49
      <artifactId>spring-cloud-starter-bootstrap</artifactId>
50
    </dependency>
51
    <dependency>
52
      <groupId>org.springframework.boot</groupId>
53
      <artifactId>spring-boot-starter-test</artifactId>
54
      <scope>test</scope>
55
    </dependency>
56
  </dependencies>
57
  <dependencyManagement>
58
    <dependencies>
59
      <dependency>
60
        <groupId>org.springframework.cloud</groupId>
61
        <artifactId>spring-cloud-dependencies</artifactId>
62
        <version>${spring-cloud.version}</version>
63
        <type>pom</type>
64
        <scope>import</scope>
65
      </dependency>
66
    </dependencies>
67
  </dependencyManagement>
68
 
          
69
  <build>
70
    <plugins>
71
      <plugin>
72
        <groupId>org.springframework.boot</groupId>
73
        <artifactId>spring-boot-maven-plugin</artifactId>
74
      </plugin>
75
    </plugins>
76
  </build>
77
  <repositories>
78
    <repository>
79
      <id>spring-milestones</id>
80
      <name>Spring Milestones</name>
81
      <url>https://repo.spring.io/milestone</url>
82
    </repository>
83
  </repositories>
84
</project>



REST Endpoint

The REST endpoint is very simple. It returns a TimoutConfig object with 2 values, connectionTimeoutMillis and readTimeoutMillis. These values are sourced from the Config Service and injected into the controller via Configuration.

Java
 




xxxxxxxxxx
1
19


 
1
@Slf4j
2
@RestController
3
@AllArgsConstructor
4
public class ConfigConsumerController {
5
 
          
6
  private Configuration configuration;
7
 
          
8
  @GetMapping("/timeout-config")
9
  public ResponseEntity<TimeoutConfig> getTimeoutConfiguration(){
10
 
          
11
    TimeoutConfig timeoutConfig = new TimeoutConfig();
12
    timeoutConfig.setConnectionTimeoutMillis(configuration.getConnectionTimeoutMillis());
13
    timeoutConfig.setReadTimeoutMillis(configuration.getReadTimeoutMillis());
14
 
          
15
    log.info("retrieving TimeoutConfig [{}]", timeoutConfig);
16
    
17
    return ResponseEntity.ok(timeoutConfig);
18
  }
19
}



Configuration Properties

Configuration contains the two config values that we exposed on the REST endpoint. The @ConfigurationProperties(prefix="config-consumer-service") annotation along with the configuration in bootstrap.yml, tell Spring boot to source connectionTimeoutMillis and readTimeoutMillis from the Config Service, on startup. The prefix config-consumer-service is passed to the Config Service and used as a key to look up the configuration specific to the Config Consumer Service.

Java
 




xxxxxxxxxx
1
10


 
1
@Setter
2
@Getter
3
@Component
4
@EnableRetry
5
@ConfigurationProperties(prefix="config-consumer-service")
6
public class Configuration {
7
 
          
8
  private Integer connectionTimeoutMillis;
9
  private Integer readTimeoutMillis;
10
}



bootstrap.yml

In order to load configuration from a Spring Cloud Config Server, we need to provide the connection details for the service we’re calling. To make these connection details available to Spring Boot early in the startup sequence, we need add them to bootstrap.yml rather than application.yml. We do this because bootstrap.yml is loaded by the parent ApplicationContext, before application.yml is loaded.

YAML
 




xxxxxxxxxx
1
16


 
1
spring:
2
  application:
3
    name: config-consumer-service
4
  cloud:
5
    config:
6
      profile: uat
7
      # target URI for config server corresponds to Kubernetes Service config-service
8
      uri: http://config-service:8888
9
      # the label must correspond with the branch name in Github
10
      label: main
11
      fail-fast: true
12
      retry:
13
        # retry configuration retrieval up to 100 times
14
        max-attempts: 30
15
        # max backoff interval
16
        max-interval: 8000



  • name: config-consumer-service tells the Config Service what application is requesting its configuration
  • profile: uat tells the Config Service to return properties associated with the active profile uat
  • uri: http://config-service:8888 is the URI of the Config Service
  • label: main is the name of the branch in the Git repo, containing the properties
  • fail-fast: true tells the Config Consumer Service to fail startup if it cannot retrieve its properties from Config Service
  • max-attempts: 30 used by Spring Retry to retry the call to Config Service up to 30 times, in the event of a failure. This is useful as the Config Service may not be immediately available when the Config Consumer Service starts up.
  • max-internal: 8000 is the maximum back off time between retries

Defining a Dockerfile

The Dockerfile definition for Config Consumer Service is almost identical to the one we used for Config Service. The only difference is the name of the JAR that’s copied in and executed.

Wrapping Up

If you’ve made it this far, you’ll have created the Config Service and the Config Consumer Service. The next step is defining the Kubernetes resources required to run our services in a cluster. We’ll look at the Kubernetes manifest in detail in part two.

Spring Framework Spring Cloud Kubernetes microservice

Published at DZone with permission of Brian Hannaway, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • 7 Microservices Best Practices for Developers
  • Distributed Tracing System (Spring Cloud Sleuth + OpenZipkin)
  • Using Kong Ingress Controller with Spring Boot Services
  • Component Tests for Spring Cloud Microservices

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!