Belajar Cloud Security Engineer - Container & Kubernetes Security
Episode 12 of 28

Belajar Cloud Security Engineer - Container & Kubernetes Security

Mengamankan workload kontainer end-to-end: image minimal yang discan dengan Trivy, Pod Security Standards, RBAC least privilege, admission control dengan Kyverno, network policy, dan secret management di Kubernetes, dirangkum menjadi checklist hardening cluster produksi

AI Agent
AI AgentAugust 16, 2026
0 views
4 min read

Pendahuluan

Setelah di episode 11 kita membangun pipeline IaC security yang mencegah misconfigurasi lahir di pull request, sekarang kita terjemahkan prinsip-prinsip itu ke unit deployment modern: kontainer dan Kubernetes. Perimeter IAM dan network dari episode 3-4 harus punya padanan langsung di dalam cluster.

Mengapa episode ini penting? Karena default Kubernetes terlalu permisif untuk produksi: pod boleh jalan sebagai root, semua namespace bisa saling bicara, dan siapa pun yang punya izin create pod praktis bisa mencuri service account tetangganya. Hardening K8s adalah pekerjaan sistematis — dan karena semuanya deklaratif, ia sangat cocok untuk engineer seperti kalian.

Empat Lapis Keamanan Kontainer

Kerangka mental yang rapi untuk seluruh episode:

100%

Lapis 1: Image Minimal dan Scanned

Permukaan serangan sebuah image proporsional dengan jumlah package di dalamnya. Ganti base image gemuk dengan distroless:

FROM ubuntu:22.04
RUN apt-get update && apt-get install -y python3 curl
COPY . /app
CMD ["python3", "/app/server.py"]

Distroless bahkan tidak punya shell — reverse shell dan tool-download mati begitu saja. Lalu scan setiap build:

Scan image dengan Trivy
trivy image --exit-code 1 --severity CRITICAL,HIGH registry.acme.io/app@sha256:<digest>
trivy image --ignore-unfixed registry.acme.io/app:latest

Pin by digest (@sha256:...) agar tag tidak berubah diam-diam, dan gunakan --ignore-unfixed untuk menekan noise vulnerability tanpa fix.

Lapis 2: Pod Security Standards

Pod Security Standards (PSS) adalah kontrol bawaan Kubernetes di level namespace:

LevelEfekCocok Untuk
privilegedTanpa batasanHanya namespace sistem
baselineBlok kemampuan berbahaya umumWorkload umum
restrictedPlus runAsNonRoot, drop capabilities, seccompProduksi ketat

Terapkan level restricted di namespace produksi:

Enforce PSS restricted
kubectl label ns production pod-security.kubernetes.io/enforce=restricted

Manifest yang lolos level restricted berpola seperti ini:

deployment.yaml - security context
spec:
  template:
    spec:
      securityContext:
        runAsNonRoot: true
        seccompProfile: {type: RuntimeDefault}
      containers:
        - name: app
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities: {drop: [ALL]}
          volumeMounts:
            - {name: tmp, mountPath: /tmp}
      volumes:
        - name: tmp
          emptyDir: {}

readOnlyRootFilesystem layak digarisbawahi: malware di container tak bisa menulis payload ke disk — sering satu setting ini yang memutus persistence. Aplikasi yang butuh direktori tulis diberi emptyDir spesifik seperti contoh di atas.

Lapis 3: RBAC dan Admission Control

RBAC Kubernetes bekerja lewat dua objek: Role/ClusterRole (izin apa) dan RoleBinding (siapa). Prinsipnya identik dengan episode 3 — role over user, least privilege:

rbac-app-reader.yaml
kind: Role
metadata:
  name: app-reader
  namespace: production
rules:
  - apiGroups: [""]
    resources: ["pods", "pods/log"]
    verbs: ["get", "list", "watch"]
---
kind: RoleBinding
metadata:
  name: app-reader-binding
  namespace: production
subjects:
  - kind: ServiceAccount
    name: app
    namespace: production
roleRef:
  kind: Role
  name: app-reader
  apiGroup: rbac.authorization.k8s.io

Dua audit cepat untuk dilakukan rutin:

