Skip to main content
Version: 3.0.0 (RC 2) 🚧

How odo works

How odo dev works​

In a nutshell, when running odo dev:

  1. odo reads and validates the Devfile in the current directory. For example, it makes sure a command of the right kind (run when running odo dev, or debug when running odo dev --debug) is defined.
  2. odo creates resources in the cluster and manages them. Specifically, it creates the following resources:
  3. Once the resources are ready, odo executes any build (optional) and run (or debug) commands defined in the Devfile into the dedicated containers. It then maintains a connection to the process launched inside the container, and representing the run or debug command defined.
  4. odo reacts to events occurring in the cluster that might affect the resources managed.
  5. odo watches for local changes and synchronizes changed files into the running container, unless told otherwise (when running odo dev --no-watch). If the local Devfile is modified, odo may need to change the resources it previously created, which might result in recreating the running containers. Note that synchronization and push to the cluster can also be triggered on demand by pressing p at any time. See the command reference on odo dev for more details.
  6. odo optionally restarts the running application if the command is not marked as hotReloadCapable in the Devfile. If the command is marked as hotReloadCapable, the application is supposed to handle source code changes on its own; so odo does not restart the application. Otherwise, odo restarts the running application by stopping the process started previously, then executes the command again in the container. Again, it maintains a connection to that process as long as it is running in the container.
  7. odo then sets up port-forwarding for each endpoint declared in the Devfile, and reports the local port in its output.
  8. When odo dev is stopped via Ctrl+C, it deletes all the resources created previously and stops port-forwarding and code synchronization.
caution

It is strongly discouraged to run multiple odo dev processes in parallel from the same component directory. Otherwise, such processes will compete with each other in trying to manage the same Kubernetes resources, and you would end up with several instances of port-forwarding and code synchronization.

How odo dev translates a container component into Kubernetes resources​

Given a component (aptly named my-component-name in the metadata.name field) in the Devfile excerpt below:

metadata:  name: my-component-name

odo will create the following Kubernetes resources in the current namespace:

  • a Deployment named my-component-name-app
  • a Service named my-component-name-app
NOTE

Per the Devfile specification, the metadata.name field is optional. If it is not defined, odo will try to autodetect the name from the project source code (based on information from files like package.json or pom.xml). As a last resort, it will use the current directory name.

Resource Labels​

By default, odo adds the following labels to all the resources it creates: You can find more information about some of those common labels in the Openshift and Kubernetes documentations.

KeyDescriptionExample Value
appthe application; always app.app
app.kubernetes.io/instancethe component name.my-component-name
app.kubernetes.io/managed-bythe tool used to create this resource; always odo.odo
app.kubernetes.io/managed-by-versionthe version of the odo binary used to create this resource.v3.0.0
app.kubernetes.io/part-ofthe higher-level application using this resource; always app.app
app.openshift.io/runtimethe application runtime, if available. Value is read in order from the metadata.projectType or metadata.language fields in the Devfile. As both metadata are optional, this annotation can be omitted.spring
componentthe component name.my-component-name
odo.dev/modein which mode the component is running. Possible values: Dev (if running odo dev), Deploy (if running odo deploy).Dev

Deployment​

odo will create a Deployment with the characteristics below.

Annotations​

By default, odo adds the following annotations to the Deployment:

KeyDescriptionExample Value
odo.dev/project-type the application runtime, if available. Value is read in order from the metadata.projectType or metadata.language fields in the Devfile. As both metadata are optional, this annotation can be omitted.spring

Notes:

  • Any additional annotations defined via the components[].container.annotation.deployment field will also be added to this resource.
  • All those annotations are also added to the underlying Pods managed by this Deployment.
Example
DevfileKubernetes Deployment
metadata:
name: my-sample-java-springboot
projectType: spring
language: java
components:
- name: tools
container:
annotation:
deployment:
example.com/my-annotation: value-1
=>
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-sample-java-springboot-app
annotations:
odo.dev/project-type: spring
example.com/my-annotation: value-1
spec:
template:
metadata:
name: my-sample-java-springboot-app
annotations:
odo.dev/project-type: spring
example.com/my-annotation: value-1

Labels​

By default, odo adds the labels mentioned in the Resource Labels section.

Note that the same labels are added to the underlying Pods managed by this Deployment.

Example
DevfileKubernetes Deployment
metadata:
name: my-sample-java-springboot
projectType: spring
language: java
components:
- name: tools
container:
...
=>
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-sample-java-springboot-app
labels:
app: app
app.kubernetes.io/instance: my-sample-java-springboot
app.kubernetes.io/managed-by: odo
app.kubernetes.io/managed-by-version: v3.0.0
app.kubernetes.io/part-of: app
app.openshift.io/runtime: spring
component: my-sample-java-springboot
odo.dev/mode: Dev
spec:
template:
metadata:
name: my-sample-java-springboot-app
labels:
app: app
app.kubernetes.io/instance: my-sample-java-springboot
app.kubernetes.io/managed-by: odo
app.kubernetes.io/managed-by-version: v3.0.0
app.kubernetes.io/part-of: app
app.openshift.io/runtime: spring
component: my-sample-java-springboot
odo.dev/mode: Dev
selector:
matchLabels:
component: my-sample-java-springboot

Replicas​

The number of Replicas for this Deployment is explicitly set to 1 and is expected to always have this value.

Pods and Containers​

Each components[].container block is translated into a dedicated container definition in the Pod template.

Environment variables​

Each entry in the components[].container.env section translates into the same environment variable in the corresponding Pod container.

Additionally, the following environment variables are reserved and injected into the container definition if mountSources is defined as true for the component's container:

KeyDescriptionExample Value
PROJECTS_ROOTA path where the project sources are mounted as defined by container component's sourceMapping. Default value is /projects./projects
PROJECT_SOURCEA path to a project source ($PROJECTS_ROOT/). If there are multiple projects, this will point to the directory of the first one. Default value is /projects./projects
Example
DevfileKubernetes Deployment
metadata:
name: my-sample-java-springboot
components:
- name: tools
container:
image: quay.io/eclipse/che-java11-maven
mountSources: true
sourceMapping: /my-code
env:
- name: DEBUG_PORT
value: "5858"
- name: another-container
container:
image: alpine:latest
mountSources: false
env:
- name: MY_ENV_VAR
value: "some value"
=>
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-sample-java-springboot-app
spec:
template:
metadata:
name: my-sample-java-springboot-app
spec:
containers:
- name: tools
env:
- name: DEBUG_PORT
value: "5858"
- name: PROJECTS_ROOT
value: /my-code
- name: PROJECT_SOURCE
value: /my-code
image: quay.io/eclipse/che-java11-maven
imagePullPolicy: Always
- name: another-container
env:
- name: MY_ENV_VAR
value: "some value"
image: alpine:latest
imagePullPolicy: Always

Command and Args​

odo will use the specified components[].container.command or components[].container.args fields as is for the Kubernetes container command and args definitions. The only requirement is that those fields should result in a non-terminating container, so odo can execute the commands it needs to manage the application. If the container is terminating, the Deployment will not reach the desired state, and odo will not be able to run the commands and start the application.

If both fields are missing, odo defaults to setting:

  • the container command to tail. This assumes that the container image (set in the Devfile) contains the tail executable.
  • the container args to [-f, /dev/null]
Example
DevfileKubernetes Deployment
metadata:
name: my-sample-java-springboot
projectType: spring
language: java
components:
- name: tools
container:
image: quay.io/eclipse/che-java11-maven
# no command or args fields set
=>
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-sample-java-springboot-app
spec:
template:
metadata:
name: my-sample-java-springboot-app
spec:
containers:
- name: tools
command: ['tail']
args: ['-f', '/dev/null']
image: quay.io/eclipse/che-java11-maven
imagePullPolicy: Always
metadata:
name: my-sample-java-springboot
components:
- name: tools
container:
image: quay.io/eclipse/che-java11-maven
command: ['/bin/my-entrypoint.sh']
args: ['arg1', 'arg2']
=>
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-sample-java-springboot-app
spec:
template:
metadata:
name: my-sample-java-springboot-app
spec:
containers:
- name: tools
command: ['/bin/my-entrypoint.sh']
args: ['arg1', 'arg2']
image: quay.io/eclipse/che-java11-maven
imagePullPolicy: Always
Image Pull Policy​

At this time, the image pull policy for all containers is fixed to Always and cannot be modified.

Resources Limits and Requests​

odo maps each components[].container.{cpu,memory}{Limit,Request} to corresponding resources.{limits,requests}.{cpu,memory} fields with the respective values.

