بازگشت به وبلاگ

تنظیم پروکسی در کلاسترهای کوبرنتیز: راهنمای کامل برای مهندسان DevOps

راهنمای کامل تنظیم پروکسی در کوبرنتیس: پیکربندی متغیرهای محیطی، تنظیم داکر، containerd، kubectl و حل مشکلات متداول دسترسی شبکه.

📅۲۸ بهمن ۱۴۰۴
```html

هنگام استقرار 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 حل می‌شوند.

```