Skip to content

Commit 660e8d5

Browse files
feat: add deployment and configuration guide for ArgoCD applications
1 parent 9e6de9b commit 660e8d5

File tree

2 files changed

+458
-0
lines changed

2 files changed

+458
-0
lines changed

docs/operations/deploy-app.md

Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
# Deploying an App
2+
3+
This guide explains how to add a new application to your cluster and have it
4+
automatically deployed by ArgoCD whenever you push to your `infra` repo.
5+
6+
---
7+
8+
## How it works (GitOps loop)
9+
10+
```
11+
You push to infra/ GitHub fires webhook ArgoCD syncs cluster
12+
kubernetes/apps/myapp/ ──────────────────────────▶ argocd.kevindb.dev ──▶ k8s applies
13+
```
14+
15+
1. Create app manifests in `infra/kubernetes/apps/<appname>/`
16+
2. Create an ArgoCD Application in `infra/kubernetes/argocd/apps/<appname>.yaml`
17+
3. Apply the ArgoCD Application once — from then on, **git push = deploy**
18+
19+
---
20+
21+
## Step 1 — Create your app manifests
22+
23+
Create a directory in your `infra` repo:
24+
25+
```
26+
infra/
27+
kubernetes/
28+
apps/
29+
myapp/
30+
deployment.yaml
31+
service.yaml
32+
ingress.yaml
33+
```
34+
35+
### deployment.yaml
36+
37+
```yaml
38+
apiVersion: apps/v1
39+
kind: Deployment
40+
metadata:
41+
name: myapp
42+
namespace: apps
43+
spec:
44+
replicas: 2
45+
selector:
46+
matchLabels:
47+
app: myapp
48+
template:
49+
metadata:
50+
labels:
51+
app: myapp
52+
spec:
53+
containers:
54+
- name: myapp
55+
image: myimage:latest
56+
ports:
57+
- containerPort: 80
58+
resources:
59+
requests:
60+
cpu: 50m
61+
memory: 64Mi
62+
limits:
63+
cpu: 200m
64+
memory: 128Mi
65+
```
66+
67+
### service.yaml
68+
69+
```yaml
70+
apiVersion: v1
71+
kind: Service
72+
metadata:
73+
name: myapp
74+
namespace: apps
75+
spec:
76+
selector:
77+
app: myapp
78+
ports:
79+
- port: 80
80+
targetPort: 80
81+
```
82+
83+
### ingress.yaml
84+
85+
```yaml
86+
# TLS certificate (cert-manager → Let's Encrypt)
87+
apiVersion: cert-manager.io/v1
88+
kind: Certificate
89+
metadata:
90+
name: myapp-tls
91+
namespace: apps
92+
spec:
93+
secretName: myapp-tls
94+
issuerRef:
95+
name: letsencrypt-production
96+
kind: ClusterIssuer
97+
dnsNames:
98+
- myapp.kevindb.dev
99+
---
100+
# Traefik IngressRoute
101+
apiVersion: traefik.io/v1alpha1
102+
kind: IngressRoute
103+
metadata:
104+
name: myapp
105+
namespace: apps
106+
spec:
107+
entryPoints:
108+
- websecure
109+
routes:
110+
- match: Host(`myapp.kevindb.dev`)
111+
kind: Rule
112+
services:
113+
- name: myapp
114+
port: 80
115+
tls:
116+
secretName: myapp-tls
117+
```
118+
119+
> Replace `myapp.kevindb.dev` with your actual subdomain.
120+
121+
---
122+
123+
## Step 2 — Add a DNS record
124+
125+
Point your subdomain to the cluster's external IP (same IP as all other apps):
126+
127+
```bash
128+
kubectl --context k3s-infra get svc -n ingress traefik \
129+
-o jsonpath='{.status.loadBalancer.ingress[0].ip}'
130+
```
131+
132+
Add an `A` record in your DNS provider:
133+
134+
| Type | Name | Value |
135+
|------|------|-------|
136+
| A | `myapp` | `<traefik-ip>` |
137+
138+
---
139+
140+
## Step 3 — Create the ArgoCD Application
141+
142+
Create `infra/kubernetes/argocd/apps/myapp.yaml`:
143+
144+
```yaml
145+
apiVersion: argoproj.io/v1alpha1
146+
kind: Application
147+
metadata:
148+
name: myapp
149+
namespace: argocd
150+
finalizers:
151+
- resources-finalizer.argocd.argoproj.io
152+
spec:
153+
project: default
154+
155+
source:
156+
repoURL: git@github.com:KevinDeBenedetti/infra.git
157+
targetRevision: main
158+
path: kubernetes/apps/myapp
159+
160+
destination:
161+
server: https://kubernetes.default.svc
162+
namespace: apps
163+
164+
syncPolicy:
165+
automated:
166+
prune: true # remove resources deleted from Git
167+
selfHeal: true # revert manual kubectl changes
168+
syncOptions:
169+
- CreateNamespace=true
170+
- ServerSideApply=true
171+
```
172+
173+
> `repoURL` must use the SSH format (`git@github.com:...`) to match the deploy key secret.
174+
175+
---
176+
177+
## Step 4 — Apply and push
178+
179+
```bash
180+
# Register the ArgoCD Application in the cluster
181+
kubectl --context k3s-infra apply -f kubernetes/argocd/apps/myapp.yaml
182+
183+
# Commit and push all manifests
184+
git add kubernetes/apps/myapp/ kubernetes/argocd/apps/myapp.yaml
185+
git commit -m "feat: add myapp"
186+
git push
187+
```
188+
189+
ArgoCD detects the push (via webhook) and syncs within seconds.
190+
191+
---
192+
193+
## Step 5 — Verify
194+
195+
```bash
196+
# Check ArgoCD sync status
197+
kubectl --context k3s-infra get application myapp -n argocd
198+
199+
# Check pods
200+
kubectl --context k3s-infra get pods -n apps
201+
202+
# Check certificate
203+
kubectl --context k3s-infra get certificate myapp-tls -n apps
204+
```
205+
206+
Or open the ArgoCD UI: **https://argocd.kevindb.dev**
207+
208+
---
209+
210+
## Day-to-day: updating an app
211+
212+
After initial setup, deploying a change is just:
213+
214+
```bash
215+
# Edit any manifest — e.g. bump the image tag
216+
vim infra/kubernetes/apps/myapp/deployment.yaml
217+
218+
git add -A && git commit -m "chore: bump myapp to v1.2.3" && git push
219+
```
220+
221+
ArgoCD auto-syncs. No `kubectl apply` needed.
222+
223+
---
224+
225+
## Removing an app
226+
227+
```bash
228+
# Delete the ArgoCD Application (triggers prune → removes cluster resources)
229+
kubectl --context k3s-infra delete application myapp -n argocd
230+
231+
# Remove the manifests from git
232+
rm -rf kubernetes/apps/myapp/ kubernetes/argocd/apps/myapp.yaml
233+
git add -A && git commit -m "chore: remove myapp" && git push
234+
```
235+
236+
---
237+
238+
## Checklist
239+
240+
- [ ] DNS `A` record pointing to Traefik IP
241+
- [ ] `kubernetes/apps/myapp/` directory with deployment, service, ingress
242+
- [ ] `kubernetes/argocd/apps/myapp.yaml` with SSH `repoURL`
243+
- [ ] `kubectl apply -f kubernetes/argocd/apps/myapp.yaml` (once)
244+
- [ ] `git push` — ArgoCD handles the rest
245+
246+
---
247+
248+
## See also
249+
250+
- [ArgoCD stack reference](../stack/argocd.md)
251+
- [Traefik IngressRoute reference](../stack/traefik.md)
252+
- [cert-manager TLS reference](../stack/cert-manager.md)
253+
- [whoami example app](https://github.com/KevinDeBenedetti/infra/tree/main/kubernetes/apps/whoami) — working reference implementation

0 commit comments

Comments
 (0)