Skip to content

Commit

Permalink
Frontend + Backend Integrated Deployment (K8s only) (#45)
Browse files Browse the repository at this point in the history
* support running backend + frontend together on k8s
* split nginx container into separate frontend service, which uses nignx-base image and the static frontend files
* add nginx-based frontend image to docker-compose build (for building only, docker-based combined deployment not yet supported)

* backend:
- fix paths for email templates
- chart: support '--set backend_only=1' and '--set frontend_only=1' to only force deploy one or the other
- run backend from root /api in uvicorn
  • Loading branch information
ikreymer committed Dec 3, 2021
1 parent 87bef6d commit 05c1129
Show file tree
Hide file tree
Showing 12 changed files with 227 additions and 58 deletions.
2 changes: 1 addition & 1 deletion backend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ RUN pip install -r requirements.txt

ADD . /app

CMD uvicorn main:app --host 0.0.0.0 --reload --access-log --log-level debug
CMD uvicorn main:app --host 0.0.0.0 --root-path /api --reload --access-log --log-level debug

4 changes: 2 additions & 2 deletions backend/emailsender.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def send_user_validation(self, receiver_email, token):
message = f"""
Please verify your registration for Browsertrix Cloud for {receiver_email}
You can verify by clicking here: {self.host}/app/verify/{token}
You can verify by clicking here: {self.host}/verify?token={token}
The verification token is: {token}"""

Expand All @@ -49,7 +49,7 @@ def send_new_user_invite(self, receiver_email, sender, archive_name, token):
message = f"""
You are invited by {sender} to join their archive, {archive_name} on Browsertrix Cloud!
You can join by clicking here: {self.host}/app/join/{token}
You can join by clicking here: {self.host}/join/{token}?email={receiver_email}
The invite token is: {token}"""

Expand Down
1 change: 1 addition & 0 deletions chart/.helmignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@
.idea/
*.tmproj
.vscode/
frontend/
6 changes: 4 additions & 2 deletions chart/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,10 @@ http {
}

location / {
proxy_pass http://localhost:8000/;
proxy_set_header Host $host;
#proxy_pass http://localhost:8000/;
#proxy_set_header Host $host;
root /usr/share/nginx/html;
index index.html index.htm;
}
}
}
Expand Down
66 changes: 16 additions & 50 deletions chart/templates/main.yaml → chart/templates/backend.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,28 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.name }}
name: {{ .Values.name }}-backend
namespace: {{ .Release.Namespace }}

spec:
selector:
matchLabels:
app: {{ .Values.name }}
role: backend
replicas: {{ .Values.api_num_replicas }}
template:
metadata:
labels:
app: {{ .Values.name }}
role: backend

annotations:
# force helm to update the deployment each time
{{- if not .Values.frontend_only }}
"helm.update": {{ randAlphaNum 5 | quote }}
{{- end }}

spec:
volumes:
- name: nginx-config
configMap:
name: nginx-config
items:
- key: nginx.conf
path: nginx.conf

- name: nginx-resolver
emptyDir: {}

initContainers:
{{- if .Values.minio_local }}
- name: init-bucket
Expand All @@ -47,42 +40,8 @@ spec:
args: ['-c', 'mc mb --ignore-existing local/{{ .Values.minio_local_bucket_name }}' ]
{{- end }}

- name: init-nginx
image: {{ .Values.nginx_image }}
command: ["/bin/sh"]
args: ["-c", "echo resolver $(awk 'BEGIN{ORS=\" \"} $1==\"nameserver\" {print $2}' /etc/resolv.conf) valid=30s \";\" > /etc/nginx/resolvers/resolvers.conf"]
volumeMounts:
- name: nginx-resolver
mountPath: /etc/nginx/resolvers/


containers:
- name: nginx
image: {{ .Values.nginx_image }}
imagePullPolicy: {{ .Values.nginx_pull_policy }}
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
readOnly: true

- name: nginx-resolver
mountPath: /etc/nginx/resolvers/
readOnly: true

resources:
limits:
cpu: {{ .Values.nginx_limit_cpu }}

requests:
cpu: {{ .Values.nginx_requests_cpu }}

readinessProbe:
httpGet:
path: /healthz
port: 80


- name: api
image: {{ .Values.api_image }}
imagePullPolicy: {{ .Values.api_pull_policy }}
Expand All @@ -101,6 +60,13 @@ spec:
cpu: {{ .Values.api_requests_cpu }}
memory: {{ .Values.api_requests_memory }}

startupProbe:
httpGet:
path: /healthz
port: 8000
failureThreshold: 30
periodSeconds: 5

readinessProbe:
httpGet:
path: /healthz
Expand All @@ -112,9 +78,10 @@ kind: Service

metadata:
namespace: {{ .Release.Namespace }}
name: {{ .Values.name }}
name: {{ .Values.name }}-backend
labels:
app: {{ .Values.name }}
role: backend

{{- if .Values.service }}
{{- if .Values.service.annotations }}
Expand All @@ -128,6 +95,7 @@ metadata:
spec:
selector:
app: {{ .Values.name }}
role: backend

