Merge pull request #6 from MealCraft/feature/traefik_who_am_i
Feature/traefik who am i
This commit is contained in:
commit
8ae3d78fad
18 changed files with 510 additions and 282 deletions
97
.github/workflows/juntekim.yml
vendored
Normal file
97
.github/workflows/juntekim.yml
vendored
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
name: Build juntekim.com
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "*"
|
||||
branches:
|
||||
- "**"
|
||||
|
||||
jobs:
|
||||
Push-to-docker-hub:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Inject slug/short variables
|
||||
uses: rlespinasse/github-slug-action@v4
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_HUB_TOKEN }}
|
||||
|
||||
- name: Build Docker Image
|
||||
run: |
|
||||
docker build \
|
||||
-f juntekim_frontend/deployment/Dockerfile \
|
||||
-t docker.io/kimjunte/portfolio_page:$GITHUB_REF_SLUG \
|
||||
juntekim_frontend
|
||||
|
||||
- name: Push to Docker Hub
|
||||
run: |
|
||||
docker push docker.io/kimjunte/portfolio_page:$GITHUB_REF_SLUG
|
||||
|
||||
|
||||
run-on-k8s:
|
||||
runs-on: mealcraft-runners # <-- your ARC scale set label
|
||||
needs: Push-to-docker-hub
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# Install kubectl inside containerMode's default Ubuntu
|
||||
- name: Install kubectl
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y curl ca-certificates
|
||||
curl -LO "https://dl.k8s.io/release/$(curl -sL https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
|
||||
sudo install -m 0755 kubectl /usr/local/bin/kubectl
|
||||
|
||||
- name: Install envsubst
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y gettext # <---- envsubst lives here
|
||||
|
||||
# Configure kubeconfig from ARC's service account
|
||||
- name: Configure kubeconfig
|
||||
run: |
|
||||
KUBE_HOST="https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT"
|
||||
SA_TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
|
||||
CA_CERT=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
|
||||
NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)
|
||||
|
||||
kubectl config set-cluster microk8s --server="$KUBE_HOST" --certificate-authority="$CA_CERT"
|
||||
kubectl config set-credentials runner --token="$SA_TOKEN"
|
||||
kubectl config set-context runner-context --cluster=microk8s --user=runner --namespace="$NAMESPACE"
|
||||
kubectl config use-context runner-context
|
||||
|
||||
- name: Inject slug variables
|
||||
uses: rlespinasse/github-slug-action@v4
|
||||
|
||||
- name: Set namespace
|
||||
id: ns
|
||||
run: |
|
||||
if [[ $GITHUB_REF == refs/tags/* ]]; then
|
||||
echo "NAMESPACE=default" >> $GITHUB_ENV
|
||||
else
|
||||
echo "NAMESPACE=staging" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Set hostname
|
||||
run: |
|
||||
if [ "$NAMESPACE" = "staging" ]; then
|
||||
echo "HOSTNAME=staging.juntekim.com" >> $GITHUB_ENV
|
||||
else
|
||||
echo "HOSTNAME=juntekim.com" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Deploy to Kubernetes
|
||||
run: |
|
||||
export IMAGE="docker.io/kimjunte/portfolio_page:$GITHUB_REF_SLUG"
|
||||
export NAMESPACE HOSTNAME
|
||||
|
||||
envsubst < juntekim_frontend/deployment/deployment.yml | kubectl apply -f -
|
||||
envsubst < juntekim_frontend/deployment/service.yml | kubectl apply -f -
|
||||
envsubst < juntekim_frontend/deployment/ingressroute.yml | kubectl apply -f -
|
||||
207
.github/workflows/k8s_traefik_init_setup.yml
vendored
207
.github/workflows/k8s_traefik_init_setup.yml
vendored
|
|
@ -4,127 +4,116 @@ on:
|
|||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
bootstrap:
|
||||
runs-on: mealcraft-runners
|
||||
container: ubuntu:22.04
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Job 1: Build and push image using GitHub-hosted runner
|
||||
# -----------------------------------------------------
|
||||
build-image:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
# -----------------------------------------------------
|
||||
# Checkout
|
||||
# -----------------------------------------------------
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Install kubectl
|
||||
# -----------------------------------------------------
|
||||
- name: Install kubectl
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get install -y ca-certificates curl
|
||||
curl -LO "https://dl.k8s.io/release/$(curl -sL https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
|
||||
install -m 0755 kubectl /usr/local/bin/kubectl
|
||||
# Docker login on GitHub-hosted runner (has Docker)
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_HUB_TOKEN }}
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Configure kubeconfig using the ARC pod token
|
||||
# -----------------------------------------------------
|
||||
- name: Configure kubeconfig
|
||||
run: |
|
||||
KUBE_HOST="https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT"
|
||||
SA_TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
|
||||
CA_CERT=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
|
||||
NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)
|
||||
# Build and push using real Docker daemon
|
||||
- name: Build & Push Traefik Image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: ./traefik
|
||||
file: ./traefik/Dockerfile
|
||||
push: true
|
||||
tags: |
|
||||
docker.io/kimjunte/edge_router:${{ github.sha }}
|
||||
docker.io/kimjunte/edge_router:latest
|
||||
|
||||
kubectl config set-cluster microk8s --server="$KUBE_HOST" --certificate-authority="$CA_CERT"
|
||||
kubectl config set-credentials runner --token="$SA_TOKEN"
|
||||
kubectl config set-context runner-context --cluster=microk8s --user=runner --namespace="$NAMESPACE"
|
||||
kubectl config use-context runner-context
|
||||
# -----------------------------------------------------
|
||||
# Job 2: Deploy to MicroK8s using ARC self-hosted runner
|
||||
# -----------------------------------------------------
|
||||
deploy:
|
||||
runs-on: mealcraft-runners
|
||||
needs: build-image
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Docker Login
|
||||
# -----------------------------------------------------
|
||||
- name: Docker Login
|
||||
uses: ./.github/actions/docker-login
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_HUB_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Build & Push the Docker Image (idempotent)
|
||||
# -----------------------------------------------------
|
||||
- name: Build Traefik Image
|
||||
run: |
|
||||
docker build traefik \
|
||||
--file traefik/Dockerfile \
|
||||
--tag docker.io/kimjunte/edge_router:$GITHUB_SHA
|
||||
# Install kubectl inside containerMode's default Ubuntu
|
||||
- name: Install kubectl
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y curl ca-certificates
|
||||
curl -LO "https://dl.k8s.io/release/$(curl -sL https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
|
||||
sudo install -m 0755 kubectl /usr/local/bin/kubectl
|
||||
|
||||
- name: Push Traefik Image
|
||||
run: |
|
||||
docker push docker.io/kimjunte/edge_router:$GITHUB_SHA
|
||||
# Configure kubeconfig from ARC's service account
|
||||
- name: Configure kubeconfig
|
||||
run: |
|
||||
KUBE_HOST="https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT"
|
||||
SA_TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
|
||||
CA_CERT=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
|
||||
NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Apply Storage Classes + PVCs — idempotent with apply
|
||||
# -----------------------------------------------------
|
||||
- name: Apply StorageClass + PV
|
||||
run: |
|
||||
kubectl apply -f traefik/storageclass/storageclass.yaml
|
||||
kubectl apply -f traefik/storageclass/certs-pv.yaml
|
||||
kubectl get storageclass
|
||||
kubectl config set-cluster microk8s --server="$KUBE_HOST" --certificate-authority="$CA_CERT"
|
||||
kubectl config set-credentials runner --token="$SA_TOKEN"
|
||||
kubectl config set-context runner-context --cluster=microk8s --user=runner --namespace="$NAMESPACE"
|
||||
kubectl config use-context runner-context
|
||||
|
||||
# -----------------------------------------------------
|
||||
# ⭐ Inject AWS secrets needed for Traefik Route53 DNS
|
||||
# -----------------------------------------------------
|
||||
- name: Apply AWS Secrets
|
||||
run: |
|
||||
kubectl create secret generic aws-secrets \
|
||||
--namespace=default \
|
||||
--from-literal=AWS_ACCESS_KEY_ID='${{ secrets.AWS_ACCESS_KEY_ID }}' \
|
||||
--from-literal=AWS_SECRET_ACCESS_KEY='${{ secrets.AWS_SECRET_ACCESS_KEY }}' \
|
||||
--from-literal=AWS_REGION='${{ secrets.AWS_REGION }}' \
|
||||
--dry-run=client -o yaml | kubectl apply -f -
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Apply Traefik CRDs only if missing
|
||||
# -----------------------------------------------------
|
||||
- name: Install Traefik CRDs (idempotent)
|
||||
run: |
|
||||
if ! kubectl get crd ingressroutes.traefik.containo.us >/dev/null 2>&1; then
|
||||
echo "Traefik CRDs not found — installing..."
|
||||
kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.10/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml
|
||||
kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.10/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml
|
||||
kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.10/docs/content/user-guides/crd-acme/05-tlsoption.yml
|
||||
else
|
||||
echo "Traefik CRDs already installed — skipping."
|
||||
fi
|
||||
# Apply storage classes + PVs
|
||||
- name: Apply StorageClass + PV
|
||||
run: |
|
||||
kubectl apply -f traefik/storageclass/storageclass.yaml
|
||||
kubectl apply -f traefik/storageclass/certs-pv.yaml
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Deploy Traefik — idempotent with kubectl apply
|
||||
# -----------------------------------------------------
|
||||
- name: Deploy Traefik (safe repeat)
|
||||
run: |
|
||||
echo "Applying Traefik PVC/Deployments/Services/etc…"
|
||||
kubectl apply -f traefik/edge-router/pvc.yaml
|
||||
kubectl apply -f traefik/edge-router/traefik-deployment.yml
|
||||
kubectl apply -f traefik/edge-router/traefik-services.yml
|
||||
kubectl apply -f traefik/edge-router/middleware.yaml
|
||||
kubectl apply -f traefik/edge-router/secret-dashboard.yml
|
||||
kubectl apply -f traefik/edge-router/traefik-ingressroute.yml
|
||||
# # Install Traefik CRDs (idempotent)
|
||||
# - name: Install Traefik CRDs
|
||||
# run: |
|
||||
# kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.11/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml
|
||||
# kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.11/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Deploy whoami — idempotent
|
||||
# -----------------------------------------------------
|
||||
- name: Deploy whoami test service
|
||||
run: |
|
||||
kubectl apply -f traefik/who-am-i/whoami-deployment.yml
|
||||
kubectl apply -f traefik/who-am-i/whoami-service.yml
|
||||
kubectl apply -f traefik/who-am-i/whoami-ingressroute.yml
|
||||
# Deploy Traefik
|
||||
- name: Deploy Traefik
|
||||
run: |
|
||||
kubectl apply -f traefik/edge-router/pvc.yaml
|
||||
kubectl apply -f traefik/edge-router/traefik-deployment.yml
|
||||
kubectl apply -f traefik/edge-router/traefik-services.yml
|
||||
kubectl apply -f traefik/edge-router/middleware.yaml
|
||||
kubectl apply -f traefik/edge-router/secret-dashboard.yml
|
||||
kubectl apply -f traefik/edge-router/traefik-ingressroute.yml
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Create Docker Registry Secrets — idempotent
|
||||
# -----------------------------------------------------
|
||||
- name: Create registry secret (default ns)
|
||||
run: |
|
||||
kubectl apply -f traefik/docker-registry-credentials/docker-credentials.yml
|
||||
# Deploy whoami test app
|
||||
- name: Deploy whoami
|
||||
run: |
|
||||
kubectl apply -f traefik/who-am-i/whoami-deployment.yml
|
||||
kubectl apply -f traefik/who-am-i/whoami-service.yml
|
||||
kubectl apply -f traefik/who-am-i/whoami-ingressroute.yml
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Create staging namespace if not exists
|
||||
# -----------------------------------------------------
|
||||
- name: Create staging namespace
|
||||
run: |
|
||||
kubectl get namespace staging >/dev/null 2>&1 || kubectl create namespace staging
|
||||
# Registry secret
|
||||
- name: Create registry secret (default)
|
||||
run: kubectl apply -f traefik/docker-registry-credentials/docker-credentials.yml
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Apply registry secret to staging — idempotent
|
||||
# -----------------------------------------------------
|
||||
- name: Registry secret in staging namespace
|
||||
run: |
|
||||
sed 's/namespace: default/namespace: staging/' \
|
||||
traefik/docker-registry-credentials/docker-credentials.yml \
|
||||
| kubectl apply -f -
|
||||
# Staging namespace
|
||||
- name: Create staging namespace
|
||||
run: kubectl get ns staging >/dev/null 2>&1 || kubectl create namespace staging
|
||||
|
||||
- name: Registry secret to staging
|
||||
run: |
|
||||
sed 's/namespace: default/namespace: staging/' \
|
||||
traefik/docker-registry-credentials/docker-credentials.yml \
|
||||
| kubectl apply -f -
|
||||
|
|
|
|||
33
.vscode/settings.json
vendored
33
.vscode/settings.json
vendored
|
|
@ -1,19 +1,32 @@
|
|||
{
|
||||
"jupyter.interactiveWindow.textEditor.executeSelection": true,
|
||||
"python.REPL.sendToNativeREPL": true,
|
||||
"notebook.output.scrolling": true,
|
||||
"terminal.integrated.defaultProfile.linux": "bash",
|
||||
"editor.rulers": [67],
|
||||
"terminal.integrated.profiles.linux": {
|
||||
"bash": {
|
||||
"path": "/bin/bash"
|
||||
}
|
||||
},
|
||||
|
||||
// Hot reload setting that needs to be in user settings
|
||||
// "jupyter.runStartupCommands": [
|
||||
// "%load_ext autoreload", "%autoreload 2"
|
||||
// ]
|
||||
|
||||
// --- VIM SETTINGS ---
|
||||
"vim.useSystemClipboard": true,
|
||||
"vim.enableNeovim": false,
|
||||
|
||||
// Allow VSCode native keybindings to override Vim when needed
|
||||
"vim.handleKeys": {
|
||||
"<C-p>": false,
|
||||
"<C-P>": false,
|
||||
"<C-S-p>": false,
|
||||
"<C-c>": false,
|
||||
"<C-v>": false,
|
||||
"<C-S-v>": false,
|
||||
"<C-S-c>": false
|
||||
},
|
||||
|
||||
// Make Y, y, p always sync with the system clipboard
|
||||
|
||||
// Terminal copy/paste via Ctrl+Shift+C / Ctrl+Shift+V
|
||||
"terminal.integrated.copyOnSelection": false,
|
||||
"terminal.integrated.commandsToSkipShell": [
|
||||
"workbench.action.terminal.copySelection",
|
||||
"workbench.action.terminal.paste"
|
||||
],
|
||||
|
||||
}
|
||||
18
README.md
18
README.md
|
|
@ -2,17 +2,15 @@ TODO:
|
|||
|
||||
- [x] Get a basic nextjs app set up
|
||||
- [x] Set up new laptop github workflow
|
||||
|
||||
|
||||
- [x] Download next js
|
||||
- [x] Aws terraform plan and apply configured
|
||||
- [] Deploy into my new k8s
|
||||
- [x] k get pods -A works
|
||||
- [] deploy docker registry credentials
|
||||
- [] deploy storageclass
|
||||
- [] deloy traefik customised
|
||||
- [] deploy who-am-i
|
||||
|
||||
- Traefik certs change to staging
|
||||
- May need to move aws terraform here too
|
||||
- [] Deploy into my dockercontainer new image
|
||||
- [x] deploy docker registry credentials
|
||||
- [x] deploy storageclass
|
||||
- [x] deloy traefik customised
|
||||
- [x] deploy who-am-i
|
||||
- [] deploy next js to juntekim.com
|
||||
- [] Traefik certs change from staging to production
|
||||
- [] Merge my code to main
|
||||
- [] Push from workflow k8s bootstrap
|
||||
|
|
@ -1,67 +1,179 @@
|
|||
#!/bin/bash
|
||||
set -ex
|
||||
|
||||
# OPTIONAL: Enable MicroK8s features first
|
||||
# sudo microk8s enable dns rbac hostpath-storage host-access
|
||||
# sudo microk8s enable metrics-server
|
||||
|
||||
# OPTIONAL: Configure kubectl
|
||||
# =====================================================================
|
||||
# OPTIONAL — MicroK8s setup/reset steps (only use when doing a hard reset)
|
||||
# =====================================================================
|
||||
# sudo microk8s reset --destroy-storage
|
||||
# sudo snap remove microk8s
|
||||
# sudo snap install microk8s --classic
|
||||
# sudo microk8s enable dns rbac hostpath-storage host-access metrics-server ingress
|
||||
# sudo microk8s enable metallb:192.168.0.200-192.168.0.220
|
||||
#
|
||||
# # Rebuild kubeconfig for your local user (optional)
|
||||
# microk8s kubectl config view --raw > ~/.kube/config
|
||||
# chmod 600 ~/.kube/config
|
||||
# sudo usermod -aG microk8s $USER
|
||||
# sudo chown -f -R $USER ~/.kube
|
||||
|
||||
# helm uninstall arc -n arc-systems || true
|
||||
NAMESPACE="arc-systems"
|
||||
RUNNER_NAME="mealcraft-runners"
|
||||
|
||||
# # =====================================================================
|
||||
# # Remove previous ARC installation (safe even if missing)
|
||||
# # =====================================================================
|
||||
# helm uninstall arc -n "${NAMESPACE}" || true
|
||||
# helm uninstall "${RUNNER_NAME}" -n "${NAMESPACE}" || true
|
||||
|
||||
# echo "=== Installing ARC Scale Set Controller ==="
|
||||
|
||||
# echo "=== Install ARC Scale Set Controller ==="
|
||||
# helm install arc \
|
||||
# --namespace arc-systems \
|
||||
# --namespace "${NAMESPACE}" \
|
||||
# --create-namespace \
|
||||
# oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller
|
||||
|
||||
# helm uninstall mealcraft-runners -n arc-systems || true
|
||||
# echo "=== Installing MealCraft Runner Scale Set (NO Docker-in-Docker) ==="
|
||||
|
||||
# helm install mealcraft-runners \
|
||||
# --namespace arc-systems \
|
||||
# helm install "${RUNNER_NAME}" \
|
||||
# --namespace "${NAMESPACE}" \
|
||||
# --create-namespace \
|
||||
# --set runnerScaleSetName="mealcraft-runners" \
|
||||
# --set runnerScaleSetName="${RUNNER_NAME}" \
|
||||
# --set githubConfigUrl="https://github.com/MealCraft" \
|
||||
# --set githubConfigSecret.name="github-secret" \
|
||||
# --set githubConfigSecret.github_token="$GITHUB_PAT" \
|
||||
# --set containerMode.type="kubernetes" \
|
||||
# --set containerMode.kubernetesModeDefaultContainer.image="ubuntu:22.04" \
|
||||
# --set containerMode.kubernetesModeWorkVolumeClaim.accessModes[0]="ReadWriteOnce" \
|
||||
# --set containerMode.kubernetesModeWorkVolumeClaim.storageClassName="microk8s-hostpath" \
|
||||
# --set containerMode.kubernetesModeWorkVolumeClaim.resources.requests.storage="1Gi" \
|
||||
# --set dockerInDockerEnabled=false \
|
||||
# --set containerMode.type="runner" \
|
||||
# --set runnerLabels[0]="mealcraft" \
|
||||
# oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set
|
||||
|
||||
echo "=== Applying RBAC for runner ==="
|
||||
# # =====================================================================
|
||||
# # RBAC — IMPORTANT
|
||||
# # Grants permissions to the exact ARC runner SA detected earlier.
|
||||
# # =====================================================================
|
||||
|
||||
microk8s kubectl apply -f - <<'EOF'
|
||||
echo "=== Applying RBAC for all ARC runners + Traefik ==="
|
||||
|
||||
microk8s kubectl apply -f - <<EOF
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: arc-runner-readonly
|
||||
name: mealcraft-bootstrap-role
|
||||
rules:
|
||||
# ----------------------------------------------------
|
||||
# Storage
|
||||
# ----------------------------------------------------
|
||||
- apiGroups: ["storage.k8s.io"]
|
||||
resources: ["storageclasses"]
|
||||
verbs: ["*"]
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Core API
|
||||
# PV, PVC, Namespaces, Secrets, ConfigMaps, Services,
|
||||
# ServiceAccounts (added for runner + Traefik needs)
|
||||
# ----------------------------------------------------
|
||||
- apiGroups: [""]
|
||||
resources: ["pods"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
resources:
|
||||
- persistentvolumes
|
||||
- persistentvolumeclaims
|
||||
- namespaces
|
||||
- secrets
|
||||
- configmaps
|
||||
- services
|
||||
- serviceaccounts
|
||||
- endpoints # <-- Traefik requires
|
||||
- pods # <-- Traefik requires
|
||||
- nodes # <-- Traefik requires for node discovery
|
||||
verbs: ["*"]
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Apps: Deployments, DaemonSets, RS, StatefulSets
|
||||
# ----------------------------------------------------
|
||||
- apiGroups: ["apps"]
|
||||
resources: ["deployments", "daemonsets", "replicasets", "statefulsets"]
|
||||
verbs: ["*"]
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Networking & Ingress
|
||||
# (Traefik needs watch on ingresses & ingressclasses)
|
||||
# ----------------------------------------------------
|
||||
- apiGroups: ["networking.k8s.io", "extensions"]
|
||||
resources: ["ingresses", "ingressclasses", "*"]
|
||||
verbs: ["*"]
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Traefik v1 CRDs (old MicroK8s installs)
|
||||
# ----------------------------------------------------
|
||||
- apiGroups: ["traefik.containo.us"]
|
||||
resources: ["*"]
|
||||
verbs: ["*"]
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Traefik v2 CRDs (modern)
|
||||
# ----------------------------------------------------
|
||||
- apiGroups: ["traefik.io"]
|
||||
resources:
|
||||
- ingressroutes
|
||||
- ingressroutetcps
|
||||
- ingressrouteudps
|
||||
- middlewares
|
||||
- middlewaretcps
|
||||
- traefikservices
|
||||
- tlsoptions
|
||||
- tlsstores
|
||||
- serverstransports
|
||||
verbs: ["*"]
|
||||
|
||||
# ----------------------------------------------------
|
||||
# CRDs
|
||||
# ----------------------------------------------------
|
||||
- apiGroups: ["apiextensions.k8s.io"]
|
||||
resources: ["customresourcedefinitions"]
|
||||
verbs: ["*"]
|
||||
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: arc-runner-readonly-binding
|
||||
name: mealcraft-bootstrap-binding
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: mealcraft-bootstrap-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: default
|
||||
name: mealcraft-runners-gha-rs-no-permission
|
||||
namespace: arc-systems
|
||||
EOF
|
||||
|
||||
microk8s kubectl apply -f - <<EOF
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: traefik-real-binding
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: arc-runner-readonly
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: mealcraft-bootstrap-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: traefik-ingress-controller
|
||||
namespace: default
|
||||
EOF
|
||||
|
||||
microk8s kubectl apply -f - <<EOF
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: traefik-rbac-fix
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: mealcraft-bootstrap-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: traefik-ingress-controller
|
||||
namespace: default
|
||||
EOF
|
||||
|
||||
|
||||
echo "=== RBAC Applied Successfully ==="
|
||||
echo "=== ARC installation + RBAC complete ==="
|
||||
|
|
|
|||
|
|
@ -2,64 +2,10 @@ import Image from "next/image";
|
|||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div className="flex min-h-screen items-center justify-center bg-zinc-50 font-sans dark:bg-black">
|
||||
<main className="flex min-h-screen w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black sm:items-start">
|
||||
<Image
|
||||
className="dark:invert"
|
||||
src="/next.svg"
|
||||
alt="Next.js logo"
|
||||
width={100}
|
||||
height={20}
|
||||
priority
|
||||
/>
|
||||
<div className="flex flex-col items-center gap-6 text-center sm:items-start sm:text-left">
|
||||
<h1 className="max-w-xs text-3xl font-semibold leading-10 tracking-tight text-black dark:text-zinc-50">
|
||||
To get started, edit the page.tsx file.
|
||||
</h1>
|
||||
<p className="max-w-md text-lg leading-8 text-zinc-600 dark:text-zinc-400">
|
||||
Looking for a starting point or more instructions? Head over to{" "}
|
||||
<a
|
||||
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
className="font-medium text-zinc-950 dark:text-zinc-50"
|
||||
>
|
||||
Templates
|
||||
</a>{" "}
|
||||
or the{" "}
|
||||
<a
|
||||
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
className="font-medium text-zinc-950 dark:text-zinc-50"
|
||||
>
|
||||
Learning
|
||||
</a>{" "}
|
||||
center.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex flex-col gap-4 text-base font-medium sm:flex-row">
|
||||
<a
|
||||
className="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-foreground px-5 text-background transition-colors hover:bg-[#383838] dark:hover:bg-[#ccc] md:w-[158px]"
|
||||
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
className="dark:invert"
|
||||
src="/vercel.svg"
|
||||
alt="Vercel logomark"
|
||||
width={16}
|
||||
height={16}
|
||||
/>
|
||||
Deploy Now
|
||||
</a>
|
||||
<a
|
||||
className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] md:w-[158px]"
|
||||
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Documentation
|
||||
</a>
|
||||
</div>
|
||||
</main>
|
||||
<div className="flex h-screen flex-col items-center justify-center space-y-6">
|
||||
<h1 className="text-3xl font-bold text-center">
|
||||
Impatient with actions, Patient with results
|
||||
</h1>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
17
juntekim_frontend/deployment/Dockerfile
Normal file
17
juntekim_frontend/deployment/Dockerfile
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# Base image
|
||||
FROM mcr.microsoft.com/devcontainers/typescript-node
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Copy ONLY the frontend project
|
||||
COPY ../ .
|
||||
|
||||
# Install dependencies and build
|
||||
RUN npm install && npm run build
|
||||
|
||||
# Expose
|
||||
EXPOSE 3000
|
||||
|
||||
# Start
|
||||
CMD ["npm", "start"]
|
||||
26
juntekim_frontend/deployment/deployment.yml
Normal file
26
juntekim_frontend/deployment/deployment.yml
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
kind: Deployment
|
||||
apiVersion: apps/v1
|
||||
metadata:
|
||||
namespace: ${NAMESPACE}
|
||||
name: portfolio-page
|
||||
labels:
|
||||
app: portfolio-page
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: portfolio-page
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: portfolio-page
|
||||
spec:
|
||||
containers:
|
||||
- name: portfolio-page
|
||||
image: kimjunte/portfolio_page:$GITHUB_REF_SLUG
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- name: portfolioport
|
||||
containerPort: 3000
|
||||
imagePullSecrets:
|
||||
- name: registrypullsecret
|
||||
19
juntekim_frontend/deployment/ingressroute.yml
Normal file
19
juntekim_frontend/deployment/ingressroute.yml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
apiVersion: traefik.io/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: juntekim-portfolio-page
|
||||
namespace: ${NAMESPACE}
|
||||
spec:
|
||||
entryPoints:
|
||||
- websecure
|
||||
routes:
|
||||
- match: "Host(`${HOSTNAME}`) || Host(`www.${HOSTNAME}`)"
|
||||
kind: Rule
|
||||
services:
|
||||
- name: portfolio-page
|
||||
port: 80
|
||||
passHostHeader: false
|
||||
tls:
|
||||
certResolver: myresolver
|
||||
domains:
|
||||
- main: ${HOSTNAME}
|
||||
13
juntekim_frontend/deployment/service.yml
Normal file
13
juntekim_frontend/deployment/service.yml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: portfolio-page
|
||||
namespace: ${NAMESPACE}
|
||||
spec:
|
||||
ports:
|
||||
- protocol: TCP
|
||||
name: portfolioport
|
||||
port: 80
|
||||
targetPort: 3000
|
||||
selector:
|
||||
app: portfolio-page
|
||||
|
|
@ -1,7 +1,10 @@
|
|||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
namespace: default
|
||||
name: test-auth
|
||||
spec:
|
||||
basicAuth:
|
||||
secret: authsecret
|
||||
secret: authsecret
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ apiVersion: v1
|
|||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: certs-pvc
|
||||
namespace: default
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
|
|
|
|||
|
|
@ -1,18 +1,8 @@
|
|||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
namespace: default
|
||||
name: traefik-ingress-controller
|
||||
|
||||
---
|
||||
|
||||
kind: Deployment
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: traefik-deployment
|
||||
labels:
|
||||
app: traefik
|
||||
|
||||
name: traefik
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
|
|
@ -24,30 +14,52 @@ spec:
|
|||
app: traefik
|
||||
spec:
|
||||
serviceAccountName: traefik-ingress-controller
|
||||
volumes:
|
||||
- name: acme
|
||||
persistentVolumeClaim:
|
||||
claimName: certs-pvc
|
||||
containers:
|
||||
- name: traefik
|
||||
image: traefik:v2.10
|
||||
image: traefik:v2.11
|
||||
ports:
|
||||
- name: web
|
||||
containerPort: 80
|
||||
- name: websecure
|
||||
containerPort: 443
|
||||
- name: admin
|
||||
containerPort: 8080
|
||||
volumeMounts:
|
||||
- name: acme
|
||||
mountPath: /acme
|
||||
args:
|
||||
- --api.insecure
|
||||
- --accesslog=True
|
||||
- --entrypoints.web.Address=:80
|
||||
- --entrypoints.websecure.Address=:443
|
||||
- --providers.kubernetescrd
|
||||
- --api.dashboard
|
||||
- --serverstransport.insecureskipverify=true
|
||||
# TLS (HTTPS)
|
||||
- "--certificatesresolvers.myresolver.acme.dnschallenge=true"
|
||||
- "--certificatesresolvers.myresolver.acme.httpChallenge=false"
|
||||
- "--certificatesresolvers.myresolver.acme.tlsChallenge=false"
|
||||
- "--certificatesresolvers.myresolver.acme.dnschallenge.provider=route53"
|
||||
- "--certificatesresolvers.myresolver.acme.email=junte.kim@mealcraft.com"
|
||||
- "--certificatesresolvers.myresolver.acme.storage=/certs/acme.json"
|
||||
- "--certificatesresolvers.myresolver.acme.httpChallenge.entryPoint=web"
|
||||
- "--api.dashboard=true"
|
||||
- "--api.insecure=true"
|
||||
- "--entrypoints.web.address=:80"
|
||||
- "--entrypoints.websecure.address=:443"
|
||||
|
||||
# Redirect HTTP → HTTPS
|
||||
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
|
||||
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
|
||||
- "--entrypoints.websecure.address=:443"
|
||||
- "--providers.kubernetescrd.allowexternalnameservices=true"
|
||||
|
||||
# Providers
|
||||
- "--providers.kubernetescrd=true"
|
||||
- "--providers.kubernetescrd.allowCrossNamespace=true"
|
||||
|
||||
|
||||
# TLS + ACME
|
||||
- "--certificatesresolvers.myresolver.acme.email=junte.kim@mealcraft.com"
|
||||
- "--certificatesresolvers.myresolver.acme.storage=/acme/acme.json"
|
||||
- "--certificatesresolvers.myresolver.acme.dnschallenge.provider=route53"
|
||||
|
||||
# STAGING (uncomment for first-time)
|
||||
# - "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||
|
||||
env:
|
||||
- name: AWS_REGION
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: aws-secrets
|
||||
key: AWS_REGION
|
||||
- name: AWS_ACCESS_KEY_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
|
|
@ -58,24 +70,3 @@ spec:
|
|||
secretKeyRef:
|
||||
name: aws-secrets
|
||||
key: AWS_SECRET_ACCESS_KEY
|
||||
- name: AWS_REGION
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: aws-secrets
|
||||
key: AWS_REGION
|
||||
ports:
|
||||
- name: web
|
||||
containerPort: 80
|
||||
- name: admin
|
||||
containerPort: 8080
|
||||
- name: websecure
|
||||
containerPort: 443
|
||||
volumeMounts:
|
||||
- name: cert-volume
|
||||
mountPath: /certs
|
||||
imagePullSecrets:
|
||||
- name: registrypullsecret
|
||||
volumes:
|
||||
- name: cert-volume
|
||||
persistentVolumeClaim:
|
||||
claimName: certs-pvc
|
||||
|
|
@ -7,10 +7,11 @@ spec:
|
|||
entryPoints:
|
||||
- websecure
|
||||
routes:
|
||||
- match: Host(`www.traefik.mealcraft.com`, `traefik.mealcraft.com`) && PathPrefix(`/api`, `/dashboard`)
|
||||
- match: (Host(`traefik.mealcraft.com`) || Host(`www.traefik.mealcraft.com`)) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))
|
||||
kind: Rule
|
||||
middlewares:
|
||||
- name: test-auth
|
||||
namespace: default
|
||||
services:
|
||||
- name: traefik
|
||||
port: 8080
|
||||
|
|
|
|||
|
|
@ -2,18 +2,18 @@ apiVersion: v1
|
|||
kind: Service
|
||||
metadata:
|
||||
name: traefik
|
||||
|
||||
namespace: default
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
ports:
|
||||
- protocol: TCP
|
||||
name: web
|
||||
port: 80
|
||||
- protocol: TCP
|
||||
name: websecure
|
||||
port: 443
|
||||
- protocol: TCP
|
||||
name: admin
|
||||
port: 8080
|
||||
selector:
|
||||
app: traefik
|
||||
app: traefik
|
||||
ports:
|
||||
- name: web
|
||||
port: 80
|
||||
targetPort: 80
|
||||
- name: websecure
|
||||
port: 443
|
||||
targetPort: 443
|
||||
- name: admin
|
||||
port: 8080
|
||||
targetPort: 8080
|
||||
|
|
|
|||
|
|
@ -19,6 +19,6 @@ spec:
|
|||
- key: kubernetes.io/hostname
|
||||
operator: In
|
||||
values:
|
||||
- gpd
|
||||
- mist
|
||||
|
||||
|
||||
|
|
@ -7,7 +7,8 @@ spec:
|
|||
entryPoints:
|
||||
- websecure
|
||||
routes:
|
||||
- match: "Host(`www.whoami.mealcraft.com`, `whoami.mealcraft.com`)"
|
||||
- match: (Host(`whoami.mealcraft.com`) || Host(`www.whoami.mealcraft.com`))
|
||||
|
||||
kind: Rule
|
||||
services:
|
||||
- name: whoami
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ apiVersion: v1
|
|||
kind: Service
|
||||
metadata:
|
||||
name: whoami
|
||||
namespace: default
|
||||
|
||||
spec:
|
||||
ports:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue