דלגו לתוכן

Networking — DNS, Ingress, TLS, NetworkPolicy

מאיפה פוניםכתובתדוגמה
אותו namespaceשם ה-Serviceredis, postgres:5432
namespace אחר<SERVICE>.<NS>.svc.cluster.localredis.trident-dev.svc.cluster.local
runs on: VM
kubectl -n <NS> exec deploy/<SERVICE> -- python -c "import socket; print(socket.gethostbyname('redis'))"
kubectl -n <NS> exec deploy/<SERVICE> -- python -c "import socket; print(socket.gethostbyname('redis.<NS>.svc.cluster.local'))"

איך מוודאים: שתי הפקודות מדפיסות את אותה כתובת (ClusterIP של ה-Service). gaierror = השם לא קיים או שגוי.

runs on: VM
kubectl -n <NS> get svc <SERVICE> -o jsonpath='{.spec.selector}{"\n"}'
kubectl -n <NS> get endpointslices -l kubernetes.io/service-name=<SERVICE>
kubectl -n <NS> get pods -l trident.dev/service=<SERVICE> --show-labels

איך מוודאים: ב-endpointslices העמודה ENDPOINTS מכילה כתובות Pod. ריקה = ה-selector של ה-Service לא תואם ל-labels של ה-Pods, או שה-Pods לא Ready (probes). השוואה: extraSelectorLabels ב-Deployment מול ב-Service (values).

runs on: VM
kubectl -n <NS> get ingress
kubectl -n <NS> describe ingress <SERVICE>
kubectl get ingressclass
kubectl -n <NS> get secret <SECRET> -o jsonpath='{.type}{"\n"}' # the TLS Secret named in the Ingress

חמש נקודות לבדוק כש-Ingress לא עובד (404, תעודה שגויה, אין תגובה):

  1. ingressClassName: nginx — מתאים ל-get ingressclass.
  2. ה-host בכלל (rule) ובתוך tls.hosts — אותו ערך. (values)
  3. serviceName ו-servicePort של ה-backend קיימים ב-namespace.
  4. ה-Secret מסוג kubernetes.io/tls קיים ב-namespace של ה-Ingress (secrets).
  5. ה-header Host בבקשה תואם ל-host. בלי זה controller מחזיר 404 משלו.

ה-controller חשוף ב-NodePort על ה-VM. את המספר מגלים, לא מנחשים — הוא משתנה בין cluster-ים.

runs on: VM
kubectl -n ingress-nginx get svc
# PORT(S) column looks like 80:30593/TCP,443:31651/TCP -> <PORT> is the number after "443:"
runs on: VM
curl -k --resolve <HOST>:<PORT>:<VM_IP> https://<HOST>:<PORT>/info
# TRIDENT (port differs per cluster): curl -k --resolve dev.trident.test:31651:192.168.242.130 https://dev.trident.test:31651/info
  • --resolve <HOST>:<PORT>:<VM_IP> אומר ל-curl: "ל-host הזה בפורט הזה, השתמש בכתובת הזאת" — בלי לשנות /etc/hosts. ה-URL ו-ה-Host header נשארים <HOST>, אז ה-Ingress מתאים לכלל.
  • -k מדלג על אימות התעודה (תעודה self-signed).
runs on: VM
curl --cacert <FILE> --resolve <HOST>:<PORT>:<VM_IP> https://<HOST>:<PORT>/info
# TRIDENT: curl --cacert ~/.local/share/trident/tls/ca.crt --resolve dev.trident.test:31651:192.168.242.130 https://dev.trident.test:31651/info

עם --cacert מוודאים גם שהתעודה נחתמה על ידי ה-CA הנכון — בדיקה אמיתית יותר מ--k.

איך מוודאים: JSON עם service, version (שווה ל-<CANDIDATE>) ו-environment (שווה ל-<ENV>). Could not resolve host = שכחת --resolve. 404 מ-nginx = ה-Host/הכלל לא תואמים. Connection refused = פורט שגוי.

לדפדפן אין --resolve; מוסיפים שורה לקובץ המארח (במחשב שממנו גולשים):

file: /etc/hosts
<VM_IP> <HOST>

הדפדפן עדיין צריך את ה-NodePort ב-URL: https://<HOST>:<PORT>/.

לקרוא את /info ולהוכיח שה-DB מקבל data

Section titled “לקרוא את /info ולהוכיח שה-DB מקבל data”

Synced/Healthy לא מוכיח שהמערכת עובדת. קרא את /info פעמיים בהפרש של כמה שניות:

שדהמה טוב
versionשווה ל-candidate שעשה promote ל-<ENV>
acceptedעולה בין שתי הקריאות = data זורם
queue_depthקרוב ל-0 (התור מתרוקן)
dropped_queue_fullישר (לא עולה); מספר גדול ויציב הוא היסטוריה, לא תקלה

detections=0 צפוי ב"ים שקט" (ה-contract: quiet sea → אין זיהוי). כדי להוכיח את מסלול ה-DB מפעילים תרחיש quick-transit בסימולטור (פורט ops 9101; ב-image יש python ואין curl):

runs on: VM
kubectl -n <NS> exec deploy/acoustic-simulator -- python -c "import urllib.request as u; u.urlopen(u.Request('http://127.0.0.1:9101/scenarios/quick-transit', method='POST'))"
kubectl -n <NS> exec postgres-0 -- psql -U trident -d trident -c 'select count(*) from detections'

איך מוודאים: אחרי כדקה (התרחיש נמשך 60 שניות) count גדול מ-0. הרץ שוב את השאילתה ומספר עולה = מסלול simulator → ingest-api → redis → signal-processor → postgres עובד. (trident/trident = POSTGRES_USER/POSTGRES_DB ב-values.)

ב-Kubernetes ברירת המחדל שטוחה: כל Pod מדבר עם כל Pod. NetworkPolicy הופכת את זה ל-allowlist: קודם חוסמים הכול, ואז פותחים רק את מסלול הנתונים. מסלול הנתונים ב-TRIDENT: simulator → ingest-api → redis ← signal-processor → postgres.

file: networkpolicies.yaml (ingress rules, one namespace)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: <NS>
spec:
podSelector: {}
policyTypes: [Ingress]
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-redis-from-api-and-processor
namespace: <NS>
spec:
podSelector:
matchLabels: {trident.dev/service: redis}
policyTypes: [Ingress]
ingress:
- from:
- podSelector:
matchLabels: {trident.dev/service: ingest-api}
- podSelector:
matchLabels: {trident.dev/service: signal-processor}
ports:
- {protocol: TCP, port: 6379}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingest-api
namespace: <NS>
spec:
podSelector:
matchLabels: {trident.dev/service: ingest-api}
policyTypes: [Ingress]
ingress:
- from:
- podSelector:
matchLabels: {trident.dev/service: acoustic-simulator}
- namespaceSelector:
matchLabels: {kubernetes.io/metadata.name: ingress-nginx}
ports:
- {protocol: TCP, port: 8080}
  • podSelector: {} בלי ingress: = בוחר את כל ה-Pods וחוסם כל כניסה אליהם.
  • כל allow בוחר את Pod היעד ב-podSelector העליון, ואת המקור ב-from. כלל דומה נדרש גם ל-postgres (מ-signal-processor, פורט 5432).
  • ה-namespaceSelector מאפשר לתעבורה מה-ingress controller להגיע ל-ingest-api. בלעדיו ה-Ingress נחסם.
  • אם Prometheus מגרד את פורטי ops/http מ-namespace אחר — צריך allow גם לו (SHOULD, תלוי ב-contract).
  • ב-values של ה-chart אותה מדיניות נכתבת תחת networkPolicies (values).
runs on: VM
kubectl create --dry-run=client -f networkpolicies.yaml -o name # syntax check, no cluster change
kubectl -n <NS> get networkpolicy
kubectl -n <NS> describe networkpolicy allow-redis-from-api-and-processor

איך מוודאים: dry-run מדפיס networkpolicy.networking.k8s.io/... לכל מדיניות. בדיקה חיה: מ-Pod אסור (למשל simulator → redis) החיבור נכשל ב-timeout, ומ-Pod מותר (ingest-api → redis) הוא מצליח.

runs on: VM
kubectl -n <NS> exec deploy/acoustic-simulator -- python -c "import socket; socket.create_connection(('redis', 6379), 3)" # must fail
kubectl -n <NS> exec deploy/ingest-api -- python -c "import socket; socket.create_connection(('redis', 6379), 3); print('ok')" # must print ok

CNI: האם המדיניות נאכפת בכלל?

Section titled “CNI: האם המדיניות נאכפת בכלל?”
runs on: VM
cat /etc/k8s-manager/cni # TRIDENT lab: prints canal
kubectl -n kube-system get pods | grep -E 'canal|flannel|calico'

איך מוודאים: canal (או calico). אם רק flannel — בדיקת ה"אסור" חייבת להיכשל; אם היא מצליחה, המדיניות לא נאכפת.