Developing and Publishing a Flame App for Great Bear
This guide gives an example of how to develop the Flame application for Great Bear. Flame is an open source platform from Cisco that enables developers to compose and deploy Federated Learning training workloads easily.
By building a Flame app and running at the edge on Great Bear, you can:
- train global machine learning models
- keep data at the edge site, and
- preserve privacy.
The Flame app itself runs as a ‘Flamelet’ in non-orchestration mode, which means that it reaches out to the Flame Control Plane and registers itself for a Federated Learning task.
In this tutorial you are going to clone the Flame open source repository, and build the associated docker image. You will then package the docker image with a Helm chart and add the relevant data to upload and run this as a Great Bear application.
Prerequisites
This guide assumes that:
- You either have access to an already deployed instance of the Flame Control Plane running in the cloud, or that you have deployed your own Flame Control Plane.
- You are familiar with using docker and creating docker images, creating Helm charts for Kubernetes, and deploying applications to Kubernetes clusters using Helm charts.
- You have docker and helm installed.
- You have the required access credentials for Great Bear. For more information on the development process for Great Bear, see Creating, Publishing and Deleting Applications.
Build and upload the Flame docker image
-
First step is to clone the Flame open source repository:
git clone https://github.com/cisco-open/flame.git
-
Once the repository has been cloned, navigate into the
fiab
directory insideflame
:cd flame/fiab
-
Next, build the Flame docker image with the command:
./build-image.sh
-
After the docker image is built, check that the image has been created by running:
docker images | head -2
Which should give output similar to the following:
REPOSITORY TAG IMAGE ID CREATED SIZE flame latest 2b53cc1e6644 1 minute ago 4.27GB
-
In order to upload this image to Great Bear, you first need to tag it by running following command, replacing <tenant-id> with the Application Store Tenant ID provided to you by Cisco:
docker tag flame repo.greatbear.io/<tenant-id>/flame:0.0.1
-
Log in to the Great Bear system using docker. To do this, run the following command, replacing
, and with the credentials provided to you by Cisco: docker login --username=<tenant-registry-username> --password=<tenant-registry-password> <tenant-registry-url>
Alternatively, you can exclude the username and password from this command, and enter them when prompted.
-
Push this image to the Great Bear repository. Run the following command, replacing
, <application-name>, and <version-number> with the values used in the previous step: docker push <tenant-registry-url>/<application-name>:<version-number>
In this case, use
flame:0.0.1
for the application name and version.
Create the Great Bear Application Package (GBAP)
-
With the Dockerfile created, you can now move onto creating the GBAP, used to publish our application to the Great Bear Application Store for subsequent deployment to Great Bear managed sites through the Great Bear Dashboard.
-
Follow the steps to install and configure the Great Bear Packaging SDK tool.
-
In a location of your choice create a new directory called
flame-app
where you will create and save the GBAP. -
Use the SDK tool to create a new GBAP instance within your
flame-app
application directory.gbear app create flame-app/GBAP
Enter the chart name, name of the application, and the description of the application when prompted:
Creating a GBAP with required fields.... Enter the chart name: flame-app Enter the chart version [SemVer2 MAJOR.MINOR.PATCH], (leave empty for default: 0.0.1): Enter the application name: Flame App Enter the application description: Flame is a platform that enables developers to compose and deploy Federated Learning training workloads easily. Successfully created a GBAP in path flame-app/GBAP
-
The SDK tool has now created a boiler plate GBAP filesystem tree:
flame-app/GBAP ├── Chart.yaml ├── gbear │ └── appmetadata.yaml
Author the GBAP Assets
The GBAP contains the following two fundamental elements:
- A Helm Chart to describe a set of Kubernetes resources used to deploy the application at Great Bear managed sites.
- Great Bear specific application metadata (gbear/appmetadata), containing:
- Properties used to render the application in the Great Bear Application Store
- Properties used to define application parameters which can be overridden when deploying the Helm Chart.
For further details on the GBAP structure, see Great Bear Application Package Guide
Extend the GBAP Helm Chart
The final things that you need to build are the elements of the Helm Chart for deploying the container image to Great Bear sites as an application. Helm Charts describe Kubernetes applications and their components: rather than creating YAML files for every application, you can provide a Helm chart and use Helm to deploy the application for you. Therefore, the next steps are to create a very basic Helm Chart that will contain a template for the Kubernetes resource that will form your application, and a values file to populate the template placeholder values.
A Chart.yaml file is required for any Helm Chart, and contains high level information about the application (you can find out more in the Helm Documentation). You can set a number of Great Bear specific parameters in the Helm chart of your application.
-
The Packaging SDK has created the root Chart file
Charts.yaml
within the GBAP filesystem tree.apiVersion: v2 name: flame-app version: 0.0.1
Create the Helm values file
-
Inside the
flame-app/GBAP
directory, create a file calledvalues.yaml
. This file contains the default values for our Flame application. It also defines the data needed for the application to pull the image, such as repository location and pull secrets. When creating this file, replace< tenant-registry-url >
in therepository
value with the URL provided to you by Cisco.# flame-app/values.yaml replicaCount: 1 config: CONTROL_PLANE_API_SERVER_URL: "" CONTROL_PLANE_NOTIFIER_URL: "" FLAME_TASK_ID: "" FLAME_TASK_KEY: "" image: repository: < tenant-registry-url >/flame pullPolicy: Always tag: 0.0.1 imagePullSecrets: - name: gbear-harbor-pull nameOverride: "" fullnameOverride: "flame-app"
Create the Helm template files
The next step is to create the template files that will:
- create your Kubernetes deployment
- the service endpoint for the deployment, and
- some template helpers that are re-used throughout the chart.
Complete the following steps.
-
Inside the
flame-app/GBAP
directory, create a new directory calledtemplates
-
In the new
templates
directory, create a file called_helpers.tpl
, which will hold some template helpers that you can re-use throughout the chart. Your_helpers.tpl
file should contain the following helpers:# flame-app/templates/_helpers.tpl {{/* Expand the name of the chart. */}} {{- define "app.name" -}} {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} {{- end }} {{/* Create a default fully qualified app name. We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). If release name contains chart name it will be used as a full name. */}} {{- define "app.fullname" -}} {{- if .Values.fullnameOverride }} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} {{- else }} {{- $name := default .Chart.Name .Values.nameOverride }} {{- if contains $name .Release.Name }} {{- .Release.Name | trunc 63 | trimSuffix "-" }} {{- else }} {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} {{- end }} {{- end }} {{- end }} {{/* Create chart name and version as used by the chart label. */}} {{- define "app.chart" -}} {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} {{- end }} {{/* Common labels */}} {{- define "app.labels" -}} helm.sh/chart: {{ include "app.chart" . }} {{ include "app.selectorLabels" . }} {{- if .Chart.AppVersion }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} {{- end }} app.kubernetes.io/managed-by: {{ .Release.Service }} {{- end }} {{/* Selector labels */}} {{- define "app.selectorLabels" -}} app.kubernetes.io/name: {{ include "app.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} {{/* Create the name of the service account to use */}} {{- define "app.serviceAccountName" -}} {{- if .Values.serviceAccount.create }} {{- default (include "app.fullname" .) .Values.serviceAccount.name }} {{- else }} {{- default "default" .Values.serviceAccount.name }} {{- end }} {{- end }}
-
In the
templates
directory, create thedeployment.yaml
file, which provides a basic manifest for creating the Kubernetes deployment your Flame application. It also sets the FLAME_TASK_ID and FLAME_TASK_KEY environment variables to the user-defined input when deploying the application, and runs the command to start the Flame app in non-orchestration mode with CONTROL_PLANE_API_SERVER_URL and CONTROL_PLANE_NOTIFIER_URL as arguments. It also defines and mounts a volume where the data from the Flame training can be placed. Therefore, in this case, thedeployment.yaml
should contain:# flame-app/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "app.fullname" . }} labels: {{- include "app.labels" . | nindent 4 }} spec: replicas: 1 selector: matchLabels: {{- include "app.selectorLabels" . | nindent 6 }} template: metadata: labels: {{- include "app.selectorLabels" . | nindent 8 }} spec: {{- with .Values.imagePullSecrets }} imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} containers: - name: {{ .Chart.Name }} volumeMounts: - mountPath: /flame/data name: volume-flamelet image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" imagePullPolicy: Always env: - name: FLAME_TASK_ID value: {{ .Values.config.FLAME_TASK_ID }} - name: FLAME_TASK_KEY value: {{ .Values.config.FLAME_TASK_KEY }} command: ["/usr/bin/flamelet", "-a", "{{ .Values.config.CONTROL_PLANE_API_SERVER_URL }}", "-n", "{{ .Values.config.CONTROL_PLANE_NOTIFIER_URL }}", "--insecure"] volumes: - name: volume-flamelet hostPath: path: /home/vagrant/data restartPolicy: Always status: {}
Customise the Great Bear Application Metadata
-
The SDK tool has generated the following boiler plate
gbear/appmetadata.yaml
file, the application metadata file to include the following properties, allowing the user to set their own values for CONTROL_PLANE_API_SERVER_URL, CONTROL_PLANE_NOTIFIER_URL, FLAME_TASK_ID and FLAME_TASK_KEY when they deploy the app via the Application Store.title: Flame App description: Flame is a platform that enables developers to compose and deploy Federated Learning training workloads easily. icon: https://github.com/cisco-open/flame/raw/main/docs/images/logo.png configuration: - name: CONTROL_PLANE_API_SERVER_URL title: The URL or IP address to connect to the API Server component in the Flame Control Plane type: String - name: CONTROL_PLANE_NOTIFIER_URL title: The URL or IP address to connect to the Notifier component in the Flame Control Plane (Cloud Cluster) type: String - name: FLAME_TASK_ID title: A Task ID is linked to a Job ID and is generated when a job has been started type: String - name: FLAME_TASK_KEY title: A Task Key is an ID that the user can chose when deploying the flame app type: String
Validate the Application Package
-
By now you should now have a complete application, and you can test that everything is setup correctly by running the following two commands in the
flame-app/GBAP
directory:helm lint
helm install flame-app . --dry-run --debug
Assuming everything is setup correctly and the previous helm commands do not report any errors, you can now move onto validate the complete GBAP structure.
-
Now that we have finished authoring our GBAP assets and tested the embedded Helm Chart works, we can use the SDK tool to perform a final validation of the complete GBAP contents:
$ gbear app validate flame-app/GBAP Validating Package: charts/ -- Validating Application Metadata... -- Validating Chart Dependencies... -- Validating Kubernetes Resource Labels... Validation Complete: Application Metadata: Passed (Errors: 0, Warnings: 0) Chart Dependencies: Passed (Errors: 0, Warnings: 0) Kubernetes Resource Labels: Passed (Errors: 0, Warnings: 0)
For further details on GBAP validation, see Validate an Application Package.
Publish to the Great Bear Application Store
Assuming that the command above didn’t give errors, you can move onto publishing the flame app to Great Bear by Publish an Application Package.
Once published, the Flame application will be available in the Application Store: