Skip to content

Commit

Permalink
feat: offer deployment manifests
Browse files Browse the repository at this point in the history
Adds a basic Dockerfile for building the image containing this
application.
Additionally adds k8s manifest files that allow for deploying
the application to a Kubernetes cluster. Alongside with that
a deployment script is introduced that can be used to deploy
the application to an existing minikube instance for development
purposes.
  • Loading branch information
DiCanio committed Mar 18, 2024
1 parent e3c407a commit 48758aa
Show file tree
Hide file tree
Showing 11 changed files with 400 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
npm-debug.log
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ db.sqlite
.env
cache
.swc

k8s/tmp**
14 changes: 14 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM node:20.11-alpine3.19@sha256:c0a3badbd8a0a760de903e00cedbca94588e609299820557e72cba2a53dbaa2c
RUN mkdir -p /home/node/node-message-broker/node_modules && chown -R node:node /home/node/node-message-broker
WORKDIR /home/node/node-message-broker
COPY --chown=node:node package*.json .

USER node

RUN npm install

COPY --chown=node:node ./dist .

EXPOSE 3000

CMD [ "node", "index.js" ]
48 changes: 48 additions & 0 deletions k8s/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# k8s

> [!CAUTION]
> Files found in this directory should be used with caution and NOT in a production environment! They are mainly for showcasing purposes. So, adjust them as necessary before applying them to your cluster.
This directory contains:
- a deployment script (`deploy-to-minikube.sh`)
- k8s manifest files

## Prerequisites

Make sure the following `minikube` addons are enabled before using this deployment solution:

- ingress
- registry
- storage-provisioner

You can enable addons using the following command:

```shell
minikube addons enable <addon>
```

