هنگام استقرار Kubernetes در محیطهای شرکتی یا پشت فایروال، اغلب نیاز به تنظیم سرور پروکسی برای دسترسی به منابع خارجی وجود دارد. این امر برای بارگذاری تصاویر کانتینر، بهروزرسانی بستهها و تعامل با APIهای خارجی بسیار مهم است. در این راهنما تمام سطوح تنظیم پروکسی در Kubernetes را بررسی خواهیم کرد — از پیکربندی گرهها تا پادهای جداگانه.
چرا پروکسی در خوشههای Kubernetes لازم است
خوشههای Kubernetes در محیطهای شرکتی اغلب در شبکههای ایزوله با دسترسی محدود به اینترنت کار میکنند. سرور پروکسی چندین وظیفه حیاتی را حل میکند:
- بارگذاری تصاویر کانتینر — Docker Hub، Google Container Registry، و ریپوزیتوریهای خصوصی به دسترسی خارجی نیاز دارند.
- بهروزرسانی بستهها — نصب وابستگیها از طریق apt، yum، pip در داخل کانتینرها.
- دسترسی به APIهای خارجی — ادغام با خدمات ابری، نظارت، و لاگگذاری.
- امنیت — کنترل ترافیک، فیلتر کردن دامنهها، و لاگگذاری درخواستها.
- کش کردن — تسریع درخواستهای تکراری به منابع مشابه.
بدون تنظیم صحیح پروکسی، با خطاهایی مانند "image pull failed"، "connection timeout" یا "network unreachable" هنگام تلاش برای استقرار برنامهها مواجه خواهید شد. این موضوع بهویژه برای CI/CD pipelineهای خودکار که هر ثانیه downtime هزینهبر است، بسیار حیاتی است.
مهم: برای خوشههای شرکتی، استفاده از پروکسیهای دیتاسنتر با پهنای باند بالا و ثبات اتصال توصیه میشود، زیرا عملکرد کل زیرساخت به آنها بستگی دارد.
سطوح تنظیم پروکسی در Kubernetes
Kubernetes دارای معماری چند لایه است و پروکسی باید در هر سطح بسته به وظایف تنظیم شود:
| سطح | چه چیزی تنظیم میشود | برای چه چیزی لازم است |
|---|---|---|
| سیستمعامل | متغیرهای محیطی سیستم | دسترسی به ابزارها (curl، wget، apt) |
| Container Runtime (Docker/containerd) | پیکربندی دیمون | بارگذاری تصاویر کانتینر |
| kubelet | پارامترهای راهاندازی kubelet | تعامل با API سرور |
| پادها (Pods) | متغیرهای محیطی در مانیفستها | دسترسی برنامهها به APIهای خارجی |
| kubectl | متغیرهای محیطی کلاینت | مدیریت خوشه از طریق پروکسی |
هر سطح نیاز به تنظیم جداگانه دارد و از دست دادن هر یک از آنها میتواند منجر به مشکلاتی شود. به عنوان مثال، اگر پروکسی فقط برای Docker تنظیم شود، اما برای پادها نه، تصاویر بارگذاری خواهند شد، اما برنامهها درون کانتینرها نمیتوانند به APIهای خارجی دسترسی پیدا کنند.
تنظیم پروکسی برای Docker و containerd
Container runtime اولین مؤلفهای است که باید تنظیم شود، زیرا مسئول بارگذاری تصاویر کانتینر از ریپوزیتوریهای خارجی است. تنظیمات را برای هر دو runtime محبوب بررسی میکنیم.
تنظیم پروکسی برای Docker
برای Docker باید یک فایل drop-in systemd ایجاد کنید که متغیرهای محیطی را به سرویس Docker اضافه کند:
# دایرکتوری برای پیکربندی ایجاد کنید
sudo mkdir -p /etc/systemd/system/docker.service.d
# فایل تنظیمات پروکسی را ایجاد کنید
sudo tee /etc/systemd/system/docker.service.d/http-proxy.conf <<EOF
[Service]
Environment="HTTP_PROXY=http://proxy.company.com:8080"
Environment="HTTPS_PROXY=http://proxy.company.com:8080"
Environment="NO_PROXY=localhost,127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,.cluster.local,.svc"
EOF
# پیکربندی systemd را دوباره بارگذاری کنید
sudo systemctl daemon-reload
# Docker را دوباره راهاندازی کنید
sudo systemctl restart docker
# بررسی کنید که تنظیمات اعمال شدهاند
sudo systemctl show --property=Environment docker
پس از این، Docker میتواند تصاویر را از طریق سرور پروکسی بارگذاری کند. میتوانید با دستور زیر کارکرد آن را بررسی کنید:
docker pull nginx:latest
تنظیم پروکسی برای containerd
Containerd در خوشههای مدرن Kubernetes به عنوان runtime اصلی کانتینر استفاده میشود. تنظیم پروکسی برای آن کمی متفاوت است:
# دایرکتوری برای پیکربندی ایجاد کنید
sudo mkdir -p /etc/systemd/system/containerd.service.d
# فایل تنظیمات پروکسی را ایجاد کنید
sudo tee /etc/systemd/system/containerd.service.d/http-proxy.conf <<EOF
[Service]
Environment="HTTP_PROXY=http://proxy.company.com:8080"
Environment="HTTPS_PROXY=http://proxy.company.com:8080"
Environment="NO_PROXY=localhost,127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,.cluster.local,.svc"
EOF
# پیکربندی را دوباره بارگذاری کنید
sudo systemctl daemon-reload
sudo systemctl restart containerd
# وضعیت را بررسی کنید
sudo systemctl status containerd
نکته: اگر از یک ریپوزیتوری کانتینر خصوصی استفاده میکنید، دامنه آن را به NO_PROXY اضافه کنید تا از تأخیرهای اضافی و مشکلات با گواهینامههای SSL جلوگیری کنید.
پیکربندی پروکسی برای kubelet
Kubelet، عامل Kubernetes است که در هر گره خوشه کار میکند. او همچنین به دسترسی به API سرور و منابع خارجی نیاز دارد. تنظیمات به روش نصب Kubernetes بستگی دارد.
برای خوشههای kubeadm
اگر از kubeadm استفاده میکنید، پروکسی را از طریق systemd تنظیم کنید:
# دایرکتوری برای پیکربندی kubelet ایجاد کنید
sudo mkdir -p /etc/systemd/system/kubelet.service.d
# فایل تنظیمات پروکسی را ایجاد کنید
sudo tee /etc/systemd/system/kubelet.service.d/http-proxy.conf <<EOF
[Service]
Environment="HTTP_PROXY=http://proxy.company.com:8080"
Environment="HTTPS_PROXY=http://proxy.company.com:8080"
Environment="NO_PROXY=localhost,127.0.0.1,10.96.0.0/12,10.244.0.0/16,.cluster.local,.svc"
EOF
# kubelet را دوباره بارگذاری کنید
sudo systemctl daemon-reload
sudo systemctl restart kubelet
برای Kubernetes مدیریتشده (EKS، GKE، AKS)
در خدمات Kubernetes مدیریتشده، تنظیم kubelet معمولاً از طریق پارامترهای راهاندازی گرهها یا اسکریپتهای user data انجام میشود. به عنوان مثال، برای AWS EKS:
#!/bin/bash
# اسکریپت user data برای گرههای کارگر EKS
# تنظیم پروکسی برای سیستم
cat <<EOF >> /etc/environment
HTTP_PROXY=http://proxy.company.com:8080
HTTPS_PROXY=http://proxy.company.com:8080
NO_PROXY=localhost,127.0.0.1,169.254.169.254,.ec2.internal,.cluster.local
EOF
# تنظیم برای kubelet
mkdir -p /etc/systemd/system/kubelet.service.d
cat <<EOF > /etc/systemd/system/kubelet.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://proxy.company.com:8080"
Environment="HTTPS_PROXY=http://proxy.company.com:8080"
Environment="NO_PROXY=localhost,127.0.0.1,169.254.169.254,.ec2.internal,.cluster.local"
EOF
systemctl daemon-reload
systemctl restart kubelet
به آدرس 169.254.169.254 در NO_PROXY توجه کنید — این آدرس سرویس metadata AWS است که باید بدون پروکسی در دسترس باشد.
تنظیم پروکسی در سطح پادها
حتی اگر پروکسی را برای Docker و kubelet تنظیم کردهاید، برنامهها درون پادها بهطور خودکار از پروکسی استفاده نخواهند کرد. باید بهطور صریح متغیرهای محیطی را در مانیفستهای Kubernetes مشخص کنید.
تنظیم از طریق مانیفست Deployment
سادهترین راه این است که متغیرهای محیطی را به مشخصات کانتینر اضافه کنید:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: my-company/my-app:latest
env:
- name: HTTP_PROXY
value: "http://proxy.company.com:8080"
- name: HTTPS_PROXY
value: "http://proxy.company.com:8080"
- name: NO_PROXY
value: "localhost,127.0.0.1,.cluster.local,.svc,10.0.0.0/8"
ports:
- containerPort: 8080
استفاده از ConfigMap برای تنظیم مرکزی
برای جلوگیری از تکرار تنظیمات پروکسی در هر Deployment، یک ConfigMap ایجاد کنید:
apiVersion: v1
kind: ConfigMap
metadata:
name: proxy-config
namespace: default
data:
HTTP_PROXY: "http://proxy.company.com:8080"
HTTPS_PROXY: "http://proxy.company.com:8080"
NO_PROXY: "localhost,127.0.0.1,.cluster.local,.svc,10.0.0.0/8"
سپس از این ConfigMap در Deployment استفاده کنید:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
template:
spec:
containers:
- name: app
image: my-company/my-app:latest
envFrom:
- configMapRef:
name: proxy-config
این رویکرد مدیریت را سادهتر میکند: هنگام تغییر آدرس پروکسی، کافی است ConfigMap را بهروزرسانی کنید و پس از راهاندازی مجدد پادها، تنظیمات جدید بهطور خودکار اعمال میشوند.
تزریق خودکار از طریق MutatingWebhook
برای افزودن خودکار متغیرهای پروکسی به تمام پادها میتوانید از MutatingAdmissionWebhook استفاده کنید. این یک رویکرد پیشرفته است که نیاز به توسعه سرویس webhook خود دارد، اما به شما امکان میدهد تنظیمات را بهطور مرکزی مدیریت کنید بدون اینکه نیاز به تغییر مانیفستهای برنامهها باشد.
پیکربندی صحیح NO_PROXY
متغیر NO_PROXY تعیین میکند که کدام آدرسها و دامنهها باید از سرور پروکسی عبور کنند. تنظیم نادرست NO_PROXY رایجترین دلیل مشکلات در خوشههای Kubernetes است.
استثنائات الزامی برای Kubernetes
آدرسها و دامنههای زیر باید همیشه در NO_PROXY باشند:
| آدرس/دامنه | هدف |
|---|---|
localhost, 127.0.0.1 |
اتصالات محلی |
.cluster.local |
DNS داخلی خوشه |
.svc |
سرویسهای Kubernetes |
10.0.0.0/8 |
شبکه پاد (بسته به CNI) |
10.96.0.0/12 |
شبکه سرویس (بهطور پیشفرض) |
172.16.0.0/12 |
شبکههای خصوصی Docker |
192.168.0.0/16 |
شبکههای محلی خصوصی |
مثال کامل از پیکربندی NO_PROXY
NO_PROXY=localhost,127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,10.96.0.0/12,.cluster.local,.svc,.default.svc,.default.svc.cluster.local,kubernetes.default.svc,kubernetes.default.svc.cluster.local
توجه: برخی از برنامهها از نوتیشن CIDR در NO_PROXY پشتیبانی نمیکنند. در این موارد از wildcard استفاده کنید: 10.* به جای 10.0.0.0/8.
تنظیم kubectl برای کار از طریق پروکسی
اگر شما خوشه را از یک ایستگاه کاری که پشت پروکسی است مدیریت میکنید، متغیرهای محیطی را برای kubectl تنظیم کنید:
# برای Linux/macOS - به ~/.bashrc یا ~/.zshrc اضافه کنید
export HTTP_PROXY=http://proxy.company.com:8080
export HTTPS_PROXY=http://proxy.company.com:8080
export NO_PROXY=localhost,127.0.0.1,kubernetes.default.svc,.cluster.local
# برای Windows PowerShell
$env:HTTP_PROXY="http://proxy.company.com:8080"
$env:HTTPS_PROXY="http://proxy.company.com:8080"
$env:NO_PROXY="localhost,127.0.0.1,kubernetes.default.svc,.cluster.local"
پس از این، kubectl میتواند به API سرور خوشه از طریق پروکسی متصل شود. کارکرد آن را بررسی کنید:
kubectl cluster-info
kubectl get nodes
تنظیم پروکسی با احراز هویت
اگر سرور پروکسی به احراز هویت نیاز دارد، اطلاعات کاربری را به URL اضافه کنید:
export HTTP_PROXY=http://username:password@proxy.company.com:8080
export HTTPS_PROXY=http://username:password@proxy.company.com:8080
امنیت: رمزهای عبور را بهصورت متن ساده در فایلهای پیکربندی ذخیره نکنید. از متغیرهای محیطی یا رازهای Kubernetes برای ذخیره اطلاعات کاربری پروکسی استفاده کنید.
تشخیص و حل مشکلات رایج
حتی با تنظیم صحیح نیز ممکن است مشکلاتی پیش بیاید. بیایید به رایجترین خطاها و راهحلهای آنها بپردازیم.
خطای "ImagePullBackOff" هنگام بارگذاری تصاویر
علائم: پادها راهاندازی نمیشوند و در رویدادها خطای "Failed to pull image" یا "connection timeout" نمایش داده میشود.
تشخیص:
# رویدادهای پاد را بررسی کنید
kubectl describe pod <pod-name>
# تنظیمات پروکسی را در Docker/containerd بررسی کنید
sudo systemctl show --property=Environment docker
sudo systemctl show --property=Environment containerd
# سعی کنید تصویر را بهصورت دستی روی گره بارگذاری کنید
sudo docker pull nginx:latest
sudo crictl pull nginx:latest
راهحل: اطمینان حاصل کنید که پروکسی برای container runtime تنظیم شده و دامنه ریپوزیتوری تصاویر در NO_PROXY نیست.
مشکلات با حل DNS درون خوشه
علائم: پادها نمیتوانند به یکدیگر از طریق نامهای DNS (به عنوان مثال، service-name.namespace.svc.cluster.local) دسترسی پیدا کنند.
تشخیص:
# DNS را از پاد بررسی کنید
kubectl run -it --rm debug --image=busybox --restart=Never -- nslookup kubernetes.default
# متغیرهای پروکسی را در پاد بررسی کنید
kubectl exec -it <pod-name> -- env | grep PROXY
راهحل: .cluster.local و .svc را به NO_PROXY اضافه کنید.
عملکرد کند یا timeoutها هنگام دسترسی به APIهای خارجی
علائم: برنامهها به آرامی کار میکنند یا هنگام درخواست به خدمات خارجی timeout میگیرند.
تشخیص:
# دسترسی پروکسی را از پاد بررسی کنید
kubectl exec -it <pod-name> -- curl -v -x http://proxy.company.com:8080 https://www.google.com
# زمان پاسخ را اندازهگیری کنید
kubectl exec -it <pod-name> -- time curl -x http://proxy.company.com:8080 https://api.example.com
راهحل: مشکل ممکن است در عملکرد سرور پروکسی باشد. استفاده از پروکسیهای مسکونی با موقعیت جغرافیایی نزدیک برای کاهش تأخیرها را در نظر بگیرید.
خطاهای SSL/TLS هنگام کار از طریق پروکسی
علائم: خطاهایی مانند "certificate verify failed" یا "SSL handshake failed".
دلیل: برخی از سرورهای پروکسی SSL inspection (رمزگشایی ترافیک HTTPS) را انجام میدهند که نیاز به نصب گواهی ریشه پروکسی دارد.
راهحل:
# ConfigMap با گواهی پروکسی ایجاد کنید
kubectl create configmap proxy-ca-cert --from-file=ca.crt=/path/to/proxy-ca.crt
# گواهی را در پاد مونت کنید و به مخزن سیستم اضافه کنید
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
containers:
- name: app
volumeMounts:
- name: proxy-ca
mountPath: /usr/local/share/ca-certificates/proxy-ca.crt
subPath: ca.crt
volumes:
- name: proxy-ca
configMap:
name: proxy-ca-cert
بهترین شیوهها برای پروکسی در تولید
بر اساس تجربه بهرهبرداری از خوشههای Kubernetes در محیطهای شرکتی، در اینجا توصیههایی برای کارکرد مطمئن با پروکسی آورده شده است:
1. از سرورهای پروکسی با دسترسی بالا استفاده کنید
پروکسی به یک نقطه شکست برای کل خوشه تبدیل میشود. چندین سرور پروکسی را پشت load balancer تنظیم کنید:
HTTP_PROXY=http://proxy-lb.company.com:8080
جایی که proxy-lb.company.com — load balancer در مقابل چندین سرور پروکسی است.
2. مدیریت متمرکز پیکربندی
از ConfigMap یا Secret برای ذخیره تنظیمات پروکسی به جای هاردکد کردن در هر مانیفست استفاده کنید:
apiVersion: v1
kind: ConfigMap
metadata:
name: cluster-proxy-config
namespace: kube-system
data:
HTTP_PROXY: "http://proxy-lb.company.com:8080"
HTTPS_PROXY: "http://proxy-lb.company.com:8080"
NO_PROXY: "localhost,127.0.0.1,.cluster.local,.svc,10.0.0.0/8"
3. نظارت و هشداردهی
نظارت بر دسترسی سرورهای پروکسی و هشدار در صورت بروز مشکلات را تنظیم کنید:
- زمان پاسخ پروکسی (باید < 100ms برای پروکسیهای محلی باشد)
- تعداد خطاهای اتصال به پروکسی
- تعداد رویدادهای ImagePullBackOff در خوشه
- بار CPU و شبکه بر روی سرورهای پروکسی
4. مستندسازی استثنائات NO_PROXY
مستنداتی نگهداری کنید که کدام دامنهها و آدرسهای IP به NO_PROXY اضافه شدهاند و چرا. این کار در هنگام عیبیابی و حسابرسی امنیتی کمک میکند.
5. تغییرات را در محیط dev آزمایش کنید
قبل از تغییر تنظیمات پروکسی در تولید، همیشه در خوشه dev/staging آزمایش کنید:
# پاد آزمایشی برای بررسی پروکسی
apiVersion: v1
kind: Pod
metadata:
name: proxy-test
spec:
containers:
- name: test
image: curlimages/curl:latest
command: ["sleep", "3600"]
env:
- name: HTTP_PROXY
value: "http://new-proxy.company.com:8080"
- name: HTTPS_PROXY
value: "http://new-proxy.company.com:8080"
# بررسی دسترسی به منابع خارجی
kubectl exec -it proxy-test -- curl -v https://registry.k8s.io
kubectl exec -it proxy-test -- curl -v https://docker.io
6. از انواع مختلف پروکسی برای وظایف مختلف استفاده کنید
برای مؤلفههای حیاتی (بارگذاری تصاویر، API خوشه) از پروکسیهای سریع دیتاسنتر استفاده کنید، و برای برنامههایی که به تنوع جغرافیایی IP نیاز دارند — از پروکسیهای مسکونی یا موبایل استفاده کنید.
7. بهروزرسانی منظم لیست NO_PROXY
هنگام اضافه کردن خدمات جدید یا تغییر توپولوژی شبکه، NO_PROXY را بهروزرسانی کنید. این کار را از طریق Helm charts یا Kustomize خودکار کنید:
# values.yaml برای Helm chart
proxy:
enabled: true
http: "http://proxy.company.com:8080"
https: "http://proxy.company.com:8080"
noProxy:
- localhost
- 127.0.0.1
- .cluster.local
- .svc
- 10.0.0.0/8
- internal-service.company.com
نتیجهگیری
تنظیم پروکسی در خوشههای Kubernetes یک وظیفه چند لایه است که نیاز به توجه به جزئیات در هر سطح دارد: از سیستمعامل و container runtime تا پادهای جداگانه. پیکربندی صحیح، عملکرد بیوقفه خوشه، دسترسی امن به منابع خارجی و انطباق با سیاستهای امنیتی شرکتی را تضمین میکند.
نکات کلیدی که باید به خاطر بسپارید:
- پروکسی را در تمام سطوح تنظیم کنید: OS، container runtime، kubelet، پادها
- NO_PROXY را بهدرستی پیکربندی کنید و تمام شبکههای داخلی خوشه را شامل کنید
- از مدیریت متمرکز از طریق ConfigMap استفاده کنید
- دسترسپذیری و عملکرد سرورهای پروکسی را نظارت کنید
- تغییرات را قبل از اعمال در تولید آزمایش کنید
برای خوشههای Kubernetes حیاتی، توصیه میشود از پروکسیهای معتبر دیتاسنتر با دسترسی بالا و تأخیر کم استفاده کنید. این کار عملکرد پایدار زیرساخت را تضمین کرده و خطرات downtime ناشی از مشکلات دسترسی شبکه را به حداقل میرساند.
در صورت بروز مشکلات، از رویکرد سیستماتیک برای تشخیص استفاده کنید: تنظیمات را در هر سطح بررسی کنید، لاگها و رویدادها را تجزیه و تحلیل کنید و اتصال را بهصورت دستی آزمایش کنید. بیشتر مشکلات پروکسی در Kubernetes با تنظیم صحیح متغیرهای محیطی و NO_PROXY حل میشوند.