שילוב של Agent Engine ‏ (ADK) PSC SWP

1. מבוא

ממשק Private Service Connect הוא משאב שמאפשר לרשת של ענן וירטואלי פרטי (VPC) של יצרן ליזום חיבורים ליעדים שונים ברשת VPC של צרכן. רשתות של יצרנים וצרכנים יכולות להיות בפרויקטים ובארגונים שונים.

אם מחבר רשת מקבל חיבור מממשק Private Service Connect, מערכת Google Cloud מקצה לממשק כתובת IP מרשת משנה של צרכן שצוינה במחבר הרשת. הרשתות של הצרכן והיצרן מחוברות ויכולות לתקשר באמצעות כתובות IP פנימיות.

חיבור בין מחבר רשת לבין ממשק Private Service Connect דומה לחיבור בין נקודת קצה של Private Service Connect לבין קובץ מצורף עם שירות, אבל יש שני הבדלים עיקריים:

  • קובץ מצורף לרשת מאפשר לרשת של יצרן ליזום חיבורים לרשת של צרכן (תעבורת נתונים יוצאת משירות מנוהל), ואילו נקודת קצה מאפשרת לרשת של צרכן ליזום חיבורים לרשת של יצרן (תעבורת נתונים נכנסת לשירות מנוהל).
  • חיבור ממשק Private Service Connect הוא טרנזיטיבי. המשמעות היא שרשת של יצרנים יכולה לתקשר עם רשתות אחרות שמחוברות לרשת של הצרכנים.

שיקולים לגבי נגישות לממשק PSC ב-Vertex AI

  • ממשק PSC יכול לנתב תעבורת נתונים ליעדים ב-VPC או בפריסה מקומית, שנלמדו על ידי רשת ה-VPC.
  • כדי להגביל את היקף הנגישות מהרשת המצורפת שבה נעשה שימוש ב-Agent Engine לרשת ה-VPC, מומלץ להטמיע כללי חומת אש לתעבורת נתונים יוצאת (egress).
  • כדי להגביל את היקף תעבורת הנתונים היוצאת מהרשת שמקורה ברשת המשנה של קובץ ה-Agent Engine המצורף לרשת, צריך לפרוס כלל של חומת אש ליציאה מרשת ה-VPC. הכלל הזה יאפשר במפורש תנועה מ-Agent Engine אל SWP, וידחה את כל התנועה היוצאת האחרת.

שיקולים לגבי VPC-SC לממשק PSC ב-Vertex AI

  • כדי שממשק ה-PSC של Agent Engine יפעל, אתם צריכים לספק קישוריות של תעבורת נתונים יוצאת (egress) באינטרנט ב-VPC של הלקוח, גם אם VPC Service Controls מופעל.

Secure Web Proxy

‫Secure Web Proxy הוא שירות מנוהל שמבוסס-ענן ומאפשר לכם שליטה וביטחון ברמת הפירוט בתעבורת נתונים היוצאת (HTTP/HTTPS). הוא פועל כשער מרכזי ומאפשר לאכוף מדיניות אבטחה על חיבורים שנוצרו מ-Agent Engine שנפרס עם ממשק PSC למשאבי VPC, כמו מכונות וירטואליות, GKE, אינטרנט וסביבות מרובות עננים.

מה הפתרון

  • מניעת זליגת נתונים: חסימת העלאות לא מורשות או תקשורת עם אתרים זדוניים.
  • אכיפת תאימות: מוודא שהתנועה היוצאת עומדת בדרישות של מדיניות האבטחה והטיפול בנתונים של הארגון.
  • מפחית את התקורה התפעולית: כיוון ש-Secure Web Proxy הוא שירות מנוהל באופן מלא, אין צורך לפרוס, לשנות את קנה המידה או לתחזק מכונות וירטואליות של proxy משלכם.
  • מספק שקיפות מלאה: מאפשר בדיקה של תעבורה מוצפנת ב-Transport Layer Security‏ (TLS) כדי לזהות איומים נסתרים.

למידע נוסף, אפשר לעיין במקורות המידע הבאים:

Deploy an agent | Generative AI on Vertex AI | Google Cloud

הגדרת ממשק Private Service Connect למשאבי Vertex AI | Google Cloud

מה תפַתחו

