Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions .github/workflows/e2e.ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,9 @@ jobs:
- name: Horizon + OAP 11 + BanyanDB (cluster)
config: test/e2e/e2e-oap11-banyandb-cluster.yaml
slug: oap11-banyandb-cluster
- name: Horizon + OAP 10.4 + Elasticsearch
config: test/e2e/e2e-oap10-elasticsearch.yaml
slug: oap10-elasticsearch
- name: Horizon + OAP 10.4 + BanyanDB 0.10
config: test/e2e/e2e-oap10-banyandb.yaml
slug: oap10-banyandb
- name: Config override via ConfigMap (OAP + Horizon)
config: test/e2e/e2e-config-override.yaml
slug: config-override
name: ${{ matrix.test.name }}
steps:
- uses: actions/checkout@v2
Expand Down
6 changes: 3 additions & 3 deletions chart/skywalking/templates/NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ it exposed points Horizon at the wrong service.
Full horizon.yaml config reference:
https://github.com/apache/skywalking-horizon-ui/blob/main/docs/setup/horizon-yaml.md

Horizon 1.0.0 ships its commented example AS the shipped config — the image's
/app/horizon.yaml is fully env-tokenized. This chart replaces that file with
the ConfigMap rendered from `ui.config`.
Horizon is configured by environment variable: the image's /app/horizon.yaml is
fully env-tokenized, and this chart mounts nothing over it unless you set
`ui.config`. Use `ui.extraEnv` and `ui.envFromSecret`.
{{- end }}

8 changes: 8 additions & 0 deletions chart/skywalking/templates/oap-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,14 @@ spec:
- name: {{ $key }}
value: {{ $value | quote }}
{{- end }}
{{- range .Values.oap.extraEnv }}
- {{ toYaml . | nindent 10 | trim }}
{{- end }}
{{- if .Values.oap.envFromSecret }}
envFrom:
- secretRef:
name: {{ .Values.oap.envFromSecret | quote }}
{{- end }}

volumeMounts:
{{- include "skywalking.oap.volumeMounts" . | nindent 8 }}
Expand Down
8 changes: 8 additions & 0 deletions chart/skywalking/templates/oap-init.job.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,14 @@ spec:
- name: {{ $key }}
value: {{ $value | quote }}
{{- end }}
{{- range .Values.oap.extraEnv }}
- {{ toYaml . | nindent 10 | trim }}
{{- end }}
{{- if .Values.oap.envFromSecret }}
envFrom:
- secretRef:
name: {{ .Values.oap.envFromSecret | quote }}
{{- end }}

volumeMounts:
{{- include "skywalking.oap.volumeMounts" . | nindent 8 }}
Expand Down
9 changes: 7 additions & 2 deletions chart/skywalking/templates/ui-configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

