Overview
Kubernetes deployment provides:- Production-ready Helm charts maintained by GitHub
- High availability with replica sets
- Auto-scaling with Horizontal Pod Autoscaler
- Security with pod security contexts and read-only root filesystem
- Monitoring with built-in health checks
- Flexibility for custom configurations
Prerequisites
- Kubernetes cluster (1.19+)
kubectlconfigured to access your cluster- Helm 3.x (for Helm deployment method)
- GitHub App created with credentials
- Container registry access (or use public
ghcr.io/github/safe-settings)
Deployment Methods
Choose between Helm (recommended) or kubectl:Helm
Recommended for production deployments
kubectl
Direct deployment with manifest files
Method 1: Helm Deployment (Recommended)
# GitHub App credentials (required)
envFrom:
- secretRef:
name: safe-settings-secrets
# Application configuration
env:
- name: ADMIN_REPO
value: "admin"
- name: LOG_LEVEL
value: "info"
- name: CONFIG_PATH
value: ".github"
- name: SETTINGS_FILE_PATH
value: "settings.yml"
# Image configuration
image:
repository: ghcr.io/github/safe-settings
pullPolicy: IfNotPresent
tag: "2.1.17"
# Replica configuration
replicaCount: 2
# Resource limits
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
# Service configuration
service:
type: ClusterIP
port: 3000
# Ingress configuration
ingress:
enabled: true
className: "nginx"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
hosts:
- host: safe-settings.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: safe-settings-tls
hosts:
- safe-settings.example.com
# Autoscaling
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 80
# Deployment config (custom validators, restricted repos)
deploymentConfig:
restrictedRepos:
exclude: ["^admin$", '^\.github$', "^safe-settings$"]
kubectl create secret generic safe-settings-secrets \
--from-literal=APP_ID="123456" \
--from-literal=WEBHOOK_SECRET="your-webhook-secret" \
--from-literal=PRIVATE_KEY="$(cat private-key.pem | base64)"
helm install safe-settings \
oci://ghcr.io/github/helm-charts/safe-settings \
--values myvalues.yaml \
--namespace safe-settings \
--create-namespace
Method 2: kubectl Deployment
For direct deployment without Helm:kubectl create secret generic app-env \
--from-literal=APP_ID="123456" \
--from-literal=WEBHOOK_SECRET="your-webhook-secret" \
--from-literal=PRIVATE_KEY="$(cat private-key.pem | base64)" \
--namespace safe-settings
kubectl create secret docker-registry regcred \
--docker-server=DOCKER_REGISTRY_SERVER \
--docker-username=DOCKER_USER \
--docker-password=DOCKER_PASSWORD \
--docker-email=DOCKER_EMAIL \
--namespace safe-settings
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: safe-settings
name: safe-settings
namespace: safe-settings
spec:
replicas: 2
selector:
matchLabels:
app: safe-settings
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: safe-settings
spec:
containers:
- image: ghcr.io/github/safe-settings:2.1.17
name: safe-settings
ports:
- containerPort: 3000
protocol: TCP
envFrom:
- secretRef:
name: app-env
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
livenessProbe:
httpGet:
path: /probot
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /probot
port: 3000
initialDelaySeconds: 10
periodSeconds: 5
# Uncomment if using private registry
# imagePullSecrets:
# - name: regcred
apiVersion: v1
kind: Service
metadata:
name: safe-settings
namespace: safe-settings
spec:
type: ClusterIP
ports:
- port: 3000
targetPort: 3000
protocol: TCP
name: http
selector:
app: safe-settings
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: safe-settings
namespace: safe-settings
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- safe-settings.example.com
secretName: safe-settings-tls
rules:
- host: safe-settings.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: safe-settings
port:
number: 3000
Configuration
Environment Variables
The Helm chart supports environment variables viaenv and envFrom:
Custom Image
For production, use a custom image with a specific version:Resource Limits
Set appropriate resource limits:Auto-Scaling
Enable Horizontal Pod Autoscaler:Deployment Config
Configure validators and restricted repos:Helm Chart Values Reference
Key values from the Safe Settings Helm chart:Upgrading
Helm Upgrade
Upgrade to a new version:kubectl Upgrade
Update the image version:Monitoring
View Logs
Check Health
View Events
Troubleshooting
Pod Not Starting
Check pod status and events:- Image pull errors: Check
imagePullSecrets - Secret not found: Verify secret exists and name matches
- Resource limits: Check if cluster has available resources
Webhook Not Receiving Events
Verify service and ingress:High Memory Usage
Increase resource limits:Certificate Issues
If using cert-manager for TLS:Uninstalling
Helm Uninstall
kubectl Uninstall
Production Considerations
For production deployments, consider these best practices:
High Availability
- Run at least 2 replicas
- Use pod anti-affinity to spread across nodes
- Enable HPA for auto-scaling
Security
- Use specific image tags (not
latest) - Enable pod security contexts
- Store secrets in external secret managers (e.g., HashiCorp Vault, AWS Secrets Manager)
- Use network policies to restrict traffic
Monitoring
- Set up Prometheus metrics
- Configure CloudWatch or similar logging
- Enable alerting for pod failures
- Monitor resource usage
Backup
- Back up your configuration files
- Document your Helm values
- Keep GitHub App credentials secure
Next Steps
Configure Settings
Set up your repository settings
Helm Chart Repo
View Helm chart source
AWS Lambda
Alternative serverless deployment
GitHub Actions
Scheduled sync with Actions