Skip to main content

Kubernetes CI/CD Cluster – VM Design & IP Plan

0.

Scope Legend

COMMON · NO CHANGE NEEDED
1.COMMON · NO CHANGE NEEDEDConfigure once and reuse across all GitHub organizations and repositories.
2.CHANGE PER GITHUB ORGRepeat or recreate for every GitHub organization or product.
3.CHANGE PER REPOSITORYRepeat for every private repository inside the GitHub organization.
1.

AC CI/CD VM Inputs

COMMON · NO CHANGE NEEDED
COMMON · NO CHANGE NEEDEDThese values describe the shared cluster infrastructure. Configure them once and reuse them for Shelvera, FP, and future GitHub organizations.
2.

Shared ARC Controller Inputs

COMMON · NO CHANGE NEEDED
COMMON · NO CHANGE NEEDEDConfigure once. Reuse these values for every GitHub organization unless the shared cluster architecture itself changes.
3.

Generic Organization and Repository Inputs

CHANGE PER GITHUB ORGCHANGE PER REPOSITORY
CHANGE PER GITHUB ORGUse one blank reusable input set. App Short Form and GitHub Organization change per organization; Service / App Name changes per repository; Target Environment changes per deployment. The examples are placeholders only and are never treated as entered values.
4.

Computed Shared Values

COMMON · NO CHANGE NEEDED
Cluster API URL:
https://ac-cicd-api.aspireclan.com
Cluster API VIP:
192.168.8.60
Subnet:
192.168.8.0/22
Gateway:
192.168.8.1
Shared ARC Controller:
arc-systems/arc
Runner Namespace Pattern:
arc-runners-<app-short-form>-<environment>
5.

Multi-GitHub Organization Design

COMMON · NO CHANGE NEEDED
✅ SHARED — configure once for all GitHub organizations
  • Kubernetes cluster, API VIP, and load balancer
  • Control-plane VMs and environment worker VMs
  • ARC controller at arc-systems/arc
  • Runner namespace prefix and worker workload label
  • Harbor server, reverse proxy, TLS endpoint, and base networking
  • Environment worker capacity, monitoring, and cluster upgrades
⚠️ PER GITHUB ORGANIZATION — enter again and create separately
  • Unique app short form and GitHub organization name
  • GitHub App, installation ID, private key, and repository access
  • Runner namespaces for each required environment
  • GitHub App and Harbor secrets inside those namespaces
  • One Harbor project and separate CI/runtime robot accounts
  • Organization working folder and scoped checklist state
🧩 PER PRIVATE REPOSITORY — repeat inside the organization
  • Service / app name and GitHub repository URL
  • Runner scale-set name, Helm release, and values file
  • Application image repository and workflow runner reference
  • Repository-level Harbor secrets and variables for GitHub Free
  • Repository-specific build and deployment settings
Reusable page behavior: this page represents one GitHub organization, private repository, and target environment at a time. Enter the generic values above, use the generated names below, and repeat only the appropriately scoped steps. No Shelvera, FP, or future-organization values are pre-populated.
Generic inputs are incomplete. Enter Service / App Name, a unique App Short Form, GitHub Organization, and Target Environment before using the generated organization- or repository-specific values.
5.1

Current Organization-Derived Values

CHANGE PER GITHUB ORG
ValueGenerated resultScope
GitHub organization<github-organization>Per GitHub organization
App short form<app-short-form>Per GitHub organization and globally unique in this cluster
Target environment<environment>Per organization deployment
Target runner namespacearc-runners-<app-short-form>-<environment>Per organization and environment
GitHub App secret<app-short-form>-arc-ghapp-secretPer organization namespace
Harbor pull secret<app-short-form>-harbor-regcredPer organization namespace
Harbor CI credentials secret<app-short-form>-harbor-credentialsPer organization namespace
Harbor project<app-short-form>-ci-cdPer product / GitHub organization
ARC working folder~/arc/<app-short-form>Per organization
Harbor CI robotPull + PushPer organization; used by GitHub Actions / ARC runners
Harbor runtime robotPull onlyPer organization; used by Kubernetes imagePullSecrets
5.2

