Jika cluster K8s Anda melakukan permintaan eksternal — ke API mitra, ke marketplace, ke platform iklan — cepat atau lambat Anda akan menghadapi pemblokiran berdasarkan IP. Ingress Controller sendiri mengelola lalu lintas masuk, tetapi untuk permintaan keluar melalui pod diperlukan skema terpisah dengan proxy. Dalam artikel ini, kita akan membahas cara mengatur ini dengan benar: dari pemilihan jenis proxy hingga konfigurasi YAML spesifik untuk NGINX Ingress dan Traefik.
Mengapa proxy di Kubernetes: skenario nyata
Kubernetes adalah pengatur, dan sebagian besar artikel tentangnya berbicara tentang lalu lintas masuk: bagaimana mengatur Ingress, bagaimana mengeluarkan sertifikat TLS, bagaimana mengarahkan permintaan ke layanan. Tetapi ada sisi lain: lalu lintas keluar dari pod. Di sinilah masalah dengan pemblokiran, pembatasan geografis, dan batasan IP muncul.
Mari kita lihat tugas spesifik di mana proxy di cluster K8s menjadi suatu keharusan:
- Pemrosesan dan pemantauan harga. Cluster Anda menjalankan CronJob setiap 15 menit dan mengumpulkan data dari Wildberries, Ozon, Amazon. Tanpa rotasi IP, dalam 2–3 jam Anda akan mendapatkan larangan di seluruh rentang IP penyedia cloud Anda.
- Bekerja dengan API iklan. Facebook Marketing API, TikTok Ads API, Google Ads API — semuanya melacak sumber permintaan. Jika puluhan pod mengirim permintaan dari satu IP pusat data, itu adalah pemicu untuk pemblokiran otomatis.
- Pemrograman geolokasi. Layanan Anda harus menunjukkan konten yang berbeda untuk pengguna dari negara yang berbeda. Melalui proxy, pod dapat meniru permintaan dari wilayah yang diperlukan untuk pengujian otomatis.
- Menghindari pembatasan korporat. Dalam beberapa infrastruktur, semua lalu lintas keluar harus melalui proxy korporat — ini adalah persyaratan kepatuhan.
- Bekerja dengan API mitra dengan daftar putih IP. Ketika mitra hanya mengizinkan permintaan dari IP tertentu, dan cluster Anda diskalakan dan mengubah alamat — proxy dengan IP statis menyelesaikan masalah.
Penting untuk memahami pemisahan arsitektur: Ingress Controller mengelola lalu lintas masuk (dari pengguna ke layanan Anda), sedangkan proxy untuk permintaan keluar adalah tugas terpisah. Namun, mereka saling terkait: konfigurasi proxy sering ditentukan pada tingkat Ingress Controller yang sama atau melalui anotasi yang dibaca olehnya.
💡 Pemisahan kunci
Dalam artikel ini, kita membahas dua skenario: (1) pengaturan Ingress Controller sebagai proxy terbalik untuk server upstream eksternal, dan (2) pengalihan lalu lintas keluar dari pod melalui server proxy eksternal. Kedua skenario ini sering ditemukan dalam produksi.
Jenis proxy apa yang harus dipilih untuk cluster K8s
Pemilihan jenis proxy secara langsung mempengaruhi seberapa lama cluster Anda dapat beroperasi tanpa pemblokiran. IP pusat data adalah yang termurah, tetapi mudah dikenali dan diblokir. IP residensial dan seluler lebih mahal, tetapi jauh lebih andal untuk tugas di mana simulasi pengguna nyata penting.
| Jenis proxy | Kecepatan | Risiko pemblokiran | Skenario terbaik di K8s |
|---|---|---|---|
| Pusat data | Tinggi | Tinggi | API internal, kepatuhan korporat, integrasi mitra dengan daftar putih IP |
| Residen | Sedang | Rendah | Pemrosesan marketplace, bekerja dengan API iklan, pengujian geolokasi |
| Seluler | Sedang | Minimal | Facebook Ads API, TikTok API, tugas dengan beban tinggi dan risiko pemblokiran |
Untuk sebagian besar tugas di cluster K8s yang terkait dengan pemrosesan atau bekerja dengan platform iklan, pilihan optimal adalah proxy residensial dengan rotasi. Mereka menyediakan IP nyata dari pengguna rumah, dan algoritma perlindungan situs menganggap permintaan semacam itu sebagai lalu lintas browser biasa.
Dari perspektif protokol, untuk K8s, HTTP/HTTPS proxy adalah yang paling universal — didukung oleh semua klien HTTP populer dalam bahasa pemrograman apa pun melalui variabel lingkungan standar HTTP_PROXY dan HTTPS_PROXY. SOCKS5 hanya diperlukan untuk protokol non-standar atau ketika diperlukan untuk memproxy tidak hanya HTTP.
Pengaturan proxy melalui NGINX Ingress Controller
NGINX Ingress Controller adalah pilihan paling umum di K8s. Mari kita lihat dua skenario: mengatur NGINX sebagai proxy terbalik ke upstream eksternal melalui server proxy, dan pengaturan global proxy keluar untuk controller itu sendiri.
Anotasi untuk memproxy permintaan ke upstream
NGINX Ingress mendukung anotasi untuk mengelola perilaku proxy. Jika Anda perlu agar Ingress meneruskan permintaan ke layanan eksternal melalui proxy perantara, gunakan ConfigMap dengan konfigurasi kustom:
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-ingress-controller
namespace: ingress-nginx
data:
# Proxy HTTP global untuk permintaan keluar NGINX
http-snippet: |
proxy_connect_timeout 10s;
proxy_read_timeout 30s;
proxy_send_timeout 30s;
# Pengaturan upstream melalui proxy
use-proxy-protocol: "false"
proxy-real-ip-cidr: "0.0.0.0/0"
Sumber Ingress dengan anotasi untuk proxy
Untuk sumber Ingress terpisah, Anda dapat menetapkan parameter proxy melalui anotasi. Ini berguna ketika layanan yang berbeda memerlukan waktu tunggu dan pengaturan yang berbeda:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-service-ingress
namespace: production
annotations:
kubernetes.io/ingress.class: "nginx"
# Waktu tunggu proxy
nginx.ingress.kubernetes.io/proxy-connect-timeout: "10"
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
# Ukuran buffer
nginx.ingress.kubernetes.io/proxy-buffer-size: "16k"
nginx.ingress.kubernetes.io/proxy-buffers-number: "8"
# Meneruskan IP nyata klien
nginx.ingress.kubernetes.io/use-forwarded-headers: "true"
nginx.ingress.kubernetes.io/forwarded-for-header: "X-Forwarded-For"
spec:
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-service
port:
number: 80
Pengaturan proxy eksternal untuk permintaan keluar pod NGINX
Jika NGINX Ingress Controller itu sendiri harus melakukan permintaan keluar melalui proxy eksternal (misalnya, untuk health-check endpoint eksternal), Anda perlu menetapkan variabel lingkungan dalam Deployment controller:
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
template:
spec:
containers:
- name: controller
image: registry.k8s.io/ingress-nginx/controller:v1.9.4
env:
- name: HTTP_PROXY
valueFrom:
secretKeyRef:
name: proxy-credentials
key: http-proxy-url
- name: HTTPS_PROXY
valueFrom:
secretKeyRef:
name: proxy-credentials
key: https-proxy-url
- name: NO_PROXY
value: "localhost,127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,.cluster.local"
Perhatikan variabel NO_PROXY — ini sangat penting. Tanpa itu, semua lalu lintas intra-cluster juga akan melewati proxy eksternal, yang akan merusak interaksi antara layanan. Dalam NO_PROXY selalu sertakan rentang RFC-1918 dan sufiks .cluster.local.
Pengaturan proxy di Traefik Ingress Controller
Traefik adalah alternatif populer untuk NGINX Ingress, terutama dalam kombinasi dengan Helm dan di cluster yang dikelola (k3s, Docker Swarm, Nomad). Traefik memiliki sistem konfigurasinya sendiri melalui CRD (Custom Resource Definitions) dan konfigurasi statis/dinamis.
Konfigurasi statis Traefik dengan proxy
apiVersion: v1
kind: ConfigMap
metadata:
name: traefik-config
namespace: traefik
data:
traefik.yaml: |
# Konfigurasi statis Traefik
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
# Pengaturan untuk bekerja di belakang proxy
serversTransport:
insecureSkipVerify: false
maxIdleConnsPerHost: 200
dialTimeout: 10s
responseHeaderTimeout: 30s
# Logging untuk diagnostik proxy
log:
level: INFO
accessLog:
fields:
headers:
defaultMode: keep
names:
X-Forwarded-For: keep
X-Real-IP: keep
Middleware untuk menambahkan header proxy
Di Traefik, Anda dapat membuat Middleware yang akan menambahkan atau memodifikasi header saat meneruskan permintaan. Ini berguna untuk meneruskan IP nyata klien dengan benar melalui rantai proxy:
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: proxy-headers
namespace: production
spec:
headers:
customRequestHeaders:
X-Forwarded-Proto: "https"
# Menghapus header yang dapat mengungkapkan infrastruktur
customResponseHeaders:
X-Powered-By: ""
Server: ""
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: my-app-route
namespace: production
spec:
entryPoints:
- websecure
routes:
- match: Host(`myapp.example.com`)
kind: Rule
middlewares:
- name: proxy-headers
services:
- name: my-service
port: 80
Variabel lingkungan untuk Deployment Traefik
Sama seperti NGINX, untuk Traefik kita menetapkan variabel lingkungan melalui nilai Helm atau langsung di Deployment. Saat menggunakan chart Helm, ini dilakukan melalui values.yaml:
# values.yaml untuk chart Helm Traefik
deployment:
enabled: true
kind: Deployment
env:
- name: HTTP_PROXY
valueFrom:
secretKeyRef:
name: proxy-credentials
key: http-proxy-url
- name: HTTPS_PROXY
valueFrom:
secretKeyRef:
name: proxy-credentials
key: https-proxy-url
- name: NO_PROXY
value: "localhost,127.0.0.1,10.96.0.0/12,10.244.0.0/16,.cluster.local,.svc"
Proxy melalui variabel lingkungan di pod
Cara paling universal untuk mengatur proxy keluar untuk pod mana pun adalah melalui variabel lingkungan standar. Metode ini bekerja terlepas dari bahasa pemrograman dan kerangka kerja: Python requests, Go net/http, Node.js axios, Java HttpClient — semuanya membaca HTTP_PROXY dan HTTPS_PROXY secara otomatis.
Opsi 1: Langsung di Pod Spec
apiVersion: v1
kind: Pod
metadata:
name: scraper-pod
namespace: production
spec:
containers:
- name: scraper
image: mycompany/scraper:latest
env:
- name: HTTP_PROXY
value: "http://username:[email protected]:8080"
- name: HTTPS_PROXY
value: "http://username:[email protected]:8080"
- name: NO_PROXY
value: "localhost,127.0.0.1,10.0.0.0/8,.cluster.local"
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "500m"
⚠️ Jangan simpan kredensial dalam bentuk terbuka!
Contoh di atas ditunjukkan untuk kejelasan. Dalam produksi, kredensial proxy selalu harus disimpan dalam Kubernetes Secret dan diteruskan melalui secretKeyRef. Lebih lanjut — di bagian tentang Secrets di bawah.
Opsi 2: Melalui ConfigMap untuk beberapa pod
Jika proxy digunakan oleh beberapa Deployment, nyaman untuk memindahkan pengaturan ke ConfigMap dan menghubungkannya melalui envFrom:
apiVersion: v1
kind: ConfigMap
metadata:
name: proxy-config
namespace: production
data:
NO_PROXY: "localhost,127.0.0.1,10.0.0.0/8,172.16.0.0/12,.cluster.local,.svc.cluster.local"
PROXY_TIMEOUT: "30"
PROXY_MAX_RETRIES: "3"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: price-monitor
namespace: production
spec:
replicas: 5
selector:
matchLabels:
app: price-monitor
template:
metadata:
labels:
app: price-monitor
spec:
containers:
- name: monitor
image: mycompany/price-monitor:v2.1
envFrom:
- configMapRef:
name: proxy-config
- secretRef:
name: proxy-credentials
ports:
- containerPort: 8080
Opsi 3: Mutating WebhookAdmissionController
Untuk cluster korporat, di mana semua pod wajib menggunakan proxy, Anda dapat mengatur mutating admission webhook yang secara otomatis menambahkan variabel lingkungan proxy ke semua pod yang dibuat. Solusi ini digunakan dalam infrastruktur enterprise, di mana kepatuhan mengharuskan semua lalu lintas keluar melewati proxy korporat. Implementasi webhook semacam itu berada di luar cakupan artikel ini, tetapi penting untuk mengetahui keberadaannya.
Rotasi IP dan pengelolaan pool proxy di K8s
Proxy statis baik untuk kepatuhan korporat, tetapi buruk untuk tugas di mana perlu menghindari pemblokiran. Jika 50 pod Anda mengirim permintaan melalui satu IP yang sama, IP tersebut akan diblokir dengan sangat cepat. Solusinya adalah rotasi proxy.
Skema dengan Proxy Sidecar
Salah satu pola adalah menjalankan agen proxy sebagai kontainer sidecar di samping aplikasi utama. Sidecar menerima permintaan di localhost:8080 dan meneruskannya melalui pool proxy eksternal yang berotasi:
apiVersion: apps/v1
kind: Deployment
metadata:
name: scraper-with-proxy-sidecar
namespace: production
spec:
replicas: 10
selector:
matchLabels:
app: scraper
template:
metadata:
labels:
app: scraper
spec:
containers:
# Aplikasi utama
- name: scraper
image: mycompany/scraper:latest
env:
- name: HTTP_PROXY
value: "http://localhost:8080"
- name: HTTPS_PROXY
value: "http://localhost:8080"
- name: NO_PROXY
value: "localhost,127.0.0.1,.cluster.local"
# Sidecar: agen proxy lokal dengan rotasi
- name: proxy-rotator
image: mycompany/proxy-rotator:latest
ports:
- containerPort: 8080
env:
- name: PROXY_LIST_URL
valueFrom:
secretKeyRef:
name: proxy-credentials
key: api-endpoint
- name: ROTATION_INTERVAL
value: "60" # rotasi setiap 60 detik
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "200m"
Skema dengan Proxy Service pusat
Pendekatan alternatif adalah satu Proxy Service di dalam cluster, yang diakses oleh semua pod. Ini lebih mudah dikelola: cukup memperbarui satu Secret dengan kredensial proxy, dan semua pod secara otomatis mulai menggunakan data baru.
apiVersion: v1
kind: Service
metadata:
name: proxy-gateway
namespace: proxy-system
spec:
selector:
app: proxy-gateway
ports:
- name: http
port: 8080
targetPort: 8080
- name: socks5
port: 1080
targetPort: 1080
type: ClusterIP
---
# Pod menggunakan proxy melalui DNS internal
# HTTP_PROXY=http://proxy-gateway.proxy-system.svc.cluster.local:8080
Untuk tugas di mana anonimitas dan risiko pemblokiran minimal sangat penting (misalnya, pemrosesan marketplace atau bekerja dengan API iklan), kami merekomendasikan menggunakan proxy residensial dengan rotasi — mereka menyediakan IP nyata dari pengguna rumah, yang membuat lalu lintas dari cluster Anda tidak dapat dibedakan dari lalu lintas browser biasa.
Penyimpanan kredensial proxy di Kubernetes Secrets
Penyimpanan kredensial yang aman adalah persyaratan wajib untuk setiap cluster produksi. Jangan pernah menyisipkan login/kata sandi proxy secara langsung ke dalam manifest YAML yang disimpan di repositori Git.
Membuat Secret untuk proxy
# Membuat melalui kubectl (nilai dikodekan dalam base64 secara otomatis)
kubectl create secret generic proxy-credentials \
--namespace=production \
--from-literal=http-proxy-url='http://user:[email protected]:8080' \
--from-literal=https-proxy-url='http://user:[email protected]:8080' \
--from-literal=socks5-proxy-url='socks5://user:[email protected]:1080'
# Memeriksa Secret yang dibuat
kubectl get secret proxy-credentials -n production -o yaml
Manifest YAML Secret
apiVersion: v1
kind: Secret
metadata:
name: proxy-credentials
namespace: production
labels:
app: proxy-config
managed-by: ops-team
type: Opaque
# Nilai dikodekan dalam base64
# echo -n 'http://user:pass@proxy:8080' | base64
stringData:
# stringData memungkinkan untuk menentukan nilai dalam bentuk terbuka
# Kubernetes secara otomatis mengkodekan mereka dalam base64
http-proxy-url: "http://user:[email protected]:8080"
https-proxy-url: "http://user:[email protected]:8080"
proxy-host: "gate.proxycove.com"
proxy-port: "8080"
proxy-username: "user"
proxy-password: "password"
Menggunakan Secret dalam Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-worker
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: api-worker
template:
metadata:
labels:
app: api-worker
spec:
containers:
- name: worker
image: mycompany/api-worker:latest
env:
- name: HTTP_PROXY
valueFrom:
secretKeyRef:
name: proxy-credentials
key: http-proxy-url
- name: HTTPS_PROXY
valueFrom:
secretKeyRef:
name: proxy-credentials
key: https-proxy-url
- name: NO_PROXY
value: "localhost,127.0.0.1,10.0.0.0/8,.cluster.local"
# Untuk aplikasi yang membaca host/port secara terpisah
- name: PROXY_HOST
valueFrom:
secretKeyRef:
name: proxy-credentials
key: proxy-host
- name: PROXY_PORT
valueFrom:
secretKeyRef:
name: proxy-credentials
key: proxy-port
Integrasi dengan penyimpanan rahasia eksternal
Di lingkungan enterprise, disarankan untuk menggunakan External Secrets Operator untuk menyinkronkan rahasia dari HashiCorp Vault, AWS Secrets Manager, atau Azure Key Vault. Ini memungkinkan pembaruan otomatis kredensial proxy tanpa intervensi manual dan restart pod:
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: proxy-credentials-ext
namespace: production
spec:
refreshInterval: 1h
secretStoreRef:
name: vault-backend
kind: ClusterSecretStore
target:
name: proxy-credentials
creationPolicy: Owner
data:
- secretKey: http-proxy-url
remoteRef:
key: secret/proxy/proxycove
property: http_proxy_url
- secretKey: https-proxy-url
remoteRef:
key: secret/proxy/proxycove
property: https_proxy_url
Diagnostik dan kesalahan umum saat mengatur proxy di K8s
Bahkan dengan konfigurasi yang benar, masalah dapat muncul. Mari kita bahas yang paling umum dan cara mendiagnosisnya.
Masalah 1: Lalu lintas intra-cluster melewati proxy
Gejala: pod tidak dapat melihat satu sama lain, resolusi DNS di dalam cluster rusak, layanan tidak merespons. Penyebabnya adalah variabel NO_PROXY tidak diatur.
Nilai minimum yang diperlukan untuk NO_PROXY untuk cluster K8s standar:
NO_PROXY=localhost,127.0.0.1,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,.cluster.local,.svc,.svc.cluster.local,kubernetes.default.svc
Masalah 2: Proxy tidak diterapkan pada pod tertentu
Diagnostik: masuk ke pod dan periksa variabel lingkungan:
# Memeriksa variabel lingkungan di pod
kubectl exec -it <pod-name> -n production -- env | grep -i proxy
# Uji koneksi melalui proxy dari pod
kubectl exec -it <pod-name> -n production -- curl -v --proxy http://proxy:8080 https://httpbin.org/ip
# Memeriksa apakah Secret terpasang dengan benar
kubectl exec -it <pod-name> -n production -- env | grep PROXY
Masalah 3: Kesalahan TLS saat menggunakan proxy HTTPS
Jika proxy menggunakan sertifikat yang ditandatangani sendiri atau CA korporat, aplikasi akan menerima kesalahan verifikasi TLS. Solusinya adalah menambahkan sertifikat CA proxy ke dalam daftar yang tepercaya:
# Membuat ConfigMap dengan sertifikat CA
kubectl create configmap proxy-ca-cert \
--from-file=proxy-ca.crt=./proxy-ca.crt \
-n production
# Memasang di pod
spec:
containers:
- name: app
volumeMounts:
- name: proxy-ca
mountPath: /etc/ssl/certs/proxy-ca.crt
subPath: proxy-ca.crt
volumes:
- name: proxy-ca
configMap:
name: proxy-ca-cert
Masalah 4: Permintaan lambat melalui proxy
Jika permintaan melalui proxy jauh lebih lambat daripada langsung — periksa:
- Resolusi DNS: pastikan permintaan DNS tidak melewati proxy (tambahkan ke
NO_PROXY) - Koneksi keep-alive: atur pool koneksi ke server proxy
- Lokasi geografis: server proxy harus berada dekat secara fisik dengan sumber daya target
- Jenis proxy: untuk tugas berkecepatan tinggi, pertimbangkan proxy pusat data — mereka memberikan latensi minimal
Perintah berguna untuk diagnostik
# Memeriksa log Ingress Controller
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx --tail=100
# Memeriksa peristiwa pod
kubectl describe pod <pod-name> -n production
# Uji koneksi proxy dari pod
kubectl run test-proxy --image=curlimages/curl --rm -it --restart=Never -- \
curl -x http://user:pass@proxy:8080 -v https://httpbin.org/ip
# Memeriksa bahwa Secret ada dan berisi kunci yang diperlukan
kubectl get secret proxy-credentials -n production -o jsonpath='{.data}' | python3 -c "
import sys, json, base64
data = json.load(sys.stdin)
for k, v in data.items():
print(f'{k}: {base64.b64decode(v).decode()[:20]}...')
"
Kesimpulan dan rekomendasi
Mengatur proxy di Kubernetes bukanlah tugas sekali saja, tetapi bagian dari arsitektur keamanan jaringan cluster. Mari kita ringkas:
- Untuk NGINX Ingress Controller — gunakan anotasi untuk mengatur parameter proxy pada tingkat sumber Ingress terpisah, dan variabel lingkungan dalam Deployment untuk pengaturan global lalu lintas keluar.
- Untuk Traefik — kombinasikan konfigurasi statis melalui ConfigMap dengan Middleware untuk mengelola header.
- Untuk pod — variabel standar
HTTP_PROXY/HTTPS_PROXYmelalui Secrets adalah pendekatan paling universal dan aman. - Selalu atur NO_PROXY — jika tidak, lalu lintas intra-cluster akan rusak.
- Jangan pernah menyimpan kredensial proxy dalam bentuk terbuka dalam manifest atau di Git.
- Untuk produksi — gunakan External Secrets Operator untuk rotasi otomatis kredensial.
Jika cluster K8s Anda menjalankan tugas di mana stabilitas IP dan risiko pemblokiran minimal sangat penting — pemrosesan, bekerja dengan API iklan, pengujian geolokasi — kami merekomendasikan menggunakan proxy residensial. Mereka menyediakan IP nyata dari pengguna rumah, yang dianggap algoritma perlindungan sebagai lalu lintas yang sah. Untuk tugas dengan persyaratan tinggi untuk kecepatan dan risiko pemblokiran minimal dari platform seluler, proxy seluler sangat cocok — mereka beroperasi melalui jaringan 4G/5G nyata dari operator.
```