{{- if .Values.service }}
{{- if .Values.service.type }}
Expand All @@ -137,7 +105,5 @@ spec:

ports:
- protocol: TCP
port: 80
port: 8000
name: api
#externalIPs:
# - 127.0.0.1
3 changes: 3 additions & 0 deletions chart/templates/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,6 @@ metadata:

data:
{{ (.Files.Glob "*.conf").AsConfig | indent 2 }}

#{{ (.Files.Glob "frontend/*.*").AsConfig | indent 2 }}

99 changes: 99 additions & 0 deletions chart/templates/frontend.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.name }}-frontend
namespace: {{ .Release.Namespace }}

spec:
selector:
matchLabels:
app: {{ .Values.name }}
role: frontend
replicas: 1
template:
metadata:
labels:
app: {{ .Values.name }}
role: frontend

annotations:
# force helm to update the deployment each time
{{- if not .Values.backend_only }}
"helm.update": {{ randAlphaNum 5 | quote }}
{{- end }}


spec:
volumes:
- name: nginx-resolver
emptyDir: {}

initContainers:
- name: init-nginx
image: {{ .Values.nginx_image }}
command: ["/bin/sh"]
args: ["-c", "echo resolver $(awk 'BEGIN{ORS=\" \"} $1==\"nameserver\" {print $2}' /etc/resolv.conf) valid=30s \";\" > /etc/nginx/resolvers/resolvers.conf"]
volumeMounts:
- name: nginx-resolver
mountPath: /etc/nginx/resolvers/


containers:
- name: nginx
image: {{ .Values.nginx_image }}
imagePullPolicy: {{ .Values.nginx_pull_policy }}
volumeMounts:
- name: nginx-resolver
mountPath: /etc/nginx/resolvers/
readOnly: true

resources:
limits:
cpu: {{ .Values.nginx_limit_cpu }}

requests:
cpu: {{ .Values.nginx_requests_cpu }}

readinessProbe:
httpGet:
path: /healthz
port: 80

---

apiVersion: v1
kind: Service

metadata:
namespace: {{ .Release.Namespace }}
name: {{ .Values.name }}-frontend
labels:
app: {{ .Values.name }}
role: frontend

{{- if .Values.service }}
{{- if .Values.service.annotations }}
annotations:
{{- range $key, $val := .Values.service.annotations }}
{{ $key }}: {{ $val | quote }}
{{- end }}
{{- end }}
{{- end }}

spec:
selector:
app: {{ .Values.name }}
role: frontend

{{- if .Values.service }}
{{- if .Values.service.type }}
type: {{ .Values.service.type | quote }}
{{- end }}
{{- end }}

ports:
- protocol: TCP
port: 80
name: frontend

10 changes: 9 additions & 1 deletion chart/templates/ingress.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,19 @@ spec:
number: 9000
{{- end }}

- path: /api/(.*)
pathType: Prefix
backend:
service:
name: browsertrix-cloud-backend
port:
number: 8000

- path: /(.*)
pathType: Prefix
backend:
service:
name: browsertrix-cloud
name: browsertrix-cloud-frontend
port:
number: 80

Expand Down
6 changes: 6 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ services:
- minio
- mongo

frontend:
build: ./frontend
image: registry.digitalocean.com/btrix/webrecorder/browsertrix-frontend
ports:
- 8010:80

redis:
image: redis
command: redis-server --appendonly yes
Expand Down
6 changes: 6 additions & 0 deletions frontend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
FROM nginx

COPY ./index.html /usr/share/nginx/html
COPY ./dist/main.js /usr/share/nginx/html
COPY ./nginx.conf /etc/nginx/nginx.conf

78 changes: 78 additions & 0 deletions frontend/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
worker_processes 1;
error_log stderr;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /dev/stdout;
sendfile on;
keepalive_timeout 65;
include ./resolvers/resolvers.conf;
server {
listen 80 default_server;
server_name _;
proxy_buffering off;
proxy_buffers 16 64k;
proxy_buffer_size 64k;
root /usr/share/nginx/html;
index index.html index.htm;

error_page 500 501 502 503 504 /50x.html;

merge_slashes off;
location = /50x.html {
root /usr/share/nginx/html;
}

# fallback to index for any page
error_page 404 /index.html;

location ~* /watch/([^/]+)/([^/]+)/ws {
set $archive $1;
set $crawl $2;
#auth_request /authcheck;

proxy_pass http://$2.crawlers.svc.cluster.local:9037/ws;
proxy_set_header Host "localhost";

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
}

location ~* /watch/([^/]+)/([^/]+)/ {
set $archive $1;
set $crawl $2;
#auth_request /authcheck;

proxy_pass http://$2.crawlers.svc.cluster.local:9037/;
proxy_set_header Host "localhost";
}

location = /authcheck {
internal;
proxy_pass http://localhost:8000/archives/$archive/crawls/$crawl;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
}

location /healthz {
return 200;
}

location / {
#proxy_pass http://localhost:8000/;
#proxy_set_header Host $host;
root /usr/share/nginx/html;
index index.html index.htm;
}
}
}

Loading

0 comments on commit 05c1129

Please sign in to comment.