Table of contents
1. Why do you need Spring Cloud Kubernetes?
3. DiscoveryClient for Kubernetes
4. Kubernetes native service discovery (service discovery)
5. Implementation of Kubernetes PropertySource
1. Use ConfigMap PropertySource
1. Why do you need Spring Cloud Kubernetes?
Spring Cloud Kubernetes provides implementations of the well-known Spring Cloud interfaces, allowing developers to build and run Spring Cloud applications on Kubernetes. While this project may be useful to you when building cloud-native applications, it is not a requirement for deploying Spring Boot applications on Kubernetes. If you are just starting to run your Spring Boot application on Kubernetes, you only need a basic Spring Boot application and Kubernetes itself can do a lot
2. Starter
Starters are convenient dependency descriptions that you can include in your application. Import a Starter for feature set dependencies and Spring Boot auto-configuration. Starters starting with spring-cloud-starter-kubernetes-fabric8 provide implementations using the Fabric8 Kubernetes Java client. Starters starting with spring-cloud-starter-kubernetes-client provide implementations using the Kubernetes Java client.
Starter | Features |
Fabric8 dependencies <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-kubernetes-fabric8</artifactId> </dependency> Kubernetes Client dependencies <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-kubernetes-client</artifactId> </dependency> |
Discovery Client implementation, the service name (service name) Resolved as a Kubernetes service. |
Fabric8 dependencies <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-kubernetes-fabric8-config</artifactId> </dependency> Kubernetes Client dependencies <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-kubernetes-client-config</artifactId> </dependency> |
Load application from Kubernetes ConfigMap and Secret application properties. When ConfigMap or Secret When a change occurs, the application properties are reloaded. |
Fabric8 dependencies <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-kubernetes-fabric8-all</artifactId> </dependency> Kubernetes Client dependencies <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-kubernetes-client-all</artifactId> </dependency> |
All Spring Cloud Kubernetes features. |
3. DiscoveryClient for Kubernetes
This project provides an implementation of Discovery Client for Kubernetes. This client (Client) allows you to query Kubernetes endpoints by name (see services). A service, typically exposed by a Kubernetes API server, is a collection of endpoints representing http and https addresses that clients can access from within a Spring Boot application running as a pod.
This is something you get automatically by adding the following dependencies to your project.
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-kubernetes-discoveryclient</artifactId> </dependency>
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-kubernetes-fabric8</artifactId> </dependency>
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-kubernetes-client</artifactId> </dependency>
To enable loading DiscoveryClient
of , @EnableDiscoveryClient
add to the appropriate configuration or application class, as shown in the example below.
@SpringBootApplication @EnableDiscoveryClient public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
You can then inject the client into your code via auto-injection, as shown in the example below.
@Autowired private DiscoveryClient discoveryClient;
You can opt-in from all namespaces by setting the following property application.properties
in DiscoveryClient
.
spring.cloud.kubernetes.discovery.all-namespaces=true
To discover services and endpoints only from specified namespaces, you should all-namespaces
set to false
, and set the following properties application.properties
in (in this example the namespaces are : ns1
and ns2
).
spring.cloud.kubernetes.discovery.namespaces[0]=ns1 spring.cloud.kubernetes.discovery.namespaces[1]=ns2
To discover service endpoint addresses that are not marked as "ready" by the kubernetes api server, the following property can be set application.properties
in (default: false
):
spring.cloud.kubernetes.discovery.include-not-ready-addresses=true
If your service exposes multiple ports, you will need to specify which port DiscoveryClient
should be used. DiscoveryClient
The following logic will be used to select the port.
- If the service has a label
primary-port-name
, it will use the port with the name specified in the label value. - If there is no label, the port name specified
spring.cloud.kubernetes.discovery.primary-port-name
in . - If neither of the above is specified, it will use the port
https
named . - If none of the above conditions are met, it will use the port
http
named . - As a last resort, it will select the first port in the port list.
By default, all ports and their names will be ServiceInstance
added the metadata.
If for any reason you need to disable it DiscoveryClient
, you can set the following property application.properties
in :
spring.cloud.kubernetes.discovery.enabled=false
Used by some Spring Cloud components DiscoveryClient
to obtain information about local service instances. To do this, you need to align the Kubernetes service name with spring.application.name
the attribute .
Spring Cloud Kubernetes can also observe changes to the Kubernetes service catalog and update DiscoveryClient
the implementation . By "watch" we mean publishing a heartbeat event every spring.cloud.kubernetes.discovery.catalog-services-watch-delay
milliseconds (30000 by default). The heartbeat event will contain the target reference as well as all endpoint addresses in the namespace (for exact details on what is returned, you can look at KubernetesCatalogWatch
internals ). This is an implementation detail and listeners of heartbeat events should not rely on these details. Instead, they should go through equals
the method to see if there is a difference between two subsequent heartbeats. We'll take care to return a correct implementation, obeying equals
the contract . The endpoint will be queried in two ways.
- All namespaces (
spring.cloud.kubernetes.discovery.all-namespaces=true
enabled ) - Specific namespaces (
spring.cloud.kubernetes.discovery.namespaces
enabled ), for example:
spring: cloud: kubernetes: discovery: namespaces: - namespace-a - namespace-b
- If we do not take the above two paths, we will use namespace resolution (Namespace Resolution).
In order to enable this feature, you need to add @EnableScheduling to the configuration class in your application. By default, we use the Endpoints (see kubernetes.io/docs/concepts/services-networking/service/#endpoints ) API to find the current state of the service. But there is another way, via EndpointSlices (kubernetes.io/docs/concepts/services-networking/endpoint-slices/). This support can be enabled via a property: spring.cloud.kubernetes.discovery.use-endpoint-slices=true (default is false). Of course, your cluster must also support it. In fact, if you enable this property, but your cluster doesn't support it, we won't be able to start the application. If you decide to enable this support, you will also need to set the Role/ClusterRole appropriately. For example:
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: default name: namespace-reader rules: - apiGroups: ["discovery.k8s.io"] resources: ["endpointslices"] verbs: ["get", "list", "watch"]
4. Kubernetes native service discovery (service discovery)
Kubernetes itself is capable of (server-side) service discovery (see: kubernetes.io/docs/concepts/services-networking/service/#discovering-services). Using native kubernetes service discovery ensures compatibility with other tools such as Istio (istio.io), a service mesh capable of load balancing, circuit breakers, failover, and more.
The caller service then simply references a resolvable name in the specific Kubernetes cluster. A simple implementation could use a spring RestTemplate pointing to a fully qualified domain name (FQDN), such as {service-name}.{namespace}.svc.{cluster}.local:{service-port}.
Additionally, you can use Hystrix for:
Implement the circuit breaker on the caller side by annotating @EnableCircuitBreaker in the spring boot application.
Fallback function, by annotating the corresponding method with @HystrixCommand(fallbackMethod=…).
5. Implementation of Kubernetes PropertySource
The most common way to configure a Spring Boot application is to create an application.properties or application.yaml or application-profile.properties or application-profile.yaml file that contains key-value pairs that provide custom values for your application or Spring Boot Starter . You can override these properties by specifying system properties or environment variables.
To enable this, you need to set spring.config.import=kubernetes in your application's configuration properties: Currently, you cannot use spring.config.import to specify a ConfigMap or Secret to load, by default Spring Cloud Kubernetes will Load ConfigMap and/or Secret based on spring.application.name property. If spring.application.name is not set, it will load a ConfigMap and/or Secret with the application name.
If you want to load the Kubernetes PropertySource at startup, like before 3.0.x, you can add spring-cloud-starter-bootstrap to your application's classpath, or set spring.cloud.bootstrap.enabled=true as an environment variable.
1. Use ConfigMap PropertySource
Kubernetes provides a resource called a ConfigMap that externalizes parameters to pass to your application in the form of key-value pairs or embedded application.properties or application.yaml files. The Spring Cloud Kubernetes Config project makes Kubernetes ConfigMap instances available during application startup and triggers hot reloading of beans or Spring contexts when changes are detected on observed ConfigMap instances.
Everything explained below refers mainly to examples using ConfigMap, but the same is true for Secret, ie: both support every feature.
The default behavior is to create a Fabric8ConfigMapPropertySource (or KubernetesClientConfigMapPropertySource) based on the Kubernetes ConfigMap, whose metadata.name value is the name of the Spring application (defined by its spring.application.name property) or a custom name defined in the application.properties file, the key is as follows : spring.cloud.kubernetes.config.name.
However, more advanced configurations are possible and you can use multiple ConfigMap instances. The spring.cloud.kubernetes.config.sources list makes this possible. For example, you can define the following ConfigMap instance:
spring: application: name: cloud-k8s-app cloud: kubernetes: config: name: default-name namespace: default-namespace sources: # Spring Cloud Kubernetes looks up a ConfigMap named c1 in namespace default-namespace - name: c1 # Spring Cloud Kubernetes looks up a ConfigMap named default-name in whatever namespace n2 - namespace: n2 # Spring Cloud Kubernetes looks up a ConfigMap named c3 in namespace n3 - namespace: n3 name: c3