Install
$ agentstack add skill-kaos-io-agent-skills-kubeapp-crud ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
KubeApp CRUD — Full Lifecycle Management
Manage the complete lifecycle of a KubeApp on the KAOS platform: create, read, update, delete, and verify all provisioned resources end-to-end.
When to Use
- User wants to create a new application
- User wants to check application status or health
- User wants to update application configuration (profile, env vars, environments, visibility)
- User wants to delete an application
- User wants to verify all CI/CD infrastructure, registry auth, and deployment resources
Prerequisites
Before any KubeApp operation, you need:
- A KubeProject in Ready state (the project this app belongs to)
- A KubeAppTemplate (defines the application type — python-rest-api, go-rest-api, react-frontend)
- Access to the control plane cluster (
KUBECONFIGset)
Discover these first:
kubectl get kubeproject -A # Find available projects
kubectl get xkubeapptemplate # Find available templates
CREATE — Provision a New KubeApp
Step 1: Gather Information
Ask the user (or determine from context):
- App name — lowercase, alphanumeric + hyphens (e.g.,
my-backend) - Project — which KubeProject (e.g.,
wow-xmas) - Template — which KubeAppTemplate (e.g.,
python-rest-api) - Profile — resource size:
small(default),medium,large - Visibility —
private(default),public,internal - Target environments — which environment types to deploy to (e.g.,
dev,stage) - Environment variables — any custom env vars (global or per-environment)
Step 2: Determine the Namespace
KubeApps live in the KubeOrg namespace (not the project namespace). Find it:
kubectl get kubeproject -A -o jsonpath='{.spec.kubeOrgRef}'
The KubeApp is created in the namespace matching the KubeOrg name (typically the org namespace like kaos-test).
Step 3: Apply the KubeApp
apiVersion: schema.kubecore.io/v1beta1
kind: KubeApp
metadata:
name:
namespace:
spec:
displayName: ""
description: ""
kubeProjectRef: ""
kubeAppTemplateRef: ""
profile: "small"
visibility: "public"
environmentSelector:
environmentTypes:
- "dev"
# Optional: environment variables
k8sAppConfig:
environmentVariables:
global:
CUSTOM_VAR: "value"
dev:
LOG_LEVEL: "debug"
The environmentSelector is critical — without it, the app will NOT deploy to any environment. Always set it.
Step 4: Monitor Provisioning
Watch the phase progression: Reconciling → Syncing → Reporting → Ready
kubectl get kubeapp -n --watch
Typical time to Ready: 3-5 minutes.
If stuck in a phase for more than 5 minutes, check conditions:
kubectl describe kubeapp -n
Step 5: Verify (see VERIFY section below)
Once Ready, run the full verification checklist.
READ — Check KubeApp Status
Quick Status
kubectl get kubeapp -n -o wide
Expected output when healthy:
NAME PHASE PROJECT TEMPLATE PROFILE REPOSITORY READY AGE
my-app Ready my-proj python-rest-api small https://github.com/org/proj-my-app true 5m
Detailed Status
kubectl get kubeapp -n -o yaml
Key fields to check:
status.phase— should beReadystatus.repositoryUrl— GitHub repository URLstatus.selectedEnvironments— which environments are activestatus.conditions— look fortype: Ready, status: "True"
Child Resources
kubectl get xgithubapp,xk8sapp -n | grep
Both should show SYNCED=True, READY=True.
UPDATE — Modify KubeApp Configuration
Update Profile
kubectl patch kubeapp -n --type=merge -p '{"spec":{"profile":"medium"}}'
Update Environment Variables
kubectl patch kubeapp -n --type=merge -p '{
"spec": {
"k8sAppConfig": {
"environmentVariables": {
"global": {"NEW_VAR": "value"},
"dev": {"LOG_LEVEL": "debug"}
}
}
}
}'
Add/Change Target Environments
kubectl patch kubeapp -n --type=merge -p '{
"spec": {
"environmentSelector": {
"environmentTypes": ["dev", "stage"]
}
}
}'
Update Visibility
kubectl patch kubeapp -n --type=merge -p '{"spec":{"visibility":"public"}}'
After any update, the operator detects the spec change (generation mismatch) and re-reconciles automatically. Monitor with:
kubectl get kubeapp -n --watch
DELETE — Remove a KubeApp
Delete the KubeApp
kubectl delete kubeapp -n
Monitor Deletion
The operator deletes resources sequentially: XK8sApp first, then XGitHubApp. This takes 1-3 minutes.
kubectl get kubeapp -n --watch
Verify Cleanup
# Child XRs should be gone
kubectl get xgithubapp,xk8sapp -n | grep
# Crossplane Objects should be gone
kubectl get object.kubernetes.m.crossplane.io -n | grep
If deletion hangs, check the operator logs:
kubectl logs -n kubecore-system deployment/kubecore-operator-controller-manager --tail=100 | grep
VERIFY — Deep Resource Verification
After creation or when troubleshooting, verify all provisioned resources across both the control plane and child cluster.
Control Plane Verification
# 1. KubeApp status
kubectl get kubeapp -n -o wide
# 2. Child XRs (both should be Synced + Ready)
kubectl get xgithubapp -n
kubectl get xk8sapp -n
# 3. All Crossplane Objects (count and health)
kubectl get object.kubernetes.m.crossplane.io -n | grep
# All should show Synced=True, Ready=True
# 4. GitHub webhook
kubectl get repositorywebhook.repo.github.m.upbound.io -n | grep
Child Cluster Verification
You need the child cluster kubeconfig. See references/child-cluster-access.md for how to obtain it.
# 5. CI namespace resources (EventSource, Sensor, Ingress)
kubectl get eventsource,sensor -n -ci | grep
kubectl get ingress -n -ci | grep
# EventSource: Deployed=True, Sensor: all conditions True
# 6. CI pods (should be Running, 0 restarts)
kubectl get pods -n -ci | grep
# 7. TLS certificate (should be Ready)
kubectl get certificate -n -ci | grep
# 8. ESO registry auth (CI push secret)
kubectl get externalsecret -n -ci | grep .*registry
kubectl get secret ci-registry-auth -n -ci
# 9. Pull secret in environment namespace
kubectl get secret -registry-pull -n - -o jsonpath='{.type}'
# Should be: kubernetes.io/dockerconfigjson
# 10. Deployment and pod
kubectl get deployment - -n -
kubectl get pods -n - -l app=-
# 11. ConfigMap with env vars
kubectl get configmap --config -n - -o jsonpath='{.data}'
# 12. Service
kubectl get svc --svc -n -
# 13. imagePullSecrets on Deployment
kubectl get deployment - -n - -o jsonpath='{.spec.template.spec.imagePullSecrets}'
Verification Summary Template
After running all checks, report status in this format:
## KubeApp Verification:
| Resource | Location | Status |
|----------|----------|--------|
| KubeApp | control plane | Ready / Phase |
| XGitHubApp | control plane | Synced+Ready / error |
| XK8sApp | control plane | Synced+Ready / error |
| Crossplane Objects | control plane | N/N healthy |
| GitHub Webhook | control plane | Synced+Ready / error |
| EventSource | child:-ci | Deployed / error |
| Sensor | child:-ci | Deployed / error |
| Ingress + TLS | child:-ci | Active + valid cert / error |
| CI Registry Auth | child:-ci | SecretSynced / error |
| Pull Secret | child:- | dockerconfigjson / missing |
| Deployment | child:- | Ready N/N / error |
| Pod | child:- | Running / status |
| ConfigMap | child:- | N keys / missing |
| Service | child:- | ClusterIP:port / missing |
| imagePullSecrets | child:- | configured / missing |
Troubleshooting
KubeApp stuck in Reconciling
- Check KubeProject is Ready:
kubectl get kubeproject -A - Check KubeAppTemplate exists:
kubectl get xkubeapptemplate - Check operator logs:
kubectl logs -n kubecore-system deployment/kubecore-operator-controller-manager --tail=100
KubeApp stuck in Syncing
- XGitHubApp or XK8sApp not ready
- Check:
kubectl describe xgithubapp -n - Common: branch protection rules failing, GitHub API rate limits
Pod ImagePullBackOff
- Pull secret missing or invalid
- Check:
kubectl get secret -registry-pull -n - - Check:
kubectl get deployment - -n - -o jsonpath='{.spec.template.spec.imagePullSecrets}'
Pod CreateContainerConfigError
- ConfigMap or Secret missing
- Check:
kubectl get configmap --config -n -
CI Workflow not triggering
- Check EventSource logs:
kubectl logs -n -ci -l eventsource-name= - Check Sensor logs:
kubectl logs -n -ci -l sensor-name= - Check webhook delivery on GitHub: repository Settings → Webhooks → Recent Deliveries
Deletion hangs
- Check operator logs for deletion errors
- XK8sApp must delete before XGitHubApp (sequential)
- If stuck, check for finalizers:
kubectl get xk8sapp -n -o jsonpath='{.metadata.finalizers}'
Environment Variables Merge Chain
When creating or updating a KubeApp, environment variables follow this merge order (lowest to highest priority):
- Template environmentSchema defaults —
SERVICE_NAME,LOG_LEVEL, etc. with context-derived values - Global environmentVariables —
spec.k8sAppConfig.environmentVariables.global - Per-environmentType overrides —
spec.k8sAppConfig.environmentVariables.dev/.stage/.prod
The base ConfigMap gets template + global. Each environment overlay gets the fully merged set.
Reference Files
references/child-cluster-access.md— How to obtain child cluster kubeconfigreferences/kubeapp-spec.md— Full KubeApp CRD field reference
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: kaos-io
- Source: kaos-io/agent-skills
- License: Apache-2.0
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.