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. - Use Docker to build the sample code into a container. To build and push with
Docker Hub, run these commands replacing
oamdev
with your Docker Hub username
# Build the container on your local machine
docker build -t oamdev/helloworld-python:v1 .
# Push the container to docker registry
docker push oamdev/helloworld-python:v1
Now we have a docker image tagged oamdev/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
annotations vela-system webservice,worker false Add annotations for your Workload.
cpuscaler vela-system webservice,worker false configure k8s HPA with CPU metrics for Deployment
ingress vela-system webservice,worker false Configures K8s ingress and service to enable web traffic for
your service. Please use route trait in cap center for
advanced usage.
labels vela-system webservice,worker false Add labels for your Workload.
scaler vela-system webservice,worker false Configures replicas for your service by patch replicas
field.
sidecar vela-system webservice,worker false inject a sidecar container into your app
Apparently, ingress
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 ingress
click to show properties of ingress trait
# Properties
+--------+------------------------------------------------------------------------------+----------------+----------+---------+
| NAME | DESCRIPTION | TYPE | REQUIRED | DEFAULT |
+--------+------------------------------------------------------------------------------+----------------+----------+---------+
| http | Specify the mapping relationship between the http path and the workload port | map[string]int | true | |
| domain | Specify the domain you want to expose | string | 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: oamdev/helloworld-python:v1
env:
- name: "TARGET"
value: "KubeVela"
port: 8080
traits:
- type: ingress # <=== trait type
properties: # <=== trait properties
domain: localhost
http:
/: 8080
Let's save it as file app.yaml
and apply to deploy.
kubectl apply -f app.yaml
We can check the application through KuveVela cli.
vela ls
APP COMPONENT TYPE TRAITS PHASE HEALTHY STATUS CREATED-TIME
first-app helloworld webservice ingress running healthy 2021-05-18 15:40:02 +0900 KST
And call the service by cURL tool
curl localhost
Hello KubeVela!
Yeah, we have successfully deploy an application from source now.
⚠️ ingress trait replies on the ingress controller, such as nginx-ingress, installed in your cluster. 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.
docker build -t oamdev/helloworld-python:v2 .
docker push oamdev/helloworld-python:v2
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: ingress
properties:
domain: localhost
http:
/: 8080
Apply the upgraded application
kubectl apply -f app-upgrade.yaml
Call the service to check the response has changed.
curl localhost
Goodbye KubeVela!