This reference guide covers how to use Spring Cloud Kubernetes.
Why do you need Spring Cloud Kubernetes?
Spring Cloud Kubernetes provide Spring Cloud common interface
implementations that consume Kubernetes native services. The main
objective of the projects provided in this repository is to facilitate
the integration of Spring Cloud and Spring Boot applications running
inside Kubernetes.
Starters
Starters are convenient dependency descriptors you can include in your
application. Include a starter to get the dependencies and Spring Boot
auto-configuration for a feature set.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes</artifactId>
</dependency>
----, <<DiscoveryClient for Kubernetes,Discovery Client>> implementation that
resolves service names to Kubernetes Services., [source,xml]
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-config</artifactId>
</dependency> ----, Load application properties from Kubernetes
[ConfigMaps](#ConfigMap PropertySource) and
Secrets. [Reload](#PropertySource Reload)
application properties when a ConfigMap or Secret changes.,
[source,xml]
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-ribbon</artifactId>
</dependency>
----, <<Ribbon discovery in Kubernetes,Ribbon>> client-side load balancer with
server list obtained from Kubernetes Endpoints., [source,xml]
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-all</artifactId>
</dependency> ----, All Spring Cloud Kubernetes features., ===
DiscoveryClient for Kubernetes
This project provides an implementation of Discovery
Client
for Kubernetes. This client lets you query
Kubernetes endpoints (see
services) by name. A
service is typically exposed by the Kubernetes API server as a
collection of endpoints that represent http
and https
addresses and
that a client can access from a Spring Boot application running as a
pod. This discovery feature is also used by the Spring Cloud Kubernetes
Ribbon project to fetch the list of the endpoints defined for an
application to be load balanced.
This is something that you get for free by adding the following
dependency inside your project:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes</artifactId>
</dependency>
To enable loading of the DiscoveryClient
, add @EnableDiscoveryClient
to the according configuration or application class, as the following
example shows:
@SpringBootApplication
@EnableDiscoveryClient
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Then you can inject the client in your code simply by autowiring it, as
the following example shows:
@Autowired
private DiscoveryClient discoveryClient;
You can choose to enable DiscoveryClient
from all namespaces by
setting the following property in application.properties
:
spring.cloud.kubernetes.discovery.all-namespaces=true
If, for any reason, you need to disable the DiscoveryClient
, you can
set the following property in application.properties
:
spring.cloud.kubernetes.discovery.enabled=false
Some Spring Cloud components use the DiscoveryClient
in order to
obtain information about the local service instance. For this to work,
you need to align the Kubernetes service name with the
spring.application.name
property.
spring.application.name
has no effect as far as the name registered
for the application within Kubernetes
Spring Cloud Kubernetes can also watch the Kubernetes service catalog
for changes and update the DiscoveryClient
implementation accordingly.
In order to enable this functionality you need to add
@EnableScheduling
on a configuration class in your application.
Kubernetes native 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
additional tooling, such as Istio (istio.io), a
service mesh that is capable of load balancing, ribbon, circuit breaker,
failover, and much more.
The caller service then need only refer to names resolvable in a
particular Kubernetes cluster. A simple implementation might use a
spring RestTemplate
that refers to a fully qualified domain name
(FQDN), such as
{service-name}.{namespace}.svc.{cluster}.local:{service-port}
.
Additionally, you can use Hystrix for:
-
Circuit breaker implementation on the caller side, by annotating the
spring boot application class with @EnableCircuitBreaker
-
Fallback functionality, by annotating the respective method with
@HystrixCommand(fallbackMethod=
Kubernetes PropertySource implementations
The most common approach to configuring your Spring Boot application is
to create an application.properties
or application.yaml
or an
application-profile.properties
or application-profile.yaml
file that
contains key-value pairs that provide customization values to your
application or Spring Boot starters. You can override these properties
by specifying system properties or environment variables.
Using a ConfigMap
PropertySource
Kubernetes provides a resource named
ConfigMap
to
externalize the 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 bootstrapping and
triggers hot reloading of beans or Spring context when changes are
detected on observed ConfigMap
instances.
The default behavior is to create a ConfigMapPropertySource
based on a
Kubernetes ConfigMap
that has a metadata.name
value of either the
name of your Spring application (as defined by its
spring.application.name
property) or a custom name defined within the
bootstrap.properties
file under the following key:
spring.cloud.kubernetes.config.name
.
However, more advanced configuration is possible where you can use
multiple ConfigMap
instances. The
spring.cloud.kubernetes.config.sources
list makes this possible. For
example, you could define the following ConfigMap
instances:
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
In the preceding example, if spring.cloud.kubernetes.config.namespace
had not been set, the ConfigMap
named c1
would be looked up in the
namespace that the application runs.
Any matching ConfigMap
that is found is processed as follows:
-
Apply individual configuration properties.
-
Apply as yaml
the content of any property named
application.yaml
.
-
Apply as a properties file the content of any property named
application.properties
.
The single exception to the aforementioned flow is when the ConfigMap
contains a single key that indicates the file is a YAML or
properties file. In that case, the name of the key does NOT have to be
application.yaml
or application.properties
(it can be anything) and
the value of the property is treated correctly. This features
facilitates the use case where the ConfigMap
was created by using
something like the following:
kubectl create configmap game-config --from-file=/path/to/app-config.yaml
Assume that we have a Spring Boot application named demo
that uses the
following properties to read its thread pool configuration.
-
pool.size.core
-
pool.size.maximum
This can be externalized to config map in yaml
format as follows:
kind: ConfigMap
apiVersion: v1
metadata:
name: demo
data:
pool.size.core: 1
pool.size.max: 16
Individual properties work fine for most cases. However, sometimes,
embedded yaml
is more convenient. In this case, we use a single
property named application.yaml
to embed our yaml
, as follows:
kind: ConfigMap
apiVersion: v1
metadata:
name: demo
data:
application.yaml:, -
pool:
size:
core: 1
max:16
The following example also works:
kind: ConfigMap
apiVersion: v1
metadata:
name: demo
data:
custom-name.yaml:, -
pool:
size:
core: 1
max:16
You can also configure Spring Boot applications differently depending on
active profiles that are merged together when the ConfigMap
is read.
You can provide different property values for different profiles by
using an application.properties
or application.yaml
property,
specifying profile-specific values, each in their own document
(indicated by the ---
sequence), as follows:
kind: ConfigMap
apiVersion: v1
metadata:
name: demo
data:
application.yml:, -
greeting:
message: Say Hello to the World
farewell:
message: Say Goodbye
---
spring:
profiles: development
greeting:
message: Say Hello to the Developers
farewell:
message: Say Goodbye to the Developers
---
spring:
profiles: production
greeting:
message: Say Hello to the Ops
In the preceding case, the configuration loaded into your Spring
Application with the development
profile is as follows:
greeting:
message: Say Hello to the Developers
farewell:
message: Say Goodbye to the Developers
However, if the production
profile is active, the configuration
becomes:
greeting:
message: Say Hello to the Ops
farewell:
message: Say Goodbye
If both profiles are active, the property that appears last within the
ConfigMap
overwrites any preceding values.
Another option is to create a different config map per profile and
spring boot will automatically fetch it based on active profiles
kind: ConfigMap
apiVersion: v1
metadata:
name: demo
data:
application.yml:, -
greeting:
message: Say Hello to the World
farewell:
message: Say Goodbye
kind: ConfigMap
apiVersion: v1
metadata:
name: demo-development
data:
application.yml:, -
spring:
profiles: development
greeting:
message: Say Hello to the Developers
farewell:
message: Say Goodbye to the Developers
kind: ConfigMap
apiVersion: v1
metadata:
name: demo-production
data:
application.yml:, -
spring:
profiles: production
greeting:
message: Say Hello to the Ops
farewell:
message: Say Goodbye
To tell Spring Boot which profile
should be enabled at bootstrap, you
can pass SPRING_PROFILES_ACTIVE
environment variable. To do so, you
can launch your Spring Boot application with an environment variable
that you can define it in the PodSpec at the container specification.
Deployment resource file, as follows:
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-name
labels:
app: deployment-name
spec:
replicas: 1
selector:
matchLabels:
app: deployment-name
template:
metadata:
labels:
app: deployment-name
spec:
containers:
- name: container-name
image: your-image
env:
- name: SPRING_PROFILES_ACTIVE
value: "development"
You should check the security configuration section. To access config
maps from inside a pod you need to have the correct Kubernetes service
accounts, roles and role bindings.
Another option for using ConfigMap
instances is to mount them into the
Pod by running the Spring Cloud Kubernetes application and having Spring
Cloud Kubernetes read them from the file system. This behavior is
controlled by the spring.cloud.kubernetes.config.paths
property. You
can use it in addition to or instead of the mechanism described earlier.
You can specify multiple (exact) file paths in
spring.cloud.kubernetes.config.paths
by using the ,
delimiter.
You have to provide the full exact path to each property file, because
directories are not being recursively parsed.
Properties:
[options="header,footer"], ===, Name, Type, Default, Description,
spring.cloud.kubernetes.config.enabled
, Boolean
, true
, Enable
ConfigMaps PropertySource
, spring.cloud.kubernetes.config.name
,
String
, ${spring.application.name}
, Sets the name of ConfigMap
to
look up, spring.cloud.kubernetes.config.namespace
, String
, Client
namespace, Sets the Kubernetes namespace where to lookup,
spring.cloud.kubernetes.config.paths
, List
, null
, Sets the paths
where ConfigMap
instances are mounted,
spring.cloud.kubernetes.config.enableApi
, Boolean
, true
, Enable or
disable consuming ConfigMap
instances through APIs, ===
Secrets PropertySource
Kubernetes has the notion of
Secrets for
storing sensitive data such as passwords, OAuth tokens, and so on. This
project provides integration with Secrets
to make secrets accessible
by Spring Boot applications. You can explicitly enable or disable This
feature by setting the spring.cloud.kubernetes.secrets.enabled
property.
When enabled, the SecretsPropertySource
looks up Kubernetes for
Secrets
from the following sources:
-
Reading recursively from secrets mounts
-
Named after the application (as defined by
spring.application.name
)
-
Matching some labels
Note:
By default, consuming Secrets through the API (points 2 and 3 above)
is not enabled for security reasons. The permission 'list' on
secrets allows clients to inspect secrets values in the specified
namespace. Further, we recommend that containers share secrets through
mounted volumes.
If you enable consuming Secrets through the API, we recommend that you
limit access to Secrets by using an authorization policy, such as RBAC.
For more information about risks and best practices when consuming
Secrets through the API refer to this
doc.
If the secrets are found, their data is made available to the
application.
Assume that we have a spring boot application named demo
that uses
properties to read its database configuration. We can create a
Kubernetes secret by using the following command:
kubectl create secret generic db-secret --from-literal=username=user --from-literal=password=p455w0rd
The preceding command would create the following secret (which you can
see by using kubectl get secrets db-secret -o yaml
):
apiVersion: v1
data:
password: cDQ1NXcwcmQ=
username: dXNlcg==
kind: Secret
metadata:
creationTimestamp: 2017-07-04T09:15:57Z
name: db-secret
namespace: default
resourceVersion: "357496"
selfLink: /api/v1/namespaces/default/secrets/db-secret
uid: 63c89263-6099-11e7-b3da-76d6186905a8
type: Opaque
Note that the data contains Base64-encoded versions of the literal
provided by the create
command.
Your application can then use this secret — for example, by exporting
the secret’s value as environment variables:
apiVersion: v1
kind: Deployment
metadata:
name: ${project.artifactId}
spec:
template:
spec:
containers:
- env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-secret
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
You can select the Secrets to consume in a number of ways:
-
By listing the directories where secrets are mapped:
-Dspring.cloud.kubernetes.secrets.paths=/etc/secrets/db-secret,etc/secrets/postgresql
If you have all the secrets mapped to a common root, you can set
them like:
-Dspring.cloud.kubernetes.secrets.paths=/etc/secrets
-
By setting a named secret:
-Dspring.cloud.kubernetes.secrets.name=db-secret
-
By defining a list of labels:
-Dspring.cloud.kubernetes.secrets.labels.broker=activemq
-Dspring.cloud.kubernetes.secrets.labels.db=postgresql
As the case with ConfigMap
, more advanced configuration is also
possible where you can use multiple Secret
instances. The
spring.cloud.kubernetes.secrets.sources
list makes this possible. For
example, you could define the following Secret
instances:
spring:
application:
name: cloud-k8s-app
cloud:
kubernetes:
secrets:
name: default-name
namespace: default-namespace
sources:
# Spring Cloud Kubernetes looks up a Secret named s1 in namespace default-namespace
- name: s1
# Spring Cloud Kubernetes looks up a Secret named default-name in whatever namespace n2
- namespace: n2
# Spring Cloud Kubernetes looks up a Secret named s3 in namespace n3
- namespace: n3
name: s3
In the preceding example, if spring.cloud.kubernetes.secrets.namespace
had not been set, the Secret
named s1
would be looked up in the
namespace that the application runs.
Properties:
[options="header,footer"], ===, Name, Type, Default, Description,
spring.cloud.kubernetes.secrets.enabled
, Boolean
, true
, Enable
Secrets PropertySource
, spring.cloud.kubernetes.secrets.name
,
String
, ${spring.application.name}
, Sets the name of the secret to
look up, spring.cloud.kubernetes.secrets.namespace
, String
, Client
namespace, Sets the Kubernetes namespace where to look up,
spring.cloud.kubernetes.secrets.labels
, Map
, null
, Sets the labels
used to lookup secrets, spring.cloud.kubernetes.secrets.paths
, List
,
null
, Sets the paths where secrets are mounted (example 1),
spring.cloud.kubernetes.secrets.enableApi
, Boolean
, false
, Enables
or disables consuming secrets through APIs (examples 2 and 3), ===
Notes:
-
The spring.cloud.kubernetes.secrets.labels
property behaves as
defined by Map-based
binding.
-
The spring.cloud.kubernetes.secrets.paths
property behaves as
defined by Collection-based
binding.
-
Access to secrets through the API may be restricted for security
reasons. The preferred way is to mount secrets to the Pod.
You can find an example of an application that uses secrets (though it
has not been updated to use the new spring-cloud-kubernetes
project)
at
spring-boot-camel-config
PropertySource
Reload
Some applications may need to detect changes on external property
sources and update their internal status to reflect the new
configuration. The reload feature of Spring Cloud Kubernetes is able to
trigger an application reload when a related ConfigMap
or Secret
changes.
By default, this feature is disabled. You can enable it by using the
spring.cloud.kubernetes.reload.enabled=true
configuration property
(for example, in the application.properties
file).
The following levels of reload are supported (by setting the
spring.cloud.kubernetes.reload.strategy
property): * refresh
(default): Only configuration beans annotated with
@ConfigurationProperties
or @RefreshScope
are reloaded. This reload
level leverages the refresh feature of Spring Cloud Context. *
restart_context
: the whole Spring ApplicationContext
is gracefully
restarted. Beans are recreated with the new configuration. *
shutdown
: the Spring ApplicationContext
is shut down to activate a
restart of the container. When you use this level, make sure that the
lifecycle of all non-daemon threads is bound to the ApplicationContext
and that a replication controller or replica set is configured to
restart the pod.
Assuming that the reload feature is enabled with default settings
(refresh
mode), the following bean is refreshed when the config map
changes:
@Configuration
@ConfigurationProperties(prefix = "bean")
public class MyConfig {
private String message = "a message that can be changed live";
// getter and setters
}
To see that changes effectively happen, you can create another bean that
prints the message periodically, as follows
@Component
public class MyBean {
@Autowired
private MyConfig config;
@Scheduled(fixedDelay = 5000)
public void hello() {
System.out.println("The message is: " + config.getMessage());
}
}
You can change the message printed by the application by using a
ConfigMap
, as follows:
apiVersion: v1
kind: ConfigMap
metadata:
name: reload-example
data:
application.properties:, -
bean.message=Hello World!
Any change to the property named bean.message
in the ConfigMap
associated with the pod is reflected in the output. More generally
speaking, changes associated to properties prefixed with the value
defined by the prefix
field of the @ConfigurationProperties
annotation are detected and reflected in the application. Associating a
ConfigMap
with a pod is explained earlier
in this chapter.
The full example is available in
spring-cloud-kubernetes-reload-example
.
The reload feature supports two operating modes: * Event (default):
Watches for changes in config maps or secrets by using the Kubernetes
API (web socket). Any event produces a re-check on the configuration
and, in case of changes, a reload. The view
role on the service
account is required in order to listen for config map changes. A higher
level role (such as edit
) is required for secrets (by default, secrets
are not monitored). * Polling: Periodically re-creates the
configuration from config maps and secrets to see if it has changed. You
can configure the polling period by using the
spring.cloud.kubernetes.reload.period
property and defaults to 15
seconds. It requires the same role as the monitored property source.
This means, for example, that using polling on file-mounted secret
sources does not require particular privileges.
Properties:
[options="header,footer"], ===, Name, Type, Default, Description,
spring.cloud.kubernetes.reload.enabled
, Boolean
, false
, Enables
monitoring of property sources and configuration reload,
spring.cloud.kubernetes.reload.monitoring-config-maps
, Boolean
,
true
, Allow monitoring changes in config maps,
spring.cloud.kubernetes.reload.monitoring-secrets
, Boolean
, false
,
Allow monitoring changes in secrets,
spring.cloud.kubernetes.reload.strategy
, Enum
, refresh
, The
strategy to use when firing a reload (refresh
, restart_context
, or
shutdown
), spring.cloud.kubernetes.reload.mode
, Enum
, event
,
Specifies how to listen for changes in property sources (event
or
polling
), spring.cloud.kubernetes.reload.period
, Duration
, 15s
,
The period for verifying changes when using the polling
strategy, ===
Notes: * You should not use properties under
spring.cloud.kubernetes.reload
in config maps or secrets. Changing
such properties at runtime may lead to unexpected results. * Deleting a
property or the whole config map does not restore the original state of
the beans when you use the refresh
level.
Ribbon Discovery in Kubernetes
Spring Cloud client applications that call a microservice should be
interested on relying on a client load-balancing feature in order to
automatically discover at which endpoint(s) it can reach a given
service. This mechanism has been implemented within the
spring-cloud-kubernetes-ribbon
project, where a Kubernetes client populates a
Ribbon ServerList
that contains
information about such endpoints.
The implementation is part of the following starter that you can use by
adding its dependency to your pom file:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-ribbon</artifactId>
<version>${latest.version}</version>
</dependency>
When the list of the endpoints is populated, the Kubernetes client
searches the registered endpoints that live in the current namespace or
project by matching the service name defined in the Ribbon Client
annotation, as follows:
@RibbonClient(name = "name-service")
You can configure Ribbon’s behavior by providing properties in your
application.properties
(through your application’s dedicated
ConfigMap
) by using the following format:
<name of your service>.ribbon.<Ribbon configuration key>
, where:
-
<name of your service>
corresponds to the service name you access
over Ribbon, as configured by using the @RibbonClient
annotation
(such as name-service
in the preceding example).
-
<Ribbon configuration key>
is one of the Ribbon configuration keys
defined by Ribbon’s CommonClientConfigKey
class.
Additionally, the spring-cloud-kubernetes-ribbon
project defines two
additional configuration keys to further control how Ribbon interacts
with Kubernetes. In particular, if an endpoint defines multiple ports,
the default behavior is to use the first one found. To select more
specifically which port to use in a multi-port service, you can use the
PortName
key. If you want to specify in which Kubernetes namespace the
target service should be looked up, you can use the
KubernetesNamespace
key, remembering in both instances to prefix these
keys with your service name and ribbon
prefix, as specified earlier.
The following examples use this module for ribbon discovery:
You can disable the Ribbon discovery client by setting the
spring.cloud.kubernetes.ribbon.enabled=false
key within the
application properties file.
Kubernetes Ecosystem Awareness
All of the features described earlier in this guide work equally well,
regardless of whether your application is running inside Kubernetes.
This is really helpful for development and troubleshooting. From a
development point of view, this lets you start your Spring Boot
application and debug one of the modules that is part of this project.
You need not deploy it in Kubernetes, as the code of the project relies
on the Fabric8 Kubernetes Java
client, which is a
fluent DSL that can communicate by using http
protocol to the REST API
of the Kubernetes Server.
To disable the integration with Kubernetes you can set
spring.cloud.kubernetes.enabled
to false
. Please be aware that when
spring-cloud-kubernetes-config
is on the classpath,
spring.cloud.kubernetes.enabled
should be set in
bootstrap.{properties, yml}
(or the profile specific one) otherwise it
should be in application.{properties, yml}
(or the profile specific
one). Also note that these properties:
spring.cloud.kubernetes.config.enabled
and
spring.cloud.kubernetes.secrets.enabled
only take effect when set in
bootstrap.{properties, yml}
Kubernetes Profile Autoconfiguration
When the application runs as a pod inside Kubernetes, a Spring profile
named kubernetes
automatically gets activated. This lets you customize
the configuration, to define beans that are applied when the Spring Boot
application is deployed within the Kubernetes platform (for example,
different development and production configuration).
Istio Awareness
When you include the spring-cloud-kubernetes-istio
module in the
application classpath, a new profile is added to the application,
provided the application is running inside a Kubernetes Cluster with
Istio installed. You can then use spring
@Profile("istio")
annotations in your Beans and @Configuration
classes.
The Istio awareness module uses me.snowdrop:istio-client
to interact
with Istio APIs, letting us discover traffic rules, circuit breakers,
and so on, making it easy for our Spring Boot applications to consume
this data to dynamically configure themselves according to the
environment.
Pod Health Indicator
Spring Boot uses
HealthIndicator
to expose info about the health of an application. That makes it really
useful for exposing health-related information to the user and makes it
a good fit for use as readiness
probes.
The Kubernetes health indicator (which is part of the core module)
exposes the following info:
-
Pod name, IP address, namespace, service account, node name, and its
IP address
-
A flag that indicates whether the Spring Boot application is
internal or external to Kubernetes
Leader Election
<TBD>
Security Configurations Inside Kubernetes
Namespace
Most of the components provided in this project need to know the
namespace. For Kubernetes (1.3+), the namespace is made available to the
pod as part of the service account secret and is automatically detected
by the client. For earlier versions, it needs to be specified as an
environment variable to the pod. A quick way to do this is as follows:
env:
- name: "KUBERNETES_NAMESPACE"
valueFrom:
fieldRef:
fieldPath: "metadata.namespace"
Service Account
For distributions of Kubernetes that support more fine-grained
role-based access within the cluster, you need to make sure a pod that
runs with spring-cloud-kubernetes
has access to the Kubernetes API.
For any service accounts you assign to a deployment or pod, you need to
make sure they have the correct roles.
Depending on the requirements, you’ll need get
, list
and watch
permission on the following resources:
Kubernetes Resource Permissions, ===, Dependency, Resources,
spring-cloud-starter-kubernetes, pods, services, endpoints,
spring-cloud-starter-kubernetes-config, configmaps, secrets,
spring-cloud-starter-kubernetes-ribbon, pods, services, endpoints, ===
For development purposes, you can add cluster-reader
permissions to
your default
service account. On a production system you’ll likely
want to provide more granular permissions.
The following Role and RoleBinding are an example for namespaced
permissions for the default
account:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: YOUR-NAME-SPACE
name: namespace-reader
rules:
- apiGroups: ["", "extensions", "apps"]
resources: ["configmaps", "pods", "services", "endpoints", "secrets"]
verbs: ["get", "list", "watch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: namespace-reader-binding
namespace: YOUR-NAME-SPACE
subjects:
- kind: ServiceAccount
name: default
apiGroup: ""
roleRef:
kind: Role
name: namespace-reader
apiGroup: ""
Service Registry Implementation
In Kubernetes service registration is controlled by the platform, the
application itself does not control registration as it may do in other
platforms. For this reason using
spring.cloud.service-registry.auto-registration.enabled
or setting
@EnableDiscoveryClient(autoRegister=false)
will have no effect in
Spring Cloud Kubernetes.
Examples
Spring Cloud Kubernetes tries to make it transparent for your
applications to consume Kubernetes Native Services by following the
Spring Cloud interfaces.
In your applications, you need to add the
spring-cloud-kubernetes-discovery
dependency to your classpath and
remove any other dependency that contains a DiscoveryClient
implementation (that is, a Eureka discovery client). The same applies
for PropertySourceLocator
, where you need to add to the classpath the
spring-cloud-kubernetes-config
and remove any other dependency that
contains a PropertySourceLocator
implementation (that is, a
configuration server client).
The following projects highlight the usage of these dependencies and
demonstrate how you can use these libraries from any Spring Boot
application:
Other Resources
This section lists other resources, such as presentations (slides) and
videos about Spring Cloud Kubernetes.
Please feel free to submit other resources through pull requests to
this
repository.
Configuration properties
To see the list of all Sleuth related configuration properties please
check the Appendix page.
Building
Basic Compile and Test
To build the source you will need to install JDK 1.7.
Spring Cloud uses Maven for most build-related activities, and you
should be able to get off the ground quite quickly by cloning the
project you are interested in and typing
$ ./mvnw install
You can also install Maven (>=3.3.3) yourself and run the mvn
command in place of ./mvnw
in the examples below. If you do that you
also might need to add -P spring
if your local Maven settings do not
contain repository declarations for spring pre-release artifacts.
Be aware that you might need to increase the amount of memory available
to Maven by setting a MAVEN_OPTS
environment variable with a value
like -Xmx512m -XX:MaxPermSize=128m
. We try to cover this in the .mvn
configuration, so if you find you have to do it to make a build succeed,
please raise a ticket to get the settings added to source control.
For hints on how to build the project look in .travis.yml
if there is
one. There should be a "script" and maybe "install" command. Also look
at the "services" section to see if any services need to be running
locally (e.g. mongo or rabbit). Ignore the git-related bits that you
might find in "before_install" since they’re related to setting git
credentials and you already have those.
The projects that require middleware generally include a
docker-compose.yml
, so consider using Docker
Compose to run the middeware servers
in Docker containers. See the README in the scripts demo
repository for
specific instructions about the common cases of mongo, rabbit and redis.
If all else fails, build with the command from .travis.yml
(usually
./mvnw install
).
Documentation
The spring-cloud-build module has a "docs" profile, and if you switch
that on it will try to build asciidoc sources from src/main/asciidoc
.
As part of that process it will look for a README.adoc
and process it
by loading all the includes, but not parsing or rendering it, just
copying it to ${main.basedir}
(defaults to ${basedir}
, i.e. the root
of the project). If there are any changes in the README it will then
show up after a Maven build as a modified file in the correct place.
Just commit it and push the change.
Working with the code
If you don’t have an IDE preference we would recommend that you use
Spring Tools Suite or
Eclipse when working with the code. We use the
m2eclipse eclipse plugin for maven support.
Other IDEs and tools should also work without issue as long as they use
Maven 3.3.3 or better.
Importing into eclipse with m2eclipse
We recommend the m2eclipse eclipse plugin
when working with eclipse. If you don’t already have m2eclipse installed
it is available from the "eclipse marketplace".
Older versions of m2e do not support Maven 3.3, so once the projects are
imported into Eclipse you will also need to tell m2eclipse to use the
right profile for the projects. If you see many different errors related
to the POMs in the projects, check that you have an up to date
installation. If you can’t upgrade m2e, add the "spring" profile to your
settings.xml
. Alternatively you can copy the repository settings from
the "spring" profile of the parent pom into your settings.xml
.
Importing into eclipse without m2eclipse
If you prefer not to use m2eclipse you can generate eclipse project
metadata using the following command:
$ ./mvnw eclipse:eclipse
The generated eclipse projects can be imported by selecting
import existing projects
from the file
menu.
Contributing
Spring Cloud is released under the non-restrictive Apache 2.0 license,
and follows a very standard Github development process, using Github
tracker for issues and merging pull requests into master. If you want to
contribute even something trivial please do not hesitate, but follow the
guidelines below.
Sign the Contributor License Agreement
Before we accept a non-trivial patch or pull request we will need you to
sign the Contributor License
Agreement. Signing the
contributor’s agreement does not grant anyone commit rights to the main
repository, but it does mean that we can accept your contributions, and
you will get an author credit if we do. Active contributors might be
asked to join the core team, and given the ability to merge pull
requests.
Code of Conduct
This project adheres to the Contributor Covenant code of
conduct.
By participating, you are expected to uphold this code. Please report
unacceptable behavior to spring-code-of-conduct@pivotal.io.
Code Conventions and Housekeeping
None of these is essential for a pull request, but they will all help.
They can also be added after the original pull request but before a
merge.
-
Use the Spring Framework code format conventions. If you use Eclipse
you can import formatter settings using the
eclipse-code-formatter.xml
file from the Spring Cloud
Build
project. If using IntelliJ, you can use the Eclipse Code Formatter
Plugin to import the
same file.
-
Make sure all new .java
files to have a simple Javadoc class
comment with at least an @author
tag identifying you, and
preferably at least a paragraph on what the class is for.
-
Add the ASF license header comment to all new .java
files (copy
from existing files in the project)
-
Add yourself as an @author
to the .java files that you modify
substantially (more than cosmetic changes).
-
Add some Javadocs and, if you change the namespace, some XSD doc
elements.
-
A few unit tests would help a lot as well — someone has to do it.
-
If no-one else is using your branch, please rebase it against the
current master (or other target branch in the main project).
-
When writing a commit message please follow these
conventions,
if you are fixing an existing issue please add Fixes gh-XXXX
at
the end of the commit message (where XXXX is the issue number).
Checkstyle
Spring Cloud Build comes with a set of checkstyle rules. You can find
them in the spring-cloud-build-tools
module. The most notable files
under the module are:
spring-cloud-build-tools/
└── src
├── checkstyle
│ └── checkstyle-suppressions.xml
└── main
└── resources
├── checkstyle-header.txt
└── checkstyle.xml
Checkstyle configuration
Checkstyle rules are disabled by default. To add checkstyle to your
project just define the following properties and plugins.
pom.xml
<properties>
<maven-checkstyle-plugin.failsOnError>true</maven-checkstyle-plugin.failsOnError>
<maven-checkstyle-plugin.failsOnViolation>true
</maven-checkstyle-plugin.failsOnViolation>
<maven-checkstyle-plugin.includeTestSourceDirectory>true
</maven-checkstyle-plugin.includeTestSourceDirectory>
</properties>
<build>
<plugins>
<plugin>
<groupId>io.spring.javaformat</groupId>
<artifactId>spring-javaformat-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
</plugin>
</plugins>
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
</plugin>
</plugins>
</reporting>
</build>
-
Fails the build upon Checkstyle errors
-
Fails the build upon Checkstyle violations
-
Checkstyle analyzes also the test sources
-
Add the Spring Java Format plugin that will reformat your code to
pass most of the Checkstyle formatting rules
-
Add checkstyle plugin to your build and reporting phases
If you need to suppress some rules (e.g. line length needs to be
longer), then it’s enough for you to define a file under
${project.root}/src/checkstyle/checkstyle-suppressions.xml
with your
suppressions. Example:
projectRoot/src/checkstyle/checkstyle-suppresions.xml
<?xml version="1.0"?>
<!DOCTYPE suppressions PUBLIC
"-//Puppy Crawl//DTD Suppressions 1.1//EN"
"https://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
<suppressions>
<suppress files=".*ConfigServerApplication\.java" checks="HideUtilityClassConstructor"/>
<suppress files=".*ConfigClientWatch\.java" checks="LineLengthCheck"/>
</suppressions>
It’s advisable to copy the
${spring-cloud-build.rootFolder}/.editorconfig
and
${spring-cloud-build.rootFolder}/.springformat
to your project. That
way, some default formatting rules will be applied. You can do so by
running this script:
$ curl https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/.editorconfig -o .editorconfig
$ touch .springformat
IDE setup
Intellij IDEA
In order to setup Intellij you should import our coding conventions,
inspection profiles and set up the checkstyle plugin. The following
files can be found in the Spring Cloud
Build
project.
spring-cloud-build-tools/
└── src
├── checkstyle
│ └── checkstyle-suppressions.xml
└── main
└── resources
├── checkstyle-header.txt
├── checkstyle.xml
└── intellij
├── Intellij_Project_Defaults.xml
└── Intellij_Spring_Boot_Java_Conventions.xml
-
Default Checkstyle rules
-
File header setup
-
Default suppression rules
-
Project defaults for Intellij that apply most of Checkstyle rules
-
Project style conventions for Intellij that apply most of Checkstyle
rules

Go to File
→ Settings
→ Editor
→ Code style
. There click on the
icon next to the Scheme
section. There, click on the Import Scheme
value and pick the Intellij IDEA code style XML
option. Import the
spring-cloud-build-tools/src/main/resources/intellij/Intellij_Spring_Boot_Java_Conventions.xml
file.

Go to File
→ Settings
→ Editor
→ Inspections
. There click on the
icon next to the Profile
section. There, click on the Import Profile
and import the
spring-cloud-build-tools/src/main/resources/intellij/Intellij_Project_Defaults.xml
file.
Checkstyle
To have Intellij work with Checkstyle, you have to install the
Checkstyle
plugin. It’s advisable to also install the
Assertions2Assertj
to automatically convert the JUnit assertions

Go to File
→ Settings
→ Other settings
→ Checkstyle
. There click
on the +
icon in the Configuration file
section. There, you’ll have
to define where the checkstyle rules should be picked from. In the image
above, we’ve picked the rules from the cloned Spring Cloud Build
repository. However, you can point to the Spring Cloud Build’s GitHub
repository (e.g. for the checkstyle.xml
:
raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-build-tools/src/main/resources/checkstyle.xml
).
We need to provide the following variables:
-
checkstyle.header.file
- please point it to the Spring Cloud
Build’s,
spring-cloud-build-tools/src/main/resources/checkstyle-header.txt
file either in your cloned repo or via the
raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-build-tools/src/main/resources/checkstyle-header.txt
URL.
-
checkstyle.suppressions.file
- default suppressions. Please point
it to the Spring Cloud Build’s,
spring-cloud-build-tools/src/checkstyle/checkstyle-suppressions.xml
file either in your cloned repo or via the
raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-build-tools/src/checkstyle/checkstyle-suppressions.xml
URL.
-
checkstyle.additional.suppressions.file
- this variable
corresponds to suppressions in your local project. E.g. you’re
working on spring-cloud-contract
. Then point to the
project-root/src/checkstyle/checkstyle-suppressions.xml
folder.
Example for spring-cloud-contract
would be:
/home/username/spring-cloud-contract/src/checkstyle/checkstyle-suppressions.xml
.
Remember to set the Scan Scope
to All sources
since we apply
checkstyle rules for production and test sources.