Skip to content
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

feat: Add www.iab.org K8s configuration #477

Merged
merged 23 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
2fc9ce8
chore: Use k8s/ietfweb as a base for k8s/iabweb
microamp Jul 17, 2024
ce80e80
chore: Change prefix for environment variables to IABWWW_
microamp Jul 17, 2024
5d69728
chore: Set iabweb as default database name
microamp Jul 17, 2024
7275ac0
chore: Update domain in email settings to iab.org
microamp Jul 17, 2024
4d0c56c
chore: Change prefix for environment variables to IABWWW_ (cont)
microamp Jul 17, 2024
6fed3ac
chore: Update domain for IABWWW_ALLOWED_HOSTS
microamp Jul 17, 2024
6ac9f55
chore: Change K8s namespace to iabwww
microamp Jul 17, 2024
e54eee5
chore: Remove custom nginx config for www.ietf.org
microamp Jul 17, 2024
bc6b238
chore: Change CONTAINER_ROLE to iabweb
microamp Jul 17, 2024
a828710
chore: Update placeholder for IABWWW_DJANGO_SECRET_KEY
microamp Jul 17, 2024
bffa304
chore: Remove volumes not needed
microamp Jul 17, 2024
2fe85b3
chore: Update value of IABWWW_CSRF_TRUSTED_ORIGINS (commented out)
microamp Jul 17, 2024
9c821fc
chore: Add www-tmp volume
microamp Jul 18, 2024
1def680
chore: Remove volume mount for dt-vol
microamp Jul 18, 2024
ebcc357
chore: Use different memcached key prefix for iabweb
microamp Jul 29, 2024
3579162
chore: Use External Secrets for iabweb
microamp Jul 29, 2024
ec4cb8e
chore: Allocate less memory to memcached for iabweb
microamp Jul 29, 2024
5d169ff
chore: Apply iabwww- prefix to volume and config map names
microamp Aug 1, 2024
c80fab1
chore: Remove iabwww- prefix from config map
microamp Aug 1, 2024
987d720
chore: Clean up config map
microamp Aug 1, 2024
ff13e64
chore: Remove placeholder for secret key from config map
microamp Aug 1, 2024
61b2de4
chore: Add secrets.yaml (placeholders)
microamp Aug 2, 2024
773fcd3
chore: Remove config map in favour of external secret
microamp Aug 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions k8s/iabweb/django-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: django-config
data:
IABWWW_ADMINS: |-
Robert Sparks <[email protected]>
Kesara Rathnayake <[email protected]>
IABWWW_ALLOWED_HOSTS: ".iab.org" # newline-separated list also allowed

IABWWW_DJANGO_SECRET_KEY: "E6a_yN@bE0-Wu5XyNb=qJT.1+>InMuUD!-zYX01t.%qp>~O*?" # secret


# IABWWW_MATOMO_SITE_ID: "1" # must be present to enable Matomo
# IABWWW_MATOMO_DOMAIN_PATH: "analytics.ietf.org"

# use this to override default - one entry per line
# IABWWW_CSRF_TRUSTED_ORIGINS: |-
# https://www.staging.iab.org
13 changes: 13 additions & 0 deletions k8s/iabweb/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace: iabwww
namePrefix: iabwww-
configMapGenerator:
- name: files-cfgmap
files:
- local.py
- supervisord.conf
- nginx-default.conf
- nginx.conf
resources:
- django-config.yaml
- memcached.yaml
- wagtail.yaml
111 changes: 111 additions & 0 deletions k8s/iabweb/local.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Copyright The IETF Trust 2007-2024, All Rights Reserved
# -*- coding: utf-8 -*-

from email.utils import parseaddr
import os

def _multiline_to_list(s):
"""Helper to split at newlines and conver to list"""
return [item.strip() for item in s.split("\n")]


DEFAULT_FROM_EMAIL = "[email protected]"
SERVER_EMAIL = "[email protected]"
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST = os.environ.get("IABWWW_EMAIL_HOST", "localhost")
EMAIL_PORT = int(os.environ.get("IABWWW_EMAIL_PORT", "2025"))