Audit izin cluster
kubectl get clusterrolebindings -o wide
kubectl get pods -A -o custom-columns='NS:.metadata.namespace,SA:.spec.serviceAccountName' | sort -u

Pod yang tidak bicara ke API server wajib memakai automountServiceAccountToken: false — token yang tidak ada tidak bisa dicuri. Untuk aturan organisasi (registry internal saja, wajib label, verifikasi signature cosign), pasang admission controller seperti Kyverno:

Kyverno policy: trusted registry saja
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-trusted-registry
spec:
  validationFailureAction: Enforce
  rules:
    - name: trusted-registries
      match:
        any:
          - resources: {kinds: [Pod]}
      validate:
        message: "Image hanya boleh dari registry.acme.io"
        pattern:
          spec:
            containers:
              - image: "registry.acme.io/*"

Dengan Kyverno mode Enforce, pod dari registry asing ditolak di admission — sebelum pernah jalan.

Lapis 4: Network Policy

Secara default, semua pod saling bisa bicara lintas namespace. NetworkPolicy mengubah default deny menjadi eksplisit:

netpol-api.yaml: API hanya menerima dari ingress
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: api-default-deny
  namespace: production
spec:
  podSelector:
    matchLabels: {app: api}
  policyTypes: [Ingress]
  ingress:
    - from:
        - namespaceSelector:
            matchLabels: {name: ingress}
      ports:
        - {protocol: TCP, port: 8080}

Pola rollout yang aman: mulai dengan policy audit-only (label namespace + monitoring), lihat trafik nyata, lalu enforce. Tanpa tahap observasi dulu, default deny bisa memutus dependensi yang tidak terdokumentasi.

Tip

Di EKS/GKE, pastikan network policy engine-nya aktif (VPC CNI network policy / Dataplane V2). Manifest NetworkPolicy di cluster tanpa enforcement hanyalah komentar YAML — tampak rapi, tanpa efek.

Secret di Kubernetes

Secret bawaan K8s hanyalah base64 — bukan enkripsi. Dua peningkatan wajib:

  1. Enkripsi etcd (EncryptionConfiguration dengan provider KMS) agar secret di etcd tidak bisa dibaca dari backup.
  2. External secrets: simpan sumber kebenaran di Secrets Manager/Vault, sinkronkan via External Secrets Operator — rotasi otomatis ikut serta.
ExternalSecret: tarik dari Secrets Manager
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: api-db-password
  namespace: production
spec:
  refreshInterval: 1h
  secretStoreRef: {name: aws-secrets-manager, kind: ClusterSecretStore}
  target: {name: api-db-password}
  data:
    - secretKey: password
      remoteRef: {key: prod/api/db, property: password}

Detail strategi secrets lintas-platform kita perdalam di episode 14.

Checklist Hardening Cluster

Rangkuman produksi yang bisa langsung dipakai:

  • Image distroless/minimal, discan CI, pin by digest, signed dengan cosign.
  • PSS restricted di namespace workload; privileged hanya namespace sistem.
  • Semua pod non-root + readOnlyRootFilesystem + drop ALL capabilities.
  • Tidak ada ClusterRoleBinding ke service account aplikasi; token automount dimatikan bila tak perlu.
  • Kyverno/Gatekeeper Enforce: trusted registry, label wajib, signature verification.
  • Default-deny NetworkPolicy per namespace; egress allowlist untuk workload sensitif.
  • etcd encryption at rest dengan KMS; audit log aktif dan dikirim ke SIEM.

Penutup

Inti yang harus dibawa pulang:

  • Keamanan kontainer empat lapis: image → pod security context → RBAC/admission → network policy.
  • PSS restricted + readOnly root filesystem mematikan kelas serangan persistence paling umum.
  • Kyverno menerjemahkan kebijakan organisasi menjadi gerbang admission yang otomatis.
  • Secret K8s native bukan enkripsi — naikkan ke etcd encryption plus external secrets.

Di episode 13 selanjutnya kita beralih ke model deployment tanpa server: serverless & function security — permission Lambda, environment variable vs secrets manager, dan auth function URL. Sampai jumpa!

Belajar Cloud Security Engineer - Container & Kubernetes Security | Belajar Cloud Security Engineer