Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
akurilov committed Oct 6, 2024
1 parent a7dfaed commit 941d7f2
Showing 16 changed files with 639 additions and 0 deletions.
24 changes: 24 additions & 0 deletions helm/int-email/.helmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# 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/
values-dev.yaml
24 changes: 24 additions & 0 deletions helm/int-email/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
apiVersion: v2
name: int-email
description: A Helm chart for Awakari int-email

# 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.0.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: "latest"
22 changes: 22 additions & 0 deletions helm/int-email/templates/NOTES.txt
Original file line number Diff line number Diff line change
@@ -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 "int-email.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 "int-email.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "int-email.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 "int-email.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:50051 to use your application"
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 50051:$CONTAINER_PORT
{{- end }}
62 changes: 62 additions & 0 deletions helm/int-email/templates/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "int-email.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 "int-email.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 "int-email.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Common labels
*/}}
{{- define "int-email.labels" -}}
helm.sh/chart: {{ include "int-email.chart" . }}
{{ include "int-email.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{/*
Selector labels
*/}}
{{- define "int-email.selectorLabels" -}}
app.kubernetes.io/name: {{ include "int-email.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

{{/*
Create the name of the service account to use
*/}}
{{- define "int-email.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "int-email.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}
7 changes: 7 additions & 0 deletions helm/int-email/templates/configmap-ingress-tcp.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: "{{ include "int-email.fullname" . }}-ingress-service"
namespace: "{{ .Release.Namespace }}"
data:
"{{ .Values.service.port }}": "default/smtp-service:{{ .Values.service.port }}"
116 changes: 116 additions & 0 deletions helm/int-email/templates/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "int-email.fullname" . }}
labels:
{{- include "int-email.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "int-email.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "int-email.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "int-email.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
priorityClassName: "{{ .Values.priority.class }}"
containers:
- name: {{ .Chart.Name }}
env:
- name: API_PORT
value: "{{ .Values.service.port }}"
- name: API_SMTP_PORT
value: "{{ .Values.service.port }}"
{{- range .Values.ingress.hosts }}
- name: API_SMTP_HOST
value: "{{ .host }}"
{{- end }}
- name: API_EVENT_TYPE
value: "{{ .Values.api.event.type }}"
- name: API_INTERESTS_URI
value: "{{ .Values.api.interests.uri }}"
- name: API_INTERESTS_DETAILS_URI_PREFIX
value: "{{ .Values.api.interests.detailsUriPrefix }}"
- name: API_WRITER_BACKOFF
value: "{{ .Values.api.writer.backoff }}"
- name: API_WRITER_BATCH_SIZE
value: "{{ .Values.api.writer.batchSize }}"
- name: API_WRITER_CACHE_SIZE
value: "{{ .Values.api.writer.cache.size }}"
- name: API_WRITER_CACHE_TTL
value: "{{ .Values.api.writer.cache.ttl }}"
- name: API_WRITER_URI
value: "{{ .Values.api.writer.uri }}"
- name: API_READER_URI
value: "{{ .Values.api.reader.uri }}"
- name: API_READER_URI_EVT_BASE
value: "{{ .Values.api.reader.uriEvtBase }}"
- name: LOG_LEVEL
value: "{{ .Values.log.level }}"
- name: API_KEY_PUBLIC
valueFrom:
secretKeyRef:
name: "{{ include "int-email.fullname" . }}-keys"
key: public
- name: API_KEY_PRIVATE
valueFrom:
secretKeyRef:
name: "{{ include "int-email.fullname" . }}-keys"
key: private
- name: DB_TABLE_RETENTION_PERIOD_FOLLOWING
value: "{{ .Values.db.table.retention.following }}"
- name: API_EVENT_TYPE_SELF
value: "{{ .Values.api.event.typ.self }}"
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: smtp
containerPort: {{ .Values.service.port }}
protocol: TCP
livenessProbe:
tcpSocket:
port: {{ .Values.service.port }}
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
tcpSocket:
port: {{ .Values.service.port }}
initialDelaySeconds: 10
periodSeconds: 10
resources:
{{- toYaml .Values.resources | nindent 12 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app.kubernetes.io/name: {{ include "int-email.name" . }}
32 changes: 32 additions & 0 deletions helm/int-email/templates/hpa.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: {{ include "int-email.fullname" . }}
labels:
{{- include "int-email.labels" . | nindent 4 }}
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "int-email.fullname" . }}
minReplicas: {{ .Values.autoscaling.minReplicas }}
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
metrics:
{{- if .Values.autoscaling.targetCPUUtilizationValue }}
- type: Resource
resource:
name: cpu
target:
type: AverageValue
averageValue: {{ .Values.autoscaling.targetCPUUtilizationValue }}
{{- end }}
{{- if .Values.autoscaling.targetMemoryUtilizationValue }}
- type: Resource
resource:
name: memory
target:
type: AverageValue
averageValue: {{ .Values.autoscaling.targetMemoryUtilizationValue }}
{{- end }}
{{- end }}
66 changes: 66 additions & 0 deletions helm/int-email/templates/ingress.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "int-email.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
{{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
{{- end }}
{{- end }}
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1beta1
{{- else -}}
apiVersion: extensions/v1beta1
{{- end }}
kind: Ingress
metadata:
name: "{{ $fullName }}-smtp"
labels:
{{- include "int-email.labels" . | nindent 4 }}
annotations:
{{/* kubernetes.io/ingress.class: nginx*/}}
{{/* nginx.ingress.kubernetes.io/ssl-redirect: "true"*/}}
{{/* nginx.ingress.kubernetes.io/force-ssl-redirect: "true"*/}}
{{/* cert-manager.io/issuer: "{{ .Values.cert.issuer.name }}-int-email"*/}}
nginx.ingress.kubernetes.io/backend-protocol: "TCP" # Tell ingress to use TCP (if possible)
ingress.kubernetes.io/server-snippet: |
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
spec:
{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
{{- 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 }}"
{{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
pathType: {{ .pathType }}
{{- end }}
backend:
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
service:
name: {{ $fullName }}
port:
number: {{ $svcPort }}
{{- else }}
serviceName: {{ $fullName }}
servicePort: {{ $svcPort }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
15 changes: 15 additions & 0 deletions helm/int-email/templates/issuer-letsencrypt.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{{- $fullName := include "int-email.fullname" . -}}
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: "{{ .Values.cert.issuer.name }}-int-email"
spec:
acme:
server: {{ .Values.cert.acme.server }}
email: {{ .Values.cert.acme.email }}
privateKeySecretRef:
name: {{ .Values.cert.issuer.name }}
solvers:
- http01:
ingress:
name: "{{ $fullName }}"
54 changes: 54 additions & 0 deletions helm/int-email/templates/job-secrets-backup.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
apiVersion: batch/v1
kind: CronJob
metadata:
name: "{{ include "int-email.fullname" . }}-secrets-backup"
spec:
schedule: "{{ .Values.backup.secrets.schedule }}"
jobTemplate:
spec:
template:
spec:
containers:
- name: "{{ include "int-email.fullname" . }}-secrets-backup"
image: "{{ .Values.backup.secrets.image }}"
env:
{{- if .Values.ingress.tls }}
{{- range .Values.ingress.tls }}
- name: SECRET_TLS_CRT
valueFrom:
secretKeyRef:
name: "{{ .secretName }}"
key: "tls.crt"
- name: SECRET_TLS_KEY
valueFrom:
secretKeyRef:
name: "{{ .secretName }}"
key: "tls.key"
{{- end}}
{{- end}}
volumeMounts:
- name: "{{ .Values.backup.secrets.volume.name }}"
mountPath: /var/backup
readOnly: false
command:
- "/bin/sh"
- "-c"
- |
mkdir -p /var/backup/{{ include "int-email.fullname" . }}
if [ -n "$SECRET_TLS_CRT" ]; then # Check if secret is not empty
echo "Original secret tls.crt is not empty. Creating backup..."
echo "$SECRET_TLS_CRT" > /var/backup/{{ include "int-email.fullname" . }}/tls.crt
else
echo "Original secret tls.crt is empty. Skipping backup."
fi
if [ -n "$SECRET_TLS_KEY" ]; then # Check if secret is not empty
echo "Original secret tls.key is not empty. Creating backup..."
echo "$SECRET_TLS_KEY" > /var/backup/{{ include "int-email.fullname" . }}/tls.key
else
echo "Original secret tls.key is empty. Skipping backup."
fi
restartPolicy: OnFailure
volumes:
- name: "{{ .Values.backup.secrets.volume.name }}"
persistentVolumeClaim:
claimName: "{{ .Values.backup.secrets.volume.name }}"
30 changes: 30 additions & 0 deletions helm/int-email/templates/job-secrets-restore.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
apiVersion: batch/v1
kind: CronJob
metadata:
name: "{{ include "int-email.fullname" . }}-secrets-restore"
spec:
schedule: "{{ .Values.backup.secrets.restore.schedule }}"
jobTemplate:
spec:
template:
spec:
containers:
- name: "{{ include "int-email.fullname" . }}-secrets-restore"
image: "{{ .Values.backup.secrets.restore.image }}"
volumeMounts:
- name: "{{ .Values.backup.secrets.volume.name }}"
mountPath: /var/backup
readOnly: false
command:
- "/bin/sh"
- "-c"
- |
echo "/var/backup/{{ include "int-email.fullname" . }}/tls.crt"
cat /var/backup/{{ include "int-email.fullname" . }}/tls.crt
echo "/var/backup/{{ include "int-email.fullname" . }}/tls.key"
cat /var/backup/{{ include "int-email.fullname" . }}/tls.key
restartPolicy: OnFailure
volumes:
- name: "{{ .Values.backup.secrets.volume.name }}"
persistentVolumeClaim:
claimName: "{{ .Values.backup.secrets.volume.name }}"
15 changes: 15 additions & 0 deletions helm/int-email/templates/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "int-email.fullname" . }}
labels:
{{- include "int-email.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: smtp
protocol: TCP
name: smtp
selector:
{{- include "int-email.selectorLabels" . | nindent 4 }}
12 changes: 12 additions & 0 deletions helm/int-email/templates/serviceaccount.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "int-email.serviceAccountName" . }}
labels:
{{- include "int-email.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
15 changes: 15 additions & 0 deletions helm/int-email/templates/tests/test-connection.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "int-email.fullname" . }}-test-connection"
labels:
{{- include "int-email.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": test
spec:
containers:
- name: wget
image: busybox
command: ['wget']
args: ['{{ include "int-email.fullname" . }}:{{ .Values.service.port }}']
restartPolicy: Never
25 changes: 25 additions & 0 deletions helm/int-email/values-awakari-com.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
api:
event:
type: "com_awakari_email_v1"
interests:
detailsUriPrefix: "https://awakari.com/sub-details.html?id="
writer:
uri: "api:50051"

# prod
cert:
acme:
server: "https://acme-v02.api.letsencrypt.org/directory"
issuer:
name: letsencrypt

ingress:
hosts:
- host: email.awakari.com
paths:
- path: /
pathType: ImplementationSpecific
tls:
- secretName: int-email-tls-server
hosts:
- email.awakari.com
120 changes: 120 additions & 0 deletions helm/int-email/values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# Default values for int-email.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

replicaCount: 1

image:
repository: ghcr.io/awakari/int-email
pullPolicy: Always
tag: "latest"
imagePullSecrets:
- name: github-registry
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: 25

ingress:
enabled: true
hosts:
- host: int-email.local
paths:
- path: /
pathType: ImplementationSpecific
tls:
- secretName: int-email-tls-server
hosts:
- int-email.local

resources:
requests:
cpu: 1m
memory: 16Mi
limits:
cpu: 100m
memory: 64Mi

autoscaling:
enabled: true
minReplicas: 1
maxReplicas: 10
targetCPUUtilizationValue: 100m
targetMemoryUtilizationValue: 64Mi

priority:
class: "awk-major"

nodeSelector: {}

tolerations: []

affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: spot
operator: In
values:
- "true"

api:
event:
typ:
self: "com_awakari_email_v1"
interests:
uri: "subscriptions-proxy:50051"
detailsUriPrefix: "https://awakari.com/sub-details.html?id="
reader:
uriEvtBase: "https://awakari.com/pub-msg.html?id="
writer:
backoff: "10s"
batchSize: 16
cache:
size: 100
ttl: "24h"
uri: "resolver:50051"
backup:
secrets:
image: "alpine:3.20"
schedule: "0 0 * * 1" # weekly
restore:
image: "alpine:3.20"
schedule: "0 0 31 2 *" # never, manually only
volume:
name: "backup-secrets"
cert:
acme:
email: "awakari@awakari.com"
server: "https://acme-staging-v02.api.letsencrypt.org/directory"
issuer:
name: letsencrypt-staging
log:
# https://pkg.go.dev/golang.org/x/exp/slog#Level
level: -4

0 comments on commit 941d7f2

Please sign in to comment.