A complete review of the Kubernetes objects most often managed by ArgoCD, an introduction to templating with Helm, configuration composition with Kustomize, and healthy manifest directory organization patterns.

In episode 2 we dissected the ArgoCD architecture and understood that it's an operator that manages Kubernetes manifests. That means, before the hands-on part, we must be truly comfortable with the thing being managed: Kubernetes manifests, plus the two tools that turn plain manifests into flexible configuration — Helm and Kustomize. This episode is a recap that brings those three worlds together, and at the same time the technical preparation for episodes 4 through 8, which are entirely hands-on.
If you already know this material from other series, treat this episode as a quick reference. For those where it's still fuzzy, this is the right time to fill the gaps — because all the manifests here will be written and managed by you through ArgoCD.
These are the objects ArgoCD manages most often. The patterns you see here will repeat throughout the entire series.
The most basic pair: a Deployment defines replicas and image; a Service opens a stable communication path:
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: ghcr.io/arman/api:v1.2.0
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: api
namespace: production
spec:
selector:
app: api
ports:
- port: 80
targetPort: 8080Both separate configuration from the image. The main difference: Secret values are stored base64-encoded (not encrypted!) and have separate RBAC behavior:
apiVersion: v1
kind: ConfigMap
metadata:
name: api-config
namespace: production
data:
LOG_LEVEL: "info"
MAX_CONNECTIONS: "100"
---
apiVersion: v1
kind: Secret
metadata:
name: api-secret
namespace: production
type: Opaque
stringData:
DB_PASSWORD: "s3cr3t-yang-harus-dikelola"Warning
Putting plain secrets in Git violates secure GitOps principles. In this series we still use them to keep the focus on ArgoCD concepts, but remember: in production, use Sealed Secrets, SOPS, the External Secrets Operator, or Vault (covered in later episodes).
An Ingress routes external traffic to a Service inside the cluster:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-ingress
namespace: production
spec:
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api
port:
number: 80A Namespace is a logical partition: production, staging, dev, or team-a. ArgoCD can be locked down to only deploy to specific namespaces via a Project (covered in episode 10).
Helm is the package manager for Kubernetes. It turns manifests into templates that can be parameterized.
The standard chart structure:
my-app/
├── Chart.yaml # metadata chart (name, version, apiVersion)
├── values.yaml # nilai default yang bisa di-override
├── values-prod.yaml # nilai khusus environment
└── templates/
├── deployment.yaml # template Deployment
├── service.yaml
└── _helpers.tpl # named template helperInside templates/deployment.yaml, the parts that change are written as template expressions that read values.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Chart.Name }}
namespace: {{ .Release.Namespace }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ .Chart.Name }}
template:
metadata:
labels:
app: {{ .Chart.Name }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"The default values in values.yaml can be overridden per environment with a -f values-prod.yaml file or --set image.tag=v1.3.0. Dependencies between charts are managed in Chart.yaml via dependencies:.
Where Helm uses templating, Kustomize uses overlays: the original definition (base) is never modified, other environments simply override parts via patches.
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
namePrefix: prod-
patches:
- target:
kind: Deployment
name: api
patch: |
- op: replace
path: /spec/replicas
value: 5
images:
- name: ghcr.io/arman/api
newTag: v1.3.0Notice Kustomize's advantage: no template expressions are injected into the text; the end result is pure YAML that can be read directly. This preserves auditability — what's in Git is exactly what gets applied.
Kustomize can also generate ConfigMaps and Secrets from files or literals:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
configMapGenerator:
- name: api-config
literals:
- LOG_LEVEL=info
- MAX_CONNECTIONS=100The advantage of generators: a small change produces a new hash suffix so the Deployment rolls automatically.
Without good organization, a manifest repository turns into garbage. Two patterns are common in the real world:
gitops/
├── base/ # definisi netral semua aplikasi
│ ├── api/
│ │ ├── deployment.yaml
│ │ └── service.yaml
│ └── web/
│ └── deployment.yaml
└── overlays/ # kustomisasi per environment
├── dev/
├── staging/
└── production/apps/
├── api/
│ ├── dev/
│ ├── staging/
│ └── production/
└── web/
├── dev/
├── staging/
└── production/Tip
The golden rule: one environment, one clear set of values. Pick one pattern and stay consistent. A tidy manifest repository is a prerequisite so that ArgoCD (and your team) can work without confusion.
This episode refreshes three technical foundations:
With this technical foundation, we're ready to enter the installation phase. In episode 4 we'll install ArgoCD on your cluster: choosing the installation method, doing the initial setup, and opening its UI for the first time. See you there!