Skip to content

Commit

Permalink
Merge branch 'release/2.0.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
LEDfan committed Mar 2, 2023
2 parents e21ab21 + 14a78c6 commit aa1d675
Show file tree
Hide file tree
Showing 162 changed files with 3,032 additions and 2,899 deletions.
6 changes: 4 additions & 2 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@ end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true


[*.kt]
ij_kotlin_call_parameters_new_line_after_left_paren = false
ij_kotlin_call_parameters_right_paren_on_new_line = false
ij_kotlin_method_parameters_new_line_after_left_paren = false
ij_kotlin_method_parameters_right_paren_on_new_line = false
ij_any_wrap_long_lines = false
ij_formatter_off_tag = "@formatter:off"
ij_formatter_on_tag = "@formatter:on"
ij_kotlin_name_count_to_use_star_import = 50000
ij_kotlin_name_count_to_use_star_import_for_members = 50000
ij_formatter_tags_enabled = true
ij_formatter_off_tag = @formatter:off
ij_formatter_on_tag = @formatter:on
max_line_length = 256
indent_style = space
indent_size = 4
Expand Down
16 changes: 13 additions & 3 deletions .github/workflows/workflows.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ jobs:
fail-fast: false
matrix:
java: [ 11 ]
kubernetes: [ 'v1.21.6', 'v1.20.12', 'v1.19.16', 'v1.18.20', 'v1.17.17', 'v1.16.15']
kubernetes:
- 'v1.22.17'
- 'v1.23.15'
- 'v1.24.9'
- 'v1.25.5'

steps:
- uses: actions/checkout@v2
Expand All @@ -24,10 +28,16 @@ jobs:
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: Setup Minikube
uses: manusa/actions-setup-minikube@v2.4.2
uses: manusa/actions-setup-minikube@v2.7.2
with:
minikube version: 'v1.16.0'
minikube version: 'v1.28.0'
kubernetes version: ${{ matrix.kubernetes }}
github token: ${{ secrets.GITHUB_TOKEN }}
- name: Pull images
run: |
minikube image pull ledfan/shinyproxy:3.0.0-SNAPSHOT-20230116.114943
minikube image pull openanalytics/shinyproxy-demo
minikube image pull curlimages/curl:latest
- name: Build with Maven
run: mvn -B -U clean install -DskipTests
- name: Run Tests
Expand Down
2 changes: 1 addition & 1 deletion LICENSE_HEADER
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
ShinyProxy-Operator

Copyright (C) 2021-2022 Open Analytics
Copyright (C) 2021-2023 Open Analytics

===========================================================================

Expand Down
133 changes: 73 additions & 60 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,46 @@

Easily run ShinyProxy on a Kubernetes cluster

**(c) Copyright Open Analytics NV, 2020-2022 - Apache License 2.0**
**(c) Copyright Open Analytics NV, 2020-2023 - Apache License 2.0**

## Why?

Deploying and managing ShinyProxy can get complex when many apps are used,
especially when the configuration of ShinyProxy is often updated. When
restarting a running ShinyProxy instance (in order to update its configuration),
especially when the configuration of ShinyProxy is often updated.

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

The ShinyProxy operator for Kubernetes is able to manage multiple ShinyProxy
instances and their configuration. To give an example of the working of the
operator, assume we have some ShinyProxy configuration `config1` which contains
one app called `app1`. When the operator starts working, it checks whether a
ShinyProxy instance exists with that configuration. If not, it starts a
ShinyProxy instance and all other required configuration. Users can now start
using `app1` on this instance. Some time later, the need for a second app
arises. Therefore, the administrator adapts the configuration of ShinyProxy to
include a second app `app2`. However, some users are still using `app1` on the
old instance. These apps may have some state, which should not be lost.
Therefore, the operator starts a second ShinyProxy instance using configuration
`config2`. The operator ensures that users which are currently using the first
instance, stay on that instance. All other users, are forwarded to the new
server and can use the new application. Nevertheless, users using an old
instance can choose to use the new instance, by clicking a button in the user
interface. The operator stops the old instance once it has no apps running.
instances and their configuration.

