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

הרכיבים העיקריים של הפתרון כוללים:
- לקוח: ישות שיוזמת בקשות HTTPS כדי ליצור אינטראקציה עם האפליקציות.
- אשכול רגיל של GDC: GDC מספק דרך מובנית ליצירת אשכולות Kubernetes Vanilla. בפתרון הזה, האשכול יארח את איזון העומסים ברמה 7 ואת בקרי איזון העומסים, יחד עם עומסי העבודה והשירות ללא ראש עבור מכונות וירטואליות חיצוניות
- מאזן עומסים ברמה 4 של GDC: מאזן העומסים המובנה ברמה 4 משמש כנקודת הכניסה ומפיץ את תעבורת הנתונים של TCP/443 ישירות אל ה-Pods של Kubernetes שמריצים את הבקרים.
- בקרי Ingress: אופרטורים של HAProxy שפועלים באשכול הרגיל.
הם עוקבים אחרי המשאבים של
Ingressומעדכנים באופן דינמי את ה-proxies הבסיסיים. HAProxy Ingress Controller ישמש בהטמעה הבאה - Ingress: משאבי Kubernetes סטנדרטיים שמגדירים את יציאת ההאזנה הפיזית (443) ואת כללי הניתוב של המארח שמבוססים על SNI עם סיום TLS.
- עומס עבודה בקונטיינר (Pods): פריסת Kubernetes רגילה שנחשפת באופן פנימי באמצעות
Serviceרגיל של Kubernetes. - עומס עבודה מבוסס-VM (חיצוני): עומס עבודה שמארח מכונה וירטואלית חיצונית ברשת הפרויקט, שנחשף לשרת ה-proxy באמצעות Kubernetes
Serviceללא ראש ונקודת קצה מותאמת אישית שמכילה את כתובת ה-IP הישירה של המכונה הווירטואלית. - Harbor Registry: מאגר פרטי של קונטיינרים שמשמש לאחסון ולשליפה של קובצי האימג' של ה-proxy והאפליקציה בסביבה מבודדת.
ב-cluster הרגיל, יוצרים שלושה מרחבי שמות:
במרחב השמות
load-balancerמתארחים HAProxy Ingress Controller ועומס העבודה של מאזן העומסים HAProxy:
מרחב השמות
hello-appמארח אתDeployment,Serviceו-Ingressעבור עומס העבודה של מאגר ההדגמה:
מרחב השמות
vm-appמארח שירות ללא ראש (headless) שחושף את כתובת ה-IP החיצונית של המכונה הווירטואלית,EndpointSliceשמצביע על כתובת ה-IP החיצונית ו-Ingress:
לפני שמתחילים
לפני שפורסים את הפתרון הזה, חשוב לוודא שהתנאים המוקדמים הבאים מתקיימים:
- תוכנה נדרשת: 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, צריך לתת למשתמש את התפקידים 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. קלאסטר רגיל מספק בסיס גמיש וחזק לפריסה של עומסי עבודה שונים, כולל HAProxy Ingress 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"יוצרים אשכול רגיל עם שני צמתי עובדים:
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_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 וסודות של Kubernetes כדי לאבטח את התקשורת של אפליקציות מבוססות-קונטיינרים ומבוססות-מכונות וירטואליות. במדריך הזה נעשה שימוש באישור בחתימה עצמית לצורך נוחות, אבל בסביבות ייצור צריך להשתמש באישורים ברמת ייצור, כמו שמתואר במאמר אופציונלי: שימוש באישורים שמוכנים לייצור. בוחרים שמות דומיין לדוגמה באופן שרירותי לאפליקציות האלה. יצירת חיבורים מאובטחים מבטיחה את שלמות הנתונים ואת הסודיות שלהם עבור לקוחות שניגשים לאפליקציה שלכם דרך HAProxy Ingress Controller.
באפליקציה שמופעלת בתוך קונטיינר, אנחנו יוצרים אישור בחתימה עצמית ושומרים אותו כסוד במרחב השמות של מאזן העומסים. האישור הזה ישמש ל-TLS כשמבקשים את k8s-app.example.com
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, מונפק ונשמר אישור דומה עם חתימה עצמית. ההגדרה הזו תשמש ל-TLS כשמתבצעת בקשה ל-vm-app.example.com
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
פריסת HAProxy
התקנה של בקר HAProxy Ingress ואיזון עומסים L4
export HAPROXY_VERSION=3.1.14
# pull the HAProxy Ingress Controller image and push it to Harbor
docker pull haproxytech/kubernetes-ingress:${HAPROXY_VERSION} \
--platform linux/amd64
docker tag haproxytech/kubernetes-ingress:${HAPROXY_VERSION} \
${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/haproxy-ingress:${HAPROXY_VERSION}
docker --config=./docker push \
${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/haproxy-ingress:${HAPROXY_VERSION}
# Get Helm repo
helm repo add haproxytech https://haproxytech.github.io/helm-charts
helm repo update
# Install the Ingress Controller with helm
helm upgrade --install haproxy-kubernetes-ingress \
haproxytech/kubernetes-ingress \
--kubeconfig kubeconfig-${CLUSTER_NAME}.yaml \
--namespace load-balancer \
--set controller.image.repository=${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/haproxy-ingress \
--set controller.image.tag=${HAPROXY_VERSION} \
--set controller.existingImagePullSecret=${IMAGE_PULL_SECRET_NAME} \
--set controller.service.type=LoadBalancer \
--set-json \
controller.service.annotations='{"networking.gke.io/load-balancer-type": "internal"}'
בקר הכניסה של HAProxy מקבל כתובת IP וירטואלית ייחודית לגישת לקוח באמצעות שירות מסוג LoadBalancer. השירות הזה מגדיר מאזן עומסים מנוהל לחלוטין ברמה 4. כדי לפשט את המדריך הזה, מאזן עומסים פנימי נוצר על ידי הגדרת ההערה load-balancer-type לערך internal. אם לא מציינים את ההערה הזו, נוצר מאזן עומסים חיצוני. פריסת Kubernetes שולפת תמונות מ-Harbor בצורה מאובטחת באמצעות הסוד שסופק (${IMAGE_PULL_SECRET_NAME}), שמכיל את פרטי הכניסה של חשבון הרובוט ב-Harbor.
אימות ההתקנה של בקר HAProxy Ingress
בודקים שהפודים של HAProxy Ingress Controller פועלים ומוכנים:
kk get pods -n load-balancer
הפלט אמור להיראות כך:
NAME READY STATUS RESTARTS AGE
haproxy-kubernetes-ingress-78dc9c8676-f8fcb 1/1 Running 0 35s
haproxy-kubernetes-ingress-78dc9c8676-lfnr2 1/1 Running 0 65s
haproxy-kubernetes-ingress-crdjob-3-tgj2h 0/1 Completed 0 65s
בודקים שהשירות של HAProxy Ingress Controller נוצר והוגדר:
kk get services -n load-balancer
הפלט אמור להיראות כך:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
haproxy-kubernetes-ingress LoadBalancer 10.252.27.46 10.252.4.17 80:32023/TCP,443:31103/TCP,443:31103/UDP,1024:30146/TCP,6060:30718/TCP 10m
הגדרת משאבי Ingress לאפליקציות ההדגמה
יצירת משאב Ingress שיקשר את HAProxy לשירות האפליקציה שמוכלת בקונטיינר
cat << EOF > hello-app-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-app-ingress
namespace: hello-app
annotations:
haproxy.org/ssl-redirect: "true"
haproxy.org/ssl-redirect-port: "443"
haproxy.org/ssl-redirect-code: "308"
spec:
ingressClassName: haproxy
tls:
- hosts:
- "k8s-app.example.com"
secretName: tls-containerized
rules:
- host: "k8s-app.example.com"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: hello-app
port:
number: 80
EOF
kk apply -f hello-app-ingress.yaml
יוצרים את משאב ה-Ingress שיתחבר לשירות של המכונה הווירטואלית ללא בורר אפליקציות, ויקצה את כתובת ה-IP של המכונה הווירטואלית שאליה התנועה תנותב.
cat << EOF > vm-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: vm-app-ingress
namespace: vm-app
annotations:
haproxy.org/ssl-redirect: "true"
haproxy.org/ssl-redirect-port: "443"
haproxy.org/ssl-redirect-code: "308"
spec:
ingressClassName: haproxy
tls:
- hosts:
- "vm-app.example.com"
secretName: tls-vm
rules:
- host: "vm-app.example.com"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: vm-app-svc
port:
number: 443
EOF
kk apply -f vm-ingress.yaml
אחזור כתובת ה-IP של מאזן העומסים
מריצים את הפקודה כדי לקבל את כתובת ה-IP של מאזן העומסים.
kk get services/haproxy-kubernetes-ingress \
-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.
שימו לב שאנחנו מעבירים את הדגל -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
אם הוא מוגדר בצורה נכונה, בקר ה-Ingress פועל בצורה חלקה כ-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. החיבור יהיה מהימן לחלוטין.
בודקים את האפליקציה בקונטיינר k8s:
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.