Isolation Boundary by Layer

COMMON · NO CHANGE NEEDED
LayerShared or IsolatedDesign
Load balancer and API VIPSHAREDOne endpoint for the Kubernetes control plane.
Kubernetes control planesSHAREDOne highly available cluster for all CI/CD runner scale sets.
ARC controllerSHAREDOne controller at arc-systems/arc.
Environment worker VMsSHARED BY ENVIRONMENTDev runners share dev workers, QA runners share QA workers, and prod runners share prod workers.
Runner namespacesPER ORGANIZATIONarc-runners-<app-short-form>-<environment>
GitHub Apps and Kubernetes secretsPER ORGANIZATIONEach GitHub organization uses its own GitHub App and namespace-scoped secrets.
Harbor project and robotsPER ORGANIZATIONOne project per product with separate CI and runtime credentials.
Runner scale-set Helm releasesPER REPOSITORYEach private repository uses a unique release and runner scale-set name.
5.3

Repository-Level Runner Resources

CHANGE PER REPOSITORY
CHANGE PER REPOSITORYRepeat these values and resources for every private repository inside the selected GitHub organization.
Repository-level valueGenerated result
Service / App Name<service-name>
GitHub repository URLhttps://github.com/<github-organization>/<service-name>
Runner scale-set / Helm release<service-name>-<environment>-arc
Runner values file~/arc/<app-short-form>/<service-name>-<environment>-values.yaml
Harbor image repositoryharbor.aspireclan.com/<app-short-form>-ci-cd/<service-name>:<tag>
Repository-level Actions secretsHARBOR_USERNAME, HARBOR_PASSWORD
Repository-level Actions variablesHARBOR_REGISTRY, HARBOR_PROJECT
  • Create a separate runner scale-set release for each repository and environment.
  • Grant the organization GitHub App access only to the required private repositories.
  • On GitHub Free, configure HARBOR_USERNAME and HARBOR_PASSWORD as repository secrets.
  • Configure HARBOR_REGISTRY and HARBOR_PROJECT as repository variables.
  • Do not depend on organization-level or environment-level Actions secrets or variables for private repositories.
  • Keep the organization namespace and Harbor project shared across repositories in the same product organization.
6.

Final VM Plan

COMMON · NO CHANGE NEEDED
1.

Create the Kubernetes API VIP and load balancer plan

COMMON · NO CHANGE NEEDED

Use the following API endpoint for the kubeadm control-plane endpoint and future kubeconfig access.

API VIP Hostname:
ac-cicd-api.aspireclan.com
API VIP IP:
192.168.8.60
Proposed Access URL:
https://ac-cicd-api.aspireclan.com
2.

Create the load balancer VM

COMMON · NO CHANGE NEEDED
VM Name:
ac-cicd-lb-01
FQDN:
ac-cicd-lb-01.aspireclan.com
IP Address:
192.168.8.61
VM Size:
1 vCPU / 2 GB / 20 GB
3.

Create the control plane VMs

COMMON · NO CHANGE NEEDED
VM NameFQDNIPvCPURAMDiskCI/CD Responsibility
ac-cicd-cp-01ac-cicd-cp-01.aspireclan.com192.168.8.6228 GB100 GBShared Kubernetes control plane and ARC controller placement
ac-cicd-cp-02ac-cicd-cp-02.aspireclan.com192.168.8.6328 GB100 GBShared Kubernetes control plane
ac-cicd-cp-03ac-cicd-cp-03.aspireclan.com192.168.8.6428 GB100 GBShared Kubernetes control plane
4.

Create the worker VMs

