Menerapkan seccomp di Kubernetes lewat field seccompProfile pada securityContext, evolusinya dari annotation alpha, dan kaitannya dengan Pod Security Standards. Termasuk distribusi profil kustom antar node serta seccomp-profiles-operator.

Di episode 9 kalian mengunci service langsung di host. Di cluster Kubernetes, tantangannya lebih besar: ada banyak node, banyak pod, dan runtime yang berbeda. Namun prinsipnya sama — pod menjalankan container yang berbagi kernel node, dan syscall berbahaya harus dipangkas. Bedanya, Kubernetes menambahkan satu lapisan abstraksi: seccompProfile di securityContext.
Episode 10 ini membahas cara menerapkan seccomp di Kubernetes: field seccompProfile, evolusinya dari annotation alpha, Pod Security Standards, distribusi profil kustom antar node, dan seccomp-profiles-operator.
Kubernetes punya sejarah panjang soal seccomp. Awalnya (jauh sebelum versi 1.19), satu-satunya cara adalah annotation alpha:
apiVersion: v1
kind: Pod
metadata:
name: legacy-app
annotations:
seccomp.security.alpha.kubernetes.io/pod: "runtime/default"
spec:
containers:
- name: app
image: busybox
command: ["sleep", "3600"]Annotation ini rapuh: tidak ada validasi schema, sulit diterapkan per-container, dan statusnya alpha membuatnya berubah kapan saja. Karena itu Kubernetes memperkenalkan field proper seccompProfile di securityContext (beta sejak 1.19, GA sejak 1.25). Sejak itu, seccomp dianggap infrastruktur — bukan eksperimen.
Note
Bila kalian menemukan dokumentasi lama atau chart Helm yang masih memakai annotation seccomp.security.alpha.kubernetes.io/pod, rencanakan migrasi ke field seccompProfile. Annotation lama tetap terbaca sebagai kompatibilitas, tapi bukan cara yang direkomendasikan untuk konfigurasi baru.
Field securityContext.seccompProfile.type menerima tiga nilai:
Unconfined — tanpa filter seccomp. Ini default historis Kubernetes; hindari kecuali benar-benar yakin.RuntimeDefault — profil bawaan runtime container. Di Docker/containerd ini adalah docker-default dari episode 8: denylist syscall berbahaya yang dirawat komunitas.Localhost — profil kustom berupa file JSON yang ada di setiap node, dirujuk lewat localhostProfile.Aturan penetapannya sederhana: seccompProfile di level pod berlaku sebagai default untuk semua container, dan container bisa menimpanya lewat seccompProfile-nya sendiri. Level paling spesifik menang.
Ini pola yang paling umum — pod memakai profil bawaan runtime:
apiVersion: v1
kind: Pod
metadata:
name: webapp
spec:
securityContext:
seccompProfile:
type: RuntimeDefault
containers:
- name: nginx
image: nginx:1.27Untuk kontrol penuh, arahkan ke profil kustom yang disimpan di node:
apiVersion: v1
kind: Pod
metadata:
name: webapp-custom
spec:
containers:
- name: nginx
image: nginx:1.27
securityContext:
seccompProfile:
type: Localhost
localhostProfile: profiles/webapp-allowlist.jsonlocalhostProfile bersifat relatif terhadap /var/lib/kubelet/seccomp/ di node. File profil harus ada di semua node tempat pod dijadwalkan — inilah sumber masalah operasional yang akan kita bahas sebentar lagi.
Tip
Mulailah dengan RuntimeDefault untuk seluruh beban kerja. Ini memberi baseline seccomp yang kuat dengan biaya operasional nol. Setelah itu, naikkan secara bertahap ke Localhost dengan allowlist khusus untuk workload yang kalian pahami (mengikuti alur baseline strace dari episode 7 dan 8).
Kubernetes tidak berhenti di level API — ia juga menstandarkan kebijakan. Pod Security Standards mendefinisikan dua level yang berhubungan dengan seccomp:
seccompProfile.type: RuntimeDefault untuk semua pod.allowPrivilegeEscalation: false dan pembuangan capabilities.Kebijakan ini ditegakkan per-namespace lewat label pod-security.kubernetes.io/enforce:
apiVersion: v1
kind: Namespace
metadata:
name: secure-ns
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restrictedPod yang tidak memenuhi level Restricted akan ditolak (karena enforce) atau dilaporkan di audit log (karena audit) — pasangan label yang tepat untuk roll out bertahap. Ini cara tercepat menormalkan seccomp di seluruh cluster: bukan mengandalkan disiplin individu, tapi menegakkan lewat platform.
Inilah tantangan nyata Localhost: profil adalah file di filesystem node, dan file itu harus identik di semua node — termasuk node yang ditambahkan nanti. Mengelola ini manual adalah resep bencana. Tiga pendekatan yang umum:
Pendekatan ketiga paling cocok untuk cluster yang terus berubah. Dengan operator, profil dideklarasikan sebagai CRD:
apiVersion: security-profiles-operator.x-k8s.io/v1beta1
kind: SeccompProfile
metadata:
name: webapp-allowlist
namespace: security
spec:
defaultAction: SCMP_ACT_ERRNO
defaultErrnoRet: 1
archs:
- SCMP_ARCH_X86_64
syscalls:
- action: SCMP_ACT_ALLOW
names:
- read
- write
- openat
- close
- mmap
- mprotect
- exit_groupOperator lalu menulis file profil ke setiap node dan memaparkannya pada path standar /var/lib/kubelet/seccomp/operator/<namespace>/<name>.json. Pod kalian tinggal merujuk: localhostProfile: operator/security/webapp-allowlist.json. Saat node baru bergabung, operator otomatis menaruh profilnya — tidak ada yang terlewat.
Important
Sebelum mengadopsi Localhost, pastikan kalian punya jawaban untuk satu pertanyaan: apa yang terjadi saat node baru bergabung? Jika jawabannya "untung-untungan", gunakan RuntimeDefault dulu atau segera pasang operator. Pod yang menunjuk profil yang tidak ada akan gagal dijadwalkan — dan kegagalan itu menyakitkan saat sedang oncall malam.
Profil yang dideklarasikan bukan berarti profil itu ada. Verifikasi di node tempat pod berjalan:
ls -la /var/lib/kubelet/seccomp/
crictl info | grep seccompcrictl adalah CLI untuk containerd — crictl info | grep seccomp memastikan runtime node mengaktifkan dukungannya. Kombinasikan dengan inspeksi pod yang sedang berjalan via kubectl describe:
kubectl describe pod webapp | grep -i seccompTiga lapis verifikasi ini — file ada, runtime mendukung, pod mengacu — menutup lingkaran dari deklarasi sampai eksekusi.
Di episode 10 ini kalian telah memahami cara menerapkan seccomp di Kubernetes: field seccompProfile dengan tiga tipe (Unconfined, RuntimeDefault, Localhost) yang menggantikan annotation alpha, kaitan dengan Pod Security Standards (Baseline dan Restricted), serta tantangan distribusi profil antar node yang dijawab dengan seccomp-profiles-operator. Kalian juga tahu cara memverifikasi profil di node lewat crictl dan kubectl describe.
Kunci yang harus dibawa pulang:
RuntimeDefault; naik ke Localhost saat beban kerja sudah dipahami.Localhost harus ada di semua node — pakai operator atau jawab dulu pertanyaannya.Sejauh ini seccomp datang dari luar: container, service unit, pod. Tetapi ada satu pendekatan yang lebih dekat ke garis pertahanan — di dalam aplikasi itu sendiri. Di episode 11, kita masuk ke Seccomp untuk Aplikasi & Daemon: memuat filter lewat libseccomp, python-seccomp, dan Go, membatasi keluarga socket untuk daemon jaringan, dan memblokir syscall berbahaya seperti unshare, mount, dan ptrace.