{{- if .Values.ui.enabled }}
{{- if and .Values.ui.enabled .Values.ui.config }}
{{- /*
horizon.yaml is built by deep-merging chart-computed values with `ui.config`.

Expand Down Expand Up @@ -67,7 +67,12 @@ default/wildcard certificate, so it covers this host too. */ -}}
{{- end }}
{{- $_ := set $serverDefaults "publicUrl" (printf "${HORIZON_PUBLIC_URL:%s://%s}" $scheme $entry) }}
{{- end }}
{{- $defaults := dict "oap" $oapDefaults "server" $serverDefaults }}
{{- /* Mounting this file replaces the image's, so any token it does not carry
is lost and the matching HORIZON_* variable goes inert. Users are the one field
where that is silently fatal -- the pod still reports Ready -- so the token is
preserved here unless the operator writes users of their own. */ -}}
{{- $authDefaults := dict "local" (dict "users" "${HORIZON_AUTH_LOCAL_USERS:[]}") }}
{{- $defaults := dict "oap" $oapDefaults "server" $serverDefaults "auth" $authDefaults }}
{{- $userConfig := default (dict) .Values.ui.config }}
{{- $merged := mergeOverwrite (deepCopy $defaults) (deepCopy $userConfig) }}
apiVersion: v1
Expand Down
45 changes: 40 additions & 5 deletions chart/skywalking/templates/ui-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,11 @@ spec:
component: "{{ .Values.ui.name }}"
release: {{ .Release.Name }}
annotations:
# Roll the pod when horizon.yaml changes — ConfigMap subPath mounts
# don't auto-update at runtime.
{{- if .Values.ui.config }}
# A subPath mount never updates in place, so roll the pod when the
# rendered horizon.yaml changes.
checksum/config: {{ include (print $.Template.BasePath "/ui-configmap.yaml") . | sha256sum }}
{{- end }}
{{- with .Values.ui.podAnnotations }}
{{ toYaml . | indent 8 }}
{{- end }}
Expand Down Expand Up @@ -91,34 +93,67 @@ spec:
readinessProbe:
{{ toYaml .Values.ui.readinessProbe | indent 10 }}
{{- end }}
{{- if or .Values.ui.envFromSecret .Values.ui.extraEnv }}
{{- $oap := include "skywalking.oap.fullname" . }}
env:
# Horizon's image ships a fully env-tokenized /app/horizon.yaml, so the
# chart supplies only what it can compute and leaves every other field to
# the image's own defaults -- which keeps all of them settable through
# ui.extraEnv / ui.envFromSecret. Mounting a file here instead would
# replace that file and silently make those variables inert.
- name: HORIZON_SERVER_PORT
value: {{ .Values.ui.service.internalPort | quote }}
- name: HORIZON_OAP_QUERY_URL
value: "http://{{ $oap }}:{{ .Values.oap.ports.rest }}"
{{- if .Values.oap.ports.admin }}
- name: HORIZON_OAP_ADMIN_URL
value: "http://{{ $oap }}:{{ .Values.oap.ports.admin }}"
{{- end }}
{{- $zipkin := index .Values.oap.ports "zipkin-query" }}
{{- if $zipkin }}
- name: HORIZON_OAP_ZIPKIN_URL
value: "http://{{ $oap }}:{{ $zipkin }}/zipkin"
{{- end }}
{{- if and .Values.ui.ingress.enabled .Values.ui.ingress.hosts }}
{{- $entry := first .Values.ui.ingress.hosts }}
{{- $host := first (splitList "/" $entry) }}
{{- $scheme := "http" }}
{{- range .Values.ui.ingress.tls }}
{{- if or (empty (.hosts | default list)) (has $host (.hosts | default list)) }}{{ $scheme = "https" }}{{ end }}
{{- end }}
# SSO callbacks and the OAuth issuer are built from this; derived per
# host, since a tls block may cover only some of them.
- name: HORIZON_PUBLIC_URL
value: "{{ $scheme }}://{{ $entry }}"
{{- end }}
{{- range .Values.ui.extraEnv }}
- {{ toYaml . | nindent 10 | trim }}
{{- end }}
{{- end }}
{{- if .Values.ui.envFromSecret }}
envFrom:
- secretRef:
name: {{ .Values.ui.envFromSecret }}
name: {{ .Values.ui.envFromSecret | quote }}
{{- end }}
volumeMounts:
{{- if .Values.ui.config }}
- name: horizon-config
mountPath: /app/horizon.yaml
subPath: horizon.yaml
readOnly: true
{{- end }}
- name: horizon-data
mountPath: /data
{{- with .Values.ui.extraVolumeMounts }}
{{ toYaml . | indent 8 }}
{{- end }}
volumes:
{{- if .Values.ui.config }}
- name: horizon-config
configMap:
name: {{ template "skywalking.ui.fullname" . }}
items:
- key: horizon.yaml
path: horizon.yaml
{{- end }}
- name: horizon-data
{{- if .Values.ui.persistence.enabled }}
persistentVolumeClaim:
Expand Down
97 changes: 58 additions & 39 deletions chart/skywalking/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,42 @@ oap:
# image: my/query-proxy:1.0.0
# ports:
# - { name: http, containerPort: 8080 }
# OAP can be configured three ways, the same as the UI below:
#
# 1. `oap.env` / `oap.extraEnv` -- environment variables. `env` is a plain
# map; `extraEnv` is a list, so it can carry `valueFrom` for a single
# value out of a Secret or the downward API.
# 2. `oap.envFromSecret` -- every key of a Secret as an env var. Note
# Kubernetes gives an explicit `env` entry precedence over `envFrom`, and
# the chart sets SW_ES_PASSWORD / SW_DATA_SOURCE_PASSWORD itself from the
# storage values -- so to source those from a Secret use `extraEnv`
# (below), which lands in `env` and wins. `envFromSecret` suits variables
# the chart does not set.
# 3. `oap.config` -- files rendered into a ConfigMap and
# mounted at /skywalking/config. Unlike Horizon, OAP reads real files for
# things like log4j2.xml and the OAL/MAL rules, so this is the only way to
# supply those.
env: # more env, please refer to https://hub.docker.com/r/apache/skywalking-oap-server