### Example

Assume we have some ShinyProxy configuration `config1` which contains one app
called `app1`. When the operator starts working, it checks whether a ShinyProxy
instance exists with that configuration. If not, it starts a ShinyProxy instance
and all other required configuration. Users can now start using `app1` on this
instance.

Some time later, the need for a second app arises. Therefore, the administrator
adapts the configuration of ShinyProxy to include a second app `app2`.

However, some users are still using `app1` on the old instance. These apps may
have some state, which should not be lost. Therefore, the operator starts a
second ShinyProxy instance using configuration `config2`. The operator does not
modify the original ShinyProxy server, therefore the existing apps continue to
work (even if they are using Websocket connections).

All new HTTP (and Websocket) connections are forwarded to the new server, i.e.
any new connection is handled by the new server. Therefore, if users go to the
main ShinyProxy page, they will see that a new app is available. Every user (
also those still using the old application) can start the new app. The operator
stops and removes the old server as soon as it has finished handling any
existing (Websocket) connections.

## Building from source

Expand All @@ -45,8 +56,9 @@ The build will result in a single `.jar` file:

## Running

The operator should be run in Kubernetes using the [docker image](https://hub.docker.com/r/openanalytics/shinyproxy-operator).
It can run in either `clustered` scope or `namespaced` mode. In the former the
The operator should be run in Kubernetes using
the [docker image](https://hub.docker.com/r/openanalytics/shinyproxy-operator).
It can run in either `clustered` or `namespaced` mode. In the former the
operator looks for ShinyProxy instances in all namespaces while in the latter it
only manages ShinyProxy instances in its own namespace.

Expand All @@ -63,8 +75,6 @@ start with the `SPO` prefix, meaning **S**hiny**P**roxy**O**perator.
- `SPO_MODE`: can either be `namespaced` or `clustered` (default). This
specifies whether the operator should only look in its own namespace for
ShinyProxy configurations or in all namespaces.
- `SPO_DISABLE_SECURE_COOKIES`: when set to any value, this disables the
`secure` flag on all cookies used by the Operator.
- `SPO_PROBE_INITIAL_DELAY`: specifies the initial delay of the Readiness and
Liveness probes. This is useful when the used Kubernetes version does not
support startup probes.
Expand All @@ -74,7 +84,8 @@ start with the `SPO` prefix, meaning **S**hiny**P**roxy**O**perator.
- `SPO_PROBE_TIMEOUT`: specifies the timeout in seconds of the Readiness and
Liveness probes. This is useful when the used Kubernetes version does not
support startup probes.
- `SPO_STARTUP_PROBE_INITIAL_DELAY`: specifies the initial delay of the StartUp probe. By default, this is 60 seconds.
- `SPO_STARTUP_PROBE_INITIAL_DELAY`: specifies the initial delay of the StartUp
probe. By default, this is 60 seconds.
- `SPO_LOG_LEVEL`: configures the log level of the operator, may be one of the
following:
- `OFF`: disables logging
Expand Down Expand Up @@ -102,22 +113,20 @@ ShinyProxy and the operator for the best experience.

| ShinyProxy Version | Minimum operator version | Maximum operator version (inclusive) |
|--------------------|----------------------------------|--------------------------------------|
| 2.4.3 | `0.0.1-SNAPSHOT-20201215.112635` | `0.0.1-SNAPSHOT-20201215.112635` |
| 3.0.0 | 2.0.0 | TBD |
| 2.6.0 | 1.0.0 | 1.1.0 |
| 2.5.0 | `0.0.1-SNAPSHOT-20210302.095930` | `0.0.1-SNAPSHOT-20210607.070151` |
| 2.6.0 | 1.0.0 | TBD |
| 2.4.3 | `0.0.1-SNAPSHOT-20201215.112635` | `0.0.1-SNAPSHOT-20201215.112635` |

## Kubernetes versions

| | 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 |
|----------------|------------|------------|----------------|----------------|----------------|----------------|-------|-------|-------|-------| ----- | ----- |
| 1.1.0 |||| ✓² || ✓² || - | - | - | - | - |
| 1.0.0 | - | - || ✓² || ✓² ||| ✓¹ | ✓¹ | - | - |
| 0.0.1-SNAPSHOT | - | - || ✓² || ✓² ||| ✓¹ | ✓¹ | ✓¹ | ✓¹ |
| | 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 |
|-------|------------|------------|-------------|------------|----------------|----------------|----------------|----------------|-------|----------|
| 2.0.0 |||||| ✓¹ || ✓¹ || - |

**Note:**

- ¹ requires the use of `SPO_PROBE_INITIAL_DELAY` and `SPO_PROBE_FAILURE_THRESHOL` due to lack of startup probes
- ² requires a workaround, see below.
- ¹ requires a workaround, see below.

### Workaround for bug in Kubernetes

Expand All @@ -135,34 +144,38 @@ only reasonable work-around is to regularly restart the Operator. Since version
minutes), the operator stops. The corresponding Docker container then
automatically restarts the Java process.

### Update to 1.0.0

Be aware of these changes when updating to version 1.0.0:

- the ShinyProxy CRD now uses version `apiextensions.k8s.io/v1` of the
`CustomResourceDefinition` resource instead of version
`apiextensions.k8s.io/v1beta`. In our tests this update when smooth, but
please take into account that you may be required to re-create the CRD and
that therefore your ShinyProxy servers may have to be re-created (causing
downtime).
- because of this change, the operator requires at least version Kubernetes
v1.16.
- the ShinyProxy CRD now specifies version `openanalytics.eu/v1` instead of
`openanalytics.eu/v1alpha1`. Nevertheless, the operator is still able to
handle ShinyProxy resources using the `openanalytics.eu/v1alpha1` version.
When creating resources with version `openanalytics.eu/v1alpha1`, Kubernetes
will automatically convert these to use version `openanalytics.eu/v1`.

### Update to 1.1.0

Be aware of these changes when updating to version 1.0.0:

- starting with this version, the operator uses the `networking.k8s.io/v1`
version of the Ingress resource. Therefore, this version is compatible with
Kubernetes 1.22 or later and requires at least Kubernetes v1.19. In order to
make this possible, the Skipper component was updated and the Skipper
configuration was changed. Make sure to re-import the manifests.
-
### Update to 2.0.0

Be aware of these changes when updating to version 2.0.0:

- the old mechanism where cookies were used to assign users to specific
ShinyProxy servers is no longer used. Instead, as soon as a new server is
started, all new requests will be handled by the new server, including
requests for existing apps. Only existing websocket connections will stay open
on the old servers. This has multiple benefits:
- when a new server is started, users will immediately use and see the
configuration of that new server. In other words, if a new configuration
includes a new app, this app is immediately available to all users (even if
they are using apps started on older servers)
- there is no longer a process of transferring users to new servers. Both the
forced method and the manual method (where users have to click a button) are
removed. Users will immediately use the new configuration.
- apps can be run for a (very) long time, even if frequently updating the
configuration and without having many old servers. Old servers are removed
as soon as no websocket connections are running on that server.
- Skipper is no longer a dependency of the operator. There is no benefit in
using with version two of the operator.
- the operator now requires ShinyProxy to store the active proxies in Redis.
Therefore, since this release Redis takes a more critical role. When running
Redis inside Kubernetes, it is therefore best practice to use Redis Sentinel.
This way Redis runs in a High Available mode, using three replicas. Compared
to running a single Redis server, this prevents a single point of failure on
Redis and the node it is running on. This repository contains all manifests
required to set up Redis Sentinel (based on the bitnamai Redis helm chart).

The best way to update to ShinyProxy 2.0.0 is by creating a fresh deployment of
the operator and migrating users to this new deployment.

## Java Version

This project requires JDK 11.
1 change: 0 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# Docs

- [Deployment (with examples)](deployment/)
- [Behavior in combination with ShinyProxy](shinyproxy.md)
- [Prometheus monitoring](prometheus.md)
Loading

0 comments on commit aa1d675

Please sign in to comment.