This episode covers GitOps and policy as code: managing Installation, IPPool, BGPPeer, and policy as code with Argo CD or Flux, complete with versioning, a review flow, and phased rollout.

So far we've applied policy with calicoctl apply directly to the cluster. In production, that pattern is risky: no trace, no review, and no easy rollback. Episode 18 changes your workflow into policy as code — all Calico configuration lives in a repository, and clusters reconcile themselves to that repository.
GitOps is not just "store YAML in git". It's about making git the single source of truth, making policy rollouts reviewable like code, and building a complete audit trail.
With calicoctl apply, policy changes have no history. Who changed the policy last night? What changes rode along with it? Hard to answer. Worse, there is no easy way to see the difference between the desired policy and what's installed.
With GitOps, every policy change is a commit with a clear message and a reviewed pull request. Clusters automatically reconcile their actual state with the repository contents. Unwanted changes are easy to detect because the cluster reports "out of sync".
Organize Calico resources in a folder separate from application manifests:
calico/
installation.yaml
ippools/
default-ipv4-ippool.yaml
bgp/
bgpconfiguration.yaml
bgppeers.yaml
policies/
tiers/
global/
namespace/This structure separates infrastructure configuration (Installation, IPPool) from security policy, so review authority can be split: the platform team for the former, the application teams for the latter.
apiVersion: operator.tigera.io/v1
kind: Installation
metadata:
name: default
spec:
calicoNetwork:
ipPools:
- name: default-ipv4-ippool
cidr: 192.168.0.0/16
blockSize: 26
encapsulation: IPIPThis resource is identical to what you'd write by hand — only now it's managed by git.
With Argo CD, create an Application pointing at the calico/ folder:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: calico-policy
namespace: argocd
spec:
destination:
server: https://kubernetes.default.svc
namespace: default
project: platform
source:
repoURL: https://git.example.com/infra.git
path: calico
targetRevision: main
syncPolicy:
automated:
prune: true
selfHeal: trueautomated.prune and automated.selfHeal make Argo CD remove resources that disappeared from git and revert manual changes back to the git state.
With Flux, create a Kustomization pointing at the same source:
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: calico-policy
namespace: flux-system
spec:
interval: 5m
path: ./clusters/prod/calico
prune: true
sourceRef:
kind: GitRepository
name: infraBoth approaches are equally valid; pick the one you already use for other workloads so operations stay uniform.
kubectl get application calico-policy -n argocd
kubectl get application calico-policy -n argocd -o jsonpath='{.status.sync.status}'
calicoctl get globalnetworkpolicy -o widecalicoctl get globalnetworkpolicy -o wide compares the installed policy with what's in git — the foundation of review and audit.
Store policy in a sensible order: a folder per environment (staging/, prod/), and use release tags for major changes. Breaking changes — like a new global default deny — deserve their own major version.
Every policy change goes through: branch → pull request → review → merge to main. Put a mandatory label on PRs that touch tier: security, because that part has the biggest impact:
git checkout -b add-payments-deny
git add calico/policies/namespace/
git commit -m "feat(calico): default deny untuk namespace payments"
git push origin add-payments-denyDon't let a merge go live in production all at once. Apply to staging first, watch the metrics, then promote to production:
staging (not production) -> one production namespace -> full productionCombine this with automated smoke tests: after sync, run a kubectl exec to confirm core applications can still communicate.
Installation and FelixConfiguration are high-impact resources. Be careful with prune: true if the policy folder is incomplete — Argo CD could delete an IPPool that's still in use. Always keep complete resources in git.
If multiple tools write the same resource (for example a manual script and Argo CD), the result is a state war. Establish one source of truth: git, and keep other tools read-only with respect to Calico resources.
Episode 18 turns Calico configuration from ad-hoc commands into managed code: a structured repository, Argo CD or Flux as the applier, a review flow per change, and a safe phased rollout.
Key takeaways:
selfHeal and prune keep the cluster always matching git.Next, in episode 19, we cover performance and troubleshooting — diagnosing with calicoctl, Felix and typha logs, common cases like pods that can't communicate, policy rejecting traffic, BGP not coming up, IPAM problems, and version upgrades.