|
| 1 | +--- |
| 2 | +title: "How to Manage Stateful Services with OpenFaaS Edge" |
| 3 | +description: "Learn how to define and manage stateful services for OpenFaaS Edge via its docker-compose.yaml file." |
| 4 | +date: 2025-03-18 |
| 5 | +author_staff_member: alex |
| 6 | +categories: |
| 7 | +- edge |
| 8 | +- stateful |
| 9 | +- services |
| 10 | +- faasd |
| 11 | +dark_background: true |
| 12 | +image: images/2025-03-edge-stateful/background.png |
| 13 | +hide_header_image: true |
| 14 | +--- |
| 15 | + |
| 16 | +OpenFaaS Edge is a distribution of OpenFaaS Standard that runs without Kubernetes, on a single host or VM. |
| 17 | + |
| 18 | +We created OpenFaaS Edge (aka faasd-pro) as an antidote to the constant churn, change, and complexity of Kubernetes. It is designed to be simple to operate, easy to understand, and reliable so that it can be redistributed as part of an appliance or edge device. |
| 19 | + |
| 20 | +In this post, we'll explore some new commands added to the `faasd` binary for managing services, then I'll show you how stateful services with via the `docker-compose.yaml`. |
| 21 | + |
| 22 | +Finally, I'll show you how the arkade tool can be used to upgrade the versions of the container images referenced in the YAML file, and how to ignore certain images if you want to hold them at a specific version. |
| 23 | + |
| 24 | +## Introducing the new service commands |
| 25 | + |
| 26 | +The `faasd` binary for OpenFaaS Edge has a new set of commands that allow you to manage the services defined in the `docker-compose.yaml` file. These commands are available in OpenFaaS Edge, and they are designed to make it easier to manage stateful services. |
| 27 | + |
| 28 | +* `faasd service list` - Lists the status of each service including its age and uptime |
| 29 | +* `faasd service logs` - Displays the logs for a given service |
| 30 | +* `faasd service restart` - Restarts a given service |
| 31 | +* `faasd service top` - Shows the CPU and memory usage of each service |
| 32 | + |
| 33 | +A simpler version of the `service logs` command was added to faasd CE. |
| 34 | + |
| 35 | +### faasd service list |
| 36 | + |
| 37 | +The `faasd service list` command lists all the services defined in the `docker-compose.yaml` file. This command is useful for getting an overview of the services that are running on your OpenFaaS Edge instance. |
| 38 | + |
| 39 | +```bash |
| 40 | +$ faasd service list |
| 41 | + |
| 42 | +NAME IMAGE CREATED STATUS |
| 43 | +cron-connector ghcr.io/openfaasltd/cron-connector:0.2.9 23 seconds ago running (23 seconds) |
| 44 | +faas-idler ghcr.io/openfaasltd/faas-idler:0.5.6 23 seconds ago running (23 seconds) |
| 45 | +gateway ghcr.io/openfaasltd/gateway:0.4.38 23 seconds ago running (23 seconds) |
| 46 | +nats docker.io/library/nats:2.10.26 24 seconds ago running (24 seconds) |
| 47 | +prometheus docker.io/prom/prometheus:v3.2.1 23 seconds ago running (23 seconds) |
| 48 | +queue-worker ghcr.io/openfaasltd/jetstream-queue-worker:0.3.46 23 seconds ago running (23 seconds) |
| 49 | + |
| 50 | +``` |
| 51 | + |
| 52 | +Note that the IP address will change between restarts. |
| 53 | + |
| 54 | +### faasd service logs |
| 55 | + |
| 56 | +The `faasd service logs` command displays the logs for a given service. This command is useful for debugging and troubleshooting issues with your services. |
| 57 | + |
| 58 | +You can use various flags which you may recognise from `docker logs`, `journalctl` or `kubectl logs`: |
| 59 | + |
| 60 | +```bash |
| 61 | +$ faasd service logs gateway |
| 62 | + |
| 63 | +$ faasd service logs gateway -f |
| 64 | + |
| 65 | +$ faasd service logs gateway --lines 1000 |
| 66 | + |
| 67 | +$ faasd service logs gateway --since 1h |
| 68 | + |
| 69 | +$ faasd service logs gateway --since-time "2025-03-18T12:00:00Z" |
| 70 | +``` |
| 71 | + |
| 72 | +### faasd service top |
| 73 | + |
| 74 | +The `faasd service top` shows the RAM and CPU usage of each service, so you can keep an eye on whether your services will continue to fit on the host. |
| 75 | + |
| 76 | +```bash |
| 77 | +$ faasd service top |
| 78 | + |
| 79 | +NAME PID CPU (Cores) Memory |
| 80 | +prometheus 5870 2m 50 MB |
| 81 | +gateway 5976 2m 12 MB |
| 82 | +nats 5759 2m 4.3 MB |
| 83 | +cron-connector 6082 0m 5.1 MB |
| 84 | +queue-worker 6184 0m 6.3 MB |
| 85 | +faas-idler 6493 0m 7.3 MB |
| 86 | + |
| 87 | +``` |
| 88 | + |
| 89 | +### faasd service restart |
| 90 | + |
| 91 | +The `faasd service restart` command restarts a given service. |
| 92 | + |
| 93 | +Whilst this command does not reload any changes from the docker-compose.yaml file, it will stop and restart the service. This is useful if you hadn't created a volume mount with the right permissions, the image you were using was not yet pushed to the registry, or there was a race condition or crash of your service. |
| 94 | + |
| 95 | +To reload the compose file, run `sudo systemctl restart faasd` instead. |
| 96 | + |
| 97 | +Perhaps you noticed an error with the faas-idler service and need to restart it? |
| 98 | + |
| 99 | +First, we check the logs to see when it started: |
| 100 | + |
| 101 | +```bash |
| 102 | +$ faasd service logs faas-idler |
| 103 | + |
| 104 | +OpenFaaS Pro: faas-idler (classic scale-to-zero) Version: 0.5.6 Commit: a2fa75c6c82297d110e4c1922ead2df77c2b3cce |
| 105 | +2025/03/18 12:48:08 read-only mode: false |
| 106 | +``` |
| 107 | + |
| 108 | +Then we restart it |
| 109 | + |
| 110 | +``` |
| 111 | +$ faasd service restart faas-idler |
| 112 | +``` |
| 113 | + |
| 114 | +Next, we can check the running time, and see that it's more recent than the other parts of the stack: |
| 115 | + |
| 116 | +```bash |
| 117 | +$ sudo faasd service list |
| 118 | +NAME IMAGE CREATED STATUS |
| 119 | +cron-connector ghcr.io/openfaasltd/cron-connector:0.2.9 2 minutes ago running (2 minutes) |
| 120 | +faas-idler ghcr.io/openfaasltd/faas-idler:0.5.6 2 minutes ago running (43 seconds) |
| 121 | +``` |
| 122 | + |
| 123 | +## New features for the docker-compose.yaml file |
| 124 | + |
| 125 | +Disable a service for a period of time, whilst retaining it in the file: |
| 126 | + |
| 127 | +```yaml |
| 128 | + cron-connector: |
| 129 | + replicas: 0 |
| 130 | +``` |
| 131 | +
|
| 132 | +Enable automatic restarts for a service such as `nats`: |
| 133 | + |
| 134 | +```yaml |
| 135 | + nats: |
| 136 | + restart: "always" |
| 137 | +``` |
| 138 | + |
| 139 | +By default, services that exit will not be restarted unless you run `sudo systemctl restart faasd`. |
| 140 | + |
| 141 | +## How the `docker-compose.yaml` file works |
| 142 | + |
| 143 | +Since OpenFaaS Edge runs on a VM, without Kubernetes, we needed a way to define the core services that make up the stack the gateway, NATS, Prometheus and the queue-worker. Docker's Compose specification was a convenient way to do this because it uses a syntax that's easy to understand and familiar to many developers who have worked with Docker at some point in their career. |
| 144 | + |
| 145 | +Every installation comes with a pre-defined file, which contains definitions for the OpenFaaS gateway, queue-worker, cron-connectors, NATS and Prometheus. Typically you'd only change this file if you wanted to update a setting like the maximum timeout for functions or what version of an image you wanted to run. |
| 146 | + |
| 147 | +Here's how NATS can be defined in the stack for faasd CE: |
| 148 | + |
| 149 | +```yaml |
| 150 | +services: |
| 151 | + nats: |
| 152 | + image: docker.io/library/nats:2.10.26 |
| 153 | + user: "65534" |
| 154 | + restart: "always" |
| 155 | + command: |
| 156 | + - "/nats-server" |
| 157 | + - "-js" |
| 158 | + - "-sd=/nats" |
| 159 | + volumes: |
| 160 | + - type: bind |
| 161 | + source: ./nats |
| 162 | + target: /nats |
| 163 | +``` |
| 164 | + |
| 165 | +We can also expose the TCP port for NATS on a given adapter, or just access it from the Linux bridge that is created by faasd. |
| 166 | + |
| 167 | +```yaml |
| 168 | +ports: |
| 169 | +- "127.0.0.1:4222:4222" |
| 170 | +``` |
| 171 | + |
| 172 | +Service discovery is relatively simple. Each service created by this file can look up other containers by name from a `/etc/hosts` file that is injected dynamically. |
| 173 | + |
| 174 | +So the code in the OpenFaaS gateway can simply open a TCP connection to `nats:4222` and it will be routed to the NATS container. |
| 175 | + |
| 176 | +All services within the compose file are already stateful in that they are run longing, and can write to their filesystem. However, if you want their data to survive restarts, then you can attach volumes to them just like with `docker run -v`. |
| 177 | + |
| 178 | +For Prometheus, we can add a volume to store its Time Series Data Base (TSDB) on the host machine: |
| 179 | + |
| 180 | +```yaml |
| 181 | + prometheus: |
| 182 | + image: docker.io/prom/prometheus:v3.2.1 |
| 183 | + user: "65534" |
| 184 | + restart: "always" |
| 185 | + volumes: |
| 186 | + - type: bind |
| 187 | + source: ./prometheus.yml |
| 188 | + target: /etc/prometheus/prometheus.yml |
| 189 | + - type: bind |
| 190 | + source: ./prometheus |
| 191 | + target: /prometheus |
| 192 | + cap_add: |
| 193 | + - CAP_NET_RAW |
| 194 | + ports: |
| 195 | + - "127.0.0.1:9090:9090" |
| 196 | +``` |
| 197 | + |
| 198 | +We've also bind-mounted the `prometheus.yml` file so that we can change the configuration without having to build a custom image. |
| 199 | + |
| 200 | +### How to update images in the docker-compose.yaml file |
| 201 | + |
| 202 | +The [arkade](https://github.com/alexellis/arkade) tool can be used to check for newer images and upgrade the image tags within the `docker-compose.yaml` file. |
| 203 | + |
| 204 | +```bash |
| 205 | +cd /var/lib/faasd |
| 206 | +
|
| 207 | +arkade chart upgrade --file ./docker-compose.yaml --write --verbose |
| 208 | +``` |
| 209 | + |
| 210 | +Example output: |
| 211 | + |
| 212 | +```bash |
| 213 | +root@build-1:/var/lib/faasd# arkade chart upgrade --file ./docker-compose.yaml --write --verbose |
| 214 | +2025/03/18 12:30:57 Verifying images in: ./docker-compose.yaml |
| 215 | +2025/03/18 12:30:57 Found 6 images |
| 216 | +2025/03/18 12:30:57 [ghcr.io/openfaasltd/gateway] 0.4.38 => 0.4.39 |
| 217 | +``` |
| 218 | + |
| 219 | +If you want to hold the version for a certain service, such as `postgresql`, then you can create a file alongside the `docker-compose.yaml` which will be read by arkade: |
| 220 | + |
| 221 | +``` |
| 222 | +/var/lib/faasd/arkade.yaml |
| 223 | +/var/lib/faasd/docker-compose.yaml |
| 224 | +``` |
| 225 | + |
| 226 | +Add the full path to each image you want `arkade chart upgrade` to ignore, for example: |
| 227 | + |
| 228 | +```yaml |
| 229 | +ignore: |
| 230 | +- services.postgresql.image |
| 231 | +``` |
| 232 | + |
| 233 | +Then run `sudo systemctl restart faasd` to apply the changes. |
| 234 | + |
| 235 | +## Conclusion |
| 236 | + |
| 237 | +We've added a new set of commands to help you manage and monitor services with OpenFaaS Edge, along with two new features for the compose file (restart policies and disabling services). |
| 238 | + |
| 239 | +We also took a look at a couple of examples of how to define services in the `docker-compose.yaml` file using the NATS and Prometheus services from the OpenFaaS Edge YAML file. You can inspect your local YAML file at `/var/lib/faasd/docker-compose.yaml` to see how the other services are set up. |
| 240 | + |
| 241 | +For additional examples of how to define services in the `docker-compose.yaml` file, please refer to [Serverless For Everyone Else](https://store.openfaas.com/l/serverless-for-everyone-else) which is the handbook for faasd CE and OpenFaaS Edge. You'll find detailed examples of how to write functions using Node.js and how to manage additional services such as Grafana, Postgresql, and InfluxDB. |
| 242 | + |
| 243 | +### Want to try it out? |
| 244 | + |
| 245 | +For personal, non-commercial use, you have two options: |
| 246 | + |
| 247 | +* faasd CE - free for 15 functions |
| 248 | +* OpenFaaS Edge - get free access when you [sponsor @openfaas](https://github.com/sponsors/openfaas) via GitHub for 25 USD/mo or higher |
| 249 | + |
| 250 | +For commercial use: |
| 251 | + |
| 252 | +* faasd CE - 1x installation for a 60 day trial or PoC |
| 253 | +* OpenFaaS Edge - [purchase a license](https://docs.google.com/forms/d/e/1FAIpQLSe2O9tnlTjc7yqzXLMvqvF2HVqwNW7ePNOxLchacKRf9LZL7Q/viewform?usp=header) and run up to 250 functions with various OpenFaaS Pro features included |
| 254 | + |
| 255 | +[Find out more in the docs](https://docs.openfaas.com/deployment/edge/) |
0 commit comments