Example
DevfileKubernetes Deployment
metadata:
name: my-sample-java-springboot
components:
- name: tools
container:
image: quay.io/eclipse/che-java11-maven
cpuLimit: 500m
cpuRequest: 250m
memoryLimit: 512Mi
memoryRequest: 256Mi
=>
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-sample-java-springboot-app
spec:
template:
metadata:
name: my-sample-java-springboot-app
spec:
containers:
- name: tools
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
image: quay.io/eclipse/che-java11-maven
imagePullPolicy: Always
Ports​

odo translates each element in the components[].container.endpoints[] block into a dedicated containerPort with the same name and port, regardless of the exposure.

Example
DevfileKubernetes Deployment
metadata:
name: my-sample-java-springboot
components:
- name: tools
container:
image: quay.io/eclipse/che-java11-maven
endpoints:
- name: http-springboot
targetPort: 8080
- name: my-custom-ep
targetPort: 3000
protocol: http
exposure: internal
- name: debug
targetPort: 5858
exposure: none
=>
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-sample-java-springboot-app
spec:
template:
metadata:
name: my-sample-java-springboot-app
spec:
containers:
- name: tools
ports:
- containerPort: 8080
name: http-springboot
protocol: TCP
- containerPort: 3000
name: my-custom-ep
protocol: TCP
- containerPort: 5858
name: debug
protocol: TCP
image: quay.io/eclipse/che-java11-maven
imagePullPolicy: Always

Volumes​

odo creates the following volumes and mounts them in the containers:

Volume nameVolume TypeMount PathDescription
odo-shared-dataemptyDir/opt/odoInternal Purpose. Contains files (like PIDs for commands) necessary for odo.
Devfile Volume Components​

The Devfile specification allows to define volume components to share files among container components. Such volume components can be marked as ephemeral or not.

  • If ephemeral is set to false, which is the default value, odo creates a PersistentVolumeClaim (PVC) (with the default storage class).
  • If ephemeral is set to true, odo translates it into an emptyDir volume, tied to the lifetime of the Pod.
Example
DevfileKubernetes Deployment
metadata:
name: my-sample-java-springboot
components:
- name: tools
container:
volumeMounts:
- name: ephemeral-data
path: /tmp
- name: m2
path: /home/user/.m2
image: quay.io/eclipse/che-java11-maven
mountSources: false
- name: m2
volume:
size: 3Gi
- name: ephemeral-data
volume:
ephemeral: true
size: 1Gi
=>
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-sample-java-springboot-app
spec:
template:
metadata:
name: my-sample-java-springboot-app
spec:
volumes:
- name: odo-shared-data
emptyDir: {}
- name: ephemeral-data
emptyDir:
sizeLimit: 1Gi
- name: m2-my-sample-java-springboot-app-vol
persistentVolumeClaim:
# odo also creates and manages this PVC
claimName: m2-my-sample-java-springboot-app
containers:
- name: tools
volumeMounts:
- name: odo-shared-data
mountPath: /opt/odo/
- name: ephemeral-data
mountPath: /tmp
- name: m2-my-sample-java-springboot-app-vol
mountPath: /home/user/.m2
Project Sources​

As mentioned in how odo dev works, odo is able to perform a one-way synchronization of the local source code, i.e., from the developer machine to the development pod running in the cluster. This is done via a Volume, named odo-projects, mounted in the container.

However, this is subject to two things:

  • the value of the mountSources flag (default value is true) in the Devfile container component. Project sources are not mounted in the container if this is set to false. Note that odo requires at least one component in the Devfile to set mountSources: true in order to synchronize files.
  • the type of volume created depends on the configuration of odo, and more specifically on the value of the Ephemeral setting:
    • if Ephemeral is false, which is the default setting, odo creates a PersistentVolumeClaim (PVC) (with the default storage class)
    • if Ephemeral is true, odo creates an emptyDir volume, tied to the lifetime of the Pod.
Volume nameVolume TypeMount PathDescription
odo-projectsPersistentVolumeClaim (PVC) if Ephemeral preference is false,
emptyDir otherwise.
Value of component[].container.sourceMapping (default value is /projects).Used for project source code synchronization.
Examples
  • with mountSources: true and Ephemeral preference set to false (default value):
