Skip to content

Commit a4566ba

Browse files
committed
Update docs for v2.1.0
1 parent 67753e7 commit a4566ba

File tree

16 files changed

+166
-100
lines changed

16 files changed

+166
-100
lines changed

README.md

Lines changed: 43 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@
22

33
Easily run ShinyProxy on a Kubernetes cluster
44

5-
**(c) Copyright Open Analytics NV, 2020-2023 - Apache License 2.0**
5+
**(c) Copyright Open Analytics NV, 2020-2024 - Apache License 2.0**
66

77
## Why?
88

99
Deploying and managing ShinyProxy can get complex when many apps are used,
1010
especially when the configuration of ShinyProxy is often updated.
1111

12-
When restarting a running ShinyProxy instance (in order to update its configuration),
13-
users will face a disconnect from their running applications. The only solution
14-
to guarantee that users do not lose their connection to running apps, is to keep
15-
the current instance alive when updating ShinyProxy's configuration. However,
16-
manually keeping track of these instances would be too cumbersome and should
17-
therefore be automated.
12+
When restarting a running ShinyProxy instance (in order to update its
13+
configuration), users will face a disconnect from their running applications.
14+
The only solution to guarantee that users do not lose their connection to
15+
running apps, is to keep the current instance alive when updating ShinyProxy's
16+
configuration. However, manually keeping track of these instances would be too
17+
cumbersome and should therefore be automated.
1818

1919
The ShinyProxy operator for Kubernetes is able to manage multiple ShinyProxy
2020
instances and their configuration.
@@ -88,13 +88,13 @@ start with the `SPO` prefix, meaning **S**hiny**P**roxy**O**perator.
8888
probe. By default, this is 60 seconds.
8989
- `SPO_LOG_LEVEL`: configures the log level of the operator, may be one of the
9090
following:
91-
- `OFF`: disables logging
92-
- `ERROR`
93-
- `WARN`
94-
- `INFO`
95-
- `DEBUG`: default (may change)
96-
- `TRACE`
97-
- `ALL`: enables all logging
91+
- `OFF`: disables logging
92+
- `ERROR`
93+
- `WARN`
94+
- `INFO`
95+
- `DEBUG`: default (may change)
96+
- `TRACE`
97+
- `ALL`: enables all logging
9898

9999
Note: in our deployments where startup probes aren't supported we have success
100100
with the following configuration:
@@ -113,20 +113,23 @@ ShinyProxy and the operator for the best experience.
113113

114114
| ShinyProxy Version | Minimum operator version | Maximum operator version (inclusive) |
115115
|--------------------|----------------------------------|--------------------------------------|
116-
| 3.0.0 | 2.0.0 | TBD |
116+
| 3.1.0 | 2.1.0 | TBD |
117+
| 3.0.0 | 2.0.0 | TBD (works with 2.1.0) |
117118
| 2.6.0 | 1.0.0 | 1.1.0 |
118119
| 2.5.0 | `0.0.1-SNAPSHOT-20210302.095930` | `0.0.1-SNAPSHOT-20210607.070151` |
119120
| 2.4.3 | `0.0.1-SNAPSHOT-20201215.112635` | `0.0.1-SNAPSHOT-20201215.112635` |
120121

121122
## Kubernetes versions
122123

123-
| | k8s 1.25.x | k8s 1.24.x | k8s 1.23.x | k8s 1.22.x | k8s >= v1.21.3 | k8s <= v1.21.2 | k8s >= 1.20.10 | k8s <= v1.20.9 | v1.19 | <= v1.18 |
124-
|-------|------------|------------|-------------|------------|----------------|----------------|----------------|----------------|-------|----------|
125-
| 2.0.0 |||||| ✓¹ || ✓¹ || - |
124+
| | k8s 1.29.x | k8s 1.28.x | k8s 1.27.x | k8s 1.26.x | k8s 1.25.x | k8s 1.24.x | k8s 1.23.x | k8s 1.22.x | k8s >= v1.21.3 | k8s <= v1.21.2 | k8s >= 1.20.10 | k8s <= v1.20.9 | v1.19 | <= v1.18 |
125+
|-------|------------|------------|------------|------------|------------|------------|------------|------------|----------------|----------------|----------------|----------------|-------|----------|
126+
| 2.1.0 |||||||||| ✓¹ || ✓¹ || - |
127+
| 2.0.0 | ✓² | ✓² | ✓² | ✓² | ✓² | ✓² |||| ✓¹ || ✓¹ || - |
126128