COMMON · NO CHANGE NEEDED
VM NameFQDNIPvCPURAMDiskRoleExpected Labels
ac-cicd-prod-wk-01ac-cicd-prod-wk-01.aspireclan.com192.168.8.71824 GB250 GBShared prod ARC runner workerenv=prod workload=arc-runner
ac-cicd-prod-wk-02ac-cicd-prod-wk-02.aspireclan.com192.168.8.72824 GB250 GBShared prod ARC runner workerenv=prod workload=arc-runner
ac-cicd-qa-wk-01ac-cicd-qa-wk-01.aspireclan.com192.168.8.81824 GB250 GBShared QA ARC runner workerenv=qa workload=arc-runner
ac-cicd-dev-wk-01ac-cicd-dev-wk-01.aspireclan.com192.168.8.91824 GB250 GBShared dev ARC runner workerenv=dev workload=arc-runner
7.

Runner Worker Placement

COMMON · NO CHANGE NEEDED

Apply environment and workload labels to the shared worker nodes. Do not assign an application or GitHub organization label in the default design because runner scale sets from different GitHub organizations intentionally share the worker pool for their environment.

kubectl label node ac-cicd-prod-wk-01 env=prod workload=arc-runner --overwrite
kubectl label node ac-cicd-prod-wk-02 env=prod workload=arc-runner --overwrite
kubectl label node ac-cicd-qa-wk-01 env=qa workload=arc-runner --overwrite
kubectl label node ac-cicd-dev-wk-01 env=dev workload=arc-runner --overwrite
kubectl get nodes -L env,workload
Capacity boundary: Kubernetes namespaces isolate credentials and resources logically, but they do not reserve CPU or memory. All runner scale-set maxRunners values for the same environment must be planned against the combined capacity of that environment's worker nodes. Add another worker VM before increasing concurrency beyond safe shared capacity.
7.1

When Dedicated Organization Worker VMs Become Appropriate

CHANGE PER GITHUB ORG

Keep the shared environment worker model initially. Add dedicated organization workers only when one of these conditions appears:

  • A product needs hard compute isolation beyond namespace and secret isolation.
  • One organization's builds regularly exhaust shared CPU, memory, disk, or Docker capacity.
  • A product requires different operating-system, tooling, network, or compliance controls.
  • Production release workloads need a dedicated failure or maintenance boundary.

A future dedicated worker can use labels such as env=<environment>, workload=arc-runner, and app=<app-short-form>. Only then should the matching runner values add an application-specific node selector and toleration.

8.

DNS Plan

COMMON · NO CHANGE NEEDED
5.

Create the internal DNS records

COMMON · NO CHANGE NEEDED

Add internal DNS records for all nodes and for the Kubernetes API VIP.

# Cluster API VIP
192.168.8.60 ac-cicd-api.aspireclan.com

# Load balancer
192.168.8.61 ac-cicd-lb-01.aspireclan.com

# Control planes
192.168.8.62 ac-cicd-cp-01.aspireclan.com
192.168.8.63 ac-cicd-cp-02.aspireclan.com
192.168.8.64 ac-cicd-cp-03.aspireclan.com

# Shared environment workers
192.168.8.71 ac-cicd-prod-wk-01.aspireclan.com
192.168.8.72 ac-cicd-prod-wk-02.aspireclan.com
192.168.8.81 ac-cicd-qa-wk-01.aspireclan.com
192.168.8.91 ac-cicd-dev-wk-01.aspireclan.com
9.

Kubeadm Endpoint

COMMON · NO CHANGE NEEDED
6.

Use the control-plane endpoint during cluster initialization

COMMON · NO CHANGE NEEDED
kubeadm init \
  --control-plane-endpoint "ac-cicd-api.aspireclan.com:443" \
  --upload-certs
10.

Proxmox Notes

COMMON · NO CHANGE NEEDED
7.

Use consistent VM settings in Proxmox