DevfileKubernetes Deployment
metadata:
name: my-sample-java-springboot
components:
- name: tools
container:
image: quay.io/eclipse/che-java11-maven
mountSources: true
sourceMapping: /my-code
=>
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-sample-java-springboot-app
spec:
template:
metadata:
name: my-sample-java-springboot-app
spec:
volumes:
- name: odo-shared-data
emptyDir: {}
- name: odo-projects
persistentVolumeClaim:
# odo also creates and manages this PVC
claimName: odo-projects-my-sample-java-springboot-app
containers:
- name: tools
env:
- name: PROJECTS_ROOT
value: /my-code
- name: PROJECT_SOURCE
value: /my-code
volumeMounts:
- name: odo-shared-data
mountPath: /opt/odo/
- name: odo-projects
mountPath: /my-code

  • with mountSources: true and Ephemeral setting set to true:
DevfileKubernetes Deployment
metadata:
name: my-sample-java-springboot
components:
- name: tools
container:
image: quay.io/eclipse/che-java11-maven
mountSources: true
sourceMapping: /my-code
=>
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-sample-java-springboot-app
spec:
template:
metadata:
name: my-sample-java-springboot-app
spec:
volumes:
- name: odo-shared-data
emptyDir: {}
- name: odo-projects
emptyDir: {}
containers:
- name: tools
env:
- name: PROJECTS_ROOT
value: /my-code
- name: PROJECT_SOURCE
value: /my-code
volumeMounts:
- name: odo-shared-data
mountPath: /opt/odo/
- name: odo-projects
mountPath: /my-code

  • with mountSources: false and Ephemeral preference set to false. Note that odo requires at least one component in the Devfile to set mountSources: true in order to synchronize files.
DevfileKubernetes Deployment
metadata:
name: my-sample-java-springboot
components:
- name: tools
container:
image: quay.io/eclipse/che-java11-maven
mountSources: false
sourceMapping: /my-code
=>
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-sample-java-springboot-app
spec:
template:
metadata:
name: my-sample-java-springboot-app
spec:
volumes:
- name: odo-shared-data
emptyDir: {}
- name: odo-projects
persistentVolumeClaim:
# odo also creates and manages this PVC
claimName: odo-projects-my-sample-java-springboot-app
containers:
- name: tools
volumeMounts:
- name: odo-shared-data
mountPath: /opt/odo/

  • with mountSources: false and Ephemeral preference set to true. Note that odo requires at least one component in the Devfile to set mountSources: true in order to synchronize files.
DevfileKubernetes Deployment
metadata:
name: my-sample-java-springboot
components:
- name: tools
container:
image: quay.io/eclipse/che-java11-maven
mountSources: false
sourceMapping: /my-code
=>
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-sample-java-springboot-app
spec:
template:
metadata:
name: my-sample-java-springboot-app
spec:
volumes:
- name: odo-shared-data
emptyDir: {}
- name: odo-projects
emptyDir: {}
containers:
- name: tools
volumeMounts:
- name: odo-shared-data
mountPath: /opt/odo/

Service​

odo will create a Service of type ClusterIP with the characteristics below.

Annotations​

By default, odo adds the following annotations to the Service:

KeyValueDescription
service.binding/backend_ippath={.spec.clusterIP}exposes the Service clusterIP address as binding data, so that this can be used as a backing service via the Service Binding Operator (SBO). More details on SBO documentation.
service.binding/backend_portpath={.spec.ports},
elementType=sliceOfMaps,
sourceKey=name,
sourceValue=port
exposes the Service ports as binding data, so this can be used as a backing service via the Service Binding Operator (SBO). More details on SBO documentation.

See this blog post for more details about binding external services.

Note that any additional annotations defined via the components[].container.annotation.service Devfile field will also be added to this resource.

Example
DevfileKubernetes Service
metadata:
name: my-sample-java-springboot
projectType: spring
language: java
components:
- name: tools
container:
annotation:
service:
example.com/my-svc-annotation: value-1
=>
apiVersion: v1
kind: Service
metadata:
name: my-sample-java-springboot-app
annotations:
service.binding/backend_ip: path={.spec.clusterIP}
service.binding/backend_port: path={.spec.ports},elementType=sliceOfMaps,sourceKey=name,sourceValue=port
example.com/my-svc-annotation: value-1
spec:
type: ClusterIP
selector:
component: my-sample-java-springboot-app

Labels​

By default, odo adds the labels mentioned in the Resource Labels section.

Example
DevfileKubernetes Service
metadata:
name: my-sample-java-springboot
projectType: spring
language: java
components:
- name: tools
container:
...
=>
apiVersion: v1
kind: Service
metadata:
name: my-sample-java-springboot-app
labels:
app: app
app.kubernetes.io/instance: my-sample-java-springboot
app.kubernetes.io/managed-by: odo
app.kubernetes.io/managed-by-version: v3.0.0
app.kubernetes.io/part-of: app
app.openshift.io/runtime: spring
component: my-sample-java-springboot
odo.dev/mode: Dev
spec:
type: ClusterIP
selector:
component: my-sample-java-springboot-app

