SimpleExampleService
SimpleExampleService
is a service intended to demonstrate integration with the XOS kubernetes
service. SimpleExampleService
provides a SimpleExampleServiceInstance
model that generates and hosts a web page, displaying two text strings on the web page: a service_message
and a tenant_message
. Each time a SimpleExampleServiceInstance
is created, a corresponding KubernetesServiceInstance
will also be created which will in turn cause a Kubernetes pod to be created that runs an apache web server hosting the web page.
Destroying the SimpleExampleServiceInstance
will cause the linked KubernetesServiceInstance
to also be destroyed, which will in turn cause the Kubernetes pod to be cleaned up.
Limitations
This service does not yet demonstrate dataplane connectivity to subscribers.
Implementation
Inside the SimpleExampleService
repository's xos/synchronizer
directory, there are three key parts to the service.
The
models
directory. This directory contains the models that compriseSimpleExampleService
. The full text of the models are specified in a file,simpleexampleservice.xproto
. A summary of the models is below:SimpleExampleService
holds global service-wide settings, including aservice_message
, which appears in all web pages generated bySimpleExampleService
, and aservice_secret
that is installed into all container that run the web servers.ServiceInstanceWithCompute
is an intermediate model, inheriting fromServiceInstance
and being inherited bySimpleExampleServiceInstance
. It augmentsServiceInstance
with acompute_instance
field that may be used to link aServiceInstance
to theComputeServiceInstance
that will hold the compute resources necessary to implement theServiceInstance
. This model will likely be migrated to the XOS core at some point as more containerized VNFs are developed. For those familiar withCORD-5.0
,ServiceInstanceWithCompute
serves the same purpose thatTenantWithContainer
and/orServiceInstanceWithContainer
served inCORD-5.0
and prior releases.SimpleExampleServiceInstance
holds per-tenant settings, including atenant_message
. EachSimpleExampleServiceInstance
corresponds to one web server serving one web page. This model has relations forforeground_color
andbackground_color
that allow some additional customization of the served page.tenant_secret
is a secret that is installed into the container running the web serverColorNew
implements the color model used by theforeground_color
andbackground_color
fields ofSimpleExampleServiceInstance
.EmbeddedImageNew
allows embedded images to be attached to web pages. As the foreign key relation is from the embedded image to the service instance, this forms a many-to-one relation that allows many images to be attached to a single web page.
The
model_policies
directory contains a model policy. This model_policy executes code every time aSimpleExampleServiceInstance
is created, updated, or deleted.Rather than reproducing the full text of the code here, the actions are summarized below, and it's suggested the reader consult
model_policy_simpleexampleserviceinstance.py
for reference.When a new
SimpleExampleServiceInstance
is created, the model policy creates aKubernetesConfigMap
,KubernetesSecret
,KubernetesServiceInstance
and the necessary objects to mount the configmap and secret into the service instance. TheSimpleExampleServiceInstance
is updated with a relation to theKubernetesServiceInstance
, to make it easy to handle updates and deletions later.When a
SimpleExampleServiceInstance
is updated, the config map is modified to contain the new data, and the relatedKubernetesServiceInstance
is resaved, to cause it to be resynchronized by the Kubernetes synchronizer.When a
SimpleExampleServiceInstance
is deleted, the relatedKubernetesServiceInstance
is deleted.The
event_steps
directory contains an event step. This event step listens for Kafka events on the Kafka topicSimpleExampleEvent
. It assumes each event is a json-encoded dictionary containing aservice_instance_name
andtenant_message
. TheSimpleExampleServiceInstance
is looked up by name, thetenant_message
is updated, and the object is re-saved. Saving the object will then trigger the update model policy to run.
Demonstration
The following subsections work through a quick demonstration of SimpleExampleService
.
Prerequisites
This document assumes that you have already installed Kubernetes in your development environment. If you haven't done so already, see QuickStart.
Note: Depending on the method that was used to deploy your Kubernetes installation, your installation may require root privilege to interact with Kubernetes. If so, then you may need to use
sudo
with many of the commands in this tutorial, for examplesudo helm init
instead ofhelm init
.
Deploy the necessary profiles
It's necessary for us to deploy three helm charts, xos-core
, base-kubernetes
. and demo-simpleexampleservice
.
If you followed the quickstart, then you should already have the proper helm charts installed and you may skip this subsection. If you're joining this guide after using an alternative method of installing Kubernetes, then you'll want to proceed with installing the following helm charts:
Note: If you've already installed a different set of XOS profile helm charts, such as the
rcord-lite
profile, then you may wish to uninstall those, as there's no guarantee that thebase-kubernetes
anddemo-simpleexampleservice
helm-charts can be layered on top of an existing XOS profile.
# Go into the helm-charts repository
cd ~/cord/helm-charts
# Initialize helm
helm init
# Install the xos-core helm chart
helm dep update xos-core
helm install xos-core -n xos-core
# Install the base-kubernetes helm chart
helm dep update xos-profiles/base-kubernetes
helm install xos-profiles/base-kubernetes -n base-kubernetes
# Install the demo-simpleexampleservice helm chart
helm dep update xos-profiles/demo-simpleexampleservice
helm install xos-profiles/demo-simpleexampleservice -n demo-simpleexampleservice
The helm charts above install successive layers of CORD. The first chart, xos-core
installs core components such as the XOS core, database, TOSCA engine, etc. The second chart, base-kubernetes
installs the XOS Kubernetes Service, which provides modeling and synchronizers for instantiating Kubernetes resources using the XOS data model. The final helm chart, demo-simpleexampleservice
installs the synchronizer for SimpleExampleService
, including registering models with the core.
Note: It will take some time for the various helm charts to deploy and the containers to come online. We recommend using
kubectl get pods
to explore the state of the system during deployment. In particular, note the presence oftosca-loader
containers. These containers are responsible for running TOSCA that configures services in the stack. Thetosca-loaders
may error and retry several times as they wait for services to be dynamically loaded. This is normal, and eventually thetosca-loader
containers will enter theCompleted
state.
Use kubectl get pods
to verify that all containers in the profile are successful and none are in error state. At this point, we've installed all of the necessary infrastructure to support SimpleExampleService
, such as registering its models and starting its synchronizer, but we haven't actually provisioned a SimpleExampleServiceInstance
yet. We will do that step next.
Create a SimpleExampleServiceInstance
using TOSCA
This step will provision a SimpleExampleServiceInstance
. This ServiceInstance will be responsible for generating a web page and hosting that we page using resoucres of the Kubernetes service. SimpleExampleService
is a multi-tenant service, and the operator may provision man SimpleExampleServiceInstance
, each one an individual tenant of the service and each one generating a custom web page. This demo will take you through creating one ServiceInstance, and leave creating further ServiceInstances as an exercise.
We will demonstrate using TOSCA to create the SimpleExampleServiceInstance
, but this is not the only mechanism available. The steps here could alternatively be done in the XOS GUI, by using the XOS REST or gRPC APIs, or implemented as part of the model policies of some other service.
- Check out the SimpleExampleService repository
If you've already checked out the CORD code, for example using repo, then make note the path to the simpleexampleservice
code as we'll be using it in a few minutes:
SIMPLEEXAMPLESERVICE_PATH=~/cord/orchestration/xos_services/simpleexampleservice
Otherwise, check out the simpleexampleservice repository now:
cd ~
git clone https://github.com/opencord/simpleexampleservice
SIMPLEEXAMPLESERVICE_PATH=~/simpleexampleservice
- Set your username and password.
# Customize as necessary for your deployment.
USERNAME=admin@opencord.org
PASSWORD=letmein
- Run the TOSCA recipe to create a
SimpleExampleServiceInstance
.
TOSCA_URL=http://$( hostname ):30007
TOSCA_FN=$SIMPLEEXAMPLESERVICE_PATH/xos/examples/SimpleExampleServiceInstance.yaml
curl -H "xos-username: $USERNAME" -H "xos-password: $PASSWORD" -X POST --data-binary @$TOSCA_FN $TOSCA_URL/run
Please wait a few seconds for model policies to run, the Kubernetes synchronizer to instantiate containers, etc.
View the status.
CHAMELEON_URL=http://$( hostname ):30006
python $SIMPLEEXAMPLESERVICE_PATH/xos/examples/show-instances.py $CHAMELEON_URL $USERNAME $PASSWORD
Note: You may have to re-execute the above a few times while waiting for the objects to be created. If all is successful, eventually you will see an IP address assigned to the service instance.
View the web page
Enter one of the other Kubernetes containers (
kubectl get pods
can be used to retrieve a list), any container such as one of the synchronizer containers will do, and perform a curl on the IP address obtained in the previous step.
Use the Event Bus to modify a SimpleExampleServiceInstace
The event bus is an optional mechanism that may be used to interact with services. SimpleExampleService
implements a single EventStep
, which listens on a Kafka topic and allows the tenant_message
to be updated.
- Launch the Kafka Helm Chart, if you have not already done so:
helm repo add incubator http://storage.googleapis.com/kubernetes-charts-incubator
helm install --name cord-kafka --set replicas=1 incubator/kafka
Wait for Kafka to be ready. Use
kubectl get pods
to make sure the Kafka containers are in Running state.Send an Event to update a web page
Enter one of the other Kubernetes containers, install the kafka library (
pip install kafka
) and execute the follow python:
import json
from kafka import KafkaProducer
producer = KafkaProducer(bootstrap_servers="cord-kafka")
producer.send("SimpleExampleEvent", json.dumps({"service_instance": "My Simple Example Service Instance", "tenant_message": "Earth"}))
producer.flush()
View the web page
Enter one of the other Kubernetes containers, any container such as one of the synchronizer containers will do, and perform a curl on the same IP address obtained in previous section. It may take up to a few minutes for the container to be updated with the new state from the event.