יצירת אשכול ופריסת עומס עבודה באמצעות 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, צריך את תפקיד ה-IAM 'אדמין של Service Usage' (roles/serviceusage.serviceUsageAdmin), שכולל את ההרשאה serviceusage.services.enable. איך מקצים תפקידים

    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, צריך את תפקיד ה-IAM 'אדמין של Service Usage' (roles/serviceusage.serviceUsageAdmin), שכולל את ההרשאה serviceusage.services.enable. איך מקצים תפקידים

    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 מהמסוף על ידי לחיצה על סמל ההפעלה של Cloud Shell‏ Activate Cloud Shellכפתור הפעלת Shell. Google Cloud הפעולה הזו תפעיל סשן בחלונית התחתונה של 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'. בדף הזה מוצג מידע על ה-Pod, כמו הערות, קונטיינרים שפועלים ב-Pod, שירותים שחושפים את ה-Pod ומדדים, כולל שימוש ב-CPU, בזיכרון ובדיסק.

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

    כניסה אל Services & Ingress

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

  5. בקטע External endpoints (נקודות קצה חיצוניות), לוחצים על IPv4 link (קישור IPv4) או על IPv6 link (קישור 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
    

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