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
modelsdirectory. 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:SimpleExampleServiceholds global service-wide settings, including aservice_message, which appears in all web pages generated bySimpleExampleService, and aservice_secretthat is installed into all container that run the web servers.ServiceInstanceWithComputeis an intermediate model, inheriting fromServiceInstanceand being inherited bySimpleExampleServiceInstance. It augmentsServiceInstancewith acompute_instancefield that may be used to link aServiceInstanceto theComputeServiceInstancethat 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,ServiceInstanceWithComputeserves the same purpose thatTenantWithContainerand/orServiceInstanceWithContainerserved inCORD-5.0and prior releases.SimpleExampleServiceInstanceholds per-tenant settings, including atenant_message. EachSimpleExampleServiceInstancecorresponds to one web server serving one web page. This model has relations forforeground_colorandbackground_colorthat allow some additional customization of the served page.tenant_secretis a secret that is installed into the container running the web serverColorNewimplements the color model used by theforeground_colorandbackground_colorfields ofSimpleExampleServiceInstance.EmbeddedImageNewallows 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_policiesdirectory contains a model policy. This model_policy executes code every time aSimpleExampleServiceInstanceis 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.pyfor reference.When a new
SimpleExampleServiceInstanceis created, the model policy creates aKubernetesConfigMap,KubernetesSecret,KubernetesServiceInstanceand the necessary objects to mount the configmap and secret into the service instance. TheSimpleExampleServiceInstanceis updated with a relation to theKubernetesServiceInstance, to make it easy to handle updates and deletions later.When a
SimpleExampleServiceInstanceis updated, the config map is modified to contain the new data, and the relatedKubernetesServiceInstanceis resaved, to cause it to be resynchronized by the Kubernetes synchronizer.When a
SimpleExampleServiceInstanceis deleted, the relatedKubernetesServiceInstanceis deleted.The
event_stepsdirectory 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_nameandtenant_message. TheSimpleExampleServiceInstanceis looked up by name, thetenant_messageis 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
sudowith many of the commands in this tutorial, for examplesudo helm initinstead 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-liteprofile, then you may wish to uninstall those, as there's no guarantee that thebase-kubernetesanddemo-simpleexampleservicehelm-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 podsto explore the state of the system during deployment. In particular, note the presence oftosca-loadercontainers. These containers are responsible for running TOSCA that configures services in the stack. Thetosca-loadersmay error and retry several times as they wait for services to be dynamically loaded. This is normal, and eventually thetosca-loadercontainers will enter theCompletedstate.
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, where kubectl get pods can be
used to retrieve a list. Any of the containers will do (e.g., one of the synchronizer
containers).
kubectl exec -it <pod-name> sh
From the shell prompt, perform a curl on the IP address obtained in the previous
step. You might need to install curl first. If so, try using either apk add curl or
apt-get install curl depending on whether the container you're using is based on
alpine or ubuntu.
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.
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 confluent_kafka import Producer
producer_config = {"bootstrap.servers": "cord-kafka"}
producer = Producer(**producer_config)
event = {"service_instance": "My Simple Example Service Instance", "tenant_message": "Earth"}
producer.produce("SimpleExampleEvent", json.dumps(event), key=event["service_instance"])
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.