Commit 160d57e6 authored by Kostis Trantzas's avatar Kostis Trantzas
Browse files

Restructuring the navigation routes, and prioritizing Kubernetes over Compose guides

parent d118609f
Loading
Loading
Loading
Loading
+275 −284
Changes for doc/getting_started/upgrade_guide/2025Q4_2026Q2.md: 275 added lines, 284 removed lines.
Original line number Diff line number Diff line
@@ -2,8 +2,7 @@


This guide upgrades a running OpenSlice instance from release 2025Q4 to release 2026Q2. Follow the
section that matches how the instance was installed: [Docker Compose](#upgrading-a-docker-compose-deployment)
or [Kubernetes](#upgrading-a-kubernetes-deployment).
section that matches how the instance was installed: [Kubernetes](#upgrading-a-kubernetes-deployment) or [Docker Compose](#upgrading-a-docker-compose-deployment).

The two paths differ in where your configuration lives. Docker Compose keeps it in generated files
that sit beside templates the new release updates, so every upgrade asks you to merge. Helm keeps it
@@ -12,7 +11,7 @@ in a values file outside the chart, which the upgrade never touches.

### What changes in this release

The complete difference between the two tags, across both deployment methods:
The complete difference between the two tags, across both deployment methods, as perceived in the main project:

| File | Change |
| ---- | ------ |
@@ -26,8 +25,7 @@ The complete difference between the two tags, across both deployment methods:
| `config.prod.default.json`, `config.theming.default.json` | version string |
| `pom.xml` | module versions |

No service is added or removed, no infrastructure image changes (Keycloak remains 16.1.1, MySQL
5.7.43, Artemis 2.31.1) and the Keycloak realm export is untouched. This is a routine upgrade.
No service is added or removed, no infrastructure image changes and the Keycloak realm export is untouched. This is a routine upgrade.

You can confirm the same on your own checkout:

@@ -42,11 +40,277 @@ git diff --stat tags/2025Q4 tags/2026Q2 -- compose kubernetes pom.xml
> name is ambiguous and git resolves it to the tag with only a warning. The collision affects
> 2025Q4, never 2026Q2.

## Before you begin
---

## Upgrading a Kubernetes deployment

The chart is at `[repo-root]/kubernetes/helm/openslice`. The examples below use `openslice` as both
the namespace and the Helm release name; substitute your own if they differ.

### 1. Prepare the environment

```bash
helm list -n openslice                              # CHART openslice-3.0.0, APP VERSION 2025Q4
helm get values openslice -n openslice > my-values.yaml
```

If that file contains `null`, your settings live in the chart's own `values.yaml`. This is the usual
outcome, because the 2025Q4 deployment guide instructs you to edit that file directly. Two problems
follow: `git checkout` refuses to move while a tracked file carries your edits, and an upgrade fed an
empty values file resets `rooturl`, `storageClass`, `oscreds` and every image tag to the shipped
defaults.

Move your settings out of the chart and hand the chart's own file back to git:

```bash
cd kubernetes/helm/openslice
git diff values.yaml              # every line here belongs in my-values.yaml
cp -n values.yaml ~/values.yaml.mine
git checkout -- values.yaml
git status --porcelain            # values.yaml must no longer appear
cd ../../..
```

> **Important Note:** `cp -n` is deliberate. If you run this step a second time, a plain `cp` would
> copy the file that `git checkout --` has already restored, replacing your saved settings with the
> shipped defaults. Supplying those to the upgrade is precisely the failure this step exists to
> prevent.

Now transcribe the settings from that comparison into `my-values.yaml`, for example:

```yaml
rooturl: http://<your-domain>
storageClass: <your-storage-class>

oscreds:
  mysql:
    keycloak:
      password: "<your-keycloak-db-password>"
      adminpassword: "<your-keycloak-admin-password>"
```

> **Note:** Do not carry the image tags across at this point. They are handled in step 5.

Back up the databases from the MySQL StatefulSet, and snapshot the volume behind
`<release>-mysql-portal-claim0` as well if your storage class supports it:

```bash
kubectl exec -n openslice sts/openslice-mysql -- \
  sh -c 'mysqldump -u root -p"$MYSQL_ROOT_PASSWORD" --single-transaction --routines --events \
    --databases osdb ostmfdb metricodb keycloak' \
  > openslice-backup-$(date +%F).sql

ls -l openslice-backup-*.sql      # a few MB, never zero
```

> **Note:** `--single-transaction` matters because the services continue writing while the dump
> runs, and this file is what the rollback procedure depends on.

### 2. Download the new release

```bash
git fetch --all --tags
git checkout tags/2026Q2
git describe --tags               # 2026Q2
```

### 3. Refresh the Web UI configuration

The chart mounts `config.prod.json` and `config.theming.json`, the copies you made at install time.
The checkout cannot modify them, so they still carry the 2025Q4 version string, and each of them
places a version on screen: `PORTALVERSION` in the first, and a release name hardcoded inside
`FOOTER_HTML` in the second.

```bash
cd kubernetes/helm/openslice/files/org.etsi.osl.tmf.web/src/assets/config
diff config.prod.default.json    config.prod.json
diff config.theming.default.json config.theming.json
```

The new release changed one line in each: the version. Where a comparison shows only that line, copy
the new default over. Where it also shows edits of your own, keep your file and move the version
inside it instead, exactly as described in the Docker Compose section.

```bash
grep PORTALVERSION config.prod.json     # must read 2026Q2
cd ../../../../../../..
```

> **Note:** `theming.scss` and `files/org.etsi.osl.portal.web/src/js/config.js` are identical in both
> releases. `config.js` must nevertheless exist, otherwise `helm upgrade` fails with
> `config.js is required`.

Skipping this step does not prevent the upgrade from succeeding, but the portal footer continues to
name 2025Q4.

### 4. Reconcile your values file

Your values file sits outside the chart, so the upgrade does not touch it:

```bash
git diff tags/2025Q4 tags/2026Q2 -- kubernetes/helm/openslice/values.yaml
```

The release adds one key, and it carries a default:

**Back up your databases.** The services run Hibernate with `ddl-auto: update`, so the schema
migrates itself on first start of the new release and nothing migrates it back. The backup commands
for each deployment method are the first step of their respective sections below.
```yaml
osom:
  secretsController:
    enable: false
```

`templates/osom.yaml` reads it as `.Values.osom.secretsController.enable | default "false"` and the
chart's own `values.yaml` supplies it, so a values file that never mentions it is perfectly valid.
Nothing is renamed or removed in this release.

> **Important Note:** `rooturl` matters most. Every service's Keycloak issuer URL is templated from
> it, as are the allowed origins, the Kroki URL and the portal-web `config.js`. The issuer mismatch
> that affects Docker Compose deployments cannot occur here as long as your values file still sets
> it.

### 5. Pin the image tags

The 2025Q4 chart ships `tag: "latest"` with `pullPolicy: Always` for all 13 OpenSlice images, and an
installation that followed the deployment guide never changed them. Unless you pinned them yourself,
that is the state of your deployment, and three consequences follow.

**You cannot determine which release is running.** `helm list` reports the chart's `appVersion`, not
the contents of the images, so it reports 2025Q4 regardless. `kubectl get deploy` shows only
`:latest`. The only reliable signal is the digest each pod resolved:

```bash
kubectl get pods -n openslice \
  -o jsonpath='{range .items[*]}{.status.containerStatuses[0].image}{"  "}{.status.containerStatuses[0].imageID}{"\n"}{end}' \
  | grep osl/code | sort -u
```

Identical digests across pods mean they were pulled together. Differing digests mean a pod restarted
later and collected a newer build than its neighbours.

**Part of the deployment may have upgraded itself already.** With `pullPolicy: Always`, every pod
restart re-pulls `latest`. A node reboot or an evicted pod after 2026Q2 was published moves that
service to 2026Q2 on its own, with no upgrade performed and no record in `helm history`.

**A rollback will not work.** `helm rollback` restores the previous manifests, but those manifests
also specify `latest`, so the pods re-pull the newest images and you return to where you started.
Until the tags are pinned, your database backup is the only means of return.

To pin them, add the following to your values file. You could also leave an empty string at the specified tags
as each template resolves its tag as `{{ .Values.image.<component>.tag | default .Chart.AppVersion }}`, so an 
empty string falls back to the chart's `appVersion`, which at 2026Q2 is `2026Q2`:

```yaml
image:
  bugzilla:   { tag: "2026Q2" }
  centrallog: { tag: "2026Q2" }
  manoclient: { tag: "2026Q2" }
  osom:       { tag: "2026Q2" }
  portalapi:  { tag: "2026Q2" }
  osscapi:    { tag: "2026Q2" }
  oasapi:     { tag: "2026Q2" }
  portalweb:  { tag: "2026Q2" }
  tmfweb:     { tag: "2026Q2" }
  cridge:     { tag: "2026Q2" }
  metrico:    { tag: "2026Q2" }
  mcpserver:  { tag: "2026Q2" }
  mcpbackend: { tag: "2026Q2" }
```

> **Note:** Leave `artemis`, `blockdiag`, `keycloak`, `kroki` and `mysql` unchanged. They carry
> explicit upstream versions, unchanged in this release, and do not follow the chart's appVersion.

This resolves all three problems permanently. From this upgrade onwards every pod resolves to the
chart's `appVersion`, so what is deployed is what you checked out, restarts are stable, and a
rollback returns the previous code rather than the same images again.

### 6. Render the chart before upgrading

A mistake caught at this point costs nothing to correct:

```bash
helm template openslice ./kubernetes/helm/openslice -n openslice -f my-values.yaml \
  | grep -oE "labs\.etsi\.org:5050/osl/code/[^\"]*" | sed 's/.*://' | sort | uniq -c
```

All 13 images must read `2026Q2`. A result of `latest` means the chart never received your values
file; `2025Q4` means the checkout did not take effect.

### 7. Deploy

```bash
helm upgrade openslice ./kubernetes/helm/openslice \
  -n openslice \
  -f my-values.yaml \
  --atomic --timeout 15m

kubectl -n openslice rollout status deploy --timeout=15m
kubectl -n openslice get pods
```

`--atomic` rolls the release back if the new pods never become ready. It has no effect on database
schema changes; your backup covers those.

Allow several minutes. The TMF API and Assurance API pods are the last to report ready, and Hibernate
applies schema changes as they start.

> **Note:** `rollout status` occasionally gives up on one of those pods shortly before it settles.
> Inspect the pod itself rather than reacting to that timeout.

Keycloak, MySQL and Artemis remain running throughout, because this release changes none of their
images, so nothing requires restarting afterwards. The two Compose steps for that have no equivalent
here: the `tmfweb` and `portalweb` images carry the front ends, and the ingress routes to Services
rather than to pod addresses.

### 8. Validate the upgrade

```bash
helm list -n openslice            # CHART openslice-4.1.0, APP VERSION 2026Q2

kubectl -n openslice get deploy \
  -o jsonpath='{range .items[*]}{.spec.template.spec.containers[0].image}{"\n"}{end}' \
  | grep osl/code | sed 's/.*://' | sort | uniq -c

kubectl exec -n openslice sts/openslice-mysql -- \
  sh -c 'mysql -u root -p"$MYSQL_ROOT_PASSWORD" -N -B \
    -e "select table_schema, count(*) from information_schema.tables \
        where table_schema in (\"osdb\",\"ostmfdb\",\"metricodb\",\"keycloak\") group by table_schema"'
```

Then open the portal, check the version in the footer, sign in, and confirm that your Service
Specifications and Product Offerings are listed.

> **Note:** A footer that still names 2025Q4 means step 3 was skipped. The upgrade itself is
> unaffected.

### Rolling back a Kubernetes deployment

```bash
helm rollback openslice -n openslice
```

Helm rolls back the manifests; your data remains as 2026Q2 left it. This returns you to 2025Q4 code
only if revision 1 carried pinned image tags. If you upgraded from an installation that used
`latest`, the restored manifests also specify `latest` and the pods re-pull 2026Q2, in which case the
database dump is your only means of return.

If Hibernate has already altered the schema, restore the dump first:

```bash
kubectl exec -i -n openslice sts/openslice-mysql -- \
  sh -c 'mysql -u root -p"$MYSQL_ROOT_PASSWORD"' < openslice-backup-YYYY-MM-DD.sql
helm rollback openslice -n openslice
```

> **Important Note:** A rollback moves the Helm release and nothing else. Your working copy remains
> on 2026Q2, where the next `helm upgrade` from that directory would quietly ship the new release
> again. Return the source tree as well:

```bash
git checkout tags/2025Q4
cd kubernetes/helm/openslice/files/org.etsi.osl.tmf.web/src/assets/config
cp config.prod.default.json    config.prod.json
cp config.theming.default.json config.theming.json
```

---

@@ -176,7 +440,7 @@ Eleven lines, all reading `2026Q2`.
> and then silently match nothing on every later upgrade.

The build in the next step tags what it produces with these names, so afterwards `docker ps` reports
the release you are running, and the 2025Q4 images remain on disk for a rollback.
the release you are running, and the 2025Q4 images remain on disk for a rollback. Older images are also available online by tag, so there is no compulsory need to keep them locally.

### 5. Build the new release

@@ -285,12 +549,11 @@ That last line must read `2026Q2` before you continue.

```bash
cd org.etsi.osl.main/compose
docker compose --profile prod up -d --build
docker compose --profile prod up -d
docker compose --profile prod restart
docker compose restart nginx
```

`--build` compiles the images from the checkouts and tags them with the names pinned in step 4.

> **Important Note:** Restart everything, not only the backends. A source build normally leaves
> MySQL, Keycloak and Artemis untouched, in which case the restart costs a few seconds. But if
@@ -378,278 +641,6 @@ from a stock installation that tag is `:latest`.

---

## Upgrading a Kubernetes deployment

The chart is at `[repo-root]/kubernetes/helm/openslice`. The examples below use `openslice` as both
the namespace and the Helm release name; substitute your own if they differ.

### 1. Prepare the environment

```bash
helm list -n openslice                              # CHART openslice-3.0.0, APP VERSION 2025Q4
helm get values openslice -n openslice > my-values.yaml
```

If that file contains `null`, your settings live in the chart's own `values.yaml`. This is the usual
outcome, because the 2025Q4 deployment guide instructs you to edit that file directly. Two problems
follow: `git checkout` refuses to move while a tracked file carries your edits, and an upgrade fed an
empty values file resets `rooturl`, `storageClass`, `oscreds` and every image tag to the shipped
defaults.

Move your settings out of the chart and hand the chart's own file back to git:

```bash
cd kubernetes/helm/openslice
git diff values.yaml              # every line here belongs in my-values.yaml
cp -n values.yaml ~/values.yaml.mine
git checkout -- values.yaml
git status --porcelain            # values.yaml must no longer appear
cd ../../..
```

> **Important Note:** `cp -n` is deliberate. If you run this step a second time, a plain `cp` would
> copy the file that `git checkout --` has already restored, replacing your saved settings with the
> shipped defaults. Supplying those to the upgrade is precisely the failure this step exists to
> prevent.

Now transcribe the settings from that comparison into `my-values.yaml`, for example:

```yaml
rooturl: http://<your-domain>
storageClass: <your-storage-class>

oscreds:
  mysql:
    keycloak:
      password: "<your-keycloak-db-password>"
      adminpassword: "<your-keycloak-admin-password>"
```

> **Note:** Do not carry the image tags across at this point. They are handled in step 5.

Back up the databases from the MySQL StatefulSet, and snapshot the volume behind
`<release>-mysql-portal-claim0` as well if your storage class supports it:

```bash
kubectl exec -n openslice sts/openslice-mysql -- \
  sh -c 'mysqldump -u root -p"$MYSQL_ROOT_PASSWORD" --single-transaction --routines --events \
    --databases osdb ostmfdb metricodb keycloak' \
  > openslice-backup-$(date +%F).sql

ls -l openslice-backup-*.sql      # a few MB, never zero
```

> **Note:** `--single-transaction` matters because the services continue writing while the dump
> runs, and this file is what the rollback procedure depends on.

### 2. Download the new release

```bash
git fetch --all --tags
git checkout tags/2026Q2
git describe --tags               # 2026Q2
```

### 3. Refresh the Web UI configuration

The chart mounts `config.prod.json` and `config.theming.json`, the copies you made at install time.
The checkout cannot modify them, so they still carry the 2025Q4 version string, and each of them
places a version on screen: `PORTALVERSION` in the first, and a release name hardcoded inside
`FOOTER_HTML` in the second.

```bash
cd kubernetes/helm/openslice/files/org.etsi.osl.tmf.web/src/assets/config
diff config.prod.default.json    config.prod.json
diff config.theming.default.json config.theming.json
```

The new release changed one line in each: the version. Where a comparison shows only that line, copy
the new default over. Where it also shows edits of your own, keep your file and move the version
inside it instead, exactly as described in the Docker Compose section.

```bash
grep PORTALVERSION config.prod.json     # must read 2026Q2
cd ../../../../../../..
```

> **Note:** `theming.scss` and `files/org.etsi.osl.portal.web/src/js/config.js` are identical in both
> releases. `config.js` must nevertheless exist, otherwise `helm upgrade` fails with
> `config.js is required`.

Skipping this step does not prevent the upgrade from succeeding, but the portal footer continues to
name 2025Q4.

### 4. Reconcile your values file

Your values file sits outside the chart, so the upgrade does not touch it:

```bash
git diff tags/2025Q4 tags/2026Q2 -- kubernetes/helm/openslice/values.yaml
```

The release adds one key, and it carries a default:

```yaml
osom:
  secretsController:
    enable: false
```

`templates/osom.yaml` reads it as `.Values.osom.secretsController.enable | default "false"` and the
chart's own `values.yaml` supplies it, so a values file that never mentions it is perfectly valid.
Nothing is renamed or removed in this release.

> **Important Note:** `rooturl` matters most. Every service's Keycloak issuer URL is templated from
> it, as are the allowed origins, the Kroki URL and the portal-web `config.js`. The issuer mismatch
> that affects Docker Compose deployments cannot occur here as long as your values file still sets
> it.

### 5. Pin the image tags

The 2025Q4 chart ships `tag: "latest"` with `pullPolicy: Always` for all 13 OpenSlice images, and an
installation that followed the deployment guide never changed them. Unless you pinned them yourself,
that is the state of your deployment, and three consequences follow.

**You cannot determine which release is running.** `helm list` reports the chart's `appVersion`, not
the contents of the images, so it reports 2025Q4 regardless. `kubectl get deploy` shows only
`:latest`. The only reliable signal is the digest each pod resolved:

```bash
kubectl get pods -n openslice \
  -o jsonpath='{range .items[*]}{.status.containerStatuses[0].image}{"  "}{.status.containerStatuses[0].imageID}{"\n"}{end}' \
  | grep osl/code | sort -u
```

Identical digests across pods mean they were pulled together. Differing digests mean a pod restarted
later and collected a newer build than its neighbours.

**Part of the deployment may have upgraded itself already.** With `pullPolicy: Always`, every pod
restart re-pulls `latest`. A node reboot or an evicted pod after 2026Q2 was published moves that
service to 2026Q2 on its own, with no upgrade performed and no record in `helm history`.

**A rollback will not work.** `helm rollback` restores the previous manifests, but those manifests
also specify `latest`, so the pods re-pull the newest images and you return to where you started.
Until the tags are pinned, your database backup is the only means of return.

To pin them, add the following to your values file. Each template resolves its tag as
`{{ .Values.image.<component>.tag | default .Chart.AppVersion }}`, so an empty string falls back to
the chart's `appVersion`, which at 2026Q2 is `2026Q2`:

```yaml
image:
  bugzilla:   { tag: "" }
  centrallog: { tag: "" }
  manoclient: { tag: "" }
  osom:       { tag: "" }
  portalapi:  { tag: "" }
  osscapi:    { tag: "" }
  oasapi:     { tag: "" }
  portalweb:  { tag: "" }
  tmfweb:     { tag: "" }
  cridge:     { tag: "" }
  metrico:    { tag: "" }
  mcpserver:  { tag: "" }
  mcpbackend: { tag: "" }
```

> **Note:** Leave `artemis`, `blockdiag`, `keycloak`, `kroki` and `mysql` unchanged. They carry
> explicit upstream versions, unchanged in this release, and do not follow the chart's appVersion.

This resolves all three problems permanently. From this upgrade onwards every pod resolves to the
chart's `appVersion`, so what is deployed is what you checked out, restarts are stable, and a
rollback returns the previous code rather than the same images again.

### 6. Render the chart before upgrading

A mistake caught at this point costs nothing to correct:

```bash
helm template openslice ./kubernetes/helm/openslice -n openslice -f my-values.yaml \
  | grep -oE "labs\.etsi\.org:5050/osl/code/[^\"]*" | sed 's/.*://' | sort | uniq -c
```

All 13 images must read `2026Q2`. A result of `latest` means the chart never received your values
file; `2025Q4` means the checkout did not take effect.

### 7. Deploy

```bash
helm upgrade openslice ./kubernetes/helm/openslice \
  -n openslice \
  -f my-values.yaml \
  --atomic --timeout 15m

kubectl -n openslice rollout status deploy --timeout=15m
kubectl -n openslice get pods
```

`--atomic` rolls the release back if the new pods never become ready. It has no effect on database
schema changes; your backup covers those.

Allow several minutes. The TMF API and Assurance API pods are the last to report ready, and Hibernate
applies schema changes as they start.

> **Note:** `rollout status` occasionally gives up on one of those pods shortly before it settles.
> Inspect the pod itself rather than reacting to that timeout.

Keycloak, MySQL and Artemis remain running throughout, because this release changes none of their
images, so nothing requires restarting afterwards. The two Compose steps for that have no equivalent
here: the `tmfweb` and `portalweb` images carry the front ends, and the ingress routes to Services
rather than to pod addresses.

### 8. Validate the upgrade

```bash
helm list -n openslice            # CHART openslice-4.1.0, APP VERSION 2026Q2

kubectl -n openslice get deploy \
  -o jsonpath='{range .items[*]}{.spec.template.spec.containers[0].image}{"\n"}{end}' \
  | grep osl/code | sed 's/.*://' | sort | uniq -c

kubectl exec -n openslice sts/openslice-mysql -- \
  sh -c 'mysql -u root -p"$MYSQL_ROOT_PASSWORD" -N -B \
    -e "select table_schema, count(*) from information_schema.tables \
        where table_schema in (\"osdb\",\"ostmfdb\",\"metricodb\",\"keycloak\") group by table_schema"'
```

Then open the portal, check the version in the footer, sign in, and confirm that your Service
Specifications and Product Offerings are listed.

> **Note:** A footer that still names 2025Q4 means step 3 was skipped. The upgrade itself is
> unaffected.

### Rolling back a Kubernetes deployment

```bash
helm rollback openslice -n openslice
```

Helm rolls back the manifests; your data remains as 2026Q2 left it. This returns you to 2025Q4 code
only if revision 1 carried pinned image tags. If you upgraded from an installation that used
`latest`, the restored manifests also specify `latest` and the pods re-pull 2026Q2, in which case the
database dump is your only means of return.

If Hibernate has already altered the schema, restore the dump first:

```bash
kubectl exec -i -n openslice sts/openslice-mysql -- \
  sh -c 'mysql -u root -p"$MYSQL_ROOT_PASSWORD"' < openslice-backup-YYYY-MM-DD.sql
helm rollback openslice -n openslice
```

> **Important Note:** A rollback moves the Helm release and nothing else. Your working copy remains
> on 2026Q2, where the next `helm upgrade` from that directory would quietly ship the new release
> again. Return the source tree as well:

```bash
git checkout tags/2025Q4
cd kubernetes/helm/openslice/files/org.etsi.osl.tmf.web/src/assets/config
cp config.prod.default.json    config.prod.json
cp config.theming.default.json config.theming.json
```

---

## Common local modifications

These are the settings that the 2025Q4 deployment guide asks you to configure, together with those
+17 −0

File added.

Preview size limit exceeded, changes collapsed.

+3 −1
Changes for mkdocs.yml: 3 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -121,7 +121,9 @@ nav:
      - NFV Orchestrator Configuration: ./getting_started/configuration/nfvo_config.md
      - Advanced topics:
        - Consuming Services From External OSS: ./getting_started/configuration/consuming_services_from_external_partners.md
    - Upgrading 2025Q4 to 2026Q2: ./getting_started/upgrading_2025Q4_2026Q2.md
    - Upgrade guide: 
        - Introduction: ./getting_started/upgrade_guide/introduction.md
        - 2025Q4 -> 2026Q2: ./getting_started/upgrade_guide/2025Q4_2026Q2.md
  - NaaS:
    - Introduction: ./naas/introduction.md
    - Services: