3. Cloud environment
Applications often need environment specific configuration information, especially in changing environments like in the Amazon cloud environment. Spring Cloud AWS provides a support to retrieve and use environment specific data inside the application context using common Spring mechanisms like property placeholder or the Spring expression language.
3.1. Retrieving instance metadata
Instance metadata are available inside an EC2 environment. The metadata can be queried using a special HTTP address that provides the instance metadata. Spring Cloud AWS enables application to access this metadata directly in expression or property placeholder without the need to call an external HTTP service.
3.1.1. Enabling instance metadata support with XML
The instance metadata retrieval support is enabled through an XML element like the standard property placeholder in Spring. The following code sample demonstrates the activation of the instance metadata support inside an application context.
<beans ...>
<aws-context:context-instance-data />
</beans>
Instance metadata can be retrieved without an authorized service call, therefore the configuration above does not require any region or security specific configuration. |
3.1.2. Enabling instance metadata support with Java
The instance metadata can also be configured within a Java configuration class without the need for an XML configuration.
The next example shows a typical Spring @Configuration
class that enables the instance metadata with the
org.springframework.cloud.aws.context.config.annotation.EnableInstanceData
@Configuration
@EnableContextInstanceData
public static class ApplicationConfiguration {
}
3.1.3. Enabling instance metadata support in Spring Boot
The instance metadata is automatically available in a Spring Boot application as a property source if the application is running on an EC2 instance.
3.1.4. Using instance metadata
Instance metadata can be used in XML, Java placeholders and expressions. The example below demonstrates the usage of
instance metadata inside an XML file using placeholders and also the expression referring to the special variable environment
<beans ...>
<bean class="org.springframework.cloud.aws....SimpleConfigurationBean">
<property name="value1" value="#{environment.ami-id}" />
<property name="value2" value="#{environment.hostname}" />
<property name="value3" value="${instance-type}" />
<property name="value4" value="${instance-id}" />
</bean>
</beans>
Instance metadata can also be injected with the Spring org.springframework.beans.factory.annotation.Value
annotation
directly into Java fields. The next example demonstrates the use of instance metadata inside a Spring bean.
@Component
public class ApplicationInfoBean {
@Value("${ami-id:N/A}")
private String amiId;
@Value("${hostname:N/A}")
private String hostname;
@Value("${instance-type:N/A}")
private String instanceType;
@Value("${services/domain:N/A}")
private String serviceDomain;
}
Every instance metadata can be accessed by the key available in the instance metadata service Nested properties can be accessed by separating the properties with a slash ('/'). |
3.1.5. Using instance user data
Besides the default instance metadata it is also possible to configure user data on each instance. This user data is retrieved and
parsed by Spring Cloud AWS. The user data can be defined while starting an EC2 instance with the application. Spring Cloud AWS
expects the format <key>:<value>;<key>:<value>
inside the user data so that it can parse the string and extract the key value pairs.
The user data can be configured using either the management console shown below or a CloudFormation template.
A CloudFormation template snippet for the configuration of the user data is outlined below:
...
"Resources": {
"ApplicationServerInstance": {
"Type": "AWS::EC2::Instance",
"Properties": {
"ImageId": "ami-6a56b81d",
"UserData": {
"Fn::Base64": "data1:value1;data2:value2"
},
"InstanceType": "t1.micro",
}
}
...
The user data can be accessed directly in the application context like the instance metadata through placeholders or expressions.
@Component
public class SecondConfigurationBean {
@Value("${data1}")
private String firstDataOption;
@Value("${data2}")
private String secondDataOption;
}
3.1.6. Using instance tags
User configured properties can also be configured with tags instead of user data. Tags are a global concept in the context of Amazon Web services and used in different services. Spring Cloud AWS supports instance tags also across different services. Compared to user data, user tags can be updated during runtime, there is no need to stop and restart the instance.
User data can also be used to execute scripts on instance startup. Therefore it is useful to leverage instance tags for user configuration and user data to execute scripts on instance startup. |
Instance specific tags can be configured on the instance level through the management console outlined below and like user data also with a CloudFormation template shown afterwards.
A CloudFormation template snippet for the configuration of the instance tags is outlined below:
...
"Resources": {
"UserTagAndUserDataInstance": {
"Type": "AWS::EC2::Instance",
"Properties": {
"ImageId": "ami-6a56b81d",
"InstanceType": "t1.micro",
"Tags": [
{
"Key": "tag1",
"Value": "tagv1"
},
{
"Key": "tag3",
"Value": "tagv3"
},
{
"Key": "tag2",
"Value": "tagv2"
},
{
"Key": "tag4",
"Value": "tagv4"
}
]
}
}
}
...
To retrieve the instance tags, Spring Cloud AWS has to make authenticated requests and therefore it will need the region
and security configuration before actually resolving the placeholders. Also because the instance tags are not available while starting
the application context, they can only be referenced as expressions and not with placeholders. The context-instance-data
element defines an attribute user-tags-map
that will create a map in the application context for the name. This map
can then be queried using expression for other bean definitions.
<beans ...>
<aws-context:context-instance-data user-tags-map="instanceData" />
</beans>
A java bean might resolve expressions with the @Value
annotation.
public class SimpleConfigurationBean {
@Value("#{instanceData.tag1}")
private String value1;
@Value("#{instanceData.tag2}")
private String value2;
@Value("#{instanceData.tag3}")
private String value3;
@Value("#{instanceData.tag4}")
private String value4;
}
3.1.7. Configuring custom EC2 client
In some circumstances it is necessary to have a custom EC2 client to retrieve the instance information. The
context-instance-data
element supports a custom EC2 client with the amazon-ec2
attribute. The next
example shows the use of a custom EC2 client that might have a special configuration in place.
<beans ...>
<aws-context:context-credentials>....</aws-context:context-credentials>
<aws-context:context-region ... />
<aws-context:context-instance-data amazon-ec2="myCustomClient"/>
<bean id="myCustomClient" class="com.amazonaws.services.ec2.AmazonEC2Client">
...
</bean>
</beans>
3.1.8. Injecting the default EC2 client
If there are user tags configured for the instance data (see above) Spring Cloud AWS configures an EC2 client with
the specified region and security credentials. Application developers can inject the EC2 client directly into their code using the @Autowired
annotation.
public class ApplicationService {
private final AmazonEC2 amazonEc2;
@Autowired
public ApplicationService(AmazonEC2 amazonEc2) {
this.amazonEc2 = amazonEc2;
}
}
3.2. Integrating your Spring Cloud application with the AWS Parameter Store
Spring Cloud provides support for centralized configuration, which can be read and made available as a regular Spring
PropertySource
when the application is started. The Parameter Store Configuration allows you to use this mechanism
with the AWS Parameter Store.
Simply add a dependency on the spring-cloud-starter-aws-parameter-store-config
starter module to activate the support.
The support is similar to the support provided for the Spring Cloud Config Server or Consul’s key-value store:
configuration parameters can be defined to be shared across all services or for a specific service and can be
profile-specific. Encrypted values will be decrypted when retrieved.
All configuration parameters are retrieved from a common path prefix, which defaults to /config
. From there shared
parameters are retrieved from a path that defaults to application
and service-specific parameters use a path that
defaults to the configured spring.application.name
. You can use both dots and forward slashes to specify the names
of configuration keys. Names of activated profiles will be appended to the path using a separator that defaults to an
underscore.
That means that for a service called my-service
the module by default would find and use these parameters:
parameter key | Spring property | description |
---|---|---|
|
|
Shared by all services that have the Configuration support enabled. Can be overridden with a service- or profile-specific property. |
|
|
Shared by all services that have the Configuration support enabled and have a |
|
|
Specific to the |
|
|
Specific to the |
Note that this module does not support full configuration files to be used as parameter values like e.g. Spring Cloud Consul does: AWS parameter values are limited to 4096 characters, so we support individual Spring properties to be configured only.
You can configure the following settings in a Spring Cloud bootstrap.properties
or bootstrap.yml
file
(note that relaxed property binding is applied, so you don’t have to use this exact syntax):
property | default | explanation |
---|---|---|
|
|
Prefix indicating first level for every property loaded from the Parameter Store. Value must start with a forward slash followed by one or more valid path segments or be empty. |
|
|
Name of the context that defines properties shared across all services |
|
|
String that separates an appended profile from the context name. Can only contain dots, dashes, forward slashes, backward slashes and underscores next to alphanumeric characters. |
|
|
Indicates if an error while retrieving the parameters should fail starting the application. |
|
the configured value for |
Name to use when constructing the path for the properties to look up for this specific service. |
|
|
Can be used to disable the Parameter Store Configuration support even though the auto-configuration is on the classpath. |
In order to find out which properties are retrieved from AWS Parameter Store on application startup,
turn on
|
3.3. Integrating your Spring Cloud application with the AWS Secrets Manager
Spring Cloud provides support for centralized configuration, which can be read and made available as a regular Spring
PropertySource
when the application is started. The Secrets Manager Configuration allows you to use this mechanism
with the AWS Secrets Manager.
Simply add a dependency on the spring-cloud-starter-aws-secrets-manager-config
starter module to activate the support.
The support is similar to the support provided for the Spring Cloud Config Server or Consul’s key-value store:
configuration parameters can be defined to be shared across all services or for a specific service and can be
profile-specific.
All configuration parameters are retrieved from a common path prefix, which defaults to /secret
. From there shared
parameters are retrieved from a path that defaults to application
and service-specific parameters use a path that
defaults to the configured spring.application.name
. You can use both dots and forward slashes to specify the names
of configuration keys. Names of activated profiles will be appended to the path using a separator that defaults to an
underscore.
That means that for a service called my-service
the module by default would find and use these parameters:
parameter key | description |
---|---|
|
Shared by all services that have the Configuration support enabled. Can be overridden with a service- or profile-specific property. |
|
Shared by all services that have the Configuration support enabled and have a |
|
Specific to the |
|
Specific to the |
You can configure the following settings in a Spring Cloud bootstrap.properties
or bootstrap.yml
file
(note that relaxed property binding is applied, so you don’t have to use this exact syntax):
property | default | explanation |
---|---|---|
|
|
Prefix indicating first level for every property loaded from the Secrets Manager. Value must start with a forward slash followed by one or more valid path segments or be empty. |
|
|
Name of the context that defines properties shared across all services |
|
|
String that separates an appended profile from the context name. Can only contain dots, dashes, forward slashes, backward slashes and underscores next to alphanumeric characters. |
|
|
Indicates if an error while retrieving the secrets should fail starting the application. |
|
the configured value for |
Name to use when constructing the path for the properties to look up for this specific service. |
|
|
Can be used to disable the Secrets Manager Configuration support even though the auto-configuration is on the classpath. |