{"id":76006,"date":"2019-04-01T09:00:05","date_gmt":"2019-04-01T16:00:05","guid":{"rendered":"https:\/\/cloudblogs.microsoft.com\/opensource\/?p=76006"},"modified":"2025-06-27T09:37:56","modified_gmt":"2025-06-27T16:37:56","slug":"brigade-kubernetes-serverless-tutorial","status":"publish","type":"post","link":"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/","title":{"rendered":"Brigade tutorial: Instant scaling on demand with serverless Kubernetes"},"content":{"rendered":"\n<p>Microservices built on Kubernetes are fast becoming one of the core scenarios where computing is done, and Kubernetes development and operations skills are therefore becoming a larger part of any cloud-native toolset. This article shows how to use Brigade, along with other tools from the Cloud Native Computing Foundation (CNCF), to build a Kubernetes-native application that listens for events and then runs serverless pipelines on Virtual Kubelet instances, each of which are dynamically created (and recycled when the pipeline is done).<\/p>\n\n\n\n<p>The&nbsp;<a href=\"https:\/\/www.cncf.io\/sandbox-projects\/\" target=\"_blank\" rel=\"noreferrer noopener\">CNCF sandbox projects<\/a>&nbsp;used in this article are:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><a href=\"https:\/\/cloudevents.io\/\" target=\"_blank\" rel=\"noreferrer noopener\">Cloud Events<\/a>, a specification for describing event data in a common way<\/li>\n\n\n\n<li><a href=\"https:\/\/brigade.sh\/\" target=\"_blank\" rel=\"noreferrer noopener\">Brigade<\/a>, a Kubernetes-native service that creates structured container pipelines<\/li>\n\n\n\n<li><a href=\"https:\/\/virtual-kubelet.io\/\" target=\"_blank\" rel=\"noreferrer noopener\">Virtual Kubelet<\/a>, an open-source Kubernetes kubelet implementation that defers its internal execution to another system.<\/li>\n<\/ol>\n\n\n\n<p>Both Brigade and an implementation of Virtual Kubelet based on Azure Container Instances (ACI) are installed using the CNCF&nbsp;<a href=\"https:\/\/helm.sh\/\" target=\"_blank\" rel=\"noreferrer noopener\">Helm<\/a>&nbsp;project, an installer for Kubernetes applications.<\/p>\n\n\n\n<p>In addition, we were&nbsp;<a href=\"https:\/\/cloudblogs.microsoft.com\/opensource\/2019\/03\/28\/announcing-brigade-1-0-new-kind-of-distributed-application\/\" target=\"_blank\" rel=\"noreferrer noopener\">happy to announce last week that Brigade<\/a>&nbsp;is now a CNCF&nbsp;<a href=\"https:\/\/www.cncf.io\/sandbox-projects\/\" target=\"_blank\" rel=\"noreferrer noopener\">sandbox<\/a>&nbsp;project, a major step for the Brigade community, collaborating on a first-class scripting runtime for constructing container pipelines.<\/p>\n\n\n\n<p>Why these projects? The nature of event-driven applications is that the load is often unpredictable, and allocating compute power for a specific workload can be quite difficult, and inefficient from a cost perspective. Brigade listens for Cloud Events and manages the pipelines in an Kubernetes cluster, but handling unexpected load is where we introduce Virtual Kubelet \u2014 a CNCF project that allows us to schedule Kubernetes pods on virtual nodes, backed by components other than VMs. Virtual Kubelet has multiple providers available, with one of them being Azure Container Instances (ACI) \u2014 a service that allows you to schedule and execute containers on Azure\u2019s infrastructure, billed by the second. It turns out that this is a really good match, since Brigade allows you to execute container pipelines, and events often do not require long periods of compute; they can be \u201cbursty.\u201d<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"How-does-Brigade-work\">How does Brigade work?<\/h2>\n\n\n\n<p>Brigade uses a few components to work:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>a controller, which looks for events in a certain namespace.<\/li>\n\n\n\n<li>a gateway, which translates external events (which can come from a git repo, webhooks, or any other event source).<\/li>\n\n\n\n<li>optionally, an API to help us interact with CLIs or web frontends.<\/li>\n<\/ul>\n\n\n\n<p>Then, when an event is fired, the Brigade controller will schedule a worker pod, which executes the JavaScript pipeline of your project, and starts scheduling all the jobs defined.<\/p>\n\n\n\n<p>This is the interesting part \u2014 you don\u2019t have to provision infrastructure for the jobs you define \u2014 they can be scheduled by Virtual Kubelet on Azure Container Instances, and be billed by the second for the time when your jobs run.<\/p>\n\n\n\n<p>You can have a number of nodes for your regular workloads, and use Brigade with Virtual Kubelet for the event-driven pipelines. You can run as many jobs in parallel as needed, without worrying about provisioning infrastructure, or the cost associated with it.<br>On top of that, you can use any Kubernetes in any cloud, or on-premises, and scale through Azure when needed.<\/p>\n\n\n\n<p>By the end of this article, we will have a Kubernetes cluster with one actual VM node, a Virtual Kubelet node backed by ACI, and Brigade, configured to schedule jobs on the virtual node.<\/p>\n\n\n\n<p>If you are interested, you can&nbsp;<a href=\"https:\/\/docs.brigade.sh\/topics\/design\/\" target=\"_blank\" rel=\"noreferrer noopener\">read more about the Brigade architecture in this document<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"Configuring-Brigade-Virtual-Kubelet-and-ACI\">Configuring Brigade, Virtual Kubelet, and ACI<\/h2>\n\n\n\n<p>Here\u2019s a list of the things we are going to need:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>first, you need a Kubernetes cluster \u2014 if you don\u2019t already have one, you can\u00a0<a href=\"https:\/\/azure.microsoft.com\/en-us\/free\/\" target=\"_blank\" rel=\"noreferrer noopener\">get started with a free Azure subscription here<\/a>, use a Minikube cluster, or any other cloud-hosted Kubernetes cluster.<\/li>\n<\/ul>\n\n\n\n<p>Note that if you use a Minikube cluster, you won\u2019t be able to create services with public IPs, or publicly exposed ingress objects. You can still follow along, and manually trigger jobs through the Brigade CLI.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>we also need to\u00a0<a href=\"https:\/\/helm.sh\/docs\/using_helm\/\" target=\"_blank\" rel=\"noreferrer noopener\">configure Helm<\/a>.<\/li>\n\n\n\n<li>optionally, you can configure an\u00a0<a href=\"https:\/\/github.com\/kubernetes\/ingress-nginx\" target=\"_blank\" rel=\"noreferrer noopener\">Nginx ingress controller<\/a>\u00a0and\u00a0<a href=\"https:\/\/github.com\/jetstack\/cert-manager\/\" target=\"_blank\" rel=\"noreferrer noopener\">Cert-Manager<\/a>\u00a0to automatically provision TLS ingress objects in your cluster,\u00a0as described in the Brigade documentation.<\/li>\n\n\n\n<li>the document above also explains how to deploy Brigade if you configure a cluster with ingress and TLS. If you don\u2019t want to configure an ingress controller, deploying Brigade can be done with Helm:<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n$ helm repo add brigade https:\/\/azure.github.io\/brigade-charts\n$ helm install brigade\/brigade --name brigade --set genericGateway.enabled=true --set genericGateway.service.type=<LoadBalancer\/ClusterIP>\n\n<\/pre><\/div>\n\n\n<p>If you have a cloud-hosted Kubernetes cluster, it should be able to automatically provision&nbsp;<code>LoadBalancer<\/code>&nbsp;type services with a public IP. If not, you can choose a&nbsp;<code>ClusterIP<\/code>&nbsp;type service, but keep in mind that this service will&nbsp;<em>not<\/em>&nbsp;be publicly exposed, and triggering jobs will only be available through the&nbsp;<code>brig<\/code>&nbsp;CLI, or from inside the cluster.<\/p>\n\n\n\n<p>The setup we are using for this article is the one described in&nbsp;the Brigade documentation that covers configuring ingress objects with TLS. Here\u2019s how the&nbsp;<code>brigade<\/code>&nbsp;namespace should look:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n$ kubectl get deployment,service,ingress --namespace brigade\nNAME                                                    DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE\ndeployment.extensions\/brigade-brigade-api               1         1         1            1           62m\ndeployment.extensions\/brigade-brigade-ctrl              1         1         1            1           62m\ndeployment.extensions\/brigade-brigade-generic-gateway   1         1         1            1           62m\ndeployment.extensions\/brigade-kashti                    1         1         1            1           62m\n\nNAME                                      TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE\nservice\/brigade-brigade-api               ClusterIP   10.0.169.168   <none>        7745\/TCP   62m\nservice\/brigade-brigade-generic-gateway   ClusterIP   10.0.0.133     <none>        8081\/TCP   62m\nservice\/brigade-kashti                    ClusterIP   10.0.225.37    <none>        80\/TCP     62m\n\nNAME                                                 HOSTS                              ADDRESS   PORTS     AGE\ningress.extensions\/brigade-brigade-generic-gateway   brigade-events-test.kube.radu.sh             80, 443   62m\n<\/pre><\/div>\n\n\n<p>Note that the subdomain used for provisioning ingress objects is&nbsp;<code>*.kube.radu.sh<\/code>&nbsp;\u2013 if you own a domain, and have access to configuring the DNS for it, you should be able to setup the ingress controller according to the document referenced above.<\/p>\n\n\n\n<p>This ingress endpoint allows Brigade to accept events in the&nbsp;<a href=\"https:\/\/cloudevents.io\/\" target=\"_blank\" rel=\"noreferrer noopener\">CloudEvents v2 format<\/a>, a CNCF industry specification which formalizes event schemas used for different systems.<\/p>\n\n\n\n<p>Note that there is another endpoint in the same Brigade gateway which allows arbitrary JSON schema events, so if your system produces other JSON schemas, you can use them without changing the format. See the&nbsp;document about the Brigade generic gateway.<\/p>\n\n\n\n<p>The cluster provisioned for this article is a 1 node AKS cluster:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n$ kubectl get nodes\nNAME                       STATUS   ROLES   AGE   VERSION\naks-agentpool-35064155-0   Ready    agent   19h   v1.12.6\n\n$ kubectl top nodes\nNAME                       CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   \naks-agentpool-35064155-0   1110m        57%    1579Mi          30%  \n<\/pre><\/div>\n\n\n<p>This means we\u2019re only paying for 1 virtual machine node (as the Kubernetes control plane in AKS is free). So how would we schedule tens, or hundreds of jobs on this small, 1 node cluster, which is already at 57% CPU load? We are going to do this using Virtual Kubelet and Azure Container Instances.<\/p>\n\n\n\n<p>For the next part, you will need an&nbsp;<a href=\"https:\/\/azure.microsoft.com\/en-us\/free\/\" target=\"_blank\" rel=\"noreferrer noopener\">Azure subscription<\/a>&nbsp;which has access to creating Container Instances, as well as access to creating an Azure Service Principal.<\/p>\n\n\n\n<p>If you are running your Kubernetes cluster on AKS, deploying Virtual Kubelet is extremely easy:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n$ az aks install-connector --resource-group <aks cluster rg> --name <aks cluster name>\n<\/pre><\/div>\n\n\n<p>Keep in mind that your subscription must be able to create container instances \u2013 to enable this provider, run&nbsp;<code>az provider register -n Microsoft.ContainerInstance<\/code>.<\/p>\n\n\n\n<p>Now, if everything worked correctly, we should have a second node in our cluster,&nbsp;<code>virtual-kubelet<\/code>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n$ kubectl get nodes\nNAME                       STATUS   ROLES   AGE   VERSION\naks-agentpool-35064155-0   Ready    agent   40h   v1.12.6\nvirtual-kubelet            Ready    agent   11h   v1.13.1-vk-v0.7.4-44-g4f3bd20e-dev\n<\/pre><\/div>\n\n\n<p>Now that everything is up and running, let\u2019s create a new Brigade project:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n$ brig project create\n? Project Name testing\/brigade-vk\n\n$ brig project list\nNAME              \tID\ntesting\/brigade-vk\tbrigade-f21cf24721ff5303ba21dd5360af71d447d0549b844329206d780c\n<\/pre><\/div>\n\n\n<p>There are a couple things to note here:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>we are not going to create a CI pipeline, so we are not going to use the clone URL, and we are setting the VCS Sidecar to\u00a0<code>NONE<\/code>.<\/li>\n<\/ul>\n\n\n\n<p>If you plan to use the Brigade gateway for CloudEvents, you can find more details about it in&nbsp;the Brigade documentation.<\/p>\n\n\n\n<p>Now let\u2019s use the project we just created to test a pipeline. We need a JavaScript pipeline that creates a Brigade job, and schedules it on the&nbsp;<code>virtual-kubelet<\/code>&nbsp;node we just created:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n\/\/ save this as brigade.js\nconst { events, Job } = require('@azure\/brigadier')\n\nevents.on(\"exec\", (brigadeEvent, project) => {\n  var hello = new Job(\"linux-job\")\n  hello.image = \"alpine:3.4\"\n  hello.tasks = [\"echo Hello Brigade from Azure\"]\n  \n  hello.host.name = \"virtual-kubelet\"\n  hello.resourceRequests.cpu = \"1\"\n  hello.resourceRequests.memory = \"1G\"\n  \n  hello.run()\n})\n<\/pre><\/div>\n\n\n<p>Breaking down the&nbsp;<code>brigade.js<\/code>&nbsp;file:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>we first import\u00a0<a href=\"https:\/\/www.npmjs.com\/package\/@azure\/brigadier\" target=\"_blank\" rel=\"noreferrer noopener\"><code>@azure\/brigadier<\/code><\/a>\u00a0library, which contains all Brigade job definitions.<\/li>\n\n\n\n<li>then, when an\u00a0<code>exec<\/code>\u00a0event is triggered, we create a new Job, and we run a single task, which echoes a message.<\/li>\n\n\n\n<li>we schedule the job to run on the virtual node we created, and set resource requests for CPU and memory.<\/li>\n\n\n\n<li>then we run start the job.<\/li>\n<\/ul>\n\n\n\n<p>Triggering an&nbsp;<code>exec<\/code>&nbsp;event can be done through the&nbsp;<code>brig<\/code>&nbsp;CLI, so if your setup doesn\u2019t include public IP services, or ingresses, you can still test this, provided you configured Virtual Kubelet correctly:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n$ brig exec testing\/brigade-vk -f brigade.js\nEvent created. Waiting for worker pod named \"brigade-worker-01d5c5g11spb27fzjwkjs7gktw\".\nBuild: 01d5c5g11spb27fzjwkjs7gktw, Worker: brigade-worker-01d5c5g11spb27fzjwkjs7gktw\nprestart: no dependencies file found\nprestart: loading script from \/etc\/brigade\/script\n[brigade] brigade-worker version: 0.20.0\n[brigade:k8s] Creating secret linux-job-01d5c5g11spb27fzjwkjs7gktw\n[brigade:k8s] Creating pod linux-job-01d5c5g11spb27fzjwkjs7gktw\n[brigade:k8s] Timeout set at 900000\n[brigade:k8s] Pod not yet scheduled\n[brigade:k8s] brigade\/linux-job-01d5c5g11spb27fzjwkjs7gktw phase Pending\n[brigade:k8s] brigade\/linux-job-01d5c5g11spb27fzjwkjs7gktw phase Succeeded\ndone\n<\/pre><\/div>\n\n\n<p>So let\u2019s see what is happening in our cluster when a job is scheduled:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n$ kubectl get pods\nNAME                                               READY   STATUS       RESTARTS   AGE\nbrigade-worker-01d5c58r90v5ernrsy6dkvcf5n          0\/1     Completed    0          65s\nlinux-job-01d5c58r90v5ernrsy6dkvcf5n               0\/1     Terminated   0          29s\n<\/pre><\/div>\n\n\n<p>The pods that we are interested in are:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>the Brigade worker \u2013 as we said before, this pod is scheduled whenever an event is triggered, it executes the\u00a0<code>brigade.js<\/code>\u00a0file associated with a project, and creates all the jobs defined.<\/li>\n\n\n\n<li>the\u00a0<code>linux-job<\/code>\u00a0pod is our job that was scheduled on the Virtual Kubelet node.<\/li>\n<\/ul>\n\n\n\n<p>Checking the logs of the job pod:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n$ kubectl logs linux-job-01d5c58r90v5ernrsy6dkvcf5n\nHello Brigade from Azure\n\n<\/pre><\/div>\n\n\n<p>Since the pod was scheduled on the Virtual Kubelet node, which is backed by Azure Container Instances, we should also see the container created in the Azure portal:<\/p>\n\n\n<figure class=\"wp-block-image aligncenter\"><img decoding=\"async\" src=\"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-1-1024x178.webp\" alt=\"container created in the Azure portal\" class=\"wp-image-76291 webp-format\" srcset=\"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-1.webp 2273w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-1-300x52.webp 300w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-1-1024x178.webp 1024w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-1-768x133.webp 768w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-1-1536x267.webp 1536w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-1-2048x356.webp 2048w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-1-330x57.webp 330w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-1-800x139.webp 800w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-1-400x70.webp 400w\" data-orig-src=\"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-1.png\" data-orig-srcset=\"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-1.png 2273w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-1-300x52.png 300w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-1-1024x178.png 1024w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-1-768x133.png 768w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-1-1536x267.png 1536w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-1-2048x356.png 2048w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-1-330x57.png 330w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-1-800x139.png 800w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-1-400x70.png 400w\"><\/figure>\n\n\n\n<p>So at this point, we have all pieces put together.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"Scaling-parallelized-jobs-with-Brigade-and-Virtual-Kubelet\">Scaling parallelized jobs with Brigade and Virtual Kubelet<\/h2>\n\n\n\n<p>Now let\u2019s assume we have a parallel job that we need to execute \u2013 it could be&nbsp;<a href=\"https:\/\/github.com\/seanmck\/aci-wordcount\" target=\"_blank\" rel=\"noreferrer noopener\">counting utterances of words in a given text<\/a>, it could be training a machine learning model using a large data set, or any job that can be parallelized.<\/p>\n\n\n\n<p>If we only have a relatively small number of executions (countdown, word count, data set size), the job can be performed sequentially, by a single instance \u2013 otherwise, we can parallelize the job, and see vastly improved results.<\/p>\n\n\n\n<p>To keep things simple, for our example, we only need a counter \u2013 and see how to parallelize this using multiple Brigade jobs. The container we are going to run as a Brigade job reads two environment variables,&nbsp;<code>COUNTDOWN_FROM<\/code>, and&nbsp;<code>COUNTDOWN_TO<\/code>, and starts a loop where it echoes the current count, then sleeps for one second, simulating a process that takes one second to complete.<\/p>\n\n\n\n<p>So let\u2019s say we need to execute the process 200 times \u2013 sequentially, it would take 200 seconds, plus the time needed to schedule the pod, pull the image, and start the execution.<\/p>\n\n\n\n<p>In the following pipeline, we will simulate the execution of the process 200 times \u2013 in two ways:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>in parallel, by starting 20 Brigade jobs, and splitting the work evenly between the two<\/li>\n\n\n\n<li>in a sequential job, which does all 200 executions one after the other<\/li>\n<\/ul>\n\n\n\n<p>Notice how we are using two core Brigade concepts \u2013 a Job, and a Group.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nconst { events, Job, Group } = require('@azure\/brigadier')\n\nconst parallelism = 20;\n\nevents.on(\"exec\", (brigadeEvent, project) => {\n\n    \/\/ Brigade grouping for jobs\n    var g = new Group();\n\n    for(i = 0; i < parallelism; i++) {\n        var job = new Job(`parallel-countdown-${i}`);\n        job.image = \"ubuntu\";\n        job.shell = \"bash\";\n        job.tasks = [\n            \"for((i=$COUNTDOWN_FROM;i<=$COUNTDOWN_TO;i++)); do echo counting $i; sleep 1;  done\"\n        ];\n\n        job.env = {\n            COUNTDOWN_FROM: (i * 10).toString(),\n            COUNTDOWN_TO: (i * 10 + 9).toString()\n        };\n\n        job.host.name = \"virtual-kubelet\";\n        job.resourceRequests.cpu = \"1\";\n        job.resourceRequests.memory = \"1G\";\n        \n        g.add(job);\n    }\n\n    var seq = new Job(\"sequential-countdown\");\n    seq.image = \"ubuntu\";\n    seq.shell = \"bash\";\n    seq.tasks = [\n        \"for((i=$COUNTDOWN_FROM;i<=$COUNTDOWN_TO;i++)); do echo counting $i; sleep 1;  done\"\n    ];\n\n    seq.env = {\n        COUNTDOWN_FROM: (0).toString(),\n        COUNTDOWN_TO: (199).toString()\n    };\n\n    seq.host.name = \"virtual-kubelet\";\n    seq.resourceRequests.cpu = \"1\";\n    seq.resourceRequests.memory = \"1G\";\n    \n    g.add(seq);\n\n    \/\/ runAll runs all jobs in parallel\n    g.runAll();\n});\n<\/pre><\/div>\n\n\n<p>In this scenario, we only start the jobs \u2013 however, with Brigade, we can get the result of the execution, and take different actions based on it.<\/p>\n\n\n\n<p>After we run this pipeline with&nbsp;<code>brig<\/code>, we can see both the parallel jobs, and the sequential one starting at around the same time \u2013 then, the parralel jobs start finishing, and the sequential one takes around 3 minutes longer to finish.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"1387\" height=\"1296\" src=\"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-1a-gif.gif\" alt=\"GIF of parallel jobs running\" class=\"wp-image-76294\" \/><\/figure>\n\n\n\n<p>The tool used to visualize the pipeline is&nbsp;<a href=\"https:\/\/github.com\/slok\/brigadeterm\" target=\"_blank\" rel=\"noreferrer noopener\">Brigadeterm<\/a>, which can also be used to get the job logs.<br>There is currently a known bug which marks job duration wrong.<\/p>\n\n\n\n<p>Brigade also comes with a web dashboard \u2013 you can access it by executing&nbsp;<code>brig dashboard<\/code>(and, if deployed in a different namespace, by passing the&nbsp;<code>--namespace<\/code>&nbsp;flag). We can also see the difference between the parallel and sequential execution:<\/p>\n\n\n<figure class=\"wp-block-image aligncenter\"><img decoding=\"async\" src=\"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-2-1024x238.webp\" alt=\"web dashboard\" class=\"wp-image-76297 webp-format\" srcset=\"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-2.webp 1595w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-2-300x70.webp 300w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-2-1024x238.webp 1024w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-2-768x179.webp 768w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-2-1536x357.webp 1536w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-2-330x77.webp 330w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-2-800x186.webp 800w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-2-400x93.webp 400w\" data-orig-src=\"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-2.png\" data-orig-srcset=\"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-2.png 1595w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-2-300x70.png 300w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-2-1024x238.png 1024w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-2-768x179.png 768w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-2-1536x357.png 1536w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-2-330x77.png 330w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-2-800x186.png 800w, https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/03\/brigade-tutorial-2-400x93.png 400w\"><\/figure>\n\n\n\n<p>Keep in mind that we have a 1 node cluster, and all jobs are scheduled on top of Azure Container Instances, allowing us to only pay for the few tens of seconds our jobs are running.<\/p>\n\n\n\n<p>By default, Azure Container Instances have a quota of 100 container groups per subscription \u2013 if you need more, a simple request with Azure Support can help. For more information, see&nbsp;<a href=\"https:\/\/docs.microsoft.com\/azure\/azure-subscription-service-limits#container-instances-limits\" target=\"_blank\" rel=\"noreferrer noopener\">azure-quotas<\/a>.<\/p>\n\n\n\n<p>In this example, we are using an&nbsp;<code>ubuntu<\/code>&nbsp;container, with a few commands \u2013 keep in mind that you can use any container to run Brigade jobs, and you can run any command that is available inside that container.<\/p>\n\n\n\n<p>Now that we have everything working, we can programmatically call the Brigade endpoint we configured with TLS and have our&nbsp;<code>brigade.js<\/code>&nbsp;file handle the event, executing our pipeline.<\/p>\n\n\n\n<p>The<code>brigade.js<\/code>&nbsp;file will have access to the incoming event, as well as to the project information (notice the&nbsp;<code>brigadeEvent<\/code>&nbsp;and&nbsp;<code>project<\/code>&nbsp;objects in the event handler).<\/p>\n\n\n\n<p>At this point, you can use the&nbsp;<code>\/cloudevents\/v02\/project-id\/secret<\/code>&nbsp;endpoint in the Brigade gateway we just exposed to send POST requests in the CloudEvents format:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n{\n    \"specversion\" : \"0.2\",\n    \"type\" : \"your.custom.event.type\",\n    \"source\" : \"event source\",\n    \"id\" : \"A234-1234-1234\",\n    \"time\" : \"2018-04-05T17:31:00Z\",\n\n    \"contenttype\" : \"json\",\n    \"data\" : {}\n}\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\" id=\"Get-started-with-Brigade\">Get started with Brigade<\/h2>\n\n\n\n<p>Here are the best places to get involved with Brigade and the community:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/github.com\/Azure\/brigade\" target=\"_blank\" rel=\"noreferrer noopener\">the Brigade GitHub repository<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/docs.brigade.sh\/\" target=\"_blank\" rel=\"noreferrer noopener\">the official documentation<\/a><\/li>\n\n\n\n<li>the #brigade channel in the Kubernetes Slack<\/li>\n\n\n\n<li>participate in the\u00a0<a href=\"https:\/\/zoom.us\/j\/280806496\" target=\"_blank\" rel=\"noreferrer noopener\">weekly community Brigade community meeting, Tuesdays at 9:30AM PST<\/a><\/li>\n<\/ul>\n\n\n\n<p>We\u2019re always happy to help if you have questions, and we\u2019d love to see what you build with Brigade!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Microservices built on Kubernetes are fast becoming one of the core scenarios where computing is done, and Kubernetes development and operations skills are therefore becoming a larger part of any cloud-native toolset.<\/p>\n","protected":false},"author":5562,"featured_media":95475,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"msxcm_post_with_no_image":false,"ep_exclude_from_search":false,"_classifai_error":"","_classifai_text_to_speech_error":"","footnotes":""},"post_tag":[158],"content-type":[346,361],"topic":[2241,2242],"programming-languages":[],"coauthors":[547],"class_list":["post-76006","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","tag-kubernetes","content-type-news","content-type-project-updates","topic-cloud","topic-containers","review-flag-1593580428-734","review-flag-1593580415-931","review-flag-1593580419-521","review-flag-1593580771-946","review-flag-1-1593580432-963","review-flag-2-1593580437-411","review-flag-3-1593580442-169","review-flag-4-1593580448-609","review-flag-6-1593580457-852","review-flag-7-1593580463-151","review-flag-9-1593580473-997","review-flag-alway-1593580310-39","review-flag-free-1593619513-693","review-flag-machi-1680214156-53","review-flag-new-1593580248-669","review-flag-vm-1593580807-312"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.2 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Brigade tutorial: Instant scaling on demand with serverless Kubernetes<\/title>\n<meta name=\"description\" content=\"This tutorial shows you how to use CNCF sandbox projects, including Brigade, to build a Kubernetes-native application that listens for events and then runs serverless pipelines on Virtual Kubelet instances.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Brigade tutorial: Instant scaling on demand with serverless Kubernetes\" \/>\n<meta property=\"og:description\" content=\"This tutorial shows you how to use CNCF sandbox projects, including Brigade, to build a Kubernetes-native application that listens for events and then runs serverless pipelines on Virtual Kubelet instances.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/\" \/>\n<meta property=\"og:site_name\" content=\"Microsoft Open Source Blog\" \/>\n<meta property=\"article:published_time\" content=\"2019-04-01T16:00:05+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-27T16:37:56+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2024\/06\/CLO24-Azure-Retail-025.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1170\" \/>\n\t<meta property=\"og:image:height\" content=\"640\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Radu Matei\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@OpenAtMicrosoft\" \/>\n<meta name=\"twitter:site\" content=\"@OpenAtMicrosoft\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Radu Matei\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 min read\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/\"},\"author\":[{\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/author\/radu-matei\/\",\"@type\":\"Person\",\"@name\":\"Radu Matei\"}],\"headline\":\"Brigade tutorial: Instant scaling on demand with serverless Kubernetes\",\"datePublished\":\"2019-04-01T16:00:05+00:00\",\"dateModified\":\"2025-06-27T16:37:56+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/\"},\"wordCount\":2023,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2024\/06\/CLO24-Azure-Retail-025.webp\",\"keywords\":[\"Kubernetes\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/\",\"url\":\"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/\",\"name\":\"Brigade tutorial: Instant scaling on demand with serverless Kubernetes\",\"isPartOf\":{\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2024\/06\/CLO24-Azure-Retail-025.webp\",\"datePublished\":\"2019-04-01T16:00:05+00:00\",\"dateModified\":\"2025-06-27T16:37:56+00:00\",\"description\":\"This tutorial shows you how to use CNCF sandbox projects, including Brigade, to build a Kubernetes-native application that listens for events and then runs serverless pipelines on Virtual Kubelet instances.\",\"breadcrumb\":{\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/#primaryimage\",\"url\":\"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2024\/06\/CLO24-Azure-Retail-025.webp\",\"contentUrl\":\"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2024\/06\/CLO24-Azure-Retail-025.webp\",\"width\":1170,\"height\":640},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/opensource.microsoft.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Brigade tutorial: Instant scaling on demand with serverless Kubernetes\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/#website\",\"url\":\"https:\/\/opensource.microsoft.com\/blog\/\",\"name\":\"Microsoft Open Source Blog\",\"description\":\"Open dialogue about openness at Microsoft \u2013 open source, standards, interoperability\",\"publisher\":{\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/opensource.microsoft.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/#organization\",\"name\":\"Microsoft Open Source Blog\",\"url\":\"https:\/\/opensource.microsoft.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/08\/Microsoft-Logo.png\",\"contentUrl\":\"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/08\/Microsoft-Logo.png\",\"width\":259,\"height\":194,\"caption\":\"Microsoft Open Source Blog\"},\"image\":{\"@id\":\"https:\/\/opensource.microsoft.com\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/OpenAtMicrosoft\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Brigade tutorial: Instant scaling on demand with serverless Kubernetes","description":"This tutorial shows you how to use CNCF sandbox projects, including Brigade, to build a Kubernetes-native application that listens for events and then runs serverless pipelines on Virtual Kubelet instances.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/","og_locale":"en_US","og_type":"article","og_title":"Brigade tutorial: Instant scaling on demand with serverless Kubernetes","og_description":"This tutorial shows you how to use CNCF sandbox projects, including Brigade, to build a Kubernetes-native application that listens for events and then runs serverless pipelines on Virtual Kubelet instances.","og_url":"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/","og_site_name":"Microsoft Open Source Blog","article_published_time":"2019-04-01T16:00:05+00:00","article_modified_time":"2025-06-27T16:37:56+00:00","og_image":[{"width":1170,"height":640,"url":"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2024\/06\/CLO24-Azure-Retail-025.png","type":"image\/png"}],"author":"Radu Matei","twitter_card":"summary_large_image","twitter_creator":"@OpenAtMicrosoft","twitter_site":"@OpenAtMicrosoft","twitter_misc":{"Written by":"Radu Matei","Est. reading time":"10 min read"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/#article","isPartOf":{"@id":"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/"},"author":[{"@id":"https:\/\/opensource.microsoft.com\/blog\/author\/radu-matei\/","@type":"Person","@name":"Radu Matei"}],"headline":"Brigade tutorial: Instant scaling on demand with serverless Kubernetes","datePublished":"2019-04-01T16:00:05+00:00","dateModified":"2025-06-27T16:37:56+00:00","mainEntityOfPage":{"@id":"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/"},"wordCount":2023,"commentCount":0,"publisher":{"@id":"https:\/\/opensource.microsoft.com\/blog\/#organization"},"image":{"@id":"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/#primaryimage"},"thumbnailUrl":"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2024\/06\/CLO24-Azure-Retail-025.webp","keywords":["Kubernetes"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/","url":"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/","name":"Brigade tutorial: Instant scaling on demand with serverless Kubernetes","isPartOf":{"@id":"https:\/\/opensource.microsoft.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/#primaryimage"},"image":{"@id":"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/#primaryimage"},"thumbnailUrl":"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2024\/06\/CLO24-Azure-Retail-025.webp","datePublished":"2019-04-01T16:00:05+00:00","dateModified":"2025-06-27T16:37:56+00:00","description":"This tutorial shows you how to use CNCF sandbox projects, including Brigade, to build a Kubernetes-native application that listens for events and then runs serverless pipelines on Virtual Kubelet instances.","breadcrumb":{"@id":"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/#primaryimage","url":"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2024\/06\/CLO24-Azure-Retail-025.webp","contentUrl":"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2024\/06\/CLO24-Azure-Retail-025.webp","width":1170,"height":640},{"@type":"BreadcrumbList","@id":"https:\/\/opensource.microsoft.com\/blog\/2019\/04\/01\/brigade-kubernetes-serverless-tutorial\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/opensource.microsoft.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Brigade tutorial: Instant scaling on demand with serverless Kubernetes"}]},{"@type":"WebSite","@id":"https:\/\/opensource.microsoft.com\/blog\/#website","url":"https:\/\/opensource.microsoft.com\/blog\/","name":"Microsoft Open Source Blog","description":"Open dialogue about openness at Microsoft \u2013 open source, standards, interoperability","publisher":{"@id":"https:\/\/opensource.microsoft.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/opensource.microsoft.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/opensource.microsoft.com\/blog\/#organization","name":"Microsoft Open Source Blog","url":"https:\/\/opensource.microsoft.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/opensource.microsoft.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/08\/Microsoft-Logo.png","contentUrl":"https:\/\/opensource.microsoft.com\/blog\/wp-content\/uploads\/2019\/08\/Microsoft-Logo.png","width":259,"height":194,"caption":"Microsoft Open Source Blog"},"image":{"@id":"https:\/\/opensource.microsoft.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/OpenAtMicrosoft"]}]}},"msxcm_display_generated_audio":false,"msxcm_animated_featured_image":null,"distributor_meta":false,"distributor_terms":false,"distributor_media":false,"distributor_original_site_name":"Microsoft Open Source Blog","distributor_original_site_url":"https:\/\/opensource.microsoft.com\/blog","push-errors":false,"_links":{"self":[{"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/posts\/76006","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/users\/5562"}],"replies":[{"embeddable":true,"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/comments?post=76006"}],"version-history":[{"count":2,"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/posts\/76006\/revisions"}],"predecessor-version":[{"id":97784,"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/posts\/76006\/revisions\/97784"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/media\/95475"}],"wp:attachment":[{"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/media?parent=76006"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/post_tag?post=76006"},{"taxonomy":"content-type","embeddable":true,"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/content-type?post=76006"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/topic?post=76006"},{"taxonomy":"programming-languages","embeddable":true,"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/programming-languages?post=76006"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/opensource.microsoft.com\/blog\/wp-json\/wp\/v2\/coauthors?post=76006"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}