# Declarative Resource Management

> **CNPA Domain:** Platform Engineering Core Fundamentals (36%) **Topic:** Declarative Resource Management

## Overview

**Declarative resource management** is the practice of describing the *desired state* of infrastructure and applications in configuration files, letting the system continuously reconcile toward that state. It is the cornerstone of modern platform engineering: combining Kubernetes manifests, Helm charts, and Kustomize overlays gives platform teams a powerful toolkit for consistent, auditable, and repeatable deployments.

***

## Declarative vs Imperative

| Approach        | How                                                    | Example                        |
| --------------- | ------------------------------------------------------ | ------------------------------ |
| **Imperative**  | Tell the system *what to do* step by step              | `kubectl create deployment...` |
| **Declarative** | Tell the system *what you want*, let it figure out how | Apply a YAML manifest          |

```bash
# Imperative — fragile, hard to reproduce
kubectl create deployment nginx --image=nginx:1.25
kubectl scale deployment nginx --replicas=3
kubectl expose deployment nginx --port=80

# Declarative — reproducible, version-controlled
kubectl apply -f deployment.yaml
```

The declarative model is the foundation of GitOps and Kubernetes-native platform workflows.

***

## Kubernetes Manifests

Kubernetes manifests are YAML (or JSON) files that describe the desired state of Kubernetes resources.

### Core Resource Types for Platform Engineers

| Resource         | Purpose                                 |
| ---------------- | --------------------------------------- |
| `Deployment`     | Declarative Pod lifecycle management    |
| `Service`        | Stable network endpoint for Pods        |
| `ConfigMap`      | Non-sensitive configuration data        |
| `Secret`         | Sensitive configuration data            |
| `Namespace`      | Environment/tenant isolation            |
| `ResourceQuota`  | CPU/memory limits per namespace         |
| `LimitRange`     | Default resource requests per container |
| `NetworkPolicy`  | Pod-to-pod traffic rules                |
| `ServiceAccount` | Identity for workloads                  |

### Example: A Complete Application Manifest

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: payment-service
  namespace: payments-production
  labels:
    app: payment-service
    version: "2.1.0"
    team: payments
spec:
  replicas: 3
  selector:
    matchLabels:
      app: payment-service
  template:
    metadata:
      labels:
        app: payment-service
        version: "2.1.0"
    spec:
      containers:
        - name: payment-service
          image: registry.example.com/payment-service:2.1.0
          ports:
            - containerPort: 8080
          resources:
            requests:
              cpu: "100m"
              memory: "128Mi"
            limits:
              cpu: "500m"
              memory: "512Mi"
          envFrom:
            - configMapRef:
                name: payment-service-config
            - secretRef:
                name: payment-service-secrets
          livenessProbe:
            httpGet:
              path: /health/live
              port: 8080
            initialDelaySeconds: 10
          readinessProbe:
            httpGet:
              path: /health/ready
              port: 8080
```

***

## Helm: Parametric Kubernetes Packaging

**Helm** is the package manager for Kubernetes, allowing you to define, install, and upgrade complex workloads as reusable **charts**.

### Key Helm Concepts

| Concept        | Description                                              |
| -------------- | -------------------------------------------------------- |
| **Chart**      | A package of Kubernetes templates + metadata             |
| **Values**     | User-supplied configuration that parameterizes templates |
| **Release**    | A deployed instance of a chart                           |
| **Repository** | Collection of charts (like npm or PyPI)                  |

### Chart Structure

```
my-app/
├── Chart.yaml          # Chart metadata
├── values.yaml         # Default values
├── values-staging.yaml # Environment overrides
├── templates/
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── configmap.yaml
│   └── _helpers.tpl    # Template helpers
└── charts/             # Chart dependencies
```

### Parameterizing for Multiple Environments

```yaml
# values.yaml (defaults)
replicaCount: 1
image:
  tag: latest
resources:
  limits:
    cpu: 500m
    memory: 512Mi

# values-production.yaml (override)
replicaCount: 5
image:
  tag: 2.1.0
resources:
  limits:
    cpu: 2000m
    memory: 2Gi
```

```bash
# Deploy to staging
helm upgrade --install myapp ./my-app -f values-staging.yaml -n myapp-staging

