🔨(CI) add Tilt

Tilt is a tool for local Kubernetes development.
It makes it easy to see your changes as you
make them, and it rebuilds and redeploys
your app as you change it.
It is a great tool for local development
and testing of Kubernetes applications.
This commit is contained in:
Anthony LC
2024-04-11 11:00:50 +02:00
committed by Anthony LC
parent 0dc1be4cc7
commit dbb592bc9a
13 changed files with 198 additions and 3 deletions

View File

@@ -25,7 +25,7 @@ COPY ./src/frontend/packages/eslint-config-impress/package.json ./packages/eslin
RUN yarn --frozen-lockfile
### ---- Front-end builder image ----
FROM node:20 as frontend-builder
FROM node:20 as frontend-builder-1
WORKDIR /builder
@@ -34,6 +34,8 @@ COPY ./src/frontend .
WORKDIR /builder/apps/impress
FROM frontend-builder-1 as frontend-builder-2
RUN yarn build
@@ -44,7 +46,7 @@ FROM nginxinc/nginx-unprivileged:1.25 as frontend-production
ARG DOCKER_USER
USER ${DOCKER_USER}
COPY --from=frontend-builder \
COPY --from=frontend-builder-2 \
/builder/apps/impress/out \
/usr/share/nginx/html
@@ -83,7 +85,7 @@ RUN yarn install --frozen-lockfile && \
# ---- static link collector ----
FROM base as link-collector
ARG PEOPLE_STATIC_ROOT=/data/static
ARG IMPRESS_STATIC_ROOT=/data/static
# Install libpangocairo & rdfind
RUN apt-get update && \

71
Tiltfile Normal file
View File

@@ -0,0 +1,71 @@
load('ext://uibutton', 'cmd_button', 'bool_input', 'location')
load('ext://namespace', 'namespace_create', 'namespace_inject')
namespace_create('impress')
docker_build(
'localhost:5001/impress-backend:latest',
context='.',
dockerfile='./Dockerfile',
only=['./src/backend', './src/mail', './docker'],
target = 'backend-development',
live_update=[
sync('./src/backend', '/app'),
run(
'pip install -r /app/requirements.txt',
trigger=['./api/requirements.txt']
)
]
)
docker_build(
'localhost:5001/impress-frontend:latest',
context='.',
dockerfile='./Dockerfile',
build_args={'ENV': 'dev'},
only=['./src/frontend', './src/mail', './docker'],
target = 'frontend-builder-1',
live_update=[
sync('./src/frontend', '/builder'),
]
)
k8s_yaml(local('cd src/helm && helmfile -n impress -e dev template .'))
migration = '''
set -eu
# get k8s pod name from tilt resource name
POD_NAME="$(tilt get kubernetesdiscovery impress-backend -ojsonpath='{.status.pods[0].name}')"
kubectl -n impress exec "$POD_NAME" -- python manage.py makemigrations
'''
cmd_button('Make migration',
argv=['sh', '-c', migration],
resource='impress-backend',
icon_name='developer_board',
text='Run makemigration',
)
pod_migrate = '''
set -eu
# get k8s pod name from tilt resource name
POD_NAME="$(tilt get kubernetesdiscovery impress-backend -ojsonpath='{.status.pods[0].name}')"
kubectl -n impress exec "$POD_NAME" -- python manage.py migrate --no-input
'''
cmd_button('Migrate db',
argv=['sh', '-c', pod_migrate],
resource='impress-backend',
icon_name='developer_board',
text='Run database migration',
)
pod_add_admin = '''
set -eu
# get k8s pod name from tilt resource name
POD_NAME="$(tilt get kubernetesdiscovery impress-backend -ojsonpath='{.status.pods[0].name}')"
kubectl -n impress exec "$POD_NAME" -- python manage.py createsuperuser --email admin@example.com --password admin
'''
cmd_button('Add admin',
argv=['sh', '-c', pod_add_admin],
resource='impress-backend',
icon_name='developer_board',
text='Create superadmin',
)

View File

@@ -0,0 +1 @@
NEXT_PUBLIC_API_URL=https://impress.127.0.0.1.nip.io/api/v1.0/

View File

@@ -4,6 +4,7 @@ image:
tag: "latest"
backend:
replicas: 1
envVars:
DJANGO_CSRF_TRUSTED_ORIGINS: https://impress.127.0.0.1.nip.io,http://impress.127.0.0.1.nip.io
DJANGO_CONFIGURATION: Production
@@ -38,6 +39,15 @@ backend:
REDIS_URL: redis://default:pass@redis-master:6379/1
frontend:
envVars:
PORT: 8080
NEXT_PUBLIC_API_URL: https://impress.127.0.0.1.nip.io/api/v1.0/
replicas: 1
command:
- yarn
- dev
image:
repository: localhost:5001/impress-frontend
pullPolicy: Always

View File

@@ -26,6 +26,7 @@ releases:
values:
- auth:
password: pass
architecture: standalone
- name: extra
installed: {{ ne .Environment.Name "dev" | toYaml }}