For further information, see: [minikube addon docs](https://minikube.sigs.k8s.io/docs/commands/addons/).

## Usage

The script will install a single message broker instance to an already existing `minikube` cluster. In order to use it make sure the following environment variables are set:

| ENV VAR | DESCRIPTION |
|---------|-------------|
| AUTH_JWKS_URL | URL to obtain JWKS from. Using keycloak this has the pattern `<KEYCLOAK_BASE_URL>/realms/<YOUR_REALM>/protocol/openid-connect/certs`. |
| HUB_AUTH_ROBOT_ID | ID of the robot account to be used. Needs to exist on the central side (hub) at `https://auth.privateaim.net/`. |
| ROBOT_SECRET | Associated secret of the robot account. |
| NODE_MESSAGE_BROKER_HOST | Host to be used for the message broker. It will be accessible under `message-broker.<HOST>.nip.io`. |
| NAMESPACE | Namespace to be used within the minikube cluster. |

Set the following optional environment variables for further configuration:

| ENV VAR | DESCRIPTION |
|---------|-------------|
| HUB_BASE_URL | Base URL of the central side (hub). Defaults to `https://api.privateaim.net`. |
| HUB_AUTH_BASE_URL | Base URL of the central side's (hub) auth provider. Defaults to `https://auth.privateaim.net`. |

After that simply call the script with:
```shell
./deploy-to-minikube
```
124 changes: 124 additions & 0 deletions k8s/deploy-to-minikube.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#!/usr/bin/env bash

# Mandatory environment variables:
#
# - AUTH_JWKS_URL
# - HUB_AUTH_ROBOT_ID
# - ROBOT_SECRET
# - NODE_MESSAGE_BROKER_HOST
# - NAMESPACE

# Optional environment variables:
#
# - HUB_AUTH_BASE_URL
# - HUB_BASE_URL

BASE_DIR="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 || exit 1 ; pwd -P )"

if [[ -z "${AUTH_JWKS_URL}" || -z "${HUB_AUTH_ROBOT_ID}" || -z "${ROBOT_SECRET}" || -z "${NODE_MESSAGE_BROKER_HOST}" || -z "${NAMESPACE}" ]]; then
echo "One or more mandatory environment variables are not set!"
echo "Mandatory environment variables are:"
echo ""
echo " - AUTH_JWKS_URL"
echo " - HUB_AUTH_ROBOT_ID"
echo " - ROBOT_SECRET"
echo " - NODE_MESSAGE_BROKER_HOST"
echo " - NAMESPACE"
exit 1
fi

echo -n "Creating temporary working directory..."
WORK_DIR=`mktemp -d -p "${BASE_DIR}"`
if [ $? -ne 0 ]; then
echo "FAILED"
exit 2
else
echo "OK"
fi

echo -n "Copying k8s manifest files..."
for f in "${BASE_DIR}"/manifests/*.yml; do
cp "${f}" "${WORK_DIR}"
done
if [ $? -ne 0 ]; then
echo "FAILED"
exit 3
else
echo "OK"
fi

echo -n "Preparing broker deployment..."
sed -i -e "s#<AUTH_JWKS_URL>#${AUTH_JWKS_URL}#" \
-e "s#<HUB_AUTH_ROBOT_ID>#${HUB_AUTH_ROBOT_ID}#" \
-e "s#<HUB_AUTH_BASE_URL>#${HUB_AUTH_BASE_URL:-"https://auth.privateaim.net"}#" \
-e "s#<HUB_BASE_URL>#${HUB_BASE_URL:-"https://api.privateaim.net"}#" \
"${WORK_DIR}/broker-deployment.yml"
if [ $? -ne 0 ]; then
echo "FAILED"
exit 4
else
echo "OK"
fi

echo -n "Preparing hub auth secret..."
sed -i -e "s#<ROBOT_SECRET>#$(echo -n ${ROBOT_SECRET} | base64)#" \
"${WORK_DIR}/hub-auth-secret.yml"
if [ $? -ne 0 ]; then
echo "FAILED"
exit 5
else
echo "OK"
fi

echo -n "Preparing ingress..."
sed -i -e "s#<NODE_MESSAGE_BROKER_HOST>#${NODE_MESSAGE_BROKER_HOST}#" \
"${WORK_DIR}/ingress.yml"
if [ $? -ne 0 ]; then
echo "FAILED"
exit 6
else
echo "OK"
fi


echo -n "Deleting previous image..."
minikube image rm docker.io/flame/node-message-broker:latest >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "FAILED"
exit 7
else
echo "OK"
fi

echo -n "Creating Docker image..."
minikube image build -t docker.io/flame/node-message-broker:latest "${BASE_DIR}/.." >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "FAILED"
exit 8
else
echo "OK"
fi

echo -n "Applying manifest files..."
# TODO: make namespace adjustable!!!
minikube kubectl -- --namespace "${NAMESPACE}" apply -f "${WORK_DIR}/hub-auth-secret.yml" \
-f "${WORK_DIR}/broker-db-service.yml" \
-f "${WORK_DIR}/broker-db-statefulset.yml" \
-f "${WORK_DIR}/broker-service.yml" \
-f "${WORK_DIR}/broker-deployment.yml" \
-f "${WORK_DIR}/ingress.yml" >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "FAILED"
exit 9
else
echo "OK"
fi

echo -n "Deleting temporary working directory..."
rm -Rf "${WORK_DIR}"
if [ $? -ne 0 ]; then
echo "FAILED"
exit 10
else
echo "OK"
fi
12 changes: 12 additions & 0 deletions k8s/manifests/broker-db-service.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: v1
kind: Service
metadata:
name: node-message-broker-db
spec:
selector:
app.kubernetes.io/name: node-message-broker
app.kubernetes.io/component: database
app.kubernetes.io/part-of: flame
ports:
- port: 27017
targetPort: 27017
85 changes: 85 additions & 0 deletions k8s/manifests/broker-db-statefulset.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: node-message-broker-db
labels:
app.kubernetes.io/name: node-message-broker
app.kubernetes.io/component: database
app.kubernetes.io/part-of: flame
spec:
serviceName: "node-message-broker-db"
updateStrategy:
rollingUpdate:
maxUnavailable: 0
selector:
matchLabels:
app.kubernetes.io/name: node-message-broker
app.kubernetes.io/component: database
app.kubernetes.io/part-of: flame
replicas: 1
template:
metadata:
labels:
app.kubernetes.io/name: node-message-broker
app.kubernetes.io/component: database
app.kubernetes.io/part-of: flame
spec:
restartPolicy: "Always"
containers:
- name: node-message-broker-db
image: mongo:7.0.5@sha256:fcde2d71bf00b592c9cabab1d7d01defde37d69b3d788c53c3bc7431b6b15de8
securityContext:
runAsNonRoot: true
runAsUser: 1000
allowPrivilegeEscalation: false
ports:
- containerPort: 27017
env:
- name: MONGO_INITDB_DATABASE
value: "message-broker"
- name: TZ
value: "Europe/Berlin"
resources:
requests:
memory: "256Mi"
limits:
memory: "1Gi"
cpu: "1"
readinessProbe:
exec:
command:
- mongosh
- --eval
- 'db.runCommand("ping").ok'
- --quiet
failureThreshold: 3
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 15
initialDelaySeconds: 30
livenessProbe:
exec:
command:
- mongosh
- --eval
- 'db.runCommand("ping").ok'
- --quiet
failureThreshold: 3
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 15

volumeMounts:
- name: storage
mountPath: /data/db
volumeClaimTemplates:
- metadata:
name: storage
spec:
accessModes: ["ReadWriteMany"]
# We are not using this to make use of the default storage class
# This however, should be changed in the future.
# storageClassName:
resources:
requests:
storage: 100Mi
75 changes: 75 additions & 0 deletions k8s/manifests/broker-deployment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: node-message-broker
labels:
app.kubernetes.io/name: node-message-broker
app.kubernetes.io/component: server
app.kubernetes.io/part-of: flame
spec:
revisionHistoryLimit: 3
selector:
matchLabels:
app.kubernetes.io/name: node-message-broker
app.kubernetes.io/component: server
app.kubernetes.io/part-of: flame
template:
metadata:
labels:
app.kubernetes.io/name: node-message-broker
app.kubernetes.io/component: server
app.kubernetes.io/part-of: flame
spec:
restartPolicy: "Always"
containers:
- name: node-message-broker
image: docker.io/flame/node-message-broker:latest
imagePullPolicy: "IfNotPresent"
securityContext:
runAsNonRoot: true
runAsUser: 1000
allowPrivilegeEscalation: false
ports:
- containerPort: 8080
env:
- name: SERVER_PORT
value: "8080"
- name: AUTH_JWKS_URL
value: <AUTH_JWKS_URL>
- name: MONGO_DB_URL
value: "mongodb://node-message-broker-db:27017"
- name: MONGO_DB_NAME
value: "message-broker"
- name: HUB_BASE_URL
value: <HUB_BASE_URL>
- name: HUB_AUTH_BASE_URL
value: <HUB_AUTH_BASE_URL>
- name: HUB_AUTH_ROBOT_ID
value: <HUB_AUTH_ROBOT_ID>
- name: HUB_AUTH_ROBOT_SECRET
valueFrom:
secretKeyRef:
name: hub-auth
key: robot-secret
# DO NOT USE THIS IN PRODUCTION!!! This is just for internal testing purposes.
- name: NODE_TLS_REJECT_UNAUTHORIZED
value: "0"
resources:
requests:
memory: "256Mi"
limits:
memory: "512Mi"
cpu: "500m"
readinessProbe:
httpGet:
path: "/health"
port: 8080
initialDelaySeconds: 60
periodSeconds: 5
timeoutSeconds: 10
livenessProbe:
httpGet:
path: "/health"
port: 8080
periodSeconds: 10
timeoutSeconds: 10
12 changes: 12 additions & 0 deletions k8s/manifests/broker-service.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: v1
kind: Service
metadata:
name: node-message-broker
spec:
selector:
app.kubernetes.io/name: node-message-broker
app.kubernetes.io/component: server
app.kubernetes.io/part-of: flame
ports:
- port: 80
targetPort: 8080
6 changes: 6 additions & 0 deletions k8s/manifests/hub-auth-secret.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: v1
kind: Secret
metadata:
name: hub-auth
data:
robot-secret: <ROBOT_SECRET>
Loading

0 comments on commit 48758aa

Please sign in to comment.