# Secrets
_SECRET_KEY = os.environ.get("IABWWW_DJANGO_SECRET_KEY", None)
if _SECRET_KEY is not None:
SECRET_KEY = _SECRET_KEY
else:
raise RuntimeError("IABWWW_DJANGO_SECRET_KEY must be set")


_CSRF_TRUSTED_ORIGINS_STR = os.environ.get("IABWWW_CSRF_TRUSTED_ORIGINS", None)
if _CSRF_TRUSTED_ORIGINS_STR is not None:
CSRF_TRUSTED_ORIGINS = _multiline_to_list(_CSRF_TRUSTED_ORIGINS_STR)

FILE_UPLOAD_PERMISSIONS = 0o664
_WAGTAILADMIN_BASE_URL = os.environ.get("WAGTAILADMIN_BASE_URL", None)
if _WAGTAILADMIN_BASE_URL is not None:
WAGTAILADMIN_BASE_URL = _WAGTAILADMIN_BASE_URL
else:
raise RuntimeError("WAGTAILADMIN_BASE_URL must be present")

# Set DEBUG if IABWWW_DEBUG env var is the word "true"
DEBUG = os.environ.get("IABWWW_DEBUG", "false").lower() == "true"

# IABWWW_ALLOWED_HOSTS env var is a comma-separated list of allowed hosts
_ALLOWED_HOSTS_STR = os.environ.get("IABWWW_ALLOWED_HOSTS", None)
if _ALLOWED_HOSTS_STR is not None:
ALLOWED_HOSTS = _multiline_to_list(_ALLOWED_HOSTS_STR)

DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql_psycopg2",
"HOST": os.environ.get("IABWWW_DB_HOST", "db"),
"PORT": os.environ.get("IABWWW_DB_PORT", "5432"),
"NAME": os.environ.get("IABWWW_DB_NAME", "iabweb"),
"USER": os.environ.get("IABWWW_DB_USER", "django"),
"PASSWORD": os.environ.get("IABWWW_DB_PASS", ""),
"CONN_MAX_AGE": 600, # number of seconds database connections should persist for
},
}

# IABWWW_ADMINS is a newline-delimited list of addresses parseable by email.utils.parseaddr
_admins_str = os.environ.get("IABWWW_ADMINS", None)
if _admins_str is not None:
ADMINS = [parseaddr(admin) for admin in _multiline_to_list(_admins_str)]
else:
raise RuntimeError("IABWWW_ADMINS must be set")

# Leave IABWWW_MATOMO_SITE_ID unset to disable Matomo reporting
if "IABWWW_MATOMO_SITE_ID" in os.environ:
MATOMO_DOMAIN_PATH = os.environ.get("IABWWW_MATOMO_DOMAIN_PATH", "analytics.ietf.org")
MATOMO_SITE_ID = os.environ.get("IABWWW_MATOMO_SITE_ID", None)
MATOMO_DISABLE_COOKIES = True

# Duplicating production cache from settings.py and using it whether we're in production mode or not
MEMCACHED_HOST = os.environ.get("IABWWW_MEMCACHED_SERVICE_HOST", "127.0.0.1")
MEMCACHED_PORT = os.environ.get("IABWWW_MEMCACHED_SERVICE_PORT", "11211")
MEMCACHED_KEY_PREFIX = "ietf"
CACHES = {
"default": {
"BACKEND": "django.core.cache.backends.memcached.PyMemcacheCache",
"LOCATION": f"{MEMCACHED_HOST}:{MEMCACHED_PORT}",
"KEY_PREFIX": MEMCACHED_KEY_PREFIX,
},
"sessions": {
"BACKEND": "django.core.cache.backends.memcached.PyMemcacheCache",
"LOCATION": f"{MEMCACHED_HOST}:{MEMCACHED_PORT}",
"KEY_PREFIX": MEMCACHED_KEY_PREFIX,
},
"dummy": {"BACKEND": "django.core.cache.backends.dummy.DummyCache"},
}

