This guide covers how to install and configure a basic Rudr installation. For more details on Rudr installation, see the Installation Guide
The following prerequisites are required for a successful use of Rudr.
- A copy of this repo (
git clone https://github.com/oam-dev/rudr.git
) - A Kubernetes cluster version 1.15 or greater
kubectl
installed and pointed at the cluster- Helm 3
To find out which cluster Rudr would install to, you can run kubectl config current-context
or kubectl cluster-info
.
$ kubectl config current-context
my-cluster
The fastest way to install Rudr is with Helm 3.
make sure your Helm 3 has version newer than
v3.0.0-beta.3
, or you have to install the CRDs withkubectl apply -f charts/rudr/crds
$ helm install rudr charts/rudr
NAME: rudr
LAST DEPLOYED: 2019-10-02 13:57:33.158655 -0600 MDT m=+5.183858344
NAMESPACE: default
STATUS: deployed
NOTES:
Rudr is a Kubernetes controller to manage Configuration CRDs.
It has been successfully installed.
This will give you a basic installation of Rudr. For the following examples, you should also install the NGINX ingress into Kubernetes:
$ helm install nginx-ingress stable/nginx-ingress
NAME: nginx-ingress
LAST DEPLOYED: 2019-10-02 13:57:57.444655 -0600 MDT m=+2.129323603
NAMESPACE: default
STATUS: deployed
NOTES:
The nginx-ingress controller has been installed.
It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status by running 'kubectl --namespace default get services -o wide -w nginx-ingress-controller'
...
This will give you a basic implementation of Kubernetes ingresses. See the Installation Guide for more about ingresses and other traits.
Once you have installed Rudr, you can start creating and deploying apps.
The first step to deploying an application is to deploy its constituent component(s). A component will not actually run until its parent application is deployed; however it must be deployed first, before application deployment.
To start, install an example component:
$ kubectl apply -f examples/helloworld-python-component.yaml
This component declares a simple web app written in Python. You can read the Create Component from Scratch doc to know how we build it.
After that, you can list all available components using kubectl
:
$ kubectl get componentschematics
NAME AGE
helloworld-python-v1 14s
You can look at an individual component:
$ kubectl get componentschematic helloworld-python-v1 -o yaml
apiVersion: core.oam.dev/v1alpha1
kind: ComponentSchematic
metadata:
creationTimestamp: "2019-10-08T13:02:23Z"
generation: 1
name: helloworld-python-v1
namespace: default
resourceVersion: "1989944"
...
spec:
containers:
- env:
- fromParam: target
name: TARGET
# ... more YAML
Rudr provides a way to attach operational features at install time. This allows application operations an opportunity to provide functionality like autoscaling, caching, or ingress control at install time, without requiring the developer to change anything in the component.
You can also list the traits that are available on Rudr:
$ kubectl get traits
NAME AGE
auto-scaler 19m
ingress 19m
manual-scaler 19m
volume-mounter 19m
And you can look at an individual trait in the same way that you investigate a component:
$ kubectl get trait ingress -o yaml
apiVersion: core.oam.dev/v1alpha1
kind: Trait
metadata:
creationTimestamp: "2019-10-02T19:57:37Z"
generation: 1
name: ingress
namespace: default
resourceVersion: "117813"
selfLink: /apis/core.oam.dev/v1alpha1/namespaces/default/traits/ingress
uid: 9f82c346-c8c6-4780-9949-3ecfd47879f9
spec:
appliesTo:
- core.oam.dev/v1alpha1.Server
- core.oam.dev/v1alpha1.SingletonServer
properties:
- description: Host name for the ingress
name: hostname
required: true
type: string
- description: Port number on the service
name: service_port
required: true
type: int
- description: Path to expose. Default is '/'
name: path
required: false
type: string
The above describes a trait that attaches an ingress to a component, handling the routing of traffic to that app.
When you are ready to try installing something, take a look at the examples/first-app-config.yaml
, which shows a basic Application Configuration with a single trait applied:
apiVersion: core.oam.dev/v1alpha1
kind: ApplicationConfiguration
metadata:
name: first-app
spec:
components:
- componentName: helloworld-python-v1
instanceName: first-app-helloworld-python-v1
parameterValues:
- name: target
value: Rudr
- name: port
value: '9999'
traits:
- name: ingress
properties:
hostname: example.com
path: /
servicePort: 9999
This is an example of an application composed of a singular component that has an ingress trait with an address of example.com
and a service port of 9999
.
To install this application configuration, use kubectl
:
$ kubectl apply -f examples/first-app-config.yaml
applicationconfiguration.core.oam.dev/first-app created
You'll need to wait for a minute or two for it to fully deploy. Behind the scenes, Rudr is creating all the necessary objects.
Once it is fully deployed, you can see your configuration:
$ kubectl get applicationconfigurations
NAME AGE
first-app 4m23s
$ kubectl get applicationconfiguration first-app -o yaml
apiVersion: core.oam.dev/v1alpha1
kind: ApplicationConfiguration
metadata:
annotations:
...
creationTimestamp: "2019-10-08T12:39:07Z"
generation: 6
name: first-app
namespace: default
resourceVersion: "2020150"
selfLink: /apis/core.oam.dev/v1alpha1/namespaces/default/applicationconfigurations/first-app
uid: 2ea9f384-993c-42b0-803a-43a1c273d291
spec:
components:
- instanceName: first-app-helloworld-python-v1
componentName: helloworld-python-v1
parameterValues:
- name: target
value: Rudr
- name: port
value: "9999"
traits:
- name: ingress
properties:
hostname: example.com
path: /
servicePort: 9999
status:
components:
helloworld-python-v1:
deployment/first-app-helloworld-python-v1: running
ingress/first-app-helloworld-python-v1-trait-ingress: Created
service/first-app-helloworld-python-v1: created
phase: synced
The way to visit the web app could be different with different platforms.
Let's use port-forward
to help us get the application URL by running these commands:
export POD_NAME=$(kubectl get pods -l "oam.dev/instance-name=first-app-helloworld-python-v1,app.kubernetes.io/name=first-app" -o jsonpath="{.items[0].metadata.name}")
kubectl port-forward $POD_NAME 9999:9999
kubectl port-forward
command will block and serve your requests.
Visit http://127.0.0.1:9999 to use your application. You will get the following output:
Hello Rudr!
Now we have successfully installed our web app and checked the result, the application worked well. But someday, the operator may want to change something. For example:
- the hostname: maybe because of there's conflict with other app, assume we change the hostname to
oamexample.com
. - env(target): this could represent some normal case of update, assume we change value of
target
toWorld
.
So you could change first-app-config.yaml
like below:
apiVersion: core.oam.dev/v1alpha1
kind: ApplicationConfiguration
metadata:
name: first-app
spec:
components:
- componentName: helloworld-python-v1
instanceName: first-app-helloworld-python-v1
parameterValues:
- name: target
- value: Rudr
+ value: World
- name: port
value: '9999'
traits:
- name: ingress
properties:
- hostname: example.com
+ hostname: oam.example.com
path: /
servicePort: 9999
Again we apply this yaml:
$ kubectl apply -f examples/first-app-config.yaml
applicationconfiguration.core.oam.dev/first-app configured
Then check the applied yaml first:
$ kubectl get applicationconfiguration first-app -o yaml
apiVersion: core.oam.dev/v1alpha1
kind: ApplicationConfiguration
metadata:
annotations:
...
creationTimestamp: "2019-10-08T12:39:07Z"
generation: 9
name: first-app
namespace: default
resourceVersion: "2022598"
selfLink: /apis/core.oam.dev/v1alpha1/namespaces/default/applicationconfigurations/first-app
uid: 2ea9f384-993c-42b0-803a-43a1c273d291
spec:
components:
- instanceName: first-app-helloworld-python-v1
componentName: helloworld-python-v1
parameterValues:
- name: target
value: World
- name: port
value: "9999"
traits:
- name: ingress
properties:
hostname: oam.example.com
path: /
servicePort: 9999
status:
components:
helloworld-python-v1:
deployment/first-app-helloworld-python-v1: running
ingress/first-app-helloworld-python-v1-trait-ingress: Created
service/first-app-helloworld-python-v1: created
phase: synced
You can see fields have been changed.
Again, get the application URL by running these commands:
export POD_NAME=$(kubectl get pods -l "oam.dev/instance-name=first-app-helloworld-python-v1,app.kubernetes.io/name=first-app" -o jsonpath="{.items[0].metadata.name}")
kubectl port-forward $POD_NAME 9999:9999
Let's visit the web app again on http://127.0.0.1:9999 and find the following result:
Hello World!
The response indicates our change of environment is successful.
Assume several days have gone and the developer have developed a new version of the web app.
For example we change prefix of the response from Hello
to Goodbye
, and make a new component called helloworld-python-v2
.
You can find more details about how we create it in Upgrade Component.
We need to change and apply the configuration file to make the component upgrade work.
apiVersion: core.oam.dev/v1alpha1
kind: ApplicationConfiguration
metadata:
name: first-app
spec:
components:
- - componentName: helloworld-python-v1
+ - componentName: helloworld-python-v2
- instanceName: first-app-helloworld-python-v1
+ instanceName: first-app-helloworld-python-v2
parameterValues:
- name: target
value: World
- name: port
value: '9999'
traits:
- name: ingress
properties:
hostname: oam.example.com
path: /
servicePort: 9999
Apply it:
$ kubectl apply -f examples/first-app-config.yaml
applicationconfiguration.core.oam.dev/first-app configured
You could check the applied yaml again by yourself. You should find the component name has been changed.
Finally, get the application URL by running these commands:
export POD_NAME=$(kubectl get pods -l "oam.dev/instance-name=first-app-helloworld-python-v2,app.kubernetes.io/name=first-app" -o jsonpath="{.items[0].metadata.name}")
kubectl port-forward $POD_NAME 9999:9999
Let's visit the web app one more time on http://127.0.0.1:9999 and find the following result:
Goodbye World!
Yeah, the updated web app worked very well!
Now we have successfully made our new component work. This could be easier as the developer only need to care about component update while the operator only need to care about application configuration.
You can delete your configurations easily with kubectl
:
$ kubectl delete applicationconfiguration first-app
applicationconfiguration.core.oam.dev "first-app" deleted
That will delete your application and all associated resources.
It will not delete the traits and the components, they are happily waiting your use in the next Application Configuration.
$ kubectl get traits,components
NAME AGE
trait.core.oam.dev/auto-scaler 31m
trait.core.oam.dev/empty 31m
trait.core.oam.dev/ingress 31m
trait.core.oam.dev/manual-scaler 31m
NAME AGE
component.core.oam.dev/alpine-replicable-task 19h
component.core.oam.dev/alpine-task 19h
component.core.oam.dev/hpa-example-replicated 19h
component.core.oam.dev/nginx-replicated 19h
component.core.oam.dev/nginx-singleton 19h
If you want to clean up your test environment and uninstall Rudr, you could do the following:
$ helm delete rudr
This will leave the CRDs and configurations intact.
NOTE: When you delete the CRDs, it will delete everything touching Open Application Model from configurations to secrets.
kubectl delete crd -l app.kubernetes.io/part-of=core.oam.dev
The above will delete the CRDs and clean up everything related with Open Application Model.
To learn more about Rudr, check out the Using Rudr guide.