feat(infra): add K3s GitOps infrastructure and Packer golden image build (#25)
### Summary of Changes This PR introduces a declarative, GitOps-managed cloud infrastructure for the monorepo using K3s, Flux v2, and HashiCorp Packer: 1. **Packer Golden Image Builder (`ci/packer/`)**: - Automated Debian 12 minimal base OS image creation using QEMU builder, UEFI firmware, GPT partition scheme, and 2M cluster size `.qcow2` conversion. - Cloud-init, `virtio` kernel drivers, and serial console (`ttyS0`, 115200 baud). - Pre-installed K3s binary (`v1.31.2+k3s1`) with isolated first-boot token and cert generation. - Full identity sanitization (`machine-id` and SSH host key resets). 2. **First-Boot Cloud-Init Bootstrapping (`ci/cloud-init/user-data.yaml`)**: - Configures K3s with `servicelb` disabled and TLS SANs for custom domains and static IP. - Waits for API readiness, initializes `flux-system` namespace, injects `sops-age` secret, and triggers Flux sync. 3. **SOPS & GitOps Root Orchestration (`.sops.yaml`, `ci/k8s/clusters/production/`)**: - SOPS encryption configuration targeting Kubernetes secrets with `age` key recipient. - Flux v2 `GitRepository` and `Kustomization` manifests tracking `next`. 4. **Infrastructure & Networking (`ci/k8s/base/`, `ci/k8s/infrastructure/`)**: - Dedicated `com-ermnvldmr` namespace. - `cert-manager` HTTP-01 `ClusterIssuer` (`letsencrypt-prod` & `letsencrypt-staging`). - Traefik Ingress routing for `ermnvldmr.com`, `www.ermnvldmr.com`, `docs.ermnvldmr.com`, and `analytics.ermnvldmr.com`. 5. **PostgreSQL & Applications (`ci/k8s/apps/`)**: - PostgreSQL 16 StatefulSet on 5Gi `local-path` persistent storage with low-memory tuning. - Deployments for `www` (pinned `sha-6d33b71`), `docs` (pinned `sha-91f5245`), and `umami` (pinned `postgresql-v2.14.0`) with zero-downtime rolling update strategy. 6. **CI/CD Workflows (`.github/workflows/`)**: - `ci - next/build-golden-image`: Workflow to build and upload `com-ermnvldmr-debian-12-k3s-amd64-<tag>.qcow2` to static S3 `/dev/images/`. - Updated `services-www-releases-dispatch-release.yml` and `services-docs-next-required.yml` with GitOps deployment steps.
This commit is contained in:
1 parent
6d33b71405
commit
710873e72c
38 files changed
+1106
-28
No files matched your search
@@ -0,0 +1,93 @@
|
||||
name: ci - next/build-golden-image
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ci-golden-image
|
||||
cancel-in-progress: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
validate-template:
|
||||
name: Validate - Packer Template
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Packer
|
||||
run: |
|
||||
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
|
||||
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
|
||||
sudo apt-get update && sudo apt-get install -y packer
|
||||
|
||||
- name: Initialize Packer plugins
|
||||
run: packer init ci/packer/debian-12-k3s.pkr.hcl
|
||||
|
||||
- name: Validate Packer template
|
||||
run: packer validate ci/packer/debian-12-k3s.pkr.hcl
|
||||
|
||||
build-image:
|
||||
name: Build - QEMU Image
|
||||
needs: validate-template
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
image_name: ${{ steps.vars.outputs.image_name }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Calculate Image Name
|
||||
id: vars
|
||||
run: |
|
||||
SHORT_SHA="sha-$(echo ${{ github.sha }} | cut -c1-7)"
|
||||
IMAGE_NAME="com-ermnvldmr-debian-12-k3s-amd64-${SHORT_SHA}.qcow2"
|
||||
echo "image_name=${IMAGE_NAME}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Install QEMU and Packer
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y qemu-system-x86 qemu-utils ovmf
|
||||
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
|
||||
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
|
||||
sudo apt-get update && sudo apt-get install -y packer
|
||||
|
||||
- name: Initialize Packer plugins
|
||||
run: packer init ci/packer/debian-12-k3s.pkr.hcl
|
||||
|
||||
- name: Build QEMU Golden Image
|
||||
run: packer build ci/packer/debian-12-k3s.pkr.hcl
|
||||
|
||||
- name: Prepare and Upload Image Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: golden-image
|
||||
path: output-qemu/com-ermnvldmr-debian-12-k3s-amd64.qcow2
|
||||
retention-days: 1
|
||||
|
||||
upload-s3:
|
||||
name: Upload - S3 Storage
|
||||
needs: build-image
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download Image Artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: golden-image
|
||||
path: output-qemu
|
||||
|
||||
- name: Upload to Static S3 (/dev/images/)
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.COM_ERMNVLDMR_STATIC_AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.COM_ERMNVLDMR_STATIC_AWS_SECRET_ACCESS_KEY }}
|
||||
AWS_DEFAULT_REGION: ${{ secrets.COM_ERMNVLDMR_STATIC_S3_REGION }}
|
||||
S3_ENDPOINT: ${{ secrets.COM_ERMNVLDMR_STATIC_S3_ENDPOINT_URL }}
|
||||
S3_BUCKET: ${{ secrets.COM_ERMNVLDMR_STATIC_S3_BUCKET }}
|
||||
IMAGE_NAME: ${{ needs.build-image.outputs.image_name }}
|
||||
run: |
|
||||
mv output-qemu/com-ermnvldmr-debian-12-k3s-amd64.qcow2 "output-qemu/${IMAGE_NAME}"
|
||||
aws --endpoint-url="${S3_ENDPOINT}" s3 cp "output-qemu/${IMAGE_NAME}" "s3://${S3_BUCKET}/dev/images/${IMAGE_NAME}"
|
||||
echo "Golden image uploaded to s3://${S3_BUCKET}/dev/images/${IMAGE_NAME}"
|
||||
@@ -91,22 +91,25 @@ jobs:
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
||||
deploy:
|
||||
name: Deploy - VPS
|
||||
name: Deploy - Kubernetes (GitOps)
|
||||
needs: release-docker
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/next'
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Deploy via SSH
|
||||
uses: appleboy/ssh-action@v1.0.3
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
host: ${{ secrets.DEPLOY_VPS_HOST }}
|
||||
username: ${{ secrets.DEPLOY_VPS_USER }}
|
||||
key: ${{ secrets.DEPLOY_VPS_SSH_KEY }}
|
||||
port: ${{ secrets.DEPLOY_VPS_SSH_PORT || 22 }}
|
||||
script: |
|
||||
cd /srv/ermnvldmr.com
|
||||
git pull
|
||||
chmod +x ci/scripts/deploy-new-tags.sh
|
||||
# Use the short SHA to match the tag from release-docker
|
||||
export DOCS_TAG="sha-$(echo ${{ github.sha }} | cut -c1-7)"
|
||||
./ci/scripts/deploy-new-tags.sh
|
||||
ref: next
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Setup Kustomize
|
||||
uses: imranismail/setup-kustomize@v2
|
||||
with:
|
||||
kustomize-version: "5.3.0"
|
||||
|
||||
- name: Deploy via GitOps
|
||||
run: |
|
||||
DOCS_TAG="sha-$(echo ${{ github.sha }} | cut -c1-7)"
|
||||
bash ci/scripts/deploy-gitops.sh docs "${DOCS_TAG}"
|
||||
@@ -235,6 +235,8 @@ jobs:
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
outputs:
|
||||
version: ${{ steps.version.outputs.version }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
@@ -287,24 +289,27 @@ jobs:
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
||||
deploy:
|
||||
name: Deploy - VPS
|
||||
name: Deploy - Kubernetes (GitOps)
|
||||
needs: release-tag-docker
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: services-www-releases-deploy
|
||||
url: https://ermnvldmr.com
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Deploy via SSH
|
||||
uses: appleboy/ssh-action@v1.0.3
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
host: ${{ secrets.DEPLOY_VPS_HOST }}
|
||||
username: ${{ secrets.DEPLOY_VPS_USER }}
|
||||
key: ${{ secrets.DEPLOY_VPS_SSH_KEY }}
|
||||
port: ${{ secrets.DEPLOY_VPS_SSH_PORT || 22 }}
|
||||
script: |
|
||||
cd /srv/ermnvldmr.com
|
||||
git pull
|
||||
chmod +x ci/scripts/deploy-new-tags.sh
|
||||
# Use the short SHA to match the tag from release-tag-docker
|
||||
export WWW_TAG="sha-$(echo ${{ github.sha }} | cut -c1-7)"
|
||||
./ci/scripts/deploy-new-tags.sh
|
||||
ref: next
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Setup Kustomize
|
||||
uses: imranismail/setup-kustomize@v2
|
||||
with:
|
||||
kustomize-version: "5.3.0"
|
||||
|
||||
- name: Deploy via GitOps
|
||||
run: |
|
||||
WWW_TAG="sha-$(echo ${{ github.sha }} | cut -c1-7)"
|
||||
bash ci/scripts/deploy-gitops.sh www "${WWW_TAG}"
|
||||
Reference in new issue
Block a user