הגדרת אבטחת שירות באמצעות gRPC בלי שרת Proxy
במדריך הזה מוסבר איך להגדיר שירות אבטחה ל-Service mesh של gRPC בלי שרת Proxy.
דרישות
לפני שמגדירים אבטחת שירות לרשת שירותים ללא proxy של gRPC, צריך לוודא שמתקיימות הדרישות הבאות.
- הפריסה שלכם עומדת בדרישות שמפורטות במאמר הכנה להגדרה של ממשקי API לניתוב שירותים עם Envoy ועומסי עבודה בלי שרת Proxy.
- חובה להשתמש ב-xDS גרסה 3.
- יש לכם גישה לגרסת xDS הנדרשת ולפונקציונליות של ספק האישורים באחת מהשפות הבאות:
- gRPC Java
- gRPC C++
- gRPC Python
- gRPC Go אפשר למצוא את גרסאות השפה הנדרשות ב-github
- יש לכם גישה לכלי ליצירת קוד bootstrap, גרסה 0.19.0. תמונת הגנרטור של ה-bootstrap נמצאת במאגר הקונטיינרים Google Cloud .
- עומדים בכל הדרישות המוקדמות לאיזון עומסים ב-gRPC proxyless service mesh.
- יש לכם הרשאות מספיקות ליצור או לעדכן את Cloud Service Mesh ואתGoogle Cloud משאבי רשת השירות כדי להשתמש באבטחת PSM. מידע מלא על ההרשאות הנדרשות זמין במאמר הכנה להגדרת Cloud Service Mesh עם שירותי gRPC ללא proxy.
- יש לכם את ההרשאות הנדרשות לשימוש ב-Certificate Authority Service, שמתוארות במאמר יצירת רשויות אישורים להנפקת אישורים
הגדרת ניהול זהויות והרשאות גישה (IAM)
צריכות להיות לכם ההרשאות הנדרשות לשימוש ב-Google Kubernetes Engine. לפחות אחד מהתפקידים הבאים צריך להיות מוקצה לכם:
- תפקיד ב-
roles/container.clusterAdminGKE roles/compute.instanceAdminתפקיד ב-Compute Engineroles/iam.serviceAccountUserתפקיד
כדי ליצור את המשאבים שנדרשים להגדרה, צריך להיות לכם תפקיד compute.NetworkAdmin. התפקיד הזה מכיל את כל ההרשאות שנדרשות כדי ליצור, לעדכן, למחוק, להציג ולהשתמש במשאבים הנדרשים (כלומר, להפנות אליהם במשאבים אחרים). אם אתם הבעלים עם הרשאת עריכה של הפרויקט, התפקיד הזה מוקצה לכם באופן אוטומטי.
שימו לב שהמגבלות networksecurity.googleapis.com.clientTlsPolicies.use ו-networksecurity.googleapis.com.serverTlsPolicies.use לא נאכפות כשמפנים למשאבים האלה במשאב של שירות לקצה העורפי.
אם האכיפה הזו תתבצע בעתיד ואתם משתמשים בתפקיד compute.NetworkAdmin, לא תיתקלו בבעיות כשהבדיקה הזו תיאכף.
אם אתם משתמשים בתפקידים בהתאמה אישית והבדיקה הזו תיאכף בעתיד, תצטרכו לוודא שאתם כוללים את ההרשאה המתאימה .use. אחרת, בעתיד יכול להיות שתגלו שלתפקיד המותאם אישית שלכם אין את ההרשאות הנדרשות כדי להפנות אל clientTlsPolicy או אל serverTlsPolicy משירות לקצה העורפי.
הכנה להגדרה
אבטחת רשת שירותים ללא proxy (PSM) מוסיפה אבטחה לרשת שירותים שהוגדרה לאיזון עומסים בהתאם למסמכי התיעוד של שירותי gRPC ללא proxy. ב-service mesh ללא proxy, לקוח gRPC משתמש בסכימה xds: ב-URI כדי לגשת לשירות, וכך מפעיל את התכונות של איזון העומסים וגילוי נקודות הקצה ב-PSM.
עדכון של לקוחות ושרתי gRPC לגרסה הנכונה
צריך לבנות מחדש את האפליקציות באמצעות גרסת gRPC המינימלית הנתמכת עבור השפה שלכם.
עדכון קובץ ה-bootstrap
אפליקציות gRPC משתמשות בקובץ bootstrap יחיד, שחייבים להיות בו כל השדות שנדרשים על ידי קוד gRPC בצד הלקוח ובצד השרת. מחולל bootstrap יוצר באופן אוטומטי את קובץ ה-bootstrap כדי לכלול דגלים וערכים שנדרשים לאבטחת PSM. מידע נוסף זמין בקטע בנושא קובץ Bootstrap, שכולל קובץ Bootstrap לדוגמה.
סקירה כללית של ההגדרה
תהליך ההגדרה הזה הוא הרחבה של הגדרת Cloud Service Mesh עם שירותי GKE ו-gRPC ללא proxy. הפניות לשלבים קיימים שלא שונו בתהליך ההגדרה מופיעות בכל מקום שבו הם רלוונטיים.
השיפורים העיקריים בהגדרת Cloud Service Mesh עם GKE הם:
- הגדרת שירות CA, שבו יוצרים מאגרי CA פרטיים ואת רשויות האישורים הנדרשות.
- יצירת אשכול GKE עם תכונות של איחוד זהויות של עומסי עבודה ב-GKE ואישורי רשת, ושילוב של CA Service.
- הגדרת הנפקת אישורים לרשת באשכול.
- יצירת חשבונות השירות של הלקוח והשרת.
- הגדרת שרת לדוגמה שמשתמש ב-xDS APIs ובפרטי כניסה של שרת xDS כדי לקבל הגדרת אבטחה מ-Cloud Service Mesh.
- הגדרת לקוח לדוגמה שמשתמש בהרשאות xDS.
- מתבצע עדכון של ההגדרה של Cloud Service Mesh כדי לכלול הגדרת אבטחה.
דוגמאות קוד לשימוש בפרטי כניסה של xDS זמינות במיקומים הבאים:
עדכון Google Cloud CLI
כדי לעדכן את Google Cloud CLI, מריצים את הפקודה הבאה:
gcloud components update
הגדרה של משתני סביבה
במדריך הזה משתמשים בפקודות Cloud Shell, ומידע שחוזר על עצמו בפקודות מיוצג על ידי משתני סביבה שונים. מגדירים את הערכים הספציפיים שלכם למשתני הסביבה הבאים בסביבת מעטפת לפני שמריצים את הפקודות. כל שורת הערה מציינת את המשמעות של משתנה הסביבה המשויך.
# Your project ID
PROJECT_ID=PROJECT_ID
# GKE cluster name and zone for this example.
CLUSTER_NAME=CLUSTER_NAME
ZONE=ZONE
gcloud config set compute/zone $ZONE
# GKE cluster URL derived from the above
GKE_CLUSTER_URL="https://container.googleapis.com/v1/projects/${PROJECT_ID}/locations/${ZONE}/clusters/${CLUSTER_NAME}"
# Workload pool to be used with the GKE cluster
WORKLOAD_POOL="${PROJECT_ID}.svc.id.goog"
# Kubernetes namespace to run client and server demo.
K8S_NAMESPACE='default'
DEMO_BACKEND_SERVICE_NAME='grpc-gke-helloworld-service'
# Compute other values
# Project number for your project
PROJNUM=$(gcloud projects describe ${PROJECT_ID} --format="value(projectNumber)")
# VERSION is the GKE cluster version. Install and use the most recent version
# from the rapid release channel and substitute its version for
# CLUSTER_VERSION, for example:
# VERSION=latest available version
# Note that the minimum required cluster version is 1.21.4-gke.1801.
VERSION="CLUSTER_VERSION"
SA_GKE=service-${PROJNUM}@container-engine-robot.iam.gserviceaccount.com
הפעלת גישה לממשקי API נדרשים
בקטע הזה מוסבר איך להפעיל גישה לממשקי ה-API הנדרשים.
מריצים את הפקודה הבאה כדי להפעיל את Cloud Service Mesh ואת ממשקי ה-API האחרים שנדרשים לאבטחת רשת שירותי gRPC ללא proxy.
gcloud services enable \ container.googleapis.com \ cloudresourcemanager.googleapis.com \ compute.googleapis.com \ trafficdirector.googleapis.com \ networkservices.googleapis.com \ networksecurity.googleapis.com \ privateca.googleapis.com \ gkehub.googleapis.comמריצים את הפקודה הבאה כדי לאפשר לחשבון השירות שמוגדר כברירת מחדל לגשת ל-Cloud Service Mesh security API.
GSA_EMAIL=$(gcloud iam service-accounts list --format='value(email)' \ --filter='displayName:Compute Engine default service account') gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member serviceAccount:${GSA_EMAIL} \ --role roles/trafficdirector.client
יצירה או עדכון של אשכול GKE
האבטחה של שירות Cloud Service Mesh תלויה בשילוב של שירות CA עם GKE. אשכול GKE צריך לעמוד בדרישות הבאות בנוסף לדרישות ההגדרה:
- צריך להשתמש בגרסת אשכול מינימלית של 1.21.4-gke.1801. אם אתם צריכים תכונות שזמינות בגרסה מאוחרת יותר, תוכלו לקבל את הגרסה הזו מערוץ ההפצה המהירה.
- צריך להפעיל את אשכול GKE ולהגדיר בו אישורי רשת, כמו שמתואר במאמר יצירת רשויות אישורים להנפקת אישורים.
יוצרים אשכול חדש שמשתמש באיחוד זהויות של עומסי עבודה ל-GKE. אם אתם מעדכנים אשכול קיים, דלגו לשלב הבא. הערך שאתם מציינים עבור
--tagsצריך להיות זהה לשם שמועבר לדגל--target-tagsעבור הפקודהfirewall-rules createבקטע הגדרת Cloud Service Mesh באמצעות רכיבי Cloud Load Balancing.# Create a GKE cluster with GKE managed mesh certificates. gcloud container clusters create CLUSTER_NAME \ --release-channel=rapid \ --scopes=cloud-platform \ --image-type=cos_containerd \ --machine-type=e2-standard-2 \ --zone=ZONE \ --workload-pool=PROJECT_ID.svc.id.goog \ --enable-mesh-certificates \ --cluster-version=CLUSTER_VERSION \ --enable-ip-alias \ --tags=allow-health-checks \ --workload-metadata=GKE_METADATA
יצירת האשכול עשויה להימשך כמה דקות.
אם אתם משתמשים באשכול קיים, צריך להפעיל את איחוד שירותי אימות הזהות של עומסי עבודה ל-GKE ואת אישורי GKE Mesh. מוודאים שהאשכול נוצר עם הדגל
--enable-ip-alias, שלא ניתן להשתמש בו עם הפקודהupdate.gcloud container clusters update CLUSTER_NAME \ --enable-mesh-certificates
מריצים את הפקודה הבאה כדי לעבור לאשכול החדש כאשכול ברירת המחדל עבור פקודות
kubectl:gcloud container clusters get-credentials CLUSTER_NAME \ --zone ZONE
רישום אשכולות ב-Fleet
רושמים את האשכול שיצרתם או עדכנתם במאמר יצירת אשכול GKE ב-Fleet. רישום האשכול מאפשר לכם להגדיר אשכולות בכמה פרויקטים בקלות רבה יותר.
הערה: כל אחד מהשלבים האלה עשוי להימשך עד עשר דקות.
רושמים את האשכול ב-Fleet:
gcloud container fleet memberships register CLUSTER_NAME \ --gke-cluster=ZONE/CLUSTER_NAME \ --enable-workload-identity --install-connect-agent \ --manifest-output-file=MANIFEST-FILE_NAME
מחליפים את המשתנים באופן הבא:
- CLUSTER_NAME: שם האשכול.
- ZONE: האזור של האשכול.
- MANIFEST-FILE_NAME: הנתיב שבו הפקודות האלה יוצרות את המניפסט לצורך רישום.
אם תהליך ההרשמה יצליח, תופיע הודעה כמו זו שבהמשך:
Finished registering the cluster CLUSTER_NAME with the fleet.
מחילים את קובץ המניפסט שנוצר על האשכול:
kubectl apply -f MANIFEST-FILE_NAME
אם תהליך הגשת הבקשה יצליח, יוצגו הודעות כמו אלה:
namespace/gke-connect created serviceaccount/connect-agent-sa created podsecuritypolicy.policy/gkeconnect-psp created role.rbac.authorization.k8s.io/gkeconnect-psp:role created rolebinding.rbac.authorization.k8s.io/gkeconnect-psp:rolebinding created role.rbac.authorization.k8s.io/agent-updater created rolebinding.rbac.authorization.k8s.io/agent-updater created role.rbac.authorization.k8s.io/gke-connect-agent-20210416-01-00 created clusterrole.rbac.authorization.k8s.io/gke-connect-impersonation-20210416-01-00 created clusterrolebinding.rbac.authorization.k8s.io/gke-connect-impersonation-20210416-01-00 created clusterrolebinding.rbac.authorization.k8s.io/gke-connect-feature-authorizer-20210416-01-00 created rolebinding.rbac.authorization.k8s.io/gke-connect-agent-20210416-01-00 created role.rbac.authorization.k8s.io/gke-connect-namespace-getter created rolebinding.rbac.authorization.k8s.io/gke-connect-namespace-getter created secret/http-proxy created deployment.apps/gke-connect-agent-20210416-01-00 created service/gke-connect-monitoring created secret/creds-gcp create
מקבלים את משאב החברות מהאשכול:
kubectl get memberships membership -o yaml
הפלט צריך לכלול את מאגר הזהויות של עומסי העבודה שהוקצה על ידי Fleet, כאשר PROJECT_ID הוא מזהה הפרויקט:
workload_identity_pool: PROJECT_ID.svc.id.goog
המשמעות היא שהאשכול נרשם בהצלחה.
יצירת רשויות אישורים להנפקת אישורים
כדי להנפיק אישורים ל-Pods, צריך ליצור מאגר של שירות CA ואת רשויות האישורים (CAs) הבאות:
- רשות אישורים (CA) עליונה. זהו הבסיס למהימנות של כל האישורים שהונפקו לרשת. אפשר להשתמש ב-CA בסיסי קיים, אם יש לכם כזה. יוצרים את CA הבסיס ברמה
enterprise, שמיועדת להנפקת אישורים לטווח ארוך עם נפח נמוך. - רשות אישורים משנית. רשות האישורים הזו מנפיקה אישורים לעומסי עבודה. יוצרים את רשות האישורים המשנית באזור שבו האשכול שלכם נפרס. יוצרים את CA המשני ברמה
devops, שמיועדת להנפקת אישורים לטווח קצר בכמויות גדולות.
יצירת רשות אישורים משנית היא אופציונלית, אבל מומלץ מאוד ליצור אחת כזו במקום להשתמש ברשות אישורי הבסיס כדי להנפיק אישורי GKE mesh. אם מחליטים להשתמש ב-CA הבסיסי כדי להנפיק אישורי רשת, צריך לוודא שמצב ההנפקה מבוסס-ההגדרות שמוגדר כברירת מחדל עדיין מותר.
רשות אישורים משנית יכולה להיות באזור אחר מהאזור של האשכול, אבל מומלץ מאוד ליצור אותה באותו אזור של האשכול כדי לשפר את הביצועים. עם זאת, אפשר ליצור את רשויות האישורים הבסיסיות והמשניות באזורים שונים בלי להשפיע על הביצועים או על הזמינות.
האזורים הבאים נתמכים בשירות CA:
| שם האזור | תיאור האזור |
|---|---|
asia-east1 |
טייוואן |
asia-east2 |
הונג קונג |
asia-northeast1 |
טוקיו |
asia-northeast2 |
אוסקה |
asia-northeast3 |
סיאול |
asia-south1 |
מומבאי |
asia-south2 |
דלהי |
asia-southeast1 |
סינגפור |
asia-southeast2 |
ג'קארטה |
australia-southeast1 |
סידני |
australia-southeast2 |
מלבורן |
europe-central2 |
ורשה |
europe-north1 |
פינלנד |
europe-southwest1 |
מדריד |
europe-west1 |
בלגיה |
europe-west2 |
לונדון |
europe-west3 |
פרנקפורט |
europe-west4 |
הולנד |
europe-west6 |
ציריך |
europe-west8 |
מילאנו |
europe-west9 |
פריז |
europe-west10 |
ברלין |
europe-west12 |
טורינו |
me-central1 |
דוחה |
me-central2 |
דמאם |
me-west1 |
תל אביב |
northamerica-northeast1 |
מונטריאול |
northamerica-northeast2 |
טורונטו |
southamerica-east1 |
סאו פאולו |
southamerica-west1 |
סנטיאגו |
us-central1 |
איווה |
us-east1 |
דרום קרוליינה |
us-east4 |
צפון וירג'יניה |
us-east5 |
קולומבוס |
us-south1 |
דאלאס |
us-west1 |
אורגון |
us-west2 |
לוס-אנג׳לס |
us-west3 |
סולט לייק סיטי |
us-west4 |
לאס וגאס |
אפשר גם להריץ את הפקודה הבאה כדי לבדוק את רשימת המיקומים הנתמכים:
gcloud privateca locations list
נותנים את הרשאת IAM
roles/privateca.caManagerלאנשים שיוצרים מאגר רשויות אישורים ורשות אישורים. שימו לב: הפורמט הנכון של MEMBER הואuser:userid@example.com. אם האדם הזה הוא המשתמש הנוכחי, אפשר לקבל את מזהה המשתמש הנוכחי באמצעות פקודת ה-Shell$(gcloud auth list --filter=status:ACTIVE --format="value(account)").gcloud projects add-iam-policy-binding PROJECT_ID \ --member=MEMBER \ --role=roles/privateca.caManager
מקצים את התפקיד
role/privateca.adminבשירות CA לאנשים שצריכים לשנות את כללי המדיניות של IAM, כאשרMEMBERהוא אדם שצריך את הגישה הזו, במיוחד כל אדם שמבצע את השלבים הבאים שמעניקים את התפקידיםprivateca.auditorו-privateca.certificateManager:gcloud projects add-iam-policy-binding PROJECT_ID \ --member=MEMBER \ --role=roles/privateca.admin
יוצרים את המאגר של שירות רשות האישורים (CA) הבסיסית.
gcloud privateca pools create ROOT_CA_POOL_NAME \ --location ROOT_CA_POOL_LOCATION \ --tier enterprise
יוצרים רשות אישורים (CA) עליונה.
gcloud privateca roots create ROOT_CA_NAME --pool ROOT_CA_POOL_NAME \ --subject "CN=ROOT_CA_NAME, O=ROOT_CA_ORGANIZATION" \ --key-algorithm="ec-p256-sha256" \ --max-chain-length=1 \ --location ROOT_CA_POOL_LOCATION
בהדגמה הזו, משתמשים בערכים הבאים למשתנים:
- ROOT_CA_POOL_NAME=td_sec_pool
- ROOT_CA_NAME=pkcs2-ca
- ROOT_CA_POOL_LOCATION=us-east1
- ROOT_CA_ORGANIZATION="TestCorpLLC"
יוצרים את המאגר המשני ואת רשות האישורים המשנית. מוודאים שמצב ההנפקה מבוסס-ההגדרות שמוגדר כברירת מחדל עדיין מותר.
gcloud privateca pools create SUBORDINATE_CA_POOL_NAME \ --location SUBORDINATE_CA_POOL_LOCATION \ --tier devops
gcloud privateca subordinates create SUBORDINATE_CA_NAME \ --pool SUBORDINATE_CA_POOL_NAME \ --location SUBORDINATE_CA_POOL_LOCATION \ --issuer-pool ROOT_CA_POOL_NAME \ --issuer-location ROOT_CA_POOL_LOCATION \ --subject "CN=SUBORDINATE_CA_NAME, O=SUBORDINATE_CA_ORGANIZATION" \ --key-algorithm "ec-p256-sha256" \ --use-preset-profile subordinate_mtls_pathlen_0
בהדגמה הזו, משתמשים בערכים הבאים למשתנים:
- SUBORDINATE_CA_POOL_NAME="td-ca-pool"
- SUBORDINATE_CA_POOL_LOCATION=us-east1
- SUBORDINATE_CA_NAME="td-ca"
- SUBORDINATE_CA_ORGANIZATION="TestCorpLLC"
- ROOT_CA_POOL_NAME=td_sec_pool
- ROOT_CA_POOL_LOCATION=us-east1
מקצים את התפקיד
privateca.auditorב-IAM למאגר של רשות אישורים (CA) בסיסית כדי לאפשר גישה מחשבון השירות של GKE:gcloud privateca pools add-iam-policy-binding ROOT_CA_POOL_NAME \ --location ROOT_CA_POOL_LOCATION \ --role roles/privateca.auditor \ --member="serviceAccount:service-PROJNUM@container-engine-robot.iam.gserviceaccount.com"
מקצים את תפקיד ה-IAM
privateca.certificateManagerלמאגר ה-CA המשני כדי לאפשר גישה מחשבון השירות של GKE:gcloud privateca pools add-iam-policy-binding SUBORDINATE_CA_POOL_NAME \ --location SUBORDINATE_CA_POOL_LOCATION \ --role roles/privateca.certificateManager \ --member="serviceAccount:service-PROJNUM@container-engine-robot.iam.gserviceaccount.com"
שומרים את הגדרת ה-YAML הבאה
WorkloadCertificateConfigכדי להגדיר לאשכול איך להנפיק אישורים לרשת:apiVersion: security.cloud.google.com/v1 kind: WorkloadCertificateConfig metadata: name: default spec: # Required. The CA service that issues your certificates. certificateAuthorityConfig: certificateAuthorityServiceConfig: endpointURI: ISSUING_CA_POOL_URI # Required. The key algorithm to use. Choice of RSA or ECDSA. # # To maximize compatibility with various TLS stacks, your workloads # should use keys of the same family as your root and subordinate CAs. # # To use RSA, specify configuration such as: # keyAlgorithm: # rsa: # modulusSize: 4096 # # Currently, the only supported ECDSA curves are "P256" and "P384", and the only # supported RSA modulus sizes are 2048, 3072 and 4096. keyAlgorithm: rsa: modulusSize: 4096 # Optional. Validity duration of issued certificates, in seconds. # # Defaults to 86400 (1 day) if not specified. validityDurationSeconds: 86400 # Optional. Try to start rotating the certificate once this # percentage of validityDurationSeconds is remaining. # # Defaults to 50 if not specified. rotationWindowPercentage: 50מחליפים את מה שכתוב בשדות הבאים:
- מזהה הפרויקט שבו פועל האשכול:
PROJECT_ID
- ה-URI המוגדר במלואו של רשות האישורים שמנפיקה את התעודות של הרשת (ISSUING_CA_POOL_URI).
יכול להיות שזו רשות אישורים משנית (מומלץ) או רשות אישורים בסיסית. הפורמט הוא:
//privateca.googleapis.com/projects/PROJECT_ID/locations/SUBORDINATE_CA_POOL_LOCATION/caPools/SUBORDINATE_CA_POOL_NAME
- מזהה הפרויקט שבו פועל האשכול:
שומרים את הגדרת ה-YAML הבאה
TrustConfigכדי להגדיר לאשכול איך לתת אמון באישורים שהונפקו:apiVersion: security.cloud.google.com/v1 kind: TrustConfig metadata: name: default spec: # You must include a trustStores entry for the trust domain that # your cluster is enrolled in. trustStores: - trustDomain: PROJECT_ID.svc.id.goog # Trust identities in this trustDomain if they appear in a certificate # that chains up to this root CA. trustAnchors: - certificateAuthorityServiceURI: ROOT_CA_POOL_URIמחליפים את מה שכתוב בשדות הבאים:
- מזהה הפרויקט שבו פועל האשכול:
PROJECT_ID
- ה-URI המוגדר במלואו של מאגר רשויות האישורים (CA) הבסיסי (ROOT_CA_POOL_URI).
הפורמט הוא:
//privateca.googleapis.com/projects/PROJECT_ID/locations/ROOT_CA_POOL_LOCATION/caPools/ROOT_CA_POOL_NAME
- מזהה הפרויקט שבו פועל האשכול:
מחילים את ההגדרות על האשכול:
kubectl apply -f WorkloadCertificateConfig.yaml kubectl apply -f TrustConfig.yaml
יצירת שירות gRPC ללא proxy באמצעות NEGs
כדי להשתמש באבטחת PSM, צריך שרת gRPC ללא proxy שיוכל להשתמש ב-xDS כדי לקבל הגדרות אבטחה מ-Cloud Service Mesh. השלב הזה דומה להגדרת שירותי GKE עם NEGs במדריך להגדרת איזון עומסים של PSM, אבל במקום התמונה java-example-hostname משתמשים בשרת helloworld עם xDS בדוגמה xDS במאגר grpc-java.
אתם יוצרים ומריצים את השרת הזה בקונטיינר שנבנה מקובץ אימג' של openjdk:8-jdk.
אפשר גם להשתמש בתכונה של קבוצת נקודות קצה ברשת עם שם, שמאפשרת לציין שם לקבוצת נקודות הקצה ברשת. הפעולה הזו מפשטת את השלבים הבאים כי הפריסה יודעת את השם של קבוצת נקודות הקצה ברשת (NEG) בלי שתצטרך לחפש אותו.
זוהי דוגמה מלאה למפרט Kubernetes של שרת gRPC. שימו לב לנקודות הבאות:
- ה-spec יוצר חשבון שירות של Kubernetes
example-grpc-serverשמשמש את ה-Pod של שרת gRPC. - במפרט נעשה שימוש בשדה
nameבהערהcloud.google.com/negשל השירות כדי לציין את שם ה-NEGexample-grpc-server. - המשתנה
${PROJNUM}מייצג את מספר הפרויקט. - במפרט נעשה שימוש בקטע
initContainersכדי להריץ מחולל אתחול לאכלוס קובץ האתחול שספריית gRPC בלי שרת Proxy צריכה. קובץ האתחול הזה נמצא בנתיב/tmp/grpc-xds/td-grpc-bootstrap.jsonבקונטיינר של שרת gRPC שנקראexample-grpc-server.
מוסיפים את ההערה הבאה למפרט ה-Pod:
annotations: security.cloud.google.com/use-workload-certificates: ""
המפרט המלא שמופיע בהמשך כולל את המיקום הנכון.
בזמן היצירה, לכל פוד יש עוצמת קול בערך /var/run/secrets/workload-spiffe-credentials.
כרך זה מכיל את הפריטים הבאים:
-
private_key.pemהוא מפתח פרטי שנוצר באופן אוטומטי. -
certificates.pemהוא חבילה של אישורים בפורמט PEM שאפשר להציג ל-Pod אחר כשרשרת אישורי הלקוח, או להשתמש בה כשרשרת אישורי השרת. -
ca_certificates.pemהוא חבילה של אישורים בפורמט PEM שמשמשים כנקודות עוגן מהימנות כשמאמתים את שרשרת האישורים של הלקוח שמוצגת על ידי Pod אחר, או את שרשרת האישורים של השרת שמתקבלת כשמתחברים ל-Pod אחר.
שימו לב שהקובץ ca_certificates.pem מכיל אישורים לדומיין המקומי של מהימנות לעומסי העבודה, שהוא מאגר עומסי העבודה של האשכול.
אישור העלה ב-certificates.pem מכיל את הצהרת הזהות הבאה ב-SPIFFE בטקסט פשוט:
spiffe://WORKLOAD_POOL/ns/NAMESPACE/sa/KUBERNETES_SERVICE_ACCOUNT
בטענה הזו:
- WORKLOAD_POOL הוא השם של מאגר זהויות של כוח העבודה של האשכול.
- NAMESPACE הוא מרחב השמות של חשבון השירות של Kubernetes.
- KUBERNETES_SERVICE_ACCOUNT הוא השם של חשבון השירות של Kubernetes.
ההוראות הבאות בשפה שלך יוצרות את המפרט לשימוש בדוגמה הזו.
Java
מריצים את הפקודה הבאה כדי לוודא שמספר הפרויקט מוגדר בצורה נכונה:
if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
יוצרים את המפרט:
cat << EOF > example-grpc-server.yaml apiVersion: v1 kind: ServiceAccount metadata: name: example-grpc-server namespace: default annotations: iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com --- apiVersion: v1 kind: Service metadata: name: example-grpc-server namespace: default labels: k8s-app: example-grpc-server annotations: cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}' spec: ports: - name: helloworld port: 8080 protocol: TCP targetPort: 50051 selector: k8s-app: example-grpc-server type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: name: example-grpc-server namespace: default labels: k8s-app: example-grpc-server spec: replicas: 1 selector: matchLabels: k8s-app: example-grpc-server strategy: {} template: metadata: annotations: security.cloud.google.com/use-workload-certificates: "" labels: k8s-app: example-grpc-server spec: containers: - image: openjdk:8-jdk imagePullPolicy: IfNotPresent name: example-grpc-server command: - /bin/sleep - inf env: - name: GRPC_XDS_BOOTSTRAP value: "/tmp/grpc-xds/td-grpc-bootstrap.json" ports: - protocol: TCP containerPort: 50051 resources: limits: cpu: 800m memory: 512Mi requests: cpu: 100m memory: 512Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/grpc-xds/ initContainers: - name: grpc-td-init image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.19.0 imagePullPolicy: Always args: - --config-mesh-experimental - "grpc-mesh" - --output - "/tmp/bootstrap/td-grpc-bootstrap.json" - --node-metadata=app=helloworld resources: limits: cpu: 100m memory: 100Mi requests: cpu: 10m memory: 100Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/bootstrap/ serviceAccountName: example-grpc-server volumes: - name: grpc-td-conf emptyDir: medium: Memory EOF
C++
מריצים את הפקודה הבאה כדי לוודא שמספר הפרויקט מוגדר בצורה נכונה:
if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
יוצרים את המפרט:
cat << EOF > example-grpc-server.yaml apiVersion: v1 kind: ServiceAccount metadata: name: example-grpc-server namespace: default annotations: iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com --- apiVersion: v1 kind: Service metadata: name: example-grpc-server namespace: default labels: k8s-app: example-grpc-server annotations: cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}' spec: ports: - name: helloworld port: 8080 protocol: TCP targetPort: 50051 selector: k8s-app: example-grpc-server type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: name: example-grpc-server namespace: default labels: k8s-app: example-grpc-server spec: replicas: 1 selector: matchLabels: k8s-app: example-grpc-server strategy: {} template: metadata: annotations: security.cloud.google.com/use-workload-certificates: "" labels: k8s-app: example-grpc-server spec: containers: - image: phusion/baseimage:18.04-1.0.0 imagePullPolicy: IfNotPresent name: example-grpc-server command: - /bin/sleep - inf env: - name: GRPC_XDS_BOOTSTRAP value: "/tmp/grpc-xds/td-grpc-bootstrap.json" ports: - protocol: TCP containerPort: 50051 resources: limits: cpu: 8 memory: 8Gi requests: cpu: 300m memory: 512Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/grpc-xds/ initContainers: - name: grpc-td-init image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.19.0 imagePullPolicy: Always args: - --config-mesh-experimental - "grpc-mesh" - --output - "/tmp/bootstrap/td-grpc-bootstrap.json" - --node-metadata=app=helloworld resources: limits: cpu: 100m memory: 100Mi requests: cpu: 10m memory: 100Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/bootstrap/ serviceAccountName: example-grpc-server volumes: - name: grpc-td-conf emptyDir: medium: Memory EOF
Python
מריצים את הפקודה הבאה כדי לוודא שמספר הפרויקט מוגדר בצורה נכונה:
if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
יוצרים את המפרט:
cat << EOF > example-grpc-server.yaml apiVersion: v1 kind: ServiceAccount metadata: name: example-grpc-server namespace: default annotations: iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com --- apiVersion: v1 kind: Service metadata: name: example-grpc-server namespace: default labels: k8s-app: example-grpc-server annotations: cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}' spec: ports: - name: helloworld port: 8080 protocol: TCP targetPort: 50051 selector: k8s-app: example-grpc-server type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: name: example-grpc-server namespace: default labels: k8s-app: example-grpc-server spec: replicas: 1 selector: matchLabels: k8s-app: example-grpc-server strategy: {} template: metadata: annotations: security.cloud.google.com/use-workload-certificates: "" labels: k8s-app: example-grpc-server spec: containers: - image: phusion/baseimage:18.04-1.0.0 imagePullPolicy: IfNotPresent name: example-grpc-server command: - /bin/sleep - inf env: - name: GRPC_XDS_BOOTSTRAP value: "/tmp/grpc-xds/td-grpc-bootstrap.json" ports: - protocol: TCP containerPort: 50051 resources: limits: cpu: 8 memory: 8Gi requests: cpu: 300m memory: 512Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/grpc-xds/ initContainers: - name: grpc-td-init image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.19.0 imagePullPolicy: Always args: - --config-mesh-experimental - "grpc-mesh" - --output - "/tmp/bootstrap/td-grpc-bootstrap.json" - --node-metadata=app=helloworld resources: limits: cpu: 100m memory: 100Mi requests: cpu: 10m memory: 100Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/bootstrap/ serviceAccountName: example-grpc-server volumes: - name: grpc-td-conf emptyDir: medium: Memory EOF
המשך
מריצים את הפקודה הבאה כדי לוודא שמספר הפרויקט מוגדר בצורה נכונה:
if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
יוצרים את המפרט:
cat << EOF > example-grpc-server.yaml apiVersion: v1 kind: ServiceAccount metadata: name: example-grpc-server namespace: default annotations: iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com --- apiVersion: v1 kind: Service metadata: name: example-grpc-server namespace: default labels: k8s-app: example-grpc-server annotations: cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}' spec: ports: - name: helloworld port: 8080 protocol: TCP targetPort: 50051 selector: k8s-app: example-grpc-server type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: name: example-grpc-server namespace: default labels: k8s-app: example-grpc-server spec: replicas: 1 selector: matchLabels: k8s-app: example-grpc-server strategy: {} template: metadata: annotations: security.cloud.google.com/use-workload-certificates: "" labels: k8s-app: example-grpc-server spec: containers: - image: golang:1.16-alpine imagePullPolicy: IfNotPresent name: example-grpc-server command: - /bin/sleep - inf env: - name: GRPC_XDS_BOOTSTRAP value: "/tmp/grpc-xds/td-grpc-bootstrap.json" ports: - protocol: TCP containerPort: 50051 resources: limits: cpu: 8 memory: 8Gi requests: cpu: 300m memory: 512Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/grpc-xds/ initContainers: - name: grpc-td-init image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.19.0 imagePullPolicy: Always args: - --config-mesh-experimental - "grpc-mesh" - --output - "/tmp/bootstrap/td-grpc-bootstrap.json" - --node-metadata=app=helloworld resources: limits: cpu: 100m memory: 100Mi requests: cpu: 10m memory: 100Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/bootstrap/ serviceAccountName: example-grpc-server volumes: - name: grpc-td-conf emptyDir: medium: Memory EOFכך משלימים את התהליך.
החלת המפרט:
kubectl apply -f example-grpc-server.yaml
מקצים לחשבון השירות את התפקידים הנדרשים:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:${PROJECT_ID}.svc.id.goog[default/example-grpc-server]" \ ${PROJNUM}-compute@developer.gserviceaccount.com gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member "serviceAccount:${PROJECT_ID}.svc.id.goog[default/example-grpc-server]" \ --role roles/trafficdirector.clientמריצים את הפקודות האלה כדי לוודא שהשירות וה-Pod נוצרו בצורה נכונה:
kubectl get deploy/example-grpc-server kubectl get svc/example-grpc-server
מוודאים ששם ה-NEG נכון:
gcloud compute network-endpoint-groups list \ --filter "name=example-grpc-server" --format "value(name)"הפקודה צריכה להחזיר את שם ה-NEG
example-grpc-server.
הגדרת Cloud Service Mesh עם Google Cloud רכיבים של איזון עומסים
השלבים בקטע הזה דומים לאלה שבקטע הגדרת Cloud Service Mesh עם רכיבי איזון עומסים, אבל יש כמה שינויים, כמו שמתואר בקטעים הבאים.
יצירת בדיקת התקינות, כלל חומת האש ושירות הקצה העורפי
כששרת gRPC מוגדר לשימוש ב-mTLS, בדיקות תקינות של gRPC לא פועלות כי לקוח בדיקת התקינות לא יכול להציג אישור לקוח תקף לשרתים. יש שתי דרכים לפתור את הבעיה הזו.
בגישה הראשונה, השרת יוצר יציאה נוספת להצגת תוכן שמוגדרת כיציאה לבדיקת תקינות. הוא מצורף לשירות מיוחד לבדיקת תקינות, כטקסט רגיל או כ-TLS ליציאה הזו.
helloworld שרת לדוגמה של xDS משתמש ב-PORT_NUMBER + 1 כיציאה לבדיקת תקינות של טקסט פשוט. בדוגמה נעשה שימוש ב-50052 כפורט לבדיקת תקינות, כי 50051 הוא הפורט של שרת האפליקציות gRPC.
בגישה השנייה, מגדירים בדיקת תקינות כדי לבדוק רק את קישוריות ה-TCP ליציאת שרת האפליקציה. הבדיקה הזו בודקת רק את הקישוריות, והיא גם יוצרת תנועה מיותרת לשרת כשיש לחיצות ידיים לא מוצלחות של TLS. לכן, מומלץ להשתמש בגישה הראשונה.
יוצרים את בדיקת התקינות. שימו לב: בדיקת תקינות מתחילה רק אחרי שיוצרים את השרת ומפעילים אותו.
אם אתם יוצרים יציאה ייעודית להצגת נתונים לבדיקת תקינות, שזו הגישה המומלצת, משתמשים בפקודה הזו:
gcloud compute health-checks create grpc grpc-gke-helloworld-hc \ --enable-logging --port 50052
אם אתם יוצרים בדיקת תקינות של TCP, שאנחנו לא ממליצים עליה, משתמשים בפקודה הזו:
gcloud compute health-checks create tcp grpc-gke-helloworld-hc \ --use-serving-port
יוצרים את חומת האש. מוודאים שהערך של
--target-tagsזהה לערך שציינתם עבור--tagsבקטע יצירה או עדכון של אשכול GKE.gcloud compute firewall-rules create grpc-gke-allow-health-checks \ --network default --action allow --direction INGRESS \ --source-ranges 35.191.0.0/16,130.211.0.0/22 \ --target-tags allow-health-checks \ --rules tcp:50051-50052
יוצרים את שירות הקצה העורפי:
gcloud compute backend-services create grpc-gke-helloworld-service \ --global \ --load-balancing-scheme=INTERNAL_SELF_MANAGED \ --protocol=GRPC \ --health-checks grpc-gke-helloworld-hc
מצרפים את ה-NEG לשירות הקצה העורפי:
gcloud compute backend-services add-backend grpc-gke-helloworld-service \ --global \ --network-endpoint-group example-grpc-server \ --network-endpoint-group-zone ${ZONE} \ --balancing-mode RATE \ --max-rate-per-endpoint 5
יצירת משאבי Mesh ו-GRPCRoute
זה דומה לאופן שבו מגדירים את המשאבים Mesh ו-GRPCRoute במאמר הגדרת שירותי gRPC ללא שרת proxy.
יוצרים את המפרט
Meshושומרים אותו בקובץ בשםmesh.yaml.name: grpc-mesh
מייבאים את המשאב
Meshמהמפרט.gcloud network-services meshes import grpc-mesh \ --source=mesh.yaml \ --location=global
יוצרים את המפרט
GRPCRouteושומרים אותו בקובץ בשםgrpc_route.yaml.name: helloworld-grpc-route hostnames: - helloworld-gke:8000 meshes: - projects/PROJECT_NUMBER/locations/global/meshes/grpc-mesh rules: - action: destinations: - serviceName: projects/PROJECT_NUMBER/locations/global/backendServices/grpc-gke-helloworld-serviceמייבאים את המשאב
GRPCRouteמהמפרטgrpc_route.yaml.gcloud network-services grpc-routes import helloworld-grpc-route \ --source=grpc_route.yaml \ --location=global
הגדרת Cloud Service Mesh עם אבטחת gRPC ללא proxy
בדוגמה הזו נראה איך מגדירים mTLS בצד הלקוח ובצד השרת.
הפורמט של סימוכין בתקנון המדיניות
שימו לב לפורמט הנדרש הבא להפניה למדיניות TLS של שרת ולמדיניות TLS של לקוח:
projects/PROJECT_ID/locations/global/[serverTlsPolicies|clientTlsPolicies]/[server-tls-policy|client-mtls-policy]
לדוגמה:
projects/PROJECT_ID/locations/global/serverTlsPolicies/server-tls-policy
projects/PROJECT_ID/locations/global/clientTlsPolicies/client-mtls-policy
הגדרת mTLS בצד השרת
קודם יוצרים מדיניות TLS של שרת. המדיניות מבקשת מצד השרת של gRPC להשתמש בהגדרת התוסף certificateProvicerInstance שמזוהה לפי השם google_cloud_private_spiffe עבור אישור הזהות, שהוא חלק מ-serverCertificate. בקטע mtlsPolicy מצוינת אבטחת mTLS, והוא משתמש באותו google_cloud_private_spiffe כמו בהגדרת הפלאגין של clientValidationCa, שהוא מפרט אישור הבסיס (אימות).
בשלב הבא יוצרים מדיניות של נקודת קצה. ההגדרה הזו מציינת ששרת קצה עורפי, לדוגמה שרת gRPC, שמשתמש ביציאה 50051 עם תוויות מטא-נתונים כלשהן או ללא תוויות מטא-נתונים, מקבל את מדיניות ה-TLS של השרת המצורפת שנקראת server-mtls-policy. אפשר לציין תוויות של מטא-נתונים באמצעות MATCH_ALL או ערך נתמך. תוכלו למצוא את התוויות הנתמכות של המטא-נתונים בשדה endpointMatcher.metadataLabelMatcher.metadataLabelMatchCriteria במסמך NetworkServicesEndpointPolicy. יוצרים את מדיניות נקודת הקצה באמצעות קובץ זמני ep-mtls-psms.yaml שמכיל את הערכים של משאב מדיניות נקודת הקצה, על סמך המדיניות שכבר הגדרתם.
יוצרים קובץ זמני
server-mtls-policy.yamlבספרייה הנוכחית עם הערכים של משאב מדיניות ה-TLS של השרת:name: "projects/PROJECT_ID/locations/global/serverTlsPolicies/server-mtls-policy" serverCertificate: certificateProviderInstance: pluginInstance: google_cloud_private_spiffe mtlsPolicy: clientValidationCa: - certificateProviderInstance: pluginInstance: google_cloud_private_spiffeיוצרים משאב של מדיניות TLS בשרת בשם
server-mtls-policyעל ידי ייבוא של הקובץ הזמניserver-mtls-policy.yaml:gcloud network-security server-tls-policies import server-mtls-policy \ --source=server-mtls-policy.yaml --location=global
יוצרים את מדיניות נקודת הקצה על ידי יצירת הקובץ הזמני
ep-mtls-psms.yaml:name: "ep-mtls-psms" type: "GRPC_SERVER" serverTlsPolicy: "projects/PROJECT_ID/locations/global/serverTlsPolicies/server-mtls-policy" trafficPortSelector: ports: - "50051" endpointMatcher: metadataLabelMatcher: metadataLabelMatchCriteria: "MATCH_ALL" metadataLabels: - labelName: app labelValue: helloworldמייבאים את הקובץ
ep-mtls-psms.yamlכדי ליצור את משאב מדיניות נקודת הקצה:gcloud beta network-services endpoint-policies import ep-mtls-psms \ --source=ep-mtls-psms.yaml --location=global
הגדרת mTLS בצד הלקוח
מדיניות האבטחה בצד הלקוח מצורפת לשירות הקצה העורפי. כשלקוח ניגש לחלק האחורי (שרת gRPC) דרך שירות החלק האחורי, מדיניות האבטחה בצד הלקוח שמצורפת נשלחת ללקוח.
יוצרים את התוכן של משאב מדיניות TLS של הלקוח בקובץ זמני בשם
client-mtls-policy.yamlבספרייה הנוכחית:name: "client-mtls-policy" clientCertificate: certificateProviderInstance: pluginInstance: google_cloud_private_spiffe serverValidationCa: - certificateProviderInstance: pluginInstance: google_cloud_private_spiffeיוצרים את משאב מדיניות TLS של הלקוח שנקרא
client-mtls-policyעל ידי ייבוא של הקובץ הזמניclient-mtls-policy.yaml:gcloud network-security client-tls-policies import client-mtls-policy \ --source=client-mtls-policy.yaml --location=global
יוצרים קטע קוד בקובץ זמני כדי להפנות למדיניות הזו ומוסיפים פרטים לגבי
subjectAltNamesבהודעהSecuritySettingsכמו בדוגמה הבאה. מחליפים את${PROJECT_ID}בערך של מזהה הפרויקט, שהוא הערך של משתנה הסביבה${PROJECT_ID}שמתואר למעלה. שימו לב ש-example-grpc-serverב-subjectAltNamesהוא שם חשבון השירות של Kubernetes שמשמש את ה-Pod של שרת gRPC במפרט הפריסה.if [ -z "$PROJECT_ID" ] ; then echo Please make sure PROJECT_ID is set. ; fi cat << EOF > client-security-settings.yaml securitySettings: clientTlsPolicy: projects/${PROJECT_ID}/locations/global/clientTlsPolicies/client-mtls-policy subjectAltNames: - "spiffe://${PROJECT_ID}.svc.id.goog/ns/default/sa/example-grpc-server" EOFמוסיפים את ההודעה
securitySettingsלשירות לקצה העורפי שכבר יצרתם. בשלבים האלה מייצאים את התוכן הנוכחי של שירות ה-Backend, מוסיפים את ההודעה של הלקוחsecuritySettingומייבאים מחדש את התוכן החדש כדי לעדכן את שירות ה-Backend.gcloud compute backend-services export grpc-gke-helloworld-service --global \ --destination=/tmp/grpc-gke-helloworld-service.yaml cat /tmp/grpc-gke-helloworld-service.yaml client-security-settings.yaml \ >/tmp/grpc-gke-helloworld-service1.yaml gcloud compute backend-services import grpc-gke-helloworld-service --global \ --source=/tmp/grpc-gke-helloworld-service1.yaml -q
אימות ההגדרה
ההגדרה של Cloud Service Mesh הושלמה, כולל אבטחה בצד השרת ובצד הלקוח. בשלב הבא, מכינים ומריצים את עומסי העבודה של השרת והלקוח. כך מסיימים את הדוגמה.
יצירת לקוח gRPC ללא proxy
השלב הזה דומה לשלב הקודם יצירת שירות gRPC ללא proxy.
משתמשים בלקוח helloworld עם תמיכה ב-xDS מתוך ספריית הדוגמאות של xDS במאגר grpc-java. אתם יוצרים ומריצים את הלקוח בקונטיינר שנבנה מקובץ אימג' של openjdk:8-jdk. מפרט Kubernetes של לקוח gRPC מבצע את הפעולות הבאות.
- הוא יוצר חשבון שירות Kubernetes
example-grpc-clientשמשמש את ה-Pod של לקוח gRPC. -
${PROJNUM}מייצג את מספר הפרויקט שלכם, וצריך להחליף אותו במספר האמיתי.
מוסיפים את ההערה הבאה למפרט ה-Pod:
annotations:
security.cloud.google.com/use-workload-certificates: ""
בזמן היצירה, לכל פוד יש עוצמת קול בערך /var/run/secrets/workload-spiffe-credentials.
כרך זה מכיל את הפריטים הבאים:
-
private_key.pemהוא מפתח פרטי שנוצר באופן אוטומטי. -
certificates.pemהוא חבילה של אישורים בפורמט PEM שאפשר להציג ל-Pod אחר כשרשרת אישורי הלקוח, או להשתמש בה כשרשרת אישורי השרת. -
ca_certificates.pemהוא חבילה של אישורים בפורמט PEM שמשמשים כנקודות עוגן מהימנות כשמאמתים את שרשרת האישורים של הלקוח שמוצגת על ידי Pod אחר, או את שרשרת האישורים של השרת שמתקבלת כשמתחברים ל-Pod אחר.
שימו לב שהקובץ ca_certificates.pem מכיל את אישורי הבסיס של דומיין האמון המקומי של עומסי העבודה, שהוא מאגר עומסי העבודה של האשכול.
אישור העלה ב-certificates.pem מכיל את הצהרת הזהות הבאה ב-SPIFFE בטקסט פשוט:
spiffe://WORKLOAD_POOL/ns/NAMESPACE/sa/KUBERNETES_SERVICE_ACCOUNT
בטענה הזו:
- WORKLOAD_POOL הוא השם של מאגר זהויות של כוח העבודה של האשכול.
- NAMESPACE הוא השם של חשבון השירות של Kubernetes.
- KUBERNETES_SERVICE_ACCOUNT הוא מרחב השמות של חשבון השירות של Kubernetes.
ההוראות הבאות בשפה שלך יוצרות את המפרט לשימוש בדוגמה הזו.
Java
מריצים את הפקודה הבאה כדי לוודא שמספר הפרויקט מוגדר בצורה נכונה:
if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
יוצרים את המפרט הבא:
cat << EOF > example-grpc-client.yaml apiVersion: v1 kind: ServiceAccount metadata: name: example-grpc-client namespace: default annotations: iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com --- apiVersion: apps/v1 kind: Deployment metadata: name: example-grpc-client namespace: default labels: k8s-app: example-grpc-client spec: replicas: 1 selector: matchLabels: k8s-app: example-grpc-client strategy: {} template: metadata: annotations: security.cloud.google.com/use-workload-certificates: "" labels: k8s-app: example-grpc-client spec: containers: - image: openjdk:8-jdk imagePullPolicy: IfNotPresent name: example-grpc-client command: - /bin/sleep - inf env: - name: GRPC_XDS_BOOTSTRAP value: "/tmp/grpc-xds/td-grpc-bootstrap.json" resources: limits: cpu: 800m memory: 512Mi requests: cpu: 100m memory: 512Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/grpc-xds/ initContainers: - name: grpc-td-init image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.19.0 imagePullPolicy: Always args: - --config-mesh-experimental - "grpc-mesh" - --output - "/tmp/bootstrap/td-grpc-bootstrap.json" resources: limits: cpu: 100m memory: 100Mi requests: cpu: 10m memory: 100Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/bootstrap/ serviceAccountName: example-grpc-client volumes: - name: grpc-td-conf emptyDir: medium: Memory EOF
C++
מריצים את הפקודה הבאה כדי לוודא שמספר הפרויקט מוגדר בצורה נכונה:
if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
יוצרים את המפרט הבא:
cat << EOF > example-grpc-client.yaml apiVersion: v1 kind: ServiceAccount metadata: name: example-grpc-client namespace: default annotations: iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com --- apiVersion: apps/v1 kind: Deployment metadata: name: example-grpc-client namespace: default labels: k8s-app: example-grpc-client spec: replicas: 1 selector: matchLabels: k8s-app: example-grpc-client strategy: {} template: metadata: annotations: security.cloud.google.com/use-workload-certificates: "" labels: k8s-app: example-grpc-client spec: containers: - image: phusion/baseimage:18.04-1.0.0 imagePullPolicy: IfNotPresent name: example-grpc-client command: - /bin/sleep - inf env: - name: GRPC_XDS_BOOTSTRAP value: "/tmp/grpc-xds/td-grpc-bootstrap.json" resources: limits: cpu: 8 memory: 8Gi requests: cpu: 300m memory: 512Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/grpc-xds/ initContainers: - name: grpc-td-init image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.19.0 imagePullPolicy: Always args: - --config-mesh-experimental - "grpc-mesh" - --output - "/tmp/bootstrap/td-grpc-bootstrap.json" resources: limits: cpu: 100m memory: 100Mi requests: cpu: 10m memory: 100Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/bootstrap/ serviceAccountName: example-grpc-client volumes: - name: grpc-td-conf emptyDir: medium: Memory EOF
Python
מריצים את הפקודה הבאה כדי לוודא שמספר הפרויקט מוגדר בצורה נכונה:
if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
יוצרים את המפרט הבא:
cat << EOF > example-grpc-client.yaml apiVersion: v1 kind: ServiceAccount metadata: name: example-grpc-client namespace: default annotations: iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com --- apiVersion: apps/v1 kind: Deployment metadata: name: example-grpc-client namespace: default labels: k8s-app: example-grpc-client spec: replicas: 1 selector: matchLabels: k8s-app: example-grpc-client strategy: {} template: metadata: annotations: security.cloud.google.com/use-workload-certificates: "" labels: k8s-app: example-grpc-client spec: containers: - image: phusion/baseimage:18.04-1.0.0 imagePullPolicy: IfNotPresent name: example-grpc-client command: - /bin/sleep - inf env: - name: GRPC_XDS_BOOTSTRAP value: "/tmp/grpc-xds/td-grpc-bootstrap.json" resources: limits: cpu: 8 memory: 8Gi requests: cpu: 300m memory: 512Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/grpc-xds/ initContainers: - name: grpc-td-init image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.19.0 imagePullPolicy: Always args: - --config-mesh-experimental - "grpc-mesh" - --output - "/tmp/bootstrap/td-grpc-bootstrap.json" resources: limits: cpu: 100m memory: 100Mi requests: cpu: 10m memory: 100Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/bootstrap/ serviceAccountName: example-grpc-client volumes: - name: grpc-td-conf emptyDir: medium: Memory EOF
המשך
מריצים את הפקודה הבאה כדי לוודא שמספר הפרויקט מוגדר בצורה נכונה:
if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
יוצרים את המפרט הבא:
cat << EOF > example-grpc-client.yaml apiVersion: v1 kind: ServiceAccount metadata: name: example-grpc-client namespace: default annotations: iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com --- apiVersion: apps/v1 kind: Deployment metadata: name: example-grpc-client namespace: default labels: k8s-app: example-grpc-client spec: replicas: 1 selector: matchLabels: k8s-app: example-grpc-client strategy: {} template: metadata: annotations: security.cloud.google.com/use-workload-certificates: "" labels: k8s-app: example-grpc-client spec: containers: - image: golang:1.16-alpine imagePullPolicy: IfNotPresent name: example-grpc-client command: - /bin/sleep - inf env: - name: GRPC_XDS_BOOTSTRAP value: "/tmp/grpc-xds/td-grpc-bootstrap.json" resources: limits: cpu: 8 memory: 8Gi requests: cpu: 300m memory: 512Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/grpc-xds/ initContainers: - name: grpc-td-init image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.19.0 imagePullPolicy: Always args: - --config-mesh-experimental - "grpc-mesh" - --output - "/tmp/bootstrap/td-grpc-bootstrap.json" resources: limits: cpu: 100m memory: 100Mi requests: cpu: 10m memory: 100Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/bootstrap/ serviceAccountName: example-grpc-client volumes: - name: grpc-td-conf emptyDir: medium: Memory EOF
כך משלימים את התהליך.
החלת המפרט:
kubectl apply -f example-grpc-client.yaml
מקצים לחשבון השירות את התפקידים הנדרשים:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:${PROJECT_ID}.svc.id.goog[default/example-grpc-client]" \ ${PROJNUM}-compute@developer.gserviceaccount.com gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member "serviceAccount:${PROJECT_ID}.svc.id.goog[default/example-grpc-client]" \ --role roles/trafficdirector.clientמוודאים ש-Pod הלקוח פועל:
kubectl get pods
הפקודה מחזירה טקסט שדומה לזה:
NAMESPACE NAME READY STATUS RESTARTS AGE default example-grpc-client-7c969bb997-9fzjv 1/1 Running 0 104s [..skip..]
הפעלת השרת
מבצעים build ומריצים את שרת helloworld עם תמיכה ב-xDS ב-Pod של השרת שיצרתם קודם.
Java
כדי לקבל את השם של ה-Pod שנוצר עבור השירות
example-grpc-server:kubectl get pods | grep example-grpc-server
יוצג משוב כמו:
default example-grpc-server-77548868d-l9hmf 1/1 Running 0 105s
פותחים מעטפת ל-Pod של השרת:
kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/bash
במעטפת, מוודאים שקובץ האתחול בנתיב
/tmp/grpc-xds/td-grpc-bootstrap.jsonתואם לסכימה שמתוארת בקטע קובץ האתחול.מורידים את gRPC Java גרסה 1.42.1 ויוצרים את אפליקציית השרת
xds-hello-world.curl -L https://github.com/grpc/grpc-java/archive/v1.42.1.tar.gz | tar -xz cd grpc-java-1.42.1/examples/example-xds ../gradlew --no-daemon installDist
מריצים את השרת עם הדגל
--xds-credsכדי לציין אבטחה עם xDS, באמצעות50051כיציאת ההאזנה ו-xds-serverכשם הזיהוי של השרת:./build/install/example-xds/bin/xds-hello-world-server --xds-creds 50051 xds-server
אחרי שהשרת מקבל את ההגדרה הנדרשת מ-Cloud Service Mesh, מוצגת הפלט הבא:
Listening on port 50051 plain text health service listening on port 50052
C++
כדי לקבל את השם של ה-Pod שנוצר עבור השירות
example-grpc-server:kubectl get pods | grep example-grpc-server
יוצג משוב כמו:
default example-grpc-server-77548868d-l9hmf 1/1 Running 0 105s
פותחים מעטפת ל-Pod של השרת:
kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/bash
במעטפת, מוודאים שקובץ האתחול בנתיב
/tmp/grpc-xds/td-grpc-bootstrap.jsonתואם לסכימה שמתוארת בקטע קובץ האתחול.מורידים את gRPC C++ ומפתחים את אפליקציית השרת
xds-hello-world.apt-get update -y && \ apt-get install -y \ build-essential \ clang \ python3 \ python3-dev curl -L https://github.com/grpc/grpc/archive/master.tar.gz | tar -xz cd grpc-master tools/bazel build examples/cpp/helloworld:xds_greeter_serverמריצים את השרת באמצעות
50051כיציאת ההאזנה, ו-xds_greeter_serverכשם הזיהוי של השרת:bazel-bin/examples/cpp/helloworld/xds_greeter_server --port=50051 --maintenance_port=50052 --secure
כדי להריץ את השרת בלי פרטי כניסה, אפשר לציין את הפרטים הבאים:
bazel-bin/examples/cpp/helloworld/xds_greeter_server --nosecure
אחרי שהשרת מקבל את ההגדרה הנדרשת מ-Cloud Service Mesh, מוצגת הפלט הבא:
Listening on port 50051 plain text health service listening on port 50052
Python
כדי לקבל את השם של ה-Pod שנוצר עבור השירות
example-grpc-server:kubectl get pods | grep example-grpc-server
יוצג משוב כמו:
default example-grpc-server-77548868d-l9hmf 1/1 Running 0 105s
פותחים מעטפת ל-Pod של השרת:
kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/bash
במעטפת, מוודאים שקובץ האתחול בנתיב
/tmp/grpc-xds/td-grpc-bootstrap.jsonתואם לסכימה שמתוארת בקטע קובץ האתחול.מורידים את gRPC Python בגרסה 1.41.0 ויוצרים את האפליקציה לדוגמה.
apt-get update -y
apt-get install -y python3 python3-pip
curl -L https://github.com/grpc/grpc/archive/v1.41.x.tar.gz | tar -xz
cd grpc-1.41.x/examples/python/xds/
python3 -m virtualenv venv
source venv/bin/activate
python3 -m pip install -r requirements.txt
מריצים את השרת עם הדגל
--xds-credsכדי לציין אבטחה עם xDS, באמצעות50051כפורט ההאזנה.python3 server.py 50051 --xds-creds
אחרי שהשרת מקבל את ההגדרה הנדרשת מ-Cloud Service Mesh, מוצגת הפלט הבא:
2021-05-06 16:10:34,042: INFO Running with xDS Server credentials 2021-05-06 16:10:34,043: INFO Greeter server listening on port 50051 2021-05-06 16:10:34,046: INFO Maintenance server listening on port 50052
המשך
כדי לקבל את השם של ה-Pod שנוצר עבור השירות
example-grpc-server:kubectl get pods | grep example-grpc-server
יוצג משוב כמו:
default example-grpc-server-77548868d-l9hmf 1/1 Running 0 105s
פותחים מעטפת ל-Pod של השרת:
kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/sh
במעטפת, מוודאים שקובץ האתחול בנתיב
/tmp/grpc-xds/td-grpc-bootstrap.jsonתואם לסכימה שמתוארת בקטע קובץ האתחול.מורידים את gRPC Go בגרסה 1.41.0 ועוברים אל הספרייה שמכילה את אפליקציית השרת
xds-hello-world.apk add curl curl -L https://github.com/grpc/grpc-go/archive/v1.42.0.tar.gz | tar -xz cd grpc-go-1.42.0/examples/features/xds/server
מריצים את השרת עם הדגל
--xds_credsכדי לציין אבטחה עם xDS, באמצעות50051כיציאת ההאזנה:GRPC_GO_LOG_VERBOSITY_LEVEL=2 GRPC_GO_LOG_SEVERITY_LEVEL="info" \ go run main.go \ -xds_creds \ -port 50051
אחרי שהשרת מקבל את ההגדרה הנדרשת מ-Cloud Service Mesh, מוצגת הפלט הבא:
Using xDS credentials... Serving GreeterService on 0.0.0.0:50051 and HealthService on 0.0.0.0:50052
תהליך בדיקת התקינות נמשך 3 עד 5 דקות עד שמוצג שהשירות תקין אחרי הפעלת השרת.
מריצים את הלקוח ומאמתים את ההגדרה
יוצרים ומריצים את לקוח helloworld עם תמיכה ב-xDS בפוד של הלקוח שיצרתם קודם.
Java
משיגים את השם של ה-Pod של הלקוח:
kubectl get pods | grep example-grpc-client
מוצג לכם משוב כזה:
default example-grpc-client-7c969bb997-9fzjv 1/1 Running 0 105s
פותחים מעטפת ל-Pod של הלקוח:
kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
במעטפת הפקודות, מורידים את gRPC Java גרסה 1.42.1 ויוצרים את אפליקציית הלקוח
xds-hello-world.curl -L https://github.com/grpc/grpc-java/archive/v1.42.1.tar.gz | tar -xz cd grpc-java-1.42.1/examples/example-xds ../gradlew --no-daemon installDist
מריצים את הלקוח עם הסימון
--xds-credsכדי לציין אבטחה עם xDS, שם לקוח ומחרוזת חיבור ליעד:./build/install/example-xds/bin/xds-hello-world-client --xds-creds xds-client \ xds:///helloworld-gke:8000הפלט אמור להיראות כך:
Greeting: Hello xds-client, from xds-server
C++
משיגים את השם של ה-Pod של הלקוח:
kubectl get pods | grep example-grpc-client
מוצג לכם משוב כזה:
default example-grpc-client-7c969bb997-9fzjv 1/1 Running 0 105s
פותחים מעטפת ל-Pod של הלקוח:
kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
אחרי שנכנסים למעטפת, מורידים את gRPC C++ ויוצרים את אפליקציית הלקוח
xds-hello-world.apt-get update -y && \ apt-get install -y \ build-essential \ clang \ python3 \ python3-devcurl -L https://github.com/grpc/grpc/archive/master.tar.gz | tar -xz
cd grpc-master
tools/bazel build examples/cpp/helloworld:xds_greeter_client
מריצים את הלקוח עם הסימון
--xds-credsכדי לציין אבטחה עם xDS, שם לקוח ומחרוזת חיבור ליעד:bazel-bin/examples/cpp/helloworld/xds_greeter_client --target=xds:///helloworld-gke:8000
כדי להריץ את הלקוח ללא פרטי כניסה, משתמשים בפקודה הבאה:
bazel-bin/examples/cpp/helloworld/xds_greeter_client --target=xds:///helloworld-gke:8000 --nosecure
הפלט אמור להיראות כך:
Greeter received: Hello world
Python
משיגים את השם של ה-Pod של הלקוח:
kubectl get pods | grep example-grpc-client
מוצג לכם משוב כזה:
default example-grpc-client-7c969bb997-9fzjv 1/1 Running 0 105s
פותחים מעטפת ל-Pod של הלקוח:
kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
אחרי שנכנסים למעטפת, מורידים את gRPC Python בגרסה 1.41.0 ויוצרים את אפליקציית הלקוח לדוגמה.
apt-get update -y apt-get install -y python3 python3-pip python3 -m pip install virtualenv curl -L https://github.com/grpc/grpc/archive/v1.41.x.tar.gz | tar -xz cd grpc-1.41.x/examples/python/xds/ python3 -m virtualenv venv source venv/bin/activate python3 -m pip install -r requirements.txt
מריצים את הלקוח עם הסימון
--xds-credsכדי לציין אבטחה עם xDS, שם לקוח ומחרוזת חיבור ליעד:python3 client.py xds:///helloworld-gke:8000 --xds-creds
הפלט אמור להיראות כך:
Greeter client received: Hello you from example-host!
המשך
משיגים את השם של ה-Pod של הלקוח:
kubectl get pods | grep example-grpc-client
מוצג לכם משוב כזה:
default example-grpc-client-7c969bb997-9fzjv 1/1 Running 0 105s
פותחים מעטפת ל-Pod של הלקוח:
kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/sh
אחרי שנכנסים למעטפת, מורידים את gRPC Go גרסה 1.42.0 ועוברים לספרייה שמכילה את אפליקציית הלקוח
xds-hello-world.apk add curl curl -L https://github.com/grpc/grpc-go/archive/v1.42.0.tar.gz | tar -xz cd grpc-go-1.42.0/examples/features/xds/client
מבצעים build והרצה של הלקוח עם הסימון
--xds_credsכדי לציין אבטחה עם הפעלת xDS, שם לקוח ומחרוזת חיבור ליעד:GRPC_GO_LOG_VERBOSITY_LEVEL=2 GRPC_GO_LOG_SEVERITY_LEVEL="info" \ go run main.go \ -xds_creds \ -name xds-client \ -target xds:///helloworld-gke:8000
הפלט אמור להיראות כך:
Greeting: Hello xds-client, from example-grpc-server-77548868d-l9hmf
הגדרת גישה ברמת השירות באמצעות מדיניות הרשאות
כדי לתמוך במדיניות הרשאות, צריך לתמוך ב-gRFC A41. אפשר למצוא את הגרסאות בשפות הנדרשות ב-github
במאמר הזה מוסבר איך להגדיר גישה ברמת השירות באמצעות מדיניות הרשאות. לפני שיוצרים מדיניות הרשאות, חשוב לקרוא את האזהרה במאמר הגבלת הגישה באמצעות הרשאות.
כדי להקל על אימות ההגדרה, יוצרים שם מארח נוסף שהלקוח יכול להשתמש בו כדי להתייחס לשירות helloworld-gke.
עדכון המפרט
GRPCRouteשאוחסן בעבר ב-grpc_route.yamlname: helloworld-grpc-route hostnames: - helloworld-gke:8000 - helloworld-gke-noaccess:8000 meshes: - projects/PROJECT_NUMBER/locations/global/meshes/grpc-mesh rules: - action: destinations: - serviceName: projects/PROJECT_NUMBER/locations/global/backendServices/grpc-gke-helloworld-serviceמייבאים שוב את המשאב
GRPCRouteמהמפרטgrpc_route.yaml.gcloud network-services grpc-routes import helloworld-grpc-route \ --source=grpc_route.yaml \ --location=global
ההוראות הבאות יוצרות מדיניות הרשאות שמאפשרת בקשות שנשלחות מחשבון example-grpc-client שבו שם המארח הוא helloworld-gke:8000 והיציאה היא 50051.
gcloud
יוצרים מדיניות הרשאות על ידי יצירת קובץ בשם
helloworld-gke-authz-policy.yaml.action: ALLOW name: helloworld-gke-authz-policy rules: - sources: - principals: - spiffe://PROJECT_ID.svc.id.goog/ns/default/sa/example-grpc-client destinations: - hosts: - helloworld-gke:8000 ports: - 50051מייבאים את המדיניות.
gcloud network-security authorization-policies import \ helloworld-gke-authz-policy \ --source=helloworld-gke-authz-policy.yaml \ --location=global
מעדכנים את מדיניות נקודת הקצה כך שתפנה למדיניות ההרשאות החדשה על ידי הוספת השורה הבאה לקובץ
ep-mtls-psms.yaml.authorizationPolicy: projects/${PROJECT_ID}/locations/global/authorizationPolicies/helloworld-gke-authz-policyבמדיניות של נקודת הקצה מצוין עכשיו שצריך לאכוף גם mTLS וגם את מדיניות ההרשאה בבקשות נכנסות ל-Pods שקבצי ה-bootstrap של gRPC שלהם מכילים את התווית
app:helloworld.מייבאים את המדיניות:
gcloud network-services endpoint-policies import ep-mtls-psms \ --source=ep-mtls-psms.yaml --location=global
אימות מדיניות ההרשאות
כדי לוודא שמדיניות ההרשאות פועלת בצורה תקינה, פועלים לפי ההוראות הבאות.
Java
פותחים מעטפת (shell) ל-pod של הלקוח שבו השתמשתם קודם.
kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
במעטפת הפקודות, מריצים את הפקודות הבאות כדי לאמת את ההגדרה.
cd grpc-java-1.42.1/examples/example-xds ./build/install/example-xds/bin/xds-hello-world-client --xds-creds xds-client \ xds:///helloworld-gke:8000הפלט אמור להיראות כך:
Greeting: Hello xds-client, from xds-server
מריצים את הלקוח שוב עם שם השרת החלופי. שימו לב שזהו מקרה של כשל. הבקשה לא חוקית כי מדיניות ההרשאה מאפשרת גישה רק לשם המארח
helloworld-gke:8000../build/install/example-xds/bin/xds-hello-world-client --xds-creds xds-client \ xds:///helloworld-gke-noaccess:8000הפלט אמור להיראות כך:
WARNING: RPC failed: Status{code=PERMISSION_DENIED}אם הפלט הזה לא מופיע, יכול להיות שמדיניות ההרשאות עדיין לא בשימוש. צריך לחכות כמה דקות ולנסות שוב את כל תהליך האימות.
המשך
פותחים מעטפת (shell) ל-pod של הלקוח שבו השתמשתם קודם.
kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
במעטפת הפקודות, מריצים את הפקודות הבאות כדי לאמת את ההגדרה.
cd grpc-go-1.42.0/examples/features/xds/client GRPC_GO_LOG_VERBOSITY_LEVEL=2 GRPC_GO_LOG_SEVERITY_LEVEL="info" \ go run main.go \ -xds_creds \ -name xds-client \ -target xds:///helloworld-gke:8000
הפלט אמור להיראות כך:
Greeting: Hello xds-client, from example-grpc-server-77548868d-l9hmf
מריצים את הלקוח שוב עם שם השרת החלופי. שימו לב שזהו מקרה של כשל. הבקשה לא חוקית כי מדיניות ההרשאה מאפשרת גישה רק לשם המארח
helloworld-gke:8000.GRPC_GO_LOG_VERBOSITY_LEVEL=2 GRPC_GO_LOG_SEVERITY_LEVEL="info" \ go run main.go \ -xds_creds \ -name xds-client \ -target xds:///helloworld-gke-noaccess:8000
הפלט אמור להיראות כך:
could not greet: rpc error: code = PermissionDenied desc = Incoming RPC is not allowed: rpc error: code = PermissionDenied desc = incoming RPC did not match an allow policy exit status 1
אם הפלט הזה לא מופיע, יכול להיות שמדיניות ההרשאות עדיין לא בשימוש. צריך לחכות כמה דקות ולנסות שוב את כל תהליך האימות.
שימוש ב-TLS במקום ב-mTLS
כדי להשתמש ב-TLS בדוגמה הזו נדרש שינוי קטן בלבד.
ב-
ServerTlsPolicy, מחליפים אתmtlsPolicy:cat << EOF > server-tls-policy.yaml name: "server-tls-policy" serverCertificate: certificateProviderInstance: pluginInstance: google_cloud_private_spiffe EOFבמקומה, צריך להשתמש במדיניות הזו ב-
EndpointPolicy:cat << EOF > ep-tls-psms.yaml name: "ep-mtls-psms" type: "GRPC_SERVER" serverTlsPolicy: "projects/${PROJECT_ID}/locations/global/serverTlsPolicies/server-tls-policy" trafficPortSelector: ports: - "50051" endpointMatcher: metadataLabelMatcher: metadataLabelMatchCriteria: "MATCH_ALL" metadataLabels: [] EOFההגדרה
ClientTlsPolicyשל mTLS פועלת גם במקרה של TLS, אבל אפשר להשמיט את הקטעclientCertificateבמדיניות כי הוא לא נדרש ל-TLS:cat << EOF > client-tls-policy.yaml name: "client-tls-policy" serverValidationCa: - certificateProviderInstance: pluginInstance: google_cloud_private_spiffe EOF
שימוש באבטחת שירות עם הדוגמה של Wallet
בקטע הזה מפורטת סקירה כללית על הפעלת הדוגמה של Wallet עם אבטחת שירות, ב-Java, ב-C++ וב-Go.
Java
אפשר למצוא את קוד המקור לדוגמה של Java ב-github.
הקוד כבר משתמש בפרטי הכניסה של XdsChannel ושל XdsServer כשמגדירים אבטחה ללא שרת proxy.
בהוראות האלה מוסבר איך להגדיר את הדוגמה של Wallet באמצעות Go. התהליך דומה לזה של Java. ההוראות מתייחסות לתמונת Docker קיימת שמתקבלת ממאגר התמונות שלGoogle Cloud .
כדי ליצור את הדוגמה, פועלים לפי ההוראות הבאות:
- משכפלים את מאגר הקוד ומקבלים את הקבצים בספרייה gRPC examples.
- עורכים את הקובץ
00-common-env.sh. מוסיפים הערה לשורה הקיימת שקובעת את הערך שלWALLET_DOCKER_IMAGEלתמונת Go Docker, ומבטלים את ההערה בשורה שקובעת את הערך שלWALLET_DOCKER_IMAGEלתמונת Java Docker. - יוצרים ומגדירים מופעים של Cloud Router לפי ההוראות שבמאמר יצירה והגדרה של מופעים של Cloud Router או באמצעות הפונקציה
create_cloud_router_instancesבסקריפט10.apis.sh. - יוצרים אשכול באמצעות ההוראות לדוגמה
hello worldאו הפונקציהcreate_clusterבסקריפט20-cluster.sh. - יוצרים רשויות אישורים פרטיות באמצעות ההוראות ל-CA Service או באמצעות הסקריפט
30-private-ca-setup.sh. - יצירת משאבי Kubernetes, כולל חשבונות שירות, מרחבי שמות, שירותי Kubernetes, קבוצות נקודות קצה ברשת (NEGs) ופריסה בצד השרת לכל השירותים:
account,stats,stats_premium,wallet_v1,wallet_v2, באמצעות הסקריפט40-k8s-resources.sh. - לכל אחד מהשירותים שיצרתם, יוצרים בדיקת תקינות ושירות קצה עורפי באמצעות
create_health_checkו-create_backend_serviceבסקריפט50-td-components.sh. - יוצרים את רכיבי הניתוב של Cloud Service Mesh באמצעות
create_routing_componentsבסקריפט60-routing-components.sh. - יוצרים את רכיבי האבטחה של Cloud Service Mesh לכל שירות לקצה העורפי באמצעות
create_security_componentsבסקריפט70-security-components.sh. - יוצרים את פריסת לקוח Wallet באמצעות
create_client_deploymentבסקריפט75-client-deployment.sh. - כדי לאמת את ההגדרה, מפעילים את הלקוח כמו שמתואר במאמר בנושא אימות באמצעות לקוחות grpc-wallet.
C++
קוד המקור לדוגמה ל-C++ זמין ב-github. הקוד כבר משתמש בפרטי הכניסה XdsChannel ו-XdsServer כשמגדירים אבטחה ללא שרת proxy.
בהוראות האלה מתואר איך להגדיר את הדוגמה של Wallet באמצעות Go. התהליך דומה ל-C++. ההוראות מתייחסות לתמונת Docker קיימת מראש שאפשר לקבל ממאגר המכולות שלGoogle Cloud .
כדי ליצור את הדוגמה, פועלים לפי ההוראות הבאות:
- משכפלים את מאגר הקוד ומקבלים את הקבצים בספרייה gRPC examples.
- עורכים את הקובץ
00-common-env.sh. מוסיפים הערה לשורה הקיימת שקובעת את הערך שלWALLET_DOCKER_IMAGEלקובץ האימג' של Go Docker ומבטלים את ההערה בשורה שקובעת את הערך שלWALLET_DOCKER_IMAGEלקובץ האימג' של C++ Docker. - יוצרים ומגדירים מופעים של Cloud Router לפי ההוראות שבמאמר יצירה והגדרה של מופעים של Cloud Router או באמצעות הפונקציה
create_cloud_router_instancesבסקריפט10.apis.sh. - יוצרים אשכול באמצעות ההוראות לדוגמה
hello worldאו הפונקציהcreate_clusterבסקריפט20-cluster.sh. - יצירת רשויות אישורים פרטיות באמצעות ההוראות לשימוש בשירות CA
או באמצעות הסקריפט
30-private-ca-setup.sh. - יצירת משאבי Kubernetes, כולל חשבונות שירות, מרחבי שמות, שירותי Kubernetes, קבוצות נקודות קצה ברשת (NEGs) ופריסה בצד השרת לכל השירותים:
account,stats,stats_premium,wallet_v1,wallet_v2, באמצעות הסקריפט40-k8s-resources.sh. - לכל אחד מהשירותים שיצרתם, יוצרים בדיקת תקינות ושירות קצה עורפי באמצעות
create_health_checkו-create_backend_serviceבסקריפט50-td-components.sh. - יוצרים את רכיבי הניתוב של Cloud Service Mesh באמצעות
create_routing_componentsבסקריפט60-routing-components.sh. - יוצרים את רכיבי האבטחה של Cloud Service Mesh לכל שירות לקצה העורפי באמצעות
create_security_componentsבסקריפט70-security-components.sh. - יוצרים את פריסת לקוח Wallet באמצעות
create_client_deploymentבסקריפט75-client-deployment.sh. - כדי לאמת את ההגדרה, מפעילים את הלקוח כמו שמתואר במאמר בנושא אימות באמצעות לקוחות grpc-wallet.
המשך
קוד מקור לדוגמה ל-Go זמין ב-github. הקוד כבר משתמש בפרטי הכניסה של XdsChannel
ושלXdsServer כשמגדירים אבטחה ללא שרת proxy.
ההוראות מתייחסות לקובץ אימג' קיים של Docker שמתקבל מGoogle Cloud מאגר הקונטיינרים.
כדי ליצור את הדוגמה, פועלים לפי ההוראות הבאות:
- משכפלים את מאגר הקוד ומקבלים את הקבצים בספרייה gRPC examples.
- עורכים את הקובץ
00-common-env.shכדי להגדיר את הערכים הנכונים למשתני הסביבה. - יוצרים ומגדירים מופעים של Cloud Router לפי ההוראות שבמאמר יצירה והגדרה של מופעים של Cloud Router או באמצעות הפונקציה
create_cloud_router_instancesבסקריפט10.apis.sh. - יוצרים אשכול באמצעות ההוראות לדוגמה
hello worldאו הפונקציהcreate_clusterבסקריפט20-cluster.sh. - יוצרים רשויות אישורים פרטיות באמצעות ההוראות ל-CA Service או באמצעות הסקריפט
30-private-ca-setup.sh. - יצירת משאבי Kubernetes, כולל חשבונות שירות, מרחבי שמות, שירותי Kubernetes, קבוצות נקודות קצה ברשת (NEGs) ופריסה בצד השרת לכל השירותים:
account,stats,stats_premium,wallet_v1,wallet_v2, באמצעות הסקריפט40-k8s-resources.sh. - לכל אחד מהשירותים שיצרתם, יוצרים בדיקת תקינות ושירות קצה עורפי באמצעות
create_health_checkו-create_backend_serviceבסקריפט50-td-components.sh. - יוצרים את רכיבי הניתוב של Cloud Service Mesh באמצעות
create_routing_componentsבסקריפט60-routing-components.sh. - יוצרים את רכיבי האבטחה של Cloud Service Mesh לכל שירות לקצה העורפי באמצעות
create_security_componentsבסקריפט70-security-components.sh. - יוצרים את פריסת לקוח Wallet באמצעות
create_client_deploymentבסקריפט75-client-deployment.sh. - כדי לאמת את ההגדרה, מפעילים את הלקוח כמו שמתואר במאמר בנושא אימות באמצעות לקוחות grpc-wallet.
קובץ Bootstrap
תהליך ההגדרה במדריך הזה משתמש במחולל bootstrap כדי ליצור את קובץ ה-bootstrap הנדרש. בקטע הזה מפורט מידע על קובץ ה-bootstrap עצמו.
קובץ ה-bootstrap מכיל פרטי תצורה שנדרשים לקוד של gRPC בלי שרת Proxy, כולל פרטי חיבור לשרת xDS. קובץ ה-bootstrap מכיל הגדרות אבטחה שנדרשות לתכונת האבטחה של gRPC ללא proxy. שרת ה-gRPC דורש שדה נוסף. קובץ bootstrap לדוגמה נראה כך:
{
"xds_servers": [
{
"server_uri": "trafficdirector.googleapis.com:443",
"channel_creds": [
{
"type": "google_default"
}
],
"server_features": [
"xds_v3"
]
}
],
"authorities": {
"traffic-director-c2p.xds.googleapis.com": {
"xds_servers": [
{
"server_uri": "dns:///directpath-pa.googleapis.com",
"channel_creds": [
{
"type": "google_default"
}
],
"server_features": [
"xds_v3",
"ignore_resource_deletion"
]
}
],
"client_listener_resource_name_template": "xdstp://traffic-director-c2p.xds.googleapis.com/envoy.config.listener.v3.Listener/%s"
}
},
"node": {
"id": "projects/9876012345/networks/mesh:grpc-mesh/nodes/b59f49cc-d95a-4462-9126-112f794d5dd3",
"cluster": "cluster",
"metadata": {
"INSTANCE_IP": "10.28.2.8",
"TRAFFICDIRECTOR_DIRECTPATH_C2P_IPV6_CAPABLE": true,
"TRAFFICDIRECTOR_GCP_PROJECT_NUMBER": "223606568246",
"TRAFFICDIRECTOR_NETWORK_NAME": "default",
"app": "helloworld"
},
"locality": {
"zone": "us-central1-c"
}
},
"certificate_providers": {
"google_cloud_private_spiffe": {
"plugin_name": "file_watcher",
"config": {
"certificate_file": "/var/run/secrets/workload-spiffe-credentials/certificates.pem",
"private_key_file": "/var/run/secrets/workload-spiffe-credentials/private_key.pem",
"ca_certificate_file": "/var/run/secrets/workload-spiffe-credentials/ca_certificates.pem",
"refresh_interval": "600s"
}
}
},
"server_listener_resource_name_template": "grpc/server?xds.resource.listening_address=%s"
}
עדכונים בקובץ האתחול של שירות האבטחה
השדות הבאים משקפים שינויים שקשורים לאבטחה ולשימוש ב-xDS v3:
השדה id בתוך node מספק זהות ייחודית ללקוח gRPC ב-Cloud Service Mesh. צריך לספק את מספר הפרויקט ואת שם הרשת באמצעות מזהה הצומת בפורמט הבא: Google Cloud
projects/{project number}/networks/{network name}/nodes/[UNIQUE_ID]
דוגמה למספר פרויקט 1234 ולרשת ברירת המחדל:
projects/1234/networks/default/nodes/client1
השדה INSTANCE_IP הוא כתובת ה-IP של ה-Pod, או 0.0.0.0 כדי לציין INADDR_ANY. השדה הזה משמש את שרת ה-gRPC לאחזור משאב Listener מ-Cloud Service Mesh לצורך אבטחה בצד השרת.
שדות של הגדרות אבטחה בקובץ האתחול
| מפתח JSON | סוג | ערך | הערות |
|---|---|---|---|
server_listener_resource_name_template |
String | grpc/server?xds.resource.listening_address=%s |
נדרש לשרתי gRPC. מערכת gRPC משתמשת בערך הזה כדי ליצור את שם המשאב לצורך אחזור המשאב Listener מ-Cloud Service Mesh לאבטחה בצד השרת ולהגדרות אחרות. מערכת gRPC משתמשת בערך הזה כדי ליצור את מחרוזת שם המשאב |
certificate_providers |
מבנה JSON | google_cloud_private_spiffe |
חובה. הערך הוא מבנה JSON שמייצג מיפוי של שמות למופעים של ספקי אישורים. מופע של ספק אישורים משמש לאחזור זהויות ואישורי שורש. קובץ ה-bootstrap לדוגמה מכיל שם אחד: google_cloud_private_spiffe עם מבנה JSON של מופע ספק האישורים כערך. כל מבנה JSON של מופע של ספק אישורים כולל שני שדות:
|
התוכן של מבנה ה-JSON config של התוסף file_watcher הוא:
-
certificate_file: מחרוזת חובה. הערך הזה הוא המיקום של אישור הזהות. -
private_key_file: מחרוזת חובה. הערך הוא המיקום של קובץ המפתח הפרטי, שצריך להיות זהה לאישור הזהות. -
ca_certificate_file: מחרוזת חובה. הערך הוא המיקום של אישור הבסיס, שנקרא גם חבילת האמון. -
refresh_interval: מחרוזת אופציונלית. הערך מציין את מרווח הרענון, שמוגדר באמצעות ייצוג המחרוזת של מיפוי JSON של משך זמן. ערך ברירת המחדל הוא '600s', כלומר משך זמן של 10 דקות.
מחולל Bootstrap
קובץ האימג' של הקונטיינר של גנרטור ה-bootstrap זמין בכתובת
gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.19.0. קוד המקור שלו זמין בכתובת https://github.com/GoogleCloudPlatform/traffic-director-grpc-bootstrap.
אלה האפשרויות הנפוצות ביותר של שורת הפקודה:
-
--output: משתמשים באפשרות הזו כדי לציין לאן ייכתב קובץ האתחול של הפלט. לדוגמה, הפקודה--output /tmp/bootstrap/td-grpc-bootstrap.jsonיוצרת את קובץ האתחול ב-/tmp/bootstrap/td-grpc-bootstrap.jsonבמערכת הקבצים של ה-Pod. -
--config-mesh-experimental: משתמשים באפשרות הזו כדי לציין את שם הרשת, שצריך להיות זהה למשאבMesh. -
--node-metadata: משתמשים בדגל הזה כדי לאכלס את המטא-נתונים של הצומת בקובץ האתחול. ההגדרה הזו נדרשת כשמשתמשים ב-EndpointPolicyבמתאמי תוויות של מטא-נתונים, שבהם Cloud Service Mesh משתמש בנתוני התוויות שמופיעים בקטע של מטא-נתוני הצומת בקובץ האתחול. הארגומנט מסופק בפורמט key=value, לדוגמה:--node-metadata version=prod --node-metadata type=grpc
הפרטים הקודמים מוסיפים את השורות הבאות לקטע המטא-נתונים של הצומת בקובץ ה-bootstrap:
{
"node": {
...
"metadata": {
"version": "prod",
"type": "grpc",
...
},
...
},
...
}
מחיקת הפריסה
אפשר גם להריץ את הפקודות האלה כדי למחוק את הפריסה שיצרתם באמצעות המדריך הזה.
כדי למחוק את האשכול, מריצים את הפקודה הבאה:
gcloud container clusters delete CLUSTER_NAME --zone ZONE --quiet
כדי למחוק את המשאבים שיצרתם, מריצים את הפקודות הבאות:
gcloud compute backend-services delete grpc-gke-helloworld-service --global --quiet
gcloud compute network-endpoint-groups delete example-grpc-server --zone ZONE --quiet
gcloud compute firewall-rules delete grpc-gke-allow-health-checks --quiet
gcloud compute health-checks delete grpc-gke-helloworld-hc --quiet
gcloud network-services endpoint-policies delete ep-mtls-psms \
--location=global --quiet
gcloud network-security authorization-policies delete helloworld-gke-authz-policy \
--location=global --quiet
gcloud network-security client-tls-policies delete client-mtls-policy \
--location=global --quiet
gcloud network-security server-tls-policies delete server-tls-policy \
--location=global --quiet
gcloud network-security server-tls-policies delete server-mtls-policy \
--location=global --quiet
פתרון בעיות
ההוראות האלה יעזרו לכם לפתור בעיות בהטמעה של אמצעי האבטחה.
עומסי העבודה לא יכולים לקבל הגדרה מ-Cloud Service Mesh
אם מופיעה שגיאה דומה לזו:
PERMISSION_DENIED: Request had insufficient authentication scopes.
חשוב לוודא את הדברים הבאים:
- יצרתם את אשכול GKE באמצעות הארגומנט
--scopes=cloud-platformargument. - הקציתם את
roles/trafficdirector.clientלחשבונות של שירות Kubernetes. - הקצית את
roles/trafficdirector.clientלחשבון השירות שמוגדר כברירת מחדל Google Cloud (${GSA_EMAIL} למעלה). - הפעלתם את השירות (API) של
trafficdirector.googleapis.com.
השרת שלכם ב-gRPC לא משתמש ב-TLS/mTLS גם אם הגדרתם את Cloud Service Mesh בצורה נכונה
חשוב לציין את GRPC_SERVER בהגדרת מדיניות נקודות הקצה. אם ציינתם את SIDECAR_PROXY, gRPC מתעלם מההגדרה.
אי אפשר ליצור את אשכול GKE עם גרסת האשכול המבוקשת
יכול להיות שהפקודה ליצירת אשכול GKE תיכשל עם שגיאה כמו:
Node version "1.20.5-gke.2000" is unsupported.
מוודאים שמשתמשים בארגומנט --release-channel rapid בפקודה ליצירת האשכול. כדי לקבל את הגרסה הנכונה של הגרסה הזו, צריך להשתמש בערוץ ההפצה המהירה.
מוצגת שגיאה No usable endpoint
אם לקוח לא יכול לתקשר עם השרת בגלל שגיאה No usable endpoint, יכול להיות שכלי הבדיקה של תקינות השרת סימן את השרתים העורפיים כלא תקינים.
כדי לבדוק את תקינות השרתים העורפיים, מריצים את הפקודה gcloud הזו:
gcloud compute backend-services get-health grpc-gke-helloworld-service --global
אם הפקודה מחזירה את הסטטוס של ה-backend כלא תקין, יכולות להיות לכך אחת מהסיבות הבאות:
- חומת האש לא נוצרה או שהיא לא מכילה את טווח כתובות ה-IP הנכון של המקור.
- תגי היעד בחומת האש לא תואמים לתגים באשכול שיצרתם.
עומסי העבודה לא יכולים לתקשר בהגדרת האבטחה
אם עומסי העבודה לא מצליחים לתקשר אחרי שמגדירים אבטחה לרשת שירותים ללא Proxy, צריך לפעול לפי ההוראות האלה כדי לזהות את הסיבה.
- השבתה של אבטחה בלי שרת Proxy ופתרון בעיות בתרחישי שימוש של איזון עומסים ב-Service mesh בלי שרת Proxy. כדי להשבית את האבטחה ברשת, מבצעים אחת מהפעולות הבאות:
- שימוש בהרשאות בטקסט פשוט בצד הלקוח ובצד השרת או
- לא מגדירים אבטחה לשירות לקצה העורפי ולמדיניות נקודת הקצה בהגדרת Cloud Service Mesh.
פועלים לפי השלבים במאמר פתרון בעיות בפריסות של Cloud Service Mesh ללא שרת proxy, כי אין הגדרת אבטחה בפריסה.
משנים את עומסי העבודה כך שישתמשו בפרטי כניסה של xDS עם טקסט פשוט או בפרטי כניסה לא מאובטחים כפרטי הכניסה החלופיים. משאירים את ההגדרה של Cloud Service Mesh עם אבטחה מושבתת, כמו שצוין קודם. במקרה הזה, למרות ש-gRPC מאפשר ל-Cloud Service Mesh להגדיר אבטחה, Cloud Service Mesh לא שולח מידע אבטחה, ולכן gRPC צריך לחזור לשימוש בפרטי כניסה בטקסט פשוט (או לא מאובטח), שצריכים לפעול באופן דומה למקרה הראשון הקודם. אם זה לא עוזר, אפשר לנסות את הפעולות הבאות:
- להגדיל את רמת הרישום ביומן בצד הלקוח ובצד השרת, כדי שתוכלו לראות את הודעות xDS שהועברו בין gRPC לבין Cloud Service Mesh.
- מוודאים ש-Cloud Service Mesh לא מפעיל אבטחה בתגובות של CDS ו-LDS שנשלחות לעומסי העבודה.
- מוודאים שעומסי העבודה לא משתמשים במצבי TLS או mTLS בערוצים שלהם. אם מופיעות הודעות יומן שקשורות ללחיצות יד של TLS, צריך לבדוק את קוד המקור של האפליקציה ולוודא שאתם משתמשים בטקסט לא מאובטח או בטקסט רגיל כגיבוי לפרטי הכניסה. אם קוד המקור של האפליקציה תקין, יכול להיות שמדובר בבאג בספריית gRPC
כדי לוודא שהשילוב של שירות CA עם GKE פועל בצורה תקינה באשכול GKE, צריך לפעול לפי השלבים לפתרון בעיות שמפורטים במדריך למשתמש. חשוב לוודא שהאישורים והמפתחות שסופקו על ידי התכונה הזו זמינים בספרייה שצוינה,
/var/run/secrets/workload-spiffe-credentials/.מפעילים TLS (במקום mTLS) ברשת, כמו שמתואר למעלה, ומפעילים מחדש את עומסי העבודה של הלקוח והשרת.
- כדי לראות את הודעות ה-xDS שהועברו בין gRPC לבין Cloud Service Mesh, צריך להגדיל את רמת הרישום ביומן בצד הלקוח ובצד השרת.
- מוודאים ש-Cloud Service Mesh הפעיל אבטחה בתגובות של CDS ו-LDS שנשלחות לעומסי העבודה.
הלקוח נכשל עם CertificateException וההודעה Peer certificate SAN check failed
המשמעות היא שיש בעיה בערכים של subjectAltNames בהודעה SecuritySettings. שימו לב שהערכים האלה מבוססים על שירותי Kubernetes שיצרתם עבור שירות לקצה העורפי. לכל שירות Kubernetes שיצרתם יש מזהה SPIFFE משויך, בפורמט הבא:
spiffe://${WORKLOAD_POOL}/ns/${K8S_NAMESPACE}/sa/${SERVICE_ACCOUNT}
הערכים האלה הם:
-
WORKLOAD_POOL: מאגר עומסי העבודה של האשכול, שהוא${PROJECT_ID}.svc.id.goog -
K8S_NAMESPACE: מרחב השמות של Kubernetes שבו השתמשתם בפריסת השירות -
SERVICE_ACCOUNT: חשבון השירות של Kubernetes שבו השתמשתם בפריסה של השירות
לכל שירות Kubernetes שצירפתם לשירות הקצה העורפי שלכם כקבוצת נקודות קצה ברשת, ודאו שחישבתם נכון את מזהה SPIFFE והוספתם את מזהה SPIFFE הזה לשדה subjectAltNames בהודעה SecuritySettings.
אי אפשר להשתמש באישורי mTLS באפליקציות עם ספריית gRPC
אם האפליקציות לא יכולות להשתמש באישורי mTLS עם ספריית gRPC, צריך לבצע את הפעולות הבאות:
מוודאים שמפרט ה-Pod מכיל את האנוטציה
security.cloud.google.com/use-workload-certificatesשמתוארת במאמר יצירת שירות gRPC בלי שרת Proxy עם NEGs.מוודאים שהקבצים שמכילים את שרשרת האישורים יחד עם אישור העלה, המפתח הפרטי ואישורי ה-CA המהימנים נגישים בנתיבים הבאים מתוך ה-Pod:
- שרשרת האישורים יחד עם אישור הקצה: "/var/run/secrets/workload-spiffe-credentials/certificates.pem"
- מפתח פרטי: /var/run/secrets/workload-spiffe-credentials/private_key.pem
- חבילת CA: "/var/run/secrets/workload-spiffe-credentials/ca_certificates.pem"
אם האישורים מהשלב הקודם לא זמינים, פועלים לפי השלבים הבאים:
gcloud privateca subordinates describe SUBORDINATE_CA_POOL_NAME
--location=LOCATIONמוודאים שלמישור הבקרה של GKE יש את הקישור הנכון של תפקיד IAM, שמעניק לו גישה לשירות CA:
# Get the IAM policy for the CA gcloud privateca roots get-iam-policy ROOT_CA_POOL_NAME # Verify that there is an IAM binding granting access in the following format - members: - serviceAccount:service-projnumber@container-engine-robot.iam.gserviceaccount.com role: roles/privateca.certificateManager # Where projnumber is the project number (e.g. 2915810291) for the GKE cluster.
מוודאים שתוקף האישור לא פג. זו שרשרת האישורים ואישור הקצה בכתובת
/var/run/secrets/workload-spiffe-credentials/certificates.pem. כדי לבדוק, מריצים את הפקודה הבאה:cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"
מריצים את הפקודה הבאה כדי לוודא שסוג המפתח נתמך באפליקציה:
cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Public Key Algorithm" -A 3
מוודאים שלאפליקציית gRPC Java יש את ההגדרות הבאות
keyAlgorithmבקובץWorkloadCertificateConfigYAML:
keyAlgorithm: rsa: modulusSize: 4096מוודאים שרשות האישורים משתמשת באותה משפחת מפתחות כמו מפתח האישור.
האישור של האפליקציה נדחה על ידי הלקוח, השרת או העמית
- מוודאים שהאפליקציה העמיתה משתמשת באותו חבילת אמון כדי לאמת את האישור.
- מוודאים שתוקף האישור שבשימוש לא פג (שרשרת האישורים יחד עם אישור הקצה: /var/run/secrets/workload-spiffe-credentials/certificates.pem).
ה-Pods נשארים במצב המתנה
אם ה-Pods נשארים במצב 'בהמתנה' במהלך תהליך ההגדרה, צריך להגדיל את משאבי ה-CPU והזיכרון של ה-Pods במפרט הפריסה.
לא ניתן ליצור אשכול עם הדגל --enable-mesh-certificates
מוודאים שאתם מריצים את הגרסה העדכנית של ה-CLI של gcloud:
gcloud components update
הערה: הדגל --enable-mesh-certificates פועל רק עם הדגל gcloud beta.
הפעלת ה-Pods נכשלת
יכול להיות ש-Pods שמשתמשים באישורים של GKE mesh לא יופעלו אם הקצאת האישורים נכשלת. זה יכול לקרות במצבים כמו:
- ההגדרה של
WorkloadCertificateConfigאו שלTrustConfigשגויה או שהם חסרים. - בקשות CSR לא מאושרות.
כדי לבדוק אם הקצאת האישורים נכשלת, בודקים את אירועי ה-Pod.
בודקים את הסטטוס של ה-Pod:
kubectl get pod -n POD_NAMESPACE POD_NAMEמחליפים את מה שכתוב בשדות הבאים:
-
POD_NAMESPACE: מרחב השמות של ה-Pod. -
POD_NAME: השם של ה-Pod.
-
כדי לבדוק אירועים אחרונים ב-Pod:
kubectl describe pod -n POD_NAMESPACE POD_NAMEאם הקצאת האישורים נכשלת, יוצג אירוע עם השדות
Type=Warning,Reason=FailedMount,From=kubeletוהשדהMessageשמתחיל ב-MountVolume.SetUp failed for volume "gke-workload-certificates". השדהMessageמכיל מידע לפתרון בעיות.Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedMount 13s (x7 over 46s) kubelet MountVolume.SetUp failed for volume "gke-workload-certificates" : rpc error: code = Internal desc = unable to mount volume: store.CreateVolume, err: unable to create volume "csi-4d540ed59ef937fbb41a9bf5380a5a534edb3eedf037fe64be36bab0abf45c9c": caPEM is nil (check active WorkloadCertificateConfig)אם הסיבה לכך ש-Pods לא מופעלים היא אובייקטים שהוגדרו בצורה שגויה או בקשות חתימה על אישורים (CSR) שנדחו, כדאי לפעול לפי השלבים הבאים לפתרון בעיות.
ההגדרה של WorkloadCertificateConfig או TrustConfig שגויה
מוודאים שיצרתם את האובייקטים WorkloadCertificateConfig ו-TrustConfig בצורה נכונה. אפשר לאבחן הגדרות שגויות באחד מהאובייקטים האלה באמצעות kubectl.
אחזור הסטטוס הנוכחי.
עבור
WorkloadCertificateConfig:kubectl get WorkloadCertificateConfig default -o yamlעבור
TrustConfig:kubectl get TrustConfig default -o yamlבודקים את פלט הסטטוס. אובייקט תקין יכלול תנאי עם
type: Readyו-status: "True".status: conditions: - lastTransitionTime: "2021-03-04T22:24:11Z" message: WorkloadCertificateConfig is ready observedGeneration: 1 reason: ConfigReady status: "True" type: Readyאם האובייקטים לא תקינים, במקום זאת מופיע
status: "False". השדותreasonוmessageמכילים פרטים נוספים לפתרון בעיות.
בקשות CSR לא מאושרות
אם משהו משתבש במהלך תהליך אישור ה-CSR, אפשר לבדוק את פרטי השגיאה בתנאים type: Approved ו-type: Issued של ה-CSR.
רשימת בקשות CSR רלוונטיות באמצעות
kubectl:kubectl get csr \ --field-selector='spec.signerName=spiffe.gke.io/spiffe-leaf-signer'בוחרים בקובץ CSR שהוא
ApprovedולאIssued, או שהוא לאApproved.כדי לקבל פרטים על ה-CSR שנבחר באמצעות kubectl:
kubectl get csr CSR_NAME -o yamlמחליפים את
CSR_NAMEבשם של בקשת ה-CSR שבחרתם.
ל-CSR תקין יש תנאי עם type: Approved ו-status: "True", ואישור תקין בשדה status.certificate:
status:
certificate: <base64-encoded data>
conditions:
- lastTransitionTime: "2021-03-04T21:58:46Z"
lastUpdateTime: "2021-03-04T21:58:46Z"
message: Approved CSR because it is a valid SPIFFE SVID for the correct identity.
reason: AutoApproved
status: "True"
type: Approved
מידע לפתרון בעיות שקשורות לבקשות CSR לא תקינות מופיע בשדות message ו-reason.
חסרים אישורים ב-Pods
מקבלים את מפרט ה-Pod של ה-Pod:
kubectl get pod -n POD_NAMESPACE POD_NAME -o yamlמחליפים את מה שכתוב בשדות הבאים:
-
POD_NAMESPACE: מרחב השמות של ה-Pod. -
POD_NAME: השם של ה-Pod.
-
מוודאים שמפרט ה-Pod מכיל את
security.cloud.google.com/use-workload-certificatesההערה שמתוארת במאמר הגדרת Pods לקבלת פרטי כניסה של mTLS.מוודאים שפקדת הכניסה של אישורי GKE mesh הצליחה להוסיף נפח של מנהל התקן CSI מסוג
workloadcertificates.security.cloud.google.comלמפרט ה-Pod:volumes: ... -csi: driver: workloadcertificates.security.cloud.google.com name: gke-workload-certificates ...בודקים אם יש נפח שמוצמד לכל אחד מהקונטיינרים:
containers: - name: ... ... volumeMounts: - mountPath: /var/run/secrets/workload-spiffe-credentials name: gke-workload-certificates readOnly: true ...מוודאים שחבילות האישורים והמפתח הפרטי זמינים במיקומים הבאים ב-Pod:
- חבילת שרשרת אישורים:
/var/run/secrets/workload-spiffe-credentials/certificates.pem - מפתח פרטי:
/var/run/secrets/workload-spiffe-credentials/private_key.pem - חבילת ישויות עוגן אמינות של רשות אישורים (CA):
/var/run/secrets/workload-spiffe-credentials/ca_certificates.pem
- חבילת שרשרת אישורים:
אם הקבצים לא זמינים, מבצעים את הפעולות הבאות:
מאחזרים את מופע שירות ה-CA (Preview) עבור האשכול:
kubectl get workloadcertificateconfigs default -o jsonpath '{.spec.certificateAuthorityConfig.certificateAuthorityServiceConfig.endpointURI}'אחזור הסטטוס של מופע CA Service (Preview):
gcloud privateca ISSUING_CA_TYPE describe ISSUING_CA_NAME \ --location ISSUING_CA_LOCATIONמחליפים את מה שכתוב בשדות הבאים:
-
ISSUING_CA_TYPE: סוג רשות האישורים המנפיקה, שחייב להיותsubordinatesאוroots. -
ISSUING_CA_NAME: השם של רשות האישורים המנפיקה. -
ISSUING_CA_LOCATION: האזור של רשות האישורים המנפיקה.
-
מקבלים את מדיניות ה-IAM עבור רשות אישורים (CA) בסיסית:
gcloud privateca roots get-iam-policy ROOT_CA_NAMEמחליפים את
ROOT_CA_NAMEבשם של רשות האישורים הבסיסית.במדיניות IAM, מוודאים שקיים
privateca.auditorpolicy binding:... - members: - serviceAccount:service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com role: roles/privateca.auditor ...בדוגמה הזו,
PROJECT_NUMBERהוא מספר הפרויקט של האשכול.קבלת מדיניות IAM עבור רשות אישורים משנית:
gcloud privateca subordinates get-iam-policy SUBORDINATE_CA_NAMEמחליפים את
SUBORDINATE_CA_NAMEבשם של רשות אישורים משנית.במדיניות IAM, מוודאים שקיים
privateca.certificateManagerקישור למדיניות:... - members: - serviceAccount: service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com role: roles/privateca.certificateManager ...בדוגמה הזו,
PROJECT_NUMBERהוא מספר הפרויקט של האשכול.
לא ניתן להשתמש באישורי mTLS שהונפקו באפליקציות
מוודאים שתוקף האישור לא פג:
cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"בודקים שסוג המפתח שבו השתמשתם נתמך על ידי האפליקציה.
cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Public Key Algorithm" -A 3בודקים שרשות האישורים שהנפיקה את האישור משתמשת באותה משפחת מפתחות כמו מפתח האישור.
קבלת הסטטוס של מופע שירות ה-CA (Preview):
gcloud privateca ISSUING_CA_TYPE describe ISSUING_CA_NAME \ --location ISSUING_CA_LOCATIONמחליפים את מה שכתוב בשדות הבאים:
-
ISSUING_CA_TYPE: סוג רשות האישורים המנפיקה, שחייב להיותsubordinatesאוroots. -
ISSUING_CA_NAME: השם של רשות האישורים המנפיקה. -
ISSUING_CA_LOCATION: האזור של רשות האישורים המנפיקה.
-
בודקים שאלגוריתם המפתח
keySpec.algorithmבפלט זהה לזה שהגדרתם בקובץ המניפסטWorkloadCertificateConfigYAML. הפלט אמור להיראות כך:config: ... subjectConfig: commonName: td-sub-ca subject: organization: TestOrgLLC subjectAltName: {} createTime: '2021-05-04T05:37:58.329293525Z' issuingOptions: includeCaCertUrl: true keySpec: algorithm: RSA_PKCS1_2048_SHA256 ...
האישורים נדחים
- מוודאים שאפליקציית העמית משתמשת באותו חבילת אמון כדי לאמת את האישור.
מוודאים שתוקף האישור לא פג:
cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"אם לא משתמשים ב-Credentials Reloading API של gRPC Go, צריך לוודא שקוד הלקוח מרענן מעת לעת את פרטי הכניסה ממערכת הקבצים.
מוודאים שעומסי העבודה נמצאים באותו דומיין מהימן כמו רשות האישורים (CA). אישורים של GKE mesh תומכים בתקשורת בין עומסי עבודה בדומיין אמון יחיד.
מגבלות
אבטחת שירותים ב-Cloud Service Mesh נתמכת רק ב-GKE. אי אפשר לפרוס אבטחת שירות באמצעות Compute Engine.
Cloud Service Mesh לא תומך בתרחישים שבהם יש שני משאבי מדיניות של נקודות קצה או יותר שתואמים באופן שווה לנקודת קצה. לדוגמה, שתי מדיניות עם אותן תוויות ואותם פורטים, או שתי מדיניות או יותר עם תוויות שונות שתואמות באופן שווה לתוויות של נקודת קצה. מידע נוסף על האופן שבו מתבצעת התאמה בין מדיניות נקודת קצה לתוויות של נקודת קצה זמין במאמר בנושא ממשקי API ל-EndpointPolicy.EndpointMatcher.MetadataLabelMatcher. במקרים כאלה, Cloud Service Mesh לא יוצר הגדרת אבטחה מאף אחד מכללי המדיניות שמתנגשים.