feat: deploy
This commit is contained in:
parent
9bbf8a96aa
commit
842f8b727e
6 changed files with 620 additions and 0 deletions
272
deploy/helm/go-guess/README.md
Normal file
272
deploy/helm/go-guess/README.md
Normal file
|
|
@ -0,0 +1,272 @@
|
||||||
|
# Go Guess Helm chart
|
||||||
|
|
||||||
|
This chart deploys Go Guess as two images, an API and a web front end, plus its
|
||||||
|
own PostgreSQL and RabbitMQ, and publishes one HTTPS host per tenant under
|
||||||
|
`https://<tenant>.guess.local`.
|
||||||
|
|
||||||
|
## 1. What the chart creates
|
||||||
|
|
||||||
|
| Resource | Name | Purpose |
|
||||||
|
|---|---|---|
|
||||||
|
| Deployment | `go-guess-api` | Go API, runs migrations and seeds before serving |
|
||||||
|
| Deployment | `go-guess-web` | nginx serving the built React application |
|
||||||
|
| Service | `api` | Cluster-internal API, proxied by the web image |
|
||||||
|
| Service | `go-guess-web` | Cluster-internal web front end, ingress backend |
|
||||||
|
| Ingress | `go-guess` | One rule and one TLS SAN per tenant host |
|
||||||
|
| Issuer | `go-guess-selfsigned` | cert-manager self-signed issuer |
|
||||||
|
| Certificate | `go-guess-web-ca` | Chart CA that signs the leaf certificate |
|
||||||
|
| Certificate | `go-guess-web` | Leaf certificate covering every tenant host |
|
||||||
|
| StatefulSet | `go-guess-postgresql` | PostgreSQL, `emptyDir` or persistent volume |
|
||||||
|
| StatefulSet | `go-guess-rabbitmq` | RabbitMQ, `emptyDir` or persistent volume |
|
||||||
|
| Secret | `go-guess-secrets` | JWT secret, connection URLs, broker credentials |
|
||||||
|
|
||||||
|
A single web deployment serves every tenant host. The API resolves the tenant
|
||||||
|
from the request `Host` header, so adding a tenant means adding one entry to
|
||||||
|
`tenants`, not deploying another stack.
|
||||||
|
|
||||||
|
## 2. Prerequisites
|
||||||
|
|
||||||
|
- A Kubernetes cluster reachable through `KUBECONFIG`.
|
||||||
|
- A `StorageClass` when `postgresql.persistence.enabled` or
|
||||||
|
`rabbitmq.persistence.enabled` is `true`.
|
||||||
|
- ingress-nginx with the `nginx` ingress class: `make ingress-nginx-install`.
|
||||||
|
- cert-manager when `ingress.tls.enabled` is `true`: `make cert-manager-install`.
|
||||||
|
- Cluster nodes trusting `batty1039.startdedicated.net:5000` as an insecure
|
||||||
|
registry, or an HTTPS registry.
|
||||||
|
|
||||||
|
Run everything the chart depends on in one step:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make cluster-prepare
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. Deploy
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make helm-lint
|
||||||
|
make helm-deploy-development
|
||||||
|
```
|
||||||
|
|
||||||
|
The development profile uses `latest` images, development fixtures, ephemeral
|
||||||
|
storage, and namespace `go-insane-development`. Production uses released tags,
|
||||||
|
production fixtures, persistent volumes, and namespace `go-insane-production`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make helm-deploy-production
|
||||||
|
```
|
||||||
|
|
||||||
|
Both targets accept per-tenant Go Loose credentials from the environment:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export GO_LOOSE_NMBS_CLIENT_ID=...
|
||||||
|
export GO_LOOSE_NMBS_CLIENT_SECRET=...
|
||||||
|
export GO_LOOSE_YPTO_CLIENT_ID=...
|
||||||
|
export GO_LOOSE_YPTO_CLIENT_SECRET=...
|
||||||
|
make helm-deploy-production
|
||||||
|
```
|
||||||
|
|
||||||
|
After a successful install the release notes list every tenant URL and the
|
||||||
|
command that exports the CA certificate. With the local platform, prefer
|
||||||
|
`docs/KUBERNETES-DEPLOYMENTS.md` in the infrastructure repository, which covers
|
||||||
|
`/etc/hosts` entries and CA trust for the whole platform.
|
||||||
|
|
||||||
|
## 4. Tenants and hosts
|
||||||
|
|
||||||
|
`tenants` is the list of slugs and `domain` is the shared parent domain:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
domain: guess.local
|
||||||
|
tenants:
|
||||||
|
- nmbs
|
||||||
|
- ypto
|
||||||
|
```
|
||||||
|
|
||||||
|
The chart derives, without any extra configuration:
|
||||||
|
|
||||||
|
- `GO_LOOSE_APP_DOMAIN=guess.local`, so the API accepts `nmbs.guess.local` and
|
||||||
|
`ypto.guess.local` as tenant hosts.
|
||||||
|
- One ingress rule per tenant, all pointing at `go-guess-web`.
|
||||||
|
- One certificate SAN per tenant, so a single secret covers every host.
|
||||||
|
- `FRONTEND_URL`, when `api.frontendURL` is empty, as
|
||||||
|
`https://<first tenant>.<domain>`. This is the fallback used to build
|
||||||
|
invitation and meeting links, so the first entry is the tenant that receives
|
||||||
|
shareable links.
|
||||||
|
|
||||||
|
A slug must be a single DNS label. The API rejects slugs containing a dot, and
|
||||||
|
the certificate would not match a two-level host.
|
||||||
|
|
||||||
|
Adding a tenant therefore requires three things: the slug in `tenants`, a DNS
|
||||||
|
record pointing at the ingress controller, and a Go Loose client when browser
|
||||||
|
sign-in is used.
|
||||||
|
|
||||||
|
## 5. Values
|
||||||
|
|
||||||
|
### Top level
|
||||||
|
|
||||||
|
| Key | Default | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `nameOverride` | `""` | Overrides the chart name in resource names and labels |
|
||||||
|
| `fullnameOverride` | `""` | Replaces the generated resource name prefix |
|
||||||
|
| `domain` | `guess.local` | Parent domain of every tenant host |
|
||||||
|
| `tenants` | `[nmbs, ypto]` | Tenant slugs served by the release |
|
||||||
|
| `imagePullSecrets` | `[]` | Pull secrets added to both pods |
|
||||||
|
|
||||||
|
### api
|
||||||
|
|
||||||
|
| Key | Default | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `api.replicaCount` | `1` | API replicas, keep at `1` while migrations run on startup |
|
||||||
|
| `api.image.repository` | `batty1039.startdedicated.net:5000/go-guess-api` | API image |
|
||||||
|
| `api.image.tag` | `0.0.1` | API image tag |
|
||||||
|
| `api.image.pullPolicy` | `IfNotPresent` | API pull policy |
|
||||||
|
| `api.environment` | `development` | `APP_ENV`, `production` seeds production fixtures only |
|
||||||
|
| `api.frontendURL` | `""` | Fallback public URL for invitation and meeting links |
|
||||||
|
| `api.tokenTTL` | `8h` | `TOKEN_TTL` for issued API tokens |
|
||||||
|
| `api.maxUploadMB` | `10` | `MAX_UPLOAD_MB` upload limit, match `proxy-body-size` |
|
||||||
|
| `api.service.name` | `api` | Service DNS name, fixed by the web image |
|
||||||
|
| `api.service.type` | `ClusterIP` | API service type |
|
||||||
|
| `api.service.port` | `8080` | API service port |
|
||||||
|
| `api.goLoose.enabled` | `false` | Enables Go Loose browser sign-in |
|
||||||
|
| `api.goLoose.authDomain` | `auth.dev` | Tenant login host `https://<tenant>.<authDomain>` |
|
||||||
|
| `api.goLoose.ca.existingSecret` | `""` | Secret holding the Go Loose CA bundle |
|
||||||
|
| `api.goLoose.ca.key` | `ca.crt` | Key projected from that secret |
|
||||||
|
| `api.goLoose.ca.mountPath` | `/certs/local-ca.crt` | `GO_LOOSE_CA_FILE` target |
|
||||||
|
| `api.goLoose.tenants.<slug>.clientID` | `""` | Go Loose client ID for that tenant |
|
||||||
|
| `api.goLoose.tenants.<slug>.clientSecret` | `""` | Go Loose client secret for that tenant |
|
||||||
|
| `api.resources` | `50m`/`128Mi` to `500m`/`512Mi` | API requests and limits |
|
||||||
|
| `api.podAnnotations`, `api.podLabels` | `{}` | Extra pod metadata |
|
||||||
|
| `api.podSecurityContext` | `{}` | Pod security context |
|
||||||
|
| `api.securityContext` | non-root, read-only root filesystem | Container security context |
|
||||||
|
| `api.strategy.type` | `Recreate` | Old pod exits before migrations run again |
|
||||||
|
|
||||||
|
### web
|
||||||
|
|
||||||
|
| Key | Default | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `web.replicaCount` | `2` | nginx replicas, safe to scale because nginx is stateless |
|
||||||
|
| `web.image.repository` | `batty1039.startdedicated.net:5000/go-guess-web` | Web image |
|
||||||
|
| `web.image.tag` | `0.0.1` | Web image tag |
|
||||||
|
| `web.image.pullPolicy` | `IfNotPresent` | Web pull policy |
|
||||||
|
| `web.service.type` | `ClusterIP` | Web service type |
|
||||||
|
| `web.service.port` | `80` | Web service port |
|
||||||
|
| `web.service.nodePort` | `null` | Node port when the type is `NodePort` |
|
||||||
|
| `web.resources` | `25m`/`32Mi` to `300m`/`128Mi` | Web requests and limits |
|
||||||
|
| `web.podAnnotations`, `web.podLabels` | `{}` | Extra pod metadata |
|
||||||
|
| `web.podSecurityContext` | `{}` | Pod security context |
|
||||||
|
| `web.securityContext` | root, `NET_BIND_SERVICE` only | Container security context |
|
||||||
|
| `web.strategy` | rolling, `maxUnavailable: 0` | Keeps the ingress backed up during rollout |
|
||||||
|
|
||||||
|
Neither container has a forced uid. Both images declare their own user, the API
|
||||||
|
as `app` and nginx as `nginx`, and `runAsNonRoot` validates it.
|
||||||
|
|
||||||
|
The web security context differs from the API one on purpose. nginx binds the
|
||||||
|
privileged port `80` and forks workers as the `nginx` user, so the pod runs as
|
||||||
|
root with `CHOWN`, `SETGID`, `SETUID`, and `NET_BIND_SERVICE`, and mounts
|
||||||
|
writable `emptyDir` volumes at `/var/cache/nginx`, `/var/run`, and `/tmp`.
|
||||||
|
|
||||||
|
### ingress
|
||||||
|
|
||||||
|
| Key | Default | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `ingress.enabled` | `true` | Creates the multi-host ingress |
|
||||||
|
| `ingress.className` | `nginx` | Ingress class of the controller |
|
||||||
|
| `ingress.annotations` | body size `10m`, timeouts `3600`, buffering off, TLS redirect | Controller annotations |
|
||||||
|
| `ingress.path` | `/` | Path routed to the web service |
|
||||||
|
| `ingress.pathType` | `Prefix` | Path type of that route |
|
||||||
|
| `ingress.tls.enabled` | `true` | Terminates TLS on the controller |
|
||||||
|
| `ingress.tls.secretName` | `""` | Defaults to `<fullname>-web-tls` |
|
||||||
|
| `ingress.tls.existingSecret` | `""` | Uses a certificate managed outside the chart |
|
||||||
|
|
||||||
|
The proxy annotations matter for the interview feature: the API streams events
|
||||||
|
over server-sent events and accepts video uploads, so buffering off, a one-hour
|
||||||
|
read timeout, and a body size at least as large as `api.maxUploadMB` are
|
||||||
|
required, otherwise streams stall and uploads fail with `413`.
|
||||||
|
|
||||||
|
### certManager
|
||||||
|
|
||||||
|
| Key | Default | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `certManager.enabled` | `true` | Chart creates the certificates |
|
||||||
|
| `certManager.issuerRef` | `{}` | Uses an existing issuer instead of the chart CA |
|
||||||
|
| `certManager.duration` | `8760h` | Certificate lifetime |
|
||||||
|
| `certManager.renewBefore` | `720h` | Renewal window |
|
||||||
|
| `certManager.caSecretName` | `""` | Defaults to `<fullname>-web-ca` |
|
||||||
|
|
||||||
|
Three certificate objects are created in order: a self-signed `Issuer`, a CA
|
||||||
|
`Certificate` stored in `caSecretName`, and the leaf `Certificate` stored in the
|
||||||
|
ingress TLS secret with one `dnsNames` entry per tenant. Set `issuerRef` to sign
|
||||||
|
with a cluster issuer instead, for example an internal ACME issuer:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
certManager:
|
||||||
|
issuerRef:
|
||||||
|
name: internal-acme
|
||||||
|
kind: ClusterIssuer
|
||||||
|
group: cert-manager.io
|
||||||
|
```
|
||||||
|
|
||||||
|
Set `ingress.tls.existingSecret` to use a certificate the chart does not own,
|
||||||
|
and `certManager.enabled: false` to stop emitting cert-manager objects.
|
||||||
|
|
||||||
|
### Secrets, storage, and scheduling
|
||||||
|
|
||||||
|
| Key | Default | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `secrets.jwtSecret` | `""` | Generated and preserved across upgrades when empty |
|
||||||
|
| `secrets.databaseURL` | derived | Full URL, required when PostgreSQL is disabled |
|
||||||
|
| `secrets.rabbitmqURL` | derived | Full URL, required when RabbitMQ is disabled |
|
||||||
|
| `secrets.postgresqlPassword` | generated | PostgreSQL user password |
|
||||||
|
| `secrets.rabbitmqPassword` | generated | RabbitMQ user password |
|
||||||
|
| `postgresql.enabled` | `true` | Bundled PostgreSQL |
|
||||||
|
| `postgresql.persistence.enabled` | `true` | Persistent volume instead of `emptyDir` |
|
||||||
|
| `postgresql.persistence.size` | `8Gi` | Volume size |
|
||||||
|
| `postgresql.auth.username` | `go_guess` | Database user |
|
||||||
|
| `rabbitmq.enabled` | `true` | Bundled RabbitMQ |
|
||||||
|
| `rabbitmq.persistence.enabled` | `true` | Persistent volume instead of `emptyDir` |
|
||||||
|
| `rabbitmq.persistence.size` | `4Gi` | Volume size |
|
||||||
|
| `nodeSelector`, `tolerations`, `affinity` | empty | Applied to both deployments |
|
||||||
|
|
||||||
|
Generated secrets are read back with `lookup` on upgrade, so leaving them empty
|
||||||
|
rotates nothing and keeps sessions valid across releases.
|
||||||
|
|
||||||
|
## 6. External services
|
||||||
|
|
||||||
|
Disable the bundled StatefulSets and pass full connection URLs to use managed
|
||||||
|
PostgreSQL and RabbitMQ:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm upgrade --install go-guess deploy/helm/go-guess \
|
||||||
|
--namespace go-insane-production --create-namespace \
|
||||||
|
-f deploy/helm/go-guess/values-production.yaml \
|
||||||
|
--set postgresql.enabled=false \
|
||||||
|
--set rabbitmq.enabled=false \
|
||||||
|
--set-string secrets.databaseURL="$DATABASE_URL" \
|
||||||
|
--set-string secrets.rabbitmqURL="$RABBITMQ_URL"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 7. Upgrade and remove
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make helm-deploy-production
|
||||||
|
helm -n go-insane-production history go-guess
|
||||||
|
helm -n go-insane-production rollback go-guess 1
|
||||||
|
make helm-down-production
|
||||||
|
```
|
||||||
|
|
||||||
|
Uninstalling removes the release secrets, so store `secrets.jwtSecret` and the
|
||||||
|
two connection URLs outside the cluster before deleting a release whose database
|
||||||
|
must survive.
|
||||||
|
|
||||||
|
## 8. Verify
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl -n go-insane-production get ingress go-guess
|
||||||
|
kubectl -n go-insane-production get certificate
|
||||||
|
kubectl -n go-insane-production rollout status deployment/go-guess-api
|
||||||
|
kubectl -n go-insane-production rollout status deployment/go-guess-web
|
||||||
|
curl --resolve nmbs.guess.local:443:127.0.0.1 --cacert go-guess-ca.crt \
|
||||||
|
https://nmbs.guess.local/api/health
|
||||||
|
```
|
||||||
|
|
||||||
|
The test pod installed by `helm test` checks the API health endpoint and the web
|
||||||
|
root from inside the cluster.
|
||||||
148
deploy/helm/go-guess/templates/api-deployment.yaml
Normal file
148
deploy/helm/go-guess/templates/api-deployment.yaml
Normal file
|
|
@ -0,0 +1,148 @@
|
||||||
|
{{- include "go-guess.validate" . -}}
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: {{ include "go-guess.apiDeploymentName" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "go-guess.labels" . | nindent 4 }}
|
||||||
|
app.kubernetes.io/component: api
|
||||||
|
spec:
|
||||||
|
replicas: {{ .Values.api.replicaCount }}
|
||||||
|
strategy:
|
||||||
|
type: {{ .Values.api.strategy.type }}
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
{{- include "go-guess.selectorLabels" . | nindent 6 }}
|
||||||
|
app.kubernetes.io/component: api
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
checksum/secrets: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }}
|
||||||
|
{{- with .Values.api.podAnnotations }}
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
labels:
|
||||||
|
{{- include "go-guess.selectorLabels" . | nindent 8 }}
|
||||||
|
app.kubernetes.io/component: api
|
||||||
|
{{- with .Values.api.podLabels }}
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
automountServiceAccountToken: false
|
||||||
|
{{- with .Values.imagePullSecrets }}
|
||||||
|
imagePullSecrets:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
securityContext:
|
||||||
|
{{- toYaml .Values.api.podSecurityContext | nindent 8 }}
|
||||||
|
containers:
|
||||||
|
- name: api
|
||||||
|
image: "{{ .Values.api.image.repository }}:{{ .Values.api.image.tag }}"
|
||||||
|
imagePullPolicy: {{ .Values.api.image.pullPolicy }}
|
||||||
|
securityContext:
|
||||||
|
{{- toYaml .Values.api.securityContext | nindent 12 }}
|
||||||
|
env:
|
||||||
|
- name: APP_ENV
|
||||||
|
value: {{ .Values.api.environment | quote }}
|
||||||
|
- name: FRONTEND_URL
|
||||||
|
value: {{ include "go-guess.frontendURL" . | quote }}
|
||||||
|
- name: TOKEN_TTL
|
||||||
|
value: {{ .Values.api.tokenTTL | quote }}
|
||||||
|
- name: MAX_UPLOAD_MB
|
||||||
|
value: {{ .Values.api.maxUploadMB | quote }}
|
||||||
|
- name: DATABASE_URL
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: {{ include "go-guess.secretName" . }}
|
||||||
|
key: database-url
|
||||||
|
- name: RABBITMQ_URL
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: {{ include "go-guess.secretName" . }}
|
||||||
|
key: rabbitmq-url
|
||||||
|
- name: JWT_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: {{ include "go-guess.secretName" . }}
|
||||||
|
key: jwt-secret
|
||||||
|
{{- if .Values.api.goLoose.enabled }}
|
||||||
|
- name: GO_LOOSE_AUTH_DOMAIN
|
||||||
|
value: {{ .Values.api.goLoose.authDomain | quote }}
|
||||||
|
- name: GO_LOOSE_APP_DOMAIN
|
||||||
|
value: {{ .Values.domain | quote }}
|
||||||
|
{{- if .Values.api.goLoose.ca.existingSecret }}
|
||||||
|
- name: GO_LOOSE_CA_FILE
|
||||||
|
value: {{ .Values.api.goLoose.ca.mountPath | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- range $tenant, $credentials := .Values.api.goLoose.tenants }}
|
||||||
|
{{- $envPrefix := printf "GO_LOOSE_%s" (upper $tenant) }}
|
||||||
|
{{- $keyPrefix := printf "go-loose-%s" (lower $tenant) }}
|
||||||
|
{{- if $credentials.clientID }}
|
||||||
|
- name: {{ $envPrefix }}_CLIENT_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: {{ include "go-guess.secretName" $ }}
|
||||||
|
key: {{ $keyPrefix }}-client-id
|
||||||
|
{{- end }}
|
||||||
|
{{- if $credentials.clientSecret }}
|
||||||
|
- name: {{ $envPrefix }}_CLIENT_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: {{ include "go-guess.secretName" $ }}
|
||||||
|
key: {{ $keyPrefix }}-client-secret
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 8080
|
||||||
|
protocol: TCP
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /api/health
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 5
|
||||||
|
timeoutSeconds: 3
|
||||||
|
failureThreshold: 12
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /api/health
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 20
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 3
|
||||||
|
failureThreshold: 3
|
||||||
|
resources:
|
||||||
|
{{- toYaml .Values.api.resources | nindent 12 }}
|
||||||
|
volumeMounts:
|
||||||
|
- name: temporary-files
|
||||||
|
mountPath: /tmp
|
||||||
|
{{- if and .Values.api.goLoose.enabled .Values.api.goLoose.ca.existingSecret }}
|
||||||
|
- name: go-loose-ca
|
||||||
|
mountPath: {{ dir .Values.api.goLoose.ca.mountPath }}
|
||||||
|
readOnly: true
|
||||||
|
{{- end }}
|
||||||
|
volumes:
|
||||||
|
- name: temporary-files
|
||||||
|
emptyDir: {}
|
||||||
|
{{- if and .Values.api.goLoose.enabled .Values.api.goLoose.ca.existingSecret }}
|
||||||
|
- name: go-loose-ca
|
||||||
|
secret:
|
||||||
|
secretName: {{ .Values.api.goLoose.ca.existingSecret }}
|
||||||
|
items:
|
||||||
|
- key: {{ .Values.api.goLoose.ca.key }}
|
||||||
|
path: {{ base .Values.api.goLoose.ca.mountPath }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.nodeSelector }}
|
||||||
|
nodeSelector:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.affinity }}
|
||||||
|
affinity:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.tolerations }}
|
||||||
|
tolerations:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
18
deploy/helm/go-guess/templates/api-service.yaml
Normal file
18
deploy/helm/go-guess/templates/api-service.yaml
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
# Kept as the literal name "api": the web image proxies /api/ to api:8080.
|
||||||
|
name: {{ include "go-guess.apiServiceName" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "go-guess.labels" . | nindent 4 }}
|
||||||
|
app.kubernetes.io/component: api
|
||||||
|
spec:
|
||||||
|
type: {{ .Values.api.service.type }}
|
||||||
|
selector:
|
||||||
|
{{- include "go-guess.selectorLabels" . | nindent 4 }}
|
||||||
|
app.kubernetes.io/component: api
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: {{ .Values.api.service.port }}
|
||||||
|
targetPort: http
|
||||||
|
protocol: TCP
|
||||||
76
deploy/helm/go-guess/templates/certificate.yaml
Normal file
76
deploy/helm/go-guess/templates/certificate.yaml
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
{{- if and .Values.ingress.enabled .Values.ingress.tls.enabled .Values.certManager.enabled }}
|
||||||
|
{{- $fullname := include "go-guess.fullname" . }}
|
||||||
|
{{- $caSecret := include "go-guess.certManagerCASecretName" . }}
|
||||||
|
{{- $tlsSecret := include "go-guess.tlsSecretName" . }}
|
||||||
|
{{- if not .Values.certManager.issuerRef }}
|
||||||
|
apiVersion: cert-manager.io/v1
|
||||||
|
kind: Issuer
|
||||||
|
metadata:
|
||||||
|
name: {{ $fullname }}-selfsigned
|
||||||
|
labels:
|
||||||
|
{{- include "go-guess.labels" . | nindent 4 }}
|
||||||
|
app.kubernetes.io/component: certificate
|
||||||
|
spec:
|
||||||
|
selfSigned: {}
|
||||||
|
---
|
||||||
|
apiVersion: cert-manager.io/v1
|
||||||
|
kind: Certificate
|
||||||
|
metadata:
|
||||||
|
name: {{ $fullname }}-web-ca
|
||||||
|
labels:
|
||||||
|
{{- include "go-guess.labels" . | nindent 4 }}
|
||||||
|
app.kubernetes.io/component: certificate
|
||||||
|
spec:
|
||||||
|
secretName: {{ $caSecret }}
|
||||||
|
commonName: {{ printf "%s-ca" $fullname }}
|
||||||
|
duration: {{ .Values.certManager.duration }}
|
||||||
|
renewBefore: {{ .Values.certManager.renewBefore }}
|
||||||
|
privateKey:
|
||||||
|
algorithm: ECDSA
|
||||||
|
size: 256
|
||||||
|
issuerRef:
|
||||||
|
name: {{ $fullname }}-selfsigned
|
||||||
|
kind: Issuer
|
||||||
|
group: cert-manager.io
|
||||||
|
---
|
||||||
|
apiVersion: cert-manager.io/v1
|
||||||
|
kind: Issuer
|
||||||
|
metadata:
|
||||||
|
name: {{ $fullname }}-web-ca
|
||||||
|
labels:
|
||||||
|
{{- include "go-guess.labels" . | nindent 4 }}
|
||||||
|
app.kubernetes.io/component: certificate
|
||||||
|
spec:
|
||||||
|
ca:
|
||||||
|
secretName: {{ $caSecret }}
|
||||||
|
---
|
||||||
|
{{- end }}
|
||||||
|
apiVersion: cert-manager.io/v1
|
||||||
|
kind: Certificate
|
||||||
|
metadata:
|
||||||
|
name: {{ $fullname }}-web
|
||||||
|
labels:
|
||||||
|
{{- include "go-guess.labels" . | nindent 4 }}
|
||||||
|
app.kubernetes.io/component: certificate
|
||||||
|
spec:
|
||||||
|
secretName: {{ $tlsSecret }}
|
||||||
|
duration: {{ .Values.certManager.duration }}
|
||||||
|
renewBefore: {{ .Values.certManager.renewBefore }}
|
||||||
|
privateKey:
|
||||||
|
algorithm: ECDSA
|
||||||
|
size: 256
|
||||||
|
usages:
|
||||||
|
- server auth
|
||||||
|
dnsNames:
|
||||||
|
{{- range .Values.tenants }}
|
||||||
|
- {{ printf "%s.%s" . $.Values.domain | quote }}
|
||||||
|
{{- end }}
|
||||||
|
issuerRef:
|
||||||
|
{{- if .Values.certManager.issuerRef }}
|
||||||
|
{{- include "go-guess.certManagerIssuerRef" . | nindent 4 }}
|
||||||
|
{{- else }}
|
||||||
|
name: {{ $fullname }}-web-ca
|
||||||
|
kind: Issuer
|
||||||
|
group: cert-manager.io
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
89
deploy/helm/go-guess/templates/web-deployment.yaml
Normal file
89
deploy/helm/go-guess/templates/web-deployment.yaml
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: {{ include "go-guess.webDeploymentName" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "go-guess.labels" . | nindent 4 }}
|
||||||
|
app.kubernetes.io/component: web
|
||||||
|
spec:
|
||||||
|
replicas: {{ .Values.web.replicaCount }}
|
||||||
|
strategy:
|
||||||
|
{{- toYaml .Values.web.strategy | nindent 4 }}
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
{{- include "go-guess.selectorLabels" . | nindent 6 }}
|
||||||
|
app.kubernetes.io/component: web
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
{{- with .Values.web.podAnnotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
labels:
|
||||||
|
{{- include "go-guess.selectorLabels" . | nindent 8 }}
|
||||||
|
app.kubernetes.io/component: web
|
||||||
|
{{- with .Values.web.podLabels }}
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
automountServiceAccountToken: false
|
||||||
|
{{- with .Values.imagePullSecrets }}
|
||||||
|
imagePullSecrets:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
securityContext:
|
||||||
|
{{- toYaml .Values.web.podSecurityContext | nindent 8 }}
|
||||||
|
containers:
|
||||||
|
- name: web
|
||||||
|
image: "{{ .Values.web.image.repository }}:{{ .Values.web.image.tag }}"
|
||||||
|
imagePullPolicy: {{ .Values.web.image.pullPolicy }}
|
||||||
|
securityContext:
|
||||||
|
{{- toYaml .Values.web.securityContext | nindent 12 }}
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 80
|
||||||
|
protocol: TCP
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 3
|
||||||
|
periodSeconds: 5
|
||||||
|
timeoutSeconds: 3
|
||||||
|
failureThreshold: 6
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 3
|
||||||
|
failureThreshold: 3
|
||||||
|
resources:
|
||||||
|
{{- toYaml .Values.web.resources | nindent 12 }}
|
||||||
|
volumeMounts:
|
||||||
|
- name: nginx-cache
|
||||||
|
mountPath: /var/cache/nginx
|
||||||
|
- name: nginx-run
|
||||||
|
mountPath: /var/run
|
||||||
|
- name: temporary-files
|
||||||
|
mountPath: /tmp
|
||||||
|
volumes:
|
||||||
|
- name: nginx-cache
|
||||||
|
emptyDir: {}
|
||||||
|
- name: nginx-run
|
||||||
|
emptyDir: {}
|
||||||
|
- name: temporary-files
|
||||||
|
emptyDir: {}
|
||||||
|
{{- with .Values.nodeSelector }}
|
||||||
|
nodeSelector:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.affinity }}
|
||||||
|
affinity:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.tolerations }}
|
||||||
|
tolerations:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
17
deploy/helm/go-guess/templates/web-service.yaml
Normal file
17
deploy/helm/go-guess/templates/web-service.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{ include "go-guess.webDeploymentName" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "go-guess.labels" . | nindent 4 }}
|
||||||
|
app.kubernetes.io/component: web
|
||||||
|
spec:
|
||||||
|
type: {{ .Values.web.service.type }}
|
||||||
|
selector:
|
||||||
|
{{- include "go-guess.selectorLabels" . | nindent 4 }}
|
||||||
|
app.kubernetes.io/component: web
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: {{ .Values.web.service.port }}
|
||||||
|
targetPort: http
|
||||||
|
protocol: TCP
|
||||||
Loading…
Add table
Add a link
Reference in a new issue