# Example: ARC Controller Configuration with Custom Helm Values
## Basic Configuration (Default)
This is what gets generated by `#arc_install_controller_hybrid --apply false`:
```yaml
chart:
repository: oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller
name: gha-runner-scale-set-controller
version: latest
release:
name: arc-controller
namespace: arc-systems
createNamespace: true
values: {} # Empty - uses Helm chart defaults
metadata:
managedBy: arc-config-mcp
mode: hybrid
generatedAt: '2025-10-31T19:27:10.002Z'
```
When applied with `#arc_apply_config --configType controller`, this executes:
```bash
helm upgrade arc-controller \
oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller \
--install \
--namespace arc-systems \
--create-namespace
```
---
## Advanced Configuration (With Custom Values)
You can edit `configs/controller.yaml` to add custom Helm values:
```yaml
chart:
repository: oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller
name: gha-runner-scale-set-controller
version: "0.9.3" # Pin to specific version
release:
name: arc-controller
namespace: arc-systems
createNamespace: true
values:
# Controller replicas for high availability
replicaCount: 2
# Resource limits
resources:
limits:
cpu: "500m"
memory: "512Mi"
requests:
cpu: "250m"
memory: "256Mi"
# Node placement
nodeSelector:
kubernetes.io/os: linux
node-role: arc-controller
# Tolerations for dedicated nodes
tolerations:
- key: "dedicated"
operator: "Equal"
value: "arc"
effect: "NoSchedule"
# Security context
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
# Logging configuration
logLevel: "debug"
logFormat: "json"
# Metrics and monitoring
metrics:
enabled: true
port: 8080
path: /metrics
# Service configuration
service:
type: ClusterIP
port: 443
# Pod annotations for monitoring
podAnnotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8080"
prometheus.io/path: "/metrics"
metadata:
managedBy: arc-config-mcp
mode: hybrid
generatedAt: '2025-10-31T19:27:10.002Z'
```
When applied with `#arc_apply_config --configType controller`, this executes:
```bash
helm upgrade arc-controller \
oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller \
--install \
--namespace arc-systems \
--create-namespace \
--version 0.9.3 \
--set replicaCount=2 \
--set resources.limits.cpu=500m \
--set resources.limits.memory=512Mi \
--set resources.requests.cpu=250m \
--set resources.requests.memory=256Mi \
--set nodeSelector.kubernetes\.io/os=linux \
--set nodeSelector.node-role=arc-controller \
--set securityContext.runAsNonRoot=true \
--set securityContext.runAsUser=1000 \
--set securityContext.fsGroup=1000 \
--set logLevel=debug \
--set logFormat=json \
--set metrics.enabled=true \
--set metrics.port=8080 \
--set metrics.path=/metrics \
--set service.type=ClusterIP \
--set service.port=443 \
--set podAnnotations.prometheus\.io/scrape=true \
--set podAnnotations.prometheus\.io/port=8080 \
--set podAnnotations.prometheus\.io/path=/metrics
# ... plus any other values
```
---
## How It Works
### 1. The `values:` Section
Everything under `values:` in your config file gets translated into Helm `--set` arguments.
**Flattening Rules:**
- `key: value` → `--set key=value`
- Nested objects use dot notation:
```yaml
parent:
child: value
```
becomes: `--set parent.child=value`
### 2. Special Characters
Keys with special characters (like `kubernetes.io/os`) are escaped automatically:
- `kubernetes.io/os: linux` → `--set nodeSelector.kubernetes\.io/os=linux`
### 3. Arrays and Complex Types
For complex Helm values (arrays, multi-line strings, etc.), you may need to:
- Use a separate `values.yaml` file
- Or pass them using `helm` directly with `-f values.yaml`
### 4. The Apply Tool
The `#arc_apply_config` tool:
1. Reads your `configs/controller.yaml` file
2. Extracts the `chart`, `release`, and `values` sections
3. Builds the Helm command dynamically with all --set flags
4. Executes `helm upgrade --install` (idempotent)
5. Shows you the status of the deployed resources
---
## Common Use Cases
### Production Configuration
```yaml
values:
replicaCount: 3
resources:
limits:
memory: "1Gi"
cpu: "1000m"
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app.kubernetes.io/name: gha-runner-scale-set-controller
topologyKey: kubernetes.io/hostname
```
### Development Configuration
```yaml
values:
replicaCount: 1
logLevel: "debug"
resources:
requests:
memory: "128Mi"
cpu: "100m"
```
### Air-Gapped Environment
```yaml
chart:
repository: oci://private-registry.company.com/charts/gha-runner-scale-set-controller
values:
image:
registry: private-registry.company.com
repository: actions-runner-controller/controller
tag: "0.9.3"
```
---
## Verification
After applying your configuration:
```bash
# Check controller pods
kubectl get pods -n arc-systems -l app.kubernetes.io/name=gha-runner-scale-set-controller
# Check Helm release
helm list -n arc-systems
# Get actual Helm values
helm get values arc-controller -n arc-systems
# Check logs
kubectl logs -n arc-systems -l app.kubernetes.io/name=gha-runner-scale-set-controller
```
---
## Related Resources
- **Helm Chart Values**: https://github.com/actions/actions-runner-controller/tree/master/charts/gha-runner-scale-set-controller
- **ARC Documentation**: https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners-with-actions-runner-controller
- **Kubernetes Resources**: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
---
## Tips
1. **Version Pin**: Always pin to a specific chart version in production
2. **Git Commit**: Commit your config changes so you have an audit trail
3. **Review First**: Review the generated Helm command before applying
4. **Test Changes**: Test configuration changes in a dev environment first
5. **Use Drift Detection**: Run `#arc_detect_drift` to catch manual cluster changes
---
**Key Takeaway**: The `values:` section is your customization layer. Everything here becomes a `--set` argument when you run `#arc_apply_config`. This gives you the power of Helm customization with the benefits of version-controlled configuration files!