Google Distributed Cloud (GDC) air-gapped מספק מאזן עומסים מנוהל מובנה ברמה 4 (L4), אבל הרבה אפליקציות ארגוניות דורשות יכולות מתקדמות ברמה 7 (L7), כמו ניתוב מבוסס-מארח, ניהול מרכזי של TLS ופיצול מורכב של תעבורת נתונים. בעבר, כדי לעשות זאת השתמשו ב-Ingress API, שנחשב עכשיו ל-feature-frozen בקהילת Kubernetes.
ארכיטקטורת ההפניה הזו מספקת פתרון לניהול עצמי של איזון עומסים בשכבה 7. לקוחות יכולים להטמיע את בקר הקוד הפתוח הפופולרי NGINX Gateway Fabric באשכול GDC Standard, וכך לנתב בצורה חלקה תנועה ברמה 7 לסביבות היברידיות. בארכיטקטורה הזו נעשה שימוש ב-TLS Termination (HTTPRoute) כדי לנתב תנועה על סמך Server Name Indication (SNI) אל פודים מובנים שנמצאים בקונטיינרים ואל אפליקציות שמתארחות במכונות וירטואליות חיצוניות.
ארכיטקטורה

הרכיבים העיקריים של הפתרון כוללים:
- לקוח: ישות שיוזמת בקשות HTTPS כדי ליצור אינטראקציה עם האפליקציות.
- אשכול GDC רגיל: GDC מספק דרך מובנית ליצירת אשכולות Kubernetes Vanilla. בפתרון הזה, האשכול יארח את איזון העומסים ברמה 7 ואת בקרי איזון העומסים, יחד עם עומסי העבודה והשירות ללא ראש (headless) למכונות וירטואליות חיצוניות
- מאזן עומסים ברמה 4 של GDC: מאזן העומסים המובנה ברמה 4 משמש כנקודת הכניסה, ומפיץ את תעבורת הנתונים של TCP/443 ישירות אל ה-Pods של Kubernetes שמריצים את בקרי שער הכניסה.
- Gateway Controllers: אופרטורים של NGINX שפועלים באשכול Standard.
הם עוקבים אחרי משאבי Gateway API (כמו
Gatewayו-HTTPRoute) ומעדכנים באופן דינמי את ה-proxies הבסיסיים. הפתרון יתבסס על Nginx Gateway Fabric. - שער (עם HTTPRoute): משאבי Kubernetes סטנדרטיים שמגדירים את יציאת ההאזנה הפיזית (443) ואת כללי הניתוב של המארח שמבוססים על SNI עם סיום TLS.
- עומס עבודה בקונטיינר (Pods): פריסת Kubernetes רגילה שנחשפת באופן פנימי באמצעות
Serviceרגיל של Kubernetes. - עומס עבודה מבוסס-VM (חיצוני): עומס עבודה שמארח מכונה וירטואלית חיצונית ברשת הפרויקט, שנחשף ל-proxy עם Kubernetes
Serviceללא ראש ונקודת קצה מותאמת אישית שמכילה את כתובת ה-IP הישירה של המכונה הווירטואלית. - Harbor Registry: מאגר פרטי של קונטיינרים שמשמש לאחסון ולשליפה של קובצי האימג' של ה-proxy והאפליקציה בסביבה מבודדת.
ב-Standard Cluster, יוצרים ארבעה מרחבי שמות:
מרחב השמות
nginx-gatewayשמארח את המשאבים של Nginx Gateway Fabric:
מרחב השמות
load-balancerשמארח את המשאביםGateway:
מרחב השמות
vm-appמארח את כתובת ה-IP החיצונית של המכונה הווירטואליתvm-app, שירות ללא ראש,EndpointSliceשמפנה לכתובת ה-IP החיצונית ו-HTTPRouteל-Gateway:
מרחב השמות
hello-appמארח אתDeployment,Service,HTTPRouteו-Gatewayשל עומס העבודה של מאגר התגים להדגמה:
לפני שמתחילים
לפני שפורסים את הפתרון הזה, חשוב לוודא שהתנאים המוקדמים הבאים מתקיימים:
- תוכנה נדרשת: helm, docker, kubectl
כניסה ל-CLI והגדרה מקומית: מורידים את gdcloud CLI ממסוף GDC ומגדירים את הסביבה באופן מקומי.
export USER_NAME="USER_NAME" export PROJECT_ID="PROJECT_ID" export ZONE="ZONE" export ORG_NAME="ORG_NAME" export GDCH_URL="GDC_URL" gdcloud components install gdcloud-k8s-auth-plugin gdcloud config set core/organization_console_url \ https://console.$ORG_NAME.$ZONE.$GDC_URL gdcloud config set core/zone $ZONE gdcloud config set core/project ${PROJECT_ID} gdcloud auth login # use --login-config-cert option in case of TLS errorהגדרת פרויקט: יוצרים פרויקט בסביבת GDC עם air gap כדי לאחסן את המשאבים.
gdcloud projects create $PROJECT_IDתפקידים ב-IAM: כדי לנהל משאבי Kubernetes, צריך להקצות למשתמש את התפקידים Cluster Admin ו-Standard Cluster Admin. כדי לדחוף תמונות, צריך להקצות לו את התפקיד Harbor Instance Admin.
# Grant standard cluster and cluster admin roles gdcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member="user:${USER_NAME}" \ --role=cluster-admin gdcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member="user:${USER_NAME}" \ --role=standard-cluster-admin # Grant Harbor instance admin role gdcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member="user:${USER_NAME}" \ --role=harbor-instance-admin
יצירת אשכול רגיל
בקטע הזה מוסבר איך להגדיר אשכול Kubernetes רגיל בסביבת GDC עם air gap. אשכול רגיל מספק בסיס גמיש וחזק לפריסת עומסי עבודה שונים, כולל בקר Nginx Gateway והאפליקציות המותאמות אישית שלכם. השלבים הבאים יעזרו לכם לוודא שהאשכול מוגדר כראוי ושהגישה אליו אפשרית לצורך פריסות עתידיות.
מריצים את הפקודה הבאה כדי לזהות את סוגי תמונות המכונות הווירטואליות שזמינים:
gdcloud compute machine-types listבוחרים סוג מכונה מתאים לצמתי העובדים של האשכול. במדריך הזה מומלץ להשתמש בסוג מכונה עם לפחות 4 vCPU.
export MACHINE_TYPE="MACHINE_TYPE"מקבלים את קובץ ה-kubeconfig של שרת הניהול של API ומגדירים כינוי:
export CLUSTER_NAME="CLUSTER_NAME" KUBECONFIG=kubeconfig-admin.yaml gdcloud clusters \ get-credentials ${ORG_NAME}-admin alias km="kubectl --kubeconfig kubeconfig-admin.yaml"יוצרים אשכול רגיל עם 2 צמתי עובד:
km create -f - <<EOF apiVersion: cluster.gdc.goog/v1 kind: Cluster metadata: name: ${CLUSTER_NAME} namespace: ${PROJECT_ID} spec: nodePools: - machineTypeName: ${MACHINE_TYPE} nodeCount: 2 name: ${CLUSTER_NAME}-node-pool EOFפרטים נוספים על האפשרויות הזמינות מופיעים במאמרי העזרה.
יצירת אשכול רגיל יכולה להימשך עד 60 דקות. כדי לבדוק את הסטטוס, משתמשים בפקודה הבאה:
km get clusters/${CLUSTER_NAME} \ -n ${PROJECT_ID} \ --watchכשהאשכול מוכן, הפלט צריך להציג את המצב Running, כמו בדוגמה הבאה:
NAME STATE K8S VERSION my-cluster Running 1.30.12-gke.300אחרי שהאשכול מוכן, מאחזרים את פרטי הכניסה שלו:
KUBECONFIG=kubeconfig-${CLUSTER_NAME}.yaml gdcloud clusters \ get-credentials ${CLUSTER_NAME} \ --standard \ --project ${PROJECT_ID} \ --zone ${ZONE}כדי שהפקודות של
kubectlיהיו תמציתיות יותר בהמשך המדריך הזה, כדאי ליצור כינוי. הכינוי הזה ישמש לאינטראקציה עם האשכול הרגיל:alias kk="kubectl --kubeconfig kubeconfig-${CLUSTER_NAME}.yaml"יוצרים מרחבי שמות בשביל בקר, אפליקציית ההדגמה hello-app שמבוססת על קונטיינר ואפליקציית ההדגמה שמבוססת על מכונה וירטואלית:
kk create namespace load-balancer kk create namespace hello-app kk create namespace vm-app
יצירה ושילוב של Harbor Registry
Harbor הוא מרשם קובצי אימג' של קונטיינר עם תמיכה מובנית ב-GDC עם air gap. בקטע הזה מוסבר איך לשלב מאגר Harbor עם אשכול רגיל, כולל הגדרת פרטי כניסה וסודות כדי לאפשר שליפה ודחיפה מאובטחות של תמונות.
- יוצרים מופע של Harborבפרויקט.
- יוצרים פרויקט Harbor במכונת Harbor.
הגדרת משתני סביבה:
export HARBOR_INSTANCE_NAME="HARBOR_INSTANCE_NAME" export HARBOR_INSTANCE_URL="HARBOR_INSTANCE_URL" export HARBOR_PROJECT="HARBOR_INSTANCE_PROJECT" export IMAGE_PULL_SECRET_NAME="harbor-secret"נכנסים למופע Harbor באמצעות חשבון רובוט:
docker --config=./docker login ${HARBOR_INSTANCE_URL}יוצרים את הסודות באשכול הרגיל:
kk create secret docker-registry ${IMAGE_PULL_SECRET_NAME} \ --from-file=.dockerconfigjson=./docker/config.json \ -n load-balancer kk create secret docker-registry ${IMAGE_PULL_SECRET_NAME} \ --from-file=.dockerconfigjson=./docker/config.json \ -n hello-app
פריסת אפליקציית הדגמה בקונטיינר
בקטע הזה מפורטת הפריסה של אפליקציה לדוגמה בקונטיינר (hello-app) באשכול Kubernetes עם בידוד פיזי ב-GDC. תצרו את משאבי הפריסה והשירות הדרושים של Kubernetes כדי להפעיל את hello-app ולחשוף אותו באופן פנימי באשכול, ותכינו אותו לגישה באמצעות מאזן העומסים L7.
מעלים תמונה לדוגמה לאפליקציה לדוגמה שמופעלת בקונטיינר אל Harbor:
docker pull gcr.io/google-samples/hello-app:1.0 \ --platform linux/amd64 docker tag gcr.io/google-samples/hello-app:1.0 \ ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/hello-app:1.0 docker --config=./docker push \ ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/hello-app:1.0פורסים את המניפסט הבא באשכול הרגיל:
cat << EOF > hello-app.yaml apiVersion: apps/v1 kind: Deployment metadata: name: hello-app namespace: hello-app spec: replicas: 2 selector: matchLabels: app: hello-app template: metadata: labels: app: hello-app spec: containers: - name: hello-server image: ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/hello-app:1.0 ports: - containerPort: 8080 imagePullSecrets: - name: ${IMAGE_PULL_SECRET_NAME} --- apiVersion: v1 kind: Service metadata: name: hello-app namespace: hello-app spec: type: ClusterIP selector: app: hello-app ports: - protocol: TCP port: 80 targetPort: 8080 EOF kk apply -f hello-app.yaml
אחר כך מוודאים שהפריסה והשירות קיימים:
kk get svc,deploy -n hello-app
פריסת אפליקציית הדגמה במכונה וירטואלית
בקטע הזה מפורטת הפריסה של אפליקציית הדגמה במכונה וירטואלית (VM) מחוץ לאשכול Kubernetes. הגדרת שרת HTTP במכונה וירטואלית מאפשרת לדמות אפליקציה חיצונית שמאזן העומסים יכול לחשוף, וכך להדגים את היכולת שלו לנהל תעבורה למשאבים בתוך האשכול ומחוצה לו.
קודם כל, יוצרים מכונה וירטואלית לאפליקציית ההדגמה
- פותחים את מסוף GDC בדפדפן האינטרנט.
- בוחרים את אותו פרויקט שבו יצרתם את אשכול Kubernetes הרגיל.
- פותחים את התפריט ולוחצים על מכונות וירטואליות.
- לוחצים על Create Instance.
- נותנים למכונה הווירטואלית את השם
vm-workload. תמונת 2 vCPU מספיקה לדוגמה. - לקובץ האימג' של דיסק האתחול, בוחרים הפצה של Ubuntu 22.04, שכוללת את Python שכבר מותקן.
- לוחצים על יצירה.
- מחכים כמה דקות עד שהמכונה הווירטואלית מוכנה.
- יוצרים חיבור SSH למכונה הווירטואלית:
- במסוף GDC, לוחצים על מכונת ה-VM.
- לוחצים על Connect with SSH (התחברות באמצעות SSH).
אחרי שמתחברים למסוף SSH, מריצים את הפקודה הבאה:
mkdir ~/simple-server
cd ~/simple-server
echo 'Welcome to my VM!' > index.html
python3 -m http.server --bind 0.0.0.0 8080 &
כדי להפנות תנועה למכונה וירטואלית, יוצרים Service ללא ראש (headless) (ללא סלקטורים). הכתובת הזו תמופה ידנית לכתובת ה-IP הפנימית של המכונה הווירטואלית באמצעות משאב EndpointSlice.
kk apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
name: vm-app-svc
namespace: vm-app
spec:
ports:
- protocol: TCP
port: 443
targetPort: 443
EOF
כדי לקבל את כתובת ה-IP של מכונה וירטואלית vm-workload, מריצים את הפקודה
gdcloud compute instances list --project ${PROJECT_ID} \
| grep workload-vm | awk '{print $3}'
הפלט יהיה כתובת ה-IP של המכונה הווירטואלית, שתהיה נחוצה להגדרת המשאב EndpointSlice.
יוצרים את המשאב EndpointSlice שיתחבר לשירות ללא בורר של אפליקציות למכונות וירטואליות, ומגדירים את כתובת ה-IP של המכונה הווירטואלית שאליה התנועה תנותב.
apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
name: vm-app-endpoints
namespace: vm-app
labels:
kubernetes.io/service-name: vm-app-svc
addressType: IPv4
ports:
- port: 8080
endpoints:
- addresses:
- "VM_IP"
conditions:
ready: true
יצירת אישורים בחתימה עצמית
בקטע הזה מוסבר איך ליצור אישורי TLS בחתימה עצמית לאפליקציות. במדריך הזה נעשה שימוש באישורים בחתימה עצמית כדי להקל על התהליך, אבל בסביבות ייצור צריך להשתמש באישורים ברמת ייצור, כמו שמתואר במאמר אופציונלי: שימוש באישורים שמוכנים לייצור. האישורים האלה חיוניים להפסקת HTTPS ב-Nginx Gateway, כדי להבטיח תקשורת מוצפנת בין לקוחות לבין מאזן העומסים, גם לעומסי עבודה מבוססי-מכונות וירטואליות וגם לעומסי עבודה מבוססי-קונטיינרים.
יוצרים אישור לאפליקציה בקונטיינר:
openssl req -x509 -newkey rsa:2048 -nodes \ -keyout tls-containerized.key \ -out tls-containerized.crt \ -subj "/CN=k8s-app.example.com" \ -days 365 kk create secret tls tls-containerized \ --namespace load-balancer \ --key tls-containerized.key \ --cert tls-containerized.crt kk create secret tls tls-containerized \ --namespace hello-app \ --key tls-containerized.key \ --cert tls-containerized.crtיוצרים אישור לאפליקציית ה-VM:
openssl req -x509 -newkey rsa:2048 -nodes \ -keyout tls-vm.key \ -out tls-vm.crt \ -subj "/CN=vm-app.example.com" \ -days 365 kk create secret tls tls-vm \ --namespace load-balancer \ --key tls-vm.key \ --cert tls-vm.crt kk create secret tls tls-vm \ --namespace vm-app \ --key tls-vm.key \ --cert tls-vm.crt
פריסת NGINX
בקטע הזה מפורטים השלבים לפריסת Nginx Gateway Controller, כולל התקנת Gateway API Custom Resource Definitions (CRD), הגדרת Nginx Gateway Fabric באמצעות Helm ואימות ההתקנה באשכול הרגיל. הפעולה הזו מכינה את התשתית לניתוב מתקדם בשכבה 7.
התקנה של CRD של Gateway API
כדי לפרוס את בקר Gateway API, צריך להתקין Custom Resource Definitions (CRDs) באשכול. אנחנו נשתמש בהגדרות הרשמיות של משאבים מותאמים אישית (CRD) מניסויים בפרויקט Gateway API (במדריך הזה נעשה שימוש בגרסה 1.2.0).
מתקינים את ה-CRD הניסיוני:
kk apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/experimental-install.yamlמריצים את הפקודה
kk get crd gateways.gateway.networking.k8s.ioכדי לוודא שה-CRD הותקנו בהצלחה.
התקנה של NGINX Gateway Fabric
פורסים את בקר NGINX Gateway Fabric באמצעות Helm. הבקר הזה יעקוב אחרי משאבי Gateway API ויגדיר את NGINX לטיפול בתנועה.
מגדירים את תג התמונה של NGINX:
helm template nfg oci://ghcr.io/nginx/charts/nginx-gateway-fabric | grep "image:" # get the tag of the nginx-gateway-fabric (in following case 2.4.2) export NGINX_TAG="2.4.2"מושכים את תמונות NGINX Gateway Fabric ו-NGINX, ואז דוחפים אותן למאגר Harbor:
docker pull ghcr.io/nginx/nginx-gateway-fabric:${NGINX_TAG} docker tag ghcr.io/nginx/nginx-gateway-fabric:${NGINX_TAG} \ ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/nginx-gateway-fabric:${NGINX_TAG} docker --config=./docker push \ ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/nginx-gateway-fabric:${NGINX_TAG} docker pull nginx:1.27.3 docker tag nginx:1.27.3 \ ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/nginx:1.27.3 docker --config=./docker push \ ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/nginx:1.27.3יוצרים את מרחב השמות
nginx-gatewayומוסיפים את סוד המשיכה של תמונת Harbor:kk create namespace nginx-gateway kk create secret docker-registry ${IMAGE_PULL_SECRET_NAME} \ --from-file=.dockerconfigjson=./docker/config.json \ -n nginx-gatewayפורסים את NGINX Gateway Fabric באמצעות Helm, ומפנים לתמונות במאגר Harbor:
KUBECONFIG=kubeconfig-${CLUSTER_NAME}.yaml helm upgrade --install ngf \ oci://ghcr.io/nginx/charts/nginx-gateway-fabric \ --create-namespace -n nginx-gateway \ --set nginxGateway.image.tag="${NGINX_TAG}" \ --set nginxGateway.image.repository="${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/nginx-gateway-fabric" \ --set nginx.image.repository="${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/nginx" \ --set nginxGateway.serviceAccount.imagePullSecret="${IMAGE_PULL_SECRET_NAME}" \ --set nginx.imagePullSecret="${IMAGE_PULL_SECRET_NAME}"הפריסה של Kubernetes שולפת תמונות מ-Harbor בצורה מאובטחת באמצעות הסוד שסופק (
${IMAGE_PULL_SECRET_NAME}), שמכיל את פרטי הכניסה של חשבון הרובוט של Harbor.מוודאים שהמשאבים של
GatewayClassמתקבלים:kk get gatewayclassהמינוי שלכם ל-
nginxאמור להופיע עםACCEPTED = True.
יצירת מכונת השער
מגדירים את המופע הלוגי של מאזן העומסים שמקשיב ביציאה 443. אנחנו נגדיר אותו במצב Terminate, כלומר השער יבצע סיום TLS ויפענח את התנועה לפני שיעביר אותה.
ליצור ולהחיל gateway.yaml:
cat << EOF > gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: my-gateway
namespace: load-balancer
spec:
gatewayClassName: nginx
listeners:
- name: https-k8s-workload
hostname: "k8s-app.example.com"
port: 443
protocol: HTTPS
allowedRoutes:
namespaces:
from: All
tls:
mode: Terminate
certificateRefs:
- kind: Secret
name: tls-containerized
- name: https-vm-workload
hostname: "vm-app.example.com"
port: 443
protocol: HTTPS
allowedRoutes:
namespaces:
from: All
tls:
mode: Terminate
certificateRefs:
- kind: Secret
name: tls-vm
EOF
kk apply -f gateway.yaml
כדי לוודא שהפריסה של שער התשלומים בוצעה בהצלחה, בודקים אם PROGRAMMED הוא:True
kk get gateway my-gateway --n load-balancer
מוודאים שמאזן עומסים מנוהל של GDC L4 נפרס כשירות לצד השער
kk get services -n load-balancer
בודקים ששירות Nginx נוצר והוגדר. הפלט צריך להיראות כך:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-gateway-nginx LoadBalancer 10.252.19.148 10.200.32.43 443:30649/TCP 45h
הגדרת לוגיקת הניתוב ברמה 7 (HTTPRoute)
מקשרים את HTTPRoutes ל-Gateway כדי להגדיר איך התנועה צריכה להתחלק על סמך שם המארח המבוקש (SNI).
ליצור ולהחיל routing.yaml:
cat << EOF > routing.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: k8s-http-route
namespace: hello-app
spec:
parentRefs:
- name: my-gateway
namespace: load-balancer
hostnames:
- "k8s-app.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: hello-app
namespace: hello-app
port: 80
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: vm-http-route
namespace: vm-app
spec:
parentRefs:
- name: my-gateway
namespace: load-balancer
hostnames:
- "vm-app.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: vm-app-svc
namespace: vm-app
port: 443
EOF
kk apply -f routing.yaml
אחזור כתובת ה-IP של מאזן העומסים
מריצים את הפקודה כדי לקבל את כתובת ה-IP של מאזן העומסים של Nginx
kk get services/my-gateway-nginx \
-n load-balancer \
-o jsonpath='{.status.loadBalancer.ingress[0].ip}'
האימות הזה יידרש כשתינתן גישה לאפליקציות. השם הזה יהיה LOAD_BALANCER_IP.
יצירת מכונה וירטואלית של לקוח
פועלים לפי השלבים ליצירת מכונת VM של לקוח
- פותחים את מסוף GDC בדפדפן האינטרנט.
- פותחים את התפריט ולוחצים על מכונות וירטואליות.
- לוחצים על Create Instance.
- יוצרים מכונה וירטואלית בשם
client, בוחרים סוג מכונה קטן ובוחרים באחת מהאפשרויות הבאות: Rocky Linux או Ubuntu, שמגיעות עםcurlשכבר מותקן. - לוחצים על יצירה.
- מחכים כמה דקות עד שהמכונה הווירטואלית מוכנה.
- אחרי שהמכונה הווירטואלית מוכנה, יוצרים חיבור SSH למכונה הווירטואלית:
- במסוף GDC, לוחצים על מכונת ה-VM.
- לוחצים על Connect with SSH (התחברות באמצעות SSH).
אימות הגישה והניתוב
כדי לבדוק את הניתוב, מריצים פקודות curl ממכונת הלקוח הווירטואלית. אתם יכולים להתחבר לשתי האפליקציות באמצעות שמות המארחים המוגדרים שלהן עם כתובת ה-IP של מאזן העומסים.
אם מעבירים את הדגל --resolve ב-curl, אפשר לכפות על שמות הדומיינים להפנות לכתובת ה-IP של מאזן העומסים L4 ב-GDC עם air gap.
שימו לב שאנחנו מעבירים את הדגל -k כדי לתת אמון באישורים בחתימה עצמית.
בודקים את האפליקציה בקונטיינר של Kubernetes:
curl -k --resolve k8s-app.example.com:443:$LOAD_BALANCER_IP https://k8s-app.example.com -v
בודקים את אפליקציית ה-VM החיצונית:
curl -k --resolve vm-app.example.com:443:$LOAD_BALANCER_IP https://vm-app.example.com -v
אם הוא מוגדר בצורה נכונה, בקר השער פועל בצורה חלקה כ-TLS terminator ומעביר את התנועה ליעד.
אופציונלי: שימוש באישור מוכן לייצור
בקטע הזה מוסבר איך להשתמש בשירות רשות האישורים של GDC עם air gap כדי ליצור רשות אישורי בסיס פרטית, להנפיק אישורים חתומים לעומסי העבודה ולעדכן בצורה מאובטחת את האשכול הרגיל ואת מכונות ה-VM של הלקוח ב-GDC עם air gap.
בקטע הזה מוסבר איך להשתמש ב-CA Service של GDC עם air gap כדי ליצור רשות אישורי בסיס (CA) פרטית ולהנפיק אישורים תקפים לאפליקציות שלכם. התקנת רשות האישורים הבסיסית הזו במכונה הווירטואלית של הלקוח מאפשרת לוודא שסיום ה-TLS פועל בצורה חלקה עם אישורים מהימנים, בלי צורך לעקוף אזהרות SSL (לדוגמה, באמצעות curl -k).
הענקת ההרשאות הנדרשות וקבלת פרטי הכניסה
כדי לנהל את שירות ה-CA ולהנפיק אישורים, המשתמש צריך לקבל את תפקידי ה-IAM המתאימים בפרויקט.
הקצאת התפקידים
certificate-authority-service-adminו-certificate-requester:gdcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member=user:${USER_NAME} \ --role=certificate-authority-service-admin gdcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member=user:${USER_NAME} \ --role=certificate-requesterמקבלים את פרטי הכניסה של שרת הניהול של API:
gdcloud clusters get-credentials ${ORG_NAME}-admin
יצירת רשות האישורים (CA) הבסיסית
תיצרו רשות אישורים בשרת של ממשק ה-API לניהול במרחב השמות של הפרויקט.
החלת המשאב
CertificateAuthority:km apply -f - <<EOF apiVersion: pki.security.gdc.goog/v1 kind: CertificateAuthority metadata: name: my-root-ca namespace: ${PROJECT_ID} spec: caProfile: commonName: "My Root CA" duration: 87600h # 10 years keyAlgorithm: RSA_2048 maxChainLength: 1 caType: ROOT keyLocation: HSM rotationPolicy: cronTime: 0 0 1 1 * EOFkm -n ${PROJECT_ID} get \ certificateauthority.pki.security.gdc.goog/my-root-ca -ojson \ | jq -r ' .status.conditions[] | select( .type as $id | "Ready" | index($id)) .status'
הנפקה ופריסה של אישורים
אחרי שה-CA מוכן, תבקשו אישורים גם לאפליקציה שמבוססת על קונטיינר וגם לאפליקציה שמבוססת על מכונה וירטואלית. הבקשות האלה מתבצעות בשרת של ה-API לניהול, והמפתחות שמתקבלים צריכים להיות מועברים לאשכול הרגיל.
יוצרים בקשות לשני הדומיינים:
km apply -f - <<EOF
apiVersion: pki.security.gdc.goog/v1
kind: CertificateRequest
metadata:
name: tls-containerized-req
namespace: ${PROJECT_ID}
spec:
certificateAuthorityRef:
name: my-root-ca
namespace: ${PROJECT_ID}
certificateConfig:
subjectConfig:
commonName: "k8s-app.example.com"
dnsNames:
- "k8s-app.example.com"
signedCertificateSecret: tls-containerized-signed
---
apiVersion: pki.security.gdc.goog/v1
kind: CertificateRequest
metadata:
name: tls-vm-req
namespace: ${PROJECT_ID}
spec:
certificateAuthorityRef:
name: my-root-ca
namespace: ${PROJECT_ID}
certificateConfig:
subjectConfig:
commonName: "vm-app.example.com"
dnsNames:
- "vm-app.example.com"
signedCertificateSecret: tls-vm-signed
EOF
מחכים כמה רגעים עד שהאישורים יונפקו. אפשר לוודא שהם מוכנים כשהתנאי Ready הוא True:
km get certificaterequests -n ${PROJECT_ID}
עדכון האשכול הרגיל
אם פעלתם לפי ההוראות בקטעים הקודמים של המדריך הזה, יש לכם סודות בחתימה עצמית באשכול הרגיל. כדי ליצור גרסאות חדשות וחתומות, צריך למחוק את הגרסאות הקיימות:
kk delete secret tls-containerized -n load-balancer
kk delete secret tls-vm -n load-balancer
kk delete secret tls-containerized -n hello-app
kk delete secret tls-vm -n vm-app
עכשיו מחלצים את האישורים החתומים משרת ה-API לניהול ויוצרים את הסודות החדשים באשכול הרגיל.
km get secret -n ${PROJECT_ID} tls-containerized-signed \
-o jsonpath='{.data.tls\.crt}' \
| base64 -d > tls-containerized.crt
km get secret -n ${PROJECT_ID} tls-containerized-signed \
-o jsonpath='{.data.tls\.key}' \
| base64 -d > tls-containerized.key
kk create secret tls tls-containerized \
--namespace load-balancer \
--key tls-containerized.key \
--cert tls-containerized.crt
kk create secret tls tls-containerized \
--namespace hello-app \
--key tls-containerized.key \
--cert tls-containerized.crt
km get secret -n ${PROJECT_ID} tls-vm-signed \
-o jsonpath='{.data.tls\.crt}' \
| base64 -d > tls-vm.crt
km get secret -n ${PROJECT_ID} tls-vm-signed \
-o jsonpath='{.data.tls\.key}' \
| base64 -d > tls-vm.key
kk create secret tls tls-vm \
--namespace load-balancer \
--key tls-vm.key \
--cert tls-vm.crt
kk create secret tls tls-vm \
--namespace vm-app \
--key tls-vm.key \
--cert tls-vm.crt
מאזני העומסים יקבלו את הסודות החדשים וירעננו אותם באופן אוטומטי.
הגדרת אמון לקוח
כדי לאמת את ההגדרה, צריך להגדיר את מכונת ה-VM של הלקוח כך שתהיה מהימנה לרשות אישורי הבסיס החדשה.
מחלצים את אישור ה-CA הבסיסי לקובץ:
km get secret -n ${PROJECT_ID} my-root-ca-secret \
-o jsonpath='{.data.tls\.crt}' \
| base64 -d > my-root-ca.crt
מעבירים את האישור למכונה הווירטואלית של הלקוח. (אפשר להעתיק את התוכן של my-root-ca.crt ולהדביק אותו בקובץ במכונה הווירטואלית של הלקוח).
במכונה הווירטואלית של הלקוח, מעדכנים את מאגר האישורים.
אם מכונת client VM היא Ubuntu:
sudo cp my-root-ca.crt /usr/local/share/ca-certificates/
sudo chmod 644 /usr/local/share/ca-certificates/my-root-ca.crt
sudo update-ca-certificates
אם מכונת client VM היא Rocky Linux:
sudo cp my-root-ca.crt /etc/pki/ca-trust/source/anchors/
sudo update-ca-trust
אימות הגישה
עכשיו אפשר לגשת לאפליקציות באמצעות curl בלי הדגל -k. החיבור יהיה מהימן לחלוטין.
בודקים את האפליקציה בקונטיינר של Kubernetes:
curl -v --resolve k8s-app.example.com:443:LOAD_BALANDER_IP https://k8s-app.example.com
בודקים את אפליקציית המכונה הווירטואלית:
curl -v --resolve vm.example.com:443:LOAD_BALANDER_IP https://vm-app.example.com
אם הפעולה תצליח, תראו את הפלט של האפליקציה באופן מיידי בלי אזהרות לגבי אישור SSL.