COMMON · NO CHANGE NEEDED
  • OS: Ubuntu Server 24.04 LTS
  • CPU Type: host
  • Machine Type: q35
  • Disk Controller: VirtIO SCSI single
  • NIC Model: VirtIO
  • Enable QEMU Guest Agent
  • Disable swap in guest after OS install
  • Keep worker VM names environment-based, not GitHub-organization-based, while workers are shared.
8.

Create VMs in this order

COMMON · NO CHANGE NEEDED
  1. ac-cicd-lb-01
  2. ac-cicd-cp-01
  3. ac-cicd-cp-02
  4. ac-cicd-cp-03
  5. ac-cicd-prod-wk-01
  6. ac-cicd-prod-wk-02
  7. ac-cicd-qa-wk-01
  8. ac-cicd-dev-wk-01
11.

Organization Isolation Rules

CHANGE PER GITHUB ORG
✅ Keep shared
  • One Kubernetes cluster and one ARC controller
  • API VIP, load balancer, control planes, and environment workers
  • Runner namespace prefix and worker placement labels
  • Cluster operations, upgrades, and shared-capacity monitoring
⚠️ Change or recreate per GitHub organization
  • App short form and GitHub organization
  • GitHub App, installation, private key, and repository permissions
  • Runner namespace: arc-runners-<app-short-form>-<environment>
  • GitHub App and Harbor namespace secrets
  • Harbor project and separate CI/runtime robot accounts
  • Organization working folder and scoped checklist state
  • Operate exactly one shared ARC controller unless a future security boundary requires another cluster.
  • Never reuse a GitHub App secret name or runner namespace across app short forms.
  • Use one GitHub App per GitHub organization and grant only the required private repositories.
  • Generate namespaces as arc-runners-<app-short-form>-<environment>.
  • Keep Harbor pull and CI credentials secrets inside the matching runner namespace.
  • Use one Harbor project per product/GitHub organization by default.
  • Plan total runner concurrency against shared worker capacity, not namespace count.
11.1

Repository-Specific Rules

CHANGE PER REPOSITORY
  • Use the Service / App Name in the Helm release and runner scale-set name.
  • Create a separate values file per repository and environment.
  • Limit GitHub App repository access to only the private repositories that require runners.
  • Configure GitHub Free private-repository Actions secrets and variables at repository scope.
  • Use HARBOR_USERNAME and HARBOR_PASSWORD as repository secrets.
  • Use HARBOR_REGISTRY and HARBOR_PROJECT as repository variables.
  • Do not create separate worker VMs or Harbor projects per repository unless a stronger boundary is required.
12.

Quick Reference

COMMON · NO CHANGE NEEDED
12.1

Shared Values

COMMON · NO CHANGE NEEDED
API URL:
https://ac-cicd-api.aspireclan.com
Gateway:
192.168.8.1
Subnet:
192.168.8.0/22
Shared ARC Controller:
arc-systems/arc
12.2

Current GitHub Organization Values

CHANGE PER GITHUB ORG
Current GitHub Organization:
<github-organization>
Current App Short Form:
<app-short-form>
Current Target Environment:
<environment>
Current Target Runner Namespace:
arc-runners-<app-short-form>-<environment>
Current GitHub App Secret:
<app-short-form>-arc-ghapp-secret
Current Harbor Project:
<app-short-form>-ci-cd
Current Harbor Pull Secret:
<app-short-form>-harbor-regcred
Current Harbor CI Credentials Secret:
<app-short-form>-harbor-credentials
12.3

Current Repository Values

CHANGE PER REPOSITORY
Current Service / App:
<service-name>
GitHub Repository URL:
https://github.com/<github-organization>/<service-name>
Runner Scale Set / Helm Release:
<service-name>-<environment>-arc
Runner Values File:
~/arc/<app-short-form>/<service-name>-<environment>-values.yaml
Harbor Image Repository:
harbor.aspireclan.com/<app-short-form>-ci-cd/<service-name>:<tag>
12.4

Shared Proxmox Portal

COMMON · NO CHANGE NEEDED

Proxmox portal:

https://pve.aspireclan.com