יצירת אשכול ופריסת עומס עבודה באמצעות Terraform

אשכול של Kubernetes מספק שירותי מחשוב, אחסון, רשת ושירותים אחרים לאפליקציות, בדומה למרכז נתונים וירטואלי. אפליקציות והשירותים המשויכים להן שפועלים ב-Kubernetes נקראים עומסי עבודה.

במדריך הזה תוכלו לראות במהירות אשכול פעיל של Google Kubernetes Engine ועומס עבודה לדוגמה, שמוגדרים באמצעות Terraform. אחרי שתסיימו את המדריך, תוכלו לעיין בעומס העבודה במסוף Google Cloud , ואז לעבור אל תוכנית הלימודים המעמיקה יותר שלנו, או להתחיל לתכנן וליצור אשכול משלכם שמוכן להפקה. במדריך הזה אנחנו מניחים שאתם כבר מכירים את Terraform.

אם אתם מעדיפים להגדיר את אשכול הדוגמה ואת עומס העבודה ב Google Cloud מסוף, תוכלו לעיין במאמר יצירת אשכול ב Google Cloud מסוף.

לפני שמתחילים

כדי להפעיל את Kubernetes Engine API:

  1. נכנסים לחשבון Google Cloud . אם אתם משתמשים חדשים ב- Google Cloud, צרו חשבון כדי שתוכלו להעריך את הביצועים של המוצרים שלנו בתרחישים מהעולם האמיתי. לקוחות חדשים מקבלים בחינם גם קרדיט בשווי 300$ להרצה, לבדיקה ולפריסה של עומסי העבודה.
  2. התקינו את ה-CLI של Google Cloud.

  3. אם אתם משתמשים בספק זהויות חיצוני (IdP), קודם אתם צריכים להיכנס ל-CLI של gcloud באמצעות המאגר המאוחד לניהול זהויות.

  4. כדי לאתחל את ה-CLI של gcloud, הריצו את הפקודה הבאה:

    gcloud init
  5. יוצרים או בוחרים Google Cloud פרויקט.

    תפקידים שנדרשים כדי לבחור או ליצור פרויקט

    • Select a project: כדי לבחור פרויקט לא צריך תפקיד IAM ספציפי – אפשר לבחור כל פרויקט שקיבלתם בו תפקיד.
    • יצירת פרויקט: כדי ליצור פרויקט, צריך את התפקיד Project Creator (roles/resourcemanager.projectCreator), שכולל את ההרשאה resourcemanager.projects.create. איך מקצים תפקידים
    • יוצרים Google Cloud פרויקט:

      gcloud projects create PROJECT_ID

      מחליפים את PROJECT_ID בשם של פרויקט Google Cloud שיוצרים.

    • בוחרים את הפרויקט שיצרתם: Google Cloud

      gcloud config set project PROJECT_ID

      מחליפים את PROJECT_ID בשם הפרויקט ב- Google Cloud .

  6. מוודאים שהחיוב מופעל בפרויקט Google Cloud .

  7. מפעילים את GKE API, אם הוא עדיין לא מופעל:

    תפקידים שנדרשים להפעלת ממשקי API

    כדי להפעיל ממשקי API, נדרשת ההרשאה serviceusage.services.enable. אם יצרתם את הפרויקט, סביר להניח שכבר יש לכם את ההרשאה הזו דרך התפקיד 'בעלים' (roles/owner). אחרת, תוכלו לקבל את ההרשאה הזו דרך התפקיד 'אדמין בממשק Service Usage' (roles/serviceusage.serviceUsageAdmin). איך מקצים תפקידים

    gcloud services enable container.googleapis.com
  8. התקינו את ה-CLI של Google Cloud.

  9. אם אתם משתמשים בספק זהויות חיצוני (IdP), קודם אתם צריכים להיכנס ל-CLI של gcloud באמצעות המאגר המאוחד לניהול זהויות.

  10. כדי לאתחל את ה-CLI של gcloud, הריצו את הפקודה הבאה:

    gcloud init
  11. יוצרים או בוחרים Google Cloud פרויקט.

    תפקידים שנדרשים כדי לבחור או ליצור פרויקט

    • Select a project: כדי לבחור פרויקט לא צריך תפקיד IAM ספציפי – אפשר לבחור כל פרויקט שקיבלתם בו תפקיד.
    • יצירת פרויקט: כדי ליצור פרויקט, צריך את התפקיד Project Creator (roles/resourcemanager.projectCreator), שכולל את ההרשאה resourcemanager.projects.create. איך מקצים תפקידים
    • יוצרים Google Cloud פרויקט:

      gcloud projects create PROJECT_ID

      מחליפים את PROJECT_ID בשם של פרויקט Google Cloud שיוצרים.

    • בוחרים את הפרויקט שיצרתם: Google Cloud

      gcloud config set project PROJECT_ID

      מחליפים את PROJECT_ID בשם הפרויקט ב- Google Cloud .

  12. מוודאים שהחיוב מופעל בפרויקט Google Cloud .

  13. מפעילים את GKE API, אם הוא עדיין לא מופעל:

    תפקידים שנדרשים להפעלת ממשקי API

    כדי להפעיל ממשקי API, נדרשת ההרשאה serviceusage.services.enable. אם יצרתם את הפרויקט, סביר להניח שכבר יש לכם את ההרשאה הזו דרך התפקיד 'בעלים' (roles/owner). אחרת, תוכלו לקבל את ההרשאה הזו דרך התפקיד 'אדמין בממשק Service Usage' (roles/serviceusage.serviceUsageAdmin). איך מקצים תפקידים

    gcloud services enable container.googleapis.com
  14. מעניקים תפקידים לחשבון המשתמש. מריצים את הפקודה הבאה לכל אחד מהתפקידים הבאים ב-IAM: roles/container.admin, roles/compute.networkAdmin, roles/iam.serviceAccountUser

    gcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE

    מחליפים את מה שכתוב בשדות הבאים:

    • ‫PROJECT_ID: מזהה הפרויקט.
    • ‫USER_IDENTIFIER: המזהה של חשבון המשתמש . לדוגמה, myemail@example.com.
    • ‫ROLE: תפקיד ה-IAM שאתם מקצים לחשבון המשתמש.

הכנת הסביבה

במדריך הזה תשתמשו ב-Cloud Shell כדי לנהל משאבים שמתארחים ב-Google Cloud. ב-Cloud Shell מותקן מראש התוכנה שדרושה למדריך הזה, כולל Terraform,‏ kubectl ו-Google Cloud CLI.

  1. מפעילים סשן Cloud Shell מהמסוף Google Cloud על ידי לחיצה על סמל ההפעלה של Cloud Shell‏ Activate Cloud Shell‏ כפתור ההפעלה של Shell. כך ייפתח סשן בחלונית התחתונה של Google Cloud המסוף.

    פרטי הכניסה לשירות שמשויכים למכונה הווירטואלית נוצרים אוטומטית, כך שלא צריך ליצור או להוריד מפתח לחשבון שירות.

  2. לפני שמריצים פקודות, מגדירים את פרויקט ברירת המחדל ב-CLI של gcloud באמצעות הפקודה הבאה:

    gcloud config set project PROJECT_ID
    

    מחליפים את PROJECT_ID במזהה הפרויקט.

  3. משכפלים את המאגר ב-GitHub:

    git clone https://github.com/terraform-google-modules/terraform-docs-samples.git --single-branch
    
  4. עוברים לספריית העבודה:

    cd terraform-docs-samples/gke/quickstart/autopilot
    

בדיקת קובצי Terraform

‫Google Cloud פלאגין שמתממשק עם שירותים חיצוניים הוא פלאגין שמאפשר לכם לנהל ולהקצות Google Cloud משאבים באמצעות Terraform. הוא משמש כגשר בין ההגדרות של Terraform לבין ממשקי API של Google Cloud , ומאפשר להגדיר משאבי תשתית כמו מכונות וירטואליות ורשתות באופן הצהרתי.

האפליקציה לדוגמה והאשכול במדריך הזה מוגדרים בשני קבצי Terraform שמשתמשים בספקי Google Cloud וב-Kubernetes.

  1. בודקים את הקובץ cluster.tf:

    cat cluster.tf
    

    הפלט אמור להיראות כך:

    resource "google_compute_network" "default" {
      name = "example-network"
    
      auto_create_subnetworks  = false
      enable_ula_internal_ipv6 = true
    }
    
    resource "google_compute_subnetwork" "default" {
      name = "example-subnetwork"
    
      ip_cidr_range = "10.0.0.0/16"
      region        = "us-central1"
    
      stack_type       = "IPV4_IPV6"
      ipv6_access_type = "INTERNAL" # Change to "EXTERNAL" if creating an external loadbalancer
    
      network = google_compute_network.default.id
      secondary_ip_range {
        range_name    = "services-range"
        ip_cidr_range = "192.168.0.0/24"
      }
    
      secondary_ip_range {
        range_name    = "pod-ranges"
        ip_cidr_range = "192.168.1.0/24"
      }
    }
    
    resource "google_container_cluster" "default" {
      name = "example-autopilot-cluster"
    
      location                 = "us-central1"
      enable_autopilot         = true
      enable_l4_ilb_subsetting = true
    
      network    = google_compute_network.default.id
      subnetwork = google_compute_subnetwork.default.id
    
      ip_allocation_policy {
        stack_type                    = "IPV4_IPV6"
        services_secondary_range_name = google_compute_subnetwork.default.secondary_ip_range[0].range_name
        cluster_secondary_range_name  = google_compute_subnetwork.default.secondary_ip_range[1].range_name
      }
    
      # Set `deletion_protection` to `true` will ensure that one cannot
      # accidentally delete this instance by use of Terraform.
      deletion_protection = false
    }

    בקובץ הזה מתוארים המשאבים הבאים:

  2. בודקים את הקובץ app.tf:

    cat app.tf
    

    הפלט אמור להיראות כך:

    data "google_client_config" "default" {}
    
    provider "kubernetes" {
      host                   = "https://${google_container_cluster.default.endpoint}"
      token                  = data.google_client_config.default.access_token
      cluster_ca_certificate = base64decode(google_container_cluster.default.master_auth[0].cluster_ca_certificate)
    
      ignore_annotations = [
        "^autopilot\\.gke\\.io\\/.*",
        "^cloud\\.google\\.com\\/.*"
      ]
    }
    
    resource "kubernetes_deployment_v1" "default" {
      metadata {
        name = "example-hello-app-deployment"
      }
    
      spec {
        selector {
          match_labels = {
            app = "hello-app"
          }
        }
    
        template {
          metadata {
            labels = {
              app = "hello-app"
            }
          }
    
          spec {
            container {
              image = "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"
              name  = "hello-app-container"
    
              port {
                container_port = 8080
                name           = "hello-app-svc"
              }
    
              security_context {
                allow_privilege_escalation = false
                privileged                 = false
                read_only_root_filesystem  = false
    
                capabilities {
                  add  = []
                  drop = ["NET_RAW"]
                }
              }
    
              liveness_probe {
                http_get {
                  path = "/"
                  port = "hello-app-svc"
    
                  http_header {
                    name  = "X-Custom-Header"
                    value = "Awesome"
                  }
                }
    
                initial_delay_seconds = 3
                period_seconds        = 3
              }
            }
    
            security_context {
              run_as_non_root = true
    
              seccomp_profile {
                type = "RuntimeDefault"
              }
            }
    
            # Toleration is currently required to prevent perpetual diff:
            # https://github.com/hashicorp/terraform-provider-kubernetes/pull/2380
            toleration {
              effect   = "NoSchedule"
              key      = "kubernetes.io/arch"
              operator = "Equal"
              value    = "amd64"
            }
          }
        }
      }
    }
    
    resource "kubernetes_service_v1" "default" {
      metadata {
        name = "example-hello-app-loadbalancer"
        annotations = {
          "networking.gke.io/load-balancer-type" = "Internal" # Remove to create an external loadbalancer
        }
      }
    
      spec {
        selector = {
          app = kubernetes_deployment_v1.default.spec[0].selector[0].match_labels.app
        }
    
        ip_family_policy = "RequireDualStack"
    
        port {
          port        = 80
          target_port = kubernetes_deployment_v1.default.spec[0].template[0].spec[0].container[0].port[0].name
        }
    
        type = "LoadBalancer"
      }
    
      depends_on = [time_sleep.wait_service_cleanup]
    }
    
    # Provide time for Service cleanup
    resource "time_sleep" "wait_service_cleanup" {
      depends_on = [google_container_cluster.default]
    
      destroy_duration = "180s"
    }

    בקובץ הזה מתוארים המשאבים הבאים:

(אופציונלי) חשיפת האפליקציה לאינטרנט

קבצי Terraform לדוגמה מתארים אפליקציה עם כתובת IP פנימית, שאפשר לגשת אליה רק מאותו ענן וירטואלי פרטי (VPC) שבו נמצאת אפליקציית הדוגמה. אם רוצים לגשת לממשק האינטרנט של אפליקציית ההדגמה הפועלת מהאינטרנט (לדוגמה, מהמחשב הנייד), צריך לשנות את קובצי Terraform כדי ליצור כתובת IP ציבורית לפני שיוצרים את האשכול. אפשר לעשות את זה באמצעות עורך טקסט ישירות ב-Cloud Shell או באמצעות Cloud Shell Editor.

כדי לחשוף את אפליקציית ההדגמה לאינטרנט:

  1. ב-cluster.tf, משנים את ipv6_access_type מ-INTERNAL ל-EXTERNAL.

    ipv6_access_type = "EXTERNAL"
    
  2. ב-app.tf, מסירים את ההערה networking.gke.io/load-balancer-type כדי להגדיר מאזן עומסים חיצוני.

     annotations = {
       "networking.gke.io/load-balancer-type" = "Internal" # Remove this line
     }
    

יצירת אשכול ופריסת אפליקציה

  1. ב-Cloud Shell, מריצים את הפקודה הבאה כדי לוודא ש-Terraform זמין:

    terraform
    

    הפלט אמור להיראות כך:

    Usage: terraform [global options] <subcommand> [args]
    
    The available commands for execution are listed below.
    The primary workflow commands are given first, followed by
    less common or more advanced commands.
    
    Main commands:
      init          Prepare your working directory for other commands
      validate      Check whether the configuration is valid
      plan          Show changes required by the current configuration
      apply         Create or update infrastructure
      destroy       Destroy previously-created infrastructure
    
  2. מאתחלים את Terraform:

    terraform init
    
  3. מתכננים את ההגדרות של Terraform:

    terraform plan
    
  4. החלת ההגדרות של Terraform

    terraform apply
    

    כשמופיעה בקשה, מזינים yes כדי לאשר את הפעולות. השלמת הפקודה הזו עשויה להימשך כמה דקות. הפלט אמור להיראות כך:

    Apply complete! Resources: 6 added, 0 changed, 0 destroyed.
    

אימות הפעולה של האשכול

כדי לוודא שהאשכול פועל בצורה תקינה:

  1. נכנסים לדף Workloads במסוף Google Cloud :

    כניסה לדף Workloads

  2. לוחצים על עומס העבודה example-hello-app-deployment. יוצג הדף Pod details. בדף הזה מוצג מידע על ה-Pod, כמו הערות, קונטיינרים שפועלים ב-Pod, שירותים שחושפים את ה-Pod ומדדים, כולל שימוש במעבד, בזיכרון ובדיסק.

  3. נכנסים לדף Services & Ingress במסוף Google Cloud :

    כניסה אל Services & Ingress

  4. לוחצים על example-hello-app-loadbalancer LoadBalancer Service. יוצג הדף Service details (דף הפרטים). בדף הזה מוצג מידע על השירות, כמו ה-Pods שמשויכים לשירות והיציאות שבהן השירות משתמש.

  5. בקטע External endpoints (נקודות קצה חיצוניות), לוחצים על הקישור IPv4 או על הקישור IPv6 כדי להציג את השירות בדפדפן. הפלט אמור להיראות כך:

    Hello, world!
    Version: 2.0.0
    Hostname: example-hello-app-deployment-5df979c4fb-kdwgr
    

הסרת המשאבים

כדי לא לצבור חיובים בחשבון Google Cloud על המשאבים שבהם השתמשתם בדף הזה, אתם צריכים למחוק את הפרויקט Google Cloud יחד עם המשאבים.

אם אתם מתכננים לעבור מדריכים נוספים או להמשיך לבדוק את הדוגמה, כדאי לחכות עד שתסיימו כדי לבצע את שלב הניקוי הזה.

  • ב-Cloud Shell, מריצים את הפקודה הבאה כדי למחוק את משאבי Terraform:

    terraform destroy --auto-approve
    

פתרון בעיות בניקוי

אם מופיעה הודעת שגיאה דומה ל-The network resource 'projects/PROJECT_ID/global/networks/example-network' is already being used by 'projects/PROJECT_ID/global/firewalls/example-network-yqjlfql57iydmsuzd4ot6n5v', מבצעים את הפעולות הבאות:

  1. מוחקים את הכללים של חומת האש:

    gcloud compute firewall-rules list --filter="NETWORK:example-network" --format="table[no-heading](name)" | xargs gcloud --quiet compute firewall-rules delete
    
  2. מריצים מחדש את פקודת Terraform:

    terraform destroy --auto-approve
    

המאמרים הבאים