2
2
3
3
Easily run ShinyProxy on a Kubernetes cluster
4
4
5
- ** (c) Copyright Open Analytics NV, 2020-2022 - Apache License 2.0**
5
+ ** (c) Copyright Open Analytics NV, 2020-2023 - Apache License 2.0**
6
6
7
7
## Why?
8
8
9
9
Deploying and managing ShinyProxy can get complex when many apps are used,
10
- especially when the configuration of ShinyProxy is often updated. When
11
- restarting a running ShinyProxy instance (in order to update its configuration),
10
+ especially when the configuration of ShinyProxy is often updated.
11
+
12
+ When restarting a running ShinyProxy instance (in order to update its configuration),
12
13
users will face a disconnect from their running applications. The only solution
13
14
to guarantee that users do not lose their connection to running apps, is to keep
14
15
the current instance alive when updating ShinyProxy's configuration. However,
15
16
manually keeping track of these instances would be too cumbersome and should
16
17
therefore be automated.
17
18
18
19
The ShinyProxy operator for Kubernetes is able to manage multiple ShinyProxy
19
- instances and their configuration. To give an example of the working of the
20
- operator, assume we have some ShinyProxy configuration ` config1 ` which contains
21
- one app called ` app1 ` . When the operator starts working, it checks whether a
22
- ShinyProxy instance exists with that configuration. If not, it starts a
23
- ShinyProxy instance and all other required configuration. Users can now start
24
- using ` app1 ` on this instance. Some time later, the need for a second app
25
- arises. Therefore, the administrator adapts the configuration of ShinyProxy to
26
- include a second app ` app2 ` . However, some users are still using ` app1 ` on the
27
- old instance. These apps may have some state, which should not be lost.
28
- Therefore, the operator starts a second ShinyProxy instance using configuration
29
- ` config2 ` . The operator ensures that users which are currently using the first
30
- instance, stay on that instance. All other users, are forwarded to the new
31
- server and can use the new application. Nevertheless, users using an old
32
- instance can choose to use the new instance, by clicking a button in the user
33
- interface. The operator stops the old instance once it has no apps running.
20
+ instances and their configuration.
21
+
22
+ ### Example
23
+
24
+ Assume we have some ShinyProxy configuration ` config1 ` which contains one app
25
+ called ` app1 ` . When the operator starts working, it checks whether a ShinyProxy
26
+ instance exists with that configuration. If not, it starts a ShinyProxy instance
27
+ and all other required configuration. Users can now start using ` app1 ` on this
28
+ instance.
29
+
30
+ Some time later, the need for a second app arises. Therefore, the administrator
31
+ adapts the configuration of ShinyProxy to include a second app ` app2 ` .
32
+
33
+ However, some users are still using ` app1 ` on the old instance. These apps may
34
+ have some state, which should not be lost. Therefore, the operator starts a
35
+ second ShinyProxy instance using configuration ` config2 ` . The operator does not
36
+ modify the original ShinyProxy server, therefore the existing apps continue to
37
+ work (even if they are using Websocket connections).
38
+
39
+ All new HTTP (and Websocket) connections are forwarded to the new server, i.e.
40
+ any new connection is handled by the new server. Therefore, if users go to the
41
+ main ShinyProxy page, they will see that a new app is available. Every user (
42
+ also those still using the old application) can start the new app. The operator
43
+ stops and removes the old server as soon as it has finished handling any
44
+ existing (Websocket) connections.
34
45
35
46
## Building from source
36
47
@@ -45,8 +56,9 @@ The build will result in a single `.jar` file:
45
56
46
57
## Running
47
58
48
- The operator should be run in Kubernetes using the [ docker image] ( https://hub.docker.com/r/openanalytics/shinyproxy-operator ) .
49
- It can run in either ` clustered ` scope or ` namespaced ` mode. In the former the
59
+ The operator should be run in Kubernetes using
60
+ the [ docker image] ( https://hub.docker.com/r/openanalytics/shinyproxy-operator ) .
61
+ It can run in either ` clustered ` or ` namespaced ` mode. In the former the
50
62
operator looks for ShinyProxy instances in all namespaces while in the latter it
51
63
only manages ShinyProxy instances in its own namespace.
52
64
@@ -63,8 +75,6 @@ start with the `SPO` prefix, meaning **S**hiny**P**roxy**O**perator.
63
75
- ` SPO_MODE ` : can either be ` namespaced ` or ` clustered ` (default). This
64
76
specifies whether the operator should only look in its own namespace for
65
77
ShinyProxy configurations or in all namespaces.
66
- - ` SPO_DISABLE_SECURE_COOKIES ` : when set to any value, this disables the
67
- ` secure ` flag on all cookies used by the Operator.
68
78
- ` SPO_PROBE_INITIAL_DELAY ` : specifies the initial delay of the Readiness and
69
79
Liveness probes. This is useful when the used Kubernetes version does not
70
80
support startup probes.
@@ -74,7 +84,8 @@ start with the `SPO` prefix, meaning **S**hiny**P**roxy**O**perator.
74
84
- ` SPO_PROBE_TIMEOUT ` : specifies the timeout in seconds of the Readiness and
75
85
Liveness probes. This is useful when the used Kubernetes version does not
76
86
support startup probes.
77
- - ` SPO_STARTUP_PROBE_INITIAL_DELAY ` : specifies the initial delay of the StartUp probe. By default, this is 60 seconds.
87
+ - ` SPO_STARTUP_PROBE_INITIAL_DELAY ` : specifies the initial delay of the StartUp
88
+ probe. By default, this is 60 seconds.
78
89
- ` SPO_LOG_LEVEL ` : configures the log level of the operator, may be one of the
79
90
following:
80
91
- ` OFF ` : disables logging
@@ -102,22 +113,20 @@ ShinyProxy and the operator for the best experience.
102
113
103
114
| ShinyProxy Version | Minimum operator version | Maximum operator version (inclusive) |
104
115
| --------------------| ----------------------------------| --------------------------------------|
105
- | 2.4.3 | ` 0.0.1-SNAPSHOT-20201215.112635 ` | ` 0.0.1-SNAPSHOT-20201215.112635 ` |
116
+ | 3.0.0 | 2.0.0 | TBD |
117
+ | 2.6.0 | 1.0.0 | 1.1.0 |
106
118
| 2.5.0 | ` 0.0.1-SNAPSHOT-20210302.095930 ` | ` 0.0.1-SNAPSHOT-20210607.070151 ` |
107
- | 2.6.0 | 1. 0.0 | TBD |
119
+ | 2.4.3 | ` 0.0.1-SNAPSHOT-20201215.112635 ` | ` 0.0.1-SNAPSHOT-20201215.112635 ` |
108
120
109
121
## Kubernetes versions
110
122
111
- | | 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 | v1.17 | v1.16 | v1.15 | v1.14 |
112
- | ----------------| ------------| ------------| ----------------| ----------------| ----------------| ----------------| -------| -------| -------| -------| ----- | ----- |
113
- | 1.1.0 | ✓ | ✓ | ✓ | ✓² | ✓ | ✓² | ✓ | - | - | - | - | - |
114
- | 1.0.0 | - | - | ✓ | ✓² | ✓ | ✓² | ✓ | ✓ | ✓¹ | ✓¹ | - | - |
115
- | 0.0.1-SNAPSHOT | - | - | ✓ | ✓² | ✓ | ✓² | ✓ | ✓ | ✓¹ | ✓¹ | ✓¹ | ✓¹ |
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 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓¹ | ✓ | ✓¹ | ✓ | - |
116
126
117
127
** Note:**
118
128
119
- - ¹ requires the use of ` SPO_PROBE_INITIAL_DELAY ` and ` SPO_PROBE_FAILURE_THRESHOL ` due to lack of startup probes
120
- - ² requires a workaround, see below.
129
+ - ¹ requires a workaround, see below.
121
130
122
131
### Workaround for bug in Kubernetes
123
132
@@ -135,34 +144,38 @@ only reasonable work-around is to regularly restart the Operator. Since version
135
144
minutes), the operator stops. The corresponding Docker container then
136
145
automatically restarts the Java process.
137
146
138
- ### Update to 1.0.0
139
-
140
- Be aware of these changes when updating to version 1.0.0:
141
-
142
- - the ShinyProxy CRD now uses version ` apiextensions.k8s.io/v1 ` of the
143
- ` CustomResourceDefinition ` resource instead of version
144
- ` apiextensions.k8s.io/v1beta ` . In our tests this update when smooth, but
145
- please take into account that you may be required to re-create the CRD and
146
- that therefore your ShinyProxy servers may have to be re-created (causing
147
- downtime).
148
- - because of this change, the operator requires at least version Kubernetes
149
- v1.16.
150
- - the ShinyProxy CRD now specifies version ` openanalytics.eu/v1 ` instead of
151
- ` openanalytics.eu/v1alpha1 ` . Nevertheless, the operator is still able to
152
- handle ShinyProxy resources using the ` openanalytics.eu/v1alpha1 ` version.
153
- When creating resources with version ` openanalytics.eu/v1alpha1 ` , Kubernetes
154
- will automatically convert these to use version ` openanalytics.eu/v1 ` .
155
-
156
- ### Update to 1.1.0
157
-
158
- Be aware of these changes when updating to version 1.0.0:
159
-
160
- - starting with this version, the operator uses the ` networking.k8s.io/v1 `
161
- version of the Ingress resource. Therefore, this version is compatible with
162
- Kubernetes 1.22 or later and requires at least Kubernetes v1.19. In order to
163
- make this possible, the Skipper component was updated and the Skipper
164
- configuration was changed. Make sure to re-import the manifests.
165
- -
147
+ ### Update to 2.0.0
148
+
149
+ Be aware of these changes when updating to version 2.0.0:
150
+
151
+ - the old mechanism where cookies were used to assign users to specific
152
+ ShinyProxy servers is no longer used. Instead, as soon as a new server is
153
+ started, all new requests will be handled by the new server, including
154
+ requests for existing apps. Only existing websocket connections will stay open
155
+ 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.
168
+ - the operator now requires ShinyProxy to store the active proxies in Redis.
169
+ Therefore, since this release Redis takes a more critical role. When running
170
+ Redis inside Kubernetes, it is therefore best practice to use Redis Sentinel.
171
+ This way Redis runs in a High Available mode, using three replicas. Compared
172
+ to running a single Redis server, this prevents a single point of failure on
173
+ Redis and the node it is running on. This repository contains all manifests
174
+ required to set up Redis Sentinel (based on the bitnamai Redis helm chart).
175
+
176
+ The best way to update to ShinyProxy 2.0.0 is by creating a fresh deployment of
177
+ the operator and migrating users to this new deployment.
178
+
166
179
## Java Version
167
180
168
181
This project requires JDK 11.
0 commit comments