From 5e043f760ef1e0456e18b2fa489a4ff2b3f4c85d Mon Sep 17 00:00:00 2001 From: Bill Maxwell Date: Mon, 20 Nov 2023 08:42:23 -0700 Subject: [PATCH] Cleaned up docs to focus on runtime. (#2345) * Cleaned up docs to focus on runtime. Also added algolia back. Signed-off-by: Bill Maxwell * Update docs/docs/30-installation/02-options.md Co-authored-by: Grant Linville Signed-off-by: Bill Maxwell * Update docs/docs/37-getting-started.md Co-authored-by: Tyler Slaton <54378333+tylerslaton@users.noreply.github.com> Signed-off-by: Bill Maxwell --------- Signed-off-by: Bill Maxwell Co-authored-by: Grant Linville Co-authored-by: Tyler Slaton <54378333+tylerslaton@users.noreply.github.com> --- docs/docs/10-home.md | 16 +- docs/docs/100-reference/03-acornfile.md | 1020 ----------------- docs/docs/100-reference/05-functions.md | 398 ------- .../100-reference/06-compute-resources.md | 85 -- docs/docs/100-reference/07-encryption.md | 72 -- docs/docs/100-reference/10-services.md | 110 -- docs/docs/30-installation/02-options.md | 26 +- docs/docs/37-getting-started.md | 12 +- docs/docs/38-authoring/00-overview.md | 435 ------- docs/docs/38-authoring/01-best-practices.md | 33 - docs/docs/38-authoring/02-structure.md | 86 -- docs/docs/38-authoring/03-containers.md | 384 ------- docs/docs/38-authoring/04-volumes.md | 202 ---- docs/docs/38-authoring/05-secrets.md | 291 ----- docs/docs/38-authoring/06-jobs.md | 73 -- .../docs/38-authoring/07-args-and-profiles.md | 188 --- docs/docs/38-authoring/08-localdata.md | 34 - docs/docs/38-authoring/09-permissions.md | 86 -- docs/docs/38-authoring/20-labels.md | 78 -- docs/docs/38-authoring/21-services.md | 31 - docs/docs/38-authoring/30-advanced.md | 167 --- docs/docs/38-authoring/31-nested-acorns.md | 62 - docs/docs/38-authoring/_category_.yaml | 1 - docs/docs/39-publishing.md | 87 -- .../02-admin => 40-admin}/02-volumeclasses.md | 0 .../03-computeclasses.md | 0 .../80-alpha-image-allow-rules.md | 0 docs/docs/50-running/01-args-and-secrets.md | 173 --- docs/docs/50-running/02-networking.md | 211 ---- docs/docs/50-running/03-certificates.md | 85 -- docs/docs/50-running/04-volumes.md | 58 - docs/docs/50-running/06-linking-acorns.md | 40 - docs/docs/50-running/20-labels.md | 38 - docs/docs/50-running/30-troubleshooting.md | 29 - docs/docs/50-running/40-upgrades.md | 46 - docs/docs/50-running/45-auto-upgrades.md | 53 - .../50-namespaces-and-service-accounts.md | 50 - docs/docs/50-running/55-compute-resources.md | 68 -- docs/docs/50-running/60-projects.md | 48 - docs/docs/50-running/65-update-acorns.md | 102 -- docs/docs/50-running/66-remove-acorns.md | 19 - docs/docs/50-running/70-dev.md | 22 - docs/docs/50-running/90-events.md | 39 - docs/docs/50-running/_category_.yaml | 1 - .../docs/55-integrations/01-github-actions.md | 97 -- docs/docs/55-integrations/_category_.yaml | 1 - docs/docusaurus.config.js | 5 + docs/sidebars.js | 65 +- 48 files changed, 47 insertions(+), 5180 deletions(-) delete mode 100644 docs/docs/100-reference/03-acornfile.md delete mode 100644 docs/docs/100-reference/05-functions.md delete mode 100644 docs/docs/100-reference/06-compute-resources.md delete mode 100644 docs/docs/100-reference/07-encryption.md delete mode 100644 docs/docs/100-reference/10-services.md delete mode 100644 docs/docs/38-authoring/00-overview.md delete mode 100644 docs/docs/38-authoring/01-best-practices.md delete mode 100644 docs/docs/38-authoring/02-structure.md delete mode 100644 docs/docs/38-authoring/03-containers.md delete mode 100644 docs/docs/38-authoring/04-volumes.md delete mode 100644 docs/docs/38-authoring/05-secrets.md delete mode 100644 docs/docs/38-authoring/06-jobs.md delete mode 100644 docs/docs/38-authoring/07-args-and-profiles.md delete mode 100644 docs/docs/38-authoring/08-localdata.md delete mode 100644 docs/docs/38-authoring/09-permissions.md delete mode 100644 docs/docs/38-authoring/20-labels.md delete mode 100644 docs/docs/38-authoring/21-services.md delete mode 100644 docs/docs/38-authoring/30-advanced.md delete mode 100644 docs/docs/38-authoring/31-nested-acorns.md delete mode 100644 docs/docs/38-authoring/_category_.yaml delete mode 100644 docs/docs/39-publishing.md rename docs/docs/{100-reference/02-admin => 40-admin}/02-volumeclasses.md (100%) rename docs/docs/{100-reference/02-admin => 40-admin}/03-computeclasses.md (100%) rename docs/docs/{50-running => 40-admin}/80-alpha-image-allow-rules.md (100%) delete mode 100644 docs/docs/50-running/01-args-and-secrets.md delete mode 100644 docs/docs/50-running/02-networking.md delete mode 100644 docs/docs/50-running/03-certificates.md delete mode 100644 docs/docs/50-running/04-volumes.md delete mode 100644 docs/docs/50-running/06-linking-acorns.md delete mode 100644 docs/docs/50-running/20-labels.md delete mode 100644 docs/docs/50-running/30-troubleshooting.md delete mode 100644 docs/docs/50-running/40-upgrades.md delete mode 100644 docs/docs/50-running/45-auto-upgrades.md delete mode 100644 docs/docs/50-running/50-namespaces-and-service-accounts.md delete mode 100644 docs/docs/50-running/55-compute-resources.md delete mode 100644 docs/docs/50-running/60-projects.md delete mode 100644 docs/docs/50-running/65-update-acorns.md delete mode 100644 docs/docs/50-running/66-remove-acorns.md delete mode 100644 docs/docs/50-running/70-dev.md delete mode 100644 docs/docs/50-running/90-events.md delete mode 100644 docs/docs/50-running/_category_.yaml delete mode 100644 docs/docs/55-integrations/01-github-actions.md delete mode 100644 docs/docs/55-integrations/_category_.yaml diff --git a/docs/docs/10-home.md b/docs/docs/10-home.md index 13ed97adc..c886c2b2b 100644 --- a/docs/docs/10-home.md +++ b/docs/docs/10-home.md @@ -8,13 +8,17 @@ slug: / Acorn is a work in progress. Features will evolve over time and there may be breaking changes between releases. Please give us your feedback in [Slack](https://slack.acorn.io), [Discussions](https://github.com/acorn-io/runtime/discussions), or [Issues](https://github.com/acorn-io/runtime/issues)! ::: +:::note +These are the docs for installing and running Acorn runtime on your own Kubernetes clusters. To learn how to use Acorn to package and deploy your applications, and the Acorn hosted platform please visit [docs.acorn.io](https://docs.acorn.io). +::: + ## Overview ### What is Acorn? Acorn is an application packaging and deployment framework that simplifies running apps on Kubernetes. Acorn is able to package up all of an application's Docker images, configuration, and deployment specifications into a single Acorn image artifact. This artifact is publishable to any OCI container registry allowing it to be deployed on any dev, test, or production Kubernetes. The portability of Acorn images enables developers to develop applications locally and move to production without having to switch tools or technology stacks. -Developers create Acorn images by describing the application configuration in an [Acornfile](38-authoring/00-overview.md). The Acornfile describes the whole application without all of the boilerplate of Kubernetes YAML files. The Acorn CLI is used to build, deploy, and operate Acorn images on any Kubernetes cluster. +Developers create Acorn images by describing the application configuration in an [Acornfile](https://docs.acorn.io/authoring/overview). The Acornfile describes the whole application without all of the boilerplate of Kubernetes YAML files. The Acorn CLI is used to build, deploy, and operate Acorn images on any Kubernetes cluster. ### Acorn Workflow @@ -35,7 +39,7 @@ differences between Acorn and Helm. 1. Helm charts are templates for Kubernetes YAML files, whereas Acornfiles define application-level constructs. Acorn is a layer of abstraction on top of Kubernetes. Acorn users do not work with Kubernetes YAML files directly. By design, no Kubernetes -knowledge is needed to use Acorn. +knowledge is needed to use Acorn. 2. Helm users can package any Kubernetes workload into Helm charts, whereas Acorn is designed to package applications and not system-level drivers, plugins, and agents. Acorn supports any type of application, stateless and stateful. Applications @@ -46,9 +50,7 @@ underlying Kubernetes API or use the underlying etcd as a database by defining c deployment specifications. Acorn brings structure to application deployment on Kubernetes. This is in marked contrast with unconstrained use of Kubernetes YAML files in Helm charts. -We hope Acorn will simplify packaging and deployment of applications on Kubernetes. - - +We hope Acorn will simplify packaging and deployment of applications on Kubernetes. ## Quickstart @@ -133,6 +135,6 @@ Next you can learn more about what you can do with Acorn in the [getting started * [Installation](30-installation/01-installing.md) * [Getting Started](37-getting-started.md) -* [Authoring Acornfiles](38-authoring/00-overview.md) -* [Running Acorn Apps](50-running/01-args-and-secrets.md) +* [Authoring Acornfiles](https://docs.acorn.io/authoring/overview) +* [Hands On Running Acorn Apps](https://docs.acorn.io/hands-on-with-acorn) * [Join our Slack channel](https://slack.acorn.io) diff --git a/docs/docs/100-reference/03-acornfile.md b/docs/docs/100-reference/03-acornfile.md deleted file mode 100644 index 6f57c8085..000000000 --- a/docs/docs/100-reference/03-acornfile.md +++ /dev/null @@ -1,1020 +0,0 @@ ---- -title: Acornfile ---- - -## Root - -The root level elements are, -[args](#args), -[services](#services), -[acorns](#acorns), -[containers](#containers), -[jobs](#jobs), -[routers](#routers), -[volumes](#volumes), -[secrets](#secrets), -and [localData](#localdata). - -[containers](#containers), -[jobs](#jobs), -and [routers](#routers) -are all maps where the keys must be unique across all types. For example, it is -not possible to have a container named `foo` and a job named `foo`, they will conflict and fail. Additional -the keys could be using in a DNS name so the keys must only contain the characters `a-z`, `0-9` and `-`. - -```acorn -// User configurable values that can be changed at build or run time. -args: { -} - -// Definition of services the Acorn app will consume -services: { -} - -// Definition of Acorns that will consumed by this Acorn app -acorns: { -} - -// Definition of containers to run -containers: { -} - -// Defintion of jobs to run -jobs: { -} - -// Defintion of HTTP routes to services -routers: { -} - -// Definition of volumes that this acorn needs to run -volumes: { -} - -// Definition of secrets that this acorn needs to run -secrets: { -} - -// Arbitrary information that can be embedded to help render this Acornfile -localData: { -} -``` - -## containers - -`containers` defines the templates of containers to be ran. Depending on the -scale parameter 1 or more containers can be created from each template (including their [sidecars](#sidecars)). - -```acorn -containers: web: { - image: "nginx" - ports: publish: "80/http" -} -``` - -### dirs, directories - -`dirs` configures one or more volumes to be mounted to the specified folder. The `dirs` parameter is a -map structure where the key is the folder name in the container and the value is the referenced volume. Refer -to the [volumes](#volumes) section for more information on volume types. - -```acorn -containers: default: { - image: "nginx" - dirs: { - // A volume named "volume-name" will be mounted at /var/tmp - "/var/tmp": "volume-name" - - // A volume named "volume-name" will be mounted at /var/tmp-full with the size of 20G and an - // access mode of readWriteMany - "/var/tmp-full": "volume://volume-name?size=20G,accessMode=readWriteMany" - - // An ephemeral volume will be created and mounted to "/var/tmp-ephemeral" - "/var/tmp-ephemeral": "ephemeral://" - - // An ephemeral volume named "shared" will be created and mounted to "/var/tmp-ephemeral" - "/var/tmp-ephemeral-named": "ephemeral://shared" - - // A folder will be created at /var/tmp-secret/ where the filenames are the - // key names of the secret "sec-name" and the contents of each file is the corresponding - // secret data value - "/var/tmp-secret": "secret://sec-nam" - - // The local folder ./www will be copied during build into the container image - // as /var/www. If running in dev mode the directory will be syncronized live with - // changes. Local folders must start with "./". - "/var/www": "./www" - } - sidecars: sidecar: { - image: "ubuntu" - dirs: { - // An ephemeral volume named "shared" will be mounted to /var/tmp with the contents of - // the volume shared with the main containers /var/tmp-ephemeral-named folder - "/var/tmp": "ephemeral://shared" - } - } -``` - -### files - -`files` will create files in the container with content from the Acornfile or the value of a secret. The -`files` parameter is a map structure with the key being the file name and the value being the text of the file -or a reference to a secret value. The default mode for files is `0644` unless the file ends with `.sh` or contains -`/bin/` or `/sbin/`. In those situations the mode will be `0755`. - -```acorn -containers: default: { - image: "nginx" - files: { - // A file named /var/tmp/file.txt will be created with mode 0644 - "/var/tmp/file.txt": "some file contents" - - // A file named /run/secret/password will be created with mode 0400 with the - // contents of from the secret named "sec-name" and the value of the data - // key named "key". - "/run/secret/password": "secret://sec-name/key?mode=0400" - - // By default if a secret value changes the application will be restarted. - // the following example will cause the container to not be restarted when - // the secret value changes, but instead the container is dynamically updated - "/run/secret/password-reload": "secret://sec-name/key?onchange=no-action" - - // A file /var/tmp/other.txt will be created with a custom mode value "0600" - "/var/tmp/other.txt": { - content: "file content" - mode: "0600" - } - - } -} -``` - -### image - -`image` refers to the OCI (Docker) image to run for this container. - -```acorn -containers: web: { - image: "nginx" -} -``` - -### build - -`build` contains the information need to build an OCI image to run for this container - -```acorn -containers: build1: { - // Build the Docker image using the context dir "." and the "./Dockerfile". - build: "." -} - -containers: build2: { - build: { - // Build using the context dir "./subdir" - context: "./subdir" - // Build using the "./subdir/Dockerfile" - dockerfile: "./subdir/Dockerfile" - // Build with the multi-stage target named "multistage-target" - target: "multistage-target" - // Pass the following build arguements to the dockerfile - buildArgs: { - "arg1": "value1" - "arg2": "value2" - } - } -} -``` - -### command, cmd - -`command` will overwrite the `CMD` value set in the Dockerfile for the running container - -```acorn -containers: arg1: { - image: "nginx" - // This command will be parsed as a shell expression and turned into an array and ran - cmd: #"/bin/sh -c "echo hi""# -} - -containers: arg2: { - image: "nginx" - // The following will not be parsed and will be ran as defined. - cmd: ["/bin/sh", "-c", "echo hi"] -} - -``` - -### entrypoint - -`entrypoint` will overwrite the `ENTRYPOINT` value set in the Dockerfile for this running container - -```acorn -containers: arg1: { - image: "nginx" - // This command will be parsed as a shell expression and turned into an array and ran - entrypoint: #"/bin/sh -c "echo hi""# -} - -containers: arg2: { - image: "nginx" - // The following will not be parsed and will be ran as defined. - entrypoint: ["/bin/sh", "-c", "echo hi"] -} -``` - -### env, environment - -`env` will set environment variables on the defined container. The value of the environment variable -may be static text or a value from a secret. - -```acorn -containers: env1: { - image: "nginx" - env: [ - // An environment variable of name "NAME" and value "VALUE" will be set - "NAME=VALUE", - - // An environment variable of name "SECRET" and value of the key "key" in the - // secret named "sec-name" will be set. When this secret changes the container - // will not be restarted. - "SECRET=secret://sec-name/key?onchange=no-action" - ] -} - -containers: env1: { - image: "nginx" - // The same configuration as above but in map form - env: [ - NAME: "VALUE" - SECRET: "secret://sec-name/key?onchange=no-action" - ] -} -``` - -### workDir, workingDir - -`workDir` sets the current working directory of the running process defined in `cmd` and `entrypoint` - -```acorn -containers: env1: { - image: "nginx" - command: "ls" - // Run the command "ls", as defined above, in the directory "/tmp" - workDir: "/tmp" -} -``` - -### dependsOn - -`dependsOn` will prevent a container from being created and/or updated until all of -it's dependencies are considered ready. Ready service are considered ready as soon as -their [ready probe](#probes-probe) passes. If there is no ready probe it is as soon -as the containers have started. - -```acorn -containers: web: { - image: "nginx" - dependsOn: ["db"] -} -containers: db: { - // ... - image: "mariadb" -} -``` - -### ports - -`ports` defines which ports are available on the container and the default level of access. Ports -are defined with three different access modes: internal, expose, publish. Internal ports are only available -to the containers within an Acorn. Expose(d) ports are available to services within the cluster. And -publish ports are available publicly outside the cluster. The access mode defined in the Acornfile is -just the default behavior and can be changed at deploy time. - -```acorn -containers: web: { - image: "nginx" - - // Define internal TCP port 80 available internally as DNS web:80 - ports: 80 - - // Define internal HTTP port 80 available internally as DNS web:80 - // Valid protocols are tcp, udp, and http - ports: "80/http" - - // Define internal HTTP port 80 that maps to the container port 8080 - // available internally as DNS web:80 - ports: "80:8080/http" - - // Define internal TCP port 80 that maps to the container port 8080 - // available internally as DNS web:80 - ports: "80:8080" - - // Define internal TCP port 80 that maps to the container port 8080 - // available internally as DNS web-alias:80 - ports: "web-alias:80:8080" - - // The similar ports as above but just in a list - ports: [ - 80, - "80/http", - "80:8080/http", - ] - - ports: { - // Define publically accessible HTTP port 80 that maps to the container port 8080 - // available publically as a DNS assigned at runtime - publish: ["80:8080/http"] - - // Define cluster accessible HTTP port 80 that maps to the container port 8080 - // available publically as a DNS assigned at runtime - expose: ["80:8080/http"] - - // Define internal HTTP port 80 that maps to the container port 8080 - // available internally as DNS web:80 - internal: ["80:8080/http"] - } - - // Define publically accessible HTTP port 80 that maps to the container port 8080 - // available publically as a DNS assigned at runtime - ports: publish: "80:8080/http" -} -``` - -### probes, probe - -`probes` configure probes that can signal when the container is ready, alive, and started. There are -three probe types: `readiness`, `liveness`, and `startup`. `readiness` probes indicate when an application -is available to handle requests. Ports will not be accessible until the `readiness` probe passes. `liveness` -probes indicate if a running process is healthy. If the `liveness` probe fails, the container will be deleted -and restarted. `startup` probe indicates that the container has started for the first time. - -```acorn -containers: web: { - image: "nginx" - - // Configure readiness probe to run probe.sh - probe: "probe.sh" - - // Configure readiness probe to look for a HTTP 200 response from localhost port 80 - probe: "http://localhost:80" - - // Configure readiness probe to connect to TCP port 1234 - probe: "tcp://localhost:1234" - - probes: { - "readiness": { - // Configure a HTTP readiness probe - http: { - url: "http://localhost:80" - headers: { - "X-SOMETHING": "some-value" - } - } - // Below are the default values for the following parameters - initialDelaySeconds: 0 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - } - "liveness": { - // Configure an Exec liveness probe - exec: { - command: ["probe.sh"] - } - } - "startup": { - // Configure a TCP startup liveness probe - tcp: { - url: "tcp://localhost:1234" - } - } - } -} - -``` - -### scale - -`scale` configures the number of container replicas based on this configuration that should -be ran. - -```acorn -containers: web: { - image: "nginx" - scale: 2 -} -``` - -### sidecars - -`sidecars` are containers that run colocated with the parent container and share the same network -address. Sidecars accept all the same parameters as a container and one additional parameter `init` - -```acorn -containers: web: { - image: "nginx" - sidecars: sidecar: { - image: "someother-image" - } -} -``` - -#### init - -`init` tells the container runtime that this `sidecar` must be ran first on startup and the main -container will not run until this container is done - -```acorn -containers: web: { - image: "nginx" - dirs: "/run/startup/": "ephemeral://startup-info" - sidecars: "stage-data": { - // This sidecar will run first and only when it exits with exit code 0 will the - // parent "web" container start - init: true - image: "ubuntu" - dirs: "/run/startup/": "ephemeral://startup-info" - command: "./stage-data-to /run/startup" - } -} -``` - -### permissions - -`permissions` allow you to define what resources the container can interact with on-cluster and what it can do with them. - -```acorn -containers: web: { - image: "nginx" - permissions: { - // These are permissions that will only be granted for this container in its namespace. - rules: [{ - // Configure what actions you can do on the defined resources - verbs: [ - "get", - "list", - "watch", - "create", - ] - // Define what API group the resources belong to - apiGroups: [ - "api.sample.io" - ] - // Configure which resources in the above apiGroups to apply the above verbs to - resources: [ - "fooresource" - ] - }] - // These are permissions that will be granted for this container in all namespaces. - clusterRules: [{ - verbs: [ - "get", - "list", - "watch", - ] - apiGroups: [ - "api.sample.io" - ] - resources: [ - "fooresource" - ] - // Optionally restrict permissions to a specific namespace and not globally - namespaces: [ - "other-namespace" - ] - }] - } -} -``` - -### memory - -`memory` allows you to specify how much memory the container should run with. It can be abbreviated to `mem`. If left unspecified, it will be defaulted to the installation default (see the [reference documentation for memory](06-compute-resources.md#memory) for more information). - -```acorn -containers: { - nginx: { - image: "nginx" - ports: publish: "80/http" - files: { - "/usr/share/nginx/html/index.html": "

My first Acorn!

" - } - memory: 512Mi - } -} -``` - -### class - -`class` allows you to specify what compute class the container should run on. If left unspecified, it will be defaulted to the project-level default. If there is no project-level default it will use the cluster-level default. If there is no cluster-level default then no compute class will be used. See the [reference documentation](06-compute-resources.md#compute-classes) for more information. - -```acorn -containers: { - nginx: { - class: "sample-compute-class" - image: "nginx" - ports: publish: "80/http" - files: { - "/usr/share/nginx/html/index.html": "

My first Acorn!

" - } - memory: 512Mi - } -} -``` - -### metrics - -`metrics` allows you to specify the HTTP port and path on which the container will expose metrics. Acorn will take this information and create the standard `prometheus.io` scrape annotations on the Kubernetes Pod(s) created for the container. - -```acorn -containers: "mycontainer": { - image: "nginx" - ports: ["80/http", "8080/http"] - metrics: { - port: 8080 - path: "/metrics" - } -} -``` - -The Pod created for this container will have the following annotations: - -```yaml -prometheus.io/scrape: "true" -prometheus.io/port: "8080" -prometheus.io/path: "/metrics" -``` - -## services (consuming) - -`services` are Acorns that will deploy cloud services outside the scope of Acorn and provide endpoints, credentials, and other information needed for other Acorns to consume the service. These services are typically managed by the cloud provider. For example, a service could be a RDS database or a S3 bucket. - -```acorn -services: rds: { - image: "ghcr.io/acorn-io/aws/rds-aurora-cluster" -} - -containers: web: { - image: "nginx" - env: { - DB_SERVER: "@{service.rds.address}" - DB_USER: "@{service.rds.secrets.admin.username}" - DB_PASS: "@{service.rds.secrets.admin.password}" - } -} -``` - -### image - -`image` refers to the Acorn image to run to provision and provide the service. - -### secrets - -`secrets` here should be used to define links from the Acorn apps secrets into the service secrets. For example, if the credentials for a service provider need to be bound into the service Acorn for it to provision a new database. - -### autoUpgrade - -`autoUpgrade` will automatically upgrade the service Acorn when a new version of the service is available in the registry. - -### autoUpgradeInterval - -`autoUpgradeInterval` will configure how often to check for a new version of the service Acorn in the registry. - -### notifyUpgrade - -`notifyUpgrade` is a boolean value that will prompt the user to upgrade the service Acorn when a new version is available in the registry. - -### memory, mem - -`memory` allows you to define a memory resource limit for the pods running/provisioning the service. - -### environment, env - -`environment` allows you to define environment variables that will be available to the service Acorn. - -### serviceArgs - -`serviceArgs` allows you to define arguments that will be passed to the service Acorn. - -## services (generating) - -`services` when defined in an Acornfile will generate a service that can be consumed by other Acorns follow this schema. - -```acorn -services: "my-service": { - generated: job: "create-service" -} -``` - -### default - -`default` is a boolean value that can be used to specify if this service should be the default service when creating multiple services in the same Acornfile. - -### generated - -`generated` has a single key `job` that defines which job in the Acornfile will be ran to generate the service. The contents of `/run/secrets/output` will be parsed as an Acornfile and the service will be created from that. - -## services (generated) - -The generated service is the definition consumed by other Acorn applications. - -```acorn -services: "my-service": { - address: "https://my-service-url" - secrets: ["service-credentials"] - data: { - "key1": "value1" - "key2": "value2" - } -} -// ... -``` - -### address - -`address` is a string that provides the address of the service. This is typically a URL or hostname. **address** and **container** are mutually exclusive. - -### Container - -`container` is a string that provides the name of the container that is providing the service. This will automatically set the address of the service. **container** and **address** are mutually exclusive. - -### ports - -`ports` can specifiy a single port or be defined as a list of ports the service endpoint is listening on. - -### secrets - -`secrets` is a list of secrets that are exposed as part of the service that can be consumed by other Acorns. These secrets can provide API keys or other credentials needed to access the service. - -### data - -`data` is an object where the service author can provide key/value data needed to consume the service like a database name or other configuration data. - -## acorns - -`acorns` reference Acorns that have been published to a registry or will be built from a self contained Acornfile outside of the current Acornfile. - -```acorn -acorns: { - "my-acorn": { - image: "my-acorn" - publishMode: "defined" - secrets: ["redis-password:redis-password"] - autoUpgrade: true - profiles: "prod" - } -} -``` - -### image - -`image` is the name of the Acorn image to run. **image** and **build** are mutually exclusive. - -### build - -`build` provides the information to build the Acorn image from source. **build** and **image** are mutually exclusive. - -```acorn -acorns: { - "my-acorn": { - build: { - context: "./acorn-other" - acornfile: "./acorn-other/Acornfile" - args: { - "ARG1": "value1" - } - } - ... - } -} -``` - -Where `context` is the directory to build the Acorn image from, `acornfile` is the path to the Acornfile to build from, and `args` is a map of arguments to pass during the build. - -### publish - -`publish` is a list of one or more ports to publish from the acorn image. - -### publishMode - -`publishMode` defines the behavior of the defined ports in the Acorn image. The values are `all`, `defined`, and `none`. `all` will publish all ports defined in the Acornfile. `defined` will only publish ports defined as `publish` in the Acornfile. `none` will not publish any ports. The default value is `none`. - -### volumes - -`volumes` are a list of volume bindings to mount into the Acorn image. - -### secrets - -`secrets` are a list of secrets to mount into the Acorn image. - -### links - -`links` are a list of links to other Acorns that will be available to the Acorn image. - -### autoUpgrade - -`autoUpgrade` is a boolean value that will automatically upgrade the Acorn image when a new version is available in the registry. - -### autoUpgradeInterval - -`autoUpgradeInterval` is a string that defines how often to check for a new version of the Acorn image in the registry. - -### notifyUpgrade - -`notifyUpgrade` is a boolean value that will prompt the user to upgrade the Acorn image when a new version is available in the registry. - -### deployArgs - -`deployArgs` is a map of arguments to pass to the Acorn image when it is deployed. - -### profiles - -`profiles` is a string that specifies which profile to use when deploying the Acorn image. - -## jobs - -`jobs` are containers that are run once to completion. If the configuration of the job changes, the will -be ran once again. All fields that apply to [containers](#containers) also apply to -jobs. - -```acorn -jobs: "setup-volume": { - image: "my-app" - command: "init-data.sh" - dirs: "/mnt/data": "data" -} -``` - -### schedule - -`schedule` field will configure your job to run on a cron schedule. The format is the standard cron format. - -``` - ┌───────────── minute (0 - 59) - │ ┌───────────── hour (0 - 23) - │ │ ┌───────────── day of the month (1 - 31) - │ │ │ ┌───────────── month (1 - 12) - │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday; - │ │ │ │ │ 7 is also Sunday on some systems) - │ │ │ │ │ OR sun, mon, tue, wed, thu, fri, sat - │ │ │ │ │ - * * * * * -``` - -The following shorthand syntaxes are supported - -| Entry | Description | Equivalent to | -|-------------------------|------------------------------------------------------------|---------------| -| @yearly (or @annually) | Run once a year at midnight of 1 January | 0 0 1 1 * | -| @monthly | Run once a month at midnight of the first day of the month | 0 0 1 ** | -| @weekly | Run once a week at midnight on Sunday morning | 0 0 ** 0 | -| @daily (or @midnight) | Run once a day at midnight | 0 0 ** * | -| @hourly | Run once an hour at the beginning of the hour | 0 **** | - -## routers - -`routers` support path based HTTP routing so one can expose multiple containers through a -single published service. For example, if you have two containers named `auth` and `api` -they would have to be exposed as two different HTTP services like `auth.example.com` and `api.example.com`. -The router feature allows you to expose these two containers as `myapp.example.com/auth` and -`myapp.example.com/api`. - -```acorn -routers: myapp: { - routes: { - // Short syntax to match all prefixes /auth and route to the auth:8080 container - "/auth": "auth:8080" - - // Verbose syntax - "/api": { - // can be "exact" or "prefix" - pathType: "exact" - targetServiceName: "api" - targetPort: 8081 - } - } -} - -containers: auth: { - image: "auth" - ports: "8080/http" -} - -containers: api: { - image: "api" - ports: "8081/http" -} -``` - -### pathType - -`pathType` describes the matching behavior of the route. Currently, "prefix" and "exact" -are supported. "exact" will require that the path matches the string and "prefix" requires -the path to start with the path string. The short syntax of routes will default to "prefix". - -```acorn -routers: myapp: routes: { - "/api": { - pathType: "exact" - targetServiceName: "api" - targetPort: 8081 - } - - // Default to "prefix" match for short syntax - "/auth": "auth:8080" -} -``` - -### targetServiceName - -`targetServiceName` is the destination service of the route. This name typically corresponds to -to a `container` name. Technically it can be any acorn resource that exposes a service name which -is currently `containers`, `jobs`, `routers` and linked in services. - -### targetPort - -`targetPort` is the destination port of the route. The target `container` or `job` must have this -port defined or else the traffic will be dropped. If you are targeting another router, routers -implicitly have the internal port `80` - -## volumes - -`volumes` store persistent data that can be mounted by containers - -```acorn -containers: db: { - image: "mariadb" - dirs: "/var/lib/mysql": "data" -} -volumes: data: { - size: "100G" - accessModes: "readWriteOnce" - class: "default" -} -``` - -### size - -`size` configures the default size of the volume to be created. At deploy-time this value can be -overwritten. - -```acorn -volumes: data: { - // All numbers are assumed to be gigabytes - size: 100 - - // The following suffixes are understood - // 2^x - Ki | Mi | Gi | Ti | Pi | Ei - // 10^x - m | k | M | G | T | P | E - size: "10G" -} -``` - -### class - -`class` refers to the `storageclass` within kubernetes. - -```acorn -volumes: data: { - // either "default" or a storageclass from `kubectl get sc` - class: "longhorn" -} -``` - -### accessModes - -`accessModes` configures how a volume can be shared among containers. - -```acorn -volumes: data: { - accessModes: [ - // Only usable by containers on the same node - "readWriteOnce", - // Usable by containers across many nodes - "readWriteMany", - // Usable by containers across many nodes but read only - "readOnlyMany", - ] -} -``` - -## secrets - -`secrets` store sensitive data that should be encrypted as rest. - -```acorn -secrets: "my-secret": { - type: "opaque" - data: { - key1: "" - key2: "" - } -} -``` - -### type - -The common pattern in Acorn is for secrets to be generated if not supplied. `type` -specifies how the secret can be generated. Refer to [the secrets documentation](38-authoring/05-secrets.md) for -descriptions of the different secret types and how they are used. - -```acorn -secrets: "a-token": { - // Valid types are "opaque", "token", "basic", "generated", and "template" - type: "opaque" -} -``` - -### params - -`params` are used to configure the behavior of the secrets generation for different types. -Refer to [the secrets documentation](38-authoring/05-secrets.md) for -descriptions of the different secret types and how their parameters. - -```acorn -secrets: "my-token": { - type: "token" - params: { - length: 32 - characters: "abcdedfhifj01234567890" - } -} -``` - -### data - -`data` defines the keys and non-sensitive values that will be used by the secret. -Refer to [the secrets documentation](38-authoring/05-secrets.md) for -descriptions of the different secret types and how to use data keys and values. - -```acorn -secrets: { - "my-template": { - type: "template" - data: { - template: """ - a ${secret://my-secret-data/key} value - """ - } - } - "my-secret-data": { - type: "opaque" - data: { - key: "value" - } - } -} -``` - -## args - -`args` defines arguments that can be modified at build or runtime by the user. -Arguments to an Acorn can be standard strings, ints, bools, and other complex types. To define an argument, -specify a name and a default value. The type will be inferred from the default value. - -```acorn -args: { - // A description that will be show to the user in `acorn run image --help` - myIntVar: 1 - // Another description that will be show to the user in `acorn run image --help` - myStringVar: "somestring" - // Another description that will be show to the user in `acorn run image --help` - myBoolVar: true -} -``` - -## localData - -`localData` is used by the Acornfile author to store values to assist in scripting in the Acornfile. These values are -not directly interpreted by Acorn and are only for the authors use. - -```acorn -containers:{ - frontend: { - // ... - env: { - "MY_IMPORTANT_SETTING": localData.myApp.frontendConfig.key - } - // ... - } - database: { - // ... - env: { - "MY_DATABASE_NAME": localData.myApp.databaseConfig.name - } - // ... - } -} -localData: { - myApp:{ - frontendConfig: { - key: "value" - } - databaseConfig: { - name: "db-prod" - } - } -} -``` diff --git a/docs/docs/100-reference/05-functions.md b/docs/docs/100-reference/05-functions.md deleted file mode 100644 index 9e34c2096..000000000 --- a/docs/docs/100-reference/05-functions.md +++ /dev/null @@ -1,398 +0,0 @@ ---- -title: Function Library ---- - -### atoi - -```acorn -std.atoi(string): number -``` - -Parses a string into a number. - -``` -std.atoi("42") // 42 -std.atoi("42.1") // 42.1 -``` - -### base64, base64decode - -```acorn -std.base64(bytes): base64_string -std.base64decode(base64_string): bytes -``` - -Encodes and decods base64. - -```acorn -std.base64("hello") // "aGVsbG8=" -std.base64decode("aGVsbG8=") // "hello" -``` - -### contains - -```acorn -std.contains(string, string): boolean -std.contains(list, value): boolean -std.contains(object, key): boolean -``` - -Returns whether the input contains a given value/key. - -```acorn -std.contains("asdf", "as") // true -std.contains("asdf", "foo") // false - -std.contains(["asdf","bar"], "bar") // true -std.contains(["asdf","bar"], "baz") // false - -std.contains({"x": "y", "a" :"b"}, "a") // true -std.contains({"x": "y", "a" :"b"}, "z") // false -``` - -### dirname, basename, fileExt - -```acorn -std.dirname(string): string -std.basename(string): string -std.fileExt(string): string -``` - -Extracts the dirname (parent path), basename (filename), and file extension of a path - -```acorn -std.dirname("/a/b/foo.txt") // "/a/b" -std.basename("/a/b/foo.txt") // "foo.txt" -std.fileExt("/a/b/foo.txt") // ".txt" -``` - -### endsWith, startsWith - -```acorn -std.endsWith(string, suffix): boolean -std.startsWith(string, prefix): boolean -``` - -Returns whether the input string starts or ends with a given string. - -```acorn -std.endsWith("foobar", "foo") // false -std.endsWith("foobar", "bar") // true - -std.startsWith("foobar", "foo") // true -std.startsWith("foobar", "bar") // false -``` - -### fromHex, toHex - -```acorn -std.toHex(ascii_string): hex_string -std.fromHex(hex_string): ascii_string -``` - -Converts characters between ascii/binary and hex-encoding. - -```acorn -std.toHex('hi') // "6869" -std.fromHex("6869") // "hi" -``` - -### fromYAML, toYAML - -```acorn -std.fromYAML(yaml_string): object -std.toYAML(object): yaml_string -``` - -Parses a string of YAML and into an object and vice-versa. - -```acorn -x: std.fromYAML(""" - foo: - bar: - a: 1 - b: 2 - """) - -// x now is equivalent to: -foo: bar: { - a: 1 - b: 2 -} - -std.toYAML({foo: bar: "baz"}) // "foo:\n bar:\n baz" -``` - -### ifelse - -```acorn -std.ifelse(condition, value1, value2): value -``` - -Returns `value1` if `condition` is true, and `value2` otherwise. - -```acorn -std.ifelse(1 > 2, "yes", "no") // "no" -std.ifelse(1 <= 2, "yes", "no") // "yes" -``` - -### indexOf - -```acorn -str.indexOf(string, substring): number -str.indexOf(list, value): number -``` - -Returns the index where a given `value` exists in the input string or list. - -```acorn -std.indexOf("hello", "ll") // 2 -std.indexOf("hello", "world") // -1 - -std.indexOf(["hello", "ll"], "hello") // 0 -std.indexOf(["hello", "ll"], "world") // -1 -``` - -### join, split - -```acorn -std.join(list, separator_string): string -std.split(string, separator_string): list -``` - -Splits a string up into a list based on a separator string, and vice-versa. - -```acorn -std.split("hi,bye", ",") // ["hi", "bye"] -std.join(["a", "b"], ",") // "a,b" -``` - -### len - -```acorn -std.len(string): number -std.len(list): number -``` - -Returns the length of the input string, or the number of items in the input list - -```acorn -std.len("hello") // 5 -std.len([1,2,3]) // 3 -``` - -### merge - -```acorn -std.merge(object1, object2): object -``` - -Recursively combines the values of two separate objects into one. - - -```acorn -x: { - a: "b", - c: "d", - f: { - a: "b", - x: "y", - l: [1, 2] - } -} - -y: { - a: "b2", - d: "e", - f: { - x: "y2", - l: [1, 2, 3] - } -} - -z: std.merge(x, y) - -// z is now: -z: { - a: "b2", - c: "d", - d: "e", - f: { - a: "b" - x: "y2" - l: [1,2,3] - } -} -``` - -### mod - -```acorn -mod(num, div): number -``` - -Computes the remainder of integer division (modulus) - -```acorn -mod(3,2) // 1 -mod(14,5) // 4 -``` - -### pathJoin - -```acorn -pathJoin(list): string -pathJoin(list, separator): string -``` - -Combines multiple segments of a path into one string. - -```acorn -std.pathJoin(["a", "//b", "c/"], "/") // "a/b/c" -std.pathJoin(["a", "//b", "c/"]) // "a/b/c" -std.pathJoin(["a", "//b", "c/"], "\\") // "a\\b\\c" -``` - -### range - -```acorn -std.range(end): list[numbers] -std.range(start, end): list[numbers] -std.range(start, end, increment): list[numbers] -``` - -Returns a list of numbers between `start` (inclusive, defaulting to 0) and `end` (exclusive) in steps of `increment` (defaulting to 1). - -```acorn -std.range(5) // [0, 1, 2, 3, 4] -std.range(2,5) // [2,3,4] -std.range(0, 5, 2) // [0, 2, 4] -``` - -### replace - -```acorn -std.replace(string, from, to): string -std.replace(string, from, to, limit): string -``` - -Replaces instances of `from` in the input string with `to`, upte `limit` times (if specified). - -```acorn -std.replace("hhh", "h", "b") // "bbb" -std.replace("hhhhh", "h", "b", 3) // "bbbhh" -``` - -### reverse - -```acorn -std.reverse(list): list -``` - -Reverses the order of items in a list. - -```acorn -std.reverse([2,5,4]) // [4,5,2] -``` - -### sha1sum, sha256sum, sha512sum - -```acorn -std.sha1sum(string): string -std.sha256sum(string): string -std.sha512sum(string): string -``` - -Returns the SHA-* hash of the input string. - -```acorn -std.sha1sum("hi") // "c22b5f9178342609428d6f51b2c5af4c0bde6a42" -std.sha256sum("hi") // "8f434346648f6b96df89dda901c5176b10a6d83961dd3c1ac88b59b2dc327aa4" -std.sha512sum("hi") // "150a14ed5bea6cc731cf86c41566ac427a8db48ef1b9fd626664b3bfbb99071fa4c922f33dde38719b8c8354e2b7ab9d77e0e67fc12843920a712e73d558e197" -``` - -### slice - -```acorn -std.slice(list, start): list -std.slice(list, start, end): list -``` - -Returns a subset of `list` starting at the `start` index, and ending at `end` (or the end of the list) - -```acorn -std.slice([1,2,3,4,5], 1) // [2,3,4,5] -std.slice([1,2,3,4,5], 1, 3) // [2,3,4] -``` - -### sort - -```acorn -std.sort(list): list -std.sort(list, compare_fn): list -``` - -Sorts the items in a list. - -``` -std.sort([2,5,4]) // [2,4,5] -std.sort([2, 5, 4], {x: int, y: int, less: x > y}) // [5,4,2] -``` - -### splitHostPort, joinHostPort - -```acorn -std.splitHostPort(host_port): [host, port] -std.joinHostPort(host, port): string -``` - -Separates a host+port string into its individual pieces, and vice-versa. - -```acorn -std.splitHostPort("example.com:443") // ["example.com", "443"] -std.splitHostPort("[1::1]:443") // ["1::1", "443"] -std.joinHostPort("1::1", 443) // "[1::1]:443" -``` - -### toLower, toTitle, toUpper - -```acorn -std.toLower(string): string -std.toTitle(string): string -std.toUpper(string): string -``` - -Converts the case of characters in the input string. - -```acorn -std.toLower("HELLO") // "hello" -std.toUpper("hello") // "HELLO" -std.toTitle("hello world") // "Hello World" -std.toTitle("hellO WorLD") // "HellO WorLD" -``` - -### trim, trimPrefix, trimSuffix - -```acorn -std.trim(string): string -std.trim(string, chars): string - -std.trimPrefix(string): string -std.trimPrefix(string, chars): string - -std.trimSuffix(string): string -std.trimSuffix(strin, charsg): string -``` - -Removes matching characters (whitespace by default) from the beginning, end or both sides of a string. - -```acorn -std.trim(" hi ") // "hi" -std.trim("wwwHIwww", "w") // "HI" - -std.trimPrefix(" asdf ") // "asdf " -std.trimPrefix("asdf", "as") // "df" - -std.trimSuffix(" asdf ") // " asdf" -std.trimSuffix("asdf", "df") // "as" -``` diff --git a/docs/docs/100-reference/06-compute-resources.md b/docs/docs/100-reference/06-compute-resources.md deleted file mode 100644 index 2856043c0..000000000 --- a/docs/docs/100-reference/06-compute-resources.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: Compute resources ---- - -Acorn comes with a number of features that allow you define how your application workloads will be scheduled at deploy-time. - -## Memory -You can configure Acorn apps to have a set memory upon startup. - -This allows you to specify memory that an Acorn will abide by when being created. There are a number of ways to set this so that you have full control over defaults, workloads, and maximums. In order of precedence, the ways to set memory are when you: - -1. [Run an Acorn](50-running/55-compute-resources.md) -2. [Author an Acornfile](38-authoring/03-containers.md#memory) -3. [Install Acorn](30-installation/02-options.md#memory) - -:::note -When installing Acorn, you can also specify `--workload-memory-maximum`. This flag sets a maximum that when exceeded prevents the offending Acorn from being installed. -::: - -### Valid memory values -Supported value formats for memory flags include -- 1_234 ->`1234` -- 5M -> `5_000_000` -- 1.5Gi ->`1_610_612_736` -- 0x1000_0000 -> `268_435_456` - -These all translate into an exact amount of bytes. We encourage you use the binary representation of large quantities of bytes when interacting with memory such as `Ki`, `Mi`, `Gi`, and `Pi`. - -#### No limit -It is possible to set any of these flags to have no limit on memory by simply setting their value to `0`. However, running an Acorn with its memory set to `0` while the `--workload-memory-maximum` is not set to `0` will roughly translate to "use as much memory as allowed". For example, say that we install Acorn with a non-zero `--workload-memory-maximum`. - -```console -acorn install --workload-memory-maximum 512Mi -``` - -Then we try to run an Acorn with its memory set to 0. - -```console -acorn run --memory 0 foo -``` - -When the `foo` Acorn gets provisioned, all of its containers will have their memory set to `512Mi` (the `--workload-memory-maximum` we set prior). - -:::note -This same interaction will occur if the `--workload-memory-default` is set to 0 (which it is by default) -::: - -## Compute Classes -You can configure Acorn apps to have a set compute class upon startup. - -Setting a compute class allows you to define what the infrastructure providing your Acorn workloads should look like. Things that compute classes control include: - -- What OS/Architecture your workloads will run on -- How much memory is minimal, maximal, default and allowed -- How many vCPUs should be allocated - -:::info -You are not able to set vCPUs directly. This is an intentional abstraction and instead vCPUs are calculated based on of the amount of memory specified for a workload. -::: - -### Using a Compute Class -You can see the compute classes available in your current project using the CLI. - -```console -$ acorn offerings computeclasses -NAME DEFAULT MEMORY RANGE MEMORT DEFAULT DESCRIPTION -default * 512Mi-1Gi 1Gi Default ComputeClass -non-default 0-1Gi 512Mi Non-default ComputeClass -unrestricted Unrestricted 512Mi Unrestricted ComputeClass -specific 128Mi,512Mi,1Gi 128Mi Specific ComputeClass -``` - -Breaking this down: - -- `DEFAULT` indicates whether a ComputeClass is the default and will be used if no ComputeClass is defined. -- `MEMORY_DEFAULT` indicates the memory that will be requested for a workload if none is specified. -- `MEMORY_RANGE` indicates what memory values are available to use, and can take two forms. - 1. `-` denotes a range and any value within it can be specified. - 2. `,` denotes specific values that are the only ones allowed. - -Specifying compute classes can be done in the Acornfile (using the [class property](03-acornfile.md#class) for containers) or at runtime (using the [--compute-class flag](50-running/55-compute-resources.md#compute-class)). If you do not specify a compute class, the default compute class for the project will be used. If there is no default for the project, the default for the cluster will be used. Finally, if there is no cluster default then no compute class will be used. Depending on the compute class that is used, the memory that you specify may be in contention with its requirements. Should that happen Acorn will provide a descriptive error message to amend any issues. - -:::note -Looking to manage a compute class? This should only be done if you are (or are in communication with) an administrator of Acorn. You can read more information about managing compute classes [here](02-admin/03-computeclasses.md) -::: \ No newline at end of file diff --git a/docs/docs/100-reference/07-encryption.md b/docs/docs/100-reference/07-encryption.md deleted file mode 100644 index 6ad0b6e9e..000000000 --- a/docs/docs/100-reference/07-encryption.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: Encryption ---- - - -## Public keys - -To get the public key for a namespace run the following. - -```shell -acorn info -#--- -#client: -# version: -# ... -#namespace: -# publicKeys: -# - keyID: 3rRkDpFF9FjhT4wGTaIvw8U5MX0p80eosk8yu61FOAY -#server: -# apiServerImage: ghcr.io/acorn-io/runtime:main -# config: -#.... -``` - -The public key is available under the namespace top level key. The value is encoding using golang's base64.RawURLEncoding encoder. This means it doesn't have padding and is safe to use in URLs. In some languages, like Python, you might need to re-add the padding before being able to use the key. - -Using the [pynacl](https://pynacl.readthedocs.io/en/latest/public/#nacl-public-sealedbox) package for instance the key needs to have the padding added back in. - -```python -import base64 -from nacl.public import SealedBox, PublicKey -from nacl.encoding import URLSafeBase64Encoder -... -key = "3rRkDpFF9FjhT4wGTaIvw8U5MX0p80eosk8yu61FOAY" -padded_key = key + '=' * (-len(key) % 4) - -pkAcorn = PublicKey(padded_key, encoder=URLSafeBase64Encoder) -... -``` - -## Encrypting the plain text - -The plain text is encrypted using a libsodium sealed secret. These make use of an ephemeral public and private key pair from the sender and the public key of the receiver. In Python using the pynacl library: - -```python -import base64 -from nacl.public import SealedBox, PublicKey -from nacl.encoding import URLSafeBase64Encoder - -... -sealed_box = SealedBox(pkAcorn) -ciphertext = sealed_box.encrypt(message) -... - ``` - -## Acorn message format - -Acorn expects the secret to be in a string in the form of: - -```shell -ACORNENC:base64.RawURLEncode.EncodeToString("{"publicKey":"base64.RawURLEncoding.EncodeToString(ciphertext)",...}) -``` - -Where the `publicKey` is the string value returned from `acorn info`. The object can include multiple `publicKey:ciphertext` items. Acorn will attempt to decrypt the values with the key available in the namespace. - -## Private keys - -Acorn creates a public/private key pair that is tied to the underlying Acorn namespace and UID. If you delete the namespace or uninstall Acorn the encrypted data can not be unencrypted. The private key is stored outside of the users Acorn namespace to prevent accidental exposure of the key. - -## Additional info - -- [libsodium](https://doc.libsodium.org/bindings_for_other_languages/) diff --git a/docs/docs/100-reference/10-services.md b/docs/docs/100-reference/10-services.md deleted file mode 100644 index af882beae..000000000 --- a/docs/docs/100-reference/10-services.md +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: Services ---- - -Service Acorns offer a convenient way for developers to provision databases, caches, storage buckets, and other as-a-service offerings from cloud providers and Kubernetes operators from within the Acorn context. The provisioning process can be implemented using any tooling that can be called from a container. - -## Creating a service Acorn - -To create a Service Acorn, you will need to create an Acornfile that interacts with the required provider APIs for creating, updating, and deleting the desired service. It will then need to generate a new Acornfile providing the connection details of the created service. - -Follow these steps to create a Service Acorn: - -1. Declare that a service is going to be created in this Acornfile. - - ```acorn - services: "my-service": { - generated: job: "create-service" - } - ``` - - The snippet above specifies that the complete service definition will be coming from a job called `create-service`. This is similar to how generated secrets are created. - -1. Declare any secrets as type generated that will be used by consumers of the service. - - Typically credentials or API keys will be required to connect to the provisioned endpoints. If these are to be exposed to the consuming Acorn app, they need to be declared as generated secrets in the service Acornfile. - - ```acorn - services: "my-service": { - generated: job: "create-service" - } - // ... - secrets: "my-service-secret": { - type: "generated" - params: job: "create-service" - } - ``` - - The above snippet adds a secret `my-service-secret` that must be produced by the `create-service` job. - -1. Last, create the job(s) that will be used to manage the lifecycle of the service. The job must produce a complete Acornfile that defines the complete service and any expected secrets. The output must be written to `/run/secrets/output` the same as a generated secret. The job can use any language or tooling to create the generated Acornfile. These examples use a shell script for simplicity and readability but could be generated in other languages. - - ```acorn - services: "my-service": { - generated: job: "create-service" - } - jobs: "create-service": { - image: "ubuntu:latest" - entrypoint: "/app/create-service.sh" - files: "/app/create-service.sh": """ - #!/bin/bash - cat < /run/secrets/output - services: "my-service": { - secrets: ["my-service-secret"] - } - secrets: "my-service-secret": { - type: "basic" - data: { - username: "foo" - password: "bar" - } - } - EOF - """ - } - secrets: "my-service-secret": { - type: "generated" - params: job: "create-service" - } - ``` - - The example above shows a job that creates a service that exposes a secret containing basic auth credentials. Here it is static, but it could be generated dynamically by the job reaching out to a service like AWS secret manager or Vault. - - The Acornfile here is using an inline script for illustration, the best practice is to use a separate file and copy it into the container like the following example. - - ```acorn - services: "my-service": { - generated: job: "create-service" - } - jobs: "create-service": { - image: "ubuntu:latest" - entrypoint: "/app/create-service.sh" - dirs: "/app/create-service.sh": "./create-service.sh" - events: ["create", "update", "delete"] - } - secrets: "my-service-secret": { - type: "generated" - params: job: "create-service" - } - ``` - - In this case the `create-service.sh` file will be copied into the container at `/app/create-service.sh`, it is easier to maintain scripts this way. Using this method, you will need to ensure the script is executable. - -## Lifecycle - -To automate the lifecycle of the service, there are lifecycle events that can be used to trigger the correct behavior. The events are: - -- `create` - Runs on the initial deployment of the Acorn. -- `update` - This will be called when the Acorn app is updated or restarted. -- `stop` - This event will be called when the Acorn app is stopped by the command `acorn stop [APP_NAME]`. -- `delete` - This will be called when the Service Acorn is being deleted. - -If no events are specified the default behavior is run on create and update. - -If no job is watching for the delete event, the resources created outside of Acorn will be orphaned when the Service Acorn is deleted. - -## Troubleshooting - -### Generated secret contains the generated Acornfile instead of secret values - -In this case, it means that there is an issue with the formatting of the generated output. Common issues are missing double quotes around names with hyphens. A quick way to determine what might be wrong is to copy the contents to a scratch `Acornfile` and run `acorn render .` to see if there are formatting issues. diff --git a/docs/docs/30-installation/02-options.md b/docs/docs/30-installation/02-options.md index 56b5bf0ad..239a9b335 100644 --- a/docs/docs/30-installation/02-options.md +++ b/docs/docs/30-installation/02-options.md @@ -3,11 +3,13 @@ title: Options --- ## Acorn image + When you install acorn, it will launch several workloads in your cluster, including an api-server and controller. By default, these workloads will use the `ghcr.io/acorn-io/runtime` image. You can customize this image by setting the `--image` option. This is useful if you are installing acorn in an environment where you are required to pull images from a private registry. ## TLS via Let's Encrypt When you launch an acorn and it has published ports, acorn will generate a unique URL for accessing it, like so: + ```bash $ acorn run -P ghcr.io/acorn-io/hello-world @@ -15,11 +17,15 @@ $ acorn ps NAME IMAGE COMMIT HEALTHY UP-TO-DATE CREATED ENDPOINTS MESSAGE little-snowflake ghcr.io/acorn-io/hello-world eab5f8c77bd6 1 1 6m2s ago https://webapp-little-snowflake-2b3b4c8d.3gjv35.dev-on-acorn.io => webapp:80 OK ``` + By default, endpoints are `http`. To have acorn automatically generate a [Let's Encrypt](https://letsencrypt.org/) certificate and secure your endpoints, you can enable acorn's Let's Encrypt integration like this: + ```bash acorn install --lets-encrypt enabled ``` + If you add this flag, you'll be prompted during install to agree to Let's Encrypt's [Terms of Service](https://letsencrypt.org/documents/LE-SA-v1.3-September-21-2022.pdf) and supply an email. You can supply these as flags too: + ```bash acorn install --lets-encrypt enabled --lets-encrypt-tos-agree=true --lets-encrypt-email ``` @@ -29,9 +35,11 @@ Let's Encrypt integration is only useful if you are running a non-local Kubernet ::: ## Endpoint domain names -Acorn provides several installation options for controlling the domain name used to generate endpoints. These are outlined in detail on our [networking page](50-running/02-networking.md#dns). + +Acorn provides several installation options for controlling the domain name used to generate endpoints. These are outlined in detail on our [network publishing](https://docs.acorn.io/production/publish-http) page. ## Custom CA bundle + Acorn allows a user to provide a custom certificate authority (CA) bundle so that users can add their own private CA that acorn will trust. The most common use case is for acorn to trust an internal image registry that is signed by a private CA. To do so, you will need to go through the following steps: @@ -44,12 +52,10 @@ kubectl -n acorn-image-system create secret generic cabundle --from-file=ca-cert kubectl -n acorn-system create secret generic cabundle --from-file=ca-certificates.crt=/path/to/your/ca-certificates.crt ``` - :::info You must provide the **full** CA certificate chain as it will override existing CA certificates in acorn control plane. ::: - 2. Install acorn with the following option ```bash @@ -57,23 +63,27 @@ acorn install --use-custom-ca-bundle ``` ## Ingress class name + Acorn [requires an ingress controller](30-installation/01-installing.md#ingress-and-service-loadbalancers) to function properly. If your cluster has more than one ingress controller or if it has one but it isn't set as the [default](https://kubernetes.io/docs/concepts/services-networking/ingress/#default-ingress-class), you can explicitly set the ingress class using `--ingress-class-name`. ## Memory + There are two `install` flags for interacting memory: `--workload-memory-default` and `--workload-memory-maximum`. Their values can both be viewed by running `acorn info`. -Check out the [memory reference documentation](100-reference/06-compute-resources.md#memory) for more information. +Check out our page on [sizing](https://docs.acorn.io/production/acorn-sizing) for more information. ### --workload-memory-default + This flag is responsible for setting the memory amount that will get defaulted to should no other value be found. -```console +```console acorn install --workload-memory-default 512Mi ``` Running the above will set all Acorns on the cluster (current and future) to use `512Mi` as their default memory. ### --workload-memory-maximum + This flag sets a maximum that when exceeded prevents the offending Acorn from being installed. ```console @@ -83,6 +93,7 @@ acorn install --workload-memory-maximum 1Gi This will set it so all Acorns on this cluster will be unable to install should they exceed `1Gi` of memory. ## Ignoring user-defined labels and annotations + There are situations where you may not want a user to be able to label or annotate the objects created by Acorn in the workload cluster. For such circumstances, the installation flag `--ignore-user-labels-and-annotations` exists. If this flag is passed to `acorn install`, then, except for the metadata scope, labels and annotations defined by users in their Acorns will be ignored when creating objects. No error nor warning will be produced. If this is too restrictive, and you would like to allow certain user-defined labels and annotations to propagate to the Kubernetes objects then you can use the `--allow-user-label` and `allow-user-annotation` installation flags. These flags take a comma-delimited list of label/annotation keys that are allowed to propagate. You can also specify the flags multiple times and the values will be concatenated to create the final list. If the `--ignore-user-labels-and-annotations` is not supplied or is false, then these flags have no effect. @@ -90,11 +101,13 @@ If this is too restrictive, and you would like to allow certain user-defined lab Note that in order to allow propagation of user-defined labels and annotations on an Acorn installation that previous disallowed it, one must pass `--ignore-user-labels-and-annotations=false` to `acorn install`. ## Manually managing volume classes + The default installation of Acorn will automatically create and sync any storage classes in the cluster to volume classes. That means that when a storage class is created or deleted, the corresponding volume class will also be created or deleted. Additionally, the default storage class in the cluster will also become the default volume class. An admin could edit these generated volume classes to set the fields on them (like min/max/default size) and those updates will be maintained. These generated volume classes will be available to every user in the cluster. If an admin would rather manually manage the volume classes and not have these generated ones, then the `--manage-volume-classes` installation flag is available. The generated volume classes are not generated if this flag is used, and are deleted when the flag is set on an existing Acorn installation. If the flag is again switched off with `--manage-volume-classes=false`, then the volume classes will be generated again. ## Kubernetes NetworkPolicies + Acorn can automatically create and manage Kubernetes [NetworkPolicies](https://kubernetes.io/docs/concepts/services-networking/network-policies/) to isolate Acorn projects on the network level. This behavior can be enabled by passing `--network-policies=true` to `acorn install`, and can later be disabled by passing `--network-policies=false`. @@ -109,6 +122,7 @@ To allow traffic from a specific namespace to all Acorn apps in the cluster, use This is useful if there is a monitoring namespace, for example, that needs to be able to connect to all the pods created by Acorn in order to scrape metrics. ## Working with external LoadBalancer controllers + If you are using an external `LoadBalancer` controller that requires annotations on `LoadBalancer` Services to operate, such as the `aws-load-balancer-controller`, you can pass the `--service-lb-annotation` flag to `acorn install`. This will cause Acorn to add the specified annotations to all `LoadBalancer` Services it creates. The value of the flag should be a comma-separated list of key-value pairs, where the key is the annotation name and the value is the annotation value. For example: ```bash @@ -135,6 +149,7 @@ These annotations get added before the the `LoadBalancer` Service is created whi ::: ## Changing install options + If you want to change your installation options after the initial installation, just rerun `acorn install` with the new options. This will update the existing install dynamically. For strings array flags, you can reset the slice to empty by pass empty string "". For example: @@ -144,6 +159,7 @@ acorn install --propagate-project-annotation "" ``` ## Install Profiles + When you are installing Acorn, you can specify a profile to use. A profile is a set of installation flag defaults that are pre-defined. You can see the list of available profiles by running `acorn install --help`. The default profile is `default`, and it is used if no profile is specified. :::note diff --git a/docs/docs/37-getting-started.md b/docs/docs/37-getting-started.md index 15db380f1..f2360ca3a 100644 --- a/docs/docs/37-getting-started.md +++ b/docs/docs/37-getting-started.md @@ -2,6 +2,10 @@ title: Getting Started --- +:::note +This getting started guide is to walk through using runtime on your own Kubernetes clusters. To get started quickly with Acorn without needing a Kubernetes cluster, check out the [getting started guide] (https://docs.acorn.io/getting-started) for our hosted offering. +::: + In this walk through you will build a Python web app, package it up and deploy it as an Acorn app. The app will interact with Redis and Postgres, which both will be packaged along with the web app in a single Acorn image. @@ -236,7 +240,7 @@ secrets: { - `accessModes`: (list of) modes to allow access to this volume - `secrets`: set of secrets that can be auto-generated and used by any container in the Acorn app - `quickstart-pg-pass`: custom secret name, referenced by `containers.app.env` and `containers.db.env` - - `type`: There are several [secret types](38-authoring/05-secrets.md#types-of-secrets). Here, a token (random string) will be generated for you at runtime. + - `type`: There are several [secret types](https://docs.acorn.io/authoring/secrets#types-of-secrets). Here, a token (random string) will be generated for you at runtime. ## Step 4. Run your Acorn app @@ -406,7 +410,7 @@ acorn rm awesome-acorn ## What's next? -- [Explore all the other awesome Acorn commands](100-reference/01-command-line/acorn.md) -- [Read through the Acornfile reference](100-reference/03-acornfile.md) +- [Explore all the other awesome Acorn commands](reference/command-line/acorn) +- [Read through the Acornfile reference](https://docs.acorn.io/reference/acornfile) - [Have a look what makes up Acorn](60-architecture/01-ten-thousand-foot-view.md) -- [Try some of our other example Acorns](https://github.com/acorn-io/examples) +- [Try our hands on guide for a more in depth overview](https://docs.acorn.io/hands-on-with-acorn) diff --git a/docs/docs/38-authoring/00-overview.md b/docs/docs/38-authoring/00-overview.md deleted file mode 100644 index 249233fe8..000000000 --- a/docs/docs/38-authoring/00-overview.md +++ /dev/null @@ -1,435 +0,0 @@ ---- -title: Overview ---- - -The primary goal of the Acornfile is to quickly and easily describe how to build, develop, and run containerized applications. - -The syntax is very similar to JSON and YAML that you're probably already familiar with from other tools. - -The resulting artifact defined by the Acornfile and produced during `acorn build` is a complete package of your application. It includes all the container images, secrets, data, nested Acorns, etc. in a single OCI image that can be distributed through a registry. - -## The primary building blocks - -### Objects - -In the Acornfile file the primary building block is an object. The generic syntax for any object is: - -```acorn -key: { - // ... fields ... -} -``` - -They start with a name `key` and wrap a collection of fields and values in `{}`. A more Acorn specific example is: - -```acorn -containers: { - "my-app": { - // ... - } -} -``` - -In the above example, there is an object called `containers`, which contains another object called `my-app`. Keys do not need to be quoted, unless they contain a `-`. - -For convenience, you can collapse objects which have only one field to a single `:` line and omit the braces. For example these: - -```acorn -containers: foo: image: "nginx" - -containers: bar: build: { - context: "." - target: "static" -} -``` - -are equivalent to: - -```acorn -containers: { - foo: { - image: "nginx" - } -} - -containers: { - bar: { - build: { - context: "." - target: "static" - } - } -} -``` - -### Lists - -The other main building block is a list. - -```acorn -containers: { - myapp: { - // ... - ports: [ - "80/http", - "8080/http", - ] - } -} -``` - -Lists are surrounded by `[]`. Items are separated by a comma. The last item can include an optional trailing comma. - -## Fields - -A `field` is a label and a value, we have seen multiple examples of `fields` in the previous examples. Here we will dive deeper. - -### Field names - -In an Acornfile fields can be strings with [a-zA-Z0-9_] without being wrapped in double quotes. You can use `-`, `/`, and `.` if you use double quotes around the field name. - -```acorn -// Valid field names -aLongField: "" -"/a/file/path": "" -"my-application-container": "" -``` - -### Assigning field values - -Variables allow you to store values and later reference them elsewhere in the Acornfile. The syntax for defining a variable is shown below. Values can be a string, number, boolean, list, object, or null. - -```acorn -localData: { - myString: "" - myInteger: 5 - myBool: true - myObject: {} - myList: [] -} -``` - -### Strings - -Strings can be a single line or multiline. A single line string is surrounded by `"` quotes. - -Multiline strings are enclosed in triple quotes `"""`. The opening `"""` must be followed by a newline. The closing `"""` must also be on it's own line. The whitespace directly preceding the closing quotes must match the preceding whitespace on all other lines and is not included in the value. This allows you to indent the text to match current level without the indenting becoming part of the actual value. - -```acorn -singleLine: "Hi!" -multiLine: """ - Hello - World! - """ -# multiLine is equivalent to "Hello \nWorld!" -``` - -### Numbers - -Numbers are integers by default unless they contain a decimal. - -```acorn -int: 4 -float: 4.2 -``` - -### Boolean - -Booleans are `true` or `false`. - -### Null - -Null is `null`. - -### Comments - -You can add comments to document your Acornfile. Comments start with `//` and continue for the rest of the line - -```acorn -// This is a comment -some: "value" // This is a comment about this line -``` - -### Accessing fields - -To reference a variable elsewhere in the file, you separate the key fields of the path by a `.`. - -Given these variables: - -```acorn -localData: { - myVariable: "" - myInteger: 5 - myBool: true - myObject: { - aKey: "value" - } - "my-app": { - // ... - } -} - -// Can Be accessed like - -v: localData.myVariable -i: localData.myInteger -b: localData.myBool -s: localData.myObject -s0: localData.myObject.aKey -s1: localData.myObject["aKey"] -a: localData."my-app" -``` - -### Scopes - -Fields that reference another field will look for a value starting at the nearest enclosing scope and working upwards until reaching the top-level. - -```acorn -port: 3307 -containers: app: { - ports: localData.port // Evaluates to 3306 -} -data: port // Evaluates to 3307 -localData: { - port: 3306 - exposedServicePort: port // Evaluates to 3306 -} -``` - -In the above example, `containers.app.ports` would be `3306` along with `localData.exposedServicePort`. - -#### Aliases - -Because of scoping in the previous example, it would not be possible in the above example to set any value under localData to a value of `port`(3307). One way to address this is to use the `let` operator to alias the port variable. - -```acorn -let topLevelPort = port -port: 3307 -containers: app: { - ports: localData.port // Evaluates to 3306 -} -data: port // Evaluates to 3307 -localData: { - port: 3306 - exposedServicePort: topLevelPort // Evaluates to 3307 -} -``` - -In the example the top level `port` variable is aliased to `topLevelPort` and assigned to `localData.exposedServicePort`. - -### String interpolation - -Variables can be inserted into a string by wrapping their name with `\()`. For example: - -```acorn -args: { - userAdjective: "cool" -} - -localData: { - config: { - key: "This is something \(args.userAdjective)" - } -} - -# localData.config.key is "This is something cool" -``` - -Interpolation can also be used for field names: - -```acorn -localData: { - index: 3 -} - -containers: { - "my-app-\(localData.index)": { - // ... - } -} - -# A container named "my-app-3" is being defined -``` - -### Assigning a variable to another field - -Assigning a variable to a field uses the variable accessor. - -```acorn -localData: { - myTokenLength: 64 -} - -secrets: { - "my-secret": { - type: "token" - params: { - length: localData.myTokenLength // length is now 64 - } - } -} -``` - -### Basic Operators - -All the basic math and comparison operators you'd find in a typical programming language are supported: - -| Operator | Symbol | Example | Result | -| :--------|:--------|:--------|:-------| -| Addition | `+` | `1 + 1` | `2` | -| Subtraction | `-` | `4 - 1` | `3` | -| Multiplication | `*` | `4 * 2` | `8` | -| Division | `/` | `5 / 2` | `2.5`| -| Greater than | `>` | `2 > 1` | `true` | -| Greater than or equal | `>=` | `2 >= 2` | `true` | -| Less than | `<` | `1 < 1` | `false` | -| Less than or equal | `<=` | `1 <= 1` | `true` | -| Equals | `==` | `1 == 2` | `false` | -| Does not equal | `!=` | `1 != 2` | `true` | -| Not | `!` | `!true` | `false` | -| Or | \|\| | true \|\| false | `true` | -| And | `&&` | `true && false` | `false` | - -`-` can also be used to negate a value: - -```acorn -a: 42 -b: -a // -42 -``` - -Operations can be grouped with parenthesis and combined with `&&` and `||`: - -```acorn -a: 5 -b: a/(1 + 1) // 2.5 -c: (2+2)*4/8 // 2 -d: -c * 10 // -20 -e: b > c // true -f: e && b > 5 // false -``` - -### String Operators - -Strings can be concatenated, repeated, and compared: - -| Operator | Symbol | Example | Result | -|:---------|:-------|:--------|:-------| -| Concatenate | `+` | `"hello " + "world"` | `"hello world"` | -| Repeat | `*` | `"hi"*5` | `"hihihihihi"` | -| Greater than | `>` | `"hi" > "bye"` | `true` | -| Greater than or equal | `>=` | `"foo" >= "bar"` | `true` | -| Less than | `<` | `"foo" < "foo` | `false` | -| Less than or equal | `<=` | `"foo" <= "foo"` | `true` | -| Equals | `==` | `"foo" == "bar"` | `false` | -| Does not equal | `!=` | `"foo" != "bar` | `true` | -| Matches regular expression | `=~` | `"hi bob" =~ "^h"` | `true` | -| Does not match regular expression | `!~` | `"hi bob" !~ "^h"` | `false` | - -### Regular Expressions - -Regular expression syntax is the one accepted by RE2 outlined here [https://github.com/google/re2/wiki/Syntax](https://github.com/google/re2/wiki/Syntax). One exception is `\C` is not accepted. - -## Conditionals - -### If statements - -Support for standard `if` statements is available in an Acornfile. If conditions evaluate to a boolean, and apply their body if the condition is true. - -```acorn -localData: { - scale: 1 -} - -if localData > 1 { - // ... Do something -} -``` - -`if` statements can be added at any level or nested within each other, but there is no `else` in this format. - -### If-else expressions - -Ternary or "if-else" expressions are available through a built-in function which takes 3 arguments: - -```std.ifelse(condition, value-if-true, value-if-false)``` - -The following example will publish either port 3000 or 80 depending on `args.dev`: - -```acorn -containers: { - app: { - ports: publish: std.ifelse(args.dev, "3000/http", "80/http") - } -} -``` - -See the [function library](../reference/functions#ifelse) for more information. - -## For loops - -The Acornfile syntax provides a for loop construct to iterate through objects and lists. - -```acorn -for i in std.range(0, 10) { - containers: { - "my-instance-\(i)": { - // ... - } - } -} -``` - -### Object field comprehensions - -```acorn -localData:{ - dataVols: { - dbData: "/var/lib/mysql" - backups: "/backups" - } -} - -for k, v in localData.dataVols { - volumes: { - "\(k)": {} - } - containers: { - // ... - dirs: { - "\(v)": "volumes://\(k)" - } - // ... - } -} -``` - -### List comprehensions - -Acornfile - -```acorn -localData: { - list: ["one", "two", "three"] -} - -localData: { - multiLineContent: std.join([for i in localData.list {"Item: \(i)"}], "\n") -} -``` - -Renders to: - -```acorn -localData: { - list: ["one", "two", "three"] - multiLineContent: """ - Item: one - Item: two - Item: three - """ -} -``` - -## Function Library - -Acorn includes a built-in library of functions to perform common operations. See the [function library](../reference/functions) for more information. diff --git a/docs/docs/38-authoring/01-best-practices.md b/docs/docs/38-authoring/01-best-practices.md deleted file mode 100644 index 99fc132e3..000000000 --- a/docs/docs/38-authoring/01-best-practices.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Best Practices ---- - -When authoring an Acorn it is best to offer a set of defaults so the user can simply `acorn run [IMAGE]` and be able to try out the Acorn without diving into its documentation first. - -### User arguments - -Provide the user with `profiles` for common runtime configurations, e.g. for production and testing. Bake in best practices where possible. - -Avoid passing sensitive information through the Acorn arguments. Instead define secrets that are auto-generated or bound at runtime with user-defined values. - -### Avoid string interpolation for configuration files - -It is best to keep configuration to a minimum within the Acornfile. Users should be able to pass in additional configuration and have that merged with the App's internal values. - -### Secrets - -Allow secrets to be auto-generated by default and kept within the Acorn where possible. - -### Images - -When adding Acorn to a project, let Acorn handle the building of the Docker image. - -When using existing images, prefer official DockerHub library images if available. - -Use specific versions and tags of images, at least to the minor version in SemVer. Acorn will package all images at build time and reference them by their SHA, ensuring that the application will always pull the same image. For maintainability and ease of troubleshooting, using a specific version is preferred. - -## Upgrades - -When dealing with stateful applications, use a unique container per instance. Do **not** use scale for stateful applications. This ensures each instance has a unique and stable FQDN. Scaling up and down is always deterministic. - -Each application container should use `dependsOn` for the instance before it. This will ensure that only one application container is taken down at a time. diff --git a/docs/docs/38-authoring/02-structure.md b/docs/docs/38-authoring/02-structure.md deleted file mode 100644 index c0ddfb879..000000000 --- a/docs/docs/38-authoring/02-structure.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -title: Structure ---- - -## Acornfile - -### Key ordering - -An Acornfile has predefined top level structs, and it is recommended to define them in the following order: - -```acorn -name: "// Friendly name of the application" -description: "// A brief description of the application" -readme: "// This is a more descriptive version of the application. Can be pulled in from a file" -info: "// rendered text that describes what the user should do after deployment" -icon: "// a location to an image for the application" -args: { // defines arguments the consumer can provide } -profiles: { // defines a set of default arguments for different deployment types } -services: { // defines services that the application depends on } -containers: { // defines the containers to run the application } -volumes: { // defines persistent storage volumes for the containers to consume } -jobs: { // defines tasks to run on changes or via cron } -acorns: { // other Acorn applications that need to be deployed with your app (databases, etc.) } -secrets: { // defines secret bits of data that are automatically generated or passed by the user } -localData: { // default data and configuration variables } -``` - -At a minimum, the Acornfile needs to specify at least one container to run. - -```acorn -containers: { - nginx: { - image: "nginx" - } -} -``` - -### Defining conditional blocks - -When defining components that are conditionally deployed, use the same ordering as the top level keys within the block. - -For example: - -```acorn -args: enableRedis: false - -containers: { - nginx: { - image: "nginx" - env: { - DB_PASS: "secrets://db-pass/password" - DB_USER: "secrets://db-pass/username" - } - } -} - -if args.enableRedis { - containers: nginx: env: { - REDIS_HOST: "redis" - REDIS_PASS: "secrets://redis-password/token" - } - - containers: redis: { - image: "redis" - env: REDIS_PASSWORD: "secrets://redis-password/token" - } - - secrets: "redis-password": { - type: "token" - } -} - -secrets: "db-pass": type: "basic" -``` - -The above shows how to use an `if` block to add and configure a new container in the Acorn. - -### User defined key requirements - -Second-level keys defined by the user underneath the `containers`, `volumes`, `secrets`, and `jobs` blocks must: - -* Contain only lowercase alphanumeric characters, `-` or `.` -* Start with an alphanumeric character -* End with an alphanumeric character - -Keys defined in `args`, `profiles`, and `localData` should use camelCase. diff --git a/docs/docs/38-authoring/03-containers.md b/docs/docs/38-authoring/03-containers.md deleted file mode 100644 index 9cde11c11..000000000 --- a/docs/docs/38-authoring/03-containers.md +++ /dev/null @@ -1,384 +0,0 @@ ---- -title: Containers ---- - -## Defining a container - -The container section in the Acornfile defines everything about the individual components needed to run your app. Each container definition will define a service in your Acorn application. A basic example of a container definition that exposes a network endpoint looks like the following: - -```acorn -containers:{ - "my-webapp": { - image: "nginx" - ports: publish: "80/http" - } -} -``` - -## Defining a container built from a Dockerfile - -### Standard build options - -Acorn provides a mechanism to build your own containers for your application. If you have an existing project that already defines a Dockerfile, you can build it using Acorn. - -```acorn -containers: { - "my-app": { - build: { - context: "." - } - } -} -``` - -Now when `acorn build .` or `acorn run -i .` is run, the `my-app` container will be built and packaged as a part of the Acorn. It will look for a Dockerfile in the `./` directory. - -### Customized build behavior - -Acorn provides options to customize the building of OCI images. If the Dockerfile is not in the root directory of the `context` you can specify the location using the `dockerfile` parameter. If the image is a multi-stage build, the desired target can be specified. See [args and profiles](07-args-and-profiles.md) to see how to customize these values at build and runtime. - -```acorn -containers: { - "my-app": { - build: { - context: "." - dockerfile: "./pkg/Dockerfile.prod" - target: "dev" - } - } -} -``` - -You can also specify a `buildArgs` object as part of the build section to pass arguments to the build. - -```acorn -containers: { - app: { - build: { - // ... - buildArgs: { - param: "value" - // ... - } - } - } -} -``` - -## Network ports - -### Basic definition - -Most containers can be interacted with over the network. In order for containers to be reached by other containers and applications, the network ports must be defined as part of the container. - -A port definition is: - -```shell -[NAME]:[/TYPE] -``` - -Where: - -* `NAME`: is an optional name for the port, like `db` or `metrics`. -* `PORT`: is the required numeric value of the port. -* `TYPE`: is an optional value of `UDP`, `TCP`, or `HTTP`. - -An example of a named port: - -```acorn -containers: { - db: { - image: "mysql" - ports: expose: "mysql:3306/tcp" - } -} -``` - -When the user runs the built Acorn image, they can reference this port by name `--expose sql:3306:mysql:3306`. - -### Scopes - -As an author, there are three scopes used to define the port's **default** access behavior: `internal`, `expose`, and `publish`. These settings can be changed at runtime by the operator. - -| Scope | Accessibility | -| ------|-----------------------------------------------------| -| `internal`| Containers defined within the Acorn image (default) | -| `expose` | Containers running across the cluster | -| `publish` | Accessible outside the cluster by consumers | - -```acorn -containers: { - "my-webapp": { - image: "nginx" - ports: [ - "5000/http", - ] - } -} -``` - -The above example defines an HTTP port `5000` accessible to other containers defined in this Acorn image. - -The next example shows the `expose` and `publish` settings, used to define ports that are meant to be accessed outside of the Acorn app or published outside the cluster. If an Acorn image is going to provide a network service to multiple apps, something like a database, you will likely want to expose the port so it can be linked to other Acorn apps. - -```acorn -containers: { - "my-webapp": { - image: "nginx" - ports: { - expose: "5001/http" - publish: "8080/http" - } - } - database: { - image: "mysql" - ports: "3306/tcp" - } -} -``` - -This Acornfile defines two containers, one called `my-webapp` and the other `database`. The `my-webapp` container is exposing port 8080 outside of the cluster and port 5001 to apps running on the cluster. When launching this Acorn the port can be published outside the cluster and accessed by linked Acorns. - -In the database container, we are using the `ports` parameter because only the my-webapp container will communicate with the database. - -## Environment variables - -Containers often use environment variables as a way to configure common settings or pass in secrets. Acorn supports both methods in the container definition. - -```acorn -containers: { - db: { - image: "mysql" - // ... - env: { - "MYSQL_ROOT_PASSWORD": "secret://root-pass/token" - "DATABASE_NAME": "test-app" - "USER_SET_VALUE": args.userValue - } - } -} -``` - -The above example has a `db` container with the `MYSQL_ROOT_PASSWORD` variable set by a [secret](38-authoring/05-secrets.md) in the Acornfile. The `DATABASE_NAME` is set to a static value, and the `USER_SET_VALUE` is defined by a user [arg](38-authoring/07-args-and-profiles.md). When launched the container can access these environment variables as needed. - -## Files - -Files are defined in a container where the key is the location inside the container, and the value is the contents of the file. - -```acorn -containers: { - web: { - image: "nginx" - // ... - files: { - "/etc/htpasswd": "secret://htpasswd-file/content" - "/usr/share/nginx/html/index.html": "

Hello!

" - } - // ... - } -} -``` - -In the above, the file `/etc/htpasswd` will contain the contents from a secret that contains the appropriate values for an htpasswd file. The `/usr/share/nginx/html/index.html` will contain static content from the string. - -## Directories - -Directories are defined in their own block and are used to mount volumes, files from a secret, or -pull in content at build time. The block has keys that are path names inside the container and values are the source. - -```acorn -containers: { - web: { - image: "nginx" - // ... - dirs:{ - "/init-scripts": "./scripts" - "/home/.ssh/": "secret://ssh-keys" - "/data": "volume://data-vol" - } - // ... - } -} -``` - -In the above file, when building the Acorn the `/init-scripts` directory will be populated with the contents of the local `./scripts` directory. Files are copied in with the same permissions. - -The `/home/.ssh/` directory will have files named after the secrets keys and content. The `/data` directory will have the volume `data-vol` mounted. - -## Probes - -Applications running for a long time sometimes fail in strange ways, or take time to startup before they are ready to receive traffic. To ensure the container is running and ready to receive traffic there are probes. - -There are three types of probes: `readiness`, `liveness`, and `startup`. Probes are defined per container in a list. You can define one of each type per container. If the probes fail, the container is restarted. - -Each probe type has the following parameters that can be optionally set. - -| Parameter | Default | Description | -| ----------|---------|-------------| -| `initialDelaySeconds`| 0 | Number of seconds to wait after the container is started before probes are initiated. | -| `periodSeconds` | 10 | Number of seconds between probe attempts. | -| `timeoutSeconds` | 1 | Number of seconds before the probe times out. | -| `successThreshold` | 1 | Number of consecutive successful probes before considering the container healthy. | -| `failureThreshold` | 3 | Number of consecutive failed probes before considering the container unhealthy. | - -There are three types of checks that can be used to check the health of the container. A script can be executed inside the container, an HTTP endpoint can be checked, or a TCP endpoint can be checked. Each of the probe types can use one of any of these check types. - -### Liveness probes - -The liveness probe detects that the container is up and considered running. The example here defines an HTTP type of check, though TCP and exec types could also be used. - -```acorn -containers: { - web: { - image: "nginx" - // ... - probes: [ - { - type: "liveness" - http: { - url: "http://localhost/healthz" - headers: { - Accept: "application/json" - } - } - }, - ] - } -} -``` - -Headers are an optional field on the HTTP health probe type. - -### Readiness probes - -A readiness probe means the container is ready to receive traffic. Sometimes when a database server starts it needs to have data loaded. During this data loading process, it should not be contacted by the application in case it has incomplete data. You can use the readinessprobe probe to prevent other containers from accessing this container before it is ready. - -This example will use an exec check, but HTTP and TCP checks could also be used. - -*Note: Readiness probes do not wait for the liveness probe to succeed first. If you need the readiness probe to wait you should use the `initialDelaySeconds` parameter to delay. Alternatively, the startup probe can also be used.* - -```acorn -containers: { - db: { - image: "mysql" - env: { - MYSQL_ROOT_PASSWORD: "secret://db-root-pass/token" - // ... - } - // ... - probes: [ - { - type: "readiness" - initialDelaySeconds: 10 - exec: command: [ - "mysqladmin", - "status", - "-uroot", - "-p${MYSQL_ROOT_PASSWORD}", - ] - }, - ] - } -} -``` - -### Startup probes - -Startup probes exist to give slow starting applications time to load data and/or configuration before starting the liveness and readiness probes. The startup probe should use the same command, HTTP, or TCP check as the liveness probe with enough time to cover the worst case startup scenario. The time is calculated by `failureThreshold * periodSeconds`. - -```acorn -containers: { - web: { - image: "nginx" - // ... - probes: [ - { - type: "liveness" - tcp:{ - url: tcp://localhost:80 - } - }, - { - type: "startup" - failureThreshold: 10 - periodSeconds: 6 - tcp:{ - url: tcp://localhost:80 - } - } - ] - } -} -``` - -In the above example the `web` container would have 60 seconds (10 tries * 6 seconds) to startup before being restarted. - -## Defining sidecar containers - -Sometimes a container needs some setup before it runs, or has additional services running alongside it. For these scenarios, the `sidecar` can be defined as part of the container. - -```acorn -containers: { - frontend: { - image: "nginx" - // ... - sidecars: { - "git-clone": { - image: "my-org/git-cloner" - init: true - } - "metrics-collector": { - image: "my-org/metrics-collector" - ports: "5000/http" - } - } - } -} -``` - -In the above file, we have two sidecars defined. One is `git-clone` which is defined as an `init` container. The init container starts up before the primary container. Each init container should run a single task, and must complete successfully before additional init and application containers are started. - -The second sidecar above is a service that runs alongside the primary frontend container and in this case provides a metrics endpoint. You can define as many sidecar containers as you need to run and support your application. - -## Memory - -There are times that you want to define the amount of memory that an Acorn will use for resource management purposes. This can be defined by the `memory` property and is settable for all `workloads` (`containers` and `jobs`). Check out the [memory reference documentation](100-reference/06-compute-resources.md#memory) for more information on ways to set memory. - -```acorn -containers: { - nginx: { - image: "nginx" - ports: publish: "80/http" - files: { - "/usr/share/nginx/html/index.html": "

My first Acorn!

" - } - memory: 512Mi - } -} -``` - -:::tip -The `memory` property can be abbreviated to `mem` in the file. -::: - -## Compute Classes - -When you want to specify what infrastructure your Acorn's workload will run on, you use Compute Classes. You can set the class of a workload by defining by the `class` property definable on all workloads (`containers` and `jobs`). Check out the [compute class documentation](100-reference/06-compute-resources.md#compute-classes) for more information. - -```acorn -containers: { - nginx: { - class: "sample-compute-class" - image: "nginx" - ports: publish: "80/http" - files: { - "/usr/share/nginx/html/index.html": "

My first Acorn!

" - } - } -} -``` - -## Additional Reading - -* [Acorn Security Considerations](60-architecture/02-security-considerations.md) -* [Acornfile reference](100-reference/03-acornfile.md) diff --git a/docs/docs/38-authoring/04-volumes.md b/docs/docs/38-authoring/04-volumes.md deleted file mode 100644 index a325c4889..000000000 --- a/docs/docs/38-authoring/04-volumes.md +++ /dev/null @@ -1,202 +0,0 @@ ---- -title: Volumes ---- - -Volumes are used to store persistent data in your applications. Volumes can be bound to containers, sidecars, and jobs whenever persistence is needed. Defining a volume in the Acornfile is done under the `volumes` key and referenced via the `volumes://` uri path when mounting. - -```acorn -containers: { - "my-app": { - image: "web" - // ... - dirs: { - "/data": "volume://my-data" - } - } -} -// ... -volumes: { - "my-data": {} -} -// ... -``` - -In the above example, there is a `my-data` volume defined and mounted into the `my-app` container at the `/data` path. The volume using the `default` volume class defined in the cluster. If the `default` volume class does not have a default size set, then the volume will be created a size of 10G. The default volume type will be created as a `ReadWriteOnce` volume and consumable by multiple containers on a single host. - -A volume has the following fields that can be customized, here is the above volume defined with all of the fields. - -```acorn -volumes: { - "my-data": { - size: 10G - class: "default" - accessModes: "readWriteOnce" - } -} -``` - -The volume class used may have restrictions on the size of volumes created or the access modes available. If your volume uses a class that is not available or uses class settings that violate its rules, then your app will build but will not run. A descriptive error will be produced to explain any failures. - -## Volumes with subpaths - -Volume subpaths allow you to utilize the underlying file structure of a volume to reference specific parts within it. This is useful for times that we want to mount specific, but not all, parts of a volume to a container. For example, say that we have a volume, named `example-volume`, with the following content. - -``` -example-volume -|- data-1 - |- nested-data-1 - |- nested-data-2 -|- data-2 -``` - -In this example, we want to create a mount for the content found in `data-1` to a container. Without subpaths, our Acornfile would look something like this. - -```acorn -containers: { - "my-app": { - image: "web" - // ... - dirs: { - "/data": "volume://example-volume" - } - } -} -``` - -This makes the content of `example-volume` available to our container. If we wanted to access `data-1`, we can now do so under the `data-1` directory. However, this also comes along with the `data-2` directory that we don't care to have. We can solve this by using subpaths. - -```acorn -containers: { - "my-app": { - image: "web" - // ... - dirs: { - "/data": "volume://example-volume?subpath=data-1" - } - } -} -``` - -As a result, the only content mounted in our container from `example-volume` is `data-1`. We can take this a step further and have another container that has a mount for the `data-2` directory without bringing along `data-1`. - -```acorn -containers: { - "my-app": { - image: "web" - // ... - dirs: { - "/data": "volume://example-volume?subpath=data-1" - } - } - "my-other-app": { - image: "web" - // ... - dirs: { - "/data": "volume://example-volume?subpath=data-2" - } - } -} -``` - -By utilizing subpaths, we now have a single volume being utilized by two containers without collisions occuring between them. If you'd like to see another example of subpaths in action you can take a look at our [Getting Started](37-getting-started.md) guide. - -## Volumes with sidecars - -Sidecars can share volumes with the primary app container or have volumes for their exclusive use. In order to share data, a volume must be created and mounted in both containers. - -```acorn -containers: { - frontend: { - image: "nginx" - dirs: { - "/var/www/html": "volume://web-content" - } - // ... - sidecars: { - image: "git-cloner" - // ... - dirs: { - "/var/www/html": "volume://web-content" - } - } - } -} -// ... -volumes: { - "web-content": {} -} -``` - -In the above example both containers will have read-write access to the data in `volume://web-content`. - -A volume can also be exclusively mounted in a sidecar container. - -## Ephemeral storage - -There are two ways to create ephemeral scratch type of storage. This type of volume is useful when you are transforming data perhaps during a restore process. - -A shorthand way to define the volume is: - - ```acorn -containers: { - frontend: { - // ... - dirs: { - "/scratch": "ephemeral://scratch-data" - } - } -} -``` - -The above is equivalent to: - -```acorn -containers: { - frontend: { - // ... - dirs: { - "/scratch": "volume://scratch-data" - } - } -} - -volumes: { - "scratch-data": { - class: "ephemeral" - } -} -``` - -The `ephemeral` class is a special case that Acorn will handle behind the scenes to create an `emptyDir` volume. - -## Volumes with jobs - -Volumes can also be mounted between app containers and job containers. - -```acorn -containers: { - db: { - // ... - dirs: { - "/var/lib/db_data": "volume://db-data" - } - // ... - } -} - -volumes: { - "db-data": {} - "backups": {} -} - -jobs: { - backups: { - // ... - dirs: { - "/backups": "volume://backups" - "/var/lib/db_data": "volume://db-data" - } - // ... - } -} -``` diff --git a/docs/docs/38-authoring/05-secrets.md b/docs/docs/38-authoring/05-secrets.md deleted file mode 100644 index 23ad8cbc5..000000000 --- a/docs/docs/38-authoring/05-secrets.md +++ /dev/null @@ -1,291 +0,0 @@ ---- -title: Secrets ---- - -Secrets are used to provide data that is considered sensitive like passwords, keys, and other sensitive information. Acorn provides multiple secret types, and makes it easy to create closed loop systems where information can be kept within the defined Acorn. - -To learn how to use secrets while deploying an Acorn image see [Args and Secrets](50-running/01-args-and-secrets.md) - -## Using secrets in an Acornfile - -Secrets must be defined in the Acornfile. The values can be generated by Acorn or provided by an existing secret in the cluster. Secrets should not be assigned values from user arguments. Secrets can be consumed in containers by referencing them by the `secret:///` URI syntax. - -It is possible to define the behavior when the secret is updated to a new value. The default is to redeploy the containers one at a time. If that operation is unsafe, or requires more user intervention, you can add the `?onchange=no-action` to the end of the secret reference URI. - -### Consume secret in an environment variable - -Some containers use environment variables for secret bits of data. The MariaDB container for instance uses an environment variable to set the root password. - -```acorn -containers: { - db: { - image: "mysql" - // ... - env: { - "MYSQL_ROOT_PASSWORD": "secret://db-root-password/token" - } - } -} -// ... -secrets: { - "db-root-password": { - type: "token" - } -} -``` - -The example shows the secret `db-root-password` being consumed as an environment variable in the db container. The secret is of type token and will automatically be generated at runtime by Acorn. The user can then use the Acorn CLI to get the credential if needed. - -### Consuming secrets in templates - -Secrets in templates are wrapped in `${}`. It is possible to pass secret configuration data to a container in a pre-rendered form. This next example shows how you can add a configuration file with sensitive data. - -```acorn -containers: { - web: { - image: "nginx" - // ... - files: { - "/etc/nginx/conf.d/website.conf": "secret://website-conf/template" - } - } -} -// ... -secrets: { - "proxy-auth": { - type: "opaque" - data: { - "basic-auth-string": "credentialsgohere" - } - } - "website-conf": { - type: "template" - data: { - template: """ - server { - listen 80; - // ... - location / { - // ... - proxy_set_header Authorization "Basic ${secret://proxy-auth/basic-auth-string}" - } - } - """ - } - } -} -``` - -The above example has a container that will use the `website-conf` secret to create a config file. Before rendering the config file, Acorn will substitute the `basic-auth-string` into the template. This technique makes it possible for the user to pass in the sensitive `basic-auth-string` at runtime by [binding a pre-existing secret](50-running/01-args-and-secrets.md#binding-a-secret-at-runtime). - -### Populating a directory with files - -You can populate a directory with sensitive data using a secret. The example below shows populating the `~/.ssh` directory with private keys from a secret. - -```acorn -containers: { - git: { - image: "my-git" - dirs: { - "/home/user/.ssh": "secret://user-provided-ssh-keys" - } - } -} -secrets: { - "user-provided-ssh-keys": { - type: "opaque" - data: { - //Example content from bound secret. - //id_rsa: "-----BEGIN OPENSSH PRIVATE KEY-----...." - //id_rsa_aws: "-----BEGIN OPENSSH PRIVATE KEY-----..." - //Do not put private keys in Acornfile - } - } -} -``` - -The above will populate the `/home/user/.ssh` directory with the content of each item in files named after the key. - -```shell -# inside the git container -ls /home/user/.ssh -id_rsa id_rsa_aws -``` - -## Types of secrets - -Acorn makes multiple types of secrets available to the Acorn author. - - 1. **Basic:** Used to generate and/or store usernames and passwords. - 1. **Template:** Used to store configuration files that contain sensitive information. - 1. **Token:** Used to generate and/or store long secret strings. - 1. **Generated:** Used to take the output of a `job` and pass along as a secret bit of info. - 1. **Opaque:** A generic secret that can store defaults in the Acorn, or is meant to be overridden by the user to pass unknown/unstructured sensitive data. - -### Basic secrets - -Basic secrets are defined in the secrets block with the type "basic". - -```acorn -// ... -secrets: { - "my-creds": { - type: "basic" // required - data: { - username: "" // optional - password: "" // optional - } - } -} -``` - -The basic secret type is used for username / password pairs. The key names must be username and password. If one or both of the fields are defined with a non-empty string, those values will be used. If the empty string, the default value, is used Acorn will generate random values for one or both. - -### Template secrets - -The template secret can be used to render and store multiple secret values into a single output. It has the following format: - -```acorn -// ... -secrets: { - "password-file": { - type: "template" // required - data: { - "password.txt": """ - password=${secret://token/token} - """ - } - } - "token": { - type: "token" - } -} -``` - -In the above example the secret renders a template secret with one key called "password.txt", consuming the token from the secret named "token." See [advanced topics](38-authoring/30-advanced.md) for other uses for the template secret type. - -### Token secrets - -Token secrets are useful for generating a password or secure string used for passwords when the user is already known or not required. - -```acorn -secrets: { - "my-token": { - type: "token" // required - params: { - length: 32 // optional - characters: "abcdedfhifj01234567890" // optional - } - data: { - token: "" // optional - } - } -} -``` - -The token secret type must be defined. The params allow customization of the generated token. By default tokens are 54 characters in length. By defining the `length` param the token can be customized to be within 0-256 characters long. The `characters` param allows the user to define the allowed character values within the token. - -The `token` field in the data object is optional and needs to be left the default empty string if Acorn should generate the token. If the `token` is defined that value will always be used. - -### Generated secrets - -Generated secrets allow storing sensitive data output from a [job](38-authoring/06-jobs.md). - -```acorn -containers: { - "frontend-proxy": { - // ... - files: { - "/etc/htpasswd": "secret://htpasswd-file/content" - } - // ... - } -} -jobs: { - "htpasswd-create": { - env: { - "USER": "secret://user-creds/username" - "PASS": "secret://user-creds/password" - } - entrypoint: "/bin/sh -c" - image: "httpd:2" - // Output of a generated secret needs to be placed in the file /run/secrets/output. - cmd: ["htpasswd -Bbc /run/secrets/output $USER $PASS"] - } -} -secrets: { - "user-creds": { - type: "basic" - } - "htpasswd-file": { - type: "generated" // required - params: { - job: "htpasswd-create" // required - format: "text" // optional - } - } -} -``` - -In the above example, there is a basic secret that Acorn will generate a username and password for. The job will run with the basic secret data passed in as environment variables. When the job runs it will generate an htpasswd file and write the content out to the required `/run/secrets/output` target. The contents of the `/run/secrets/output` file will be placed into the secret `htpasswd-file` and consumed by the `frontend-proxy` container. The key `content` must be used when referencing the value. - -The `job` parameter is always required, and is the name of the job that will generate the output. The `format` parameter is optional and defaults to text. - -### Opaque secrets - -Opaque secrets have no defined structure and can have arbitrary key value pairs. These types of secrets are best used for allowing a user to input sensitive data at runtime. In some cases an unstructured secret can be used if the user will be passing data that will be used in user defined templates. Expected keys should be predefined with reasonable defaults to provide the user some context. - -```acorn -secrets: { - "user-secret-data": { - type: "opaque" - } -} -``` - -## External secrets - -External secrets are defined in the Acornfile to specify a specific secret must be present in the cluster before the Acorn can be deployed. The definition must include the field `external` with the value of the expected name of the secret in the cluster. - -```acorn -containers: app: { - image: ubuntu - entrypoint: ["sleep"] - command: ["3600"] - env: { - USER: "secret://foo/user" - PASS: "secret://foo/pass" - } -} - -secrets: foo:{ - external: "basic-creds" -} -``` - -The above example requires a secret named `basic-creds` to be present in the cluster before the Acorn can be deployed. - -For readability and documentation purposes, the best practice to define the type and data fields that the external secret is expected to have. This is optional and the values will be ignored by Acorn. - -```acorn -containers: app: { - image: ubuntu - entrypoint: ["sleep"] - command: ["3600"] - env: { - USER: "secret://foo/user" - PASS: "secret://foo/pass" - } -} - -secrets: foo: { - external: "basic-creds" - type: "opaque" - data: { - user: "username" - pass: "password" - } -} -``` - -Looking at the above example a user knows they must create a secret named `basic-creds` with keys/values for `user` and `pass` before the Acorn can be deployed. diff --git a/docs/docs/38-authoring/06-jobs.md b/docs/docs/38-authoring/06-jobs.md deleted file mode 100644 index 70f3b1acc..000000000 --- a/docs/docs/38-authoring/06-jobs.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -title: Jobs ---- - -Jobs are containers that perform one-off or scheduled tasks to support the application. Jobs are defined in their own top-level `jobs` section of the Acornfile. A job container will continue to run until it has successfully completed all operations once. - -A Job has all the same fields as a container, with the exception of an optional `schedule` and `events` field. - -## Scheduled jobs - -Jobs that need to be run on a schedule, like a backup job, must also define the schedule field. - -```acorn -jobs: { - "db-backup": { - image: "registry.io/myorg/db-backup" - env: { - "BACKUP_USER": "secret://backup-user-creds/username" - "BACKUP_PASS": "secret://backup-user-creds/password" - } - command: ["/scripts/backup"] - schedule: "@hourly" - } -} -``` - -The `schedule` key makes this a cron based job. The `schedule` field must be a valid crontab format entry. Meaning it can use standard `* * * * *` format or @[interval] crontab shorthand. - -## Events - -Acorn supports four events that can trigger a job to run: `create`, `update`, `stop`, and `delete`. By default jobs will run on create and update. To change this behavior, use the `events` field. - -The `create` event will run the job when the app is created, or when the job is first added to the Acornfile. - -The `update` event will run the job when the app is updated or started from stop. - -The `stop` event will run the job when the app is stopped. - -The `delete` event will run the job when the app is deleted. The job will run, and must complete successfully, before the remaining containers are deleted in that Acorn app. If the job fails, the app will not be deleted. To skip the job, use the [`--ignore-cleanup`](100-reference/01-command-line/acorn_rm.md#options) flag. - -```acorn -jobs: { - "cluster-reconcile": { - image: "registry.io/myorg/cluster-manager" - env: { - "CLUSTER_PASS": "secret://cluster-auth-token/token" - } - events: ["create", "update", "stop", "delete"] - entrypoint: ["/lc.sh"] - files: { - "/lc.sh": """ - #!/bin/sh - if if [ "${ACORN_EVENT}" = "create" ]; then - echo "Create event" - exit 0 - elif [ "${ACORN_EVENT}" = "update" ]; then - echo "Update event" - exit 0 - elif [ "${ACORN_EVENT}" = "stop" ]; then - echo "Stop event" - exit 0 - elif [ "${ACORN_EVENT}" = "delete" ]; then - echo "Delete event" - exit 0 - else - echo "Unknown event" - exit 1 - fi - """ - } - } -} -``` diff --git a/docs/docs/38-authoring/07-args-and-profiles.md b/docs/docs/38-authoring/07-args-and-profiles.md deleted file mode 100644 index 83ac0d0d9..000000000 --- a/docs/docs/38-authoring/07-args-and-profiles.md +++ /dev/null @@ -1,188 +0,0 @@ ---- -title: Args and Profiles ---- - -## Args - -Args are provided to allow users to provide input at different points in the Acorn lifecycle. Args allow Acornfile authors to let the user provide data and values to best suit their needs. Args should be dynamic bits of information. If they are static, use the localData structure to store the variables. - -Args are defined in the top level `args` struct. - -### Defining default values - -Arguments to an Acorn can be standard `strings`, `ints`, `bools`, and other complex types. To define an argument, specify a name and a default value. The type will be inferred from the default value. Here are some examples: - -```acorn -args: { - myIntVar: 1 - myStringVar: "somestring" - myBoolVar: true -} -``` - -Arg names should be in camelCase, and when entered by the user they will be dash separated. - -`thisVariableName` becomes `--this-variable-name` when the user passes it on the command line. - -### Provide the user some guidance - -When defining arguments to the Acorn, it is helpful to the end user to also provide some context. When the user runs `acorn [IMAGE] --help` the output shows all available arguments and if defined provides a short help string. - -When defining args add a `// Comment` above the argument. That will be shown to the user when they do a `--help` - -```acorn -args: { - // Number of instances to run. - replicas: 1 -} -``` - -When the user passes the `--help` arg to Acorn for this image they will see - -```shell -$ acorn MYIMAGE --help -// ... ---replicas Number of instances to run. -// ... -``` - -### Complex data types - -Sometimes more complex data types are needed from the user. If the Acorn provides the minimum production ready configuration for an app, but some users might want to use more advanced features, authors can allow passing in `yaml`objects from files. - -Authors define the variable like: - -```acorn -args: { - // User configuration data for XYZ tool - userConfigData: {} -} -``` - -The user can then create a `config.yaml` file like: - -```yaml -toplevel: - config: - - key1: "value" - - key2: "valueOther" -``` - -The config file can then be passed to the Acorn using -`acorn run [IMAGE] --user-config-data @config.yaml` - -### Built-in - -To prevent the author from having to create a profile, Acorn provides the `args.dev` boolean value. It is set to `true` when running in dev mode (`acorn dev` or `acorn run -i`). Acorn authors can use this boolean with `if` statements to change dev vs. production runtime behaviors. - -```acorn -containers: { - web: { - // ... - if args.dev { - ports: publish: "1313/http" - } - if !args.dev { - ports: publish: "80/http" - } - } -} -``` - -## Profiles - -Profiles specify default arguments for different contexts like dev, test, and prod. This makes it easier for the end user to consume the Acorn application. When developing an application, often there are non-prod ports, different Dockerfile build targets, and replica counts differ from prod. Authors can define a different set of defaults for each environment. - -```acorn -args: { - // Number of instances to run - replicas: 3 -} -profiles: { - dev: { - replicas: 1 - } -} -``` - -:::note -Acorn automatically uses the `dev` profile when when running in dev mode (`acorn dev` or `acorn run -i`). -::: - -In this case when an Acorn consumer deploys the Acorn in production, 3 replicas will be deployed. When the developer working on this app runs it locally with `acorn run --profile dev .` there will only be a single replica deployed by default. - -In either case, consumers of the Acorn can pass `--replicas #` to customize the deployment. - -## Using args in the Acornfile - -### As an environment variable or input to localData - -When the value is assigned to any key in the config file, you can use '.' notation to reference the variable. - -```acorn -args: { - // URL to documentation website - docUrl: "" - - // App Config Value - configValue: "follower" -} -containers: { - web: { - // ... - env: { - "APP_DOC_URL": args.docUrl - } - } -} -localData: { - web: { - config: { - key: args.configValue - } - } -} -``` - -### In a string or template - -When using an arg in a string or template the '.' variable needs to be placed in "\()". - -```acorn -args: { - // A string arg - aStringArg: "default" -} -// ... -secrets: { - type: "template" - data: { - template: """ - a_config_line=\(args.aStringArg) - """ - } -} -``` - -### Complex data input / merging - -When allowing the user to pass complex structures to the Acorn, you can merge that with data predefined in localData. If you would like the user to be able to override the default localData copy of the config, you will need to also define it with ` | *` in the localData section of the Acornfile. - -Merging data is done with the `&` operator. - -Here is an example of allowing the user to override some defaults, but pass in additional configuration. - -```acorn -args: { - userConfig: {} -} -// ... -localData: { - appConfig: args.userConfig & { - userDefinableInt: 3 - staticConfigString: "this is static" - } -} -``` - -In the above if the user passes a config that contains a `userDefinableInt` value the user value will be used. If the user passes `staticConfigString` in their input, Acorn will error out letting the user know that value is already defined. Everything else the user passes will be added to the `appConfig` structure. diff --git a/docs/docs/38-authoring/08-localdata.md b/docs/docs/38-authoring/08-localdata.md deleted file mode 100644 index da30875ec..000000000 --- a/docs/docs/38-authoring/08-localdata.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Local Data ---- - -The `localData` top level key is used by the Acorn author to store default values for the application. The entire object is freeform below the top level and it's up to the author to decide how it needs to be structured. Fields in this block should all be camelCased. - -```acorn -containers:{ - frontend: { - // ... - env: { - "MY_IMPORTANT_SETTING": localData.myApp.frontendConfig.key - } - // ... - } - database: { - // ... - env: { - "MY_DATABASE_NAME": localData.myApp.databaseConfig.name - } - // ... - } -} -localData: { - myApp:{ - frontendConfig: { - key: "value" - } - databaseConfig: { - name: "db-prod" - } - } -} -``` diff --git a/docs/docs/38-authoring/09-permissions.md b/docs/docs/38-authoring/09-permissions.md deleted file mode 100644 index 09f8d463f..000000000 --- a/docs/docs/38-authoring/09-permissions.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -title: Permissions ---- - -When writing applications, you can run into a situation where your application needs to interact with on-cluster resources. In a typical Kubernetes environment you would need to go through a somewhat involved process to accomplish this. Luckily, `permissions` is a straight forward Acornfile definition that allows you to simplify that process. - -Let's take a look at an example. Here we have a `container`, named API, that we want to grant CRUD operations on the `FooResource` in the application's namespace. For all other namespaces, we want the `container` to only be able to retrieve `FooResources`. - -```acorn -containers:{ - api: { - // ... - permissions: { - rules: [{ - verbs: [ - "get", - "list", - "watch", - "create", - "update", - "patch", - "delete" - ] - apiGroups: [ - "api.sample.io" - ] - resources: [ - "fooresource" - ] - }] - clusterRules: [{ - verbs: [ - "get", - "list", - "watch", - ] - apiGroups: [ - "api.sample.io" - ] - resources: [ - "fooresource" - ] - }] - // ... - } -} -``` - -:::info -Standard with every [container](03-containers.md) and [job](06-jobs.md) definition, you get a `ServiceAccount` with the same name as that service. - -If you're curious, creating `permissions` in our Acornfile generates a few on-cluster resources that interact with this `ServiceAccount`, such as a: -- `Role` with the `rules` we specified -- `ClusterRole` with the `clusterRules` we specified -- `RoleBinding` with the `Role` bound to the `ServiceAccount` -- `ClusterRoleBinding` with the `ClusterRole` bound to the `ServiceAccount` -::: - -With this Acornfile, we accomplish our original goal. Breaking down the Acornfile a bit further, we get 5 keywords that are set to define permissions. Let's look at them one at a time. - -## Rules -Physically defining the permissions of your application, `rules` get converted into a `Role` that then gets attached to your application's unique `ServiceAccount`. This is only applicable for your application's unique namespace and, as a result, the permissions will not work in other namespaces. - -## ClusterRules -Similar to `rules`, `clusterRules` define permissions in the application's namespace but with the added benefit of working in other ones as well. Instead of creating a `Role` that gets attached to your application's `ServiceAccount`, you get a `ClusterRole`. If you would like to allow your application to perform the defined rules in any namespace on the cluster then `clusterRules` are the way to go. - -## Verbs -To define what actions your application can perform on a given resource, you define a `verb`. These `verbs` are words that allow you to declaratively define what actions your application can perform on given resources. - -:::info -Wondering what verbs are available? Take a look! -- get -- list -- watch -- create -- update -- patch -- delete -- deletecollection -::: - -## ApiGroups -When interacting with on-cluster resources, related resources are typically grouped by an `apiGroup`. For the context of Acorn, we need to know what `apiGroup` the resource we're granting permissions for is in. In our original example this was `api.sample.io` and others will typically be in this format. - -## Resources -Inside of `apiGroups` you'll find associated `resources`. With this field, you specify which `resources` the `rules` you are creating apply to. In our original example, this was `foo`. \ No newline at end of file diff --git a/docs/docs/38-authoring/20-labels.md b/docs/docs/38-authoring/20-labels.md deleted file mode 100644 index c6a0ca9e5..000000000 --- a/docs/docs/38-authoring/20-labels.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -title: Labels and Annotations ---- - -Labels and annotations are Kubernetes constructs for attaching arbitrary metadata as key-value pairs to resources. Often, they are used by third-party integrations to enhance the functionality of Kubernetes. For example, if you were using [cert-manager](https://cert-manager.io/docs/) to provision SSL certificates, you could add the `cert-manager.io/cluster-issuer` annotation to your ingress resources. - -To allow you to take advantage of such integrations, Acorn supports specifying labels and annotations in your Acornfile. These will be applied to the core Kubernetes resources created by Acorn. - -Labels and annotations can be defined as top-level elements in an Acornfile or on individual members of the following resources: -- containers -- jobs -- volumes -- secrets - -To define labels or annotations that apply to all resources created for your app, add them as top-level elements: -```acorn -labels: { - key: "value" -} -annotations: { - key: "value" -} - -containers: { - // ... -} - -volumes: { - // .. -} -``` - -To define labels or annotations that apply to a specific resource, add them to the desired resource: -```acorn -containers:{ - frontend: { - labels: { - key: "value" - } - annotations: { - key: "value" - } - } - // ... -} -``` -In the above examples, the core Kubernetes resources created for the acorn container called "frontend" will get the labels and annotations. This includes the deployment, pods, ingress, and services. - -You can also specify labels and annotations from the CLI when launching an acorn via the `run` command. See [here](50-running/20-labels.md) for more details. - -:::note - -If the Acorn installation has [disabled user label and annotation propagation](30-installation/02-options.md#ignoring-user-defined-labels-and-annotations), then, except for the metadata scope, labels and annotations will be silently ignored. - -::: - -## Metrics - -To automatically create Prometheus scrape annotations on your Acorn apps, define the metrics port and HTTP path in the Acornfile: -```acorn -containers: "mycontainer": { - ports: ["8080/http", "8081/http"] - metrics: { - port: 8081 - path: "/metrics" - } - // ... -} -``` - -This would create the following annotations on the Kubernetes Pods for the container: -```yaml -prometheus.io/scrape: "true" -prometheus.io/port: "8081" -prometheus.io/path: "/metrics" -``` - -The `path` parameter must begin with `/`, and the `port` parameter must be an integer in between 1 and 65535. diff --git a/docs/docs/38-authoring/21-services.md b/docs/docs/38-authoring/21-services.md deleted file mode 100644 index a467d2dbe..000000000 --- a/docs/docs/38-authoring/21-services.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Services ---- - -## Consuming services - -When you are authoring the Acornfile for your application you can define cloud services that will be provisioned for your application. The services will be deployed alongside your application at deploy/run time. To learn how to create your own service Acorns see [services](/100-reference/10-services.md) in the reference section. - -### Wiring services into your Acorn app - -Service attritibutes are accessed through the `@{}` syntax in the Acornfile. Here is a simple example of accessing the `address` attribute of a service named `db`. For complete service syntax see the [services](/100-reference/03-acornfile.md#services-consuming) section in the Acornfile reference. - -```acorn -// This service exposes an address and a secret -services: db: { - image: "ghcr.io/acorn-io/aws/rds-aurora-cluster:latest" -} - -containers: app: { - image: "my-app:latest" - env: { - MY_SERVICE_ADDRESS: "@{service.db.address}" - MY_SERVICE_PORT: "@{service.db.ports.3306}" - DB_USER: "@{service.db.secrets.admin.username}" - DB_PASS: "@{service.db.secrets.admin.password}" - DB_NAME: "@{service.db.data.dbName}" - } -} -``` - -In the above example the service db parameters are accessed using the `@{service.db}` syntax. Ports are referenced by the expected value, in this case `3306` for MySQL. However, the actual port number may not be `3306` as it can be dynamically assigned during the service creation. diff --git a/docs/docs/38-authoring/30-advanced.md b/docs/docs/38-authoring/30-advanced.md deleted file mode 100644 index db34d69ec..000000000 --- a/docs/docs/38-authoring/30-advanced.md +++ /dev/null @@ -1,167 +0,0 @@ ---- -title: Advanced Topics ---- - -## Scaling Applications - -### Stateless applications - -In the case of scaling stateless applications the `scale` field can be defined on the container to increase the number of containers deployed. This is where consumers of the Acorn won't need persistent data or to know which instance will be deleted on scale down operation. - -```acorn -args: { - // Number of stateless web servers to run - scale: 1 -} - -containers: { - web: { - image: "web" - scale: args.scale - } -} -``` - -### Stateful applications - -Applications that have stateful data or where an operator would care in which order the containers will be removed in a scale down event should not use the `scale` field and should instead create unique instances of the container. - -To accomplish this, users can leverage `for` loops in the Acornfile. Within the `for` loop all items unique to that instance should be defined. In most cases, this will be a container and data volumes. The loop can contain any of the top level objects if needed. - -```acorn -args: { - // Number of instances - replicas: 1 -} - -for i in std.range(0, replicas, 1) { - containers: { - "instance-\(i)": { - // ... - dirs: { - "/data": "volume://instance-data-\(i)" - } - } - } - volumes: { - "instance-data-\(i)": {} - } -} -``` - -The above example makes use of the `std.range` function used in the `for` loop. The loop variable `i` will be an integer and placed into the container and volume names. When the application is scaled up, new containers will be deployed with their own data volumes. When the application is scaled down the highest numbered replicas will be removed first. The `0` replica will always be the first replica deployed and last removed. - -When deploying stateful applications it is a reasonable assumption to bootstrap from the `0` instance and for new replicas to use that as the first point of contact to register. - -### Yaml templates for config files - -If you would like to dump a section of the localData config into YAML format, you can use the YAML encoder package. - -```acorn -args: { - // User provided yaml - userConfig: {} -} - -containers: { - frontend: { - // ... - files: { - "/my/app/config.yaml": "secret://yaml-config/template" - } - // ... - } -} - -secrets: { - "yaml-config": { - type: "template" - data: { - template: std.toYAML(localData.config) - } - } -} - -localData: { - config: std.merge({ - this: { - isGoing: { - to: "be a yaml file" - } - }}, args.userConfig) -} -``` - -In the above example the frontend config file will be rendered from user and Acorn data in YAML format. This example is using the `std.merge()` function which takes two objects and merges them where the second overwrites the first. - -### Generating files from key value pairs - -Another useful built-in for rendering key value pairs with an optional separator is the `std.join` function. - -If you need to create a file with content in this format: - -`key=value` - -```acorn -// ... -containers: { - web: { - // ... - files: { - "/etc/config_file": "secret://config/template" - } - // ... - } -} -secrets: { - "config": { - type: "template" - data: { - template: std.join([for key, value in localData.configData {"\(key)=\(value)"}], "\n") - } - } -} -localData: { - configData: { - key: "value1" - key0: "value2" - } -} -``` - -The above will output into /etc/config_file: - -```ini -key=value1 -key0=value2 -``` - -## Templates - -Templates provide a way to bulk add additional fields to objects. - -To do this, the template is declared for the top level Acorn object, and then a set of `[]` to bind to the nested objects field. - -```acorn -args: dev: false -containers: { - app: {} - db: {} -} - -// ... Other objects ... - -if !args.dev { - containers: [string]: { - probes: [ - // ... probe definitions - ] - } - - containers: [Name= =~ "db"]: { - ports: internal: "\(Name)-metrics-port:5000/http" // Metrics port - } -} -``` - -In the above example when the `args.dev` variable is not set, all containers would have [probes](38-authoring/03-containers.md#probes) assigned. In the case of the `db` container it would have a metrics port defined. The field's name is assigned to the `Name` variable if the regex matches `db`, the `Name` variable can then be referenced in the template. diff --git a/docs/docs/38-authoring/31-nested-acorns.md b/docs/docs/38-authoring/31-nested-acorns.md deleted file mode 100644 index 7b7532260..000000000 --- a/docs/docs/38-authoring/31-nested-acorns.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: Nested Acorns ---- - -Nested acorns allow you to describe a collection of microservices that make up a complete deployment of an Application. This is useful when describing entire deployments along with profiles for their arguments. Combined with the auto-upgrade functionality, it allows you to create a delivery pipeline in a single file that can be checked into VCS. Additionally, Acorns can also be used within an Acorn app to provide functionality to the app. The use of Acorns can be thought of as using a module or library in a programming language. - -## Using nested Acorn - -Acorns are defined under the `acorns` toplevel key in the Acornfile. - -```acorn -//... -acorns: { - "my-acorn": { - image: "ghcr.io/acorn-io/hello-world:latest" - } -} -//... -``` - -## Describe a deployment pipeline with Acorns and services - -To describe an entire deployment with Acorns you declare each Acorn and define a profile for the deployment type. You can also use `services` to provide infrastructure components to the app deployment. - -```acorn -args: { - uri: "" - tag: "" -} - -profiles: { - dev: { - uri: "index.io/my-app/dev/secret-name" - tag: "latest" - } - prod: { - uri: "index.io/my-app/prod/secret-name" - tag: "1.2.#" - } -} - -acorns: { - "my-app": { - image: "example.com/repo/org/hello-world:\(args.tag)" - secrets: ["secrets-getter.this:redis-creds"] - autoUpgrade: true - } - -} - -services: { - // A service that returns a secret from an external source under the name `this` - "secret-getter": { - image: "example.com/repo/org/secret-getter:latest" - serviceArgs: { - secretURI: args.uri - } - } -} -``` - -Now when this Acornfile is initially deployed with the `--profile` flag Acorn will deploy the app with the appropriate default values. In this case `dev` will always update whenever the latest tag moves. Production will always update on new patch releases. diff --git a/docs/docs/38-authoring/_category_.yaml b/docs/docs/38-authoring/_category_.yaml deleted file mode 100644 index fa78ce640..000000000 --- a/docs/docs/38-authoring/_category_.yaml +++ /dev/null @@ -1 +0,0 @@ -label: Authoring Acornfiles diff --git a/docs/docs/39-publishing.md b/docs/docs/39-publishing.md deleted file mode 100644 index 64121503e..000000000 --- a/docs/docs/39-publishing.md +++ /dev/null @@ -1,87 +0,0 @@ ---- -title: Publishing Acorn Images ---- - -Once the application is in a state where it is ready to move to test and production you will need to build an Acorn image and publish it to a registry. Acorn images are only accessible to the Acorn namespace they were built in. In order to use them in other namespaces or on other Kubernetes clusters, the images need to be tagged and published to a registry. - -## Building and tagging an Acorn image - -To publish your image run the familiar build command with a `-t` option to tag the image. A tag will include the FQDN of the registry and the URI path for the image. Commonly, the URI path is a variation of `//:` - -An example would be: - -```shell -acorn build -t ghcr.io/acorn-io/runtime:v1.0 . -``` - -This is very similar to the Docker build workflow: - -```shell -docker build -t index.docker.io//: . -``` - -You can use the tag to reference the built Acorn image to run, push, and update it. - -## Tagging existing Acorn images - -If you want to push a local Acorn image to another registry, or move from a SHA to a friendly name, you can tag the image. The command is: - -```shell -acorn tag -``` - -To tag and prepare to push to Dockerhub `index.docker.io/my-org/image:version` run: - -```shell -acorn tag [MY-IMAGE] /myorg/image:latest -``` - -## Pushing Acorn image to production - -Once the image is tagged, it is ready to be pushed to the remote registry. - -### Logging in - -First you will need to login with credentials that have push access to the remote registry. - -```shell - -# Docker hub -acorn login index.docker.io - -# - or - - -#GitHub container registry -acorn login ghcr.io -``` - -You will be prompted for your username and password to login. If your company has an internal registry you can login substituting `ghcr.io` for your organizations registry domain. - -### Push the image - -Pushing to a registry requires 2 things: - -1. User is logged in and authorized. -1. Image is tagged for the remote registry. - -```shell -acorn push index.docker.io/myorg/image:v1.0 -``` - -## Pulling / Running the Acorn image - -Once the image has been published to a registry, it can be run on other clusters that have access to that registry. You can run the acorn and the Acorn image will automatically be pulled. - -```shell -acorn run index.docker.io/myorg/image:v1.0 -``` - -You can manually pull the Acorn image: - -```shell -acorn pull index.docker.io/myorg/image:v1.0 -``` - -## Additional Information - -* See [Credentials](60-architecture/02-security-considerations.md) docs for details on how registry credentials are scoped and stored. diff --git a/docs/docs/100-reference/02-admin/02-volumeclasses.md b/docs/docs/40-admin/02-volumeclasses.md similarity index 100% rename from docs/docs/100-reference/02-admin/02-volumeclasses.md rename to docs/docs/40-admin/02-volumeclasses.md diff --git a/docs/docs/100-reference/02-admin/03-computeclasses.md b/docs/docs/40-admin/03-computeclasses.md similarity index 100% rename from docs/docs/100-reference/02-admin/03-computeclasses.md rename to docs/docs/40-admin/03-computeclasses.md diff --git a/docs/docs/50-running/80-alpha-image-allow-rules.md b/docs/docs/40-admin/80-alpha-image-allow-rules.md similarity index 100% rename from docs/docs/50-running/80-alpha-image-allow-rules.md rename to docs/docs/40-admin/80-alpha-image-allow-rules.md diff --git a/docs/docs/50-running/01-args-and-secrets.md b/docs/docs/50-running/01-args-and-secrets.md deleted file mode 100644 index 3c6d8db93..000000000 --- a/docs/docs/50-running/01-args-and-secrets.md +++ /dev/null @@ -1,173 +0,0 @@ ---- -title: Args and Secrets ---- - -By design authors will build Acorns Images with defaults for the common use-case, but every deployment has some organization- or environment-specific configurations. Acorn allows consumers to customize behavior at runtime. - -To learn which arguments are available for the Acorn image you can run: - -```shell -acorn run [IMAGE] --help -``` - -### Passing simple arguments - -To pass simple arguments, you pass the value after the argument name. - -```shell -acorn run [IMAGE] --a-string "oneday" --int-arg 4 --bool-defaults-true --negate-a-true-bool=false -``` - -### Passing complex arguments - -To pass complex arguments, create a file in the local directory and pass it to Acorn with the `@` syntax: - -```yaml title="config.yaml" -my: - map: - config: value -``` - -`acorn run registry.example.com/myorg/image --config @config.yaml` - -This is assuming that the Acorn defines a `config` arg where the contents should end up in. - -## Binding secrets - -To securely manage sensitive information while running Acorns the best practice is to use secrets. To accomplish this, the user needs to pre-create secrets before running the app. - -### Discovering which secrets exist in the Acorn image - -To see which secrets will be created when the Acorn is deployed pass the `--help` flag on the Acorn image. - -```shell -acorn run registry.example.com/myorg/image --help -``` - -There will be a `Secrets` line that lists the names of the secrets in the Acorn. - -### Creating a secret - -To create a secret you can use the `acorn secret create` command - -```shell -# Create the secret -> acorn secret create --data username=user0 --data password=supersecret1 my-app-secret-creds -my-app-secret-creds -``` - -In the above example the values from `my-app-secret-creds` will now be available to bind in the secret. - -### Binding a secret at runtime - -When running the Acorn you can bind in a secret with the `-s` option. - -```shell -acorn run -s my-predefined-creds:user-creds registry.example.com/myorg/image -``` - -When this Acorn runs it will use the values in the `my-predefined-creds` secret. - -## Encrypting data - -### Overview - -Encrypted secrets provide a way to pass sensitive information to Acorn apps through public channels. To accomplish this, Acorn uses a [libsodium sealed box](https://libsodium.gitbook.io/doc/public-key_cryptography/sealed_boxes) that is encrypted with the Acorn namespace's public key. This data can only be decrypted by Acorn in the intended namespace. For convenience data can be encrypted with multiple Acorn namespace public keys and put into the same data field. At runtime Acorn will try to decrypt the data with its own key pair. Once decrypted inside the namespace the values are stored in regular Kubernetes secrets for the app to consume. The primary use for encrypted secrets is to provide a mechanism to pass the data through untrusted systems like pipelines and command lines. - -The [encryption reference section](100-reference/07-encryption.md) explains how to use the Acorn public key to encrypt secrets in other languages. - -### Encrypting - -Acorn can encrypt plain text data as long as it is less than 4096 bytes. It is a good idea to keep the plain text value stored in another system like a password manager so that there is a backup of the sensitive data and that it can be re-encrypted if needed in a different Acorn namespace. - -#### Encrypting for a single namespace - -```shell -acorn secret encrypt "my secret data" -# ACORNENC:eyIzclJrRH... -``` - -#### Encrypting for multiple targets - -If you want to use the same sensitive data across multiple clusters or Acorn namespaces you can gather all of the public keys and encrypt all at once with the following command. - -```shell -acorn secret encrypt --public-key [--public-key ...] "my secret data" -# ACORNENC:eyIzclJrRH... -``` - -The cipher text can be decrypted on all of the targets with that output. - -### Using encrypted data - -The encrypted text can be delivered to to the Acorn app by passing as an arg to the Acorn image (if one is predefined), or by placing the text into an existing secret that will be bound into the Acorn app at runtime. - -When placing the data in either a secret or passing on the command line the entire string, including the `ACORNENC:` needs to be passed along. - -If an argument was defined running the app would like: - -```shell -acorn run db --root-password ACORNENC:eyIzclJrRH... -``` - -To create a secret that will be bound to the app at runtime. - -```shell -acorn secret create --data key=ACORNENC:eyIzclJr... my-secret - -acorn run -s my-secret:app-secret-name [IMAGE] -``` - -The secret will be decrypted when it is bound into the running app. - -Alternatively, the Kubernetes secrets could be created using other tools and consumed by the running app by binding the secrets at runtime. - -#### Complete encryption example - -Using the following Acornfile we will pass in an encrypted secret using the methods above. - -```acorn -args: password: "" - -containers: app: { - image: "alpine" - env: { - PASSWORD: "secret://user-password/pass" - } -} - -secrets: "user-password": { - type: "opaque" - data: password: "\(args.password)" -} -``` - -##### To pass in via an arg - -```shell -acorn secret encrypt "secret password" -# ACORNENC:eyIzclJrRHBGRjlGamhUNHdHVGFJdnc4VTVNWDBwODBlb3NrOHl1NjFGT0FZIjoiZkU3RHB6TnF3ZkVacWRtaVBmdktKbGtTcTllSzdCa3VSM3ctT01YTG54a1RkZi1MR0Y5aWk2ZXhUMm9iWE02OC1Hc0RuQkJRWnZfUGNpQ0tzOVplIn0 - -acorn run . --password ACORNENC:eyIzclJrRHBGRjlGamhUNHdHVGFJdnc4VTVNWDBwODBlb3NrOHl1NjFGT0FZIjoiZkU3RHB6TnF3ZkVacWRtaVBmdktKbGtTcTllSzdCa3VSM3ctT01YTG54a1RkZi1MR0Y5aWk2ZXhUMm9iWE02OC1Hc0RuQkJRWnZfUGNpQ0tzOVplIn0 -``` - -The environment variable will be set to "secret password" inside the running container. - -Passing the password via the command line does open up the possibility of someone accidentally passing in plain text, but this is a quick and simple way to do it. - -##### Pass via secret - -WIth the same Acornfile as above, we will encrypt the data, create a secret and then bind in at runtime. - -```shell -acorn secret encrypt "secret password" -# ACORNENC:eyIzclJrRHBGRjlGamhUNHdHVGFJdnc4VTVNWDBwODBlb3NrOHl1NjFGT0FZIjoiZkU3RHB6TnF3ZkVacWRtaVBmdktKbGtTcTllSzdCa3VSM3ctT01YTG54a1RkZi1MR0Y5aWk2ZXhUMm9iWE02OC1Hc0RuQkJRWnZfUGNpQ0tzOVplIn0 - -acorn secret create --data password=ACORNENC:eyIzclJrRHBGRjlGamhUNHdHVGFJdnc4VTVNWDBwODBlb3NrOHl1NjFGT0FZIjoiZkU3RHB6TnF3ZkVacWRtaVBmdktKbGtTcTllSzdCa3VSM3ctT01YTG54a1RkZi1MR0Y5aWk2ZXhUMm9iWE02OC1Hc0RuQkJRWnZfUGNpQ0tzOVplIn0 -# pre-created-secret - -acorn run -s pre-created-secret:user-password . -# wild-horse -``` - -Instead of manually creating the secret via command line in the second step, a separate process could apply the manifests with the encrypted value. diff --git a/docs/docs/50-running/02-networking.md b/docs/docs/50-running/02-networking.md deleted file mode 100644 index 0da845510..000000000 --- a/docs/docs/50-running/02-networking.md +++ /dev/null @@ -1,211 +0,0 @@ ---- -title: Networking ---- - -Applications will need to be reachable by their users. This can be users on the internet, within the organization, and other application teams. When deploying the Acorn app, there is a lot of flexibility. - -## Defaults - -By default Acorn apps run with the Acornfile author's default configurations. - -```shell -acorn run registry.example.com/myorg/image -``` - -### Publish all ports - -To publish all ports you can run with `-P` or the long form `--publish-all`. - -### Publish no ports - -To launch the Acorn app with all ports internal, you can launch with the `-P=false` or `--publish-all=false`. - -## Publish individual ports - -Publishing ports makes the services available outside of the cluster. HTTP ports will be exposed via the layer 7 ingress and TCP/UDP ports will be exposed via service load balancers. When specifying a port to publish without its protocol, the protocol defined for it in the Acornfile will be used. If no protocol is defined in the Acornfile, the default will be tcp. - -| Flag value | Description | -| --------------------------- | ---------------------------------------------------------------------------------------- | -| `-p 80` | Publish port 80 in the Acorn to port 80 with its protocol. | -| `-p 80/http` | Publish port 80/http in the Acorn to a random hostname. | -| `-p 81:80` | Publish port 80 in the Acorn to 81 on cluster with the port's protocol. | -| `-p 81:80/tcp` | Publish 80/tcp in the Acorn to 81 as a cluster service. | -| `-p 81:80/http` | Publish 80/http in the Acorn to 81 with a random hostname. | -| `-p app:80` | Publish container `app` port 80 in the Acorn to 80 on cluster with its protocol. | -| `-p app:80/tcp` | Publish container `app` port 80/tcp in the Acorn to 80 as a cluster service. | -| `-p app:80/http` | Publish container `app` port 80/http in the Acorn to 80 with a random hostname. | -| `-p app.example.com:app` | Publish container `app` protocol HTTP from the Acorn to external name `app.example.com`. | -| `-p app.example.com:app:80` | Publish container `app` port 80 from the Acorn to external name `app.example.com`. | - -## Expose individual ports - -Exposing ports makes the services available to applications and other Acorns running on the cluster. When specifying a port to expose without its protocol the protocol defined for it in the Acornfile will be used. If no protocol is defined in the Acornfile, the default will be tcp. - -| Flag value | Description | -| ------------------------ | ----------------------------------------------------------------------------------------- | -| `--expose 80` | Expose port 80 in the Acorn to port 80 with its protocol. | -| `--expose 81:80` | Expose 80 in the Acorn to 81 on cluster with its protocol. | -| `--expose 81:80/tcp` | Expose 80/tcp in the Acorn to 81 as a cluster service. | -| `--expose 81:80/http` | Expose 80/http in the Acorn to 81 as a cluster service. | -| `--expose app:80` | Expose container `app` port 80 with its protocol in the Acorn to 80 as a cluster service. | -| `--expose app:80/tcp` | Expose container `app` port 80/tcp in the Acorn to 80 as a cluster service. | -| `--expose app:80/http` | Expose container `app` port 80/http in the Acorn to 80 as a cluster service. | -| `--expose web:80:app:80` | Expose container `app` port 80/tcp as cluster service called `web` on port 80/tcp. | - -## DNS - -When an Acorn app has published a port, it will be accessible on a unique endpoint. This endpoint can be seen in the output of `acorn app`: - -```shell -NAME IMAGE HEALTHY UP-TO-DATE CREATED ENDPOINTS MESSAGE -purple-water my-org/my-acorn:v1 1 1 50s ago http://app-purple-water-caa5ade4.local.oss-acorn.io => default:8080 OK -``` - -You have significant control over the domain name and format of your endpoints, as described below. - -### Cluster Domain - -Your cluster domain is the domain used as the suffix for all your Acorn apps' endpoints. - -If you're running a local cluster, such as Docker Desktop, Rancher Desktop, or Minikube, the cluster domain will be `local.oss-acorn.io` and will always resolve to `localhost`. - -If you are running any other type of cluster, Acorn provides a DNS service that will reserve a unique cluster domain and create publicly accessible DNS entries for you. The domain will look like `.oss-acorn.io` and will resolve to the hostnames or IP addresses supplied by your ingress controller. This domain is unique to your cluster and will be used for all Acorn apps. - -:::caution - -The oss-acorn.io DNS service is a public service ran on the Internet. Your Acorn installation must have outbound access to to access it. - -To create and maintain public DNS entries, the DNS service expects your Acorn installation to make on-demand and periodic renewal requests to it. - -If your Acorn installation ceases to make requests to the DNS service, your DNS entries and reserved domain will eventually expire and be deleted. -::: - -You can choose to use your own cluster domain instead of the generated domain like so: - -```shell -acorn install --cluster-domain my-company.com -``` - -If you do so, you must manage your own DNS entries. - -You can turn off the Acorn DNS feature as part of installation (or after by rerunning the command): - -```shell -acorn install --acorn-dns disabled -``` - -This will prevent Acorn from reserving a domain for your cluster. If you disable the DNS service and haven't defined a custom cluster domain, the `local.oss-acorn.io` domain will be used as a fallback. - -### Naming Conventions - -The endpoints generated for your Acorn apps follow this convention by default: - -``` ---. -``` - -Here's an example: - -``` -web-purple-water-7961a9e1.73fh5y.oss-acorn.io -``` - -Let's break that FQDN down: - -- **web** is the name of the container from your Acorn app. If the container name is "*default*", it will be omitted from the FQDN. -- **purple-water** is the generated name of your Acorn app. You can control this by supplying a name through the `--name` flag. -- **7961a9e1** is a hash created from the container name and app name together. This ensures that the url is unique and will be persistent across runs. -- **73fh5y.oss-acorn.io** is the cluster domain generated for your cluster. You can control this as described in the previous section. - -To highlight the level of control this gives you, consider the following: - -In addition to this method of controlling your endpoint, you can publish to an explicit external name using the `--publish` flag. See the [publishing ports](#publish-individual-ports) section for more details. - -### Endpoint Patterns - -Endpoints generated by Acorn are built using a Go Template. By default, endpoints are built using the `{{.Container}}-{{.App}}-{{.Hash}}.{{.ClusterDomain}}` pattern to allow integration with [Let's Encrypt](30-installation/02-options.md#tls-via-lets-encrypt). - -However, should you want your application endpoints to be something completely different, you can pass a Go Template to the `--http-endpoint-pattern` flag. For example, say that we want our `blog` container to be reachable at `blog.local.oss-acorn.io` instead of the the standard Let's Encrypt variant. To accomplish this, we just need to install Acorn with a pattern for it set. - -```shell -acorn install --http-endpoint-pattern "{{.Container}}.{{.ClusterDomain}}" -``` - -This will work for existing installations of Acorn by overwriting the current pattern. To go to the original default, simply reinstall with the flag set to `""` like so. - -```shell -acorn install --http-endpoint-pattern "" -``` - -When building the template, there are a few variables that can be referenced in any order. - -| Variable | Description | -| ------------------ | ------------------------------------------------------- | -| {{.Container}} | Name of the container being hit with the endpoint. | -| {{.App}} | Name of the application. | -| {{.Hash}} | A hash generated from the Container and App together. | -| {{.Namespace}} | Namespace that the application is deployed in. | -| {{.ClusterDomain}} | Domain set during installation with `--cluster-domain`. | - -You can arrange these variables in any order as long as they do not break DNS and Kubernetes conventions. Using this you have very close to full control over the endpoint for your http application. - -:::caution -There are a few restrictions that will fail validation - -1. If any segment (individual string segmented by a `.`) has more than 63 characters, it will not pass validation. -2. You cannot use the root cluster domain as the endpoint pattern alone. (i.e. `{{.ClusterDomain}}`) -::: - -## Routers -If you have multiple containers normally they would be exposed as multiple different HTTP services. The router feature allows you to expose those containers as a single HTTP service with separate routes. Let's take a look at how we can achieve this with two containers below. - -Starting with a sample Acornfile that exposes two services - -```acorn -containers: { - api: { - image: "nginx" - ports: publish: "80/http" - } - auth: { - image: "nginx" - ports: publish: "80/http" - } -} -``` - -If you start this Acornfile with `acorn run` the generated output should look like - -```shell - STATUS: ENDPOINTS[http://api-wild-cloud-a6e8ab1c.local.oss-acorn.io => api:80, http://auth-wild-cloud-aa56b1c9.local.oss-acorn.io => auth:80] HEALTHY[2] UPTODATE[2] OK -``` - -Adding in the router to the Acornfile - -```acorn -routers: myroute: { - routes: { - "/auth": "auth:80" - "/api": { - pathType: "exact" - targetServiceName: "api" - targetPort: 80 - } - } -} - -containers: auth: { - image: "nginx" - ports: "80/http" -} - -containers: api: { - image: "nginx" - ports: "80/http" -} -``` - -Results in an endpoint that now routes to both services through `/api` and `/auth` - -```shell -| STATUS: ENDPOINTS[http://api-delicate-leaf-4ceee54b.local.oss-acorn.io => api:80, http://auth-delicate-leaf-a6e05d96.local.oss-acorn.io => auth:80, http://myroute-delicate-leaf-6633a4ae.local.oss-acorn.io => myroute:8080] HEALTHY[2] UPTODATE[2] OK | diff --git a/docs/docs/50-running/03-certificates.md b/docs/docs/50-running/03-certificates.md deleted file mode 100644 index b4b4aaae9..000000000 --- a/docs/docs/50-running/03-certificates.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: TLS Certificates ---- - -Applications that publish HTTP endpoints can be protected by TLS certificates. If you've enabled Acorn's [Let's Encrypt integration](30-installation/02-options.md#tls-via-lets-encrypt), a valid certificate will be provisioned for your app's endpoints. This only applies to oss-acorn.io generated endpoints. For custom endpoints configured using the [publish flag](50-running/02-networking.md#publish-individual-ports), Acorn relies on external cert-manager to issue certificates. For more information on how to configure cert-manager, see [Issuing custom domain certs](#issuing-custom-domain-certs). - -## Manually adding certificates -If you don't wish to use Acorn's Let's Encrypt integration, you can configure certificates manually or by integrating with cert-manager. Acorn will automatically look for SANs in secrets of type `kubernetes.io/tls` for the exposed FQDN of the application in the Acorn namespace. - -The following examples assume you are deploying an app and plan to host on `my-app.example.com` - -### Add existing certificates using kubectl - -Before launching the application pre-create a secret in the `acorn` namespace containing the -certificate like so: - -`kubectl create secret tls my-app-tls-secret --cert=path/to/my-app-tls.cert --key=path/to/my-app-tls.key` - -### Add with Cert-Manager - -If you are already using Cert-Manager today, you can leverage it with Acorn right away. First you must -create a certificate resource in the Acorn namespace: - -`kubectl apply -n acorn -f ./my-cert.yaml` - -```yaml -# my-cert.yaml -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: registry-studio-cert -spec: - dnsNames: - - my-app.example.com - issuerRef: - group: cert-manager.io - kind: ClusterIssuer - name: prod-issuer - secretName: my-app-tls-secret -``` - -Cert-Manager will create a certificate for `my-app.example.com` and store it in a secret `my-app-tls-secret`. - -### Consume the secret - -Once you have manually created the TLS secret using one of the methods above you can consume it in your application. - -When you deploy the application Acorn, you can launch with the FQDN of your app. - -```shell -acorn run -p my-app.example.com:web [MY_APP_IMAGE] -``` - -Acorn will automatically inspect each certificate in the Acorn namespace for one that can be used with `my-app.example.com`. -If no TLS secret is found with that FQDN, it will be exposed on HTTP only. - -### Issuing custom domain certs - -Acorn's Let's Encrypt integration does not issue certificates for custom domains. Instead, you will rely on external cert-manager to issue certificates. To do so, you will need to create a cluster-issuer first. For more information on how to install and configure cert-manager, see [cert-manager docs](https://cert-manager.io/docs/). - -```yaml -apiVersion: cert-manager.io/v1 -kind: ClusterIssuer -metadata: - name: letsencrypt-prod -spec: - acme: - server: https://acme-v02.api.letsencrypt.org/directory - email: users@exmaple.io - privateKeySecretRef: - name: letsencrypt-prod - solvers: - - http01: - ingress: - ingressClassName: traefik -``` - -Modify the `ingressClassName` to match the ingress controller you are using. For example, if you are using the NGINX ingress controller, you will need to change it to `nginx`. -Once you have created the cluster-issuer, pass the cluster-issuer's name to `acorn install` so that Acorn knows which cluster-issuer to apply to the ingress resource. - -Once you have created the cluster issuer, pass the cluster issuer's name to acorn install so that acorn knows where to apply the cluster issuer to the ingress resource. - -```shell -acorn install --cert-manager-issuer=letsencrypt-prod -``` \ No newline at end of file diff --git a/docs/docs/50-running/04-volumes.md b/docs/docs/50-running/04-volumes.md deleted file mode 100644 index c241a3873..000000000 --- a/docs/docs/50-running/04-volumes.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: Volumes ---- - -## Configuring volumes at runtime - -Acorn images can define volumes. To see which volumes are available for an Acorn image you can run `--help` on the image. - -```shell -acorn run [IMAGE] --help -# ... -Volumes: my-data -``` - -The `Volumes` line shows the volumes that will be created as part of the Acorn app deployment. Unless otherwise [specified in the Acorn image](38-authoring/04-volumes.md) and if no default volume class is specified, each volume will be created using the following default values: - -|Field |Default Value| -|----------- | -----| -| size | 10G | -| class | default | -| accessMode | readWriteOnce | - -These values can be customized at runtime by passing `-v` arguments. For example, the following command will cause the "my-data" volume to be created with `5G` of storage and using the `fast` volume class: - -```shell -acorn run -v my-data,size=5G,class=fast [IMAGE] -``` - -The volume class used, including the default, may have restrictions on the size of volumes created or the access modes available. If your volume uses a class that is not available or uses class settings that violate its rules, then will not run. A descriptive error will be produced to explain any failures. - -You can see a list of available volume classes and their restrictions, if any, with the [`acorn offerings volumeclasses`](100-reference/01-command-line/acorn_offerings_volumeclasses.md) command. - -## Using pre-existing volumes - -You can use a pre-existing volume by binding the volume at runtime. -The volume can be referenced either by its PersistentVolume name in Kubernetes, or by its name in Acorn (displayed in the output of `acorn volume`). -In this example, the new Acorn app uses an old volume called `data` that an app called `db` used. It uses it as its `my-data` volume. - -``` -$ acorn volume -NAME APP-NAME BOUND-VOLUME CAPACITY VOLUME-CLASS STATUS ACCESS-MODES CREATED -db.data db.data data 1G local-path bound RWO 23s ago - -$ acorn run -v "db.data:my-data" -n my-new-app [IMAGE] -``` - -The volume will match the size and class of the pre-existing volume `db.data`. -Once the old volume is consumed by the new app, it will be renamed. - -``` -$ acorn volume -NAME APP-NAME BOUND-VOLUME CAPACITY VOLUME-CLASS STATUS ACCESS-MODES CREATED -my-new-app.my-data my-new-app.my-data my-data-bind 1G local-path bound RWO 2m16s ago -``` - -A pre-existing volume can only be bound to a new app if the new app is created in the same Acorn project as the old app that previously used the volume. - -At this time, volumes created outside of Acorn cannot be bound to an Acorn app. diff --git a/docs/docs/50-running/06-linking-acorns.md b/docs/docs/50-running/06-linking-acorns.md deleted file mode 100644 index 2b0525068..000000000 --- a/docs/docs/50-running/06-linking-acorns.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: Linking Acorn Apps ---- - -Acorn apps can link to containers from other Acorn apps at runtime to provide supporting services. For instance, if you have an Acorn running PostgreSQL, it can be used to provide the `db` service to another app. - -If you have an Acorn that defines a `web` container and a `redis` container, you can consume a separate Acorn to provide the redis service from an already running Acorn. - -```shell -acorn run --link my-other-redis-acorn:redis [IMAGE] -``` - -In the above example, the container service from the running Acorn will be available within the new Acorn as `redis`. Your new instance will be able to resolve the `redis` name and it will connect to the remote service defined by the link. - -:::note -The port from the container being linked to must be explicitly exposed in the `Acornfile` i.e. `ports: expose: "5432/tcp"`. -::: - -The more general linking syntax is as follows: - -```shell -acorn run --link : [IMAGE] -``` - -`` is the name that the new Acorn app can use to resolve the linked service. - -`` is one of the following: - -- The name of another Acorn in the same project, if that Acorn only has one container -- A reference to a particular container in a different Acorn in the same project, in the format `.` - -For example, if I have an Acorn called `my-app` with two containers `nginx` and `db`, I can link the `db` container to another Acorn in the same project: - -```shell -acorn run --link my-app.db:db [IMAGE] -``` - -:::note -If you set the `` to a name identical to the name of one of the containers in the new app, then that container in the new app will not be created, since the linked container takes its place. -::: diff --git a/docs/docs/50-running/20-labels.md b/docs/docs/50-running/20-labels.md deleted file mode 100644 index a2e1bb857..000000000 --- a/docs/docs/50-running/20-labels.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: Labels and Annotations ---- - -As mentioned in the [authoring section](38-authoring/20-labels.md), you can add labels and annotations to your Acorns that will then be propagated down to the core Kubernetes resources created by Acorn. Authors of Acorn images can add these directly to the Acornfile, but users can also add them at runtime. - -The flags for adding labels and annotations allow you to specify the resource type and name you are targeting. This is best explained through examples: - -```shell - -# Add a label to all resources created by the app -acorn run --label key=value - -# Add an annotation to just the top-level acorn app's metadata. No child resources will inherit -acorn run --annotation metadata:key=value - -# Add a label to all resources created as part of any containers in the acorn -acorn run --label containers:key=value - -# Add an annotation to the resources created as part of a specific container named 'mycontainer' in the acorn -acorn run --annotation containers:mycontainer:key=value -``` - -Valid resource types are: -- global _(achieved by omitting resource type completely)_ -- metadata -- containers -- jobs -- volumes -- secrets - -For all resource types except metadata, you can add a name to only apply the label/annotation to the resource matching that name and scope. - -:::note - -If the Acorn installation has [disabled user label and annotation propagation](30-installation/02-options.md#ignoring-user-defined-labels-and-annotations), then, except for the metadata scope, labels and annotations will be silently ignored. - -::: diff --git a/docs/docs/50-running/30-troubleshooting.md b/docs/docs/50-running/30-troubleshooting.md deleted file mode 100644 index 73fba28f7..000000000 --- a/docs/docs/50-running/30-troubleshooting.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Troubleshooting ---- - -## Viewing logs - -To view the logs of your running application you can run: - -```shell -acorn logs [APP-NAME] -``` - -If you would like the logs to continue streaming, you can add `-f` to follow the logs. - -## Executing commands inside a container - -To execute commands in a running Acorn container, you can do: - -```shell -acorn exec [APP-NAME] -``` - -You will be prompted for which container if there is more than one running. - -If you know the container name you can specify it with the `-c` option. - -```shell -acorn exec -c web-01 [APP-NAME] -``` diff --git a/docs/docs/50-running/40-upgrades.md b/docs/docs/50-running/40-upgrades.md deleted file mode 100644 index 0c035330d..000000000 --- a/docs/docs/50-running/40-upgrades.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Manual Upgrades ---- - -When upgrading an Acorn app, you do not need to pass in all arguments on every update. The args are persisted between runs and only the passed in updates are changed. - -## What happens during an upgrade - -During an upgrade: - -1. Container images are updated. -1. Secrets are deployed. -1. Jobs are run. - -## Updating a running image - -To upgrade the image in production - -```shell -acorn update --image [NEW-IMAGE] [APP-NAME] -``` - -This will replace the Acorn, and if new container images or configurations are provided, the application containers will be restarted. - -## Updating parameters - -Deployed Acorns can have their parameters changed through the update command. Depending on the parameters being updated it is possible that network connectivity may be lost or containers restarted. - -When updating args for the Acorn app, the behavior will be dependent on how the Acorn app was designed/written. Look for documentation from the Acorn app author to understand what is possible and how to operate the Acorn app. - -## Updating published DNS names - -If an Acorn was deployed like: - -```shell -$ acorn run -p my-app.test.example.com:web [IMAGE] --replicas 3 --cluster-mode active-active -purple-field -``` - -The app DNS can be updated by running: - -```shell -acorn update -p my-app.example.com:web purple-field -``` - -Only the argument being changed needs to be passed in. diff --git a/docs/docs/50-running/45-auto-upgrades.md b/docs/docs/50-running/45-auto-upgrades.md deleted file mode 100644 index 03a289dbc..000000000 --- a/docs/docs/50-running/45-auto-upgrades.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: Automatic Upgrades ---- -You can configure Acorn apps to automatically upgrade when a new version of the Acorn image they are using is available. - -Automatic upgrade for an app will be enabled if `#`, `*`, or `**` appears in the image's tag as part of the run command. Tags will sorted according to the rules for these special characters described below. The newest tag will be selected for upgrade. - -`#` denotes a segment of the image tag that should be sorted numerically when finding the newest tag. - -This example deploys the hello-world app with auto-upgrade enabled and matching all major, minor, and patch versions: -```shell -acorn run myorg/hello-world:v#.#.# -``` - -`*` denotes a segment of the image tag that should be sorted alphabetically when finding the latest tag. - -In this example, if you had a tag named alpha and a tag named zeta, zeta would be recognized as the newest: -```shell -acorn run myorg/hello-world:* -``` - - -`**` denotes a wildcard. This segment of the image tag won't be considered when sorting. This is useful if your tags have a segment that is unpredictable. - -This example would sort numerically according to major and minor version (ie v1.2) and ignore anything following the "-": - -```shell -acorn run myorg/hello-world:v#.#-** -``` - -NOTE: Depending on your shell, you may see errors when using `*` and `**`. Using quotes will tell the shell to ignore them so Acorn can parse them: -```shell -acorn run "myorg/hello-world:v#.#-**" -``` - -Automatic upgrades can be configured explicitly via a flag. - -In this example, the tag will always be "latest", but acorn will periodically check to see if new content has been pushed to that tag: -```shell -acorn run --auto-upgrade myorg/hello-world:latest -``` - -To have acorn notify you that an app has an upgrade available and require confirmation before proceeding, set the notify-upgrade flag: -```shell -acorn run --notify-upgrade myorg/hello-world:v#.#.# myapp - -``` -To proceed with an upgrade you've been notified of: -```shell -acorn update --confirm-upgrade myapp -``` - -New image versions are checked for on an interval. You can control the default interval via the install command and the the `--auto-upgrade-interval` flag. You can control the interal on a per app basis as part of the run command by specifying the `--interval` flag. diff --git a/docs/docs/50-running/50-namespaces-and-service-accounts.md b/docs/docs/50-running/50-namespaces-and-service-accounts.md deleted file mode 100644 index 9f25101fd..000000000 --- a/docs/docs/50-running/50-namespaces-and-service-accounts.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: Namespaces and Service Accounts ---- -## Namespaces - -By design Acorn will run apps under the `acorn` namespace. If you are planning to deploy an app to a pre-created namespace you will need to label it explicitly. - -#### To label : - -```shell -kubectl label namespaces acorn.io/app-name= -kubectl label namespaces acorn.io/app-namespace=acorn -``` -#### To verify : -```shell -acorn run --target-namespace -n -P ghcr.io/acorn-io/hello-world -acorn % kubectl get pods -n ns-test-app -NAME READY STATUS RESTARTS AGE -webapp-556947c87d-gt97r 1/1 Running 0 3m54s - -``` -:::caution -When the app is removed the namespace will also be deleted. -::: - -## Service Accounts - -All Kubernetes deployments or jobs launched by Acorn will have a service account attached based on their definition in the Acornfile. - -For example: - -```acorn -containers: { - "my-app-container": { - // ... - } -} -jobs: { - "my-app-job": { - // ... - } -} -routers: { - "my-app-router": { - // ... - } -} -``` - -Running the above Acornfile will result in three service accounts named `my-app-container`, `my-app-job`, and `my-app-router` being created. diff --git a/docs/docs/50-running/55-compute-resources.md b/docs/docs/50-running/55-compute-resources.md deleted file mode 100644 index 5467f89e1..000000000 --- a/docs/docs/50-running/55-compute-resources.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: Compute resources ---- - -## Memory -Setting `memory` via `acorn run` has the highest order of precedence. When setting this, you operate under the `--memory` flag (`-m` for short). - -:::note -Check out the [memory reference documentation](100-reference/06-compute-resources.md#memory) for more information. -::: - -### --memory -When setting this value, you have two options - globally or per workload and you can do a combination of both. When setting the memory globally for the Acorn, you provide the memory you would like to set. - -```console -acorn run -m 512Mi foo -``` - -This will set all workloads in the `foo` acorn to have `512Mi` of memory. Adjacently, you can set the memory of each individual workload in the Acorn using a `workload=memory` pattern. - -```console -acorn run -m nginx=512Mi foo -``` - -This will only update Acorn's `nginx` workload to have `512Mi` of memory. - -Finally, you can do a combination of both. - -```console -acorn run -m 256Mi,nginx=512Mi foo -``` - -This sets all workloads in the `foo` acorn to have `256Mi` of memory except for the `nginx` workload which will have `512Mi` of memory. - -## Compute Classes -To set a compute class at run time, you can utilize the `--compute-class` flag. - -:::note -Check out the [compute class reference documentation](100-reference/06-compute-resources.md#compute-classes) for more information about how compute classes work. -::: - -### --compute-class - -When setting compute classes, you have two options - globally or per workload, and you can do a combination of both. When setting the compute class globally for the Acorn, you provide the compute class you would like to set. Any classes defined for a specific container or job will overwrite the global value. - -```console -acorn run --compute-class sample foo -``` - -This will set all workloads in the `foo` acorn to use the `sample` compute class. Adjacently, you can set the memory of each individual workload in the Acorn using a `workload=class` pattern. - -```console -acorn run --compute-class nginx=sample foo -``` - -:::tip -This flag comes with auto completions! Hit tab to see compute classes that can be used. -::: - -This will only update Acorn's `nginx` workload to use the `sample` compute class. - -Finally, you can do a combination of both. - -```console -acorn run --compute-class sample,nginx=different foo -``` - -This sets all workloads in the `foo` acorn to use the `sample` compute class except for the `nginx` workload which will have the `different` compute class. diff --git a/docs/docs/50-running/60-projects.md b/docs/docs/50-running/60-projects.md deleted file mode 100644 index 215813536..000000000 --- a/docs/docs/50-running/60-projects.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Projects ---- - -Acorn applications and other resources can be grouped into projects. Eventually, projects will serve as the unit at which Acorn manages functionality like: - -- membership and RBAC -- network isolation -- resource quotas - -For now, their primary purpose is to group resources like applications, images, volumes, and secrets together. - -Projects can be created, listed, removed, and "used". When you "use" a project, it becomes the context under which you are interacting with Acorn applications and related resources. - -### List Projects -When you install acorn, you'll automatically have one project called `acorn`. It can be seen in the project list. If you do nothing else, this is the project you'll use by default. -```bash -$ acorn projects - -NAME DEFAULT DESCRIPTION -acorn * -``` - -### Create Project -The following command creates a new project. -```bash -$ acorn project create my-new-project -``` - -### Use Project -To begin using a project, you must specify it using the `use` sub-command. -```bash -$ acorn project use my-new-project -``` -Once you start using a project, all other acorn commands, such as `acorn ps` or `acorn run` will be executed within that project. So, for example, if you switch to project `my-new-project` and then run `acorn ps`, you won't see any applications that were launched in the default `acorn` project. - -### Remove project -To remove or delete a project, simply run the `rm` command: -```bash -acorn project rm my-new-project -``` -This will cause the project and all related resources to be deleted. - -### Temporarily specifying a different project -All acorn commands now support the `--project` (or `-j`) flag for specifying the project just for that command. So, for example, the following command would create an application in the `development` project, regardless of which project you were currently using: -```bash -acorn -j development run ghcr.io/acorn-io/hello-world -``` diff --git a/docs/docs/50-running/65-update-acorns.md b/docs/docs/50-running/65-update-acorns.md deleted file mode 100644 index 82f947150..000000000 --- a/docs/docs/50-running/65-update-acorns.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: Update Acorns ---- - -There are multiple ways to update an Acorn, including using the following methods: - -- `acorn run --update` -- `acorn run --replace` -- `acorn update` - -### run --update -By running `acorn run --update`, you can create a new Acorn or update an existing one with the specified flags and/or arguments. - -Take this Acornfile -```Acornfile -containers: { - nginx: { - image: "nginx" - ports: publish: "80/http" - files: { - "/usr/share/nginx/html/index.html": "

My " + args.msg + " Acornfile

" - } - mem: 128Mi - labels: { - key: "test-label" - } - } -} -args: { - // new arg - msg: "1" -} -``` - -```bash -#start an acorn from a directory -$ acorn run -n awesome-acorn . -awesome-acorn - -$ acorn app -NAME IMAGE HEALTHY UP-TO-DATE CREATED ENDPOINTS MESSAGE -awesome-acorn 3e23d225e777 1 1 10s ago http://nginx-awesome-acorn-9ca4278a.local.oss-acorn.io => nginx:80 OK - -#update the msg arg and add a label -acorn run --update --label label=new -n awesome-acorn -- --msg 2 - -#navigate to the endpoint to see the updated message -``` - -:::note -The purpose of using -- is to distinguish between command-line options (flags) and arguments for the Acorn. -::: - - -### run --replace -Similarly to `acorn run --update`, `acorn run --replace` will create or update an existing acorn with ONLY the provided flags and args. Any previous modifications will be replaced. - -If we attempt a replace on the previous acorn, we should see the label be dropped -```bash -$ acorn run --replace -n awesome-acorn -- --msg 3 - -$ acorn app awesome-acorn -o yaml ---- -metadata: - creationTimestamp: "2023-03-23T20:11:11Z" - generation: 3 - name: awesome-acorn - namespace: acorn - ... -status: - appImage: - acornfile: | - containers: { - nginx: { - image: "nginx" - ports: publish: "80/http" - files: { - "/usr/share/nginx/html/index.html": "

My " + args.msg + " Acornfile

" - } - - mem: 128Mi - labels: { - key: "test-value" - } - } - } - ... -``` - -### acorn update -Both `acorn update` and `acorn run --update` have identical functionality, with the former being an alias for the latter. - - -### More Examples - -```shell -# update a currently running acorn's image and modify its' acorn args -acorn run --update -n my-acorn --image my-new-image -- --acorn-arg newArg - -#update a currently running acorn from the current dir -acorn update -n my-acorn . -``` diff --git a/docs/docs/50-running/66-remove-acorns.md b/docs/docs/50-running/66-remove-acorns.md deleted file mode 100644 index 635f61820..000000000 --- a/docs/docs/50-running/66-remove-acorns.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -title: Removing Acorns ---- - -When you want to remove an Acorn and its components, you can use the `acorn rm` command. - -## Default behavior - -To remove an Acorn app run `acorn rm [APP]`. This will remove the app and all of the containers associated with it. If the app has any services, secrets, or volumes they will remain until they are removed manually. This behavior is to protect against accidental deletion of data. - -## Removing services and nested Acorns - -To remove services and nested Acorns when removing the Acorn app use the `--all` and optionally `--force` flags. The `--all` flag will remove all services and nested Acorns. The `--force` flag will remove the services and nested Acorns without prompting for confirmation. This will also remove all of the secrets and volumes for the app and the child services and nested Acorns. - -Otherwise, you can remove the services and nested Acorns manually with the `acorn rm` command after the app has been removed. - -```bash -acorn rm [APP].[SERVICE] -``` diff --git a/docs/docs/50-running/70-dev.md b/docs/docs/50-running/70-dev.md deleted file mode 100644 index a25de9fc3..000000000 --- a/docs/docs/50-running/70-dev.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: Dev Mode ---- -To facilitate interactive development, Acorn provides a `dev` command that enables you to run your project in a live-reload mode, which automatically reloads your application whenever you make changes to your code. To start the interactive mode, you can use the `acorn dev` command. -The interactive dev mode offers a convenient way to test and debug your project as you develop it, as you can quickly see the effects of any changes you make. This mode can also help you to identify and fix errors more efficiently by providing real-time feedback on your code. - -- Start a dev session from the current working directory - - ```bash - acorn dev - ``` -- Start a dev session from a pre-built image in the current working directory - - ```bash - acorn dev [IMAGE] - ``` -- Attach a dev session to a pre-existing acorn in the current working directory - - ```bash - acorn dev -n [APP_NAME] - ``` - -:::note -When using `acorn dev`, the `dev` profile will be automatically used. This behavior is the same when using `acorn run -i`. -::: \ No newline at end of file diff --git a/docs/docs/50-running/90-events.md b/docs/docs/50-running/90-events.md deleted file mode 100644 index 94dc9f370..000000000 --- a/docs/docs/50-running/90-events.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: Events ---- - -Acorn installations maintain a curated event log of the operational details associated with managing acorns. - -To access this log, use the [`acorn events`](../100-reference/01-command-line/acorn_events.md) command: - -```shell -# List all events in the current project -acorn events - -# List events across all projects -acorn -A events - -# List the last 10 events -acorn events --tail 10 - -# List the last 5 events and follow the event log -acorn events --tail 5 -f - -# List events related to the 'hello' app in the current project -acorn events app/hello - -# List events related to any app in the current project -acorn events app - -# List events with names that begin with '4b2b' -acorn events 4b2b - -# Get a single event by name -acorn events 4b2ba097badf2031c4718609b9179fb5 -``` -:::note - -Events are printed in chronological order, from oldest to newest, based on the time they were observed. - -::: - diff --git a/docs/docs/50-running/_category_.yaml b/docs/docs/50-running/_category_.yaml deleted file mode 100644 index d7bab7760..000000000 --- a/docs/docs/50-running/_category_.yaml +++ /dev/null @@ -1 +0,0 @@ -label: Running Acorn Apps diff --git a/docs/docs/55-integrations/01-github-actions.md b/docs/docs/55-integrations/01-github-actions.md deleted file mode 100644 index e4d0ca71c..000000000 --- a/docs/docs/55-integrations/01-github-actions.md +++ /dev/null @@ -1,97 +0,0 @@ -# GitHub Actions - -## Quick Start - -Use a GitHub [Action](https://github.com/features/actions) to build and push a new Acorn into a [Packages](https://ghcr.io/) repository each time a new version is tagged: - -```yaml -# Save into your repo as .github/workflows/on-tag.yaml -name: On Tag -on: - push: - tags: - - "v*" -jobs: - publish: - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v3 - - uses: acorn-io/actions-setup@v1 - - uses: acorn-io/actions-login@v1 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Set Tag - run: | - echo "TAG=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV - - name: Build and Push - run: | - acorn build --tag ghcr.io/${{ github.repository }}:$TAG . - acorn push ghcr.io/${{ github.repository }}:$TAG -``` - -The action is automatically provided with a `GITHUB_TOKEN` that already has permission to push to the registry for its own repo, so no special secrets configuration is needed. - -You can choose any other Linux or macOS runner for the `runs-on`, see [GitHub Docs](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#choosing-github-hosted-runners) for available choices or specify your own self-hosted runner. - -## Setup Action - -The setup action creates a k3s cluster, installs acorn, and hooks everything up so you can use the `acorn` CLI just like you would from your workstation. - -### Usage -```yaml -name: My Workflow -on: - push: {} -jobs: - publish: - steps: - - uses: actions/checkout@v3 - - uses: acorn-io/actions-setup@v1 - - run: | - # Do something with the CLI - acorn --version -``` - -### Options - -| Key | Default | Description | -| --------------- | ---------| ----------- | -| `acorn-version` | `latest` | Version of Acorn to install -| `k3s-version` | `latest` | Version of K3s to install -| `kubeconfig` | (none) | Provide a kubeconfig to use instead of installing k3s - -See [actions-setup](https://github.com/acorn-io/actions-setup#readme) for additional advanced options. For example it is possible to point acorn at an existing k8s cluster instead of spinning up a new one. - -## Login Action - -The login action logs into a registry so that later steps can push an acorn to it. - -### Usage - -```yaml -name: My Workflow -on: - push: - tags: - - "v*" -jobs: - publish: - steps: - - uses: actions/checkout@v3 - - uses: acorn-io/actions-setup@v1 - - uses: acorn-io/actions-login@v1 - with: - registry: docker.io - username: yourDockerHubUsername - password: ${{ secrets.DOCKERHUB_PASSWORD }} -``` - -### Options - -| Key | Default | Description | -| ---------- | ------------ | ----------- | -| `registry` | **Required** | Registry address to login to (e.g. `ghcr.io` or `docker.io`) -| `username` | **Required** | Registry username -| `password` | **Required** | Registry password diff --git a/docs/docs/55-integrations/_category_.yaml b/docs/docs/55-integrations/_category_.yaml deleted file mode 100644 index 08b3b4a14..000000000 --- a/docs/docs/55-integrations/_category_.yaml +++ /dev/null @@ -1 +0,0 @@ -label: Integrations diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index 80b8cacc0..c839a4f2a 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -106,6 +106,11 @@ const config = { darkTheme: darkCodeTheme, additionalLanguages: ['cue', 'docker'], }, + algolia: { + appId: 'KA4CNV2PUX', + apiKey: 'd65a6b6f6eb217f433716ba99aa51bc2', + indexName: 'runtime-acorn', + } }) }; diff --git a/docs/sidebars.js b/docs/sidebars.js index a57a0481f..63785442d 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -29,57 +29,13 @@ const sidebars = { "getting-started", { "type": "category", - "label": "Authoring Acornfiles", + "label": "Administration", "items": [ - "authoring/overview", - "authoring/best-practices", - "authoring/structure", - "authoring/containers", - "authoring/volumes", - "authoring/secrets", - "authoring/jobs", - "authoring/args-and-profiles", - "authoring/localdata", - "authoring/permissions", - "authoring/labels", - "authoring/services", - "authoring/advanced", - "authoring/nested-acorns" + "admin/volumeclasses", + "admin/computeclasses", + "admin/alpha-image-allow-rules", ] }, - "publishing", - { - "type": "category", - "label": "Running Acorn Apps", - "items": [ - "running/args-and-secrets", - "running/networking", - "running/certificates", - "running/volumes", - "running/linking-acorns", - "running/labels", - "running/troubleshooting", - "running/upgrades", - "running/auto-upgrades", - "running/namespaces-and-service-accounts", - "running/compute-resources", - "running/projects", - "running/update-acorns", - "running/remove-acorns", - "running/dev", - "running/events", - "running/alpha-image-allow-rules" - ], - "collapsed": true - }, - { - "type": "category", - "label": "Integrations", - "items": [ - "integrations/github-actions" - ], - "collapsed": true - }, { "type": "category", "label": "Architecture", @@ -143,19 +99,6 @@ const sidebars = { "reference/command-line/acorn_wait" ] }, - { - "type": "category", - "label": "Administration", - "items": [ - "reference/admin/volumeclasses", - "reference/admin/computeclasses" - ] - }, - "reference/acornfile", - "reference/functions", - "reference/compute-resources", - "reference/encryption", - "reference/services" ], "collapsed": true },