View File

@@ -5,6 +5,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ $fullName }}
namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "impress.common.labels" (list . $component) | nindent 4 }}
spec:

View File

@@ -5,6 +5,7 @@ apiVersion: batch/v1
kind: Job
metadata:
name: {{ $fullName }}-migrate
namespace: {{ .Release.Namespace | quote }}
{{- with .Values.backend.migrateJobAnnotations }}
annotations:
{{- toYaml . | nindent 4 }}

View File

@@ -5,6 +5,7 @@ apiVersion: v1
kind: Service
metadata:
name: {{ $fullName }}
namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "impress.common.labels" (list . $component) | nindent 4 }}
annotations:

View File

@@ -5,6 +5,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ $fullName }}
namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "impress.common.labels" (list . $component) | nindent 4 }}
spec:

View File

@@ -5,6 +5,7 @@ apiVersion: v1
kind: Service
metadata:
name: {{ $fullName }}
namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "impress.common.labels" (list . $component) | nindent 4 }}
annotations:

View File

@@ -15,6 +15,7 @@ apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: {{ $fullName }}
namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "impress.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}

View File

@@ -15,6 +15,7 @@ apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: {{ $fullName }}-admin
namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "impress.labels" . | nindent 4 }}
{{- with .Values.ingressAdmin.annotations }}

103
start-kind.sh Normal file
View File

@@ -0,0 +1,103 @@
#!/bin/sh
set -o errexit
CURRENT_DIR=$(pwd)
echo "0. Create ca"
# 0. Create ca
mkcert -install
cd /tmp
mkcert "127.0.0.1.nip.io" "*.127.0.0.1.nip.io"
cd $CURRENT_DIR
echo "1. Create registry container unless it already exists"
# 1. Create registry container unless it already exists
reg_name='kind-registry'
reg_port='5001'
if [ "$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" != 'true' ]; then
docker run \
-d --restart=always -p "127.0.0.1:${reg_port}:5000" --network bridge --name "${reg_name}" \
registry:2
fi
echo "2. Create kind cluster with containerd registry config dir enabled"
# 2. Create kind cluster with containerd registry config dir enabled
# TODO: kind will eventually enable this by default and this patch will
# be unnecessary.
#
# See:
# https://github.com/kubernetes-sigs/kind/issues/2875
# https://github.com/containerd/containerd/blob/main/docs/cri/config.md#registry-configuration
# See: https://github.com/containerd/containerd/blob/main/docs/hosts.md
cat <<EOF | kind create cluster --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
containerdConfigPatches:
- |-
[plugins."io.containerd.grpc.v1.cri".registry]
config_path = "/etc/containerd/certs.d"
nodes:
- role: control-plane
image: kindest/node:v1.27.3
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
extraPortMappings:
- containerPort: 80
hostPort: 80
protocol: TCP
- containerPort: 443
hostPort: 443
protocol: TCP
- role: worker
image: kindest/node:v1.27.3
- role: worker
image: kindest/node:v1.27.3
EOF
echo "3. Add the registry config to the nodes"
# 3. Add the registry config to the nodes
#
# This is necessary because localhost resolves to loopback addresses that are
# network-namespace local.
# In other words: localhost in the container is not localhost on the host.
#
# We want a consistent name that works from both ends, so we tell containerd to
# alias localhost:${reg_port} to the registry container when pulling images
REGISTRY_DIR="/etc/containerd/certs.d/localhost:${reg_port}"
for node in $(kind get nodes); do
docker exec "${node}" mkdir -p "${REGISTRY_DIR}"
cat <<EOF | docker exec -i "${node}" cp /dev/stdin "${REGISTRY_DIR}/hosts.toml"
[host."http://${reg_name}:5000"]
EOF
done
echo "4. Connect the registry to the cluster network if not already connected"
# 4. Connect the registry to the cluster network if not already connected
# This allows kind to bootstrap the network but ensures they're on the same network
if [ "$(docker inspect -f='{{json .NetworkSettings.Networks.kind}}' "${reg_name}")" = 'null' ]; then
docker network connect "kind" "${reg_name}"
fi
echo "5. Document the local registry"
# 5. Document the local registry
# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: local-registry-hosting
namespace: kube-public
data:
localRegistryHosting.v1: |
host: "localhost:${reg_port}"
help: "https://kind.sigs.k8s.io/docs/user/local-registry/"
EOF
echo "6. Install ingress-nginx"
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
kubectl -n ingress-nginx create secret tls mkcert --key /tmp/127.0.0.1.nip.io+1-key.pem --cert /tmp/127.0.0.1.nip.io+1.pem
kubectl -n ingress-nginx patch deployments.apps ingress-nginx-controller --type 'json' -p '[{"op": "add", "path": "/spec/template/spec/containers/0/args/-", "value":"--default-ssl-certificate=ingress-nginx/mkcert"}]'