From 3e118b59063fdee5c31a900c927a165f4a337a4c Mon Sep 17 00:00:00 2001 From: "Hugo \"ThePooN\" Denizart" Date: Fri, 23 Jul 2021 01:58:29 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20initial=20Helm=20chart?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile.deployment | 4 +- deploy.sh | 1 + docker-compose.deployment.yml | 95 ++++++++ docker/deployment/entrypoint.sh | 42 +++- docker/deployment/sudoers | 1 + docker/deployment/symlink-k8s-env.sh | 4 + osu-web-chart/.helmignore | 23 ++ osu-web-chart/Chart.yaml | 24 ++ osu-web-chart/templates/NOTES.txt | 22 ++ osu-web-chart/templates/_helpers.tpl | 62 +++++ osu-web-chart/templates/deployment.yaml | 97 ++++++++ osu-web-chart/templates/hpa.yaml | 28 +++ osu-web-chart/templates/ingress.yaml | 41 ++++ osu-web-chart/templates/secret.yaml | 148 ++++++++++++ osu-web-chart/templates/service.yaml | 15 ++ osu-web-chart/templates/serviceaccount.yaml | 12 + osu-web-chart/templates/shared-secret.yaml | 39 +++ osu-web-chart/values.yaml | 254 ++++++++++++++++++++ 18 files changed, 908 insertions(+), 4 deletions(-) create mode 100644 docker-compose.deployment.yml create mode 100644 docker/deployment/sudoers create mode 100755 docker/deployment/symlink-k8s-env.sh create mode 100644 osu-web-chart/.helmignore create mode 100644 osu-web-chart/Chart.yaml create mode 100644 osu-web-chart/templates/NOTES.txt create mode 100644 osu-web-chart/templates/_helpers.tpl create mode 100644 osu-web-chart/templates/deployment.yaml create mode 100644 osu-web-chart/templates/hpa.yaml create mode 100644 osu-web-chart/templates/ingress.yaml create mode 100644 osu-web-chart/templates/secret.yaml create mode 100644 osu-web-chart/templates/service.yaml create mode 100644 osu-web-chart/templates/serviceaccount.yaml create mode 100644 osu-web-chart/templates/shared-secret.yaml create mode 100644 osu-web-chart/values.yaml diff --git a/Dockerfile.deployment b/Dockerfile.deployment index bfb6bd30dd6..3c6857bc826 100644 --- a/Dockerfile.deployment +++ b/Dockerfile.deployment @@ -30,7 +30,8 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get install -y \ unit \ unit-php \ yarnpkg \ - zip + zip \ + sudo WORKDIR /app @@ -41,6 +42,7 @@ COPY package.json yarn.lock ./ RUN yarnpkg COPY . . +RUN cp /app/docker/deployment/sudoers /etc/sudoers RUN mkdir -p bootstrap/cache storage/framework/views storage/framework/sessions RUN composer dump-autoload diff --git a/deploy.sh b/deploy.sh index ba28c4e6890..ad0115cce2c 100755 --- a/deploy.sh +++ b/deploy.sh @@ -12,6 +12,7 @@ ln -snf "$outdir" "/deploy/current" cd "$outdir" +# if debug is enabled if [ ! "${APP_DEBUG:-false}" = "true" ] then php artisan config:cache diff --git a/docker-compose.deployment.yml b/docker-compose.deployment.yml new file mode 100644 index 00000000000..1ee63929a62 --- /dev/null +++ b/docker-compose.deployment.yml @@ -0,0 +1,95 @@ +version: '3.4' + +x-env: &x-env + APP_ENV: production + BROADCAST_DRIVER: redis + CACHE_DRIVER: redis + DB_HOST: 172.17.0.1 + ES_HOST: elasticsearch:9200 + ES_SCORES_HOST: elasticsearch:9200 + GITHUB_TOKEN: "${GITHUB_TOKEN}" + NOTIFICATION_REDIS_HOST: 172.17.0.1 + REDIS_HOST: 172.17.0.1 + CACHE_REDIS_HOST: 172.17.0.1 + SESSION_DRIVER: redis + NOTIFICATION_ENDPOINT: ws://localhost:2345 + +x-web: &x-web + image: pppy/osu-web:latest + build: + context: . + dockerfile: Dockerfile.deployment + args: + APP_URL: http://localhost:${NGINX_PORT:-8000} + DOCS_URL: https://docs.ppy.sh + PAYMENT_SANDBOX: "true" + SHOPIFY_DOMAIN: notarealdomainortld + SHOPIFY_STOREFRONT_TOKEN: notreal + GIT_SHA: latest + environment: + <<: *x-env + env_file: .env + +services: + nginx-unit: + <<: *x-web + volumes: + - ./storage:/app/storage + - ./public/uploads:/app/public/uploads + - ./public/uploads-avatar:/app/public/uploads-avatar + ports: + - "${NGINX_PORT:-8000}:8000" + command: ['nginx'] + + job: + <<: *x-web + command: ['artisan', 'queue:work', '--queue=beatmap_default,beatmap_high,default,notification,store-notifications', '--tries=3', '--timeout=1000'] + + schedule: + <<: *x-web + command: ['schedule'] + + notification-server: + image: pppy/osu-notification-server + depends_on: + - redis + - db + volumes: + - .env:/app/.env + - ./storage/oauth-public.key:/app/oauth-public.key + ports: + - 2345:2345 + environment: + <<: *x-env + env_file: .env + + db: + image: mysql:8.0 + volumes: + - database:/var/lib/mysql + - ./bin/db_setup.sh:/docker-entrypoint-initdb.d/db_setup.sh + - ./docker/development/db_user.sql:/docker-entrypoint-initdb.d/db_user.sql + environment: + <<: *x-env + MYSQL_ALLOW_EMPTY_PASSWORD: "yes" + MYSQL_ONETIME_PASSWORD: "yes" + ports: + - "${MYSQL_EXTERNAL_PORT:-3306}:3306" + command: --default-authentication-plugin=mysql_native_password + + redis: + image: redis:latest + + elasticsearch: + # Version must be kept up to date with library defined in: composer.json + image: docker.elastic.co/elasticsearch/elasticsearch-oss:6.8.12 + volumes: + - elasticsearch:/usr/share/elasticsearch/data + environment: + action.auto_create_index: "false" + discovery.type: single-node + cluster.routing.allocation.disk.threshold_enabled: "false" + +volumes: + database: + elasticsearch: diff --git a/docker/deployment/entrypoint.sh b/docker/deployment/entrypoint.sh index c558ae384b2..e6a4542e865 100755 --- a/docker/deployment/entrypoint.sh +++ b/docker/deployment/entrypoint.sh @@ -10,6 +10,8 @@ _nginx() { # exit on config update fail set -e + echo "starting nginx unit" + # start NGINX Unit touch /home/osuweb/unit/unit.pid exec unitd \ @@ -20,25 +22,58 @@ _nginx() { --no-daemon & PID=$! + echo "clearing laravel cache" + + /app/artisan config:cache + /app/artisan route:cache + # wait for NGINX Unit control socket to be open - inotifywait -e create,open /home/osuweb/unit + if [ ! -d /home/osuweb/unit/control.unit.sock ]; then + echo "awaiting for nginx unit socket to be open" + inotifywait -e create,open /home/osuweb/unit -t 2 || true + fi + echo "updating nginx unit config" # update config curl \ + -s \ -X PUT \ --data-binary @/app/docker/deployment/nginx-unit.json \ --unix-socket /home/osuweb/unit/control.unit.sock \ - http://localhost/config + http://localhost/config 2>&1 > /dev/null + echo "applying env vars" # update environment variables jq -n env | curl \ + -s \ -X PUT \ --data-binary @- \ --unix-socket /home/osuweb/unit/control.unit.sock \ - http://localhost/config/applications/laravel/environment + http://localhost/config/applications/laravel/environment 2>&1 > /dev/null + echo "spawning config reloader" + /app/docker/deployment/entrypoint.sh config_reloader & + CONFIG_RELOADER_PID=$! + + echo "init done" # keep running this script until NGINX Unit ends wait $PID + + echo "nginx exit $?" + + # kill child processes (config reloader) + pkill -TERM -P $$ +} + +_config_reloader() { + while true; do + echo "Awaiting config update on .env..." + inotifywait -e modify .env + + echo "Reloading config..." + /app/artisan config:cache + /app/artisan route:cache + done } _php() { @@ -59,5 +94,6 @@ case "$command" in nginx) _nginx;; php) _php;; schedule) _schedule;; + config_reloader) _config_reloader;; *) exec "$command" "$@";; esac diff --git a/docker/deployment/sudoers b/docker/deployment/sudoers new file mode 100644 index 00000000000..6af01517583 --- /dev/null +++ b/docker/deployment/sudoers @@ -0,0 +1 @@ +osuweb ALL=(ALL) NOPASSWD: /app/docker/deployment/symlink-k8s-env.sh diff --git a/docker/deployment/symlink-k8s-env.sh b/docker/deployment/symlink-k8s-env.sh new file mode 100755 index 00000000000..80c0ef5b868 --- /dev/null +++ b/docker/deployment/symlink-k8s-env.sh @@ -0,0 +1,4 @@ +#!/bin/sh +set +e + +ln -s /var/env-secret/.env /app/.env diff --git a/osu-web-chart/.helmignore b/osu-web-chart/.helmignore new file mode 100644 index 00000000000..0e8a0eb36f4 --- /dev/null +++ b/osu-web-chart/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/osu-web-chart/Chart.yaml b/osu-web-chart/Chart.yaml new file mode 100644 index 00000000000..7920a1bf2e4 --- /dev/null +++ b/osu-web-chart/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: osu-web-chart +description: production osu!web deployment in Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: 0.1.0 diff --git a/osu-web-chart/templates/NOTES.txt b/osu-web-chart/templates/NOTES.txt new file mode 100644 index 00000000000..d92d474386c --- /dev/null +++ b/osu-web-chart/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "osu-web-chart.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "osu-web-chart.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "osu-web-chart.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "osu-web-chart.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/osu-web-chart/templates/_helpers.tpl b/osu-web-chart/templates/_helpers.tpl new file mode 100644 index 00000000000..6d96d951e81 --- /dev/null +++ b/osu-web-chart/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "osu-web-chart.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "osu-web-chart.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "osu-web-chart.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "osu-web-chart.labels" -}} +helm.sh/chart: {{ include "osu-web-chart.chart" . }} +{{ include "osu-web-chart.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "osu-web-chart.selectorLabels" -}} +app.kubernetes.io/name: {{ include "osu-web-chart.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "osu-web-chart.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "osu-web-chart.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/osu-web-chart/templates/deployment.yaml b/osu-web-chart/templates/deployment.yaml new file mode 100644 index 00000000000..675275a31a8 --- /dev/null +++ b/osu-web-chart/templates/deployment.yaml @@ -0,0 +1,97 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "osu-web-chart.fullname" . }} + labels: + {{- include "osu-web-chart.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "osu-web-chart.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "osu-web-chart.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "osu-web-chart.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: + - /app/docker/deployment/entrypoint.sh + - nginx + ports: + - name: http + containerPort: 8000 + protocol: TCP + livenessProbe: + tcpSocket: + port: http + # httpGet: + # path: /home + # port: http + readinessProbe: + tcpSocket: + port: http + # httpGet: + # path: /home + # port: http + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumeMounts: + - mountPath: /var/env-secret + name: env-secret + readOnly: true + - mountPath: /app/storage/passport + name: oauth-secret + readOnly: true + lifecycle: + postStart: + exec: + command: + - /bin/sh + - -c + - sudo /app/docker/deployment/symlink-k8s-env.sh + volumes: + - name: oauth-secret + secret: + secretName: {{ include "osu-web-chart.fullname" . }}-shared + items: + - key: laravelOauthPublicKey + path: oauth-public.key + - key: laravelOauthPrivateKey + path: oauth-private.key + - name: env-secret + secret: + secretName: {{ include "osu-web-chart.fullname" . }} + items: + - key: .env + path: .env + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/osu-web-chart/templates/hpa.yaml b/osu-web-chart/templates/hpa.yaml new file mode 100644 index 00000000000..51b5c72276b --- /dev/null +++ b/osu-web-chart/templates/hpa.yaml @@ -0,0 +1,28 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "osu-web-chart.fullname" . }} + labels: + {{- include "osu-web-chart.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "osu-web-chart.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/osu-web-chart/templates/ingress.yaml b/osu-web-chart/templates/ingress.yaml new file mode 100644 index 00000000000..e75ff4348aa --- /dev/null +++ b/osu-web-chart/templates/ingress.yaml @@ -0,0 +1,41 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "osu-web-chart.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "osu-web-chart.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + backend: + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} diff --git a/osu-web-chart/templates/secret.yaml b/osu-web-chart/templates/secret.yaml new file mode 100644 index 00000000000..9f6e719cab6 --- /dev/null +++ b/osu-web-chart/templates/secret.yaml @@ -0,0 +1,148 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "osu-web-chart.fullname" . }} + labels: + {{- include "osu-web-chart.labels" . | nindent 4 }} +type: Opaque +stringData: + .env: | + APP_URL={{ .Values.config.laravel.url }} + APP_ENV={{ .Values.config.laravel.env }} + APP_DEBUG={{ .Values.config.laravel.debug }} + APP_KEY={{ .Values.config.laravel.appKey }} + APP_SENTRY={{ .Values.config.laravel.sentry.url }} + APP_SENTRY_PUBLIC={{ .Values.config.laravel.sentry.public_url }} + + DB_HOST={{ .Values.config.db.host }} + DB_DATABASE={{ .Values.config.db.database }} + DB_USERNAME={{ .Values.config.db.user }} + DB_PASSWORD={{ .Values.config.db.password }} + + REDIS_HOST={{ .Values.config.redis.app.host }} + REDIS_PORT={{ .Values.config.redis.app.port }} + REDIS_DB={{ .Values.config.redis.app.db }} + + CACHE_REDIS_HOST={{ .Values.config.redis.cache.host }} + CACHE_REDIS_PORT={{ .Values.config.redis.cache.port }} + CACHE_REDIS_DB={{ .Values.config.redis.cache.db }} + + MEMCACHED_PERSISTENT_ID={{ .Values.config.memcache.persistent_id }} + MEMCACHED_USERNAME={{ .Values.config.memcache.username }} + MEMCACHED_PASSWORD={{ .Values.config.memcache.password }} + MEMCACHED_HOST={{ .Values.config.memcache.host }} + MEMCACHED_PORT={{ .Values.config.memcache.port }} + + BROADCAST_DRIVER={{ .Values.config.laravel.log.driver }} + CACHE_DRIVER={{ .Values.config.laravel.cache.driver }} + CACHE_DRIVER_LOCAL={{ .Values.config.laravel.cache.localDriver }} + SESSION_DRIVER={{ .Values.config.laravel.session.driver }} + SESSION_DOMAIN={{ .Values.config.laravel.session.domain }} + SESSION_SECURE_COOKIE={{ .Values.config.laravel.session.secureCookie }} + + MAIL_DRIVER={{ .Values.config.mail.driver }} + MAIL_HOST={{ .Values.config.mail.host }} + MAIL_PORT={{ .Values.config.mail.port }} + MAIL_ENCRYPTION={{ .Values.config.mail.encryption }} + MAIL_USERNAME={{ .Values.config.mail.username }} + MAIL_PASSWORD={{ .Values.config.mail.password }} + + SHARED_INTEROP_SECRET={{ .Values.config.laravel.legacy.sharedInteropSecret }} + + FILESYSTEM_DISK={{ .Values.config.laravel.filesystem.disk }} + + BM_PROCESSOR_MIRRORS={{ .Values.config.beatmapsProcessor.mirrors }} + BM_PROCESSOR_THUMBNAILER={{ .Values.config.beatmapsProcessor.thumbnailer }} + BM_PROCESSOR_SENTRY={{ .Values.config.beatmapsProcessor.sentry }} + + S3_KEY={{ .Values.config.s3.default.key }} + S3_SECRET={{ .Values.config.s3.default.secret }} + S3_REGION={{ .Values.config.s3.default.region }} + S3_BUCKET={{ .Values.config.s3.default.bucket }} + + S3_AVATAR_KEY={{ .Values.config.s3.avatar.key }} + S3_AVATAR_SECRET={{ .Values.config.s3.avatar.secret }} + S3_AVATAR_REGION={{ .Values.config.s3.avatar.region }} + S3_AVATAR_BUCKET={{ .Values.config.s3.avatar.bucket }} + AVATAR_STORAGE={{ .Values.config.s3.avatar.storage }} + AVATAR_CACHE_PURGE_PREFIX={{ .Values.config.s3.avatar.cache_purge_prefix }} + + # Either "s3" or "local". + SCORE_REPLAYS_STORAGE={{ .Values.config.laravel.scoreReplaysStorage }} + + QUEUE_DRIVER={{ .Values.config.laravel.queueDriver }} + CAMO_KEY={{ .Values.config.laravel.camo.key }} + CAMO_PREFIX={{ .Values.config.laravel.camo.prefix }} + + PASSPORT_KEY_PATH=/app/storage/passport + + GITHUB_TOKEN={{ .Values.config.laravel.githubToken }} + + DATADOG_ENABLED={{ .Values.config.laravel.datadog.enabled }} + DATADOG_PREFIX={{ .Values.config.laravel.datadog.prefix }} + DATADOG_API_KEY={{ .Values.config.laravel.datadog.apiKey }} + DATADOG_APP_KEY={{ .Values.config.laravel.datadog.appKey }} + DATADOG_HOST={{ .Values.config.laravel.datadog.host }} + DATADOG_STATSD_HOST={{ .Values.config.laravel.datadog.statsd.host }} + DATADOG_STATSD_PORT={{ .Values.config.laravel.datadog.statsd.port }} + DATADOG_STATSD_SOCKET={{ .Values.config.laravel.datadog.statsd.socket }} + + CHANGELOG_GITHUB_TOKEN={{ .Values.config.laravel.changelogGithubToken }} + + PAYMENT_SANDBOX={{ .Values.config.laravel.payments.sandbox }} + + SHOPIFY_DOMAIN={{ .Values.config.laravel.payments.shopify.domain }} + SHOPIFY_STOREFRONT_TOKEN={{ .Values.config.laravel.payments.shopify.storeFrontToken }} + SHOPIFY_WEBHOOK_KEY={{ .Values.config.laravel.payments.shopify.webhookKey }} + + STORE_NOTIFICATION_CHANNEL={{ .Values.config.laravel.notifications.store.channel }} + STORE_NOTIFICATIONS_QUEUE={{ .Values.config.laravel.notifications.store.queue }} + STORE_STALE_DAYS={{ .Values.config.laravel.payments.storeStaleDays }} + + PAYPAL_URL={{ .Values.config.laravel.payments.paypal.url }} + PAYPAL_MERCHANT_ID={{ .Values.config.laravel.payments.paypal.merchantId }} + PAYPAL_CLIENT_ID={{ .Values.config.laravel.payments.paypal.clientId }} + PAYPAL_CLIENT_SECRET={{ .Values.config.laravel.payments.paypal.clientSecret }} + PAYPAL_NO_SHIPPING_EXPERIENCE_PROFILE_ID={{ .Values.config.laravel.payments.paypal.noShippingExperienceProfileId }} + + XSOLLA_API_KEY={{ .Values.config.laravel.payments.xsolla.apiKey }} + XSOLLA_MERCHANT_ID={{ .Values.config.laravel.payments.xsolla.merchantId }} + XSOLLA_PROJECT_ID={{ .Values.config.laravel.payments.xsolla.projectId }} + XSOLLA_SECRET_KEY={{ .Values.config.laravel.payments.xsolla.secretKey }} + + CENTILI_API_KEY={{ .Values.config.laravel.payments.centili.apiKey }} + CENTILI_SECRET_KEY={{ .Values.config.laravel.payments.centili.secretKey }} + CENTILI_CONVERSION_RATE={{ .Values.config.laravel.payments.centili.conversionRate }} + CENTILI_WIDGET_URL={{ .Values.config.laravel.payments.centili.widgetUrl }} + + ES_HOST={{ .Values.config.elasticsearch.host }} + ES_SCORES_HOST={{ .Values.config.elasticsearch.scores.host }} + ES_INDEX_PREFIX={{ .Values.config.elasticsearch.indexPrefix }} + ES_CLIENT_TIMEOUT={{ .Values.config.elasticsearch.clientTimeout }} + ES_CLIENT_CONNECT_TIMEOUT={{ .Values.config.elasticsearch.clientConnectTimeout }} + ES_SEARCH_TIMEOUT={{ .Values.config.elasticsearch.searchTimeout }} + + NOTIFICATION_QUEUE={{ .Values.config.laravel.notifications.queue }} + NOTIFICATION_REDIS_HOST={{ .Values.config.redis.notification.host }} + NOTIFICATION_REDIS_PORT={{ .Values.config.redis.notification.port }} + NOTIFICATION_REDIS_DB={{ .Values.config.redis.notification.db }} + NOTIFICATION_ENDPOINT={{ .Values.config.notificationServer.publicUrl }} + + LOG_CHANNEL={{ .Values.config.laravel.logChannel }} + + #RECAPTCHA_SECRET={{ .Values.config.laravel.recaptcha.secret }} + #RECAPTCHA_SITEKEY={{ .Values.config.laravel.recaptcha.siteKey }} + #RECAPTCHA_THRESHOLD={{ .Values.config.laravel.recaptcha.threshold }} + + TWITCH_CLIENT_ID={{ .Values.config.laravel.twitch.clientId }} + TWITCH_CLIENT_SECRET={{ .Values.config.laravel.twitch.clientSecret }} + + SCORES_ES_CACHE_DURATION={{ .Values.config.laravel.scores.cacheDuration }} + SCORES_RANK_CACHE_LOCAL_SERVER={{ .Values.config.laravel.scoresRankCache.localServer }} + SCORES_RANK_CACHE_MIN_USERS={{ .Values.config.laravel.scoresRankCache.minUsers }} + SCORES_RANK_CACHE_SERVER_URL={{ .Values.config.laravel.scoresRankCache.serverUrl }} + SCORES_RANK_CACHE_TIMEOUT={{ .Values.config.laravel.scoresRankCache.timeout }} + + BANCHO_BOT_USER_ID={{ .Values.config.laravel.legacy.banchoBotUserId }} + + {{ .Values.config.laravel.extraEnv }} diff --git a/osu-web-chart/templates/service.yaml b/osu-web-chart/templates/service.yaml new file mode 100644 index 00000000000..b119f89b7d3 --- /dev/null +++ b/osu-web-chart/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "osu-web-chart.fullname" . }} + labels: + {{- include "osu-web-chart.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "osu-web-chart.selectorLabels" . | nindent 4 }} diff --git a/osu-web-chart/templates/serviceaccount.yaml b/osu-web-chart/templates/serviceaccount.yaml new file mode 100644 index 00000000000..7009d1178b6 --- /dev/null +++ b/osu-web-chart/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "osu-web-chart.serviceAccountName" . }} + labels: + {{- include "osu-web-chart.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/osu-web-chart/templates/shared-secret.yaml b/osu-web-chart/templates/shared-secret.yaml new file mode 100644 index 00000000000..1ee0762e758 --- /dev/null +++ b/osu-web-chart/templates/shared-secret.yaml @@ -0,0 +1,39 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "osu-web-chart.fullname" . }}-shared + labels: + {{- include "osu-web-chart.labels" . | nindent 4 }} +type: Opaque +stringData: + {{- if .Values.config.laravel.debug }} + appDebug: "true" + {{- end }} + appEnv: {{ required "Missing app env" .Values.config.laravel.env }} + {{- if .Values.config.db.database }} + dbDatabase: {{ .Values.config.db.database }} + {{- end }} + dbHost: {{ required "Missing db host" .Values.config.db.host }} + {{- if .Values.config.db.password }} + dbPassword: {{ .Values.config.db.password }} + {{- end }} + {{- if .Values.config.db.port }} + dbPort: {{ .Values.config.db.port }} + {{- end }} + {{- if .Values.config.db.user }} + dbUser: {{ .Values.config.db.user }} + {{- end }} + {{- if .Values.config.dbName.chat }} + dbNameChat: {{ .Values.config.dbName.chat }} + {{- end }} + laravelAppKey: "{{ required "Missing Laravel appKey" .Values.config.laravel.appKey }}" + laravelOauthPublicKey: {{- printf " |%s" (required "Missing Laravel oauthPublicKey" .Values.config.laravel.oauth.publicKey | nindent 4) }} + laravelOauthPrivateKey: {{- printf " |%s" (required "Missing Laravel oauthPrivateKey" .Values.config.laravel.oauth.privateKey | nindent 4) }} + redisAppHost: {{ required "Missing redis host" .Values.config.redis.app.host }} + {{- if .Values.config.redis.app.port }} + redisAppPort: "{{ .Values.config.redis.app.port }}" + {{- end }} + redisNotificationHost: {{ required "Missing redis notification host" .Values.config.redis.notification.host }} + {{- if .Values.config.redis.notification.port }} + redisNotificationPort: "{{ .Values.config.redis.notification.port }}" + {{- end }} diff --git a/osu-web-chart/values.yaml b/osu-web-chart/values.yaml new file mode 100644 index 00000000000..ba4444f58ed --- /dev/null +++ b/osu-web-chart/values.yaml @@ -0,0 +1,254 @@ +# Default values for osu-web-chart. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +config: + laravel: + url: http://localhost:8080 # APP_URL + env: local # APP_ENV + debug: true # APP_DEBUG + appKey: "" # APP_KEY + extraEnv: "" + + sentry: + url: "" # APP_SENTRY + public_url: "" # APP_SENTRY_PUBLIC + + log: + driver: log # BROADCAST_DRIVER + logChannel: single # LOG_CHANNEL + + cache: + driver: file # CACHE_DRIVER + localDriver: file # CACHE_DRIVER_LOCAL + + session: + driver: file # SESSION_DRIVER + domain: "" # SESSION_DOMAIN + secureCookie: false # SESSION_SECURE_COOKIE + + legacy: + sharedInteropSecret: "" # SHARED_INTEROP_SECRET + banchoBotUserId: "" # BANCHO_BOT_USER_ID + + filesystem: + disk: local # FILESYSTEM_DISK + + scoreReplaysStorage: local # SCORE_REPLAYS_STORAGE # Either "s3" or "local". + queueDriver: "" # QUEUE_DRIVER + + camo: + key: "" # CAMO_KEY + prefix: "" # CAMO_PREFIX + + oauth: + publicKey: "" + privateKey: "" + + githubToken: "" # GITHUB_TOKEN + changelogGithubToken: "" # CHANGELOG_GITHUB_TOKEN + + datadog: + enabled: false # DATADOG_ENABLED + prefix: osu.web # DATADOG_PREFIX + apiKey: "" # DATADOG_API_KEY + appKey: "" # DATADOG_APP_KEY + host: https://app.datadoghq.com # DATADOG_HOST + statsd: + host: "" # DATADOG_STATSD_HOST + port: "" # DATADOG_STATSD_PORT + socket: "" # DATADOG_STATSD_SOCKET + + payments: + sandbox: true # PAYMENT_SANDBOX + storeStaleDays: "" # STORE_STALE_DAYS + shopify: + domain: "" # SHOPIFY_DOMAIN + storeFrontToken: "" # SHOPIFY_STOREFRONT_TOKEN + webhookKey: "" # SHOPIFY_WEBHOOK_KEY + paypal: + url: https://www.sandbox.paypal.com/cgi-bin/webscr # PAYPAL_URL + merchantId: "" # PAYPAL_MERCHANT_ID + clientId: "" # PAYPAL_CLIENT_ID + clientSecret: "" # PAYPAL_CLIENT_SECRET + noShippingExperienceProfileId: "" # PAYPAL_NO_SHIPPING_EXPERIENCE_PROFILE_ID + xsolla: + apiKey: "" # XSOLLA_API_KEY + merchantId: "" # XSOLLA_MERCHANT_ID + projectId: "" # XSOLLA_PROJECT_ID + secretKey: "" # XSOLLA_SECRET_KEY + centili: + apiKey: "" # CENTILI_API_KEY + secretKey: "" # CENTILI_SECRET_KEY + conversionRate: "" # CENTILI_CONVERSION_RATE + widgetUrl: https://api.centili.com/payment/widget # CENTILI_WIDGET_URL + + notifications: + queue: notification # NOTIFICATION_QUEUE + store: + channel: test # STORE_NOTIFICATION_CHANNEL + queue: store-notifications # STORE_NOTIFICATIONS_QUEUE + + recaptcha: + secret: "" # RECAPTCHA_SECRET + siteKey: "" # RECAPTCHA_SITEKEY + threshold: "" # RECAPTCHA_THRESHOLD + + twitch: + clientId: "" # TWITCH_CLIENT_ID + clientSecret: "" # TWITCH_CLIENT_SECRET + + scores: + cacheDuration: "" # SCORES_ES_CACHE_DURATION + + scoresRankCache: + localServer: 0 # SCORES_RANK_CACHE_LOCAL_SERVER + minUsers: 35000 # SCORES_RANK_CACHE_MIN_USERS + serverUrl: "" # SCORES_RANK_CACHE_SERVER_URL + timeout: 10 # SCORES_RANK_CACHE_TIMEOUT + + db: + host: localhost # DB_HOST + database: osu # DB_DATABASE + user: osuweb # DB_USERNAME + password: "" # DB_PASSWORD + + dbName: + chat: "" # default to osu_chat + + redis: + app: + host: 127.0.0.1 # REDIS_HOST + port: 6379 # REDIS_PORT + db: 0 # REDIS_DB + cache: + host: 127.0.0.1 # CACHE_REDIS_HOST + port: 6379 # CACHE_REDIS_PORT + db: 0 # CACHE_REDIS_DB + notification: + host: 127.0.0.1 # NOTIFICATION_REDIS_HOST + port: 6379 # NOTIFICATION_REDIS_PORT + db: 0 # NOTIFICATION_REDIS_DB + + memcache: + persistent_id: "" # MEMCACHED_PERSISTENT_ID + username: "" # MEMCACHED_USERNAME + password: "" # MEMCACHED_PASSWORD + host: 127.0.0.1 # MEMCACHED_HOST + port: 11211 # MEMCACHED_PORT + + mail: + driver: log # MAIL_DRIVER + host: "" # MAIL_HOST + port: "" # MAIL_PORT + encryption: "" # MAIL_ENCRYPTION + username: "" # MAIL_USERNAME + password: "" # MAIL_PASSWORD + + beatmapsProcessor: + mirrors: 1 # BM_PROCESSOR_MIRRORS + thumbnailer: http://localhost:4001 # BM_PROCESSOR_THUMBNAILER + sentry: "" # BM_PROCESSOR_SENTRY + + s3: + default: + key: "" # S3_KEY + secret: "" # S3_SECRET + region: "" # S3_REGION + bucket: "" # S3_BUCKET + avatar: + key: "" # S3_AVATAR_KEY + secret: "" # S3_AVATAR_SECRET + region: "" # S3_AVATAR_REGION + bucket: "" # S3_AVATAR_BUCKET + storage: local-avatar # AVATAR_STORAGE + cache_purge_prefix: "" # AVATAR_CACHE_PURGE_PREFIX + + elasticsearch: + host: localhost:9200 # ES_HOST + scores: + host: localhost:9200 # ES_SCORES_HOST + indexPrefix: "" # ES_INDEX_PREFIX + clientTimeout: 5 # ES_CLIENT_TIMEOUT + clientConnectTimeout: 0.5 # ES_CLIENT_CONNECT_TIMEOUT + searchTimeout: 5s # ES_SEARCH_TIMEOUT + + notificationServer: + publicUrl: wss://notify.ppy.sh # NOTIFICATION_ENDPOINT + +replicaCount: 1 + +image: + repository: pppy/osu-web + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +ingress: + enabled: true + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: osu.ppy.sh + paths: + - path: / + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +affinity: {}