Skip to content

Commit

Permalink
Update Rstudio Helm Chart (#30)
Browse files Browse the repository at this point in the history
* Update Rstudio Helm Chart

- Add NGINX in front of Rstudio for authentication
- Route points NGINX
- Add secret with USER and PASSWORD to connect to Rstudio
- Update README and NOTES.txt

* Remove testing host values

* Update NOTES.txt & fix random_pw_secret_key value
  • Loading branch information
trispera authored Apr 26, 2024
1 parent 452e318 commit 3ee93dd
Show file tree
Hide file tree
Showing 12 changed files with 249 additions and 30 deletions.
2 changes: 1 addition & 1 deletion charts/rstudio/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apiVersion: v2
name: rstudio
description: RStudio Helm Chart for Rahti platform
Link to the repo https://github.com/CSCfi/helm-charts
version: 1.2.1
version: 1.2.2
sources:
- https://github.com/CSCfi/helm-charts
icon: https://upload.wikimedia.org/wikipedia/commons/0/0e/Eo_circle_light-blue_white_letter-r.svg
48 changes: 27 additions & 21 deletions charts/rstudio/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,46 @@ helm upgrade --install rstudio .

## Explanations
This Helm Chart helps you to deploy Rstudio with Shiny on CSC Rahti 2 (Openshift 4).
If you want to use it with different values, you can edit `values.yaml` file and then run:
Rstudio is accessible through NGINX. The default user is `rstudio` and the password is generated randomly. You can set you own values by editing the `values.yaml` file and then run:
```sh
helm upgrade --install rstudio . -f {custom_values.yaml}
```

## Parameters
### Common parameters

| Name | Description | Value |
| -------------------------------------- | --------------------------------------------------------- | ------------------------------------------------------------ |
| `openshift.enabled` | If you are deploying on OKD 4 | `true` |
| `appName` | Name for the application | `csc-rstudio-shiny` |
| `route.insecureEdgeTerminationPolicy` | If `openshift.enabled`, will create a route | `Redirect` |
| `route.termination` | If `openshift.enabled`, will create a route | `edge` |
| `route.host` | If `openshift.enabled`, will create a route | `""` |
| `buildConfig.gitRepoUri` | Uri of the GitHub repo where the `Dockerfile` is located | `https://github.com/CSCfi/helm-charts.git` |
| `buildConfig.gitBranch` | Branch of the GitHub repo | `main` |
| `buildConfig.contextDir` | Context directory for the build | `charts/rstudio/source` |
| Name | Description | Value |
| -------------------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------ |
| `openshift.enabled` | If you are deploying on OKD 4 | `true` |
| `appName` | Name for the application | `csc-rstudio-shiny` |
| `buildConfig.gitRepoUri` | Uri of the GitHub repo where the `Dockerfile` is located | `https://github.com/CSCfi/helm-charts.git` |
| `buildConfig.gitBranch` | Branch of the GitHub repo | `main` |
| `buildConfig.contextDir` | Context directory for the build | `charts/rstudio/source` |

### Rstudio parameters

| Name | Description | Value |
| -------------------------------------- | ------------------------------------------------------- | --------------------------------- |
| `rstudio.podSecurityContext` | Set SecurityContext for the pod | `{}` |
| `rstudio.containerSecurityContext` | Set SecurityContext for the container | `allowPrivilegeEscalation: false`<br>`runAsUser:`<br>`runAsGroup:`<br>`capabilities:`<br>&nbsp;&nbsp;`drop:`<br>&nbsp;&nbsp;`- ALL`<br>`runAsNonRoot: true`<br>`seccompProfile:`<br>&nbsp;&nbsp;`type: RuntimeDefault` |
| `rstudio.pvc.mountName` | Name for the `PersistentVolumeClaim` | `rstudio-server-home` |
| `rstudio.pvc.storageSize` | Storage size for the `PersistentVolumeClaim` | `5Gi` |
| Name | Description | Value |
| ---------------------------------------------- | ------------------------------------------------------------- | --------------------------------- |
| `rstudio.podSecurityContext` | Set SecurityContext for the pod | `{}` |
| `rstudio.containerSecurityContext` | Set SecurityContext for the container | `allowPrivilegeEscalation: false`<br>`runAsUser:`<br>`runAsGroup:`<br>`capabilities:`<br>&nbsp;&nbsp;`drop:`<br>&nbsp;&nbsp;`- ALL`<br>`runAsNonRoot: true`<br>`seccompProfile:`<br>&nbsp;&nbsp;`type: RuntimeDefault` |
| `rstudio.pvc.mountName` | Name for the `PersistentVolumeClaim` | `rstudio-server-home` |
| `rstudio.pvc.storageSize` | Storage size for the `PersistentVolumeClaim` | `5Gi` |
| `rstudio.route.insecureEdgeTerminationPolicy` | If `openshift.enabled`, will create a route | `Redirect` |
| `rstudio.route.termination` | If `openshift.enabled`, will create a route | `edge` |
| `rstudio.route.host` | If `openshift.enabled`, will create a route. REQUIRED VALUE | `` |
| `rstudio.random_pw_secret_key` | Key to store the random password | `nginx-password` |
| `rstudio.secret.USER` | User to connect to Rstudio | `rstudio` |
| `rstudio.secret.PASSWORD` | Password to connect to Rstudio | generated randomly |

### Shiny parameters

| Name | Description | Value |
| -------------------------------------- | ------------------------------------------------------- | --------------------------------- |
| `shiny.pvc.mountName` | Name for the `PersistentVolumeClaim` | `shiny-server` |
| `shiny.pvc.storageSize` | Storage size for the `PersistentVolumeClaim` | `5Gi` |
| Name | Description | Value |
| -------------------------------------------- | ------------------------------------------------------------- | --------------------------------- |
| `shiny.pvc.mountName` | Name for the `PersistentVolumeClaim` | `shiny-server` |
| `shiny.pvc.storageSize` | Storage size for the `PersistentVolumeClaim` | `5Gi` |
| `shiny.route.insecureEdgeTerminationPolicy` | If `openshift.enabled`, will create a route | `Redirect` |
| `shiny.route.termination` | If `openshift.enabled`, will create a route | `edge` |
| `shiny.route.host` | If `openshift.enabled`, will create a route. REQUIRED VALUE | `` |

## Cleanup
To delete all the resources, simply uninstall the Helm Chart:
Expand Down
9 changes: 7 additions & 2 deletions charts/rstudio/templates/NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,15 @@ Once the build is over, you can access your Rstudio by retrieving the URL:

You can retrieve Rstudio URL via this command:

export RSTUDIO=$(oc get route --namespace {{ .Release.Namespace }} -o yaml | yq '.items[0].spec.host')
export RSTUDIO=$(oc get route rstudio --namespace {{ .Release.Namespace }} -o yaml | yq .spec.host)
echo "Rstudio server URL: http://$RSTUDIO/"

To retrieve USER and PASSWORD:

echo USER: $(oc get secret --namespace={{ .Release.Namespace }} nginx-password -o jsonpath="{.data.USER}" | base64 -d)
echo PASSWORD: $(oc get secret --namespace={{ .Release.Namespace }} nginx-password -o jsonpath="{.data.PASSWORD}" | base64 -d)

And for the Shiny Server:

export SHINY=$(oc get route --namespace {{ .Release.Namespace }} -o yaml | yq '.items[1].spec.host')
export SHINY=$(oc get route shiny --namespace {{ .Release.Namespace }} -o yaml | yq .spec.host)
echo "Shiny App URL: http://$SHINY/"
35 changes: 35 additions & 0 deletions charts/rstudio/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,38 @@ Create the name of the service account to use
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

{{/*
Define a function that generate static password
*/}}
{{- define "generate_static_password" -}}
{{- /* Create "tmp_vars" dict inside ".Release" to store various stuff. */ -}}
{{- if not (index .Release "tmp_vars") -}}
{{- $_ := set .Release "tmp_vars" dict -}}
{{- end -}}
{{- /* Some random ID of this password, in case there will be other random values alongside this instance. */ -}}
{{- $key := printf "%s_%s" .Release.Name "password" -}}
{{- /* If $key does not yet exist in .Release.tmp_vars, then... */ -}}
{{- if not (index .Release.tmp_vars $key) -}}
{{- /* ... store random password under the $key */ -}}
{{- $_ := set .Release.tmp_vars $key (randAlphaNum 20) -}}
{{- end -}}
{{- /* Retrieve previously generated value. */ -}}
{{- index .Release.tmp_vars $key -}}
{{- end -}}

{{/*
Define a function that lookup the secret on upgrade. If install, it requires the name of secret to create and the key to store the password.
*/}}
{{- define "random_pw_reusable" -}}
{{- if .Release.IsUpgrade -}}
{{- $data := default dict (lookup "v1" "Secret" .Release.Namespace "nginx-password").data -}}
{{- if $data -}}
{{- index $data .Values.rstudio.random_pw_secret_key | b64dec -}}
{{- end -}}
{{- else -}}
{{- if and (required "You must pass nginx-password (the name of a secret to retrieve password from on upgrade)" "nginx-password") (required "You must pass .Values.rstudio.random_pw_secret_key (the name of the key in the secret to retrieve password from on upgrade)" .Values.rstudio.random_pw_secret_key) -}}
{{- (include "generate_static_password" .) -}}
{{- end -}}
{{- end -}}
{{- end -}}
40 changes: 40 additions & 0 deletions charts/rstudio/templates/buildconfig.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,43 @@ spec:
secretReference:
name: webhooksecret
type: GitHub

---
apiVersion: build.openshift.io/v1
kind: BuildConfig
metadata:
name: nginx-okd
annotations:
description: Defines how to build the application
template.alpha.openshift.io/wait-for-ready: "true"
spec:
source:
dockerfile: |
FROM nginx:alpine
# support running as arbitrary user which belogs to the root group
RUN chmod g+rwx /var/cache/nginx /var/run /var/log/nginx && \
chown nginx.root /var/cache/nginx /var/run /var/log/nginx && \
# users are not allowed to listen on priviliged ports
sed -i.bak 's/listen\(.*\)80;/listen 8081;/' /etc/nginx/conf.d/default.conf && \
# Make /etc/nginx/html/ available to use
mkdir -p /etc/nginx/html/ && chmod 777 /etc/nginx/html/ && \
# comment user directive as master process is run as user in OpenShift anyhow
sed -i.bak 's/^user/#user/' /etc/nginx/nginx.conf && \
# Increase the number of worker connections per process
sed -i 's/worker_connections\s*1024/worker_connections 10240/' /etc/nginx/nginx.conf && \
apk add apache2-utils && \
mkdir /etc/nginx/secret/ && \
chown nginx.root /etc/nginx/secret/ && \
chmod g+w /etc/nginx/secret/
WORKDIR /usr/share/nginx/html/
EXPOSE 8081
USER nginx:root
strategy:
type: Docker
output:
to:
kind: ImageStreamTag
name: nginx-okd:latest
triggers:
- type: ImageChange
- type: ConfigChange
23 changes: 23 additions & 0 deletions charts/rstudio/templates/configmap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-default
data:
default.conf: |
server {
listen 8081;
server_name {{ tpl .Values.rstudio.route.host . }}.2.rahtiapp.fi;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
auth_basic \"Rstudio\";
auth_basic_user_file /etc/nginx/secret/htpasswd;
proxy_pass http://{{ tpl .Values.appName . }}:8787/;
proxy_set_header Host $http_host;
client_max_body_size 2000M;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
71 changes: 71 additions & 0 deletions charts/rstudio/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,74 @@ spec:
- name: {{ .Values.shiny.pvc.mountName }}
persistentVolumeClaim:
claimName: {{ .Values.shiny.pvc.mountName }}

---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-okd
name: nginx-okd
spec:
selector:
matchLabels:
app: nginx-okd
strategy:
type: RollingUpdate
template:
metadata:
labels:
app: nginx-okd
spec:
serviceAccount: build-reader
initContainers:
- name: wait-for-build
imagePullPolicy: IfNotPresent
image: quay.io/openshift/origin-cli:4.16
command:
- sh
- -c
- oc wait --for=jsonpath='{.status.phase}'=Complete build -l buildconfig=nginx-okd --timeout=900s
containers:
- name: nginx-okd
image: image-registry.openshift-image-registry.svc:5000/{{ .Release.Namespace }}/nginx-okd:latest
command:
- sh
- -xc
- >-
htpasswd -bc /etc/nginx/secret/htpasswd $USER $PASSWORD;
/docker-entrypoint.sh nginx -g "daemon off;"
env:
- name: USER
valueFrom:
secretKeyRef:
key: USER
name: nginx-password
- name: PASSWORD
valueFrom:
secretKeyRef:
key: PASSWORD
name: nginx-password
ports:
- containerPort: 8081
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /etc/nginx/conf.d/
name: nginx-default
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
volumes:
- configMap:
defaultMode: 420
name: nginx-default
name: nginx-default
- name: nginx-password
secret:
defaultMode: 420
secretName: nginx-password
11 changes: 11 additions & 0 deletions charts/rstudio/templates/imagestream.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ metadata:
annotations:
description: Keeps track of changes in the appliation image
name: {{ .Values.appName }}
spec:
lookupPolicy:
local: true
---

apiVersion: image.openshift.io/v1
kind: ImageStream
metadata:
annotations:
description: Keeps track of changes in the appliation image
name: nginx-okd
spec:
lookupPolicy:
local: true
8 changes: 4 additions & 4 deletions charts/rstudio/templates/routes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ metadata:
app: {{ .Values.appName }}
name: rstudio
spec:
host: {{ .Values.rstudio.route.host }}
host: {{ required "A valid .Values.rstudio.route.host entry is required!" .Values.rstudio.route.host }}.2.rahtiapp.fi
port:
targetPort: 8787
targetPort: 8081
tls:
insecureEdgeTerminationPolicy: {{ .Values.rstudio.route.insecureEdgeTerminationPolicy }}
termination: {{ .Values.rstudio.route.termination }}
to:
kind: Service
name: {{ .Values.appName }}
name: nginx-okd
weight: 100

---
Expand All @@ -25,7 +25,7 @@ metadata:
app: {{ .Values.appName }}
name: shiny
spec:
host: {{ .Values.shiny.route.host }}
host: {{ required "A valid .Values.shiny.route.host entry is required!" .Values.shiny.route.host }}.2.rahtiapp.fi
port:
targetPort: 3838
tls:
Expand Down
11 changes: 11 additions & 0 deletions charts/rstudio/templates/secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
apiVersion: v1
kind: Secret
metadata:
name: nginx-password
{{- if .Values.rstudio.secret }}
data:
{{- range $key, $val := .Values.rstudio.secret }}
"{{ $key }}": "{{ tpl $val $ | b64enc }}"
{{- end }}
{{- end }}
type: Opaque
13 changes: 13 additions & 0 deletions charts/rstudio/templates/service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,16 @@ spec:
- name: shiny
port: 3838
targetPort: 3838

---
apiVersion: v1
kind: Service
metadata:
name: nginx-okd
spec:
selector:
app: nginx-okd
ports:
- name: 8081-tcp
port: 8081
targetPort: 8081
8 changes: 6 additions & 2 deletions charts/rstudio/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ rstudio:
route:
insecureEdgeTerminationPolicy: Redirect
termination: edge
host: ""
host: # REQUIRED
random_pw_secret_key: PASSWORD
secret:
USER: rstudio
PASSWORD: '{{- include "random_pw_reusable" . -}}'

shiny:
pvc:
Expand All @@ -30,7 +34,7 @@ shiny:
route:
insecureEdgeTerminationPolicy: Redirect
termination: edge
host: ""
host: # REQUIRED

buildConfig:
gitRepoUri: https://github.com/CSCfi/helm-charts.git
Expand Down

0 comments on commit 3ee93dd

Please sign in to comment.