diff --git a/osf-pigeon/Chart.yaml b/osf-pigeon/Chart.yaml index 7e1ae299..71c23d0e 100644 --- a/osf-pigeon/Chart.yaml +++ b/osf-pigeon/Chart.yaml @@ -1,9 +1,17 @@ -apiVersion: v1 +apiVersion: v2 description: A Helm chart for Kubernetes name: osf-pigeon -version: 0.1.0 +type: application +version: 1.0.0 sources: - https://github.com/CenterForOpenScience/osf-pigeon/ +dependencies: + - name: cos-common + version: 1.0.0 + repository: https://centerforopenscience.github.io/helm-charts/ + # - name: cos-common + # version: 1.0.0 + # repository: "file://../cos-common" maintainers: - name: Matt Frazier email: matt@cos.io @@ -11,5 +19,3 @@ maintainers: - name: Matt Clark email: mattclark@cos.io url: https://github.com/mattclark -engine: gotpl -tillerVersion: '>=2.7.0' diff --git a/osf-pigeon/files/nginx.conf b/osf-pigeon/files/nginx.conf new file mode 100644 index 00000000..66997af7 --- /dev/null +++ b/osf-pigeon/files/nginx.conf @@ -0,0 +1,117 @@ +user nginx; +worker_processes {{ .Values.main.nginx.workerCount }}; + +load_module /usr/lib/nginx/modules/ngx_http_brotli_filter_module.so; +{{- if .Values.main.nginx.vts.enabled }} +load_module /usr/lib/nginx/modules/ngx_http_geoip_module.so; +load_module /usr/lib/nginx/modules/ngx_http_vhost_traffic_status_module.so; +{{- end }} + +error_log /var/log/nginx/error.log warn; +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 - $upstream_cache_status $remote_user [$time_local] ' + '"$request" $status $body_bytes_sent ' + '"$http_referer" "$http_user_agent" "$http_x_forwarded_for" ' + 'rt=$request_time uct="$upstream_connect_time" uht="$upstream_header_time" urt="$upstream_response_time"'; + access_log /var/log/nginx/access.log main; + + real_ip_header {{ .Values.main.nginx.realIpHeader }}; + real_ip_recursive {{ .Values.main.nginx.realIpRecursive }}; + {{- range .Values.main.nginx.proxySourceRanges }} + set_real_ip_from {{ . }}; + {{- end }} + + {{- if .Values.main.nginx.vts.enabled }} + geoip_country /etc/nginx/GeoIP.dat; + geoip_city /etc/nginx/GeoLiteCity.dat; + geoip_proxy_recursive on; + {{- range .Values.main.nginx.proxySourceRanges }} + geoip_proxy {{ . }}; + {{- end }} + + vhost_traffic_status_zone shared:vhost_traffic_status:{{ .Values.main.nginx.vts.statusZoneSize }}; + vhost_traffic_status_filter_by_set_key {{ .Values.main.nginx.vts.defaultFilterKey }}; + {{- end }} + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 620s; + keepalive_requests 10000; + types_hash_max_size 2048; + server_tokens off; + + gzip on; + gzip_proxied any; + gzip_disable "msie6"; + gzip_min_length 1400; + gzip_vary on; + gzip_buffers 4 32k; + gzip_types text/plain text/css image/svg+xml application/javascript application/x-javascript text/xml text/javascript application/json application/vnd.api+json; + + brotli on; + brotli_types text/plain text/css image/svg+xml application/javascript application/x-javascript text/xml text/javascript application/json application/vnd.api+json; + + {{- if .Values.main.nginx.vts.enabled }} + server { + listen {{ .Values.main.nginx.vts.internalPort }}; + server_name _; + + location /healthz { + access_log off; + return 200; + } + + location /nginx_status { + vhost_traffic_status_display; + vhost_traffic_status_display_format html; + } + } + {{- end }} + + server { + listen {{ .Values.main.http.containers.nginx.internalPort }}; + keepalive_timeout 620s; + client_max_body_size 25M; + server_name _; + + if ($http_x_forwarded_proto = "http") { + return 301 https://$host$request_uri; + } + + location = /healthz { + access_log off; + return 200; + } + + location = /robots.txt { + alias /usr/share/nginx/html/robots.txt; + } + + location / { + # Disable caching of application requests + add_header Cache-Control "no-cache, no-store, max-age=0, must-revalidate"; + add_header Expires "-1"; + add_header Pragma "no-cache"; + + # Mitigate HTTPoxy Vulnerability + # https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/ + proxy_set_header Proxy ""; + + proxy_buffering off; + proxy_request_buffering off; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_pass http://127.0.0.1:{{ .Values.main.http.containers.nginx.externalPort }}; + } + } +} \ No newline at end of file diff --git a/osf-pigeon/templates/NOTES.txt b/osf-pigeon/templates/NOTES.txt index 5aa8956c..268c81da 100644 --- a/osf-pigeon/templates/NOTES.txt +++ b/osf-pigeon/templates/NOTES.txt @@ -1,17 +1,24 @@ -1. Get the application URL by running these commands: -{{- if .Values.ingress.hostname }} - http://{{- .Values.ingress.hostname }} -{{- else if contains "NodePort" .Values.service.type }} - export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "osf-pigeon.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 svc -w {{ template "osf-pigeon.fullname" . }}' - export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "osf-pigeon.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') - echo http://$SERVICE_IP:{{ .Values.service.externalPort }} -{{- else if contains "ClusterIP" .Values.service.type }} - export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "osf-pigeon.fullname" . }}" -o jsonpath="{.items[0].metadata.name}") - echo "Visit http://127.0.0.1:8080 to use your application" - kubectl port-forward $POD_NAME 8080:{{ .Values.service.externalPort }} +Component fullname: {{ include "cos-common.fullname" (dict "root" . "name" "" "values" .Values.main) }} + +{{- if and .Values.main.ingress.enabled (.Values.main.ingress.hosts) }} +Ingress hosts: +{{- $hosts := list }} +{{- if and (kindIs "map" .Values.main.ingress.hosts) (or (hasKey .Values.main.ingress.hosts "primary") (hasKey .Values.main.ingress.hosts "additional")) }} + {{- range $h := (default (list) .Values.main.ingress.hosts.primary) }} + {{- $hosts = append $hosts $h }} + {{- end }} + {{- range $h := (default (list) .Values.main.ingress.hosts.additional) }} + {{- $hosts = append $hosts $h }} + {{- end }} +{{- else }} + {{- range $h := .Values.main.ingress.hosts }} + {{- $hosts = append $hosts $h.host }} + {{- end }} +{{- end }} +{{- range $hosts }} + - {{ . }} +{{- end }} +{{- else }} +Port-forward example: +kubectl -n {{ .Release.Namespace }} port-forward svc/{{ include "cos-common.fullname" (dict "root" . "name" "" "values" .Values.main) }} 8080:{{ ( .Values.main.http.containers.nginx.internalPort ) }} {{- end }} diff --git a/osf-pigeon/templates/_helpers.tpl b/osf-pigeon/templates/_helpers.tpl deleted file mode 100644 index 804fafd9..00000000 --- a/osf-pigeon/templates/_helpers.tpl +++ /dev/null @@ -1,55 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "osf-pigeon.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). -*/}} -{{- define "osf-pigeon.fullname" -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified certificate name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -*/}} -{{- define "osf-pigeon.certificate.fullname" -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- printf "%s-%s-%s" .Release.Name $name .Values.certificate.name | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Overridable deployment annotations -*/}} -{{- define "osf-pigeon.deploymentAnnotations" -}} -checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} -checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} -{{- end -}} - -{{- define "osf-pigeon.environment" -}} -{{- $fullname := include "osf-pigeon.fullname" . -}} -{{- range $key, $value := .Values.configEnvs }} -- name: {{ $key }} - valueFrom: - configMapKeyRef: - name: {{ $fullname }} - key: {{ $key }} -{{- end }} -{{- range $key, $value := .Values.secretEnvs }} -- name: {{ $key }} - valueFrom: - secretKeyRef: - name: {{ $fullname }} - key: {{ $key }} -{{- end }} -{{- if and .Values.persistence.enabled .Values.persistence.mountPath }} -- name: PIGEON_FILESTORE_DIR - value: {{ .Values.persistence.mountPath }} -{{- end }} -{{- end -}} diff --git a/osf-pigeon/templates/certificate-networkpolicy.yaml b/osf-pigeon/templates/certificate-networkpolicy.yaml deleted file mode 100644 index aa0d07e1..00000000 --- a/osf-pigeon/templates/certificate-networkpolicy.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if (and .Values.networkPolicy.enabled .Values.certificate.enabled) }} -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: "{{ template "osf-pigeon.certificate.fullname" . }}" - labels: - app: {{ template "osf-pigeon.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} - component: "{{ .Values.certificate.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -spec: - policyTypes: - - Ingress - podSelector: - matchExpressions: - - {key: acme.cert-manager.io/http01-solver, operator: Exists} - ingress: - - from: [] -{{- end }} diff --git a/osf-pigeon/templates/certificate.yaml b/osf-pigeon/templates/certificate.yaml deleted file mode 100644 index 83115ecb..00000000 --- a/osf-pigeon/templates/certificate.yaml +++ /dev/null @@ -1,34 +0,0 @@ -{{- if .Values.certificate.enabled -}} -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: "{{ template "osf-pigeon.certificate.fullname" . }}" - labels: - app: {{ template "osf-pigeon.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} - component: "{{ .Values.certificate.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -spec: - secretName: "{{ template "osf-pigeon.certificate.fullname" . }}" - issuerRef: - name: {{ .Values.certificate.issuerRef.name }} - kind: {{ .Values.certificate.issuerRef.kind }} - commonName: {{ .Values.certificate.commonName }} - dnsNames: - {{- range .Values.certificate.dnsNames }} - - {{ . }} - {{- end }} - acme: - config: - - http01: - {{- if hasKey .Values.certificate.acmeConfig.http01 "ingress" }} - ingress: {{ .Values.certificate.acmeConfig.http01.ingress }} - {{- else }} - ingress: {{ template "osf-pigeon.fullname" . }} - {{- end }} - domains: - {{- range .Values.certificate.acmeConfig.domains }} - - {{ . }} - {{- end }} -{{- end -}} diff --git a/osf-pigeon/templates/configmap.yaml b/osf-pigeon/templates/configmap.yaml deleted file mode 100644 index cb86b386..00000000 --- a/osf-pigeon/templates/configmap.yaml +++ /dev/null @@ -1,137 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ template "osf-pigeon.fullname" . }} - labels: - app: {{ template "osf-pigeon.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -data: - {{- define "osf-pigeon.inlineconfigs" }} -nginx.conf: |- - user nginx; - worker_processes {{ .Values.nginx.workerCount }}; - - load_module /usr/lib/nginx/modules/ngx_http_brotli_filter_module.so; - {{- if .Values.nginx.vts.enabled }} - load_module /usr/lib/nginx/modules/ngx_http_geoip_module.so; - load_module /usr/lib/nginx/modules/ngx_http_vhost_traffic_status_module.so; - {{- end }} - - error_log /var/log/nginx/error.log warn; - 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 - $upstream_cache_status $remote_user [$time_local] ' - '"$request" $status $body_bytes_sent ' - '"$http_referer" "$http_user_agent" "$http_x_forwarded_for" ' - 'rt=$request_time uct="$upstream_connect_time" uht="$upstream_header_time" urt="$upstream_response_time"'; - access_log /var/log/nginx/access.log main; - - real_ip_header {{ .Values.nginx.realIpHeader }}; - real_ip_recursive {{ .Values.nginx.realIpRecursive }}; - {{- range .Values.nginx.proxySourceRanges }} - set_real_ip_from {{ . }}; - {{- end }} - - {{- if .Values.nginx.vts.enabled }} - geoip_country /etc/nginx/GeoIP.dat; - geoip_city /etc/nginx/GeoLiteCity.dat; - geoip_proxy_recursive on; - {{- range .Values.nginx.proxySourceRanges }} - geoip_proxy {{ . }}; - {{- end }} - - vhost_traffic_status_zone shared:vhost_traffic_status:{{ .Values.nginx.vts.statusZoneSize }}; - vhost_traffic_status_filter_by_set_key {{ .Values.nginx.vts.defaultFilterKey }}; - {{- end }} - - sendfile on; - tcp_nopush on; - tcp_nodelay on; - keepalive_timeout 620s; - keepalive_requests 10000; - types_hash_max_size 2048; - server_tokens off; - - gzip on; - gzip_proxied any; - gzip_disable "msie6"; - gzip_min_length 1400; - gzip_vary on; - gzip_buffers 4 32k; - gzip_types text/plain text/css image/svg+xml application/javascript application/x-javascript text/xml text/javascript application/json application/vnd.api+json; - - brotli on; - brotli_types text/plain text/css image/svg+xml application/javascript application/x-javascript text/xml text/javascript application/json application/vnd.api+json; - - {{- if .Values.nginx.vts.enabled }} - server { - listen {{ .Values.nginx.vts.internalPort }}; - server_name _; - - location /healthz { - access_log off; - return 200; - } - - location /nginx_status { - vhost_traffic_status_display; - vhost_traffic_status_display_format html; - } - } - {{- end }} - - server { - listen {{ .Values.service.internalPort }}; - keepalive_timeout 620s; - client_max_body_size 25M; - server_name _; - - if ($http_x_forwarded_proto = "http") { - return 301 https://$host$request_uri; - } - - location = /healthz { - access_log off; - return 200; - } - - location = /robots.txt { - alias /usr/share/nginx/html/robots.txt; - } - - location / { - # Disable caching of application requests - add_header Cache-Control "no-cache, no-store, max-age=0, must-revalidate"; - add_header Expires "-1"; - add_header Pragma "no-cache"; - - # Mitigate HTTPoxy Vulnerability - # https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/ - proxy_set_header Proxy ""; - - proxy_buffering off; - proxy_request_buffering off; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_pass http://127.0.0.1:{{ .Values.service.externalPort }}; - } - } - } -{{- end -}} - {{- range $key, $value := .Values.configEnvs }} - {{ $key }}: {{ $value | quote }} - {{- end }} - {{- range $key, $value := merge .Values.configFiles (include "osf-pigeon.inlineconfigs" . | fromYaml) ((.Files.Glob "files/*").AsConfig | fromYaml) }} - {{ $key }}: |- - {{- $value | nindent 4 }} - {{- end }} diff --git a/osf-pigeon/templates/deployment.yaml b/osf-pigeon/templates/deployment.yaml deleted file mode 100644 index ba78ca1a..00000000 --- a/osf-pigeon/templates/deployment.yaml +++ /dev/null @@ -1,140 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ template "osf-pigeon.fullname" . }} - labels: - app: {{ template "osf-pigeon.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -spec: - selector: - matchLabels: - app: {{ template "osf-pigeon.name" . }} - release: {{ .Release.Name }} - replicas: {{ .Values.replicaCount }} - {{- if .Values.strategy }} - strategy: - {{- toYaml .Values.strategy | nindent 4 }} - {{- end }} - template: - metadata: - labels: - app: {{ template "osf-pigeon.name" . }} - release: {{ .Release.Name }} - annotations: - {{- include "osf-pigeon.deploymentAnnotations" . | nindent 8 }} - spec: - affinity: - {{- if .Values.additionalAffinities }} - {{- toYaml .Values.additionalAffinities | nindent 8 }} - {{- end }} - {{- if eq .Values.antiAffinity "hard" }} - podAntiAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - - topologyKey: kubernetes.io/hostname - labelSelector: - matchLabels: - app: {{ template "osf-pigeon.name" . }} - release: {{ .Release.Name }} - {{- else if eq .Values.antiAffinity "soft" }} - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 1 - podAffinityTerm: - topologyKey: kubernetes.io/hostname - labelSelector: - matchLabels: - app: {{ template "osf-pigeon.name" . }} - release: {{ .Release.Name }} - {{- end }} - containers: - - name: nginx - image: "{{ .Values.nginx.image.repository }}:{{ .Values.nginx.image.tag }}" - imagePullPolicy: {{ .Values.nginx.image.pullPolicy }} - command: - - nginx - - -c - - /etc/nginx/nginx.conf - - -g - - daemon off; - ports: - - name: http-internal - containerPort: {{ .Values.service.internalPort }} - readinessProbe: - httpGet: - path: /healthz - port: {{ .Values.service.internalPort }} - initialDelaySeconds: 10 - volumeMounts: - - name: config - subPath: nginx.conf - mountPath: /etc/nginx/nginx.conf - readOnly: true - - name: config - subPath: robots.txt - mountPath: /usr/share/nginx/html/robots.txt - readOnly: true - resources: - {{- toYaml .Values.nginx.resources | nindent 12 }} - - name: sanic - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - command: - - /bin/sh - - -c - - python3 -m osf_pigeon - env: - {{- include "osf-pigeon.environment" . | nindent 12 }} - ports: - - name: http-external - containerPort: {{ .Values.service.externalPort }} - readinessProbe: - httpGet: - path: / - port: {{ .Values.service.externalPort }} - volumeMounts: - - name: localcache - mountPath: /tmp/pigeonlocalcache - {{- if .Values.persistence.enabled }} - - name: data - mountPath: {{ .Values.persistence.mountPath }} - {{- end }} - resources: - {{- toYaml .Values.sanic.resources | nindent 12 }} - volumes: - - name: localcache - emptyDir: {} - - name: data - {{- if .Values.persistence.enabled }} - persistentVolumeClaim: - claimName: {{ .Values.persistence.existingClaim | default (include "osf-pigeon.fullname" .) }} - {{- else }} - emptyDir: {} - {{- end }} - - name: config - configMap: - name: {{ template "osf-pigeon.fullname" . }} - - name: secret - secret: - secretName: {{ template "osf-pigeon.fullname" . }} - {{- if .Values.nodeSelector }} - nodeSelector: - {{- toYaml .Values.nodeSelector | nindent 8 }} - {{- end }} - {{- if .Values.persistence.enabled }} - volumeClaimTemplates: - - metadata: - name: data - spec: - accessModes: - {{- range .Values.persistence.accessModes }} - - {{ . | quote }} - {{- end }} - {{- if hasKey .Values.persistence "storageClass" }} - storageClassName: {{ .Values.persistence.storageClass | quote }} - {{- end }} - resources: - requests: - storage: {{ .Values.persistence.size | quote }} - {{- end }} diff --git a/osf-pigeon/templates/hpa.yaml b/osf-pigeon/templates/hpa.yaml deleted file mode 100644 index 28b5df92..00000000 --- a/osf-pigeon/templates/hpa.yaml +++ /dev/null @@ -1,19 +0,0 @@ -{{- if .Values.horizontalPodAutoscaler.enabled -}} -apiVersion: autoscaling/v1 -kind: HorizontalPodAutoscaler -metadata: - name: {{ template "osf-pigeon.fullname" . }} - labels: - app: {{ template "osf-pigeon.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: {{ template "osf-pigeon.fullname" . }} - minReplicas: {{ .Values.replicaCount }} - maxReplicas: {{ .Values.horizontalPodAutoscaler.maxReplicas }} - targetCPUUtilizationPercentage: {{ .Values.horizontalPodAutoscaler.targetCPUUtilizationPercentage }} -{{- end -}} diff --git a/osf-pigeon/templates/ingress.yaml b/osf-pigeon/templates/ingress.yaml deleted file mode 100644 index 4cf9c446..00000000 --- a/osf-pigeon/templates/ingress.yaml +++ /dev/null @@ -1,49 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- $serviceName := include "osf-pigeon.fullname" . -}} -{{- $servicePort := .Values.service.externalPort -}} -{{- $ingressPaths := .Values.ingress.paths -}} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: {{ template "osf-pigeon.fullname" . }} - labels: - app: {{ template "osf-pigeon.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - annotations: - {{- range $key, $value := .Values.ingress.annotations }} - {{ $key }}: {{ $value | quote }} - {{- end }} -spec: - rules: - {{- $serviceName := include "osf-pigeon.fullname" . -}} - {{- $servicePort := .Values.service.externalPort -}} - {{- range .Values.ingress.hosts }} - - host: {{ . }} - http: - paths: - {{- range $ingressPaths }} - - path: {{ . }} - pathType: ImplementationSpecific - backend: - service: - name: {{ $serviceName }} - port: - number: {{ $servicePort }} - {{- end -}} - {{- end -}} - {{- if (or .Values.ingress.tls (and .Values.certificate.enabled .Values.certificate.tls)) }} - tls: - {{- if .Values.ingress.tls }} - {{- toYaml .Values.ingress.tls | nindent 4 }} - {{- end -}} - {{- if (and .Values.certificate.enabled .Values.certificate.tls) }} - - secretName: "{{ template "osf-pigeon.certificate.fullname" . }}" - hosts: - {{- range .Values.certificate.acmeConfig.domains }} - - {{ . }} - {{- end }} - {{- end -}} - {{- end -}} -{{- end -}} diff --git a/osf-pigeon/templates/main.yaml b/osf-pigeon/templates/main.yaml new file mode 100644 index 00000000..adaf50ef --- /dev/null +++ b/osf-pigeon/templates/main.yaml @@ -0,0 +1,10 @@ +{{- include "cos-common.configmap" (dict "root" . "name" "" "values" .Values.main) }} +{{- include "cos-common.secret" (dict "root" . "name" "" "values" .Values.main) }} +{{- include "cos-common.pvc" (dict "root" . "name" "" "values" .Values.main) }} +{{- include "cos-common.certificate" (dict "root" . "name" "cert" "values" .Values.main) }} +{{- include "cos-common.deployment" (dict "root" . "name" "" "values" .Values.main) }} +{{- include "cos-common.service" (dict "root" . "name" "" "values" .Values.main) }} +{{- include "cos-common.ingress" (dict "root" . "name" "" "values" .Values.main) }} +{{- include "cos-common.hpa" (dict "root" . "name" "" "values" .Values.main) }} +{{- include "cos-common.pdb" (dict "root" . "name" "" "values" .Values.main) }} +{{- include "cos-common.networkpolicy" (dict "root" . "name" "" "values" .Values.main) }} diff --git a/osf-pigeon/templates/networkpolicy.yaml b/osf-pigeon/templates/networkpolicy.yaml deleted file mode 100644 index 724e2fe1..00000000 --- a/osf-pigeon/templates/networkpolicy.yaml +++ /dev/null @@ -1,30 +0,0 @@ -{{- if .Values.networkPolicy.enabled }} -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: {{ template "osf-pigeon.fullname" . }} - labels: - app: {{ template "osf-pigeon.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -spec: - podSelector: - matchLabels: - app: {{ template "osf-pigeon.name" . }} - release: {{ .Release.Name }} - ingress: - - ports: - - port: {{ .Values.service.internalPort }} - {{- if not .Values.networkPolicy.allowExternal }} - from: - - podSelector: - matchLabels: - {{ template "osf-pigeon.fullname" . }}-client: "true" - {{- end }} - {{- if .Values.nginx.vts.enabled }} - - ports: - - port: {{ .Values.nginx.vts.internalPort }} - {{- end }} - egress: {{- toYaml .Values.networkPolicy.egress | nindent 4 }} -{{- end }} diff --git a/osf-pigeon/templates/pdb.yaml b/osf-pigeon/templates/pdb.yaml deleted file mode 100644 index 8bbf40fc..00000000 --- a/osf-pigeon/templates/pdb.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- if .Values.budget.minAvailable -}} -{{- if .Capabilities.APIVersions.Has "policy/v1" -}} -apiVersion: policy/v1 -{{- else}} -apiVersion: policy/v1beta1 -{{- end }} -kind: PodDisruptionBudget -metadata: - name: "{{ template "osf-pigeon.fullname" . }}" - labels: - app: {{ template "osf-pigeon.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -spec: - selector: - matchLabels: - app: {{ template "osf-pigeon.name" . }} - release: {{ .Release.Name }} - minAvailable: {{ .Values.budget.minAvailable }} -{{- end -}} diff --git a/osf-pigeon/templates/secret.yaml b/osf-pigeon/templates/secret.yaml deleted file mode 100644 index 9bd78874..00000000 --- a/osf-pigeon/templates/secret.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: {{ template "osf-pigeon.fullname" . }} - labels: - app: {{ template "osf-pigeon.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -type: Opaque -data: -{{- range $key, $value := .Values.secretEnvs }} - {{ $key }}: {{ $value | b64enc | quote }} -{{- end }} -{{- range $key, $value := .Values.secretFiles }} - {{ $key }}: {{ $value | b64enc | quote }} -{{- end }} diff --git a/osf-pigeon/templates/service.yaml b/osf-pigeon/templates/service.yaml deleted file mode 100644 index 00bf4965..00000000 --- a/osf-pigeon/templates/service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ template "osf-pigeon.fullname" . }} - labels: - app: {{ template "osf-pigeon.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.externalPort }} - targetPort: {{ .Values.service.internalPort }} - protocol: TCP - name: {{ .Values.service.name }} - selector: - app: {{ template "osf-pigeon.name" . }} - release: {{ .Release.Name }} diff --git a/osf-pigeon/values.yaml b/osf-pigeon/values.yaml index d03560e9..cb3fd888 100644 --- a/osf-pigeon/values.yaml +++ b/osf-pigeon/values.yaml @@ -1,162 +1,372 @@ -# Default values for osf-pigeon. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. -replicaCount: 1 - +### ---------- Global or Reusable parts across values.yaml ---------- image: repository: quay.io/centerforopenscience/osf-pigeon tag: develop pullPolicy: Always -antiAffinity: soft +## Remember that full name for all objects is '{{ include "cos-common.fullname" (dict "root" . "name" "") | trim }}' +## or in other form current naming is Release.Name-Chart.Name + +## =============== MAIN Component =============== +main: + enabled: true -# strategy: -# rollingUpdate: -# maxSurge: 25% -# maxUnavailable: 25% -# type: RollingUpdate + replicas: 1 -budget: - minAvailable: 0 + http: + containers: + nginx: + internalPort: 80 + externalPort: 2020 + serviceType: ClusterIP -nginx: - workerCount: 1 +# ------- Configuration follows for containerName: nginx ------- image: repository: quay.io/centerforopenscience/nginx tag: latest pullPolicy: Always + + containerName: nginx + + command: + - nginx + - -c + - /etc/nginx/nginx.conf + - -g + - daemon off; + + env: [] + + envFrom: [] + + probes: + readiness: + httpGet: + path: /healthz + port: "{{ .Values.main.http.containers.nginx.internalPort }}" + initialDelaySeconds: 10 + + ports: + - name: http-internal + containerPort: "{{ .Values.main.http.containers.nginx.internalPort }}" + protocol: TCP + + volumeMounts: + - name: config + mountPath: /etc/nginx/nginx.conf + subPath: nginx.conf + readOnly: true + - name: config + mountPath: /usr/share/nginx/html/robots.txt + subPath: robots.txt + readOnly: true + + additionalVolumeMounts: [] + resources: {} - # limits: - # cpu: 1 - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi - proxySourceRanges: [] - # - 130.211.0.0/22 - # - 35.191.0.0/16 - realIpHeader: X-Real-IP - realIpRecursive: "off" - vts: + + +# ------- Init containers ------- + initContainers: [] + + additionalInitContainers: [] + + +# ------- Additional containers ------- + sanic: + resources: + limits: + cpu: 1 + memory: 564Mi + requests: + cpu: 10m + memory: 282Mi + ephemeral-storage: 10Gi + volumeMounts: + - name: localcache + mountPath: /tmp/pigeonlocalcache + #### If Enabled persistence < ---------- + # - name: data + # mountPath: /var/lib/pigeonlocaldata/ + + sidecars: [] # same as additionalContainers, but maybe you prefer this name more :) + + additionalContainers: + - name: sanic + inheritVolumeMountsFrom: sanic # <----- gets volume mounts from sanic set of vars above + inheritResourcesFrom: sanic # <----- gets resources from sanic set of vars above + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: "{{ .Values.image.pullPolicy }}" + command: + - /bin/sh + - -c + - python3 -m osf_pigeon + env: [] + envFrom: + - configMapRef: + name: '{{ include "cos-common.fullname" (dict "root" . "name" "common-env") | trim }}' + - secretRef: + name: '{{ include "cos-common.fullname" (dict "root" . "name" "common-env") | trim }}' + - configMapRef: + name: '{{ include "cos-common.fullname" (dict "root" . "name" "sanic-env") | trim }}' + ports: + - name: http-external + containerPort: "{{ .Values.main.http.containers.nginx.externalPort }}" + protocol: TCP + readinessProbe: + httpGet: + path: / + port: "{{ .Values.main.http.containers.nginx.externalPort }}" + + +# ------- Volumes configuration for the pod ------- + volumes: + - name: localcache + emptyDir: {} + - name: config + configMap: + name: '{{ include "cos-common.fullname" (dict "root" . "name" "") | trim }}' + - name: secret + secret: + secretName: '{{ include "cos-common.fullname" (dict "root" . "name" "") | trim }}' + + additionalVolumes: + - name: data + emptyDir: {} + #### If Enabled persistence < ---------- + # -----> Option 1 to create persistent volume + # + # - name: data # PVC name will be: '{{ include "cos-common.fullname" (dict "root" . "name" "") | trim }}' + name + # persistence: + # enabled: true + # accessModes: + # - ReadWriteOnce + # size: 100Gi + # storageClass: "" + # existingClaim: "" + + # -----> Option 2 to create persistent volume + # + # - name: data + # persistentVolumeClaim: + # claimName: '{{ include "cos-common.fullname" (dict "root" . "name" "") | trim }}' + + # -----> Option 2 to create persistent volume + # + # PVC name will be '{{ include "cos-common.fullname" (dict "root" . "name" "") | trim }}' + # + # persistence: + # enabled: true + # accessModes: + # - ReadWriteOnce + # size: 100Gi + # storageClass: "" + # existingClaim: "" + + +# ------- Affitnity configuration ------- + affinity: {} + # podAntiAffinity: + # preferredDuringSchedulingIgnoredDuringExecution: + # - weight: 1 + # podAffinityTerm: + # topologyKey: kubernetes.io/hostname + # labelSelector: + # matchLabels: + # app.kubernetes.io/name: "{{ .Chart.Name }}" + # app.kubernetes.io/instance: "{{ .Release.Name }}" + # app.kubernetes.io/component: "{{ .Chart.Name }}" # in this case component name = chart name, because we leave component name in main.yaml empty. + + additionalAffinities: [] + + +# ------- Pod Annotations ------- + podAnnotations: + checksum/main-config: '{{ include "cos-common.componentChecksum" (dict "root" . "name" "" "values" .Values.main "resource" "configmap") }}' + checksum/main-config-sanic-env: '{{ include "cos-common.componentChecksum" (dict "root" . "name" "sanic-env" "values" .Values.main "resource" "configmap") }}' + checksum/main-config-common-env: '{{ include "cos-common.componentChecksum" (dict "root" . "name" "common-env" "values" .Values.main "resource" "configmap") }}' + checksum/main-secret: '{{ include "cos-common.componentChecksum" (dict "root" . "name" "" "values" .Values.main "resource" "secret") }}' + checksum/main-secret-common-env: '{{ include "cos-common.componentChecksum" (dict "root" . "name" "common-env" "values" .Values.main "resource" "secret") }}' + + +# ------- Service configuration ------- +# service name: '{{ include "cos-common.fullname" (dict "root" . "name" "") | trim }}' + service: + enabled: true + type: "{{ .Values.main.http.containers.nginx.serviceType }}" + ports: + - name: http + port: "{{ .Values.main.http.containers.nginx.externalPort }}" + targetPort: "{{ .Values.main.http.containers.nginx.internalPort }}" + protocol: TCP + + +# ------- Ingress configuration ------- +# ingress name: '{{ include "cos-common.fullname" (dict "root" . "name" "") | trim }}' + ingress: enabled: false - internalPort: 18080 - statusZoneSize: 10m - defaultFilterKey: "$geoip_country_code country::*" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + primary: + - chart-example.local + rules: + - name: main + includeForPrimaryHost: true + includeForAdditionalHost: false + pathType: ImplementationSpecific + service: + name: '{{ include "cos-common.fullname" (dict "root" . "name" "") | trim }}' + port: "{{ .Values.main.http.containers.nginx.externalPort }}" + paths: + - / + tls: [] + # - secretName: secret_name + # hosts: + # - chart-example.local -sanic: - resources: {} - # limits: - # cpu: 100m - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi - -horizontalPodAutoscaler: - enabled: false - maxReplicas: 3 - targetCPUUtilizationPercentage: 90 - -service: - name: http - type: ClusterIP - externalPort: 2020 - internalPort: 80 - -ingress: - enabled: false - # Used to create Ingress record (should used with service.type: ClusterIP). - hosts: - - chart-example.local - annotations: - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - paths: - - / - tls: - # Secrets must be manually created in the namespace. - # - secretName: osf-io-tls - # hosts: - # - chart-example.local - -certificate: - enabled: false - name: cert - # WORKAROUND: Ingress deploy blocked to GLBC due to race condition w/ missing TLS certificate - # - Issue: https://github.com/jetstack/cert-manager/issues/606 - # - PR: https://github.com/kubernetes/ingress-gce/pull/388 - tls: true - # issuerRef: - # name: letsencrypt-prod - # kind: ClusterIssuer - # commonName: example.org - # dnsNames: - # - example.org - # - subdomain.example.org - # acmeConfig: - # http01: {} - # # ingress: '' - # domains: - # - example.org - # - subdomain.example.org - -networkPolicy: - enabled: false - # Allows external access to the pod, otherwise access is restricted to - # clients with the explicit label. - allowExternal: true - egress: {} - # - to: - # - namespaceSelector: {} - # ports: - # - port: 53 # dns - # protocol: TCP - # - port: 53 # dns - # protocol: UDP - # - to: - # - ipBlock: - # cidr: 0.0.0.0/0 - # except: - # - 10.0.0.0/8 - # - 172.16.0.0/12 - # - 192.168.0.0/16 - # ports: - # - port: 80 # http - # protocol: TCP - # - port: 443 # https - # protocol: TCP - -configEnvs: {} - # DEBUG: "" - -configFiles: {} - # Override configmap files here (and delete the {} above), e.g.: - #robots.txt: |- - # User-agent: * - # Disallow: / - -secretEnvs: {} - # DATACITE_USERNAME: "CHANGEME" - # DATACITE_PASSWORD: "CHANGEME" - # OSF_BEARER_TOKEN: "CHANGEME" - # IA_ACCESS_KEY: "CHANGEME" - # IA_SECRET_KEY: CHANGEME - -## Enable persistence using Persistent Volume Claims -## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ -## -persistence: - enabled: false - ## Persistent Volume Storage Class - ## If defined, storageClassName: - ## If set to "-", storageClassName: "", which disables dynamic provisioning - ## If undefined (the default) or set to null, no storageClassName spec is - ## set, choosing the default provisioner. (gp2 on AWS, standard on - ## GKE, AWS & OpenStack) - ## - # storageClass: "-" - accessModes: - - ReadWriteOnce - size: 100Gi - - mountPath: /var/lib/pigeonlocaldata/ + +# ------- Certificate configuration ------- (if we want to create Certificate object) +# cert name: '{{ include "cos-common.fullname" (dict "root" . "name" "cert") | trim }}' + certificate: + enabled: false + # secretName: secret-with-cert # default secret name is certificate name + issuerRef: + name: letsencrypt-prod + kind: ClusterIssuer + commonName: example.org + dnsNames: + - example.org + acmeConfig: + http01: {} + # ingress: '' + domains: + - example.org + - subdomain.example.org + + # additionalCertificates: + # # cert name: '{{ include "cos-common.fullname" (dict "root" . "name" "certificate") | trim }}' + name + # - name: example-org-cert + # enabled: false + # # secretName: secret-with-cert + # commonName: example.org + # dnsNames: + # - example.org + # - submdomain.example.org + # issuerRef: + # name: letsencrypt-prod + # kind: ClusterIssuer + # acmeConfig: + # http01: {} + # # ingress: '' + # domains: + # - example.org + # - subdomain.example.org + + +# ------- HPA configuration ------- + hpa: + enabled: false + minReplicas: "{{ .Values.main.replicas }}" + maxReplicas: 3 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 90 + + +# ------- PDB configuration ------- + pdb: + enabled: false + minAvailable: 1 + + +# ------- Network Policy configuration ------- +# Network Policy name: '{{ include "cos-common.fullname" (dict "root" . "name" "") | trim }}' + networkPolicy: + enabled: false + componentScoped: true # this network policy will be applied to all components + ingressRules: + - ports: + - port: "{{ .Values.main.http.containers.nginx.internalPort }}" + from: + - podSelector: + matchLabels: + '{{ include "cos-common.fullname" (dict "root" . "name" "client") | trim }}': "true" + - ports: + - port: "{{ .Values.main.nginx.vts.internalPort }}" + egressRules: + - {} + +# Additional network Policy name: '{{ include "cos-common.fullname" (dict "root" . "name" "") | trim }}' + name + additionalNetworkPolicies: + - name: cert-solver + enabled: false + podSelector: + matchExpressions: + - key: acme.cert-manager.io/http01-solver + operator: Exists + ingressRules: + - from: [] + + +# ------- ConfigMap configuration ------- +# ConfigMap name: '{{ include "cos-common.fullname" (dict "root" . "name" "") | trim }}' + configMap: + enabled: true + tpl: true + data: + robots.txt: | + {{ .Files.Get "files/robots.txt" }} + nginx.conf: | + {{ tpl (.Files.Get "files/nginx.conf") (dict "Values" .Values "root" .) }} + +# configmap name: '{{ include "cos-common.fullname" (dict "root" . "name" "") | trim }}' + name + additionalConfigMaps: + - name: common-env + enabled: true + tpl: false + data: {} + - name: sanic-env + enabled: true + tpl: false + data: {} + #### If Enabled persistence < ---------- + # PIGEON_FILESTORE_DIR: /var/lib/pigeonlocaldata/ + # Provide other envs for sanic + + +# ------- Secrets configuration ------- +# Secret name: '{{ include "cos-common.fullname" (dict "root" . "name" "") | trim }}' + secret: + enabled: true + includeTls: false + data: {} + +# secret name: '{{ include "cos-common.fullname" (dict "root" . "name" "") | trim }}' + name + additionalSecrets: + - name: common-env + enabled: true + includeTls: false + data: {} + + +# ------- Selectors and etc. ------- + nodeSelector: {} + + +# ------- Other variables which are used accross files or values.yaml ------- + nginx: + workerCount: 1 + proxySourceRanges: [] + realIpHeader: X-Real-IP + realIpRecursive: "off" + vts: + enabled: false + internalPort: 18080 + statusZoneSize: 10m + defaultFilterKey: "$geoip_country_code country::*"