Deploy a "hello world" application
Creating a template application with Spring Initializr
Create a Spring Boot template application with Spring Initializr and deploy it immediately with cf push
.
Create a handson
directory as a working place.
mkdir handson
cd handson
Create a template application with the following command.
curl https://start.spring.io/starter.tgz \
-d artifactId=hello-cf \
-d baseDir=hello-cf \
-d type=maven-project \
-d dependencies=web,actuator,configuration-processor,prometheus \
-d packageName=com.example \
-d applicationName=HelloCfApplication | tar -xzvf -
Build the application with the following command:
cd hello-cf
./mvnw clean package -Dmaven.test.skip=true
Deploy with cf push
Create manifest.yml
under the hello-cf
directory and describe the following contents.
applications:
- name: hello-cf
random-route: true
instances: 1
memory: 768m
path: target/hello-cf-0.0.1-SNAPSHOT.jar
buildpacks:
- java_buildpack_offline
env:
JBP_CONFIG_OPEN_JDK_JRE: '{jre: {version: 17.+}}'
Note: In Hands-on environment, multiple people deploy an application with the same name. By default, the Host part of the application's URL will be the same as the name, which causes a URL collision. To avoid this, add
random-route: true
and add a random character string to the Host part.
Redeploy the application with cf push
.
cf push
Access the app deployed with the following command.
# Get the Host part that contains a random string and set it in a variable
HOST=$(cf curl /v2/apps/$(cf app hello-cf --guid)/routes | jq -r ".resources[0].entity.host")
# Access Spring Boot Acutator Health Endpoint
curl -s https://${HOST}.apps.dhaka.cf-app.com/actuator/health -w '\n'
You'll see the below output
{"status":"UP"}
Expose Spring Boot Actuator endpoints
Spring Boot Actuator has many useful endpoints for operation. By default, only /actuator/health
is exposed. Let's expose the /actutor/info
, /actuator/env
and /actuator/prometheus
by setting the following environment variables in manifest.yml
:
applications:
- name: hello-cf
random-route: true
instances: 1
memory: 768m
path: target/hello-cf-0.0.1-SNAPSHOT.jar
buildpacks:
- java_buildpack_offline
env:
JBP_CONFIG_OPEN_JDK_JRE: '{jre: {version: 17.+}}'
# ⭐️⭐️⭐️
MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE: info,health,env,prometheus
MANAGEMENT_INFO_JAVA_ENABLED: true
MANAGEMENT_INFO_OS_ENABLED: true
Redeploy the application with cf push.
cf push
Access the info endpoint.
curl -s https://${HOST}.apps.dhaka.cf-app.com/actuator/info | jq .
{
"java": {
"version": "17.0.9",
"vendor": {
"name": "BellSoft"
},
"runtime": {
"name": "OpenJDK Runtime Environment",
"version": "17.0.9+11-LTS"
},
"jvm": {
"name": "OpenJDK 64-Bit Server VM",
"vendor": "BellSoft",
"version": "17.0.9+11-LTS"
}
},
"os": {
"name": "Linux",
"version": "6.5.0-15-generic",
"arch": "amd64"
}
}
Access the env endpoint.
curl -s https://${HOST}.apps.dhaka.cf-app.com/actuator/env | jq .
{
"activeProfiles": [
"cloud"
],
"propertySources": [
{
"name": "server.ports",
"properties": {
"local.server.port": {
"value": "******"
}
}
},
{
"name": "vcap",
"properties": {
"vcap.application.process_type": {
"value": "******"
},
"vcap.application.application_uris": {
"value": "******"
},
"vcap.application.space_name": {
"value": "******"
},
...
"HOME": {
"value": "******",
"origin": "System Environment Property \"HOME\""
},
"MALLOC_ARENA_MAX": {
"value": "******",
"origin": "System Environment Property \"MALLOC_ARENA_MAX\""
}
}
}
]
}
Note: The values inside the response of the env endpoint are masked by default.
curl -s https://${HOST}.apps.dhaka.cf-app.com/actuator/prometheus
Access the prometheus endpoint.
# HELP jvm_threads_live_threads The current number of live threads including both daemon and non-daemon threads
# TYPE jvm_threads_live_threads gauge
jvm_threads_live_threads 21.0
# HELP executor_active_threads The approximate number of threads that are actively executing tasks
# TYPE executor_active_threads gauge
executor_active_threads{name="applicationTaskExecutor",} 0.0
# HELP process_files_open_files The open file descriptor count
# TYPE process_files_open_files gauge
process_files_open_files 56.0
# HELP executor_completed_tasks_total The approximate total number of tasks that have completed execution
# TYPE executor_completed_tasks_total counter
executor_completed_tasks_total{name="applicationTaskExecutor",} 0.0
# HELP jvm_memory_used_bytes The amount of used memory
# TYPE jvm_memory_used_bytes gauge
jvm_memory_used_bytes{area="heap",id="Tenured Gen",} 1.6711832E7
jvm_memory_used_bytes{area="nonheap",id="CodeHeap 'profiled nmethods'",} 9542656.0
jvm_memory_used_bytes{area="heap",id="Eden Space",} 1.0675856E7
jvm_memory_used_bytes{area="nonheap",id="Metaspace",} 3.6345472E7
jvm_memory_used_bytes{area="nonheap",id="CodeHeap 'non-nmethods'",} 1265920.0
jvm_memory_used_bytes{area="heap",id="Survivor Space",} 1355856.0
jvm_memory_used_bytes{area="nonheap",id="Compressed Class Space",} 4847896.0
jvm_memory_used_bytes{area="nonheap",id="CodeHeap 'non-profiled nmethods'",} 2567424.0
# HELP disk_free_bytes Usable space for path
# TYPE disk_free_bytes gauge
disk_free_bytes{path="/home/vcap/app/.",} 8.8434688E8
# HELP jvm_threads_daemon_threads The current number of live daemon threads
# TYPE jvm_threads_daemon_threads gauge
jvm_threads_daemon_threads 17.0
...
Utilization of Info endpoint
The Info endpoint outputs properties or starting with info.
or INFO_
in JSON format. It is convenient to include the version of the running application.
applications:
- name: hello-cf
random-route: true
instances: 1
memory: 768m
path: target/hello-cf-0.0.1-SNAPSHOT.jar
buildpacks:
- java_buildpack_offline
env:
JBP_CONFIG_OPEN_JDK_JRE: '{jre: {version: 17.+}}'
MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE: info,health,env,prometheus
MANAGEMENT_INFO_JAVA_ENABLED: true
MANAGEMENT_INFO_OS_ENABLED: true
# ⭐️⭐️⭐️
MANAGEMENT_INFO_ENV_ENABLED: true
INFO_VERSION: 0.0.1
INFO_MESSAGE: Hello World!
Redeploy the application with cf push
.
cf push
Access the info endpoint.
curl -s https://${HOST}.apps.dhaka.cf-app.com/actuator/info | jq .
{
"message": "Hello World!",
"version": "0.0.1",
"java": {
"version": "17.0.9",
"vendor": {
"name": "BellSoft"
},
"runtime": {
"name": "OpenJDK Runtime Environment",
"version": "17.0.9+11-LTS"
},
"jvm": {
"name": "OpenJDK 64-Bit Server VM",
"vendor": "BellSoft",
"version": "17.0.9+11-LTS"
}
},
"os": {
"name": "Linux",
"version": "6.5.0-15-generic",
"arch": "amd64"
}
}
In the JSON of the response, you will see that it contains the keys message
and version
.