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

הרכיבים העיקריים של הפתרון כוללים:
- לקוח: ישות שיוזמת בקשות HTTPS כדי ליצור אינטראקציה עם האפליקציות.
- אשכול GDC רגיל: ב-GDC יש דרך מובנית ליצור אשכולות Kubernetes Vanilla. בפתרון הזה, האשכול יארח את מאזן העומסים L7 ואת הבקרים שלו, יחד עם עומסי העבודה והשירות ללא ממשק משתמש למכונות וירטואליות חיצוניות.
- מאזן עומסים GDC L4: מאזן העומסים המובנה L4 משמש כנקודת הכניסה, ומפיץ את תעבורת הנתונים של TCP/443 ישירות לפודים של Kubernetes שמריצים את בקרי השער.
- בקרי שער: אופרטורים של NGINX שפועלים באשכול הרגיל.
הם עוקבים אחרי משאבי Gateway API (כמו
Gatewayו-HTTPRoute) ומעדכנים באופן דינמי את שרתי ה-proxy הבסיסיים. הפתרון ישתמש ב-Nginx Gateway Fabric. - Gateway (עם HTTPRoute): משאבים סטנדרטיים של Kubernetes שמגדירים את יציאת ההאזנה הפיזית (443) ואת כללי הניתוב של המארח שמבוססים על SNI עם סיום TLS.
- עומס עבודה בקונטיינרים (Pods): פריסה רגילה של Kubernetes שנחשפת באופן פנימי באמצעות
Serviceרגיל של Kubernetes. - עומס עבודה מבוסס-VM (חיצוני): עומס עבודה שמתארח ב-VM חיצוני ברשת הפרויקט, ונחשף לשרת ה-proxy באמצעות
Serviceללא ממשק משתמש ב-Kubernetes ונקודת קצה מותאמת אישית שמכילה את כתובת ה-IP הישירה של ה-VM. - Harbor Registry: Container Registry פרטי שמשמש לאחסון ולהצגה של קובצי האימג' של שרת ה-proxy ושל האפליקציה בסביבה עם air gap.
באשכול הרגיל, יוצרים ארבעה מרחבי שמות:
מרחב השמות
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 GDC_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, ואת התפקיד אדמין של מכונה ב-Harbor כדי לשלוח אימג'ים.
# 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 Controller והאפליקציות בהתאמה אישית. כדי לוודא שהאשכול מוגדר כמו שצריך ונגיש לפריסות הבאות, צריך לבצע את השלבים הבאים.
מזהים את סוגי האימג'ים הזמינים של המכונות הווירטואליות באמצעות הפקודה:
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 ולאפליקציה לדוגמה שמבוססת על VM:
kk create namespace load-balancer kk create namespace hello-app kk create namespace vm-app
יצירה ושילוב של Harbor Registry
Harbor הוא מאגר של קובצי אימג' של קונטיינרים עם תמיכה מובנית ב-GDC עם air gap. בקטע הזה נסביר איך לשלב את Harbor Registry עם אשכול רגיל, כולל הגדרת פרטי כניסה וסודות כדי לאפשר משיכה ודחיפה מאובטחות של קובצי אימג'.
- יוצרים מכונה של 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 עם air gap. תיצרו את המשאבים הנדרשים של Kubernetes Deployment ו-Service כדי להריץ את 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
בקטע הזה מוסבר איך לפרוס אפליקציית הדגמה במכונה וירטואלית (VM) מחוץ לאשכול Kubernetes. כדי לדמות אפליקציה חיצונית שמאזן העומסים יכול לחשוף, תגדירו שרת HTTP ב-VM. כך תדגימו את היכולת של מאזן העומסים לנהל את התנועה למשאבים בתוך האשכול ומחוצה לו.
קודם כל, יוצרים מכונה וירטואלית לאפליקציית ההדגמה
- פותחים את מסוף GDC בדפדפן האינטרנט.
- בוחרים את אותו פרויקט שבו יצרתם את אשכול Kubernetes הרגיל.
- פותחים את התפריט ולוחצים על Virtual machines.
- לוחצים על Create Instance.
- נותנים למכונה הווירטואלית את השם
vm-workload. תמונה של 2 vCPU מספיקה לדוגמה. - לקובץ האימג' של דיסק האתחול, בוחרים בהפצה של Ubuntu 22.04, שכוללת את Python מותקן מראש.
- לוחצים על יצירה.
- מחכים כמה דקות עד שהמכונה הווירטואלית תהיה מוכנה.
- יוצרים חיבור SSH למכונה הווירטואלית:
- במסוף GDC, לוחצים על המכונה הווירטואלית.
- לוחצים על Connect with 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 &
כדי לנתב תנועה למכונה וירטואלית, יוצרים שירות ללא ממשק משתמש (ללא בוררים). הכתובת הזו תמופה באופן ידני לכתובת ה-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 שיתחבר לשירות ללא בורר של אפליקציית ה-VM, ומציינים את כתובת ה-IP של ה-VM שאליה צריך לנתב את התנועה.
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, ומבטיחים תקשורת מוצפנת בין הלקוחות לבין מאזן העומסים גם לעומסי עבודה בקונטיינרים וגם לעומסי עבודה שמבוססים על מכונות וירטואליות.
יוצרים אישור לאפליקציה בקונטיינר:
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יוצרים אישור לאפליקציית המכונה הווירטואלית:
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, כולל התקנת הגדרות המשאבים בהתאמה אישית (CRD) של Gateway API, הגדרת Nginx Gateway Fabric באמצעות Helm ואימות ההתקנה באשכול הרגיל. כך התשתית מוכנה לניתוב מתקדם בשכבה 7.
התקנת ה-CRD של Gateway API
כדי להשתמש ב-Gateway API, צריך להתקין באשכול הגדרות של משאבים בהתאמה אישית (CRD) לפני שפורסים את הבקר. נשתמש בהגדרות הניסיוניות הרשמיות של משאבים בהתאמה אישית (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.
יצירת המכונה של Gateway
מגדירים את המכונה הלוגית של מאזן העומסים שמאזינה ליציאה 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
הגדרת הלוגיקה של הניתוב ב-L7 (HTTPRoute)
מקשרים את HTTPRoute לשער כדי להגדיר איך התנועה צריכה להתחלק על סמך שם המארח המבוקש (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 בדפדפן האינטרנט.
- פותחים את התפריט ולוחצים על Virtual machines.
- לוחצים על Create Instance.
- יוצרים מכונה וירטואלית בשם
client, בוחרים סוג מכונה קטן ובוחרים ב-Rocky Linux או ב-Ubuntu, שכוללות אתcurlמותקן מראש. - לוחצים על יצירה.
- מחכים כמה דקות עד שהמכונה הווירטואלית תהיה מוכנה.
- אחרי שהמכונה הווירטואלית מוכנה, יוצרים חיבור SSH למכונה הווירטואלית:
- במסוף GDC, לוחצים על המכונה הווירטואלית.
- לוחצים על Connect with SSH.
אימות הגישה והניתוב
כדי לבדוק את הניתוב, מריצים פקודות curl מה-VM של הלקוח. אפשר להתחבר לשתי האפליקציות באמצעות שמות המארחים שהוגדרו להן, עם כתובת ה-IP של מאזן העומסים.
אם מעבירים את הדגל --resolve ב-curl, אפשר לאלץ את שמות הדומיינים לזהות את כתובת ה-IP של מאזן העומסים בשכבה 4 של GDC עם air gap.
שימו לב שאנחנו מעבירים את הדגל -k כדי לתת אמון באישורים בחתימה עצמית.
בודקים את האפליקציה בקונטיינר של Kubernetes:
curl -k --resolve k8s-app.example.com:443:$LOAD_BALANCER_IP https://k8s-app.example.com -v
איך בודקים את האפליקציה של המכונה הווירטואלית החיצונית:
curl -k --resolve vm-app.example.com:443:$LOAD_BALANCER_IP https://vm-app.example.com -v
אם הוא מוגדר בצורה נכונה, בקר ה-Gateway יפעל בצורה חלקה כסיום TLS ויעביר את התנועה ליעד.
אופציונלי: שימוש באישורים שמוכנים לייצור
בקטע הזה מוסבר איך להשתמש בשירות ה-CA של GDC עם air gap כדי ליצור רשות אישורי בסיס (CA) פרטית, להנפיק אישורים חתומים לעומסי העבודה ולעדכן באופן מאובטח את המכונות הווירטואליות של הלקוח ואת האשכול הרגיל של GDC עם air gap.
בקטע הזה מוסבר איך להשתמש בשירות ה-CA של GDC עם air gap כדי ליצור רשות אישורי בסיס (CA) פרטית ולהנפיק אישורים תקפים לאפליקציות שלכם. אם תתקינו את ה-CA הבסיסי הזה ב-VM של הלקוח, תוכלו לוודא שסיום ה-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
יצירת רשות אישורים בסיסית (root 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'
הנפקה ופריסה של אישורים
אחרי שרשות האישורים מוכנה, צריך לבקש אישורים גם לאפליקציה בקונטיינר וגם לאפליקציה שמבוססת על VM. הבקשות האלה מתבצעות בשרת ה-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 הבסיסי החדש.
מחלצים את אישור ה-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 ולהדביק אותו בקובץ ב-VM של הלקוח).
ב-VM של הלקוח, מעדכנים את מאגר האישורים.
אם המכונה הווירטואלית של client היא 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
אם ה-VM של client הוא 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.