5. Kubernetes Workloads
5. Kubernetes Workloads
← Previous: Components | Index | Next: CI/CD Identity →
5.1 ServiceAccount Patterns
5.1.1 ServiceAccount as Identity Foundation
Every Kubernetes pod runs with a ServiceAccount. This RFC builds on ServiceAccounts as the foundation for workload identity:
| Layer | Identity Source |
|---|---|
| Kubernetes | ServiceAccount → Pod identity |
| SPIRE | ServiceAccount → SPIFFE ID |
| Vault | ServiceAccount → Vault policy |
| Linkerd | ServiceAccount → mTLS identity |
| Cloud | ServiceAccount → Cloud IAM role |
5.1.2 ServiceAccount Best Practices
| Practice | Requirement | Rationale |
|---|---|---|
| Dedicated SAs | One SA per workload type | Enables fine-grained RBAC |
| No default SA | Never use default SA | Prevents accidental over-permissioning |
| Minimal RBAC | Only required API access | Least privilege |
| Token projection | Use projected tokens, not legacy | Short-lived, audience-bound |
5.1.3 ServiceAccount Configuration
Example ServiceAccount with projected token:
5.2 SPIRE Agent Deployment
5.2.1 SPIRE Agent DaemonSet
SPIRE Agent runs on every node to provide workload attestation:
5.2.2 Workload Socket Access
Workloads access SPIRE through a shared Unix socket:
5.2.3 SPIRE Registration
Workloads must be registered with SPIRE to receive SVIDs:
| Registration Method | Use Case |
|---|---|
| Manual | Static workloads with known identity |
| K8s Registrar | Automatic registration based on labels |
| Controller | Dynamic registration via API |
Example registration via K8s Registrar:
5.2.4 SPIRE Workload Flow
5.3 Vault Kubernetes Auth
5.3.1 Authentication Flow
5.3.2 Auth Method Configuration
5.3.3 Role Configuration
Roles map ServiceAccounts to policies:
5.3.4 Policy Templates
Policies use identity metadata for dynamic scoping:
5.4 Namespace Isolation
5.4.1 Namespace as Security Boundary
Namespaces provide the primary isolation boundary for workload identity:
| Scope | Isolation Mechanism |
|---|---|
| Kubernetes RBAC | Namespace-scoped Roles |
| Vault policies | Templated paths with namespace |
| SPIFFE IDs | Namespace in path |
| Network policies | Namespace selectors |
| Linkerd | Namespace-scoped authorization |
5.4.2 Cross-Namespace Access
Cross-namespace access requires explicit configuration:
| Scenario | Configuration |
|---|---|
| Service mesh | ServerAuthorization allows specific source namespaces |
| Vault | Policy explicitly grants cross-namespace paths |
| SPIRE | Registration entry allows cross-namespace SPIFFE ID |
Example cross-namespace authorization:
5.4.3 Namespace-Scoped SPIFFE IDs
SPIFFE ID structure enforces namespace isolation:
| SPIFFE ID | Access |
|---|---|
spiffe://prod.example.com/ns/payments/sa/api | Payments namespace resources |
spiffe://prod.example.com/ns/monitoring/sa/prometheus | Monitoring + observed namespaces |
5.5 Identity Lifecycle
5.5.1 Workload Bootstrap
5.5.2 Credential Renewal
| Credential | TTL | Renewal Mechanism |
|---|---|---|
| SA Token | 10 min | Kubelet automatic projection |
| SPIFFE SVID | 1-24h | SPIRE Agent pushes new SVID |
| Vault Token | 1h | Vault Agent renews |
| DB Credential | 1h | Vault lease renewal |
5.5.3 Workload Termination
On pod termination:
| Credential | Revocation |
|---|---|
| SA Token | Invalidated by Kubernetes |
| SPIFFE SVID | Removed from agent cache |
| Vault Token | Revoked on agent shutdown |
| DB Credential | Lease not renewed, expires |
5.6 Workload Patterns
5.6.1 Standard Application Pattern
5.6.2 Sidecar Pattern
For applications requiring continuous secret refresh:
5.6.3 CSI Driver Pattern
For simpler secret consumption:
5.7 Compliance Mapping
5.7.1 Invariant Enforcement
| Invariant | Kubernetes Implementation |
|---|---|
| INV-1 | ServiceAccount + SPIRE SVID |
| INV-2 | Projected tokens (10 min), SVID (24h max) |
| INV-3 | SPIRE workload attestation |
| INV-4 | Projected SA token to Vault |
| INV-6 | Linkerd mTLS |
| INV-7 | Namespace-scoped policies |
5.7.2 Verification Checklist
| Verification | Method |
|---|---|
| All pods have non-default SA | `kubectl get pods -A -o jsonpath='{.items[*].spec.serviceAccountName}' |
| All pods in service mesh | linkerd stat deploy -A |
| No legacy SA tokens | `kubectl get sa -A -o yaml |
| SPIRE coverage | SPIRE Agent metrics |
Document Navigation
| Previous | Index | Next |
|---|---|---|
| ← 4. Components | Table of Contents | 6. CI/CD Identity → |
End of Section 5