# Deploy to production
helm upgrade --install myapp ./my-app -f values-production.yaml -n myapp-production
```

Platform teams publish **curated Helm charts** as golden path templates—developers fill in values, the platform handles the rest.

***

## Kustomize: Overlay-Based Customization

**Kustomize** is built into `kubectl` and enables environment-specific customization via **overlays** without templating.

### Directory Structure

```
k8s/
├── base/               # Shared base manifests
│   ├── kustomization.yaml
│   ├── deployment.yaml
│   └── service.yaml
└── overlays/
    ├── staging/
    │   ├── kustomization.yaml
    │   └── replica-patch.yaml
    └── production/
        ├── kustomization.yaml
        └── resource-patch.yaml
```

```yaml
# overlays/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - ../../base

namespace: myapp-production

images:
  - name: myapp
    newTag: "2.1.0"

patches:
  - path: resource-patch.yaml
    target:
      kind: Deployment
      name: myapp
```

```bash
# Apply production overlay
kubectl apply -k k8s/overlays/production/
```

### Helm vs Kustomize

| Aspect         | Helm                     | Kustomize                   |
| -------------- | ------------------------ | --------------------------- |
| Approach       | Templating with `{{ }}`  | Pure YAML + patches         |
| Learning curve | Medium                   | Low                         |
| Ecosystem      | Huge chart library       | Kubernetes-native           |
| Best for       | Complex parameterization | Simple environment overlays |
| GitOps support | Via Helm Controller      | Native `kubectl apply -k`   |

Many teams use **both**: Helm for third-party charts, Kustomize for their own application overlays.

***

## Desired State and Reconciliation

The declarative model introduces the concept of **desired state** vs **actual state**:

```
Desired State (Git)          Actual State (Cluster)
──────────────────           ──────────────────────
replicas: 3             ≠    replicas: 2 (pod crashed)
image: v2.1.0           ≠    image: v2.0.0 (pending rollout)
     ↓
Reconciliation Loop (e.g., Kubernetes controller, ArgoCD)
     ↓
Actual State → Desired State
```

This is the foundation of [GitOps](https://blog.htunnthuthu.com/getting-started/fundamentals/platform-engineering-101/platform-engineering-101-gitops): the Git repository is the single source of truth for desired state, and tools continuously reconcile the cluster toward it.

***

## Resource Management Best Practices for Platform Teams

### 1. Always Set Resource Requests and Limits

```yaml
resources:
  requests:        # Guaranteed allocation (scheduling)
    cpu: "100m"
    memory: "128Mi"
  limits:          # Maximum allowed (throttling/OOM kill)
    cpu: "500m"
    memory: "512Mi"
```

### 2. Use ResourceQuotas per Namespace/Team

```yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: team-quota
  namespace: payments-dev
spec:
  hard:
    requests.cpu: "4"
    requests.memory: "8Gi"
    limits.cpu: "8"
    limits.memory: "16Gi"
    pods: "20"
```

### 3. Label Everything Consistently

```yaml
labels:
  app.kubernetes.io/name: payment-service
  app.kubernetes.io/version: "2.1.0"
  app.kubernetes.io/component: backend
  app.kubernetes.io/part-of: checkout-platform
  app.kubernetes.io/managed-by: helm
  team: payments
  environment: production
```

### 4. Separate Configuration from Code

Always use `ConfigMaps` and `Secrets` injected at runtime. Never bake environment-specific values into container images.

***

## Key Takeaways

* **Declarative management** describes desired state; the platform continuously reconciles actual state to match
* **Kubernetes manifests** are the primitive — always prefer `kubectl apply` over imperative commands in production
* **Helm** enables parameterized, reusable chart packaging useful for platform golden paths
* **Kustomize** provides clean overlay-based customization without templating overhead
* Set **resource requests/limits** and **ResourceQuotas** to prevent noisy-neighbor issues
* Consistent **labels** are essential for observability, policy enforcement, and cost attribution

***

## Further Reading

* [Kubernetes Declarative Management](https://kubernetes.io/docs/tasks/manage-kubernetes-objects/declarative-config/)
* [Helm Documentation](https://helm.sh/docs/)
* [Kustomize Documentation](https://kustomize.io/)
* → Next: [CI/CD Fundamentals for Platform Engineering](https://blog.htunnthuthu.com/getting-started/fundamentals/platform-engineering-101/platform-engineering-101-cicd-fundamentals)