במדריך הזה נסביר איך ליצור Agent Engine מקיף שנפרס עם ממשק Private Service Connect ‏ (PSC) שמשולב עם SWP, כדי לבצע את הפעולות הבאות באמצעות ספריות ADK:

  • פריסת DNS Peering ב-Agent Engine כדי לפתור את שם הדומיין שמוגדר במלואו של SWP שמשמש בהגדרת ה-Proxy.
  • אפשר קישוריות לאתר ציבורי (https://api.frankfurter.app/) דרך Secure Web Proxy שנפרס ב-VPC של הצרכן עם כתובת RFC1918.
  • מאפשרים תנועה מרשת המשנה של קובץ ה-SWP אל קובץ ה-SWP, ודוחים את כל השאר.

איור 1

565e9eb07ef18f44.png

מה תלמדו

  • איך יוצרים קובץ מצורף לרשת
  • איך מפיק יכול להשתמש בצירוף לרשת כדי ליצור ממשק PSC
  • איך יוצרים תקשורת מהיצרן לצרכן באמצעות קישור בין שרתי DNS (DNS Peering)
  • איך פורסים SWP ומשתמשים בו לתעבורת נתונים יוצאת (egress) לאינטרנט
  • איך מגדירים כללים לחומת אש ליציאה כדי לצמצם את הנגישות של Agent Engine לרשת

מה תצטרכו

פרויקט ב-Google Cloud

הרשאות IAM

‫2. לפני שמתחילים

עדכון הפרויקט כדי לתמוך במדריך

במדריך הזה נעשה שימוש ב-$variables כדי להקל על הטמעת ההגדרה של gcloud ב-Cloud Shell.

ב-Cloud Shell, מבצעים את הפעולות הבאות:

gcloud config set project [YOUR-PROJECT-NAME]
projectid=YOUR-PROJECT-NAME
echo $projectid

הפעלת API

ב-Cloud Shell, מבצעים את הפעולות הבאות:

gcloud services enable "compute.googleapis.com"
gcloud services enable "aiplatform.googleapis.com"
gcloud services enable "dns.googleapis.com"
gcloud services enable "notebooks.googleapis.com"
gcloud services enable "storage.googleapis.com"
gcloud services enable "iap.googleapis.com"
gcloud services enable "networksecurity.googleapis.com"
gcloud services enable "networkservices.googleapis.com"
gcloud services enable "cloudresourcemanager.googleapis.com"

אימות שממשקי ה-API הופעלו בהצלחה

gcloud services list --enabled

3. הגדרת צרכנים

יצירת VPC של צרכן

ה-VPC הזה נמצא בפרויקט של לקוח. המשאבים הבאים ייווצרו ב-VPC הזה

  • Consumer Subnet
  • תת-רשת של מחבר רשת
  • רשת משנה של שרת proxy בלבד
  • כללי חומת אש
  • Cloud DNS

ב-Cloud Shell, מבצעים את הפעולות הבאות:

gcloud compute networks create consumer-vpc --project=$projectid --subnet-mode=custom

יצירת רשתות משנה לצרכנים

ב-Cloud Shell, יוצרים את התת-רשת עבור ה-SWP:

gcloud compute networks subnets create swp-subnet --project=$projectid --range=10.10.10.0/28 --network=consumer-vpc --region=us-central1 --enable-private-ip-google-access

יצירת תת-רשת של קובץ מצורף עם הרשת של Private Service Connect

ב-Cloud Shell, יוצרים את תת-הרשת לחיבור הרשת של PSC:

gcloud compute networks subnets create intf-subnet --project=$projectid --range=192.168.10.0/28 --network=consumer-vpc --region=us-central1 --enable-private-ip-google-access

יצירת תת-רשת אזורית של שרת proxy

ב-Cloud Shell, יוצרים את רשת המשנה proxy-only שנדרשת למוצרים מבוססי Envoy כמו Secure Web Proxy ומאזני עומסים אזוריים פנימיים/חיצוניים של אפליקציות. צריך להגדיר את הדגל ‎–purpose לערך REGIONAL_MANAGED_PROXY:

gcloud compute networks subnets create proxy-subnet \
  --purpose=REGIONAL_MANAGED_PROXY \
  --role=ACTIVE \
  --region=us-central1 \
  --network=consumer-vpc \
  --range=100.100.10.0/26

יצירת תת-רשת של נוטבוק

ב-Cloud Shell, יוצרים את תת-הרשת של מכונת ה-Notebook:

gcloud compute networks subnets create notebook-subnet --project=$projectid --range=192.168.20.0/28 --network=consumer-vpc --region=us-central1 --enable-private-ip-google-access

4. יצירת Secure Web Proxy

מצב Explicit (או מצב ניתוב Explicit Proxy) של Secure Web Proxy הוא שיטת פריסה שבה צריך להגדיר באופן מפורש את עומסי העבודה של הלקוח כך שישתמשו בכתובת ה-IP הפנימית של SWP או בשם הדומיין שמוגדר במלואו (FQDN) וביציאה כשרת proxy להעברה.

המדיניות הזו תכלול את הכללים ששולטים בתנועה דרך פרוקסי האינטרנט המאובטח על סמך התאמה לסשן, host() == 'api.frankfurter.app' והתאמה לאפליקציה request.method == 'GET'

בשלבים הבאים, חשוב לשנות את YOUR-PROJECT-ID למזהה הפרויקט שלכם

ב-Cloud Shell, יוצרים קובץ policy.yaml:

cat > policy.yaml << EOF
name: projects/$projectid/locations/us-central1/gatewaySecurityPolicies/my-swp-policy 
description: "My basic SWP policy" 
EOF

ב-Cloud Shell, מייבאים את המדיניות:

gcloud network-security gateway-security-policies import my-swp-policy \
    --source=policy.yaml \
    --location=us-central1

יצירת כללים ל-Secure Web Proxy

מגדירים כללים במדיניות כדי לציין איזו תעבורה מותרת או נדחית. הערכת הכללים מתבצעת לפי סדר העדיפות.

בתוך Cloud Shell, יוצרים קובץ rule.yaml כדי לאפשר גישה לנקודת הקצה באינטרנט שמשמשת את Agent Engine, ‏ api.frankfurter.app:

cat > rule.yaml << EOF
name: "projects/$projectid/locations/us-central1/gatewaySecurityPolicies/my-swp-policy/rules/allow-example"
description: "Allow frankfurter API"
enabled: true
priority: 10
basicProfile: ALLOW
sessionMatcher: "host() == 'api.frankfurter.app'"
EOF

ב-Cloud Shell, יוצרים כלל למדיניות האבטחה:

gcloud network-security gateway-security-policies rules import allow-example \
    --source=rule.yaml \
    --location=us-central1 \
    --gateway-security-policy=my-swp-policy

יצירת כללים ל-Secure Web Proxy

צריך ליצור את מופע ה-SWP, שנפרס במצב ניתוב מפורש, כך שמנוע הסוכן יידרש לציין את כתובת ה-IP או את ה-FQDN של ה-SWP בתצורת ה-proxy של ה-ADK, כפי שמוגדר בקובץ ה-YAML של השער. ההגדרה הזו גם מקשרת את המופע למדיניות, לרשת ולרשת המשנה המתאימות.

בתוך Cloud Shell, יוצרים קובץ gateway.yaml שמשמש לפריסת ה-SWP.

חשוב לשמור את קובץ ה-YAML אחרי שמעדכנים את המשתנים הבאים עם הפרטים של הסביבה: PROJECT_ID,‏ REGION,‏ NETWORK_NAME ו-PROXY_ONLY_SUBNET_NAME. היציאה 8888 שצוינה היא יציאת המנהרה החיצונית שממופה להגדרת ה-proxy ב-Agent Engine.

cat > gateway.yaml << EOF
name: "projects/$projectid/locations/us-central1/gateways/my-swp-instance"
type: SECURE_WEB_GATEWAY
ports: [8888]
addresses: ["10.10.10.5"]
gatewaySecurityPolicy: "projects/$projectid/locations/us-central1/gatewaySecurityPolicies/my-swp-policy"
network: "projects/$projectid/global/networks/consumer-vpc"
subnetwork: "projects/$projectid/regions/us-central1/subnetworks/swp-subnet"
routingMode: EXPLICIT_ROUTING_MODE
EOF

ב-Cloud Shell, מייבאים את השער:

gcloud network-services gateways import my-swp-instance \
    --source=gateway.yaml \
    --location=us-central1

5. מחבר רשת של Private Service Connect

קבצים מצורפים עם הרשת הם משאבים אזוריים שמייצגים את הצד של הצרכן בממשק Private Service Connect. משייכים תת-רשת אחת לקובץ מצורף לרשת, והבעלים של השירות המנוהל מקצה כתובות IP לממשק Private Service Connect מאותה תת-רשת. רשת המשנה צריכה להיות באותו אזור שבו נמצא מחבר הרשת. קובץ מצורף לרשת צריך להיות באותו אזור כמו שירות היצרן.

יצירת מחבר הרשת

ב-Cloud Shell, יוצרים את מחבר הרשת.

gcloud compute network-attachments create psc-network-attachment \
    --region=us-central1 \
    --connection-preference=ACCEPT_AUTOMATIC \
    --subnets=intf-subnet

הצגת הקבצים המצורפים לרשת

ב-Cloud Shell, מציגים את רשימת קבצים מצורפים לרשת.

gcloud compute network-attachments list

תיאור הקבצים המצורפים לרשת

ב-Cloud Shell, מתארים את הרשת המצורפת.

gcloud compute network-attachments describe psc-network-attachment --region=us-central1

חשוב לשים לב לשם קובץ הרשת המצורף של PSC, ‏ psc-network-attachment, שבו ישתמש היצרן כשיצור את ממשק Private Service Connect.

כדי לראות את כתובת ה-URL של רשת PSC ב-Cloud Console, עוברים אל:

Network Services → Private Service Connect → Network Attachment → psc-network-attachment

15f80b46c3a0332d.png

6. תחום DNS פרטי

תצטרכו ליצור תחום (Zone) ב-Cloud DNS בשביל demo.com ולאכלס אותו ברשומת A שמפנה לכתובות ה-IP של ה-SWP. בהמשך, נשיק את DNS peering ב-Agent Engine, שיאפשר גישה לרשומות ה-DNS של הצרכן.

ב-Cloud Shell, מבצעים את הפעולות הבאות כדי ליצור שם DNS demo.com.

gcloud dns --project=$projectid managed-zones create private-dns-codelab --description="" --dns-name="demo.com." --visibility="private" --networks="https://compute.googleapis.com/compute/v1/projects/$projectid/global/networks/consumer-vpc"

מקבלים ושומרים את כתובות ה-IP של ה-SWP שמשמשות לרשומת ה-A של ה-DNS.

ב-Cloud Shell, מריצים פקודת describe על ה-SWP, ‏my-swp-instance:

gcloud network-services gateways describe my-swp-instance --location=us-central1

ב-Cloud Shell, יוצרים את קבוצת הרשומות עבור ה-SWP, ‏ swp.demo.com, ומוודאים שמעדכנים את כתובת ה-IP בהתאם לפלט של הסביבה.

gcloud dns --project=$projectid record-sets create swp.demo.com. --zone="private-dns-codelab" --type="A" --ttl="300" --rrdatas="10.10.10.5"

הגדרת חומת אש

יצירת כלל ב-Cloud Firewall כדי לאפשר גישה מממשק ה-PSC

בקטע הבא, יוצרים כלל חומת אש שמאפשר גישה לתעבורת נתונים שמגיעה מ-PSC Network Attachment לתת-הרשת SWP ב-Consumer VPC. כדי להגביר את האבטחה, אפשר לציין את כתובת ה-IP של SWP כיעד היחיד.

ב-Cloud Shell, יוצרים את כלל חומת האש לתעבורת נתונים יוצאת (egress) שמאפשר גישה מחיבור לרשת אל SWP:

gcloud compute firewall-rules create allow-access-to-swp \
    --network=consumer-vpc \
    --action=ALLOW \
    --rules=ALL \
    --direction=EGRESS \
    --priority=1000 \
    --source-ranges="192.168.10.0/28" \
    --destination-ranges="10.10.10.5/32" \
    --enable-logging

ב-Cloud Shell, יוצרים את כלל חומת האש לתעבורה יוצאת (egress) שחוסם את כל התעבורה מהרשת המצורפת:

gcloud compute firewall-rules create deny-all \
    --network=consumer-vpc \
    --action=DENY \
    --rules=ALL \
    --direction=EGRESS \
    --priority=65534 \
    --source-ranges="192.168.10.0/28" \
    --destination-ranges="0.0.0.0/0" \
    --enable-logging

7. יוצרים מדיניות חומת אש לרשת ה-VPC כדי להבטיח מודיעין איומים:

בקטע הבא, יוצרים מדיניות חומת אש שמאפשרת להשתמש ברשימות מנוהלות של איומים מ-Google כדי לחסום אתרים זדוניים מוכרים לפני שהתנועה מתקבלת על ידי ה-SWP.

ב-Cloud Shell, יוצרים את מדיניות חומת האש הגלובלית:

gcloud compute network-firewall-policies create psc-secure-policy \
    --global \
    --description="Policy to protect VPC with Threat Intelligence"

ב-Cloud Shell, משייכים את המדיניות ל-VPC:

gcloud compute network-firewall-policies associations create \
    --firewall-policy=psc-secure-policy \
    --network=consumer-vpc \
    --name=psc-swp-association \
    --global-firewall-policy

ב-Cloud Shell, מוסיפים את הכללים של Threat Intelligence:

הכללים האלה יפסיקו את התנועה לשחקנים זדוניים מוכרים לפני שהתנועה תופעל מהסוכן. בדוגמה הזו, הוספנו כללים לחסימה של צמתי יציאה של Tor (תעבורת נתונים יוצאת), לחסימה של כתובות IP זדוניות ידועות (תעבורת נתונים יוצאת), לחסימה של שרתי proxy אנונימיים ידועים(תעבורת נתונים יוצאת) ולחסימה של כריית מטבעות קריפטוגרפיים כדי למנוע שימוש לא מורשה במשאבים (תעבורת נתונים יוצאת).

gcloud compute network-firewall-policies rules create 100 \
    --firewall-policy=psc-secure-policy \
    --action=deny \
    --direction=EGRESS \
    --dest-threat-intelligence=iplist-tor-exit-nodes \
    --layer4-configs=all \
    --enable-logging \
    --description="Block anonymous Tor traffic" \
    --global-firewall-policy
gcloud compute network-firewall-policies rules create 110 \
    --firewall-policy=psc-secure-policy \
    --action=deny \
    --direction=EGRESS \
    --dest-threat-intelligence=iplist-known-malicious-ips \
    --layer4-configs=all \
    --enable-logging \
    --description="Block known botnets and malware sources" \
    --global-firewall-policy
gcloud compute network-firewall-policies rules create 120 \
    --firewall-policy=psc-secure-policy \
    --action=deny \
    --direction=EGRESS \
    --dest-threat-intelligence=iplist-anon-proxies \
    --layer4-configs=all \
    --enable-logging \
    --description="Block Known Anonymous Proxies" \
    --global-firewall-policy
gcloud compute network-firewall-policies rules create 130 \
    --firewall-policy=psc-secure-policy \
    --action=deny \
    --direction=EGRESS \
    --dest-threat-intelligence=iplist-crypto-miners \
    --layer4-configs=all \
    --enable-logging \
    --description="Block Crypto Miners (Prevent unauthorized resource usage)" \
    --global-firewall-policy

8. יצירת מחברת Jupyter

בקטע הבא מוסבר איך ליצור Jupyter Notebook. ה-notebook הזה ישמש לפריסת Agent Engine שמטרגט שרת proxy מפורש ליציאה מהאינטרנט.

יצירה של חשבון שירות שמנוהל על ידי משתמש

בקטע הבא תיצרו חשבון שירות שישויך למופע Vertex AI Workbench שבו נעשה שימוש במדריך.

במדריך הזה, התפקידים הבאים יוקצו לחשבון השירות:

ב-Cloud Shell, יוצרים את חשבון השירות.

gcloud iam service-accounts create notebook-sa \
    --display-name="notebook-sa"

ב-Cloud Shell, מעדכנים את חשבון השירות עם התפקיד Storage Admin (אדמין אחסון).

gcloud projects add-iam-policy-binding $projectid --member="serviceAccount:notebook-sa@$projectid.iam.gserviceaccount.com" --role="roles/storage.admin"

ב-Cloud Shell, מעדכנים את חשבון השירות עם התפקיד Vertex AI User.

gcloud projects add-iam-policy-binding $projectid --member="serviceAccount:notebook-sa@$projectid.iam.gserviceaccount.com" --role="roles/aiplatform.user"

ב-Cloud Shell, מעדכנים את חשבון השירות עם התפקיד Artifact Registry Admin.

gcloud projects add-iam-policy-binding $projectid --member="serviceAccount:notebook-sa@$projectid.iam.gserviceaccount.com" --role="roles/artifactregistry.admin"

ב-Cloud Shell, מאפשרים לחשבון השירות של מחברת ה-Notebook להשתמש בחשבון השירות שמוגדר כברירת מחדל של Compute Engine.

gcloud iam service-accounts add-iam-policy-binding \
    $(gcloud projects describe $(gcloud config get-value project) --format='value(projectNumber)')-compute@developer.gserviceaccount.com \
    --member="serviceAccount:notebook-sa@$projectid.iam.gserviceaccount.com" \
    --role="roles/iam.serviceAccountUser"

9. יצירת מכונה של Vertex AI Workbench

בקטע הבא, יוצרים מכונה של Vertex AI Workbench שמשלבת את חשבון השירות שיצרתם קודם, notebook-sa.

ב-Cloud Shell, יוצרים את המכונה private-client.

gcloud workbench instances create workbench-tutorial --vm-image-project=cloud-notebooks-managed --vm-image-family=workbench-instances --machine-type=n1-standard-4 --location=us-central1-a --subnet-region=us-central1 --subnet=notebook-subnet --disable-public-ip --shielded-secure-boot=true --shielded-integrity-monitoring=true --shielded-vtpm=true --service-account-email=notebook-sa@$projectid.iam.gserviceaccount.com     

מוסיפים עוד כלל ב-Secure Web Proxy הקיים כדי להעביר את התנועה ממופע הנוטבוק הזה:

ב-Cloud Shell, יוצרים את הקובץ rule-notebook.yaml באמצעות עורך טקסט. חשוב לעדכן את קובץ ה-YAML עם מזהה הפרויקט.

cat > rule-notebook.yaml << EOF
name: projects/$projectid/locations/us-central1/gatewaySecurityPolicies/my-swp-policy/rules/allow-notebook-subnet
description: Allow Internet access for notebook subnet
enabled: true
priority: 2
basicProfile: ALLOW
sessionMatcher: inIpRange(source.ip,'192.168.20.2')
EOF

ב-Cloud Shell, יוצרים כלל למדיניות האבטחה:

gcloud network-security gateway-security-policies rules import allow-notebook-subnet \
    --source=rule-notebook.yaml \
    --location=us-central1 \
    --gateway-security-policy=my-swp-policy

10. עדכון של סוכן השירות של Vertex AI

‫Vertex AI פועל בשמכם כדי לבצע פעולות כמו קבלת כתובת IP מרשת המשנה של צירוף לרשת PSC שמשמשת ליצירת ממשק PSC. לשם כך, Vertex AI משתמש בסוכן שירות (שמפורט בהמשך) שנדרשת לו הרשאת Network Admin:

service-$projectnumber@gcp-sa-aiplatform.iam.gserviceaccount.com

ב-Cloud Shell, מאתרים את מספר הפרויקט.

gcloud projects describe $projectid | grep projectNumber

ב-Cloud Shell, מגדירים את מספר הפרויקט.

projectnumber=YOUR-PROJECT-NUMBER

ב-Cloud Shell, יוצרים חשבון שירות ל-AI Platform. אפשר לדלג על השלב הזה אם כבר יש לכם חשבון שירות בפרויקט.

gcloud beta services identity create --service=aiplatform.googleapis.com --project=$projectnumber

ב-Cloud Shell, מעדכנים את חשבון סוכן השירות עם התפקיד compute.networkAdmin.

gcloud projects add-iam-policy-binding $projectid --member="serviceAccount:service-$projectnumber@gcp-sa-aiplatform.iam.gserviceaccount.com" --role="roles/compute.networkAdmin"

ב-Cloud Shell, מעדכנים את חשבון סוכן השירות עם התפקיד dns.peer.

gcloud projects add-iam-policy-binding $projectid --member="serviceAccount:service-$projectnumber@gcp-sa-aiplatform.iam.gserviceaccount.com" --role="roles/dns.peer"

עדכון חשבון שירות שמוגדר כברירת מחדל

מעניקים לחשבון השירות שמוגדר כברירת מחדל גישה ל-Vertex AI. הערה: יכול להיות שיעבור זמן עד שהשינוי בהרשאות יתעדכן.

ב-Cloud Shell, מעדכנים את חשבון השירות שמוגדר כברירת מחדל עם התפקיד aiplatform.user.

gcloud projects add-iam-policy-binding $projectid \
  --member="serviceAccount:$projectnumber-compute@developer.gserviceaccount.com" \
    --role="roles/aiplatform.user"

11. פריסה של Agent Engine

הערה: כדי להשלים את המשימות בקטע הזה, נשתמש במסוף GCP ובמחברת JupyterLab.

בקטע הבא תיצרו מחברת שמבצעת את המשימות הבאות:

  • משתמש ב-Frankfurter API ‏ (https://api.frankfurter.app/) כדי לקבל נתוני שער חליפין
  • הפניה לשרת proxy מפורש (proxy_server) שמטרגט את ה-SWP ב-VPC של הצרכן באמצעות FQDN swp.demo.com
  • הגדרה של dnsPeeringConfigs ‎ "domain": "demo.com."‎

מריצים את משימת האימון במכונת Vertex AI Workbench.

  • במסוף Google Cloud, עוברים אל Vertex AI → Workbench
  • ליד השם של מופע Vertex AI Workbench (workbench-tutorial), לוחצים על Open JupyterLab. המכונה של Vertex AI Workbench תיפתח ב-JupyterLab.
  • בחירה באפשרות File > New > Notebook
  • בחירה באפשרות Kernel > Python 3

מתקינים את ספריות Python הנדרשות: מתקינים את הספריות שנדרשות ל-Agent Engine, כולל pyyaml,‏ google-cloud-aiplatform,‏ cloudpickle,‏ google-cloud-api-keys ו-langchain-google-vertexai.

במחברת JupyterLab, יוצרים תא חדש ומריצים את הפקודה הבאה, תוך ציון כתובת ה-IP של ה-SWP

7b827a6a38bb5afc.png

!pip install --proxy http://10.10.10.5:8888 --upgrade google-cloud-aiplatform[agent_engines,adk]

מגדירים את המשתנים הבאים לפי הסביבה בקטע הקוד הבא:

  • PROJECT_ID
  • BUCKET_NAME
  • AGENT_NAME

בשיעור ה-Lab הזה תשתמשו במשתנים BUCKET_NAME ו-AGENT_NAME כדי לאתחל ולהגדיר את קטגוריית האחסון שלכם, שזמינה באופן גלובלי.

בקטע הבא מוגדר PROXY_SERVER, למשל swp.demo.com, שנדרש לו DNS peering לפתרון שמות. בהגדרה, AGENT_PEER_DOMAIN נפרס כ-demo.com, שמתאים לאזור ה-DNS הפרטי שנוצר בשלב קודם בתוך AGENT_PEER_NETWORK, consumer-vpc.

במחברת JupyterLab, יוצרים תא חדש ומריצים את הפקודה הבאה:

# --- Fundamental Project Configuration ---
PROJECT_ID = "YOUR_PROJECT_ID"
LOCATION = "us-central1" # e.g., "us-central1"
BUCKET_NAME = "YOUR_BUCKET_NAME" # A GCS bucket in the same location

# --- Agent Configuration ---
AGENT_NAME = "YOUR_AGENT_NAME"
MODEL = "gemini-2.5-flash" # Or another suitable model

# --- Network and Proxy Configuration ---
# The agent will call the Frankfurter API via this proxy
PROXY_SERVER = "http://swp.demo.com:8888"

# --- Deployment Configuration (PSC & DNS Peering) ---
# This should be a pre-existing Network Attachment
NETWORK_ATTACHMENT_NAME = f"projects/{PROJECT_ID}/regions/{LOCATION}/networkAttachments/psc-network-attachment"
# Optional DNS Peering config
AGENT_PEER_DOMAIN = "demo.com."
AGENT_PEER_NETWORK = "consumer-vpc"

# --- Initialize Vertex AI SDK ---
import vertexai
STAGING_BUCKET = f"gs://{BUCKET_NAME}"

vertexai.init(project=PROJECT_ID, location=LOCATION, staging_bucket=STAGING_BUCKET)

print(f"Vertex AI SDK initialized for project {PROJECT_ID} in {LOCATION}.")

במחברת JupyterLab, יוצרים תא חדש ומריצים את הפקודה הבאה.

!adk create $AGENT_NAME --model=$MODEL --project=$PROJECT_ID --region=$LOCATION

במחברת JupyterLab, יוצרים תא חדש ומריצים את הפקודה הבאה כדי ליצור את משתנה ה-proxy שמתאים ל-FQDN ולפורט של SWP.

import os
os.environ["PROXY_SERVER_URL"] = "http://swp.demo.com:8888"

בתא הקוד הבא מוצגת ההגדרה של שרת proxy מפורש ל-Agent Engine כדי לגשת לנקודת הקצה של האינטרנט api.frankfurter.app באמצעות ציון SWP, באמצעות PROXY_SERVER_TO_USE שמופה ל-os.environ["PROXY_SERVER_URL"].

import requests
# Use the globally defined proxy server URL
    proxies = {
       "http": PROXY_SERVER_TO_USE,
       "https": PROXY_SERVER_TO_USE,
    }
    try:
        response = requests.get(
            f"https://api.frankfurter.app/{currency_date}",
            params={"from": currency_from, "to": currency_to},
            proxies=proxies,
) 
response.raise_for_status() 
print(response.json()) 
except requests.exceptions.RequestException as e: print(f"An error occurred: {e}")

במחברת JupyterLab, יוצרים תא חדש ומריצים את הפקודה הבאה שמגדירה את הטמעת הכלי עבור ה-API של טירגוט המרת מטבעות: api.frankfurther.app.

%%writefile $AGENT_NAME/agent.py
from google.adk.agents.llm_agent import Agent
import os
import requests


# Get Proxy Server URL
# This is the VM's FQDN to reach the proxy vm in the consumers network
if "PROXY_SERVER_URL" not in os.environ:
    raise ValueError("Missing required environment variable: PROXY_SERVER_URL is not set.")
PROXY_SERVER_TO_USE = os.environ["PROXY_SERVER_URL"]

# Mock tool implementation
def get_exchange_rate(
    currency_from: str = "USD",
    currency_to: str = "EUR",
    currency_date: str = "latest",
):
    """Retrieves the exchange rate between two currencies on a specified date.

    Uses the Frankfurter API (https://api.frankfurter.app/) to obtain
    exchange rate data.

    Args:
        currency_from: The base currency (3-letter currency code).
            Defaults to "USD" (US Dollar).
        currency_to: The target currency (3-letter currency code).
            Defaults to "EUR" (Euro).
        currency_date: The date for which to retrieve the exchange rate.
            Defaults to "latest" for the most recent exchange rate data.
            Can be specified in YYYY-MM-DD format for historical rates.

    Returns:
        dict: A dictionary containing the exchange rate information.
            Example: {"amount": 1.0, "base": "USD", "date": "2023-11-24",
                "rates": {"EUR": 0.95534}}
    """
    # Use the globally defined proxy server URL
    proxies = {
       "http": PROXY_SERVER_TO_USE,
       "https": PROXY_SERVER_TO_USE,
    }
    
    try:
        response = requests.get(
            f"https://api.frankfurter.app/{currency_date}",
            params={"from": currency_from, "to": currency_to},
            proxies=proxies,
        )
        response.raise_for_status()  # Raise an error for bad responses
        return response.json()
    except Exception as e:
        return f"An unexpected error occurred: {e}"

root_agent = Agent(
    model='gemini-2.5-flash',
    name='root_agent',
    description="Provides the currency exchange rates between two currencies",
    instruction="You are a helpful assistant that provides the currency exchange rates between two currencies. Use the 'get_exchange_rate' tool for this purpose.",
    tools=[get_exchange_rate],
)

במחברת JupyterLab, יוצרים תא חדש ומריצים את הפקודה הבאה.

# 1. Set your variables
CURRENCY_DATE="latest"
CURRENCY_FROM="USD"
CURRENCY_TO="EUR"
PROXY_SERVER="http://swp.demo.com:8888"

# 2. Run the curl command
!curl -x "$PROXY_SERVER" "https://api.frankfurter.app/$CURRENCY_DATE?from=$CURRENCY_FROM&to=$CURRENCY_TO"

במחברת JupyterLab, יוצרים תא חדש ומריצים את הפקודה הבאה שמפעילה את הגדרת ממשק ה-PSC שמשמשת את Agent Engine, בנוסף ל-DNS peering.

import json
import os

CONFIG_FILE_PATH = os.path.join(AGENT_NAME, ".agent_engine_config.json")
# Create your config as a Python dictionary ---
config_data = {
    "requirements": [
        "google-cloud-aiplatform[agent_engines,adk]",
        "requests",
    ],
    "psc_interface_config": {
        "network_attachment": NETWORK_ATTACHMENT_NAME,
        "dns_peering_configs": [
            {
                "domain": AGENT_PEER_DOMAIN,
                "target_project": PROJECT_ID,
                "target_network": AGENT_PEER_NETWORK,
            },
        ],
    },
}

# Write the dictionary to a JSON file ---
os.makedirs(AGENT_NAME, exist_ok=True) # Ensure the directory exists
with open(CONFIG_FILE_PATH, 'w') as f:
    json.dump(config_data, f, indent=4)

print(f"Successfully created {CONFIG_FILE_PATH} with your variables.")

במחברת JupyterLab, יוצרים תא חדש ומריצים את הפקודה הבאה.

import json
import os

CONFIG_FILE_PATH = os.path.join(AGENT_NAME, ".agent_engine_config.json")
# Create your config as a Python dictionary ---
config_data = {

    "psc_interface_config": {
        "network_attachment": NETWORK_ATTACHMENT_NAME,
        "dns_peering_configs": [
            {
                "domain": AGENT_PEER_DOMAIN,
                "target_project": PROJECT_ID,
                "target_network": AGENT_PEER_NETWORK,
            },
        ],
    },
}

# Write the dictionary to a JSON file ---
os.makedirs(AGENT_NAME, exist_ok=True) # Ensure the directory exists
with open(CONFIG_FILE_PATH, 'w') as f:
    json.dump(config_data, f, indent=4)

print(f"Successfully created {CONFIG_FILE_PATH} with your variables.")

במחברת JupyterLab, יוצרים תא חדש ומריצים את הפקודה הבאה.

%%writefile $AGENT_NAME/.env

GOOGLE_CLOUD_PROJECT=PROJECT_ID
GOOGLE_CLOUD_LOCATION=us-central1
GOOGLE_GENAI_USE_VERTEXAI=1


PROXY_SERVER_URL=http://swp.demo.com:8888

במחברת JupyterLab, יוצרים תא חדש ומריצים את הפקודה הבאה שיוצרת את הסוכן.

!adk deploy agent_engine $AGENT_NAME --staging_bucket=$STAGING_BUCKET --env_file=$AGENT_NAME/.env --agent_engine_config_file=$AGENT_NAME/.agent_engine_config.json --display_name=$AGENT_NAME

מזהה של מנוע נימוקים ייווצר אחרי הרצת התא. בשלב הבא תצטרכו את המזהה שנוצר, שהוא 3235268984265768960 בדוגמה הזו.

✅ Created agent engine: projects/9315891080/locations/us-central1/reasoningEngines/3235268984265768960

במחברת JupyterLab, יוצרים תא חדש ומריצים את הפקודה הבאה. חשוב לעדכן את מספר הפרויקט ואת מזהה הנימוק של Agent Engine מהפלט הקודם:

from vertexai import agent_engines
remote_app = agent_engines.get("projects/PROJECT_NUMBER/locations/us-central1/reasoningEngines/ENTER_YOUR_ID")

במחברת JupyterLab, יוצרים תא חדש ומריצים את הפקודה הבאה.

def print_event_nicely_with_thoughts(event):
    """
    Parses and prints streaming query events, including thoughts.
    """
    try:
        content = event.get('content', {})
        role = content.get('role')
        parts = content.get('parts', [{}])

        if not parts:
            print("...")
            return

        part = parts[0] # Get the first part

        # Event 1: Model is thinking (calling a tool or just text)
        if role == 'model':

            # Check for and print any explicit 'thought' text
            if 'thought' in part:
                print(f"🧠 Thought: {part['thought']}")

            # Check for a function call
            if 'function_call' in part:
                # If we haven't *already* printed an explicit thought,
                # print a generic one.
                if 'thought' not in part:
                    print("🧠 Thinking... (decided to use a tool)")

                call = part['function_call']
                print(f"   🔧 Tool Call: {call.get('name')}()")
                print(f"      Args: {call.get('args')}")

            # Check for the final text answer
            elif 'text' in part:
                text = part.get('text', '')
                print(f"\n💬 Model: {text}")

        # Event 2: The tool returns its result
        elif role == 'user' and 'function_response' in part:
            resp = part['function_response']
            print(f"⚙️ Tool Response (from {resp.get('name')}):")
            print(f"   Output: {resp.get('response')}")

        # Other event types (like progress messages)
        else:
            print("...") # Show progress for other events

    except Exception as e:
        print(f"Error processing event: {e}")
        # print(f"Raw event: {event}") # Uncomment to debug



for event in remote_app.stream_query(
    user_id="u_456",
    # session_id=remote_session["id"],
    message="Provide USD to INR conversion rate",
):
    print_event_nicely_with_thoughts(event)

דוגמה להפעלה מוצלחת שמאמתת את הקישוריות לנקודת הקצה הציבורית api.frankfurther.app דרך ה-SWP על סמך שער ההמרה מ-USD ל-INR.

f9f925983ab5cc9d.png

12. אימות של ממשק PSC

אפשר גם לראות את כתובות ה-IP של Network Attachment שבהן נעשה שימוש ב-Agent Engine. לשם כך, עוברים אל:

Network Services (שירותי רשת) ‏→ Private Service Connect ‏→ Network Attachment (קובץ מצורף עם הרשת) ‏→ psc-network-attachment

בוחרים את הפרויקט של הדייר (שם הפרויקט מסתיים ב-tp)

c9c412334a7f5ad9.png

השדה המודגש מציין את כתובת ה-IP שמשמשת את Agent Engine מחיבור הרשת של PSC.

e94c6c03fb51f7fe.png

13. SWP - Cloud Logging Validation

כדי לראות את יומני Cloud Logging כדי לוודא שתעבורת הנתונים היוצאת (egress) מהאינטרנט בוצעה על ידי SWP, עוברים אל:

מעקב → Logs Explorer

מזינים את השאילתה: resource.type=" networkservices.googleapis.com/Gateway" ואז לוחצים על Run Query. בהמשך מוצגת דוגמה שמאשרת את נקודת הקצה של היעד, api.frankfurter.app.

f53831ef8ec663db.pngfc154a5b22da2a87.png

בדוגמה הבאה של Cloud Logging מתבצע אימות של:

‫Destination_range: כתובת ה-IP של ממשק PSC ב-Agent Engine

‫Source_range: רשת משנה של Proxy בלבד Dest_ip: כתובת ה-IP של Secure Web Proxy

חשוב לוודא ששיניתם את השדה project_id בשאילתה של רישום ביומן ב-Cloud.

logName:("projects/project_id/logs/compute.googleapis.com%2Ffirewall") AND jsonPayload.rule_details.reference:("network:consumer-vpc/firewall:allow-access-to-swp")
{
  "insertId": "1j9ym95fmu8g6o",
  "jsonPayload": {
    "vpc": {
      "project_id": "XXXXXXXXXXXXX",
      "subnetwork_name": "intf-subnet",
      "vpc_name": "consumer-vpc"
    },
    "rule_details": {
      "destination_range": [
        "10.10.10.5/32"
      ],
      "reference": "network:consumer-vpc/firewall:allow-access-to-swp",
      "priority": 1000,
      "source_range": [
        "192.168.10.0/28"
      ],
      "direction": "EGRESS",
      "ip_port_info": [
        {
          "ip_protocol": "ALL"
        }
      ],
      "action": "ALLOW"
    },
    "disposition": "ALLOWED",
    "remote_instance": {
      "region": "us-central1"
    },
    "remote_vpc": {
      "vpc_name": "consumer-vpc",
      "project_id": "XXXXXXXXXXXXXXX",
      "subnetwork_name": "swp-subnet"
    },
    "connection": {
      "src_ip": "192.168.10.2",
      "src_port": 48640,
      "dest_port": 8888,
      "dest_ip": "10.10.10.5",
      "protocol": 6
    }
  },
  "resource": {
    "type": "gce_subnetwork",
    "labels": {
      "subnetwork_id": "7147084067647653041",
      "project_id": "XXXXXXXXXXXXXX",
      "location": "us-central1",
      "subnetwork_name": "intf-subnet"
    }
  },
  "timestamp": "2025-12-30T12:51:36.628538815Z",
  "logName": "projects/dec30-run1-agent/logs/compute.googleapis.com%2Ffirewall",
  "receiveTimestamp": "2025-12-30T12:51:40.846652708Z"
}

14. הסרת המשאבים

במחברת JupyterLab, יוצרים תא חדש ומריצים את הפקודה הבאה שתפעיל את המחיקה של פריסת Agent Engine.

חשוב לוודא שאתם מעדכנים את "project number" ואת "reasoningEngines token"

import requests
token = !gcloud auth application-default print-access-token
ENDPOINT = "https://us-central1-aiplatform.googleapis.com"
response = requests.delete(
    f"{ENDPOINT}/v1beta1/projects/218166745590/locations/us-central1/reasoningEngines/3086854705725308928",
    params={"force": "true"},
    headers={
        "Content-Type": "application/json; charset=utf-8",
        "Authorization": f"Bearer {token[0]}"
    },
)
print(response.text)

מ-Cloud Shell, מוחקים את רכיבי ההדרכה.

gcloud workbench instances delete workbench-tutorial --project=$projectid --location=us-central1-a

gcloud network-security gateway-security-policies rules delete allow-notebook-subnet \
    --gateway-security-policy=my-swp-policy \
    --location=us-central1

gcloud network-security gateway-security-policies rules delete allow-example \
    --gateway-security-policy=my-swp-policy \
    --location=us-central1

gcloud network-security gateway-security-policies delete my-swp-policy \
    --location=us-central1
gcloud network-services gateways delete my-swp-instance\
    --location=us-central1

gcloud dns record-sets delete swp.demo.com --zone=private-dns-codelab  --type=A

gcloud dns managed-zones delete private-dns-codelab


gcloud compute network-attachments delete psc-network-attachment --region=us-central1 --quiet

export ROUTER_NAME=$(gcloud compute routers list --regions=us-central1 \
    --filter="name ~ swg-autogen-router" --format="value(name)")


 gcloud compute routers nats delete swg-autogen-nat --router=$ROUTER_NAME --region=us-central1 --quiet 

gcloud compute routers delete $ROUTER_NAME --region=us-central1 --quiet

gcloud compute networks subnets delete intf-subnet rfc1918-subnet1 --region=us-central1 --quiet

gcloud compute networks subnets delete intf-subnet swp-subnet
 --region=us-central1 --quiet

gcloud compute networks subnets delete intf-subnet intf-subnet --region=us-central1 --quiet

gcloud compute networks subnets delete intf-subnet proxy-subnet
 --region=us-central1 --quiet

gcloud compute networks subnets delete intf-subnet notebook-subnet
--region=us-central1 --quiet

gcloud compute networks delete consumer-vpc --quiet

15. מזל טוב

הגדרתם ואימתתם בהצלחה את Agent Engine שנפרס באמצעות ממשק Private Service Connect עם תעבורת נתונים יוצאת (egress) לאינטרנט שמתבצעת דרך שרת proxy מפורש.

יצרתם את התשתית של הצרכן והוספתם קובץ מצורף לרשת שמאפשר ליצרן ליצור מכונת VM עם כמה כרטיסי NIC כדי לגשר על התקשורת בין הצרכן ליצרן. למדתם איך ליצור פרוקסי מפורש וחיבור DNS שמאפשרים קישוריות לאינטרנט.

‫Cosmopup חושב שהדרכות הן מדהימות!!

e6d3675ca7c6911f.jpeg

מה השלב הבא?

קריאה נוספת וסרטונים

מסמכי עזר