|
| 1 | +# Tutorial 5: Large deployments with cue |
| 2 | + |
| 3 | +> [!NOTE] |
| 4 | +> |
| 5 | +> This tutorial is work in progress. |
| 6 | +
|
| 7 | +With application simulator you are able to describe a complex multi-service architecture without thinking about the business logic of each service that is part of your setup. |
| 8 | +This allows you to create arbitrarily large deployments for your purposes, e.g. if you'd like to generate lots of telemetry data for your observability backend. |
| 9 | + |
| 10 | +The only limitation that remains, is that YAML does not provide you with a level of programmability, that allows you to write a lot of similar services in one place. You have |
| 11 | +to write them down one by one. |
| 12 | + |
| 13 | +Instead of enriching the application simulation configuration file format with such a functionality, you can leverage configuration languages like [`pkl`](https://pkl-lang.org/), [`dhall`](https://dhall-lang.org/) or [`cue`](https://cuelang.org/). |
| 14 | +In this tutorial we will use `cue` to demonstrate this use case. |
| 15 | + |
| 16 | +## Requirements |
| 17 | + |
| 18 | +Make sure you have `cue` installed locally, following [these instructions](https://cuelang.org/docs/introduction/installation/) |
| 19 | + |
| 20 | +## Create cue file |
| 21 | + |
| 22 | +To get started create the following file named [`large-application.cue`](../../examples/cue/large-application.cue) in an empty folder: |
| 23 | + |
| 24 | +```cue |
| 25 | +import "list" |
| 26 | +import "math" |
| 27 | +
|
| 28 | +#depth: int @tag(depth,type=int) |
| 29 | +#adjectives: ["swift", "happy", "brave", "clever", "silent", "bold", "lucky", "fierce", "gentle", "mighty", "shy", "curious", "wise", "playful", "proud", "loyal"] |
| 30 | +#nouns: ["lion", "tiger", "eagle", "panda", "fox", "wolf", "hawk", "bear", "otter", "falcon", "rabbit", "panther", "deer", "owl", "cheetah", "dolphin"] |
| 31 | +
|
| 32 | +loaders: { |
| 33 | + "user1": { |
| 34 | + type: "curl", |
| 35 | + wait: 5, |
| 36 | + sleep: 2, |
| 37 | + urls: [ "http://swift-lion/next" ] |
| 38 | + } |
| 39 | +} |
| 40 | +
|
| 41 | +services: { |
| 42 | + for x in list.Range(0, #depth+1, 1) { |
| 43 | + for y in list.Range(0, x+1, 1) { |
| 44 | + "\(#adjectives[x])-\(#nouns[y])": { |
| 45 | + type: "java" |
| 46 | + endpoints: { |
| 47 | + http: { |
| 48 | + "/next": list.Concat([[ |
| 49 | + for i in [y, y+1] if x < #depth { |
| 50 | + "http://\(#adjectives[x+1])-\(#nouns[i])/next" |
| 51 | + } |
| 52 | + ], ["sleep,\(math.Exp2(x)+(y*10))"]]) |
| 53 | + } |
| 54 | + } |
| 55 | + } |
| 56 | + } |
| 57 | + } |
| 58 | +} |
| 59 | +``` |
| 60 | + |
| 61 | +## Export cue to YAML |
| 62 | + |
| 63 | +Run the following command to generate a YAML file: |
| 64 | + |
| 65 | +```shell |
| 66 | +cue -t depth=3 export large-application.cue --out yaml > config.yaml |
| 67 | +``` |
| 68 | + |
| 69 | +This will generate an application simulation configuration file with 10 services, since the `for` loop within the `services` block creates a tree of services, where each node talks to two children, until `depth` is reached: |
| 70 | + |
| 71 | +```mermaid |
| 72 | +flowchart TD |
| 73 | + user1 --> swift-lion |
| 74 | + swift-lion --> happy-lion |
| 75 | + swift-lion --> happy-tiger |
| 76 | + happy-lion --> brave-lion |
| 77 | + happy-lion --> brave-tiger |
| 78 | + happy-tiger --> brave-tiger |
| 79 | + happy-tiger --> brave-eagle |
| 80 | + brave-lion --> clever-lion |
| 81 | + brave-lion --> clever-tiger |
| 82 | + brave-tiger --> clever-tiger |
| 83 | + brave-tiger --> clever-eagle |
| 84 | + brave-eagle --> clever-eagle |
| 85 | + brave-eagle --> cleaver-panda |
| 86 | +``` |
| 87 | + |
| 88 | +By increasing the `depth` parameter, you can add additional layers, e.g. `depth=4` will create 15 services, `depth=5` will create 21 services and `depth=6` will create 28 services. |
| 89 | + |
| 90 | +Additionally, each service will introduce some milliseconds of delay using `sleep` depending on their position in the tree. |
| 91 | + |
| 92 | +We recommend that you continue the tutorial with `depth=3`. Afterwards you can increase the value step by step and check how many nodes you can run simultaneously. |
| 93 | + |
| 94 | +## Create your k8s deployment files |
| 95 | + |
| 96 | +To turn the application simulation configuration file from the last step into manifests for kubernetes, run the generator: |
| 97 | + |
| 98 | +``` |
| 99 | +docker run --rm -t -i -v ${PWD}/deployments:/app/deployments -v ${PWD}:/mnt ghcr.io/cisco-open/app-simulator-generators-k8s:latest --config /mnt/config.yaml |
| 100 | +``` |
| 101 | + |
| 102 | +This will create a folder `deployments` that will continue all the files you need to run your simulation on your cluster, using the following command: |
| 103 | + |
| 104 | +``` |
| 105 | +kubectl create namespace app-sim-cue |
| 106 | +kubectl apply -f deployments/ --namespace app-sim-cue |
| 107 | +``` |
| 108 | + |
| 109 | +This will spin up your sample application. You can now use [OpenTelemetry](./5-observability-with-opentelemetry.md) or [cilium hubble](./4-observability-with-cilium-hubble.md to visualize your application. |
| 110 | + |
| 111 | +For example, the following image shows an application with `depth=4` in cilium hubble ui: |
| 112 | + |
| 113 | + |
0 commit comments