127129
**Note:**
128130

129131
- ¹ requires a workaround, see below.
132+
- ² version 2.0.0 supports these Kubernetes versions, but might stop syncing after some time, this issue is solved in version 2.1.0
130133

131134
### Workaround for bug in Kubernetes
132135

@@ -153,18 +156,18 @@ Be aware of these changes when updating to version 2.0.0:
153156
started, all new requests will be handled by the new server, including
154157
requests for existing apps. Only existing websocket connections will stay open
155158
on the old servers. This has multiple benefits:
156-
- when a new server is started, users will immediately use and see the
157-
configuration of that new server. In other words, if a new configuration
158-
includes a new app, this app is immediately available to all users (even if
159-
they are using apps started on older servers)
160-
- there is no longer a process of transferring users to new servers. Both the
161-
forced method and the manual method (where users have to click a button) are
162-
removed. Users will immediately use the new configuration.
163-
- apps can be run for a (very) long time, even if frequently updating the
164-
configuration and without having many old servers. Old servers are removed
165-
as soon as no websocket connections are running on that server.
166-
- Skipper is no longer a dependency of the operator. There is no benefit in
167-
using with version two of the operator.
159+
- when a new server is started, users will immediately use and see the
160+
configuration of that new server. In other words, if a new configuration
161+
includes a new app, this app is immediately available to all users (even
162+
if they are using apps started on older servers)
163+
- there is no longer a process of transferring users to new servers. Both
164+
the forced method and the manual method (where users have to click a
165+
button) are removed. Users will immediately use the new configuration.
166+
- apps can be run for a (very) long time, even if frequently updating the
167+
configuration and without having many old servers. Old servers are removed
168+
as soon as no websocket connections are running on that server.
169+
- Skipper is no longer a dependency of the operator. There is no benefit in
170+
using with version two of the operator.
168171
- the operator now requires ShinyProxy to store the active proxies in Redis.
169172
Therefore, since this release Redis takes a more critical role. When running
170173
Redis inside Kubernetes, it is therefore best practice to use Redis Sentinel.
@@ -182,8 +185,16 @@ need to be made to the ShinyProxy configuration file:
182185
- optionally add the
183186
property [`kubernetesIngressPatches`](docs/deployment#modify-the-ingress-resource)
184187
in order to customize the ingress created by the operator.
185-
- update the ShinyProxy image to `openanalytics/shinyproxy:3.0.1`
188+
- update the ShinyProxy image to `openanalytics/shinyproxy:3.1.0`
189+
190+
### Update to 2.1.0
191+
192+
The [ShinyProxy CRD](docs/deployment/bases/namespaced/crds/shinyproxy.crd.yaml)
193+
has been updated in version 2.1.0, it is important to update the CRD in your
194+
cluster. Running the [deployment commands](docs/deployment/) is enough. The CRD
195+
can be updated while ShinyProxy and the ShinyProxy operator are running in the
196+
cluster.
186197

187198
## Java Version
188199

189-
This project requires JDK 11.
200+
This project requires JDK 17.

docs/deployment/README.md

Lines changed: 103 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ and dependencies of the operator.
1313
servers.
1414
- **ShinyProxy**: the ShinyProxy servers, these host the Shiny apps. You do not
1515
need to create these servers manually, since these are created by the
16-
operator. Instead, you define which servers to create, and the operator creates
17-
all necessary Kubernetes resources, without affecting any existing server or
18-
causing downtime.
16+
operator. Instead, you define which servers to create, and the operator
17+
creates all necessary Kubernetes resources, without affecting any existing
18+
server or causing downtime.
1919
- **Redis**: Redis is used by ShinyProxy (not by the operator) to implement
2020
[session and app persistence](https://shinyproxy.io/documentation/configuration/#session-and-app-persistence).
2121
This ensures that when a ShinyProxy server is replaced, the user is still
@@ -26,8 +26,8 @@ and dependencies of the operator.
2626
server provided by cloud providers.
2727

2828
**Note:** when deploying to production, it is important to change the password
29-
used to secure Redis. Each example (see below) already changes the
30-
password to `mySecurePassword12`. For an example see
29+
used to secure Redis. Each example (see below) already changes the password
30+
to `mySecurePassword12`. For an example see
3131
the [`overlays/1-namespaced/patches/redis.secret.yaml`](overlays/1-namespaced/patches/redis.secret.yaml)
3232
file.
3333

@@ -82,7 +82,8 @@ ShinyProxy operator on minikube.
8282
minikube ip
8383
```
8484
85-
Next, add the following entries to `/etc/hosts`, replacing `MINIKUBE_IP` by the output of the previous command;
85+
Next, add the following entries to `/etc/hosts`, replacing `MINIKUBE_IP` by
86+
the output of the previous command;
8687
8788
```text
8889
MINIKUBE_IP shinyproxy-demo.local
@@ -114,22 +115,23 @@ ShinyProxy operator on minikube.
114115
title: ShinyProxy 2 # <- MAKE THE CHANGE HERE
115116
# ...
116117
replicas: 2 # <- ADD THIS LINE
117-
image: openanalytics/shinyproxy:3.0.1
118+
image: openanalytics/shinyproxy:3.1.0
118119
imagePullPolicy: Always
119120
fqdn: shinyproxy-demo.local
120121
```
121122
10. Apply this change using `kubectl`:
122123
123-
```bash
124-
kubectl apply -f resources/shinyproxy.shinyproxy.yaml
125-
```
124+
```bash
125+
kubectl apply -f resources/shinyproxy.shinyproxy.yaml
126+
```
127+
128+
The operator now deploys a new ShinyProxy instance. The old instance will be
129+
kept intact as long as a Websocket connection is active on the old instance. The
130+
old instance will automatically be removed once it no longer has any open
131+
Websocket connections. New requests will immediately be handled by the new
132+
server as soon as it is ready. Try going to the main page of ShinyProxy and
133+
check whether the change your made has been applied.
126134
127-
The operator now deploys a new ShinyProxy instance. The old instance will be
128-
kept intact as long as a Websocket connection is active on the old instance.
129-
The old instance will automatically be removed once it no longer has any open
130-
Websocket connections. New requests will immediately be handled by the new
131-
server as soon as it is ready. Try going to the main page of ShinyProxy and
132-
check whether the change your made has been applied.
133135
11. Try the other examples. The following commands first remove the current
134136
example, next you can open another example (e.g. `2-clustered`) and deploy
135137
it using `kubectl`:
@@ -150,37 +152,37 @@ The Operator is designed to be flexible and fit many type of deployments. This
150152
repository includes examples for many kinds of deployments:
151153
152154
- *1-namespaced*:
153-
- Operator-mode: `namespaced`
154-
- Operator-namespace: `shinyproxy`
155-
- Redis-namespace: `shinyproxy`
156-
- ShinyProxy-namespace: `shinyproxy`
157-
- URLs: `https://shinyproxy-demo.local`
155+
- Operator-mode: `namespaced`
156+
- Operator-namespace: `shinyproxy`
157+
- Redis-namespace: `shinyproxy`
158+
- ShinyProxy-namespace: `shinyproxy`
159+
- URLs: `https://shinyproxy-demo.local`
158160
159161
This is a very simple deployment of the operator, where everything runs in the
160162
same namespace.
161163
162164
- *2-clustered*:
163-
- Operator-mode: `clustered`
164-
- Operator-namespace: `shinyproxy-operator`
165-
- Redis-namespace: `redis`
166-
- ShinyProxy-namespace: `shinyproxy` and `shinyproxy-dept2`
167-
- URLs:
168-
- `https://shinyproxy-demo.local`
169-
- `https://shinyproxy-demo2.local`
165+
- Operator-mode: `clustered`
166+
- Operator-namespace: `shinyproxy-operator`
167+
- Redis-namespace: `redis`
168+
- ShinyProxy-namespace: `shinyproxy` and `shinyproxy-dept2`
169+
- URLs:
170+
- `https://shinyproxy-demo.local`
171+
- `https://shinyproxy-demo2.local`
170172
171173
In this example, the operator runs in `clustered` mode. Therefore, the
172174
operator will look into all namespaces for `ShinyProxy` resources and deploy
173-
these resources in their respective namespace. This example also demonstrates how
174-
the Operator can be used in a multi-tenancy or multi-realm way. Each
175+
these resources in their respective namespace. This example also demonstrates
176+
how the Operator can be used in a multi-tenancy or multi-realm way. Each
175177
ShinyProxy server runs in its own namespace, isolated from the other servers.
176178
However, they are managed by a single operator.
177179
178180
- *3-namespaced-app-ns*:
179-
- Operator-mode: `namespaced`
180-
- Operator-namespace: `shinyproxy`
181-
- Redis-namespace: `shinyproxy`
182-
- ShinyProxy-namespace: `shinyproxy`
183-
- URLs: `https://shinyproxy-demo.local`
181+
- Operator-mode: `namespaced`
182+
- Operator-namespace: `shinyproxy`
183+
- Redis-namespace: `shinyproxy`
184+
- ShinyProxy-namespace: `shinyproxy`
185+
- URLs: `https://shinyproxy-demo.local`
184186
185187
Similar to example 1, however, the `01_hello` app will now run in the
186188
`my-namespace` namespace instead of the `shinyproxy` namespace. In addition to
@@ -189,14 +191,14 @@ repository includes examples for many kinds of deployments:
189191
the `ServiceAccount` of the ShinyProxy server.
190192
191193
- *4-namespaced-multi*:
192-
- Operator-mode: `namespaced`
193-
- Operator-namespace: `shinyproxy`
194-
- Redis-namespace: `shinyproxy`
195-
- ShinyProxy-namespace: `shinyproxy`
196-
- URLs:
197-
- `https://shinyproxy-demo.local/shinyproxy1/`
198-
- `https://shinyproxy-demo.local/shinyproxy2/`
199-
- `https://shinyproxy-demo.local/shinyproxy3/`
194+
- Operator-mode: `namespaced`
195+
- Operator-namespace: `shinyproxy`
196+
- Redis-namespace: `shinyproxy`
197+
- ShinyProxy-namespace: `shinyproxy`
198+
- URLs:
199+
- `https://shinyproxy-demo.local/shinyproxy1/`
200+
- `https://shinyproxy-demo.local/shinyproxy2/`
201+
- `https://shinyproxy-demo.local/shinyproxy3/`
200202
201203
Based on the second example, this example shows how multi-tenancy can be
202204
achieved using sub-paths instead of multiple domain names. Each ShinyProxy
@@ -218,16 +220,24 @@ important:
218220
the [example](#modify-the-shinyproxy-pod))
219221
- `kubernetesIngressPatches`: allows to patch the `Ingress` resources created by
220222
the operator (see the [example](#modify-the-ingress-resource))
223+
- `kubernetesServicePatches`: allows to patch the `Service` resources created by
224+
the operator (see the [example](#modify-the-service-resource))
221225
- `image`: the docker image to use for the ShinyProxy server (
222-
e.g. `openanalytics/shinyproxy:3.0.1`)
226+
e.g. `openanalytics/shinyproxy:3.1.0`)
223227
- `imagePullPolicy`: the pull policy for ShinyProxy Image; the default value is
224228
`IfNotPresent`; valid options are `Never`, `IfNotPresent` and `Always`.
225229
- `fqdn`: the FQDN at which the service should be available, e.g. `
226230
shinyproxy-demo.local
231+
- `additionalFqdns`: (optional) a list of additional FQDNs that can be used to
232+
access this ShinyProxy server
227233
- `appNamespaces`: a list of namespaces in which apps will be deployed. This is
228234
only needed when you change the namespace of an app using the
229235
`kubernetes-pod-patches` feature. The namespace of the operator and ShinyProxy
230236
instance are automatically included
237+
- `antiAffinityTopologyKey`: the topology key to use in
238+
the [anti-affinity](#anti-affinity) configuration of the ShinyProxy pods
239+
- `antiAffinityRequired`: if enabled, the [anti-affinity](#anti-affinity)
240+
configuration rules are `required` instead of `preferred`
231241
232242
## Modify the Ingress Resource
233243
@@ -248,7 +258,7 @@ metadata:
248258
namespace: shinyproxy
249259
spec:
250260
proxy:
251-
# ...
261+
# ...
252262
kubernetesIngressPatches: |
253263
- op: add
254264
path: /metadata/annotations
@@ -265,7 +275,7 @@ spec:
265275
- hosts:
266276
- shinyproxy-demo.local
267277
# secretName: example # uncomment and change this line if needed
268-
image: openanalytics/shinyproxy:3.0.1
278+
image: openanalytics/shinyproxy:3.1.0
269279
imagePullPolicy: Always
270280
fqdn: shinyproxy-demo.local
271281
```
@@ -304,7 +314,7 @@ metadata:
304314
namespace: shinyproxy
305315
spec:
306316
proxy:
307-
# ...
317+
# ...
308318
kubernetesPodTemplateSpecPatches: |
309319
- op: add
310320
path: /spec/containers/0/env/-
@@ -326,7 +336,7 @@ spec:
326336
- op: add
327337
path: /spec/serviceAccountName
328338
value: shinyproxy-sa
329-
image: openanalytics/shinyproxy:3.0.1
339+
image: openanalytics/shinyproxy:3.1.0
330340
imagePullPolicy: Always
331341
fqdn: shinyproxy-demo.local
332342
```
@@ -397,3 +407,48 @@ and `/spec/containers/0/volumeMounts` arrays of the pod. The ShinyProxy Operator
397407
automatically creates a mount for a configmap which contains the ShinyProxy
398408
configuration. By overriding these mounts, this configmap is not be mounted and
399409
the default (demo) configuration of ShinyProxy is loaded.
410+
411+
## Modify the Service Resource
412+
413+
The ShinyProxy Operator automatically creates a Service resource for each
414+
ShinyProxy resource you create. The created Service resource contains everything
415+
that is needed for a working ShinyProxy deployment. However, in some cases it is
416+
required to modify the resource. This can be achieved using
417+
the `kubernetesServicePatches` field. This field should contain a string which
418+
contains a list of [JSON Patches](https://jsonpatch.com/) to apply to the
419+
Service resource. For example:
420+
421+
```yaml
422+
apiVersion: openanalytics.eu/v1
423+
kind: ShinyProxy
424+
metadata:
425+
name: shinyproxy
426+
namespace: shinyproxy
427+
spec:
428+
proxy:
429+
# ...
430+
kubernetesServicePatches: |
431+
- op: add
432+
path: /metadata/annotations
433+
value:
434+
my-annotation: my-value
435+
image: openanalytics/shinyproxy:3.1.0
436+
imagePullPolicy: Always
437+
fqdn: shinyproxy-demo.local
438+
```
439+
440+
This example patch adds the annotation `my-annotation: my-value` to the Service
441+
resource created by the operator.
442+
443+
## Anti-affinity
444+
445+
Starting with version 2.1.0, the operator automatically
446+
adds [anti-affinity](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/)
447+
rules, such that Kubernetes will try to not schedule multiple ShinyProxy
448+
replicas on the same Kubernetes node. Note that this only has effect when
449+
running multiple replicas of ShinyProxy. If Kubernetes is unable to satisfy the
450+
requirement, it will still schedule multiple replicas on the same node. This
451+
behavior can be changed by setting `antiAffinityRequired` to `true` in your
452+
ShinyProxy configuration. It is also possible to change the topology, by setting
453+
the `antiAffinityTopologyKey`, e.g. to not run multiple replicas in the same
454+
availability zone you can set this property to `topology.kubernetes.io/zone `.

docs/deployment/overlays/1-namespaced/kustomization.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ kind: Kustomization
33
namespace: shinyproxy
44

55
resources:
6-
- github.com/openanalytics/shinyproxy-operator/docs/deployment/bases/redis-sentinel?ref=v2.0.0
7-
- github.com/openanalytics/shinyproxy-operator/docs/deployment/bases/namespaced?ref=v2.0.0
8-
- github.com/openanalytics/shinyproxy-operator/docs/deployment/bases/shinyproxy?ref=v2.0.0
6+
- github.com/openanalytics/shinyproxy-operator/docs/deployment/bases/redis-sentinel?ref=v2.1.0
7+
- github.com/openanalytics/shinyproxy-operator/docs/deployment/bases/namespaced?ref=v2.1.0
8+
- github.com/openanalytics/shinyproxy-operator/docs/deployment/bases/shinyproxy?ref=v2.1.0
99
- resources/shinyproxy.namespace.yaml
1010
- resources/shinyproxy.shinyproxy.yaml
1111

0 commit comments

Comments
 (0)