# Logging

LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"handlers": {
"mail_admins": {
"level": "ERROR",
"class": "django.utils.log.AdminEmailHandler",
},
},
"loggers": {
"django.request": {
"handlers": ["mail_admins"],
"level": "ERROR",
"propagate": False,
},
"django.security": {
"handlers": ["mail_admins"],
"level": "ERROR",
"propagate": False,
},
},
}
74 changes: 74 additions & 0 deletions k8s/iabweb/memcached.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: memcached
spec:
replicas: 1
revisionHistoryLimit: 2
selector:
matchLabels:
app: memcached
template:
metadata:
labels:
app: memcached
spec:
securityContext:
runAsNonRoot: true
containers:
- image: "quay.io/prometheus/memcached-exporter:v0.14.3"
imagePullPolicy: IfNotPresent
name: memcached-exporter
ports:
- name: metrics
containerPort: 9150
protocol: TCP
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsUser: 65534 # nobody
runAsGroup: 65534 # nobody
- image: "memcached:1.6-alpine"
imagePullPolicy: IfNotPresent
args: ["-m", "1024"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it actually need 1GB? Consider using a smaller value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reduced to 256 MB.

name: memcached
ports:
- name: memcached
containerPort: 11211
protocol: TCP
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
# memcached image sets up uid/gid 11211
runAsUser: 11211
runAsGroup: 11211
dnsPolicy: ClusterFirst
restartPolicy: Always
terminationGracePeriodSeconds: 30
---
apiVersion: v1
kind: Service
metadata:
name: memcached
annotations:
k8s.grafana.com/scrape: "true" # this is not a bool
k8s.grafana.com/metrics.portName: "metrics"
spec:
type: ClusterIP
ports:
- port: 11211
targetPort: memcached
protocol: TCP
name: memcached
- port: 9150
targetPort: metrics
protocol: TCP
name: metrics
selector:
app: memcached
32 changes: 32 additions & 0 deletions k8s/iabweb/nginx-default.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
server {
listen 8080 default_server;
listen [::]:8080 default_server;
server_name _;
gzip on;
access_log /dev/stdout;
error_log /dev/stdout warn;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $${keepempty}host;
proxy_set_header X-Forwarded-For $${keepempty}proxy_add_x_forwarded_for;
}
location /media/ {
alias /app/media/;

error_page 404 = @error_redirect;
}
location /static/ {
alias /app/static/;

error_page 404 = @error_redirect;
}
location /robots.txt {
add_header Content-Type text/plain;
return 200 "User-agent: *\nDisallow: /admin/\n";
}
location @error_redirect {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $${keepempty}host;
proxy_set_header X-Forwarded-For $${keepempty}proxy_add_x_forwarded_for;
}
}
53 changes: 53 additions & 0 deletions k8s/iabweb/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
worker_processes auto;
pid /var/lib/nginx/nginx.pid;
error_log /dev/stdout;
include /etc/nginx/modules-enabled/*.conf;

events {
worker_connections 768;
# multi_accept on;
}

http {

##
# Basic Settings
##

sendfile on;
tcp_nopush on;
types_hash_max_size 2048;
# server_tokens off;

# server_names_hash_bucket_size 64;
# server_name_in_redirect off;

include /etc/nginx/mime.types;
default_type application/octet-stream;

##
# SSL Settings
##

ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;

##
# Logging Settings
##

access_log /dev/stdout;

##
# Gzip Settings
##

gzip on;

##
# Virtual Host Configs
##

include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
17 changes: 17 additions & 0 deletions k8s/iabweb/supervisord.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[supervisord]
nodaemon=true
logfile=/dev/stdout
logfile_maxbytes=0

[program:nginx]
command=nginx -g "daemon off;"
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
redirect_stderr=true

[program:gunicorn]
command=/usr/local/bin/gunicorn --config /app/docker/gunicorn.py ietf.wsgi
directory=/app
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
redirect_stderr=true
Loading
Loading