In this tutorial, we will build a simple web app component written in Python that you can use for testing. It reads in an env variable TARGET and prints “Hello ${TARGET}!“. If TARGET is not specified, it will use “World” as the TARGET.
- Follow the instructions in the installation document to get KubeVela installed.
- Docker installed and running on your local machine, and a Docker Hub account configured (we’ll use it for a container registry).
The following instructions will lead you to build an image from source, you can get all the files mentioned here in the app folder.
- Create a new directory and cd into it:
mkdir app cd app
- Create a file named
app.py
and copy the code fromapp/app.py
- Create a file named
Dockerfile
and copy the code fromapp/Dockerfile
, See official Python docker image for more details. - Login to your Docker Hub account, using the below command.
This would direct you to click enter and it would open up a browser. Login to your Docker Hub account on the browser and the control would come back to CLI. You would get a success message if login was completed.
docker login
- Use Docker to build the sample code into a container. To build and push with Docker Hub, run these commands after updating your Docker Hub Username.
# Build the container on your local machine
docker_hub_username = <your_docker_username>
docker build -t $docker_hub_username/helloworld-python:v1 .
# Push the container to docker registry
docker push $docker_hub_username/helloworld-python:v1
Now we have a docker image tagged <your_docker_username>/helloworld-python:v1
.
Next setp is to determine the type of your component, namely, the runtime workload inside which you expect your containerized application runs.
According to our sample application, we need a container runtime that can accept
an ENV parameter named TARGET
and is capable of exposing a port for external
to access the service.
Furthermore, the application is stateless and can be replicated.
Currently, KubeVela provides several out-of-box types of component,
webservice
, worker
and task
,
After checking the usage of each type through KubeVela cli vela components
, we can figure out that, webservice
matches our requirements to
deploy the application.
vela components
NAME NAMESPACE WORKLOAD DESCRIPTION
...
webservice vela-system deployments.apps Describes long-running, scalable, containerized services
that have a stable network endpoint to receive external
network traffic from customers.
...
Now we have determined to use webservice
as our component's type.
As an end-user, you are supposed to know how to check the component types supported by the platform and the usage of each. However, if you find no one can satisfy your requirement, you are encouraged to contact platform administrators to ask for solution.
⚠️ End-users are not allowed to create new component types.
Once component type is decided, you may need to append specific operational characteristics (Traits) to your components. In this sample, we need to expose the service of our python app to outside of Kubernetes cluster. Let's check which traits can help here.
vela traits
NAME NAMESPACE APPLIES-TO CONFLICTS-WITH POD-DISRUPTIVE DESCRIPTION
gateway [deployments.apps statefulsets.apps] Enable public web traffic for the component, the ingress API
matches K8s v1.20+.
hostalias [deployments.apps statefulsets.apps daemonsets.apps Add host aliases on K8s pod for your workload which follows
jobs.batch] the pod spec in path 'spec.template'.
hpa [deployments.apps statefulsets.apps] Configure k8s HPA for Deployment or Statefulset
Apparently, gateway
is exactly what we need.
Again, as an end-user, you are also supposed to know how to check the traits already installed on the platform and the usage of each. If you find no one can satisfy your requirement, you are encouraged to contact platform administrators to ask for solutions.
⚠️ End-users are not allowed to create new traits.
Once component type and trait are both choosen, we can assemble them in
an Application entity.
To author an Application file, you must know the configurable points of the
component type as well as traits, then you can fulfill their properties
fields
according to your needs.
Check the configurable points (properties) of a component type
vela show webservice
click to show properties of webservice
# Properties
+------------------+----------------------------------------------------------------------------------+-----------------------+----------+---------+
| NAME | DESCRIPTION | TYPE | REQUIRED | DEFAULT |
+------------------+----------------------------------------------------------------------------------+-----------------------+----------+---------+
| cmd | Commands to run in the container | []string | false | |
| env | Define arguments by using environment variables | [[]env](#env) | false | |
| addRevisionLabel | | bool | true | false |
| image | Which image would you like to use for your service | string | true | |
| port | Which port do you want customer traffic sent to | int | true | 80 |
| cpu | Number of CPU units for the service, like `0.5` (0.5 CPU core), `1` (1 CPU core) | string | false | |
| volumes | Declare volumes and volumeMounts | [[]volumes](#volumes) | false | |
+------------------+----------------------------------------------------------------------------------+-----------------------+----------+---------+
##### volumes
+-----------+---------------------------------------------------------------------+--------+----------+---------+
| NAME | DESCRIPTION | TYPE | REQUIRED | DEFAULT |
+-----------+---------------------------------------------------------------------+--------+----------+---------+
| name | | string | true | |
| mountPath | | string | true | |
| type | Specify volume type, options: "pvc","configMap","secret","emptyDir" | string | true | |
+-----------+---------------------------------------------------------------------+--------+----------+---------+
## env
+-----------+-----------------------------------------------------------+-------------------------+----------+---------+
| NAME | DESCRIPTION | TYPE | REQUIRED | DEFAULT |
+-----------+-----------------------------------------------------------+-------------------------+----------+---------+
| name | Environment variable name | string | true | |
| value | The value of the environment variable | string | false | |
| valueFrom | Specifies a source the value of this var should come from | [valueFrom](#valueFrom) | false | |
+-----------+-----------------------------------------------------------+-------------------------+----------+---------+
### valueFrom
+--------------+--------------------------------------------------+-------------------------------+----------+---------+
| NAME | DESCRIPTION | TYPE | REQUIRED | DEFAULT |
+--------------+--------------------------------------------------+-------------------------------+----------+---------+
| secretKeyRef | Selects a key of a secret in the pod's namespace | [secretKeyRef](#secretKeyRef) | true | |
+--------------+--------------------------------------------------+-------------------------------+----------+---------+
#### secretKeyRef
+------+------------------------------------------------------------------+--------+----------+---------+
| NAME | DESCRIPTION | TYPE | REQUIRED | DEFAULT |
+------+------------------------------------------------------------------+--------+----------+---------+
| name | The name of the secret in the pod's namespace to select from | string | true | |
| key | The key of the secret to select from. Must be a valid secret key | string | true | |
+------+------------------------------------------------------------------+--------+----------+---------+
Check the configurable points (properties) of a trait
vela show gateway
click to show properties of gateway trait
# Properties
+---------------------+------------------------------------------------------------------------------------------------------+-------------------------------------------------+----------+------------------------+
| NAME | DESCRIPTION | TYPE | REQUIRED | DEFAULT |
+---------------------+------------------------------------------------------------------------------------------------------+-------------------------------------------------+----------+------------------------+
| domain | Specify the domain you want to expose. | string | false | |
| http | Specify the mapping relationship between the http path and the workload port. | map[string]int | true | |
Pick up the properties we need and fulfill them in Application file as below.
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: first-app
spec:
components:
- name: helloworld
type: webservice # <=== component type
properties: # <=== component properties
image: <your_docker_username>/helloworld-python:v1
env:
- name: "TARGET"
value: "KubeVela"
port: 8080
traits:
- type: gateway # <=== trait type
properties: # <=== trait properties
domain: localhost
http:
/: 8080
Update the above code with your docker username and save it as file app.yaml
.
Use the Vela command to apply.
vela up -f app.yaml --publish-version v1.1.0
You will get a success message as mentioned below.
Applying an application in vela K8s object format...
✅ App has been deployed 🚀🚀🚀
Port forward: vela port-forward first-app -n prod
SSH: vela exec first-app -n prod
Logging: vela logs first-app -n prod
App status: vela status first-app -n prod
Endpoint: vela status first-app -n prod --endpoint
Application prod/first-app applied.
You can check the end point using the command
vela status first-app --endpoint
The output would like the below
+---------+------------+--------------------------+-----------------------------+-------+
| CLUSTER | COMPONENT | REF(KIND/NAMESPACE/NAME) | ENDPOINT | INNER |
+---------+------------+--------------------------+-----------------------------+-------+
| local | helloworld | Ingress/prod/helloworld | http://localhost | false |
| local | helloworld | Service/prod/helloworld | http://helloworld.prod:8080 | true |
+---------+------------+--------------------------+-----------------------------+-------+
We can check the application through KuveVela cli.
vela ls
APP COMPONENT TYPE TRAITS PHASE HEALTHY STATUS CREATED-TIME
first-app helloworld webservice gateway running healthy Ready:1/1 2025-01-06 22:42:28 +0530 IST
And call the service by cURL tool
curl localhost
Hello KubeVela!
Yeah, we have successfully deploy an application from source now.
If you cannot access the domain, you may check the network or ingress configuration of your cluster.
If we want to upgrade an application, the easiest way is to modify the application components' properties.
For example, we change the code from Hello
to Goodbye
.
import os
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
target = os.environ.get('TARGET', 'World')
- return 'Hello {}!\n'.format(target)
+ return 'Goodbye {}!\n'.format(target)
if __name__ == "__main__":
app.run(debug=True, host='0.0.0.0', port=int(os.environ.get('PORT', "8080")))
Build and create image with a new tag.
# Build the container on your local machine
docker_hub_username = <your_docker_username>
docker build -t $docker_hub_username/helloworld-python:v1 .
# Push the container to docker registry
docker push $docker_hub_username/helloworld-python:v1
Change the image tag to new one (v1 => v2).
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: first-app
spec:
components:
- name: helloworld
type: webservice
properties:
image: oamdev/helloworld-python:v2 # new image tag
env:
- name: "TARGET"
value: "KubeVela"
port: 8080
traits:
- type: gateway
properties:
domain: localhost
http:
/: 8080
Apply the upgraded application
vela up -f app.yaml --publish-version v1.1.1
Call the service to check the response has changed.
curl localhost
Goodbye KubeVela!