Upgrade
How to run helm upgrade on this chart, and the breaking changes chart 5.0.0 brings — the booster
UI removal, the OAP 11 dashboard-template changes, and the new ui.config default.
Run the upgrade
helm upgrade skywalking oci://docker.io/apache/skywalking-helm \
--version 5.0.0 -n skywalking \
--set oap.image.tag=11.0.0 \
--set oap.storageType=banyandb \
--set ui.image.tag=horizon-1.0.0 \
--set elasticsearch.enabled=false \
--set banyandb.enabled=true \
--set banyandb.image.tag=0.11.0 \
--wait --wait-for-jobs
Three values have no defaults and must be present on every upgrade, not just the first install:
| value | example |
|---|---|
oap.image.tag |
11.0.0 |
oap.storageType |
elasticsearch, postgresql, banyandb |
ui.image.tag |
horizon-1.0.0 (only when ui.enabled is true) |
helm upgrade does not remember --set flags from the previous release, so either repeat them,
pass a values file with -f, or add --reuse-values. --wait-for-jobs alongside --wait makes
Helm report an init-Job failure directly instead of leaving you to guess why OAP never went Ready.
Chart 5.0.0 is a version set
OAP and BanyanDB are hard-coupled and must move together — that pair is the most common upgrade
failure. Horizon releases independently of OAP (1.0.0 covers both OAP 10.4.0 and 11.x), so its tag
is pinned separately, but it must be a horizon-* tag: the chart no longer supports booster UI.
| component | value | version |
|---|---|---|
| chart | --version |
5.0.0 |
| OAP | oap.image.tag |
11.0.0 |
| Horizon UI | ui.image.tag |
horizon-1.0.0 |
| BanyanDB | banyandb.image.tag |
0.11.0 |
OAP ships the BanyanDB server API versions it accepts in
SW_STORAGE_BANYANDB_COMPATIBLE_SERVER_API_VERSIONS. OAP 11.0.0 accepts API 0.11, which maps to
BanyanDB release 0.11.x. The check is an exact string match with no lenient fallback, so OAP 11
against BanyanDB 0.10.x refuses to start with Incompatible BanyanDB server API version. The
mapping is published at
BanyanDB API versions;
see also BanyanDB.
The bump from 4.9.0 to 5.0.0 is a major one because the UI image line, several values.yaml
keys and the init Job’s identity all changed incompatibly. The rest of this page is that list.
Breaking: booster UI is gone
OAP 11 deleted apm-webapp — the Armeria reverse proxy behind the skywalking/ui image — along
with the skywalking-ui git submodule and the docker.ui Maven target. The last booster image
published to apache/skywalking-ui is 10.4.0; there is no 11.x tag and there will not be one.
Only horizon-* tags are published going forward.
What to change when coming from a release that ran booster UI:
| before (4.9.0) | after (5.0.0) | |
|---|---|---|
| image tag | ui.image.tag=<oap-version> |
ui.image.tag=horizon-1.0.0 |
| container port | 8080 |
8081 (ui.service.internalPort; Service still fronts 80) |
| OAP admin port | no oap.ports.admin key at all |
oap.ports.admin: 17128, required |
| login | none — booster was unauthenticated | must be configured — no fallback |
/graphql on the UI |
proxied to OAP | not proxied; call OAP directly |
| UI env | ui.env (map); chart set SW_OAP_ADDRESS / SW_ZIPKIN_ADDRESS |
ui.extraEnv (list) and ui.envFromSecret; OAP URLs come from the horizon.yaml ConfigMap |
| Zipkin port keys | oap.ports.zipkinreceiver / zipkinquery |
oap.ports.zipkin-receiver / zipkin-query |
ui.env no longer exists — a values file that still sets it renders nothing and the BFF gets no
extra environment. The Zipkin keys were renamed too: oap-deployment.yaml reads them as
zipkin-receiver / zipkin-query, so a carried-over zipkinquery still opens a container port but
no longer sets SW_QUERY_ZIPKIN / SW_QUERY_ZIPKIN_REST_PORT, and the UI’s oap.zipkinUrl is not
derived.
Configure logins before you cut over. Horizon has no built-in admin/admin, and the BFF does
not fail closed: with no users it boots, logs an error, serves the login page, and answers
/api/auth/health with 200 — which is the chart’s own readiness probe. The pod goes Ready and
nobody can sign in. See Set Up Logins.
Expose the OAP admin port. OAP 11 serves /status/* and /debugging/* on the admin REST port
only, and Horizon’s BFF reads inspect, DSL debugging, runtime rules and (in the default
templates.mode: live) the dashboard template store from it. oap.ports.admin defaults to 17128;
set it to null on any OAP 10.x release — the admin server is an OAP 11 addition.
Retarget swctl and any other GraphQL caller. The BFF does not pass /graphql through to OAP,
so anything that used to query the UI must address the OAP Service:
# before
swctl --base-url=http://skywalking-skywalking-helm-ui/graphql service ls
# after — OAP directly, on oap.ports.rest
swctl --display yaml \
--base-url=http://skywalking-skywalking-helm-oap:12800/graphql \
service ls
Point it at the OAP Service on 12800; copy the form from
there if you need the in-cluster hostname pattern.
Upgrading the UI first
Horizon 1.0.0 runs against OAP 10.4.0 as well as OAP 11.x, so you can split the move in two: swap
the UI while still on OAP 10, then upgrade OAP. On OAP 10 add one setting, because OAP 10 does not
serve the /ui-management REST API Horizon reads templates from:
--set ui.config.templates.mode=readonly
That renders the templates bundled in the image and makes the configuration surface display-only.
Dashboards, traces, logs, topology, alarms and profiling all work. Remove it once OAP is on 11. The
mode is read at boot, so it needs a BFF restart — the UI Deployment’s checksum/config annotation
rolls the pod for you whenever the ConfigMap changes.
Breaking: OAP 11 removed the UI template seeds
These OAP-side surfaces went with the bundled UI. If your values still set them, they are read by nothing — delete them:
| removed | where it used to live |
|---|---|
ui-initialized-templates |
a key under oap.config, seeding on-disk dashboard JSON |
SW_ENABLE_UPDATE_UI_TEMPLATE |
an env var under oap.env |
| sidebar menu storage | OAP storage |
UIConfigurationManagement GraphQL queries and mutations |
OAP query API |
The on-disk dashboard seed files were deleted along with UITemplateInitializer. Horizon ships its
own dashboard library and manages templates over the admin REST port instead — that is what
oap.ports.admin and ui.config.templates.mode are for.
Breaking: ui.config is empty by default
The interim Horizon work on main mounted a ConfigMap of literal values over /app/horizon.yaml.
As of 5.0.0 ui.config defaults to {} and the ConfigMap carries only the fields the chart has to
compute:
| field | derived from |
|---|---|
oap.queryUrl |
the in-cluster OAP Service and oap.ports.rest |
oap.adminUrl |
the in-cluster OAP Service and oap.ports.admin |
oap.zipkinUrl |
the OAP Service and oap.ports.zipkin-query, only when that port is set |
server.publicUrl |
the first ui.ingress.hosts entry, only when ui.ingress.enabled and ui.ingress.hosts are both set (https when ui.ingress.tls is non-empty) |
server.port |
ui.service.internalPort, so the BFF binds the port the container exposes |
The four URLs are written as ${VAR:default} tokens, not literals, so the in-cluster value is
only the default and the matching HORIZON_* variable still wins. server.port is the deliberate
exception — the chart writes it as a plain number, because the container port and both probes are
derived from ui.service.internalPort and the BFF has to bind that same port.
This matters because Horizon expands ${...} over the raw text of the config file before parsing
it. A field written as a literal makes its HORIZON_* environment variable silently inert, and a
field the file omits falls back to a schema default that consults the environment for only a
fraction of the image’s variables. A config file full of literals therefore does not merely
duplicate defaults — it disables most of the image’s configuration surface.
If you are carrying a full ui.config block forward — from the pre-release main values, not
from 4.x, which had no ui.config at all — drop every field that only restates what the image
already sets (server.host, oap.timeoutMs, auth.backend, rbac.enabled, session.* and
templates.mode all did), and move the rest to ui.extraEnv or ui.envFromSecret:
| config field | how to set it now |
|---|---|
templates.mode |
HORIZON_TEMPLATES_MODE — works as a bare env var |
session.cookieSecure |
keep in ui.config, optionally as ${HORIZON_SESSION_COOKIE_SECURE:false} |
server.trustProxy |
keep in ui.config, optionally as ${HORIZON_TRUST_PROXY:false} |
auth.local.users |
keep in ui.config as ${HORIZON_AUTH_LOCAL_USERS:[]} + ui.envFromSecret |
oap.auth |
keep in ui.config as ${HORIZON_OAP_AUTH:null} + ui.envFromSecret |
Only the first row works from a bare environment variable. The other four have literal schema
defaults, so their HORIZON_* variables are reachable only through a ${...} token in the
mounted file — set the variable without the token and nothing happens, with no error. See
Configure Horizon.
ui.config is still there for pinning a field regardless of the environment, and ${VAR} tokens
you write in it do expand — that is how the Secret pattern works. See
Configure Horizon.
The init Job re-runs on every upgrade that changes a value
The storage schema is created by a one-shot *-oap-init-* Job that runs OAP with -Dmode=init; the
main Deployment runs -Dmode=no-init and blocks until the schema exists. The Job name carries a
sha256 of the chart values, so any helm upgrade that changes a value produces a new Job name and
re-runs init automatically, with Helm pruning the previous one. An upgrade that changes nothing
reuses the existing Job.
Before 5.0.0 this Job was a post-install,post-upgrade,post-rollback Helm hook with a fixed name —
the OAP Service name plus -init, e.g. skywalking-skywalking-helm-oap-init. Helm does not own
hook resources, so an upgrade from 4.9.0 leaves that completed Job behind in the namespace. It is
inert; delete it by hand.
To force a rerun without changing a value, delete the Job and upgrade again:
kubectl delete job -n skywalking -l release=skywalking
helm upgrade skywalking oci://docker.io/apache/skywalking-helm \
--version 5.0.0 -n skywalking --reuse-values
More detail in The OAP Init Job.
Rolling back
helm rollback restores the previous release’s manifests, so image tags and configuration revert.
It does not revert anything the init Job wrote to storage — the chart has no downgrade path for
the storage schema. Before an OAP major upgrade, make sure the storage backend is one you can
restore independently.
If the UI comes back Ready but unusable after an upgrade, start at UI and Login Problems; if OAP or the init Job fails, see Install and Startup Failures.