Ports​

For each endpoint with an exposure other than none defined in the components[].container.endpoints Devfile block, odo adds a port to the Service spec.

Example
DevfileKubernetes Service
metadata:
name: my-sample-java-springboot
components:
- id: my-container1
container:
endpoints:
- name: http-springboot
targetPort: 8080
- name: my-custom-ep
targetPort: 3000
exposure: internal
- name: debug
targetPort: 5005
exposure: none
- id: my-container2
container:
endpoints:
- name: another-ep
targetPort: 9090
=>
apiVersion: v1
kind: Service
metadata:
name: my-sample-java-springboot-app
spec:
type: ClusterIP
ports:
- name: http-springboot
port: 8080
protocol: TCP
targetPort: 8080
- name: my-custom-ep
port: 3000
protocol: TCP
targetPort: 3000
- name: another-ep
port: 9090
protocol: TCP
targetPort: 3000

Full example​

Example of Devfile and resulting Kubernetes resources

Given this Devfile:

schemaVersion: 2.2.0
metadata:
description: Spring Boot® using Java
displayName: Spring Boot®
globalMemoryLimit: 2674Mi
icon: https://spring.io/images/projects/spring-edf462fec682b9d48cf628eaf9e19521.svg
language: java
name: my-sample-java-springboot
projectType: spring
tags:
- Java
- Spring
version: 1.1.0

commands:
- exec:
commandLine: mvn clean -Dmaven.repo.local=/home/user/.m2/repository package -Dmaven.test.skip=true
component: tools
group:
isDefault: true
kind: build
workingDir: ${PROJECT_SOURCE}
id: build
- exec:
commandLine: mvn -Dmaven.repo.local=/home/user/.m2/repository spring-boot:run
component: tools
group:
isDefault: true
kind: run
workingDir: ${PROJECT_SOURCE}
id: run
- exec:
commandLine: java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=${DEBUG_PORT},suspend=n
-jar target/*.jar
component: tools
group:
isDefault: true
kind: debug
workingDir: ${PROJECT_SOURCE}
id: debug

components:
- container:
annotation:
deployment:
example.com/my-deploy-annotation1: my-deploy-annotation-val1
service:
example.com/my-svc-annotation1: my-svc-annotation-val1
endpoints:
- name: http-springboot
targetPort: 8080
- name: debug
targetPort: 5858
exposure: none
env:
- name: DEBUG_PORT
value: "5858"
image: quay.io/eclipse/che-java11-maven:next
memoryLimit: 768Mi
mountSources: true
volumeMounts:
- name: m2
path: /home/user/.m2
name: tools

- container:
annotation:
deployment:
example.com/my-deploy-annotation-echo1: my-deploy-annotation-val1
service:
example.com/my-svc-annotation-echo1: my-svc-annotation-val1
endpoints:
- name: echo-ep1
targetPort: 18080
env:
- name: MY_ENV_VAR
value: "some value"
image: alpine:latest
mountSources: false
command: [tail]
args: [-f, /dev/null]
name: echo-container

- name: m2
volume:
size: 3Gi

odo will generate the following Kubernetes Resources:

  • Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
example.com/my-deploy-annotation-echo1: my-deploy-annotation-val1
example.com/my-deploy-annotation1: my-deploy-annotation-val1
odo.dev/project-type: spring
labels:
app: app
app.kubernetes.io/instance: my-sample-java-springboot
app.kubernetes.io/managed-by: odo
app.kubernetes.io/managed-by-version: v3.0.0
app.kubernetes.io/part-of: app
app.openshift.io/runtime: spring
component: my-sample-java-springboot
odo.dev/mode: Dev
name: my-sample-java-springboot-app
namespace: default
spec:
replicas: 1
selector:
matchLabels:
component: my-sample-java-springboot
strategy:
type: Recreate
template:
metadata:
annotations:
example.com/my-deploy-annotation-echo1: my-deploy-annotation-val1
example.com/my-deploy-annotation1: my-deploy-annotation-val1
odo.dev/project-type: spring
labels:
app: app
app.kubernetes.io/instance: my-sample-java-springboot
app.kubernetes.io/managed-by: odo
app.kubernetes.io/managed-by-version: v3.0.0
app.kubernetes.io/part-of: app
app.openshift.io/runtime: spring
component: my-sample-java-springboot
odo.dev/mode: Dev
name: my-sample-java-springboot-app
namespace: default
spec:
containers:
- args:
- -f
- /dev/null
command:
- tail
env:
- name: DEBUG_PORT
value: "5858"
- name: PROJECTS_ROOT
value: /projects
- name: PROJECT_SOURCE
value: /projects
image: quay.io/eclipse/che-java11-maven:next
imagePullPolicy: Always
name: tools
ports:
- containerPort: 8080
name: http-springboot
protocol: TCP
- containerPort: 5858
name: debug
protocol: TCP
resources:
limits:
memory: 768Mi
volumeMounts:
- mountPath: /projects
name: odo-projects
- mountPath: /opt/odo/
name: odo-shared-data
- mountPath: /home/user/.m2
name: m2-my-sample-java-springboot-app-vol
- args:
- -f
- /dev/null
command:
- tail
env:
- name: MY_ENV_VAR
value: some value
image: alpine:latest
imagePullPolicy: Always
name: echo-container
ports:
- containerPort: 18080
name: echo-ep1
protocol: TCP
resources: {}
volumeMounts:
- mountPath: /opt/odo/
name: odo-shared-data
restartPolicy: Always
securityContext: {}
volumes:
- name: m2-my-sample-java-springboot-app-vol
persistentVolumeClaim:
claimName: m2-my-sample-java-springboot-app
- name: odo-projects
persistentVolumeClaim:
claimName: odo-projects-my-sample-java-springboot-app
- emptyDir: {}
name: odo-shared-data

  • Service:
apiVersion: v1
kind: Service
metadata:
annotations:
example.com/my-svc-annotation-echo1: my-svc-annotation-val1
example.com/my-svc-annotation1: my-svc-annotation-val1
service.binding/backend_ip: path={.spec.clusterIP}
service.binding/backend_port: path={.spec.ports},elementType=sliceOfMaps,sourceKey=name,sourceValue=port
labels:
app: app
app.kubernetes.io/instance: my-sample-java-springboot
app.kubernetes.io/managed-by: odo
app.kubernetes.io/managed-by-version: v3.0.0
app.kubernetes.io/part-of: app
app.openshift.io/runtime: spring
component: my-sample-java-springboot
odo.dev/mode: Dev
namespace: default
name: my-sample-java-springboot-app
ownerReferences:
- apiVersion: apps/v1
blockOwnerDeletion: true
kind: Deployment
name: my-sample-java-springboot-app
spec:
ports:
- name: http-springboot
port: 8080
protocol: TCP
targetPort: 8080
- name: echo-ep1
port: 18080
protocol: TCP
targetPort: 18080
selector:
component: my-sample-java-springboot
sessionAffinity: None
type: ClusterIP
  • PersistentVolumeClaim for the project source code (because of Ephemeral Setting set to false (default)):
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
finalizers:
- kubernetes.io/pvc-protection
labels:
app: app
app.kubernetes.io/instance: my-sample-java-springboot
app.kubernetes.io/managed-by: odo
app.kubernetes.io/managed-by-version: v3.0.0
app.kubernetes.io/part-of: app
app.kubernetes.io/storage-name: odo-projects
app.openshift.io/runtime: spring
component: my-sample-java-springboot
odo-source-pvc: odo-projects
odo.dev/mode: Dev
storage-name: odo-projects
name: odo-projects-my-sample-java-springboot-app
namespace: default
ownerReferences:
- apiVersion: apps/v1
blockOwnerDeletion: true
kind: Deployment
name: my-sample-java-springboot-app
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
  • PersistentVolumeClaim for the non-ephemeral volume component:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
finalizers:
- kubernetes.io/pvc-protection
labels:
app: app
app.kubernetes.io/instance: my-sample-java-springboot
app.kubernetes.io/managed-by: odo
app.kubernetes.io/managed-by-version: v3.0.0
app.kubernetes.io/part-of: app
app.kubernetes.io/storage-name: m2
app.openshift.io/runtime: spring
component: my-sample-java-springboot
odo.dev/mode: Dev
storage-name: m2
name: m2-my-sample-java-springboot-app
namespace: default
ownerReferences:
- apiVersion: apps/v1
blockOwnerDeletion: true
kind: Deployment
name: my-sample-java-springboot-app
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi