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

הרכיבים העיקריים של הפתרון כוללים:
- לקוח: ישות שיוזמת בקשות HTTPS כדי ליצור אינטראקציה עם האפליקציות.
- אשכול רגיל ב-GDC: ב-GDC יש דרך מובנית ליצור אשכולות Vanilla של Kubernetes. בפתרון הזה, האשכול יארח את מאזן העומסים L7 ואת הבקרים שלו, יחד עם עומסי העבודה והשירות ללא ממשק משתמש למכונות וירטואליות חיצוניות.
- מאזן עומסים GDC L4: מאזן העומסים המובנה L4 משמש כנקודת הכניסה, ומפיץ את תעבורת הנתונים של TCP/443 ישירות לפודים של Kubernetes שמריצים את הבקרים.
- בקרי Ingress: אופרטורים של HAProxy שפועלים באשכול הרגיל.
הם עוקבים אחרי המשאבים של
Ingressומעדכנים באופן דינמי את שרתי ה-proxy הבסיסיים. בהטמעה הבאה נשתמש ב-HAProxy Ingress Controller. - Ingress: משאבים סטנדרטיים ב-Kubernetes שמגדירים את יציאת ההאזנה הפיזית (443) ואת כללי הניתוב של המארח שמבוססים על SNI עם סיום TLS.
- עומס עבודה בקונטיינרים (Pods): פריסה רגילה של Kubernetes שנחשפת באופן פנימי באמצעות
Serviceרגיל של Kubernetes. - עומס עבודה מבוסס-VM (חיצוני): עומס עבודה שמתארח ב-VM חיצוני ברשת של הפרויקט, ונחשף לשרת ה-proxy באמצעות
Serviceללא ממשק משתמש של Kubernetes ונקודת קצה מותאמת אישית שמכילה את כתובת ה-IP הישירה של ה-VM. - Harbor Registry: Container Registry פרטי שמשמש לאחסון ולהצגה של קובצי האימג' של שרת ה-proxy ושל האפליקציה בסביבה עם air gap.
באשכול הרגיל, יוצרים שלושה מרחבי שמות:
מרחב השמות
load-balancerמארח את HAProxy Ingress Controller ואת עומס העבודה של מאזן העומסים של HAProxy:
מרחב השמות
hello-appמארח אתDeployment,Serviceו-Ingressבשביל עומס העבודה של מאגר ההדגמה:
מרחב השמות
vm-appמארח שירות ללא ממשק משתמש שחושף את כתובת ה-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, מקצים למשתמש את התפקידים אדמין של אשכול ואדמין רגיל של אשכול. כדי להעביר קובצי אימג'ים, מקצים למשתמש את התפקיד אדמין של מכונה ב-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. אשכול רגיל מספק בסיס גמיש וחזק לפריסת עומסי עבודה שונים, כולל 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 ולאפליקציה לדוגמה שמבוססת על 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_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 וסודות של 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 LB
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"}'
בקר ה-Ingress של HAProxy מקבל כתובת IP וירטואלית ייחודית לגישת לקוח באמצעות שירות מסוג LoadBalancer. השירות הזה מגדיר מאזן עומסים מנוהל לחלוטין בשכבה 4. כדי לפשט את המדריך, יוצרים מאזן עומסים פנימי על ידי הגדרת ההערה load-balancer-type ל-internal. אם לא תכללו את ההערה הזו, ייווצר מאזן עומסים חיצוני. הפריסה של Kubernetes שולפת באופן מאובטח קובצי אימג' מ-Harbor באמצעות הסוד שסופק (${IMAGE_PULL_SECRET_NAME}), שמכיל את פרטי הכניסה של חשבון הרובוט של Harbor.
אימות ההתקנה של בקר HAProxy Ingress
בודקים שה-Pods של 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 שיתחבר לשירות ללא בורר של אפליקציית ה-VM, ומציינים את כתובת ה-IP של ה-VM שאליה צריך לנתב את התנועה.
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.
יצירת מכונה וירטואלית של לקוח
כדי ליצור מכונה וירטואלית של לקוח:
- פותחים את מסוף GDC בדפדפן האינטרנט.
- פותחים את התפריט ולוחצים על Virtual machines.
- לוחצים על Create Instance.
- יוצרים מכונה וירטואלית בשם
client, בוחרים סוג מכונה קטן ובוחרים ב-Rocky Linux או ב-Ubuntu, שכוללות אתcurlמותקן מראש. - לוחצים על יצירה.
- מחכים כמה דקות עד שהמכונה הווירטואלית תהיה מוכנה.
- אחרי שהמכונה הווירטואלית מוכנה, יוצרים חיבור SSH למכונה הווירטואלית:
- במסוף GDC, לוחצים על המכונה הווירטואלית.
- לוחצים על Connect with SSH.
אימות הגישה והניתוב
כדי לבדוק את הניתוב, מריצים פקודות curl מה-VM של הלקוח. אפשר להתחבר לשתי האפליקציות באמצעות שמות המארחים שהוגדרו להן, עם כתובת ה-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
אם מגדירים אותו נכון, בקר ה-Ingress יפעל בצורה חלקה כסיום 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. החיבור יהיה מהימן לחלוטין.
בודקים את האפליקציה בקונטיינר של 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.