|
| 1 | +## Function Custom Resource Definition (CRD) |
| 2 | + |
| 3 | +In addition to the REST API of the OpenFaaS gateway, the `Function` Custom Resource Definition can be used to manage functions. |
| 4 | + |
| 5 | +Glossary: |
| 6 | + |
| 7 | +* CRD - the definition of a Function, the Custom Resource Definition (CRD) is installed to the cluster via Helm, once. |
| 8 | +* Each instance of a Function is called a Custom Resource (CR). |
| 9 | + |
| 10 | +!!! warning "Do not remove the CRD" |
| 11 | + |
| 12 | + Do not remove the Custom Resource Definition from the cluster. |
| 13 | + |
| 14 | + If you remove the Function CRD, then all instances of the CRD (known as CRs) will be removed from the cluster, meaning all your functions will be deleted immediately. |
| 15 | + |
| 16 | +See also: |
| 17 | + |
| 18 | +* [How and why you should upgrade to the Function Custom Resource Definition (CRD)](https://www.openfaas.com/blog/upgrade-to-the-function-crd/) |
| 19 | +* [How to package OpenFaaS functions with Helm](https://www.openfaas.com/blog/howto-package-functions-with-helm/) |
| 20 | + |
| 21 | +### Function Spec |
| 22 | + |
| 23 | +Here is an example of a function, written out in long form: |
| 24 | + |
| 25 | +```yaml |
| 26 | +--- |
| 27 | +apiVersion: openfaas.com/v1 |
| 28 | +kind: Function |
| 29 | +metadata: |
| 30 | + name: nodeinfo |
| 31 | + namespace: openfaas-fn |
| 32 | +spec: |
| 33 | + name: nodeinfo |
| 34 | + handler: node main.js |
| 35 | + image: functions/nodeinfo:latest |
| 36 | + labels: |
| 37 | + com.openfaas.scale.min: "2" |
| 38 | + com.openfaas.scale.max: "15" |
| 39 | + annotations: |
| 40 | + current-time: Mon 6 Aug 23:42:00 BST 2018 |
| 41 | + next-time: Mon 6 Aug 23:42:00 BST 2019 |
| 42 | + environment: |
| 43 | + write_debug: "true" |
| 44 | + limits: |
| 45 | + cpu: "200m" |
| 46 | + memory: "256Mi" |
| 47 | + requests: |
| 48 | + cpu: "10m" |
| 49 | + memory: "128Mi" |
| 50 | + constraints: |
| 51 | + - "cloud.google.com/gke-nodepool=default-pool" |
| 52 | + secrets: |
| 53 | + - nodeinfo-secret1 |
| 54 | +``` |
| 55 | +
|
| 56 | +## How to generate a spec from a stack.yml |
| 57 | +
|
| 58 | +If you already have functions defined in a stack.yml file, you can generate the Function resources with: |
| 59 | +
|
| 60 | +```bash |
| 61 | +faas-cli generate [-f stack.yml] |
| 62 | +``` |
| 63 | + |
| 64 | +If you'd like to generate a Function CR from a store-function, run: |
| 65 | + |
| 66 | +```bash |
| 67 | +faas-cli generate --from-store env |
| 68 | +``` |
| 69 | + |
| 70 | +Either command can be piped into a file, or directly into `kubectl apply` |
| 71 | + |
| 72 | +```bash |
| 73 | +faas-cli generate > functions.yaml |
| 74 | + |
| 75 | +faas-cli generate --from-store env > env.yaml |
| 76 | + |
| 77 | +faas-cli generate --from-store nodeinfo | kubectl apply -f- |
| 78 | +``` |
| 79 | + |
| 80 | +### Environment substitution |
| 81 | + |
| 82 | +Whilst generating the Function Custom Resource from a stack.yml file, you can also substitute text such as within labels or the image tag. |
| 83 | + |
| 84 | +stack.yml |
| 85 | + |
| 86 | +```yaml |
| 87 | +provider: |
| 88 | + name: openfaas |
| 89 | + |
| 90 | +functions: |
| 91 | + bcrypt: |
| 92 | + lang: golang-middleware |
| 93 | + handler: ./bcrypt |
| 94 | + image: ghcr.io/${OWNER:-alexellis}/bcrypt:${TAG:-latest} |
| 95 | + labels: |
| 96 | + com.openfaas.scale.min: 1 |
| 97 | + com.openfaas.scale.max: 10 |
| 98 | + com.openfaas.scale.target: 500 |
| 99 | + com.openfaas.scale.type: cpu |
| 100 | + |
| 101 | + com.openfaas.git-branch: master |
| 102 | + com.openfaas.git-owner: ${OWNER:-alexellis} |
| 103 | + com.openfaas.git-repo: autoscaling-functions |
| 104 | + com.openfaas.git-sha: ${TAG:-4089a5f18b0692833e28a88d9ca263a68c329034} |
| 105 | + |
| 106 | + annotations: |
| 107 | + com.openfaas.git-repo-url: https://github.com/${OWNER:-alexellis}/autoscaling-functions |
| 108 | + github: true |
| 109 | +``` |
| 110 | +
|
| 111 | +In the example above, there is a default owner for the: image owner, image tag, owner and tag in two labels, and in an annotation. |
| 112 | +
|
| 113 | +Therefore, in CI, you may run something like: |
| 114 | +
|
| 115 | +```bash |
| 116 | +TAG=$CI_TAG OWNER=$CI_OWNER faas-cli generate | kubectl apply -f - |
| 117 | +``` |
| 118 | + |
| 119 | +### Readiness and health |
| 120 | + |
| 121 | +The OpenFaaS REST API contains readiness information in the form of available replicas being > 0. The `faas-cli` also has a `describe` command which queries the amount of available replicas and will report Ready or Not Ready. |
| 122 | + |
| 123 | +That said, the Custom Resource now has a `.status` field with a number of conditions. |
| 124 | + |
| 125 | +* `Reconciling` is `True` - the operator has discovered the Function CR and is working on creating child resources in Kubernetes |
| 126 | +* `Stalled` is `True` - the operator cannot create the function, check the reason, perhaps some secrets are missing? |
| 127 | +* `Ready` condition is `True` - the operator was able to create the required Deployment, all required secrets exist, and it has no more work to do. The `Reconciling` condition is removed |
| 128 | +* `Healthy` condition is `True` - there is at least one ready Pod available to serve traffic |
| 129 | + |
| 130 | +What about scaling to zero? When a Function is scaled to zero, the Ready state will be `True` and the Healthy state will be `False`. Invoke the function via its URL on the gateway to have it scale up from zero, you'll see it progress and gain a `Healthy` condition of `True`. |
| 131 | + |
| 132 | +If you change a Function once it has passed into the Ready=true state, then the Ready condition will change to Unknown, and the Reconciling condition will be added again. |
| 133 | + |
| 134 | +If you're an ArgoCD user, then you can define a custom health check at deployment time to integrate with the Custom Resource: [ArgoCD: Custom Health Checks](https://argo-cd.readthedocs.io/en/stable/operator-manual/health/#custom-health-checks) |
| 135 | + |
| 136 | +To check that all secrets existed, and that the function could be applied correctly, then look for a `Ready` condition with a status of `True` for the current generation of the object. If you want to know if the function's code was valid, and was able to start, and that its image could be pulled, look for the `Healthy` condition instead. Bear in mind that any functions scaled to zero may have the Healthy condition removed, or set to False. |
| 137 | + |
| 138 | +What happens when auto-scaling? When a Function is scaling from at least one replica to some higher number, the Healthy condition will continue to be set to `True`. The same applies when scaling down, so long as the target number of replicas is greater than zero. |
| 139 | + |
| 140 | +### Deploy functions via Helm |
| 141 | + |
| 142 | +You can template and deploy functions via Helm, ArgoCD and Flux by including the Function's CR YAML in the same way you would for any other native Kubernetes resource. |
| 143 | + |
| 144 | +See also: [How to package OpenFaaS functions with Helm](https://www.openfaas.com/blog/howto-package-functions-with-helm/) |
0 commit comments