# or https://github.com/apache/skywalking-docker/blob/master/6/6.4/oap/README.md#sw_telemetry

# A list, so entries may use valueFrom. Use it where `oap.env` cannot reach --
# a single credential from a Secret, or a value from the downward API. This is
# also the only way to override a variable the chart sets itself, since these
# land in `env` and an explicit `env` entry beats `envFrom`:
#
# extraEnv:
# - name: SW_DATA_SOURCE_PASSWORD
# valueFrom:
# secretKeyRef:
# name: oap-postgres
# key: password
extraEnv: []
# Every key of a pre-created Secret becomes an env var in the OAP container
# (and in the init Job, which needs the same storage credentials).
# envFromSecret: oap-secrets
envFromSecret: ""

# Allows you to add any config files in /skywalking/config
# such as log4j2.xml, oal/core.oal, etc.
config: {}
Expand Down Expand Up @@ -224,9 +256,10 @@ ui:
# defaults to 101 (alpine's typical `nobody` GID).
securityContext:
fsGroup: 101
# Persistent state directory used by the BFF for audit log, setup state,
# alarm state, and wire debug log. Without persistence these files land in
# the container's writable layer and are lost on pod restart.
# Persistent state directory (/data). Horizon 1.0.0 writes the wire debug log
# there when debugLog is enabled; the login audit is not file-backed at all,
# its only backend is Postgres. Without persistence anything written there
# lands in the container's writable layer and is lost on restart.
persistence:
enabled: false
# existingClaim: ""
Expand All @@ -253,51 +286,37 @@ ui:
initialDelaySeconds: 10
periodSeconds: 10
failureThreshold: 6
# Extra `horizon.yaml` content, deep-merged over the values the chart computes
# (the in-cluster OAP URLs, the ingress-derived publicUrl, and the BFF port).
# Schema reference:
# https://github.com/apache/skywalking-horizon-ui/blob/main/docs/setup/horizon-yaml.md
# Horizon can be configured three ways. The image ships a complete
# /app/horizon.yaml in which every field is a `${HORIZON_*:default}`
# placeholder, so the first two need no file at all:
#
# EMPTY BY DESIGN. Horizon's image ships a fully env-tokenized
# /app/horizon.yaml, and the chart's ConfigMap replaces it -- so every field
# written here as a literal makes its `HORIZON_*` env var inert. Prefer
# `ui.extraEnv` / `ui.envFromSecret` for anything the chart does not compute,
# and set a field here only when you want to pin it regardless of env.
# 1. `ui.extraEnv` -- plain values, one env var per field
# 2. `ui.envFromSecret` -- the same, from a Secret, for anything sensitive
# 3. `ui.config` -- a horizon.yaml rendered into a ConfigMap and
# mounted over the image's copy
#
# Some examples, with the env var that does the same job:
# Prefer 1 and 2. Structured settings take JSON in a single variable, so a
# Secret covers even the nested ones:
#
# Only fields whose built-in default reads the environment can be set by a
# bare env var -- templates.mode, server.*, ai.*, mcp.*, oauth.*, audit.enabled
# among them:
# HORIZON_AUTH_LOCAL_USERS=[{"username":"admin","passwordHash":"$argon2id$...","roles":["admin"]}]
# HORIZON_AUTH_LDAP={"url":"ldaps://...","userBaseDn":"..."}
# HORIZON_RBAC_ROLES={...}
#
# templates.mode HORIZON_TEMPLATES_MODE `readonly` on OAP 10.x
# (with oap.ports.admin: null)
# `ui.config` is for pinning a field regardless of the environment. Setting it
# mounts a file over the image's, which REPLACES that file: any field you do
# not write falls back to Horizon's built-in default, and its `HORIZON_*`
# variable stops working unless you write the token yourself
# (`cookieSecure: ${HORIZON_SESSION_COOKIE_SECURE:false}`). The chart's own
# computed values are merged in as tokens, so OAP stays reachable either way.
# Left empty, no ConfigMap is created and nothing is mounted.
#
# Everything else has a literal default, so its HORIZON_* var is reachable ONLY
# through a `${...}` token written here. Setting the var alone does nothing:
#
# session:
# cookieSecure: ${HORIZON_SESSION_COOKIE_SECURE:false}
# server:
# trustProxy: ${HORIZON_TRUST_PROXY:false}
# oap:
# auth: ${HORIZON_OAP_AUTH:null}
# Field reference:
# https://github.com/apache/skywalking-horizon-ui/blob/main/docs/setup/horizon-yaml.md
#
# NO LOGIN IS CONFIGURED BY DEFAULT, and the BFF does not refuse to start
# without one -- it boots, logs an error, serves the login page, and answers
# the readiness probe with 200, so the pod goes Ready and nobody can log in.
# Supply users before you rely on the deployment. auth.local.users has a
# literal default, so HORIZON_AUTH_LOCAL_USERS in a Secret does NOTHING on its
# own -- the token has to be written here for the variable to reach it. Put the
# token in `config` and the value in a Secret named by `ui.envFromSecret`:
#
# config:
# auth:
# local:
# users:
# - username: admin
# passwordHash: "${HORIZON_ADMIN_HASH}"
# roles: [admin]
# Set HORIZON_AUTH_LOCAL_USERS before you rely on the deployment.
config: {}
# Optional: pass extra env vars into the BFF container. Use this to
# provide values referenced by `${VAR}` interpolation in `config`
Expand Down
4 changes: 0 additions & 4 deletions docs/contributing/e2e-tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ each of those pairings needs.
| `test/e2e/e2e-oap11-elasticsearch.yaml` | `$OAP_REPO:$OAP_TAG` (11.0.0) | `oap.storageType=elasticsearch` against the ECK subchart, left on by the chart's `elasticsearch.enabled: true` | Pre-installs the ECK CRDs out of `chart/skywalking/charts/eck-operator-3.3.1.tgz` and passes `eck-operator.installCRDs=false`. |
| `test/e2e/e2e-oap11-banyandb-standalone.yaml` | 11.0.0 | BanyanDB 0.11 (`$BANYANDB_REPO:$BANYANDB_TAG`) | `oap.storageType=banyandb`, `elasticsearch.enabled=false`, `banyandb.enabled=true`, `banyandb.standalone.enabled=true`, `banyandb.cluster.enabled=false`, `banyandb.auth.enabled=true`. |
| `test/e2e/e2e-oap11-banyandb-cluster.yaml` | 11.0.0 | BanyanDB 0.11, cluster mode | As above but `banyandb.standalone.enabled=false`, `banyandb.cluster.enabled=true`. |
| `test/e2e/e2e-oap10-elasticsearch.yaml` | `$OAP_10_REPO:$OAP_10_TAG` (10.4.0) | ECK Elasticsearch, with the same CRD pre-install and `eck-operator.installCRDs=false` as the cell above | `oap.ports.admin=null`, `ui.config.templates.mode=readonly`. |
| `test/e2e/e2e-oap10-banyandb.yaml` | 10.4.0 | BanyanDB 0.10.3 (`$BANYANDB_0_10_REPO:$BANYANDB_0_10_TAG`), standalone with auth | `oap.ports.admin=null`, `ui.config.templates.mode=readonly`. |

The three OAP 11 cells also switch Zipkin on — `oap.ports.zipkin-query=9412` plus
`SW_RECEIVER_ZIPKIN=default` and `SW_QUERY_ZIPKIN=default` — because the chart only emits
Expand Down Expand Up @@ -191,8 +189,6 @@ versions under test are pinned.
| `UI_REPO` / `UI_TAG` | `docker.io/apache/skywalking-ui` : `horizon-1.0.0` | Yes. Dev images live on GHCR (`apache/skywalking-horizon-ui`) if CI needs an unreleased fix. |
| `BANYANDB_REPO` / `BANYANDB_TAG` | `ghcr.io/apache/skywalking-banyandb` at commit `3b83e18…` | Yes. A GHCR commit pin rather than `docker.io/apache/skywalking-banyandb:0.11.0` **on purpose**: that commit *is* the v0.11.0 tag, and naming it pins the exact source under test instead of a tag that can be re-pushed. The release image is published; user-facing install docs quote it. |
| `SATELLITE_REPO` / `SATELLITE_TAG` | `ghcr.io/apache/skywalking-satellite/skywalking-satellite` at a commit tag | Yes. |
| `OAP_10_REPO` / `OAP_10_TAG` | `docker.io/apache/skywalking-oap-server` : `10.4.0` | **No — frozen.** 10.4.0 is the last v10 release. |
| `BANYANDB_0_10_REPO` / `BANYANDB_0_10_TAG` | `docker.io/apache/skywalking-banyandb` : `0.10.3` | **No — frozen.** OAP 10.4.0 pins `compatibleServerApiVersions` to BanyanDB API 0.10, so this pair never moves again. |

The OAP 11 line moves as a trio: OAP 11.0.0 accepts BanyanDB server API 0.11 only, and Horizon 1.0.0
is the UI tested against it — see [Version Compatibility](../evaluate/version-compatibility.md).
Expand Down
2 changes: 1 addition & 1 deletion docs/evaluate/version-compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Which OAP, UI and storage versions go together for chart **5.0.0**. Only two pai

## The tested set

This is the combination the three OAP 11 cells in `test/e2e/` install on every CI run, so it is the set the chart is best known to work with. The other two cells hold the OAP 10.4 line described further down.
This is the combination every cell in `test/e2e/` installs on each CI run, so it is the set the chart is best known to work with. The OAP 10.4 line described further down is documented but **not** covered by CI.

| Component | Version | Where you set it |
|---|---|---|
Expand Down
2 changes: 1 addition & 1 deletion docs/evaluate/what-this-chart-deploys.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ With everything else left at its default (`elasticsearch.enabled=true`), that re
| Service | `skywalking-skywalking-helm-oap` | ClusterIP; ports `11800`, `12800`, `17128` |
| Deployment | `skywalking-skywalking-helm-ui` | `ui.replicas: 1`, `strategy: Recreate` |
| Service | `skywalking-skywalking-helm-ui` | ClusterIP, `80` → container `8081` |
| ConfigMap | `skywalking-skywalking-helm-ui` | the `horizon.yaml` mounted at `/app/horizon.yaml` |
| ConfigMap | `skywalking-skywalking-helm-ui` | only when `ui.config` is set — the rendered `horizon.yaml`, mounted over the image's |
| ServiceAccount | `skywalking-skywalking-helm-oap` | used by both the OAP Deployment and the init Job |
| Role + RoleBinding | `skywalking-skywalking-helm` | `get/watch/list` on pods, configmaps |
| ClusterRole + ClusterRoleBinding | `skywalking-skywalking-helm` | `get/watch/list` on pods, pods/log, endpoints, services, nodes, namespaces, configmaps, deployments, replicasets, Istio `serviceentries` |
Expand Down
16 changes: 9 additions & 7 deletions docs/expose/tls.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,15 @@ ui:
cookieSecure: true
```

**Set it in `ui.config`, not as an env var.** The `HORIZON_SESSION_COOKIE_SECURE`
environment variable is inert under this chart. The chart mounts its own generated
`horizon.yaml` over `/app/horizon.yaml`, and that file omits the `session:` block
entirely. Horizon expands `${...}` over the raw *text* of the config file, so with no
`session:` block there is no token to expand and the schema default (`false`) wins —
`ui.extraEnv` will not change it. This is the general rule for the chart's ConfigMap and
is covered in [Configure Horizon](../ui/configure.md).
Set `HORIZON_SESSION_COOKIE_SECURE=true` whenever the UI is served over HTTPS — browsers refuse a
`Secure` cookie over plain HTTP, so without it the session cookie travels in the clear:

```yaml
ui:
extraEnv:
- name: HORIZON_SESSION_COOKIE_SECURE
value: "true"
```

If you still want the value overridable by env — for example to keep one values file for
both an HTTP dev cluster and an HTTPS production one — write the token yourself, quoted so
Expand Down
Loading
Loading