Deploying to Kubernetes
This page is part of the documentation for release V1.0. This documentation is outdated and V1.0 is no longer maintained. See index for the latest information.
Kubernetes, often abbreviated as K8s, is an open-source container orchestration platform used for automating the deployment, scaling, and management of containerized applications. With Kubernetes, you can set up a configuration file that automatically deploys the website's infrastructure in seconds.
Kubernetes is based on Docker, an open-source platform and a set of tools for creating, deploying, and managing containerized applications. To deploy the website on Kubernetes, you'll first need to build the website's container image.
Prerequisites
- Complete the Getting Started guide.
- Docker: build the website container image.
- Kubernetes Cluster & Kubectl: Use a cloud hosting platform or launch a Kubernetes node on Docker.
Building the Docker image
If you're using a SaaS/cloud solution, you'll need to upload the container image to your project's artifact registry.
Navigate to the source directory
cd Club_Website_2
Run docker build:
docker build --tag osc-website .
Configuring Kubernetes
You can deploy containers on Kubernetes using yaml files. Yaml is a file format similar to JSON, you can read more about it here. The website YAML file is documented below.
apiVersion: v1
kind: Secret
# The secrets here correspond to the website's environment variables.
# These are documented at https://docs.ufosc.org/docs/website/Developers/configuration
data:
secret: [YOU-SECRET-HERE]
smtp-user: [YOUR-SMTP-USER]
smtp-pass: [YOUR-SMPT-PASS]
captcha: [YOUR-CAPTCHA-KEY] # Optional
email: [YOUR-CONTACT-FORM-EMAIL]
metadata:
name: osc-website-secrets
labels:
app: osc-website
---
# A volume is a persistent store of data.
# This is the volume for the website database.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: osc-website-volume-db
labels:
app: osc-website
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
# The amount of persistent storage to allocate.
storage: 1Gi
---
# A deployment provides a declarative way to describe the desired state of
# an application. In this case, the desired state is to have at least 1
# replica of Mongodb and the OSC Website running on the node.
apiVersion: apps/v1
kind: Deployment
metadata:
name: osc-website
labels:
app: osc-website
spec:
# The replicas property specifies how many copies of this deployment
# to try to launch. Generally, more replicas mean the app scales to
# more users.
replicas: 1
selector:
matchLabels:
app: osc-website
template:
metadata:
labels:
app: osc-website
spec:
containers:
- name: mongodb
image: mongo
args: ["--dbpath", "/data/db"]
volumeMounts:
- name: osc-website-volume-db
mountPath: "/data/db/"
- name: club-website
# If you're using a cloud provider, you'll need to modify the image
# name to reference your artifact registry.
image: club-website:latest
# Environment variable configurations, as documented here:
# https://docs.ufosc.org/docs/website/Developers/configuration
env:
- name: MONGO_URI
value: "mongodb://127.0.0.1:27017"
- name: NODE_ENV
value: "production"
- name: RATE_LIMIT_MAX
value: "150"
- name: RATE_LIMIT_TIMEOUT
value: "1"
- name: SECRET
valueFrom:
secretKeyRef:
name: osc-website-secrets
key: secret
- name: SMTP_USER
valueFrom:
secretKeyRef:
name: osc-website-secrets
key: smtp-user
- name: SMTP_PASS
valueFrom:
secretKeyRef:
name: osc-website-secrets
key: smtp-pass
- name: ADMIN_EMAIL
valueFrom:
secretKeyRef:
name: osc-website-secrets
key: email
- name: CACHE_INTERVAL
value: "480"
- name: CAPTCHA_SECRET
valueFrom:
secretKeyRef:
name: osc-website-secrets
key: captcha
volumeMounts:
- name: osc-website-volume-uploads
mountPath: "/ufosc/app/uploads/"
volumes:
- name: osc-website-volume-db
- name: osc-website-volume-uploads
---
# A service exposes the 3002 port (default website port) of the osc-website
# deployment. If you're running Kubernetes locally and you specify a nodePort,
# the website will be accessible at http://localhost:nodePort.
apiVersion: v1
kind: Service
metadata:
name: osc-website-service
labels:
app: osc-website
spec:
type: NodePort
selector:
app: osc-website
ports:
- protocol: TCP
port: 3002
targetPort: 3002
# nodePort: 30000
---
# An ingress redirects traffic from your cluster's endpoint to
# port 3002 of the website deployment. It is generally not required
# in locally hosted environments.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: osc-website-ingress
labels:
app: osc-website
spec:
defaultBackend:
service:
name: osc-website-service
port:
number: 3002
Applying the YAML configuration
kubectl apply -f your_file.yml
If you're using a cloud platform, ensure that kubectl is configured to target your remote cluster.
GKE-specific resources
These options only apply to clusters managed by Google Kubernetes Engine (GKE).
Additional resources for Google Kubernetes engine.
# The ManagedCertificate resource instructs Google Cloud to
# generate and sign an SSL certificate for the specified domains.
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
name: osc-website-cert
labels:
app: osc-website
spec:
domains:
- ufosc.org
---
# The GKE FrontendConfig is configured to redirect non-HTTPS
# traffic to the HTTPS endpoint.
apiVersion: networking.gke.io/v1beta1
kind: FrontendConfig
metadata:
name: osc-website-fe-config
spec:
sslPolicy: gke-ingress-ssl-policy
redirectToHttps:
enabled: true
---
# Same as before, but metadata.annotations specifies which
# Google ingress controller, static IP, and certificate to
# deploy the site with.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: osc-website-ingress
labels:
app: osc-website
annotations:
kubernetes.io/ingress.class: "gce"
kubernetes.io/ingress.global-static-ip-name: oscwebsite
networking.gke.io/managed-certificates: osc-website-cert
networking.gke.io/v1beta1.FrontendConfig: osc-website-fe-config
spec:
defaultBackend:
service:
name: osc-website-service
port:
number: 3002
Static IP
The configuration above requires registering a static IP address. A static IP address makes deployment considerably easier, since the website won't have to be exposed on (volatile) node IP addresses.
See Google's documentation here.
SSL Ingress Policy
Additionally, the GKE configuration depends on a registered SSL ingress policy. SSL policies specify the set of SSL features that Google Cloud load balancers use when negotiating SSL with clients.
See Google's documentation here.
Creating an Admin
The Kubernetes config sets up the website with an empty database, which makes logging in to the site is impossible. This is solved by connecting to the Mongo container and calling mongosh to add the first user. This process should only be done once, additional admins can be added through the admin dashboard.
First, get a list of all pods
kubectl get pods
The command should respond with something like this:
NAME READY STATUS RESTARTS AGE
osc-website-c5986c5ff-zdbxk 2/2 Running 0 4h55m
You'll be connecting to one of the pods specified by the output of the kubectl get pods
command. Note down one of the pod names assosciated with the osc-website deployment (if you have multiple replicas, you can choose any pod just as long as its part of the osc-website deployment resource).
Connect using the following command (replace [YOUR-POD-NAME-HERE] with the pod name from above):
kubectl exec --stdin --tty [YOUR-POD-NAME-HERE] -- /bin/bash
Once connected, open the mongosh console by typing mongosh
. Then, paste the following:
use test
db.users.insertOne({"username": "admin","password": {"hash": "�a2O���w��\u0004��Ȳ��7\u000fM�2\u0011�<\u0015z\u0016\u0019E*��cЮ\u0010\u001e\u0015���ւ)�Ne��G�VH/��9�����q\u0003�\t��פ}���i��Y�\u00125��d3�V�\t6������W;�~���?A��\u001c��X8��/\u0012��\u0007)t��9\u0001<","salt": "4vRF0ZTMELWmPGMpAgy6hsiJm/pOUlgPYFk+faK+yaFv/x0+lITG+4kX/y5bXudjMdGWLN2PV8UhH5s5dRLPaGgh2qwrbocDqEdyvbqSqVPAQxKIwFSytoRySYfKZJdCgK970UmrPDyGmoAIRZ/DN8YZ4fTirkSAeRlTWLSbyfg="},"fullName": "admin","role": "admin","isAdmin": true,"date": {"$date": "2023-09-17T15:53:18.529Z"},"__v": 0})
The command above adds a user with the username admin
and password 123456
. You should now reset the admin's password using the admin dashboard as soon as possible to prevent attackers from logging in with the default credentials. Resetting the password through the admin dashboard should reset the password salt as well.
Finally, type exit
and press enter to exit the mongosh console. Type exit
and press enter once again to close the connection to the pod.