|
| 1 | +--- |
| 2 | +title: Deploy airgapped Serverless Functions with OpenFaaS |
| 3 | +description: Learn how to install OpenFaaS into an airgap with airfaas for private serverless functions. |
| 4 | +date: 2024-04-15 |
| 5 | +categories: |
| 6 | +- serverless |
| 7 | +- functions |
| 8 | +- portable |
| 9 | +- airgap |
| 10 | +dark_background: true |
| 11 | +author_staff_member: alex |
| 12 | +hide_header_image: true |
| 13 | +--- |
| 14 | + |
| 15 | +In this tutorial, I'll show you how to install [OpenFaaS Standard or OpenFaaS for Enterprises](https://docs.openfaas.com/openfaas-pro/introduction/) into a private, airgapped network. |
| 16 | + |
| 17 | +There are no special tools required to perform an offline installation, but you will need a computer with Internet access in order to prepare for the installation. On your private network, you should have Kubernetes already installed, but if you don't, [K3s](https://k3s.io) could be a good option and has [documentation for offline installations](https://docs.k3s.io/installation/airgap). |
| 18 | + |
| 19 | +If you don't have a private registry in your airgap or are unsure how to set one up, [CNCF Harbor](https://www.cncf.io/projects/harbor/) is a popular open-source choice. For testing, I used Docker's open source registry now called ["CNCF Distribution"](https://github.com/distribution/distribution), with authentication and a self-signed TLS certificate, with the CA's public key placed in the trust bundle. |
| 20 | + |
| 21 | +Since the private network has no Internet access, we need to perform a subset of the tasks on a computer with access to the public Internet: |
| 22 | + |
| 23 | +On the public network: |
| 24 | + |
| 25 | +* Download container images |
| 26 | +* Download specific chart versions |
| 27 | +* Download any CLI tools needed |
| 28 | + |
| 29 | + |
| 30 | +> Download the various charts, images and CLI tools required. |
| 31 | +
|
| 32 | +On the private network: |
| 33 | + |
| 34 | +* Restore container images into a self-hosted registry |
| 35 | +* Configure any pull secrets required |
| 36 | +* Install the exported chart with Helm |
| 37 | + |
| 38 | + |
| 39 | +> "airfaas restore" places the container images into the private registry, Helm performs an installation pointing at the new images, then the kubelet will pull those images and start the containers for OpenFaaS. |
| 40 | +
|
| 41 | +Now, all of the steps above can become tedious and repetitive, and there a number of existing solutions for automation. However most of the ones we looked at were opinionated, complex, and tied you into new concepts that were unnecessary. That's where airfaas comes in. A simple extension to the existing OpenFaaS CLI which makes your initial installation, and subsequent updates a walk in the park. |
| 42 | + |
| 43 | +## Walk-through with airfaas |
| 44 | + |
| 45 | +There are two logic parts to this walk-through, the first set of steps are run on an Internet-facing computer, to prepare what's needed for an offline installation. The second set of steps cover the offline installation itself, and deploying a sample function from the store. |
| 46 | + |
| 47 | +### Download the charts you will need |
| 48 | + |
| 49 | +First of all, you can download airfaas for the public network using: |
| 50 | + |
| 51 | +```bash |
| 52 | +faas-cli plugin get airfaas |
| 53 | +``` |
| 54 | + |
| 55 | +You can then use it via `faas-cli airfaas` or create an alias `alias airfaas="faas-cli airfaas"`. |
| 56 | + |
| 57 | +If your local machine is running MacOS with Apple Silicon, and the remote machine runs Linux, you can override the Operating System and Architecture to pre-download airfaas for the remote computer. |
| 58 | + |
| 59 | +Now, download the Helm chart or charts that you require. |
| 60 | + |
| 61 | +```bash |
| 62 | +Examples: |
| 63 | +## Download all charts from repo |
| 64 | +airfaas download chart |
| 65 | + |
| 66 | +## Download a single chart |
| 67 | +airfaas download chart openfaas/cron-connector |
| 68 | + |
| 69 | +## Download a specific version of a chart |
| 70 | +airfaas download chart openfaas/openfaas --version 0.9.0 |
| 71 | +``` |
| 72 | + |
| 73 | +The charts `--url` is set to `https://openfaas.github.io/faas-netes/` as a default. |
| 74 | + |
| 75 | +Here's what you get when you download all the charts in the repository (which is the default): |
| 76 | + |
| 77 | +```bash |
| 78 | +$ airfaas download chart |
| 79 | + |
| 80 | +Downloading: (all charts) https://openfaas.github.io/faas-netes/ |
| 81 | +NAME VERSION DESCRIPTION |
| 82 | +openfaas/openfaas 14.2.34 OpenFaaS - Serverless Functions Made Simple |
| 83 | +openfaas/cron-connector 0.6.10 Trigger OpenFaaS Functions with cron schedules |
| 84 | +openfaas/federated-gateway 0.1.0 Federated Gateway for OpenFaaS service providers |
| 85 | +openfaas/kafka-connector 0.7.9 Connect OpenFaaS functions to Kafka topics |
| 86 | +openfaas/mqtt-connector 0.4.7 Connect OpenFaaS functions to MQTT topics |
| 87 | +openfaas/nats-connector 0.3.2 Trigger OpenFaaS Functions from NATS Pub/Sub |
| 88 | +openfaas/postgres-connector 0.1.1 Trigger OpenFaaS functions from PostgreSQL |
| 89 | +openfaas/pro-builder 0.4.13 Build OpenFaaS functions via a REST API |
| 90 | +openfaas/probuilder 0.2.0 Build OpenFaaS functions via a REST API |
| 91 | +openfaas/queue-worker 0.2.7 Dedicated queue-worker for OpenFaaS using JetStream |
| 92 | +openfaas/sns-connector 0.1.3 Invoke functions from an AWS SNS messages. |
| 93 | +openfaas/sqs-connector 0.2.4 Connect OpenFaaS functions to SQS topics |
| 94 | +Downloading openfaas/openfaas (14.2.34) => chart/openfaas/openfaas |
| 95 | +Downloading openfaas/cron-connector (0.6.10) => chart/openfaas/cron-connector |
| 96 | +Downloading openfaas/federated-gateway (0.1.0) => chart/openfaas/federated-gateway |
| 97 | +Downloading openfaas/kafka-connector (0.7.9) => chart/openfaas/kafka-connector |
| 98 | +Downloading openfaas/mqtt-connector (0.4.7) => chart/openfaas/mqtt-connector |
| 99 | +Downloading openfaas/nats-connector (0.3.2) => chart/openfaas/nats-connector |
| 100 | +Downloading openfaas/postgres-connector (0.1.1) => chart/openfaas/postgres-connector |
| 101 | +Downloading openfaas/pro-builder (0.4.13) => chart/openfaas/pro-builder |
| 102 | +Downloading openfaas/probuilder (0.2.0) => chart/openfaas/probuilder |
| 103 | +Downloading openfaas/queue-worker (0.2.7) => chart/openfaas/queue-worker |
| 104 | +Downloading openfaas/sns-connector (0.1.3) => chart/openfaas/sns-connector |
| 105 | +Downloading openfaas/sqs-connector (0.2.4) => chart/openfaas/sqs-connector |
| 106 | +``` |
| 107 | + |
| 108 | +Then you'll see the various tarballs downloaded: |
| 109 | + |
| 110 | +```bash |
| 111 | +$ find chart/ | grep tgz |
| 112 | +chart/openfaas/queue-worker/queue-worker-0.2.7.tgz |
| 113 | +chart/openfaas/mqtt-connector/mqtt-connector-0.4.7.tgz |
| 114 | +chart/openfaas/nats-connector/nats-connector-0.3.2.tgz |
| 115 | +chart/openfaas/postgres-connector/postgres-connector-0.1.1.tgz |
| 116 | +chart/openfaas/probuilder/probuilder-0.2.0.tgz |
| 117 | +chart/openfaas/federated-gateway/federated-gateway-0.1.0.tgz |
| 118 | +chart/openfaas/sqs-connector/sqs-connector-0.2.4.tgz |
| 119 | +chart/openfaas/sns-connector/sns-connector-0.1.3.tgz |
| 120 | +chart/openfaas/pro-builder/pro-builder-0.4.13.tgz |
| 121 | +chart/openfaas/cron-connector/cron-connector-0.6.10.tgz |
| 122 | +chart/openfaas/kafka-connector/kafka-connector-0.7.9.tgz |
| 123 | +chart/openfaas/openfaas/openfaas-14.2.34.tgz |
| 124 | +``` |
| 125 | + |
| 126 | +### Download the container images |
| 127 | + |
| 128 | +Next, download the images for all the charts, or a specific chart. |
| 129 | + |
| 130 | +Like the previous command, a `--url` and `--version` command are available. |
| 131 | + |
| 132 | +Here, we'll download just two of the charts we need: |
| 133 | + |
| 134 | +```bash |
| 135 | +$ airfaas download images openfaas/openfaas |
| 136 | +$ airfaas download images openfaas/cron-connector |
| 137 | +``` |
| 138 | + |
| 139 | +Here's the output from the second chart, notice how it's downloaded all available images, so if you change a configuration value later on, you won't have to download and sync images again. |
| 140 | + |
| 141 | +```bash |
| 142 | +$ airfaas download images openfaas/cron-connector |
| 143 | +Downloading: chart openfaas/cron-connector https://openfaas.github.io/faas-netes/ |
| 144 | +Showing values for: "openfaas/cron-connector" |
| 145 | +Total images: 2 |
| 146 | +NAME IMAGE |
| 147 | +image ghcr.io/openfaas/cron-connector:0.6.1 |
| 148 | +pro.image ghcr.io/openfaasltd/cron-connector:0.2.5 |
| 149 | + |
| 150 | +Downloading: ghcr.io/openfaas/cron-connector:0.6.1 |
| 151 | +Wrote images/openfaas/cron-connector/image.tar (7.4MB) |
| 152 | + |
| 153 | +Downloading: ghcr.io/openfaasltd/cron-connector:0.2.5 |
| 154 | +Wrote images/openfaas/cron-connector/pro.image.tar (6.205MB) |
| 155 | +``` |
| 156 | + |
| 157 | +### Download a sample function for testing |
| 158 | + |
| 159 | +We recommend exporting one of the sample functions from the store so you can deploy something and see the setup working. |
| 160 | + |
| 161 | +```bash |
| 162 | +arkade get crane |
| 163 | + |
| 164 | +mkdir -p images/samples/ |
| 165 | + |
| 166 | +crane pull ghcr.io/openfaas/alpine:latest ./images/samples/alpine.tar |
| 167 | +``` |
| 168 | + |
| 169 | +### Download any supporting CLI tools |
| 170 | + |
| 171 | +Lastly, you may wish to download various CLI utilities for use on the air-gapped computer on the private network, where you'll perform the installation, including a separate copy of airfaas itself. |
| 172 | + |
| 173 | +Let's assume you're going to run the various tools on a Linux computer with an amd64 architecture, and want to download them to `./tools`. |
| 174 | + |
| 175 | +```bash |
| 176 | +mkdir -p tools |
| 177 | + |
| 178 | +export OS="linux" |
| 179 | +export ARCH="x86_64" |
| 180 | + |
| 181 | +faas-cli plugin get airfaas \ |
| 182 | + --path ./tools \ |
| 183 | + --os $OS \ |
| 184 | + --arch $ARCH |
| 185 | + |
| 186 | +arkade get \ |
| 187 | + --path ./tools \ |
| 188 | + --os $OS \ |
| 189 | + --arch $ARCH \ |
| 190 | + kubectl \ |
| 191 | + crane \ |
| 192 | + kind \ |
| 193 | + k3sup \ |
| 194 | + kubectx \ |
| 195 | + helm \ |
| 196 | + faas-cli |
| 197 | +``` |
| 198 | + |
| 199 | +Now prepare a USB disk, or use `scp` or `rsync` to copy the files to the computer or jump host on the private network. |
| 200 | + |
| 201 | +### Perform an installation on the private network |
| 202 | + |
| 203 | +#### Restore the images into a private registry |
| 204 | + |
| 205 | +We typically encounter registries with any of the below: |
| 206 | + |
| 207 | +1. HTTP only, no authentication |
| 208 | +2. TLS with a self-signed certificate not in the local trust bundle |
| 209 | +3. TLS with a self-signed certificate in the local trust bundle |
| 210 | +4. TLS with authentication |
| 211 | + |
| 212 | +For option one and two, when restoring images use the `--insecure-registry` flag. |
| 213 | + |
| 214 | +For the third option, there is no change required. |
| 215 | + |
| 216 | +For the fourth option, you should create a `~/.docker/config.json` file with valid credentials for the server |
| 217 | + |
| 218 | +There is no need to install a Docker daemon to do this. You can use the `faas-cli` to generate a valid Docker credential file: |
| 219 | + |
| 220 | +Create a password.txt file with the password required to log in, and then set the USERNAME variable: |
| 221 | + |
| 222 | +```bash |
| 223 | +export USERNAME=openfaas |
| 224 | +export REGISTRY=probable-stargazer.local:5000 |
| 225 | + |
| 226 | +mkdir -p ~/.docker/ |
| 227 | + |
| 228 | +cat ./password.txt | faas-cli registry-login \ |
| 229 | + --username $USERNAME \ |
| 230 | + --server $REGISTRY \ |
| 231 | + --password-stdin |
| 232 | +``` |
| 233 | + |
| 234 | +Restore the images into the private registry: |
| 235 | + |
| 236 | +```bash |
| 237 | +export REGISTRY=probable-stargazer.local:5000 |
| 238 | +airfaas restore ./images/openfaas/openfaas/images.json --prefix $REGISTRY |
| 239 | +``` |
| 240 | + |
| 241 | +The final output of the command will print re-mapped image names from the upstream URLs to the ones in your private registry. |
| 242 | + |
| 243 | +Save that file to values-air.yaml, for instance.. |
| 244 | + |
| 245 | +```yaml |
| 246 | +gatewayPro: |
| 247 | + image: probable-stargazer.local:5000/openfaasltd/gateway:0.4.27 |
| 248 | +autoscaler: |
| 249 | + image: probable-stargazer.local:5000/openfaasltd/autoscaler:0.3.6 |
| 250 | +dashboard: |
| 251 | + image: probable-stargazer.local:5000/openfaasltd/openfaas-dashboard:0.5.11 |
| 252 | +gateway: |
| 253 | + image: probable-stargazer.local:5000/openfaas/gateway:0.27.6 |
| 254 | +queueWorkerPro: |
| 255 | + image: probable-stargazer.local:5000/openfaasltd/queue-worker:0.4.0 |
| 256 | +``` |
| 257 | +
|
| 258 | +#### Prepare the OpenFaaS namespaces |
| 259 | +
|
| 260 | +```bash |
| 261 | +kubectl create ns openfaas |
| 262 | +kubectl create ns openfaas-fn |
| 263 | +``` |
| 264 | + |
| 265 | +If you are using authentication for your private registry, then create a pull secret and bind it to the default service account. |
| 266 | + |
| 267 | +You can skip this step if there is no authentication required for your private registry. |
| 268 | + |
| 269 | +```bash |
| 270 | +export REG=probable-stargazer.local:5000 |
| 271 | +export NS=openfaas |
| 272 | + |
| 273 | +kubectl create namespace $NS || "echo Namespace: $NS already exists" |
| 274 | + |
| 275 | +kubectl create secret docker-registry private-registry-creds \ |
| 276 | + --docker-server=$REG \ |
| 277 | + --from-file .dockerconfigjson=$HOME/.docker/config.json \ |
| 278 | + -n $NS |
| 279 | + |
| 280 | +kubectl patch serviceaccount -n $NS default -p '{"imagePullSecrets": [{"name": "private-registry-creds"}]}' |
| 281 | +``` |
| 282 | + |
| 283 | +Repeat the above, changing openfaas to openfaas-fn if you are intending on hosting functions within the same registry. |
| 284 | + |
| 285 | +#### Create a secret for the OpenFaaS license |
| 286 | + |
| 287 | +```bash |
| 288 | +kubectl create secret generic \ |
| 289 | + -n openfaas \ |
| 290 | + openfaas-license \ |
| 291 | + --from-file license=$HOME/.openfaas/LICENSE |
| 292 | +``` |
| 293 | + |
| 294 | +#### Install OpenFaaS with Helm |
| 295 | + |
| 296 | +First, run `ls chart/openfaas/openfaas` to see which chart versions you have available, then pick one for the installation: |
| 297 | + |
| 298 | +```bash |
| 299 | +helm upgrade --install openfaas ./chart/openfaas/openfaas/openfaas-14.2.34.tgz \ |
| 300 | + --namespace openfaas \ |
| 301 | + --set openfaasPro=true \ |
| 302 | + --set operator.create=true \ |
| 303 | + --set clusterRole=true \ |
| 304 | + -f ./values-air.yaml |
| 305 | +``` |
| 306 | + |
| 307 | +Alternatively, you can use the [values-pro.yaml file from the OpenFaaS documentation](https://docs.openfaas.com/deployment/pro/#installation), then provide values-air.yaml to set the images only: |
| 308 | + |
| 309 | +```bash |
| 310 | +helm upgrade --install openfaas ./chart/openfaas/openfaas/openfaas-14.2.34.tgz \ |
| 311 | + --namespace openfaas \ |
| 312 | + --set openfaasPro=true \ |
| 313 | + --set operator.create=true \ |
| 314 | + --set clusterRole=true \ |
| 315 | + -f ./values-pro.yaml \ |
| 316 | + -f ./values-air.yaml |
| 317 | +``` |
| 318 | + |
| 319 | +As you can see, there are no special chart options required for OpenFaaS to run in an offline environment, with a private registry. |
| 320 | + |
| 321 | +### Deploy and invoke a sample function |
| 322 | + |
| 323 | +Port-forward and log into the gateway with the instructions from `arkade info openfaas`. |
| 324 | + |
| 325 | +Now, restore the sample function to your registry: |
| 326 | + |
| 327 | +```bash |
| 328 | +export REG=probable-stargazer.local:5000 |
| 329 | +crane push ./images/samples/alpine.tar $REG/openfaas/alpine:latest |
| 330 | +``` |
| 331 | + |
| 332 | +Deploy it: |
| 333 | + |
| 334 | +```bash |
| 335 | +export REG=probable-stargazer.local:5000 |
| 336 | +faas-cli deploy --name env --fprocess=env --image $REG/openfaas/alpine:latest |
| 337 | +``` |
| 338 | + |
| 339 | +Invoke the function: |
| 340 | + |
| 341 | +```bash |
| 342 | +faas-cli invoke env <<< "" |
| 343 | +Handling connection for 8080 |
| 344 | +PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin |
| 345 | +HOSTNAME=env-6f95bcc679-qv7dp |
| 346 | +OPENFAAS_NAME=env |
| 347 | +fprocess=env |
| 348 | +KUBERNETES_SERVICE_PORT_HTTPS=443 |
| 349 | +KUBERNETES_PORT=tcp://10.43.0.1:443 |
| 350 | +KUBERNETES_PORT_443_TCP=tcp://10.43.0.1:443 |
| 351 | +KUBERNETES_PORT_443_TCP_PROTO=tcp |
| 352 | +KUBERNETES_PORT_443_TCP_PORT=443 |
| 353 | +KUBERNETES_PORT_443_TCP_ADDR=10.43.0.1 |
| 354 | +KUBERNETES_SERVICE_HOST=10.43.0.1 |
| 355 | +KUBERNETES_SERVICE_PORT=443 |
| 356 | +``` |
| 357 | + |
| 358 | +### Offline function development |
| 359 | + |
| 360 | +You can adapt a template from the OpenFaaS template store by downloading its Git repository, mirroring any base images and copying it across to the private registry. |
| 361 | + |
| 362 | +Take the `golang-middleware` template for instance. Its [Dockerfile](https://github.com/openfaas/golang-http-template/blob/master/template/golang-middleware/Dockerfile) uses two public images: |
| 363 | + |
| 364 | +```diff |
| 365 | +-FROM --platform=${TARGETPLATFORM:-linux/amd64} ghcr.io/openfaas/of-watchdog:0.9.15 as watchdog |
| 366 | ++FROM --platform=${TARGETPLATFORM:-linux/amd64} probable-stargazer.local:5000/openfaas/of-watchdog:0.9.15 as watchdog |
| 367 | +-FROM --platform=${BUILDPLATFORM:-linux/amd64} golang:1.22-alpine as build |
| 368 | ++FROM --platform=${BUILDPLATFORM:-linux/amd64} probable-stargazer.local:5000/golang:1.22-alpine as build |
| 369 | +``` |
| 370 | + |
| 371 | +Simply mirror those images with `crane pull` and `crane push`, then add a prefix to the Dockerfile and you'll be able to build, push and deploy functions within your airgap. |
| 372 | + |
| 373 | +Bear in mind that most templates use package managers like `pip`, `npm`, `gradle`, or Gomodules. These packages will need to be mirrored into a separate private package repository for completely offline development. |
| 374 | + |
| 375 | +Alternatively, you could do all your function development outside of the airgap on a public network, then export individual function images as required, to be copied into the private network. |
| 376 | + |
| 377 | +## Wrapping up |
| 378 | + |
| 379 | +As explained in the introduction, no special tooling is required to run a commercial version of OpenFaaS in an airgap, however tooling can improve the experience. Not only can we download the images, charts, and supporting tooling very quickly, but we can perform the initial installation and subsequent updates with a few CLI commands, that have been tested together and are supported by the OpenFaaS team. |
| 380 | + |
| 381 | +What's next? |
| 382 | + |
| 383 | +All the tooling included in OpenFaaS Standard and OpenFaaS for Enterprises is designed to work on any Kubernetes cluster, whether online or offline - including OpenShift. Just mirror any additional connectors or components that you may need, and decide whether you're going to build functions within the airgap, or outside of it, and then to synchronise them as required. |
| 384 | + |
| 385 | +Day two operations are simply a case of running: |
| 386 | + |
| 387 | +```bash |
| 388 | +airfaas download chart |
| 389 | +airfaas download images |
| 390 | +``` |
| 391 | + |
| 392 | +Then on the private network, doing a `helm upgrade` using the instructions from above. |
| 393 | + |
| 394 | +So it's over to you. [Get in touch with us](https://openfaas/pricing) if you'd like to try OpenFaaS in an airgap, or if you're already a licensed customer running in an airgap, we'd be happy to hear your feedback on how to improve airfaas for you. |
| 395 | + |
0 commit comments