[{"data":1,"prerenderedAt":223},["ShallowReactive",2],{"tag-labels":3,"site-header":4,"article-health-check-readiness-liveness-probe-kubernetes-id":72},{},{"featuredPost":5,"navigations":29},{"id":6,"title":7,"title_en":8,"slug":9,"excerpt":10,"excerpt_en":11,"has_translation":12,"published_at":13,"reading_time":14,"hidden_from_listing":15,"tags":16,"thumbnail_image":21,"og_image":22,"series":23,"authors":28},110,"Ketika Pilih Framework Cuma Biar Kelihatan Beda","When You Pick a Framework Just to Look Different","ketika-pilih-framework-cuma-biar-kelihatan-beda","Terakhir kali kamu milih framework atau library baru, itu karena masalahmu butuh alat itu, atau karena alatnya kedengaran keren dan belum banyak yang pakai? Pertanyaan ini nggak enak dijawab. Soalnya keputusan teknologi sering diambil dengan alasan yang nggak pernah ditulis di dokumen teknis mana pun.","The last time you chose a new framework or library, was it because your problem needed that tool, or because it sounded cool and few people around you were using it? That question is uncomfortable. Technology decisions are often made for reasons that never appear in any technical document.",true,"2026-10-06T15:25:21.000Z",5,false,[17,18,19,20],"karier","framework","opini","pengalaman",null,"\u002Fog\u002Fketika-pilih-framework-cuma-biar-kelihatan-beda.png",{"id":24,"title":25,"title_en":26,"slug":27},9,"Artikel","Articles","all",[],[30,46,67],{"collection":31,"item":32},"series",{"__typename":31,"title":25,"title_en":26,"slug":27,"children_series":33},[34,38,42],{"title":35,"title_en":36,"slug":37},"Kecerdasan Artifisial","Artificial Intelligence","kecerdasan-artifisial",{"title":39,"title_en":40,"slug":41},"Konsep Dasar Pemrograman","Programming Fundamentals","konsep-dasar-pemrograman",{"title":43,"title_en":44,"slug":45},"Algoritma dan Struktur Data","Algorithms and Data Structures","algoritma-struktur-data",{"collection":31,"item":47},{"__typename":31,"title":48,"title_en":48,"slug":49,"children_series":50},"Tutorial","tutorial",[51,55,59,63],{"title":52,"title_en":53,"slug":54},"Belajar Python","Learning Python","belajar-python",{"title":56,"title_en":57,"slug":58},"Belajar Golang","Learning Go","belajar-golang",{"title":60,"title_en":61,"slug":62},"Belajar Java","Learning Java","belajar-java",{"title":64,"title_en":65,"slug":66},"Belajar Pascal","Learning Pascal","belajar-pascal",{"collection":31,"item":68},{"__typename":31,"title":69,"title_en":69,"slug":70,"children_series":71},"Lab","lab",[],{"article":73,"renderedBody":102,"renderedTakeaway":103,"latestArticles":104,"toc":207},{"id":74,"title":75,"title_en":76,"slug":77,"excerpt":78,"excerpt_en":79,"has_translation":12,"published_at":80,"reading_time":14,"hidden_from_listing":15,"tags":81,"thumbnail_image":21,"og_image":89,"series":21,"authors":90,"body_locale":97,"available_locales":98,"body":100,"takeway":101,"prerequisite":21},42,"Health Check vs Readiness vs Liveness Probe di Kubernetes: Jangan Sampai Traffic Masuk ke Pod Mati!","Health Check vs Readiness vs Liveness Probe in Kubernetes: Don't Let Traffic Land on a Dead Pod","health-check-readiness-liveness-probe-kubernetes","Semua pod kalian hijau Running, tapi pengguna malah disambut 502 Bad Gateway? Atau seluruh pod restart barengan gara-gara database lagi lambat? Salah kaprah soal probe bisa jadi biangnya. Yuk, kita bongkar bareng!","Every pod is green and Running, yet users get a 502 Bad Gateway? Or all your pods restart at once because the database got slow? The wrong probe is usually behind it.","2026-09-02T03:15:08.836Z",[82,83,84,85,86,87,88],"kubernetes","devops","backend","docker","microservices","reliability","system-design","\u002Fog\u002Fhealth-check-readiness-liveness-probe-kubernetes.png",[91],{"authors_id":92},{"id":93,"name":94,"slug":95,"role":96,"profile_picture":21},2,"Inva","inva","Writer","id",[99,97],"en","Pernah nggak kalian ngalamin *deployment* aplikasi di Kubernetes yang kelihatannya sukses? Semua *pod* berstatus `Running` dengan warna hijau cantik. Tapi pengguna langsung disambut *error* `502 Bad Gateway` pas buka aplikasi.\n\nAtau skenario yang lebih horor. *Server database* lagi kelambatan sementara. Eh, tiba-tiba seluruh *pod backend* di-*restart* serentak oleh Kubernetes. Jadilah *cascading failure*. 😅\n\nMasalah klasik ini hampir selalu berakar pada satu hal. Salah kaprah soal *health check* di Kubernetes.\n\nBanyak *developer* pemula nganggep health check cukup satu *endpoint* `\u002Fhealth` sederhana. Padahal [Kubernetes](https:\u002F\u002Fkubernetes.io\u002F) nyediain tiga mekanisme *probe* yang beda. Tugas dan konsekuensinya sangat berlainan. Ada *startup probe*, *liveness probe*, dan *readiness probe*.\n\nMari kita bedah cara kerja masing-masing probe. Sekalian gimana masangnya dengan benar biar aplikasi kita tangguh di *production*.\n\n## Tiga Serangkai Probe di Kubernetes\n\nBiar gampang kebayang, bayangin aja restoran cepat saji. Ada koki, ada dapur, ada manajer. Tiap probe punya peran kayak salah satu dari mereka.\n\nStartup probe bertugas meriksa apakah proses inisialisasi aplikasi udah selesai. Beberapa aplikasi butuh waktu lama buat beneran *booting*. Misalnya yang pakai *framework* berat kayak Java Spring Boot. Atau *backend* yang memuat model *machine learning* dan ngejalanin migrasi *database*. Bisa puluhan detik sampai menit, lho.\n\nSelama startup probe belum berhasil (`Success`), Kubernetes menonaktifkan pemeriksaan *liveness* dan *readiness*. Tujuannya jelas. Biar aplikasi nggak keburu dibunuh liveness probe sebelum sempat selesai menyala.\n\nLiveness probe jawab satu pertanyaan. Apakah proses aplikasi masih hidup dan sehat? Atau udah ngalami *deadlock*, alias *hang* total? Kalau liveness probe gagal (`Failed`) melebihi batas toleransi (`failureThreshold`), *kubelet* langsung membunuh *container* dan me-restart-nya. Ibaratnya gini. Kalau koki pingsan di dapur, manajer restoran bakal ganti dia dengan koki baru.\n\nReadiness probe jawab pertanyaan yang beda lagi. Apakah aplikasi siap nerima *traffic* dari pengguna sekarang? Sebuah pod bisa aja masih hidup normal. Tapi sedang nggak mampu memproses *request*. Contohnya, *cache in-memory* lokal sedang di-*refresh*. Atau koneksi *pool* ke database sedang penuh. Bisa juga aplikasi sedang memproses antrean *batch* yang berat.\n\nKalau readiness probe gagal, Kubernetes **nggak** bakal membunuh pod itu. Kubernetes cuma mencabut pod itu dari daftar *endpoint Service* alias *Load Balancer*. Traffic pengguna nggak bakal dialirin ke pod itu sampai probe-nya kembali sukses.\n\n## Jebakan Terbesar: Meriksa Database di Liveness Probe\n\nIni *anti-pattern* **paling berbahaya** yang sering ketemu di lapangan:\n\n```python\n# CONTOH SALAH BESAR UNTUK LIVENESS PROBE!\n@app.get(\"\u002Fhealthz\")\nasync def health_check(db: Session = Depends(get_db)):\n    # JANGAN PERNAH LAKUKAN INI DI LIVENESS PROBE!\n    await db.execute(text(\"SELECT 1\"))\n    return {\"status\": \"ok\"}\n```\n\nBayangin kalau database PostgreSQL kalian mendadak kelebihan beban. CPU-nya 100%. Query `SELECT 1` ngalami *timeout* lebih dari 2 detik. Apa yang terjadi kalau endpoint di atas dipasang sebagai liveness probe?\n\n1. Liveness probe di Pod 1 timeout. Kubernetes membunuh Pod 1 dan bikin ulang pod baru.\n2. Liveness probe di Pod 2 timeout. Kubernetes membunuh Pod 2.\n3. Begitu seterusnya sampai seluruh pod di-restart bersamaan!\n4. *Pod-pod* baru langsung membanjiri database dengan *connection pool* baru. Namanya *connection spike*. Database pun makin sekarat. 😅\n\nJadi aturan emasnya gini, nih. Liveness probe cuma periksa status internal aplikasi sendiri. Misal *event loop* nggak *blocking*, atau *web server* masih merespons. **Jangan pernah** meriksa dependensi eksternal kayak database, Redis, atau *service* pihak ketiga. Sementara readiness probe justru tempat yang tepat. Di situ kalian bisa memverifikasi kesiapan koneksi database sebelum nerima request bisnis pengguna.\n\n## Sebaiknya Pisahkan Endpoint Health Check\n\nCara paling bersih adalah memisahkan endpoint di aplikasi backend kalian:\n\n```python\nfrom fastapi import FastAPI, status, Response\n\napp = FastAPI()\n\nis_app_ready = False\n\n@app.on_event(\"startup\")\nasync def startup_event():\n    # Inisialisasi koneksi, load model, warming cache...\n    global is_app_ready\n    await init_database_connection()\n    is_app_ready = True\n\n# 1. Liveness: Cuma cek apakah FastAPI masih bernapas\n@app.get(\"\u002Fhealthz\", status_code=status.HTTP_200_OK)\nasync def liveness():\n    return {\"status\": \"alive\"}\n\n# 2. Readiness: Cek apakah dependensi siap menerima traffic\n@app.get(\"\u002Fready\")\nasync def readiness(response: Response):\n    global is_app_ready\n    if not is_app_ready or not await check_db_health():\n        response.status_code = status.HTTP_503_SERVICE_UNAVAILABLE\n        return {\"status\": \"unavailable\"}\n    return {\"status\": \"ready\"}\n```\n\n## Konfigurasi Manifest Kubernetes yang Ideal\n\nBerikut contoh konfigurasi Deployment Kubernetes. Isinya ngegabungin ketiga probe secara harmonis. Saya tambahin `selector` dan *label* sekalian, biar manifest-nya beneran valid, ya.\n\n```yaml\napiVersion: apps\u002Fv1\nkind: Deployment\nmetadata:\n  name: payment-service\nspec:\n  replicas: 3\n  selector:\n    matchLabels:\n      app: payment-service\n  template:\n    metadata:\n      labels:\n        app: payment-service\n    spec:\n      containers:\n      - name: payment-api\n        image: payment-service:v1.2.0\n        ports:\n        - containerPort: 8000\n\n        # 1. Startup Probe: Berikan napas lega saat cold start\n        startupProbe:\n          httpGet:\n            path: \u002Fhealthz\n            port: 8000\n          failureThreshold: 30\n          periodSeconds: 2 # Total waktu tunggu booting: hingga 60 detik\n\n        # 2. Liveness Probe: Bunuh container hanya jika hang total\n        livenessProbe:\n          httpGet:\n            path: \u002Fhealthz\n            port: 8000\n          periodSeconds: 10\n          timeoutSeconds: 2\n          failureThreshold: 3 # Toleransi 3x gagal berturut-turut\n\n        # 3. Readiness Probe: Cabut traffic jika aplikasi overload \u002F DB putus\n        readinessProbe:\n          httpGet:\n            path: \u002Fready\n            port: 8000\n          periodSeconds: 5\n          timeoutSeconds: 2\n          failureThreshold: 2\n          successThreshold: 1 # Langsung alirkan traffic begitu kembali sehat\n```\n\nPerhatiin parameter `periodSeconds` dan `failureThreshold`. Jangan pasang `timeoutSeconds` terlalu agresif, misal 100 ms. Soalnya saat CPU lagi *spike* sesaat, *request probe* bisa tertunda. Akhirnya memicu restart yang nggak perlu, alias *false-positive restart*.\n\n## Jadi, Gimana Biar Pod Nggak Mati Nerima Tamu?\n\nDengan memisahkan peran liveness dan readiness probe secara disiplin, tiga hal ini bakal kalian dapat. Pertama, kita terhindar dari mimpi buruk *cascading restart* saat infrastruktur database bermasalah. Kedua, pengguna nggak bakal dapat error 502\u002F504. Traffic cuma dikirim ke pod yang beneran siap melayani. Ketiga, proses *rolling deployment* dan *auto-scaling* HPA (Horizontal Pod Autoscaler) jalan jauh lebih mulus tanpa *downtime*.\n\nSudahkah probe di klaster Kubernetes kalian dikonfigurasi dengan benar hari ini? Yuk, audit manifest kalian sekarang.\n\nSelamat ber-Kubernetes ria, dan semoga pod kalian nggak pernah restart tanpa alasan! 👋\n","- Tiga tipe probe di Kubernetes punya peran spesifik: startup probe buat inisialisasi awal, liveness probe buat deteksi deadlock atau crash, dan readiness probe buat nentuin kesiapan nerima traffic.\n- Liveness probe yang meriksa dependensi eksternal (database\u002FRedis) itu jebakan maut, soalnya bisa memicu restart massal alias cascading failure.\n- Endpoint `\u002Fhealthz` buat liveness dan `\u002Fready` buat readiness sebaiknya dipisah di aplikasi backend, entah itu FastAPI, Go, atau Node.js.\n- Parameter `initialDelaySeconds`, `periodSeconds`, `timeoutSeconds`, dan `failureThreshold` perlu disetel biar lonjakan CPU sesaat nggak memicu false-positive restart.","\u003Cp>Pernah nggak kalian ngalamin \u003Cem>deployment\u003C\u002Fem> aplikasi di Kubernetes yang kelihatannya sukses? Semua \u003Cem>pod\u003C\u002Fem> berstatus \u003Ccode>Running\u003C\u002Fcode> dengan warna hijau cantik. Tapi pengguna langsung disambut \u003Cem>error\u003C\u002Fem> \u003Ccode>502 Bad Gateway\u003C\u002Fcode> pas buka aplikasi.\u003C\u002Fp>\n\u003Cp>Atau skenario yang lebih horor. \u003Cem>Server database\u003C\u002Fem> lagi kelambatan sementara. Eh, tiba-tiba seluruh \u003Cem>pod backend\u003C\u002Fem> di-\u003Cem>restart\u003C\u002Fem> serentak oleh Kubernetes. Jadilah \u003Cem>cascading failure\u003C\u002Fem>. 😅\u003C\u002Fp>\n\u003Cp>Masalah klasik ini hampir selalu berakar pada satu hal. Salah kaprah soal \u003Cem>health check\u003C\u002Fem> di Kubernetes.\u003C\u002Fp>\n\u003Cp>Banyak \u003Cem>developer\u003C\u002Fem> pemula nganggep health check cukup satu \u003Cem>endpoint\u003C\u002Fem> \u003Ccode>\u002Fhealth\u003C\u002Fcode> sederhana. Padahal \u003Ca href=\"https:\u002F\u002Fkubernetes.io\u002F\">Kubernetes\u003C\u002Fa> nyediain tiga mekanisme \u003Cem>probe\u003C\u002Fem> yang beda. Tugas dan konsekuensinya sangat berlainan. Ada \u003Cem>startup probe\u003C\u002Fem>, \u003Cem>liveness probe\u003C\u002Fem>, dan \u003Cem>readiness probe\u003C\u002Fem>.\u003C\u002Fp>\n\u003Cp>Mari kita bedah cara kerja masing-masing probe. Sekalian gimana masangnya dengan benar biar aplikasi kita tangguh di \u003Cem>production\u003C\u002Fem>.\u003C\u002Fp>\n\u003Ch2 id=\"tiga-serangkai-probe-di-kubernetes\">Tiga Serangkai Probe di Kubernetes\u003C\u002Fh2>\n\u003Cp>Biar gampang kebayang, bayangin aja restoran cepat saji. Ada koki, ada dapur, ada manajer. Tiap probe punya peran kayak salah satu dari mereka.\u003C\u002Fp>\n\u003Cp>Startup probe bertugas meriksa apakah proses inisialisasi aplikasi udah selesai. Beberapa aplikasi butuh waktu lama buat beneran \u003Cem>booting\u003C\u002Fem>. Misalnya yang pakai \u003Cem>framework\u003C\u002Fem> berat kayak Java Spring Boot. Atau \u003Cem>backend\u003C\u002Fem> yang memuat model \u003Cem>machine learning\u003C\u002Fem> dan ngejalanin migrasi \u003Cem>database\u003C\u002Fem>. Bisa puluhan detik sampai menit, lho.\u003C\u002Fp>\n\u003Cp>Selama startup probe belum berhasil (\u003Ccode>Success\u003C\u002Fcode>), Kubernetes menonaktifkan pemeriksaan \u003Cem>liveness\u003C\u002Fem> dan \u003Cem>readiness\u003C\u002Fem>. Tujuannya jelas. Biar aplikasi nggak keburu dibunuh liveness probe sebelum sempat selesai menyala.\u003C\u002Fp>\n\u003Cp>Liveness probe jawab satu pertanyaan. Apakah proses aplikasi masih hidup dan sehat? Atau udah ngalami \u003Cem>deadlock\u003C\u002Fem>, alias \u003Cem>hang\u003C\u002Fem> total? Kalau liveness probe gagal (\u003Ccode>Failed\u003C\u002Fcode>) melebihi batas toleransi (\u003Ccode>failureThreshold\u003C\u002Fcode>), \u003Cem>kubelet\u003C\u002Fem> langsung membunuh \u003Cem>container\u003C\u002Fem> dan me-restart-nya. Ibaratnya gini. Kalau koki pingsan di dapur, manajer restoran bakal ganti dia dengan koki baru.\u003C\u002Fp>\n\u003Cp>Readiness probe jawab pertanyaan yang beda lagi. Apakah aplikasi siap nerima \u003Cem>traffic\u003C\u002Fem> dari pengguna sekarang? Sebuah pod bisa aja masih hidup normal. Tapi sedang nggak mampu memproses \u003Cem>request\u003C\u002Fem>. Contohnya, \u003Cem>cache in-memory\u003C\u002Fem> lokal sedang di-\u003Cem>refresh\u003C\u002Fem>. Atau koneksi \u003Cem>pool\u003C\u002Fem> ke database sedang penuh. Bisa juga aplikasi sedang memproses antrean \u003Cem>batch\u003C\u002Fem> yang berat.\u003C\u002Fp>\n\u003Cp>Kalau readiness probe gagal, Kubernetes \u003Cstrong>nggak\u003C\u002Fstrong> bakal membunuh pod itu. Kubernetes cuma mencabut pod itu dari daftar \u003Cem>endpoint Service\u003C\u002Fem> alias \u003Cem>Load Balancer\u003C\u002Fem>. Traffic pengguna nggak bakal dialirin ke pod itu sampai probe-nya kembali sukses.\u003C\u002Fp>\n\u003Ch2 id=\"jebakan-terbesar-meriksa-database-di-liveness-probe\">Jebakan Terbesar: Meriksa Database di Liveness Probe\u003C\u002Fh2>\n\u003Cp>Ini \u003Cem>anti-pattern\u003C\u002Fem> \u003Cstrong>paling berbahaya\u003C\u002Fstrong> yang sering ketemu di lapangan:\u003C\u002Fp>\n\n\u003Cdiv class=\"code-block-wrapper my-6 not-prose rounded-xl border-2 border-black dark:border-gray-600 shadow-neo overflow-hidden bg-[#24292e] text-[#e1e4e8] transition-all\">\n  \u003Cdiv class=\"code-block-header flex items-center justify-between px-4 py-2.5 bg-[#1f2428] border-b-2 border-black dark:border-gray-600 font-mono text-xs font-bold text-gray-300 select-none\">\n    \u003Cdiv class=\"flex items-center gap-2\">\n      \u003Cspan class=\"w-3 h-3 rounded-full bg-[#ff5f56] border border-black\u002F40 inline-block\">\u003C\u002Fspan>\n      \u003Cspan class=\"w-3 h-3 rounded-full bg-[#ffbd2e] border border-black\u002F40 inline-block\">\u003C\u002Fspan>\n      \u003Cspan class=\"w-3 h-3 rounded-full bg-[#27c93f] border border-black\u002F40 inline-block\">\u003C\u002Fspan>\n      \u003Cspan class=\"ml-2 font-mono font-bold text-xs uppercase tracking-wider text-gray-300\">PYTHON\u003C\u002Fspan>\n    \u003C\u002Fdiv>\n    \u003Cbutton type=\"button\" class=\"copy-code-btn flex items-center gap-1.5 px-3 py-1 text-xs font-bold bg-[#2f363d] text-gray-200 border-2 border-black dark:border-gray-500 rounded-lg shadow-neo-sm hover:translate-x-0.5 hover:translate-y-0.5 hover:shadow-none hover:bg-gray-700 transition-all cursor-pointer\" data-code=\"%23%20CONTOH%20SALAH%20BESAR%20UNTUK%20LIVENESS%20PROBE!%0A%40app.get(%22%2Fhealthz%22)%0Aasync%20def%20health_check(db%3A%20Session%20%3D%20Depends(get_db))%3A%0A%20%20%20%20%23%20JANGAN%20PERNAH%20LAKUKAN%20INI%20DI%20LIVENESS%20PROBE!%0A%20%20%20%20await%20db.execute(text(%22SELECT%201%22))%0A%20%20%20%20return%20%7B%22status%22%3A%20%22ok%22%7D\" title=\"Salin kode\">\n      \u003Csvg class=\"w-3.5 h-3.5 copy-icon-svg\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n        \u003Cpath stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\">\u003C\u002Fpath>\n      \u003C\u002Fsvg>\n      \u003Cspan class=\"copy-text\">Copy\u003C\u002Fspan>\n    \u003C\u002Fbutton>\n  \u003C\u002Fdiv>\n  \u003Cdiv class=\"code-block-content p-4 overflow-x-auto text-sm font-mono leading-relaxed bg-[#24292e]\">\n    \u003Cpre class=\"shiki github-dark\" style=\"background-color:#24292e;color:#e1e4e8\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\"># CONTOH SALAH BESAR UNTUK LIVENESS PROBE!\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">@app.get\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">\"\u002Fhealthz\"\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">async\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> def\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\"> health_check\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(db: Session \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> Depends(get_db)):\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">    # JANGAN PERNAH LAKUKAN INI DI LIVENESS PROBE!\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">    await\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> db.execute(text(\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">\"SELECT 1\"\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">))\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">    return\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> {\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">\"status\"\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">\"ok\"\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n  \u003C\u002Fdiv>\n\u003C\u002Fdiv>\u003Cp>Bayangin kalau database PostgreSQL kalian mendadak kelebihan beban. CPU-nya 100%. Query \u003Ccode>SELECT 1\u003C\u002Fcode> ngalami \u003Cem>timeout\u003C\u002Fem> lebih dari 2 detik. Apa yang terjadi kalau endpoint di atas dipasang sebagai liveness probe?\u003C\u002Fp>\n\u003Col>\n\u003Cli>Liveness probe di Pod 1 timeout. Kubernetes membunuh Pod 1 dan bikin ulang pod baru.\u003C\u002Fli>\n\u003Cli>Liveness probe di Pod 2 timeout. Kubernetes membunuh Pod 2.\u003C\u002Fli>\n\u003Cli>Begitu seterusnya sampai seluruh pod di-restart bersamaan!\u003C\u002Fli>\n\u003Cli>\u003Cem>Pod-pod\u003C\u002Fem> baru langsung membanjiri database dengan \u003Cem>connection pool\u003C\u002Fem> baru. Namanya \u003Cem>connection spike\u003C\u002Fem>. Database pun makin sekarat. 😅\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>Jadi aturan emasnya gini, nih. Liveness probe cuma periksa status internal aplikasi sendiri. Misal \u003Cem>event loop\u003C\u002Fem> nggak \u003Cem>blocking\u003C\u002Fem>, atau \u003Cem>web server\u003C\u002Fem> masih merespons. \u003Cstrong>Jangan pernah\u003C\u002Fstrong> meriksa dependensi eksternal kayak database, Redis, atau \u003Cem>service\u003C\u002Fem> pihak ketiga. Sementara readiness probe justru tempat yang tepat. Di situ kalian bisa memverifikasi kesiapan koneksi database sebelum nerima request bisnis pengguna.\u003C\u002Fp>\n\u003Ch2 id=\"sebaiknya-pisahkan-endpoint-health-check\">Sebaiknya Pisahkan Endpoint Health Check\u003C\u002Fh2>\n\u003Cp>Cara paling bersih adalah memisahkan endpoint di aplikasi backend kalian:\u003C\u002Fp>\n\n\u003Cdiv class=\"code-block-wrapper my-6 not-prose rounded-xl border-2 border-black dark:border-gray-600 shadow-neo overflow-hidden bg-[#24292e] text-[#e1e4e8] transition-all\">\n  \u003Cdiv class=\"code-block-header flex items-center justify-between px-4 py-2.5 bg-[#1f2428] border-b-2 border-black dark:border-gray-600 font-mono text-xs font-bold text-gray-300 select-none\">\n    \u003Cdiv class=\"flex items-center gap-2\">\n      \u003Cspan class=\"w-3 h-3 rounded-full bg-[#ff5f56] border border-black\u002F40 inline-block\">\u003C\u002Fspan>\n      \u003Cspan class=\"w-3 h-3 rounded-full bg-[#ffbd2e] border border-black\u002F40 inline-block\">\u003C\u002Fspan>\n      \u003Cspan class=\"w-3 h-3 rounded-full bg-[#27c93f] border border-black\u002F40 inline-block\">\u003C\u002Fspan>\n      \u003Cspan class=\"ml-2 font-mono font-bold text-xs uppercase tracking-wider text-gray-300\">PYTHON\u003C\u002Fspan>\n    \u003C\u002Fdiv>\n    \u003Cbutton type=\"button\" class=\"copy-code-btn flex items-center gap-1.5 px-3 py-1 text-xs font-bold bg-[#2f363d] text-gray-200 border-2 border-black dark:border-gray-500 rounded-lg shadow-neo-sm hover:translate-x-0.5 hover:translate-y-0.5 hover:shadow-none hover:bg-gray-700 transition-all cursor-pointer\" data-code=\"from%20fastapi%20import%20FastAPI%2C%20status%2C%20Response%0A%0Aapp%20%3D%20FastAPI()%0A%0Ais_app_ready%20%3D%20False%0A%0A%40app.on_event(%22startup%22)%0Aasync%20def%20startup_event()%3A%0A%20%20%20%20%23%20Inisialisasi%20koneksi%2C%20load%20model%2C%20warming%20cache...%0A%20%20%20%20global%20is_app_ready%0A%20%20%20%20await%20init_database_connection()%0A%20%20%20%20is_app_ready%20%3D%20True%0A%0A%23%201.%20Liveness%3A%20Cuma%20cek%20apakah%20FastAPI%20masih%20bernapas%0A%40app.get(%22%2Fhealthz%22%2C%20status_code%3Dstatus.HTTP_200_OK)%0Aasync%20def%20liveness()%3A%0A%20%20%20%20return%20%7B%22status%22%3A%20%22alive%22%7D%0A%0A%23%202.%20Readiness%3A%20Cek%20apakah%20dependensi%20siap%20menerima%20traffic%0A%40app.get(%22%2Fready%22)%0Aasync%20def%20readiness(response%3A%20Response)%3A%0A%20%20%20%20global%20is_app_ready%0A%20%20%20%20if%20not%20is_app_ready%20or%20not%20await%20check_db_health()%3A%0A%20%20%20%20%20%20%20%20response.status_code%20%3D%20status.HTTP_503_SERVICE_UNAVAILABLE%0A%20%20%20%20%20%20%20%20return%20%7B%22status%22%3A%20%22unavailable%22%7D%0A%20%20%20%20return%20%7B%22status%22%3A%20%22ready%22%7D\" title=\"Salin kode\">\n      \u003Csvg class=\"w-3.5 h-3.5 copy-icon-svg\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n        \u003Cpath stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\">\u003C\u002Fpath>\n      \u003C\u002Fsvg>\n      \u003Cspan class=\"copy-text\">Copy\u003C\u002Fspan>\n    \u003C\u002Fbutton>\n  \u003C\u002Fdiv>\n  \u003Cdiv class=\"code-block-content p-4 overflow-x-auto text-sm font-mono leading-relaxed bg-[#24292e]\">\n    \u003Cpre class=\"shiki github-dark\" style=\"background-color:#24292e;color:#e1e4e8\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> fastapi \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> FastAPI, status, Response\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">app \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> FastAPI()\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">is_app_ready \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\"> False\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">@app.on_event\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">\"startup\"\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">async\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> def\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\"> startup_event\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">():\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">    # Inisialisasi koneksi, load model, warming cache...\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">    global\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> is_app_ready\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">    await\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> init_database_connection()\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">    is_app_ready \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\"> True\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\"># 1. Liveness: Cuma cek apakah FastAPI masih bernapas\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">@app.get\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">\"\u002Fhealthz\"\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">, \u003C\u002Fspan>\u003Cspan style=\"color:#FFAB70\">status_code\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">status.\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">HTTP_200_OK\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">async\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> def\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\"> liveness\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">():\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">    return\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> {\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">\"status\"\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">\"alive\"\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">}\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\"># 2. Readiness: Cek apakah dependensi siap menerima traffic\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">@app.get\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">\"\u002Fready\"\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">async\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> def\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\"> readiness\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(response: Response):\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">    global\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> is_app_ready\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">    if\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> not\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> is_app_ready \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">or\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> not\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\"> await\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> check_db_health():\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">        response.status_code \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> status.\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">HTTP_503_SERVICE_UNAVAILABLE\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">        return\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> {\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">\"status\"\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">\"unavailable\"\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">}\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">    return\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> {\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">\"status\"\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">\"ready\"\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n  \u003C\u002Fdiv>\n\u003C\u002Fdiv>\u003Ch2 id=\"konfigurasi-manifest-kubernetes-yang-ideal\">Konfigurasi Manifest Kubernetes yang Ideal\u003C\u002Fh2>\n\u003Cp>Berikut contoh konfigurasi Deployment Kubernetes. Isinya ngegabungin ketiga probe secara harmonis. Saya tambahin \u003Ccode>selector\u003C\u002Fcode> dan \u003Cem>label\u003C\u002Fem> sekalian, biar manifest-nya beneran valid, ya.\u003C\u002Fp>\n\n\u003Cdiv class=\"code-block-wrapper my-6 not-prose rounded-xl border-2 border-black dark:border-gray-600 shadow-neo overflow-hidden bg-[#24292e] text-[#e1e4e8] transition-all\">\n  \u003Cdiv class=\"code-block-header flex items-center justify-between px-4 py-2.5 bg-[#1f2428] border-b-2 border-black dark:border-gray-600 font-mono text-xs font-bold text-gray-300 select-none\">\n    \u003Cdiv class=\"flex items-center gap-2\">\n      \u003Cspan class=\"w-3 h-3 rounded-full bg-[#ff5f56] border border-black\u002F40 inline-block\">\u003C\u002Fspan>\n      \u003Cspan class=\"w-3 h-3 rounded-full bg-[#ffbd2e] border border-black\u002F40 inline-block\">\u003C\u002Fspan>\n      \u003Cspan class=\"w-3 h-3 rounded-full bg-[#27c93f] border border-black\u002F40 inline-block\">\u003C\u002Fspan>\n      \u003Cspan class=\"ml-2 font-mono font-bold text-xs uppercase tracking-wider text-gray-300\">YAML\u003C\u002Fspan>\n    \u003C\u002Fdiv>\n    \u003Cbutton type=\"button\" class=\"copy-code-btn flex items-center gap-1.5 px-3 py-1 text-xs font-bold bg-[#2f363d] text-gray-200 border-2 border-black dark:border-gray-500 rounded-lg shadow-neo-sm hover:translate-x-0.5 hover:translate-y-0.5 hover:shadow-none hover:bg-gray-700 transition-all cursor-pointer\" data-code=\"apiVersion%3A%20apps%2Fv1%0Akind%3A%20Deployment%0Ametadata%3A%0A%20%20name%3A%20payment-service%0Aspec%3A%0A%20%20replicas%3A%203%0A%20%20selector%3A%0A%20%20%20%20matchLabels%3A%0A%20%20%20%20%20%20app%3A%20payment-service%0A%20%20template%3A%0A%20%20%20%20metadata%3A%0A%20%20%20%20%20%20labels%3A%0A%20%20%20%20%20%20%20%20app%3A%20payment-service%0A%20%20%20%20spec%3A%0A%20%20%20%20%20%20containers%3A%0A%20%20%20%20%20%20-%20name%3A%20payment-api%0A%20%20%20%20%20%20%20%20image%3A%20payment-service%3Av1.2.0%0A%20%20%20%20%20%20%20%20ports%3A%0A%20%20%20%20%20%20%20%20-%20containerPort%3A%208000%0A%0A%20%20%20%20%20%20%20%20%23%201.%20Startup%20Probe%3A%20Berikan%20napas%20lega%20saat%20cold%20start%0A%20%20%20%20%20%20%20%20startupProbe%3A%0A%20%20%20%20%20%20%20%20%20%20httpGet%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20path%3A%20%2Fhealthz%0A%20%20%20%20%20%20%20%20%20%20%20%20port%3A%208000%0A%20%20%20%20%20%20%20%20%20%20failureThreshold%3A%2030%0A%20%20%20%20%20%20%20%20%20%20periodSeconds%3A%202%20%23%20Total%20waktu%20tunggu%20booting%3A%20hingga%2060%20detik%0A%0A%20%20%20%20%20%20%20%20%23%202.%20Liveness%20Probe%3A%20Bunuh%20container%20hanya%20jika%20hang%20total%0A%20%20%20%20%20%20%20%20livenessProbe%3A%0A%20%20%20%20%20%20%20%20%20%20httpGet%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20path%3A%20%2Fhealthz%0A%20%20%20%20%20%20%20%20%20%20%20%20port%3A%208000%0A%20%20%20%20%20%20%20%20%20%20periodSeconds%3A%2010%0A%20%20%20%20%20%20%20%20%20%20timeoutSeconds%3A%202%0A%20%20%20%20%20%20%20%20%20%20failureThreshold%3A%203%20%23%20Toleransi%203x%20gagal%20berturut-turut%0A%0A%20%20%20%20%20%20%20%20%23%203.%20Readiness%20Probe%3A%20Cabut%20traffic%20jika%20aplikasi%20overload%20%2F%20DB%20putus%0A%20%20%20%20%20%20%20%20readinessProbe%3A%0A%20%20%20%20%20%20%20%20%20%20httpGet%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20path%3A%20%2Fready%0A%20%20%20%20%20%20%20%20%20%20%20%20port%3A%208000%0A%20%20%20%20%20%20%20%20%20%20periodSeconds%3A%205%0A%20%20%20%20%20%20%20%20%20%20timeoutSeconds%3A%202%0A%20%20%20%20%20%20%20%20%20%20failureThreshold%3A%202%0A%20%20%20%20%20%20%20%20%20%20successThreshold%3A%201%20%23%20Langsung%20alirkan%20traffic%20begitu%20kembali%20sehat\" title=\"Salin kode\">\n      \u003Csvg class=\"w-3.5 h-3.5 copy-icon-svg\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n        \u003Cpath stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\">\u003C\u002Fpath>\n      \u003C\u002Fsvg>\n      \u003Cspan class=\"copy-text\">Copy\u003C\u002Fspan>\n    \u003C\u002Fbutton>\n  \u003C\u002Fdiv>\n  \u003Cdiv class=\"code-block-content p-4 overflow-x-auto text-sm font-mono leading-relaxed bg-[#24292e]\">\n    \u003Cpre class=\"shiki github-dark\" style=\"background-color:#24292e;color:#e1e4e8\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">apiVersion\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">apps\u002Fv1\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">kind\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">Deployment\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">metadata\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">:\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">  name\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">payment-service\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">spec\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">:\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">  replicas\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">3\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">  selector\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">:\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">    matchLabels\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">:\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">      app\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">payment-service\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">  template\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">:\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">    metadata\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">:\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">      labels\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">:\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">        app\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">payment-service\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">    spec\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">:\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">      containers\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">:\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">      - \u003C\u002Fspan>\u003Cspan style=\"color:#85E89D\">name\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">payment-api\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">        image\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">payment-service:v1.2.0\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">        ports\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">:\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">        - \u003C\u002Fspan>\u003Cspan style=\"color:#85E89D\">containerPort\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">8000\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">        # 1. Startup Probe: Berikan napas lega saat cold start\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">        startupProbe\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">:\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">          httpGet\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">:\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">            path\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">\u002Fhealthz\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">            port\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">8000\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">          failureThreshold\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">30\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">          periodSeconds\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">2\u003C\u002Fspan>\u003Cspan style=\"color:#6A737D\"> # Total waktu tunggu booting: hingga 60 detik\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">        # 2. Liveness Probe: Bunuh container hanya jika hang total\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">        livenessProbe\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">:\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">          httpGet\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">:\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">            path\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">\u002Fhealthz\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">            port\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">8000\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">          periodSeconds\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">10\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">          timeoutSeconds\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">2\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">          failureThreshold\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">3\u003C\u002Fspan>\u003Cspan style=\"color:#6A737D\"> # Toleransi 3x gagal berturut-turut\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">        # 3. Readiness Probe: Cabut traffic jika aplikasi overload \u002F DB putus\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">        readinessProbe\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">:\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">          httpGet\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">:\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">            path\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">\u002Fready\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">            port\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">8000\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">          periodSeconds\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">5\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">          timeoutSeconds\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">2\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">          failureThreshold\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">2\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">          successThreshold\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">1\u003C\u002Fspan>\u003Cspan style=\"color:#6A737D\"> # Langsung alirkan traffic begitu kembali sehat\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n  \u003C\u002Fdiv>\n\u003C\u002Fdiv>\u003Cp>Perhatiin parameter \u003Ccode>periodSeconds\u003C\u002Fcode> dan \u003Ccode>failureThreshold\u003C\u002Fcode>. Jangan pasang \u003Ccode>timeoutSeconds\u003C\u002Fcode> terlalu agresif, misal 100 ms. Soalnya saat CPU lagi \u003Cem>spike\u003C\u002Fem> sesaat, \u003Cem>request probe\u003C\u002Fem> bisa tertunda. Akhirnya memicu restart yang nggak perlu, alias \u003Cem>false-positive restart\u003C\u002Fem>.\u003C\u002Fp>\n\u003Ch2 id=\"jadi-gimana-biar-pod-nggak-mati-nerima-tamu\">Jadi, Gimana Biar Pod Nggak Mati Nerima Tamu?\u003C\u002Fh2>\n\u003Cp>Dengan memisahkan peran liveness dan readiness probe secara disiplin, tiga hal ini bakal kalian dapat. Pertama, kita terhindar dari mimpi buruk \u003Cem>cascading restart\u003C\u002Fem> saat infrastruktur database bermasalah. Kedua, pengguna nggak bakal dapat error 502\u002F504. Traffic cuma dikirim ke pod yang beneran siap melayani. Ketiga, proses \u003Cem>rolling deployment\u003C\u002Fem> dan \u003Cem>auto-scaling\u003C\u002Fem> HPA (Horizontal Pod Autoscaler) jalan jauh lebih mulus tanpa \u003Cem>downtime\u003C\u002Fem>.\u003C\u002Fp>\n\u003Cp>Sudahkah probe di klaster Kubernetes kalian dikonfigurasi dengan benar hari ini? Yuk, audit manifest kalian sekarang.\u003C\u002Fp>\n\u003Cp>Selamat ber-Kubernetes ria, dan semoga pod kalian nggak pernah restart tanpa alasan! 👋\u003C\u002Fp>\n","\u003Cul>\n\u003Cli>Tiga tipe probe di Kubernetes punya peran spesifik: startup probe buat inisialisasi awal, liveness probe buat deteksi deadlock atau crash, dan readiness probe buat nentuin kesiapan nerima traffic.\u003C\u002Fli>\n\u003Cli>Liveness probe yang meriksa dependensi eksternal (database\u002FRedis) itu jebakan maut, soalnya bisa memicu restart massal alias cascading failure.\u003C\u002Fli>\n\u003Cli>Endpoint \u003Ccode>\u002Fhealthz\u003C\u002Fcode> buat liveness dan \u003Ccode>\u002Fready\u003C\u002Fcode> buat readiness sebaiknya dipisah di aplikasi backend, entah itu FastAPI, Go, atau Node.js.\u003C\u002Fli>\n\u003Cli>Parameter \u003Ccode>initialDelaySeconds\u003C\u002Fcode>, \u003Ccode>periodSeconds\u003C\u002Fcode>, \u003Ccode>timeoutSeconds\u003C\u002Fcode>, dan \u003Ccode>failureThreshold\u003C\u002Fcode> perlu disetel biar lonjakan CPU sesaat nggak memicu false-positive restart.\u003C\u002Fli>\n\u003C\u002Ful>\n",[105,127,140,153,166,187],{"id":106,"title":107,"title_en":21,"slug":108,"excerpt":109,"excerpt_en":21,"has_translation":15,"published_at":110,"reading_time":111,"hidden_from_listing":15,"tags":112,"thumbnail_image":21,"og_image":115,"series":116,"authors":121},133,"Python Strings: the Badge That Only Worked for One Name","python-strings","The badge script printed the right name for the person who wrote it and the wrong name for everybody else. Slicing counts characters, and a name is words.","2026-10-28T13:00:00.000Z",6,[113,114],"python","string","\u002Fog\u002Fpython-strings.png",{"id":117,"title":118,"title_en":119,"slug":120},30,"Koleksi dan String","Collections and Strings","python-collections",[122],{"authors_id":123},{"id":124,"name":125,"slug":126,"role":96,"profile_picture":21},1,"Daffa Izzuddin","izzudd",{"id":128,"title":129,"title_en":21,"slug":130,"excerpt":131,"excerpt_en":21,"has_translation":15,"published_at":132,"reading_time":111,"hidden_from_listing":15,"tags":133,"thumbnail_image":21,"og_image":135,"series":136,"authors":137},132,"Python Tuples: Why All Three Points Are the Same Point","python-tuples","Three points walk into a loop and come out identical. The list was never copied three times; the name was. A tuple makes that bug impossible.","2026-10-28T12:00:00.000Z",[113,134],"tuple","\u002Fog\u002Fpython-tuples.png",{"id":117,"title":118,"title_en":119,"slug":120},[138],{"authors_id":139},{"id":124,"name":125,"slug":126,"role":96,"profile_picture":21},{"id":141,"title":142,"title_en":21,"slug":143,"excerpt":144,"excerpt_en":21,"has_translation":15,"published_at":145,"reading_time":111,"hidden_from_listing":15,"tags":146,"thumbnail_image":21,"og_image":148,"series":149,"authors":150},131,"Python Sets: the Duplicate That Keeps Coming Back","python-sets","A de-duplication loop that works on clean data leaves four tags where there should be two. The bug is case, and the fix is a `set`.","2026-10-28T11:00:00.000Z",[113,147],"set","\u002Fog\u002Fpython-sets.png",{"id":117,"title":118,"title_en":119,"slug":120},[151],{"authors_id":152},{"id":124,"name":125,"slug":126,"role":96,"profile_picture":21},{"id":154,"title":155,"title_en":21,"slug":156,"excerpt":157,"excerpt_en":21,"has_translation":15,"published_at":158,"reading_time":111,"hidden_from_listing":15,"tags":159,"thumbnail_image":21,"og_image":161,"series":162,"authors":163},130,"Python Dictionaries: the Key That Isn't There","python-dictionary","A word counter dies the first time it meets a word twice. The fix is one line; what takes longer is knowing which of a dict's three lookups to reach for.","2026-10-28T10:00:00.000Z",[113,160],"dictionary","\u002Fog\u002Fpython-dictionary.png",{"id":117,"title":118,"title_en":119,"slug":120},[164],{"authors_id":165},{"id":124,"name":125,"slug":126,"role":96,"profile_picture":21},{"id":167,"title":168,"title_en":169,"slug":170,"excerpt":171,"excerpt_en":172,"has_translation":12,"published_at":173,"reading_time":14,"hidden_from_listing":15,"tags":174,"thumbnail_image":21,"og_image":181,"series":182,"authors":184},129,"Biar RAG nggak kena 504: pisahin jalur query dan ingestion","So Your RAG Stops Hitting 504: Split the Query Path From Ingestion","rag-pisah-jalur-query-dan-ingestion","Satu service RAG yang merangkap parsing dan menjawab kueri bakal tumbang pas ada yang upload PDF 200 halaman. Obatnya dua jalur dan satu queue.","One RAG service that both parses uploads and answers queries will fall over the moment someone uploads a 200-page PDF. The cure is two paths and one queue.","2026-10-22T01:30:00.000Z",[175,176,177,178,179,180],"rag","cloud-run","cloud-tasks","gcp","serverless","arsitektur","\u002Fog\u002Frag-pisah-jalur-query-dan-ingestion.png",{"id":183,"title":35,"title_en":36,"slug":37},8,[185],{"authors_id":186},{"id":124,"name":125,"slug":126,"role":96,"profile_picture":21},{"id":188,"title":189,"title_en":190,"slug":191,"excerpt":192,"excerpt_en":193,"has_translation":12,"published_at":194,"reading_time":111,"hidden_from_listing":15,"tags":195,"thumbnail_image":21,"og_image":202,"series":203,"authors":204},128,"Linear atau graf: cara mengatur banyak agent tanpa loop abadi","Linear or Graph: How to Run Many Agents Without an Eternal Loop","multi-agen-linear-atau-grafik","Satu agent dengan dua puluh tool gampang kacau. Begitu beberapa agent saling revisi, kamu butuh graf yang mendukung cycle dan angka yang membuatnya berhenti.","One agent with twenty tools gets messy fast. Once several agents revise each other, you need a graph that allows cycles and a number that makes it stop.","2026-10-21T16:05:00.000Z",[196,197,198,199,200,201],"multi-agent","langgraph","autogen","orkestrasi","checkpoint","llm","\u002Fog\u002Fmulti-agen-linear-atau-grafik.png",{"id":183,"title":35,"title_en":36,"slug":37},[205],{"authors_id":206},{"id":124,"name":125,"slug":126,"role":96,"profile_picture":21},[208,211,214,217,220],{"text":209,"depth":93,"id":210},"Tiga Serangkai Probe di Kubernetes","tiga-serangkai-probe-di-kubernetes",{"text":212,"depth":93,"id":213},"Jebakan Terbesar: Meriksa Database di Liveness Probe","jebakan-terbesar-meriksa-database-di-liveness-probe",{"text":215,"depth":93,"id":216},"Sebaiknya Pisahkan Endpoint Health Check","sebaiknya-pisahkan-endpoint-health-check",{"text":218,"depth":93,"id":219},"Konfigurasi Manifest Kubernetes yang Ideal","konfigurasi-manifest-kubernetes-yang-ideal",{"text":221,"depth":93,"id":222},"Jadi, Gimana Biar Pod Nggak Mati Nerima Tamu?","jadi-gimana-biar-pod-nggak-mati-nerima-tamu",1793295834150]