-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mrc-4908 k8s setup #1
Changes from 11 commits
eb5618b
69d5f98
4fc22d8
6e4e6c7
7badd77
1078b51
55e8329
37c5cfd
472a689
31b18a4
a6f2fa5
16ad36d
8b19073
d5fd1c4
bc066f3
9a9c8f0
526208e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
apache/ssl | ||
k8s/ssl |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -2,60 +2,22 @@ | |||||
|
||||||
This is a temporary repo designed to give an easy-to-understand deployment of the apache / haproxy / shiny stack; it does not include configurable applications or anything like that. See it online at https://shiny-dev.dide.ic.ac.uk (DIDE network only). | ||||||
|
||||||
## The components | ||||||
|
||||||
Some of these are docker images, and they are not set to pull, so you will want to rebuild. All build very quickly. | ||||||
## Running in Kubernetes | ||||||
|
||||||
### apache | ||||||
The following is guide to run the shiny server in kubernetes. They are based on running a Kind cluster. The configuration may | ||||||
nee to be adjusted for other k8s clusters. | ||||||
|
||||||
Running an unmodified httpd container (previously was 2.4, we'll update once we know this works). The configuration ([`apache/httpd.conf`](httpd/httpd.conf)) and certificates (`apache/ssl`) will be read-only mounted into the container. You need to fetch the ssl key and certificate, run `./apache/configure_ssl` to do this (only needs to be done if they change or if the `ssl` directory is deleted) | ||||||
### Prerequisites | ||||||
|
||||||
### haproxy | ||||||
A production kubernetes cluster using k3s is needed to be setup first. To setup a k8s cluster follow the guide [here](https://mrc-ide.myjetbrains.com/youtrack/articles/RESIDE-A-31/Setting-up-Kubernetes-k8s-Cluster). Note: If using dev cluster (KIND), the storageClassName: local-path & longhorn is unavailable and you will need to provision own storage class and persistant volume. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does the recommended setup look like for developing this locally? or on a staging machine (separate from the shiny staging, which is really for the users)? Do we need a second cluster somewhere that we use? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the link shows the dev and prod setup and they both can be used locally... for staging, we can use the same cluster and just do another deployment and rename the deployment to something else... But if you wanted a seperate machine for just staging spinning up another cluster might be easiest There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Sorry, don't really understand this. Why aren't these available? You talk about using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. have updated to avoid confusion |
||||||
|
||||||
Build the image with `./haproxy/build` which builds `mrcide/haproxy` with a configuration that can be seen in [`haproxy/haproxy.cfg`](haproxy/haproxy.cfg) and some utilities which enable some degree of dynamic scaling of shiny servers. | ||||||
Run `start-k8s-shiny <env>` to run the shint server in k8s. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
### shiny | ||||||
|
||||||
A lightly modified version of the official shiny container; the original version was more extensively modified | ||||||
#### Teardown | ||||||
|
||||||
### apps | ||||||
Run the following: | ||||||
|
||||||
Some applications (copied over from the original deployment are in `apps`). These will want to be in a volume; run `./apps/create_volume` to copy them into the volume | ||||||
|
||||||
### Summary | ||||||
|
||||||
``` | ||||||
./apache/configure_ssl | ||||||
./haproxy/build | ||||||
./shiny/build | ||||||
./apps/create_volume | ||||||
``` | ||||||
|
||||||
## Bringing the bits up | ||||||
|
||||||
``` | ||||||
docker network create twinkle 2> /dev/null || /bin/true | ||||||
docker volume create shiny_logs | ||||||
docker run -d --name haproxy --network twinkle mrcide/haproxy:dev | ||||||
docker run -d --name apache --network twinkle \ | ||||||
-p 80:80 \ | ||||||
-p 443:443 \ | ||||||
-p 9000:9000 \ | ||||||
-v "${PWD}/apache/httpd.conf:/usr/local/apache2/conf/httpd.conf:ro" \ | ||||||
-v "${PWD}/apache/auth:/usr/local/apache2/conf/auth:ro" \ | ||||||
-v "${PWD}/apache/ssl:/usr/local/apache2/conf/ssl:ro" \ | ||||||
httpd:2.4 | ||||||
docker run -d --name shiny-1 --network=twinkle \ | ||||||
-v twinkle_apps:/shiny/apps \ | ||||||
-v twinkle_logs:/shiny/logs \ | ||||||
-p 3838:3838 \ | ||||||
mrcide/shiny-server:dev | ||||||
docker exec haproxy update_shiny_servers shiny 1 | ||||||
``` | ||||||
|
||||||
Teardown | ||||||
|
||||||
``` | ||||||
docker rm -f haproxy apache shiny-1 | ||||||
docker network rm twinkle | ||||||
``` | ||||||
1. `kubectl delete -k k8s/overlays/<env>`. Replace <env> with testing or production. | ||||||
2. `kubectl delete ns twinkle` to remove namespace. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
apiVersion: apps/v1 | ||
kind: Deployment | ||
metadata: | ||
name: shiny-deploy | ||
labels: | ||
app: shiny | ||
spec: | ||
replicas: 2 | ||
selector: | ||
matchLabels: | ||
app: shiny | ||
template: | ||
metadata: | ||
labels: | ||
app: shiny | ||
spec: | ||
initContainers: | ||
- name: init-shiny | ||
image: busybox:1.28 | ||
command: ["sh", "-c", "mkdir -p /shiny/logs /shiny/apps"] | ||
volumeMounts: | ||
- name: shiny-data | ||
mountPath: /shiny | ||
containers: | ||
- name: shiny | ||
image: absternator/shiny-server:dev # todo: change to actual one!!! mrcide- | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What changes did you make here? Can we get the image build script/Dockerfile here and building on BK? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just changed the image so it has an image to pull from the docker hub... i can add the docker build & push step to the startup script? is that you want? ps.. sorry whats BK? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. BK=BuildKite, where we have some non-gha CI builds running, |
||
volumeMounts: | ||
- name: shiny-data | ||
mountPath: /shiny | ||
# todo: create appropriate resource requests | ||
# resources: | ||
# requests: | ||
# memory: "128Mi" | ||
# cpu: "250m" | ||
volumes: | ||
- name: shiny-data | ||
persistentVolumeClaim: | ||
claimName: shiny-pvc |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
apiVersion: networking.k8s.io/v1 | ||
kind: Ingress | ||
metadata: | ||
name: ingress-shiny | ||
annotations: | ||
nginx.ingress.kubernetes.io/affinity: "cookie" | ||
nginx.ingress.kubernetes.io/session-cookie-name: "shinycookie" | ||
nginx.ingress.kubernetes.io/session-cookie-expires: "172800" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this in seconds? 48 hours? Seems reasonable There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yup in seconds... 48 hours |
||
nginx.ingress.kubernetes.io/session-cookie-max-age: "172800" | ||
spec: | ||
ingressClassName: nginx | ||
tls: | ||
- hosts: | ||
- shiny-dev.dide.ic.ac.uk | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So we'll need to update this setting for prod, and for running locally? |
||
secretName: tls-secret | ||
rules: | ||
- host: shiny-dev.dide.ic.ac.uk | ||
http: | ||
paths: | ||
- path: / | ||
pathType: Prefix | ||
backend: | ||
service: | ||
name: shiny-svc | ||
port: | ||
number: 3838 |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,12 @@ | ||||||
apiVersion: kustomize.config.k8s.io/v1beta1 | ||||||
kind: Kustomization | ||||||
metadata: | ||||||
name: shiny | ||||||
|
||||||
namespace: twinkle # assume this namespace exists | ||||||
|
||||||
resources: | ||||||
- persistance.yaml | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
- deployment.yaml | ||||||
- service.yaml | ||||||
- ingress.yaml |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# todo: storage capacity as per requirements | ||
# can use local-path if single node or dont need distributed & replicated | ||
apiVersion: v1 | ||
kind: PersistentVolumeClaim | ||
metadata: | ||
name: shiny-pvc | ||
spec: | ||
storageClassName: longhorn | ||
accessModes: | ||
- ReadWriteMany | ||
resources: | ||
requests: | ||
storage: 15Gi |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
apiVersion: v1 | ||
kind: Service | ||
metadata: | ||
name: shiny-svc | ||
spec: | ||
type: ClusterIP | ||
selector: | ||
app: shiny | ||
ports: | ||
- protocol: TCP | ||
port: 3838 | ||
targetPort: 3838 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#!/usr/bin/env bash | ||
# TODO: update to use vault k8s auth | ||
set -eu | ||
|
||
export VAULT_ADDR=https://vault.dide.ic.ac.uk:8200 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a k8s/vault adaptor to make this easier? Not necessarily for this PR, but feels like something we might do a bunch of we do more with this style. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. il have a look into that... in the past when we stored secerts in azure key vault we would run and get the secrets in CI and create the secret that way so kubernetes could use it... but il see if there is other ways |
||
export VAULT_TOKEN=$(vault login -method=github -token-only) | ||
|
||
DEST=${PWD}/k8s/ssl | ||
mkdir -p $DEST | ||
|
||
vault read -field=value /secret/shiny.dide/dev/ssl/cert > \ | ||
${DEST}/certificate.pem | ||
vault read -field=value /secret/shiny.dide/dev/ssl/key > \ | ||
${DEST}/key.pem | ||
|
||
kubectl -n twinkle create secret tls tls-secret --cert ${DEST}/certificate.pem --key ${DEST}/key.pem |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
#!/usr/bin/env bash | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does this script do? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. pretty much coppies files from host machine into a kubernetes pod using rsync |
||
set -eu | ||
# https://serverfault.com/questions/741670/rsync-files-to-a-kubernetes-pod | ||
# example usage: | ||
# ./krsync -av --progress --stats <hostdir> podName@namespace:<poddir> | ||
|
||
if [ -z "$KRSYNC_STARTED" ]; then | ||
export KRSYNC_STARTED=true | ||
exec rsync -a --delete --blocking-io --rsh "$0" $@ | ||
fi | ||
|
||
# Running as --rsh | ||
namespace='' | ||
pod=$1 | ||
shift | ||
|
||
# If user uses pod@namespace, rsync passes args as: {us} -l pod namespace ... | ||
if [ "X$pod" = "X-l" ]; then | ||
pod=$1 | ||
shift | ||
namespace="-n $1" | ||
shift | ||
fi | ||
|
||
|
||
exec kubectl $namespace exec -i $pod -- "$@" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
apiVersion: kustomize.config.k8s.io/v1beta1 | ||
kind: Kustomization | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤨 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 😕 ? |
||
|
||
resources: | ||
- ../../base | ||
|
||
commonLabels: | ||
env: production | ||
|
||
replicas: | ||
- name: shiny-deploy | ||
count: 9 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
apiVersion: kustomize.config.k8s.io/v1beta1 | ||
kind: Kustomization | ||
|
||
resources: | ||
- ../../base | ||
|
||
commonLabels: | ||
env: testing | ||
|
||
replicas: | ||
- name: shiny-deploy | ||
count: 3 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#!/usr/bin/env bash | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So this is just a temporary thing until we have the management bit working? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yup temporary until we sort the management side |
||
set -eu | ||
# uses krysnc to sync files to a kubernetes pod and thus into k8s cluster (via persistant volume) | ||
# RUN this from repository root to ensure correct paths to app files | ||
NAMESPACE=twinkle | ||
SYNC_DIR=/shiny/apps | ||
|
||
|
||
FIRST_SHINY_POD=$(kubectl get pods -l app=shiny -n $NAMESPACE -o jsonpath='{.items[0].metadata.name}') | ||
echo "pod name: $FIRST_SHINY_POD" | ||
$PWD/k8s/krsync -av --progress --stats $PWD/apps/* $FIRST_SHINY_POD@$NAMESPACE:$SYNC_DIR |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
#!/usr/bin/env bash | ||
set -eu | ||
# example use case: ./start-k8s-shiny production | ||
|
||
# Set the environment variable to the first command-line argument or default to 'testing' | ||
ENV=${1:-testing} | ||
if [[ "$ENV" != "testing" && "$ENV" != "production" ]]; then | ||
echo "Error: env must be either 'testing' or 'production'" | ||
exit 1 | ||
fi | ||
# Make the script itself executable | ||
chmod +x "$0" | ||
|
||
# Make the k8s directory and its contents executable | ||
chmod +x k8s/ | ||
|
||
# Create a Kubernetes namespace named 'twinkle' | ||
kubectl create ns twinkle | ||
|
||
# Run the script to configure SSL (assuming it's in the k8s directory) | ||
k8s/configure_ssl || { echo "Error: Failed to configure SSL"; exit 1; } | ||
|
||
# Apply Kubernetes manifests from overlays based on the specified or default environment | ||
kubectl apply -k "k8s/overlays/$ENV" | ||
|
||
# Wait for the 'shiny-deploy' deployment to be in the 'available' condition within the 'twinkle' namespace | ||
echo 'Waiting for pods to be ready...' | ||
kubectl wait -n twinkle --for=condition=available --timeout=300s deployment/shiny-deploy | ||
|
||
# Run the script for 'shiny-sync' (assuming it's in the k8s directory) | ||
k8s/shiny-sync |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.