O Archestack no Kubernetes, a forma curta
Esta é a forma mais curta de chegar a um cluster que já gere, AKS ou outro qualquer: o Archestack
sob um caminho de um hostname que o seu ingress já serve, como
https://apps.example.com/archestack/. Cinco ficheiros de manifesto e um pipeline, no
Azure DevOps, no GitHub Actions ou no GitLab CI, sem Helm, e nada a criar fora do cluster: o
PostgreSQL também corre lá dentro. Uma instalação AKS real corre exatamente estes manifestos, a
partir do pipeline do Azure DevOps.
Quer hostnames próprios, uma base de dados gerida, várias réplicas da API e atualizações noturnas? Alojamento no AKS é a versão completa.
O que corre
https://apps.example.com
/archestack/api, /archestack/hubs -> archestack-api 1 pod, with disks for files and backups
/archestack/... -> archestack-web 2 pods: the builder and the published app
/archestack-grafana/ -> archestack-grafana optional, with Prometheus, Tempo and Loki
archestack-api -> archestack-postgres PostgreSQL 16 on a disk of its own
O browser carrega o builder a partir de /archestack/ e chama a API em
/archestack/api no mesmo endereço, por isso não há um segundo hostname nem
configuração cross-origin. As atualizações em tempo real usam um WebSocket para
/archestack/hubs. A aplicação publicada está em /archestack/app/.
Do que precisa
- Um cluster com ingress-nginx e um hostname que ele já serve por HTTPS.
-
Um namespace
archestack, e uma storage class que forneça discos, como faz a predefinida do AKS. - Azure DevOps, GitHub ou GitLab, com o repositório a partir do qual o pipeline corre. Os runners próprios do GitHub e do GitLab chegam à API do cluster a partir da internet, por isso um cluster privado precisa de um runner seu dentro da rede dele.
Três passos
- Descompacte o kit no seu repositório como
archestack/. -
Configure o pipeline no seu sistema de CI, como diz a secção dele mais
abaixo: onde fica o seu ficheiro, e um ambiente por cada ambiente do Archestack,
archestack-devprimeiro, com estas cinco, as três últimas como segredos:HOST apps.example.com ADMIN_EMAIL you@example.com POSTGRES_PASSWORD secret, set once and never changed ADMIN_PASSWORD secret, the first admin's password GRAFANA_PASSWORD secret, Grafana's user admin -
Corra o pipeline e escolha o ambiente. O primeiro arranque demora alguns minutos, porque a API
cria e migra as suas bases de dados antes de responder. Depois inicie sessão em
https://<HOST>/archestack/com o email e a palavra-passe do admin.
O pipeline
O kit tem-no para três sistemas de CI. Cada um dá os mesmos três passos: preenche os manifestos, cria o Secret, e depois faz deploy e espera até todos os pods estarem prontos.
Azure DevOps
- Acrescente
archestack/azure-pipelines.ymlcomo pipeline. -
Em Pipelines, Environments, crie
archestack-deve acrescente-lhe o namespacearchestackdo cluster como recurso Kubernetes. Criearchestack-tst,-acce-prdda mesma forma quando precisar deles. -
Em Pipelines, Library, crie um grupo de variáveis com o mesmo nome,
archestack-dev, com as cinco, as palavras-passe como segredos.
# archestack/azure-pipelines.yml: Archestack on a Kubernetes cluster, under /archestack of a hostname the cluster's
# ingress already serves. Run it by hand, pick the environment and the Archestack version.
trigger:
branches:
include: [main]
paths:
include:
- archestack/**
parameters:
- name: environment
displayName: Environment
type: string
default: dev
values: [dev, tst, acc, prd]
- name: imageTag
displayName: Archestack version (image tag)
type: string
default: latest
- name: monitoring
displayName: Deploy Grafana with Prometheus, Tempo and Loki
type: boolean
default: true
variables:
# One variable group per environment, named archestack-<environment>, holding:
# HOST the hostname the cluster's ingress serves, such as apps.example.com
# ADMIN_EMAIL the first Archestack admin, created on the first start
# POSTGRES_PASSWORD secret; set once, see the note at "Secrets" below
# ADMIN_PASSWORD secret; the first admin's password
# GRAFANA_PASSWORD secret; Grafana's user admin
- group: archestack-${{ parameters.environment }}
- name: namespace
value: archestack
# The public Docker Hub images of Archestack.
- name: registry
value: docker.io/nickpeelman
stages:
- stage: deploy
displayName: Deploy ${{ parameters.environment }}
jobs:
- deployment: deploy
displayName: Deploy Archestack
pool:
vmImage: ubuntu-latest
# An Azure DevOps environment with the cluster's namespace added as a Kubernetes resource.
environment:
name: archestack-${{ parameters.environment }}
resourceName: archestack
resourceType: Kubernetes
strategy:
runOnce:
deploy:
steps:
- checkout: self
# Only these six names are replaced, so the $(POSTGRES_PASSWORD) the API reads and
# Grafana's $${...} stay as they are.
- bash: |
set -e
if [ -z "$HOST" ] || [ -z "$ADMIN_EMAIL" ]; then
echo "##vso[task.logissue type=error]Set HOST and ADMIN_EMAIL in the variable group archestack-${{ parameters.environment }}."
exit 1
fi
mkdir -p "$(Agent.TempDirectory)/manifests"
for f in archestack/manifests/*.yml; do
envsubst '${NAMESPACE} ${REGISTRY} ${IMAGE_TAG} ${ADMIN_EMAIL} ${HOST} ${MONITORING}' < "$f" > "$(Agent.TempDirectory)/manifests/$(basename "$f")"
done
if [ "$MONITORING" != "true" ]; then rm "$(Agent.TempDirectory)/manifests/observability.yml"; fi
displayName: Fill in the manifests
env:
NAMESPACE: $(namespace)
REGISTRY: $(registry)
IMAGE_TAG: ${{ parameters.imageTag }}
ADMIN_EMAIL: $(ADMIN_EMAIL)
HOST: $(HOST)
MONITORING: ${{ lower(parameters.monitoring) }}
# Secrets. The database password is fixed when PostgreSQL first starts on an empty disk:
# changing it afterwards does not change it in the database, and the API can no longer
# connect. The admin password is used only to create the first admin.
- bash: |
set -e
for value in "$PG_PASSWORD" "$ADMIN_PASSWORD_VALUE" "$GRAFANA_PASSWORD_VALUE"; do
case "$value" in
"" | '$('*)
echo "##vso[task.logissue type=error]Set the secrets POSTGRES_PASSWORD, ADMIN_PASSWORD and GRAFANA_PASSWORD in the variable group archestack-${{ parameters.environment }}."
exit 1
;;
esac
done
kubectl create secret generic archestack-secrets \
--from-literal=postgres-password="$PG_PASSWORD" \
--from-literal=admin-password="$ADMIN_PASSWORD_VALUE" \
--from-literal=grafana-admin-password="$GRAFANA_PASSWORD_VALUE" \
-n $(namespace) --dry-run=client -o yaml > "$(Agent.TempDirectory)/manifests/secrets.yml"
displayName: Make the secret
env:
PG_PASSWORD: $(POSTGRES_PASSWORD)
ADMIN_PASSWORD_VALUE: $(ADMIN_PASSWORD)
GRAFANA_PASSWORD_VALUE: $(GRAFANA_PASSWORD)
# Waits for every rollout. The API's first start creates and migrates its databases.
- task: KubernetesManifest@1
displayName: Deploy Archestack
inputs:
action: deploy
namespace: $(namespace)
rolloutStatusTimeout: 1800
manifests: $(Agent.TempDirectory)/manifests/*.yml
- bash: |
echo "Builder: https://$(HOST)/archestack/"
echo "Published app: https://$(HOST)/archestack/app/"
echo "Grafana: https://$(HOST)/archestack-grafana/"
displayName: Archestack addresses - Fill in the manifests substitui seis nomes nos manifestos e nada mais, por isso a palavra-passe da base de dados que a API lê em execução continua a ser uma referência ao Secret.
- Make the secret transforma as três palavras-passe num só Secret do Kubernetes. Para a execução quando falta uma, em vez de fazer deploy com uma palavra-passe vazia.
- Deploy Archestack aplica a pasta e espera até todos os pods estarem prontos. Com monitoring desligado, o Grafana e a sua stack ficam de fora.
GitHub Actions
-
Mova
archestack/github-actions.ymlpara.github/workflows/archestack.yml: o GitHub só corre workflows a partir dessa pasta. -
Em Settings, Environments, crie
archestack-dev, comHOSTeADMIN_EMAILcomo variáveis e as três palavras-passe como segredos, mais o segredoKUBECONFIG: o que okubeconfig.shimprime. Num repositório privado, os ambientes precisam do GitHub Pro, Team ou Enterprise. - Corra-o em Actions, Archestack, Run workflow.
# archestack/github-actions.yml: Archestack on a Kubernetes cluster, from GitHub Actions. GitHub runs
# workflows from one folder only: move this file to .github/workflows/archestack.yml. A push to main
# that changes archestack/ deploys to dev; under Actions, Archestack, Run workflow, you pick the
# environment and the Archestack version.
name: Archestack
on:
push:
branches: [main]
paths: ["archestack/**"]
workflow_dispatch:
inputs:
environment:
description: Environment
type: choice
options: [dev, tst, acc, prd]
default: dev
imageTag:
description: Archestack version (image tag)
default: latest
monitoring:
description: Deploy Grafana with Prometheus, Tempo and Loki
type: boolean
default: true
permissions:
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
# One GitHub environment per environment, named archestack-<environment>, holding the variables
# HOST the hostname the cluster's ingress serves, such as apps.example.com
# ADMIN_EMAIL the first Archestack admin, created on the first start
# and the secrets
# POSTGRES_PASSWORD set once: PostgreSQL keeps the password it first started with
# ADMIN_PASSWORD the first admin's password
# GRAFANA_PASSWORD Grafana's user admin
# KUBECONFIG the cluster sign-in archestack/kubeconfig.sh prints
environment: archestack-${{ inputs.environment || 'dev' }}
concurrency: archestack-${{ inputs.environment || 'dev' }} # one rollout per environment at a time
steps:
- uses: actions/checkout@v4
- uses: azure/setup-kubectl@v4
with:
version: v1.35.9 # within one minor version of the cluster's
- name: Sign in to the cluster
run: |
if [ -z "$KUBECONFIG_FILE" ]; then
echo "::error::Set the secret KUBECONFIG in the environment archestack-${{ inputs.environment || 'dev' }}."
exit 1
fi
install -m 600 /dev/null "$RUNNER_TEMP/kubeconfig"
printf '%s\n' "$KUBECONFIG_FILE" > "$RUNNER_TEMP/kubeconfig"
echo "KUBECONFIG=$RUNNER_TEMP/kubeconfig" >> "$GITHUB_ENV"
env:
KUBECONFIG_FILE: ${{ secrets.KUBECONFIG }}
- name: Deploy Archestack
run: bash archestack/deploy.sh
env:
IMAGE_TAG: ${{ inputs.imageTag || 'latest' }}
# A push has no inputs, so it deploys with monitoring on.
MONITORING: ${{ (github.event_name == 'workflow_dispatch' && !inputs.monitoring) && 'false' || 'true' }}
HOST: ${{ vars.HOST }}
ADMIN_EMAIL: ${{ vars.ADMIN_EMAIL }}
POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }}
ADMIN_PASSWORD: ${{ secrets.ADMIN_PASSWORD }}
GRAFANA_PASSWORD: ${{ secrets.GRAFANA_PASSWORD }} - Um push para
mainque alterearchestack/faz deploy para desenvolvimento com as imagenslatest, como faz o pipeline do Azure DevOps. -
concurrencyimpede que duas execuções façam rollout para o mesmo ambiente ao mesmo tempo. - O kubectl está fixado. Mantenha-o a não mais de uma versão minor de distância da do seu cluster.
GitLab CI
-
Inclua o ficheiro do kit a partir do
.gitlab-ci.ymldo próprio repositório, ou crie um só com isto:include: - local: archestack/gitlab-ci.yml -
Em Settings, CI/CD, Variables, acrescente as cinco com o âmbito de ambiente
archestack-dev, as palavras-passe mascaradas, maisKUBECONFIGdo tipo File: o que okubeconfig.shimprime. Proteja-as todas, para que só as branches protegidas as recebam. - Corra-o em Build, Pipelines, New pipeline, e escolha lá o ambiente.
# archestack/gitlab-ci.yml: Archestack on a Kubernetes cluster, from GitLab CI. Include it from the
# repository's own .gitlab-ci.yml (a file holding just these two lines when there is none):
# include:
# - local: archestack/gitlab-ci.yml
# A push to the default branch that changes archestack/ deploys to dev; under Build, Pipelines,
# New pipeline, you pick the environment and the Archestack version.
variables:
ARCHESTACK_ENVIRONMENT:
value: dev
options: [dev, tst, acc, prd]
description: Environment
ARCHESTACK_IMAGE_TAG:
value: latest
description: Archestack version (image tag)
ARCHESTACK_MONITORING:
value: "true"
options: ["true", "false"]
description: Deploy Grafana with Prometheus, Tempo and Loki
archestack:
stage: deploy
image: alpine:3.22
rules:
- if: $CI_PIPELINE_SOURCE == "web"
- if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
changes: [archestack/**/*]
# Variables scoped to this environment (Settings, CI/CD, Variables), all protected:
# HOST the hostname the cluster's ingress serves, such as apps.example.com
# ADMIN_EMAIL the first Archestack admin, created on the first start
# POSTGRES_PASSWORD masked; set once: PostgreSQL keeps the password it first started with
# ADMIN_PASSWORD masked; the first admin's password
# GRAFANA_PASSWORD masked; Grafana's user admin
# KUBECONFIG type File: the cluster sign-in archestack/kubeconfig.sh prints. With the
# GitLab agent for Kubernetes, set KUBE_CONTEXT to the agent's context instead.
environment:
name: archestack-$ARCHESTACK_ENVIRONMENT
resource_group: archestack-$ARCHESTACK_ENVIRONMENT # one rollout per environment at a time
variables:
KUBECTL_VERSION: v1.35.9 # within one minor version of the cluster's
before_script:
- apk add --no-cache bash curl gettext-envsubst
- curl -fsSLo /usr/local/bin/kubectl "https://dl.k8s.io/release/$KUBECTL_VERSION/bin/linux/amd64/kubectl"
- chmod +x /usr/local/bin/kubectl
- 'if [ -n "${KUBE_CONTEXT:-}" ]; then kubectl config use-context "$KUBE_CONTEXT"; fi'
script:
- IMAGE_TAG=$ARCHESTACK_IMAGE_TAG MONITORING=$ARCHESTACK_MONITORING bash archestack/deploy.sh - Um push para a branch predefinida que altere
archestack/faz deploy para desenvolvimento com as imagenslatest. - O job corre no stage
deploy, que o GitLab tem, a não ser que o seu.gitlab-ci.ymlliste stages próprios sem ele. - O agente do GitLab para Kubernetes também funciona: defina
KUBE_CONTEXTcom o contexto do agente em vez deKUBECONFIG. -
resource_groupimpede que dois pipelines façam rollout para o mesmo ambiente ao mesmo tempo. - A imagem e o kubectl estão fixados. Mantenha o kubectl a não mais de uma versão minor de distância da do seu cluster.
O que o GitHub Actions e o GitLab CI correm
Ambos correm o deploy.sh, os três passos do pipeline do Azure DevOps num só script:
#!/usr/bin/env bash
# archestack/deploy.sh: what github-actions.yml and gitlab-ci.yml run, the same three steps
# azure-pipelines.yml takes with Azure DevOps' own tasks. kubectl has to reach the cluster already.
# Reads HOST, ADMIN_EMAIL, POSTGRES_PASSWORD, ADMIN_PASSWORD and GRAFANA_PASSWORD, and optionally
# IMAGE_TAG (latest) and MONITORING (true):
# IMAGE_TAG=1.4.23 bash archestack/deploy.sh
set -euo pipefail
cd "$(dirname "$0")"
for name in HOST ADMIN_EMAIL POSTGRES_PASSWORD ADMIN_PASSWORD GRAFANA_PASSWORD; do
if [ -z "${!name:-}" ]; then echo "Set $name for this environment" >&2; exit 1; fi
done
export NAMESPACE=${NAMESPACE:-archestack}
export REGISTRY=${REGISTRY:-docker.io/nickpeelman} # the public Docker Hub images of Archestack
export IMAGE_TAG=${IMAGE_TAG:-latest}
export MONITORING=${MONITORING:-true}
export HOST ADMIN_EMAIL
# 1. Fill in the manifests. Only these six names are replaced, so the $(POSTGRES_PASSWORD) the API
# reads and Grafana's $${...} stay as they are.
out=$(mktemp -d)
trap 'rm -rf "$out"' EXIT
for f in manifests/*.yml; do
envsubst '${NAMESPACE} ${REGISTRY} ${IMAGE_TAG} ${ADMIN_EMAIL} ${HOST} ${MONITORING}' < "$f" > "$out/$(basename "$f")"
done
if [ "$MONITORING" != true ]; then rm "$out/observability.yml"; fi
# 2. The secret, handed from one kubectl to the next and never written to a file. The database
# password is fixed when PostgreSQL first starts on an empty disk; the admin password only makes
# the first admin.
kubectl create secret generic archestack-secrets -n "$NAMESPACE" \
--from-literal=postgres-password="$POSTGRES_PASSWORD" \
--from-literal=admin-password="$ADMIN_PASSWORD" \
--from-literal=grafana-admin-password="$GRAFANA_PASSWORD" \
--dry-run=client -o yaml | kubectl apply -f -
# 3. Deploy, then wait for every rollout. The API's first start creates and migrates its databases.
applied=$(kubectl apply -n "$NAMESPACE" -f "$out" -o name)
for workload in $(grep -E '^(deployment|statefulset)\.apps/' <<< "$applied"); do
kubectl rollout status -n "$NAMESPACE" "$workload" --timeout=30m
done
echo "Builder: https://$HOST/archestack/"
echo "Published app: https://$HOST/archestack/app/"
if [ "$MONITORING" = true ]; then echo "Grafana: https://$HOST/archestack-grafana/"; fi Iniciar sessão no cluster
O GitHub Actions e o GitLab CI iniciam sessão com o kubeconfig que o kubeconfig.sh
imprime: uma service account com acesso ao namespace archestack e a nada mais, com um
token que não expira. Corra-o uma vez por cluster, como alguém que lá possa criar roles:
#!/usr/bin/env bash
# archestack/kubeconfig.sh: the cluster sign-in for the GitHub Actions or GitLab CI pipeline, allowed
# into the archestack namespace and nothing else. Run it once per cluster, as someone who may create
# roles there, with kubectl pointing at that cluster:
# bash archestack/kubeconfig.sh > kubeconfig-dev
# Paste the file into the environment's KUBECONFIG, then delete it. To take the access away:
# kubectl -n archestack delete secret archestack-deploy-token
set -euo pipefail
NAMESPACE=${NAMESPACE:-archestack}
kubectl create namespace "$NAMESPACE" --dry-run=client -o yaml | kubectl apply -f - >&2
kubectl apply -n "$NAMESPACE" -f - >&2 <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: archestack-deploy
---
# Everything inside the namespace (the built-in admin role), nothing outside it.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: archestack-deploy
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: admin
subjects:
- kind: ServiceAccount
name: archestack-deploy
namespace: $NAMESPACE
---
# A token that does not expire. Deleting this secret revokes it.
apiVersion: v1
kind: Secret
metadata:
name: archestack-deploy-token
annotations:
kubernetes.io/service-account.name: archestack-deploy
type: kubernetes.io/service-account-token
EOF
# Kubernetes fills the token in a moment later.
token=""
for _ in $(seq 30); do
token=$(kubectl get secret archestack-deploy-token -n "$NAMESPACE" -o jsonpath='{.data.token}' | base64 --decode)
if [ -n "$token" ]; then break; fi
sleep 1
done
if [ -z "$token" ]; then echo "The token did not appear in archestack-deploy-token" >&2; exit 1; fi
ca=$(kubectl get secret archestack-deploy-token -n "$NAMESPACE" -o jsonpath='{.data.ca\.crt}')
server=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')
cat <<EOF
apiVersion: v1
kind: Config
clusters:
- name: cluster
cluster:
server: $server
certificate-authority-data: $ca
users:
- name: archestack-deploy
user:
token: $token
contexts:
- name: archestack
context:
cluster: cluster
user: archestack-deploy
namespace: $NAMESPACE
current-context: archestack
EOF - Não o seu próprio kubeconfig. Leva os seus direitos sobre todo o cluster, e no AKS com início de sessão via Entra ID pede a uma pessoa que inicie sessão, o que um pipeline não consegue fazer.
- Retirar o acesso é apagar o Secret
archestack-deploy-tokenno namespace. Corra o script outra vez para obter um novo.
Os ficheiros
archestack/
azure-pipelines.yml Azure DevOps: fills in the manifests, makes the secret, deploys
github-actions.yml GitHub Actions: move it to .github/workflows/archestack.yml
gitlab-ci.yml GitLab CI: include it from the repository's .gitlab-ci.yml
deploy.sh what GitHub Actions and GitLab CI run: the same three steps
kubeconfig.sh their sign-in, allowed into the archestack namespace only
manifests/
postgres.yml PostgreSQL 16 with a 32 GB disk
api.yml the API, with disks for files (20 GB) and backups (50 GB)
web.yml the builder and the published app
ingress.yml /archestack on the hostname the cluster already serves
observability.yml optional: Grafana with Prometheus, Tempo and Loki O ingress é o único ficheiro que tem de se ajustar ao seu cluster:
# Archestack on the cluster's ingress-nginx, under a path of the shared host:
# https://${HOST}/archestack/ the builder
# https://${HOST}/archestack/app/<page> the published app
# https://${HOST}/archestack/api, /hubs the API and live updates
# No rewrite-target: the API (Http__PathBase) and the frontend (BASE_PATH) both expect the prefix.
# No oauth2 annotations on this one: they would replace the bearer token every API call carries.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: archestack
annotations:
# The default 1m refuses package imports and file uploads.
nginx.ingress.kubernetes.io/proxy-body-size: "1024m"
# /hubs keeps a WebSocket open; backups and imports read for a long time.
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
spec:
ingressClassName: nginx
rules:
- host: ${HOST}
http:
paths:
- path: /archestack/api
pathType: Prefix
backend:
service:
name: archestack-api
port:
number: 8080
- path: /archestack/hubs
pathType: Prefix
backend:
service:
name: archestack-api
port:
number: 8080
- path: /archestack
pathType: Prefix
backend:
service:
name: archestack-web
port:
number: 80 - Sem reescrita. A API e o builder esperam ambos o prefixo
/archestack(Http__PathBaseemapi.yml,BASE_PATHemweb.yml), por isso o ingress passa os caminhos sem os alterar. - Uploads grandes e ligações longas. O tamanho do body permite importações de pacotes e uploads de ficheiros, e os timeouts mantêm abertos o WebSocket das atualizações em tempo real e os backups longos.
- Nenhum proxy de início de sessão à frente. Uma anotação oauth2 substituiria o token que cada chamada à API leva. O Archestack inicia a sessão das pessoas por si. O ingress do Grafana pode ter um.
Atualizar
Corra o pipeline outra vez com outra tag da imagem. latest leva a release mais
recente; uma versão como 1.0.42 diz exatamente o que corre, e é a forma de levar a
mesma versão do teste à produção. O pod da API é substituído em vez de correr ao lado do antigo,
porque os seus discos só se ligam a um pod de cada vez, por isso a API fica indisponível durante o
minuto que demora a arrancar. Tudo o que criou está nos discos e fica.
Armadilhas
- A palavra-passe da base de dados define-se uma só vez. O PostgreSQL fica com ela quando arranca pela primeira vez num disco vazio. Alterá-la depois no sistema de CI não a altera na base de dados, e a API deixa então de conseguir ligar-se.
- A palavra-passe do admin usa-se uma só vez, para criar o primeiro admin. Depois altere-a no Archestack, não no sistema de CI.
- Os backups ficam no cluster. São escritos no disco
archestack-backups. Copie-os também para outro sítio. - Voltar a uma versão mais antiga pode falhar depois de uma mais recente ter migrado
a base de dados. Teste primeiro uma atualização em
archestack-tst.
Para onde seguir a partir daqui
Fazer deploy a partir do repositório leva as suas aplicações do git a estes ambientes. Alojamento no AKS acrescenta hostnames próprios, uma base de dados gerida, várias réplicas da API e atualizações noturnas.