Deploy aplikasi Server-Side Rendering (SSR) seperti Next.js langsung ke 100% trafik menyimpan risiko runtime failure yang tidak terdeteksi saat tahap build. Kesalahan parsing JSON pada getServerSideProps, kegagalan koneksi upstream database, atau memory leak pada Node.js runtime dapat melumpuhkan layanan seketika. Pola rolling update standar Kubernetes sering kali terlambat mendeteksi kegagalan logis ini selama container berstatus Running.
Solusi deterministik untuk masalah ini adalah Canary Release dengan evaluasi metrik otomatis menggunakan Argo Rollouts dan Prometheus. Artikel ini menguraikan instrumentasi metrik pada Next.js (standalone output), pembuatan AnalysisTemplate untuk memantau HTTP 5xx dan latensi P95, serta konfigurasi rollback otomatis saat metrik performa melampaui batas toleransi.
Arsitektur Canary Deployment Next.js Standalone
Saat menggunakan opsi output: 'standalone' pada next.config.js, Next.js menghasilkan build server minimal tanpa memerlukan seluruh direktori node_modules. Arsitektur canary membagi alur trafik menjadi dua subset pod: stable dan canary.
Argo Rollouts bertindak sebagai pengganti Kubernetes Deployment controller standar. Komponen ingress controller (seperti Ingress-NGINX, Traefik, atau Istio) mengatur persentase trafik jaringan ke Service stable dan Service canary sesuai langkah (steps) yang ditentukan. Selama proses transisi, metrik dari container diekspos ke Prometheus untuk dianalisis oleh Rollout Controller.
Eksposur Metrik SSR ke Prometheus dengan prom-client
Next.js secara default tidak mengekspos endpoint metrik Prometheus. Untuk menangkap status code HTTP dan durasi rendering SSR, buat custom server minimal atau gunakan Node.js wrapper di sekitar file server.js hasil build standalone.
Instal dependensi prom-client:
npm install prom-clientBuat file metrics-server.js untuk membungkus server standalone Next.js dan mengekspos endpoint /metrics pada port terpisah atau path internal:
const http = require('http');
const { parse } = require('url');
const client = require('prom-client');
const nextHandler = require('./server'); // Standalone entrypoint Next.js
const register = new client.Registry();
client.collectDefaultMetrics({ register });
const httpRequestDurationMicroseconds = new client.Histogram({
name: 'http_request_duration_seconds',
help: 'Durasi request HTTP Next.js dalam detik',
labelNames: ['method', 'route', 'status_code'],
buckets: [0.05, 0.1, 0.25, 0.5, 1, 2.5, 5]
});
register.registerMetric(httpRequestDurationMicroseconds);
const server = http.createServer(async (req, res) => {
const parsedUrl = parse(req.url, true);
if (parsedUrl.pathname === '/metrics') {
res.setHeader('Content-Type', register.contentType);
res.end(await register.metrics());
return;
}
const endTimer = httpRequestDurationMicroseconds.startTimer({
method: req.method,
route: parsedUrl.pathname
});
res.on('finish', () => {
endTimer({ status_code: res.statusCode });
});
// Delegasikan request ke internal handler Next.js
nextHandler.render(req, res, parsedUrl);
});
server.listen(3000, () => {
console.log('Next.js standalone runner with Prometheus listening on port 3000');
});
Catatan: Pisahkan metrik asset statis (/_next/static/*) jika trafik tersebut dialihkan ke CDN untuk menghindari bias pembacaan latensi SSR murni.Konfigurasi AnalysisTemplate Argo Rollouts
AnalysisTemplate mendefinisikan query Prometheus dan kriteria lolos/gagal. Konfigurasi ini mengevaluasi dua parameter kritis: HTTP 5xx Error Rate harus di bawah 1% dan Latency P95 tidak boleh melebihi 500 milidetik.
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: nextjs-canary-analysis
namespace: production
spec:
metrics:
- name: error-rate
interval: 30s
successCondition: result[0] < 0.01
failureLimit: 2
provider:
prometheus:
address: http://prometheus-k8s.monitoring.svc.cluster.local:9090
query: |
sum(rate(http_request_duration_seconds_count{app="nextjs-frontend",status_code=~"5.."}[1m]))
/
sum(rate(http_request_duration_seconds_count{app="nextjs-frontend"}[1m]))
- name: p95-latency
interval: 30s
successCondition: result[0] < 0.5
failureLimit: 2
provider:
prometheus:
address: http://prometheus-k8s.monitoring.svc.cluster.local:9090
query: |
histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket{app="nextjs-frontend"}[1m])) by (le))
Parameter failureLimit: 2 memberi toleransi maksimum 2 kali kegagalan query berturut-turut sebelum memicu status Failed dan membatalkan deployment secara otomatis.
Manifest Rollout Next.js dengan Traffic Routing Bertahap
Ganti resource Deployment menjadi Rollout. Konfigurasi berikut menerapkan skema canary bertahap: 10% trafik, jeda analisis selama 5 menit, naik ke 50% trafik selama 5 menit, sebelum akhirnya beralih penuh ke 100%.
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: nextjs-frontend
namespace: production
spec:
replicas: 10
strategy:
canary:
canaryService: nextjs-frontend-canary
stableService: nextjs-frontend-stable
trafficRouting:
nginx:
stableIngress: nextjs-frontend-ingress
analysis:
templates:
- templateName: nextjs-canary-analysis
startingStep: 1
steps:
- setWeight: 10
- pause: { duration: 5m }
- setWeight: 50
- pause: { duration: 5m }
selector:
matchLabels:
app: nextjs-frontend
template:
metadata:
labels:
app: nextjs-frontend
spec:
containers:
- name: nextjs
image: registry.internal/nextjs-frontend:v2.4.0
ports:
- containerPort: 3000
env:
- name: NODE_ENV
value: "production"
resources:
limits:
cpu: "1"
memory: 1Gi
requests:
cpu: 250m
memory: 512Mi
readinessProbe:
httpGet:
path: /api/health
port: 3000
initialDelaySeconds: 5
periodSeconds: 5
Mekanisme Rollback Otomatis
Alur kerja saat terjadi kegagalan sistem adalah sebagai berikut:
- Argo Rollouts mengalihkan 10% trafik ke versi canary baru (
v2.4.0). - Prometheus mulai mengumpulkan metrik dari pod canary via
AnalysisTemplate. - Jika rilis canary menyebabkan unhandled exception pada
getServerSideProps, metrik HTTP 5xx meningkat melampaui batas0.01(1%). AnalysisRunmenandai metrik berstatus Failed.- Argo Rollouts membatalkan siklus rilis (Aborted), mengalihkan kembali 100% routing trafik ke
nextjs-frontend-stable, dan mengecilkan replika canary ke 0 secara otomatis tanpa campur tangan engineer.
Postmortem Skenario: SSR Runtime Failure & Validasi Synthetic
Insiden
Pada rilis v2.3.1, tim frontend menambahkan pemanggilan data downstream API baru di dalam SSR layout utama. Variabel environment URL endpoint internal tertinggal di level ConfigMap. Saat deployment dijalankan pada arsitektur lama (non-canary), seluruh pod baru lulus fase readiness probe karena endpoint /api/health hanya mengecek status server lokal. Dampaknya: 100% pengguna menerima tampilan Internal Server Error (HTTP 500) selama 8 menit sebelum rollback manual selesai dieksekusi.
Hasil Evaluasi dengan Argo Rollouts
Dengan implementasi Canary Release via Prometheus:
- Kegagalan hanya berdampak pada 10% pengguna selama rentang 60 detik.
- Query Prometheus mendeteksi kenaikan error 5xx hingga 18% pada interval scraping pertama.
- Rollback otomatis selesai dalam 90 detik setelah verifikasi kegagalan kedua.
Langkah Preventif: Validasi Synthetic Traffic
Kelemahan canary murni pada trafik rendah adalah lambatnya pengumpulan data sampel metrik. Untuk rute halaman kritikal yang jarang diakses namun berdampak tinggi, pasang step synthetic run sebelum trafik dialihkan ke pengguna publik.
Gunakan prePromotionAnalysis pada manifest Rollout dengan job synthetic tester (misalnya k6 atau curl-runner) yang memvalidasi rendering SSR pada Service canary:
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: nextjs-smoke-test
namespace: production
spec:
metrics:
- name: smoke-test-job
provider:
job:
spec:
template:
spec:
containers:
- name: test
image: curlimages/curl:8.5.0
command: ["sh", "-c"]
args:
- |
STATUS=$(curl -s -o /dev/null -w "%{http_code}" http://nextjs-frontend-canary.production.svc.cluster.local:3000/dashboard)
if [ "$STATUS" -ne 200 ]; then exit 1; fi
restartPolicy: Never
backoffLimit: 0
Kombinasi antara synthetic smoke testing pada tahap prePromotionAnalysis dan evaluasi metrik runtime pasif via Prometheus memastikan rilis Next.js tidak lagi menjadi sumber insiden produksi fatal.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!