מדריך: ניפוי באגים של אירועי ניתוב ל-Cloud Run

במדריך הזה נסביר איך לפתור שגיאות בזמן ריצה שנתקלים בהן כשמשתמשים ב-Eventarc כדי לנתב אירועים מ-Cloud Storage לשירות לא מאומת של Cloud Run באמצעות יומני הביקורת של Cloud.

מטרות

במדריך הזה מוסבר איך לבצע את הפעולות הבאות:

  1. יוצרים מאגר רגיל של Artifact Registry כדי לאחסן את קובץ האימג' בקונטיינר.
  2. יוצרים קטגוריה של Cloud Storage שתשמש כמקור האירועים.
  3. יצירה, העלאה ופריסה של קובץ אימג' של קונטיינר ל-Cloud Run.
  4. יצירת טריגרים של Eventarc.
  5. מעלים קובץ לקטגוריה של Cloud Storage.
  6. לפתור בעיות ולתקן את שגיאות זמן הריצה.

עלויות

במסמך הזה משתמשים ברכיבים הבאים של Google Cloud, והשימוש בהם כרוך בתשלום:

כדי להעריך את ההוצאות בהתאם לתחזית השימוש שלכם, אתם יכולים להיעזר במחשבון העלויות.

משתמשים חדשים של Google Cloud ? יכול להיות שאתם זכאים לתקופת ניסיון בחינם.

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

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

  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. מפעילים את ממשקי ה-API של Artifact Registry,‏ Cloud Build,‏ Cloud Logging,‏ Cloud Run,‏ Cloud Storage,‏ Eventarc ו-Pub/Sub:

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

    כדי להפעיל ממשקי API, צריך את תפקיד ה-IAM 'אדמין של Service Usage' (roles/serviceusage.serviceUsageAdmin), שכולל את ההרשאה serviceusage.services.enable. איך מקצים תפקידים

    gcloud services enable artifactregistry.googleapis.com cloudbuild.googleapis.com eventarc.googleapis.com logging.googleapis.com pubsub.googleapis.com run.googleapis.com storage.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. מפעילים את ממשקי ה-API של Artifact Registry,‏ Cloud Build,‏ Cloud Logging,‏ Cloud Run,‏ Cloud Storage,‏ Eventarc ו-Pub/Sub:

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

    כדי להפעיל ממשקי API, צריך את תפקיד ה-IAM 'אדמין של Service Usage' (roles/serviceusage.serviceUsageAdmin), שכולל את ההרשאה serviceusage.services.enable. איך מקצים תפקידים

    gcloud services enable artifactregistry.googleapis.com cloudbuild.googleapis.com eventarc.googleapis.com logging.googleapis.com pubsub.googleapis.com run.googleapis.com storage.googleapis.com
  14. אם אתם יוצרי הפרויקט, מוקצה לכם תפקיד הבעלים הבסיסי (roles/owner). כברירת מחדל, תפקיד ניהול הזהויות והרשאות הגישה (IAM) הזה כולל את ההרשאות שנדרשות לגישה מלאה לרוב המשאבים Google Cloud, ואפשר לדלג על השלב הזה.

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

    שימו לב: כברירת מחדל, ההרשאות של Cloud Build כוללות הרשאות להעלאה ולהורדה של ארטיפקטים מ-Artifact Registry.

    ההרשאות הנדרשות

    כדי לקבל את ההרשאות שדרושות להשלמת המדריך הזה, צריך לבקש מהאדמין להקצות לכם בפרויקט את תפקידי ה-IAM הבאים:

    להסבר על מתן תפקידים, ראו איך מנהלים את הגישה ברמת הפרויקט, התיקייה והארגון.

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

  15. ב-Cloud Storage, מפעילים את יומני הביקורת עבור סוגי הגישה לנתונים ADMIN_READ, ‏DATA_WRITE ו-DATA_READ.

    1. קוראים את מדיניות ניהול הזהויות והרשאות הגישה (IAM) שמשויכת ל Google Cloud פרויקט, לתיקייה או לארגון ומאחסנים אותה בקובץ זמני:
      gcloud projects get-iam-policy PROJECT_ID > /tmp/policy.yaml
    2. פותחים את הקובץ /tmp/policy.yaml בעורך טקסט ומוסיפים או משנים רק את ההגדרה של יומן הביקורת בקטע auditConfigs:

      auditConfigs:
      - auditLogConfigs:
        - logType: ADMIN_READ
        - logType: DATA_WRITE
        - logType: DATA_READ
        service: storage.googleapis.com
      bindings:
      - members:
      [...]
      etag: BwW_bHKTV5U=
      version: 1
    3. כותבים את מדיניות ה-IAM החדשה:
      gcloud projects set-iam-policy PROJECT_ID /tmp/policy.yaml

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

  16. מקצים את התפקיד eventarc.eventReceiver לחשבון השירות של Compute Engine:

    export PROJECT_NUMBER="$(gcloud projects describe $(gcloud config get-value project) --format='value(projectNumber)')"
    
    gcloud projects add-iam-policy-binding $(gcloud config get-value project) \
        --member=serviceAccount:${PROJECT_NUMBER}-compute@developer.gserviceaccount.com \
        --role='roles/eventarc.eventReceiver'

  17. אם הפעלתם את חשבון השירות של Pub/Sub ב-8 באפריל 2021 או לפני כן, צריך להקצות את התפקיד iam.serviceAccountTokenCreator לחשבון השירות של Pub/Sub:

    gcloud projects add-iam-policy-binding $(gcloud config get-value project) \
        --member="serviceAccount:service-${PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com"\
        --role='roles/iam.serviceAccountTokenCreator'

  18. מגדירים את ברירות המחדל שמשמשות במדריך הזה:
    export REGION=us-central1
    gcloud config set run/region ${REGION}
    gcloud config set run/platform managed
    gcloud config set eventarc/location ${REGION}

יצירת מאגר רגיל ב-Artifact Registry

יוצרים מאגר רגיל של Artifact Registry לאחסון קובץ האימג' של הקונטיינר:

gcloud artifacts repositories create REPOSITORY \
    --repository-format=docker \
    --location=$REGION

מחליפים את REPOSITORY בשם ייחודי למאגר.

יצירת קטגוריה של Cloud Storage

יוצרים קטגוריה של Cloud Storage בכל אחד משני אזורים כמקור האירועים לשירות Cloud Run:

  1. יוצרים קטגוריה ב-us-east1:

    export BUCKET1="troubleshoot-bucket1-PROJECT_ID"
    gcloud storage buckets create gs://${BUCKET1} --location=us-east1
  2. יוצרים קטגוריה ב-us-west1:

    export BUCKET2="troubleshoot-bucket2-PROJECT_ID"
    gcloud storage buckets create gs://${BUCKET2} --location=us-west1

אחרי שיוצרים את מקור האירועים, פורסים את שירות מקבל האירועים ב-Cloud Run.

פריסת מקלט האירועים

פריסת שירות Cloud Run שמקבל אירועים ומתעד אותם ביומן.

  1. מאחזרים את דוגמת הקוד על ידי שיבוט של מאגר GitHub:

    המשך

    git clone https://github.com/GoogleCloudPlatform/golang-samples.git
    cd golang-samples/eventarc/audit_storage
    

    Java

    git clone https://github.com/GoogleCloudPlatform/java-docs-samples.git
    cd java-docs-samples/eventarc/audit-storage
    

    ‎.NET

    git clone https://github.com/GoogleCloudPlatform/dotnet-docs-samples.git
    cd dotnet-docs-samples/eventarc/audit-storage
    

    Node.js

    git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git
    cd nodejs-docs-samples/eventarc/audit-storage
    

    Python

    git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
    cd python-docs-samples/eventarc/audit-storage
    
  2. כדאי לעיין בקוד של המדריך הזה, שכולל את הרכיבים הבאים:

    • גורם מטפל באירועים שמקבל את האירוע הנכנס כ-CloudEvent בבקשת HTTP‏ POST:

      המשך

      
      // Processes CloudEvents containing Cloud Audit Logs for Cloud Storage
      package main
      
      import (
      	"fmt"
      	"log"
      	"net/http"
      	"os"
      
      	cloudevent "github.com/cloudevents/sdk-go/v2"
      )
      
      // HelloEventsStorage receives and processes a Cloud Audit Log event with Cloud Storage data.
      func HelloEventsStorage(w http.ResponseWriter, r *http.Request) {
      	if r.Method != http.MethodPost {
      		http.Error(w, "Expected HTTP POST request with CloudEvent payload", http.StatusMethodNotAllowed)
      		return
      	}
      
      	event, err := cloudevent.NewEventFromHTTPRequest(r)
      	if err != nil {
      		log.Printf("cloudevent.NewEventFromHTTPRequest: %v", err)
      		http.Error(w, "Failed to create CloudEvent from request.", http.StatusBadRequest)
      		return
      	}
      	s := fmt.Sprintf("Detected change in Cloud Storage bucket: %s", event.Subject())
      	fmt.Fprintln(w, s)
      }
      

      Java

      import io.cloudevents.CloudEvent;
      import io.cloudevents.rw.CloudEventRWException;
      import io.cloudevents.spring.http.CloudEventHttpUtils;
      import org.springframework.http.HttpHeaders;
      import org.springframework.http.HttpStatus;
      import org.springframework.http.ResponseEntity;
      import org.springframework.web.bind.annotation.RequestBody;
      import org.springframework.web.bind.annotation.RequestHeader;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RequestMethod;
      import org.springframework.web.bind.annotation.RestController;
      
      @RestController
      public class EventController {
      
        @RequestMapping(value = "/", method = RequestMethod.POST, consumes = "application/json")
        public ResponseEntity<String> receiveMessage(
            @RequestBody String body, @RequestHeader HttpHeaders headers) {
          CloudEvent event;
          try {
            event =
                CloudEventHttpUtils.fromHttp(headers)
                    .withData(headers.getContentType().toString(), body.getBytes())
                    .build();
          } catch (CloudEventRWException e) {
            return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
          }
      
          String ceSubject = event.getSubject();
          String msg = "Detected change in Cloud Storage bucket: " + ceSubject;
          System.out.println(msg);
          return new ResponseEntity<>(msg, HttpStatus.OK);
        }
      }

      ‎.NET

      
      using Microsoft.AspNetCore.Builder;
      using Microsoft.AspNetCore.Hosting;
      using Microsoft.AspNetCore.Http;
      using Microsoft.Extensions.DependencyInjection;
      using Microsoft.Extensions.Hosting;
      using Microsoft.Extensions.Logging;
      
      public class Startup
      {
          public void ConfigureServices(IServiceCollection services)
          {
          }
      
          public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger<Startup> logger)
          {
              if (env.IsDevelopment())
              {
                  app.UseDeveloperExceptionPage();
              }
      
              logger.LogInformation("Service is starting...");
      
              app.UseRouting();
      
              app.UseEndpoints(endpoints =>
              {
                  endpoints.MapPost("/", async context =>
                  {
                      logger.LogInformation("Handling HTTP POST");
      
                      var ceSubject = context.Request.Headers["ce-subject"];
                      logger.LogInformation($"ce-subject: {ceSubject}");
      
                      if (string.IsNullOrEmpty(ceSubject))
                      {
                          context.Response.StatusCode = 400;
                          await context.Response.WriteAsync("Bad Request: expected header Ce-Subject");
                          return;
                      }
      
                      await context.Response.WriteAsync($"GCS CloudEvent type: {ceSubject}");
                  });
              });
          }
      }
      

      Node.js

      const express = require('express');
      const app = express();
      
      app.use(express.json());
      app.post('/', (req, res) => {
        if (!req.header('ce-subject')) {
          return res
            .status(400)
            .send('Bad Request: missing required header: ce-subject');
        }
      
        console.log(
          `Detected change in Cloud Storage bucket: ${req.header('ce-subject')}`
        );
        return res
          .status(200)
          .send(
            `Detected change in Cloud Storage bucket: ${req.header('ce-subject')}`
          );
      });
      
      module.exports = app;

      Python

      @app.route("/", methods=["POST"])
      def index():
          # Create a CloudEvent object from the incoming request
          event = from_http(request.headers, request.data)
          # Gets the GCS bucket name from the CloudEvent
          # Example: "storage.googleapis.com/projects/_/buckets/my-bucket"
          bucket = event.get("subject")
      
          print(f"Detected change in Cloud Storage bucket: {bucket}")
          return (f"Detected change in Cloud Storage bucket: {bucket}", 200)
      
      
    • שרת שמשתמש בגורם שמטפל באירועים:

      המשך

      
      func main() {
      	http.HandleFunc("/", HelloEventsStorage)
      	// Determine port for HTTP service.
      	port := os.Getenv("PORT")
      	if port == "" {
      		port = "8080"
      	}
      	// Start HTTP server.
      	log.Printf("Listening on port %s", port)
      	if err := http.ListenAndServe(":"+port, nil); err != nil {
      		log.Fatal(err)
      	}
      }
      

      Java

      
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      
      @SpringBootApplication
      public class Application {
        public static void main(String[] args) {
          SpringApplication.run(Application.class, args);
        }
      }

      ‎.NET

          public static void Main(string[] args)
          {
              CreateHostBuilder(args).Build().Run();
          }
          public static IHostBuilder CreateHostBuilder(string[] args)
          {
              var port = Environment.GetEnvironmentVariable("PORT") ?? "8080";
              var url = $"http://0.0.0.0:{port}";
      
              return Host.CreateDefaultBuilder(args)
                  .ConfigureWebHostDefaults(webBuilder =>
                  {
                      webBuilder.UseStartup<Startup>().UseUrls(url);
                  });
          }
      

      Node.js

      const app = require('./app.js');
      const PORT = parseInt(process.env.PORT) || 8080;
      
      app.listen(PORT, () =>
        console.log(`nodejs-events-storage listening on port ${PORT}`)
      );

      Python

      import os
      
      from cloudevents.http import from_http
      
      from flask import Flask, request
      
      app = Flask(__name__)
      if __name__ == "__main__":
          app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
    • קובץ Dockerfile שמגדיר את סביבת ההפעלה של השירות. התוכן של קובץ ה-Dockerfile משתנה בהתאם לשפה:

      המשך

      
      # Use the official Go image to create a binary.
      # This is based on Debian and sets the GOPATH to /go.
      # https://hub.docker.com/_/golang
      FROM golang:1.25-bookworm as builder
      
      # Create and change to the app directory.
      WORKDIR /app
      
      # Retrieve application dependencies.
      # This allows the container build to reuse cached dependencies.
      # Expecting to copy go.mod and if present go.sum.
      COPY go.* ./
      RUN go mod download
      
      # Copy local code to the container image.
      COPY . ./
      
      # Build the binary.
      RUN go build -v -o server
      
      # Use the official Debian slim image for a lean production container.
      # https://hub.docker.com/_/debian
      # https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
      FROM debian:bookworm-slim
      RUN set -x && apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
          ca-certificates && \
          rm -rf /var/lib/apt/lists/*
      
      # Copy the binary to the production image from the builder stage.
      COPY --from=builder /app/server /server
      
      # Run the web service on container startup.
      CMD ["/server"]
      

      Java

      
      # Use the official maven image to create a build artifact.
      # https://hub.docker.com/_/maven
      FROM maven:3-eclipse-temurin-17-alpine as builder
      
      # Copy local code to the container image.
      WORKDIR /app
      COPY pom.xml .
      COPY src ./src
      
      # Build a release artifact.
      RUN mvn package -DskipTests
      
      # Use Eclipse Temurin for base image.
      # https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
      FROM eclipse-temurin:17.0.18_8-jre-alpine
      
      # Copy the jar to the production image from the builder stage.
      COPY --from=builder /app/target/audit-storage-*.jar /audit-storage.jar
      
      # Run the web service on container startup.
      CMD ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/audit-storage.jar"]
      

      ‎.NET

      
      # Use Microsoft's official build .NET image.
      # https://hub.docker.com/_/microsoft-dotnet-core-sdk/
      FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build
      WORKDIR /app
      
      # Install production dependencies.
      # Copy csproj and restore as distinct layers.
      COPY *.csproj ./
      RUN dotnet restore
      
      # Copy local code to the container image.
      COPY . ./
      WORKDIR /app
      
      # Build a release artifact.
      RUN dotnet publish -c Release -o out
      
      
      # Use Microsoft's official runtime .NET image.
      # https://hub.docker.com/_/microsoft-dotnet-core-aspnet/
      FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine AS runtime
      WORKDIR /app
      COPY --from=build /app/out ./
      
      # Run the web service on container startup.
      ENTRYPOINT ["dotnet", "AuditStorage.dll"]

      Node.js

      
      # Use the official lightweight Node.js image.
      # https://hub.docker.com/_/node
      FROM node:20-slim
      # Create and change to the app directory.
      WORKDIR /usr/src/app
      
      # Copy application dependency manifests to the container image.
      # A wildcard is used to ensure both package.json AND package-lock.json are copied.
      # Copying this separately prevents re-running npm install on every code change.
      COPY package*.json ./
      
      # Install dependencies.
      # if you need a deterministic and repeatable build create a 
      # package-lock.json file and use npm ci:
      # RUN npm ci --omit=dev
      # if you need to include development dependencies during development
      # of your application, use:
      # RUN npm install --dev
      
      RUN npm install --omit=dev
      
      # Copy local code to the container image.
      COPY . .
      
      # Run the web service on container startup.
      CMD [ "npm", "start" ]
      

      Python

      
      # Use the official Python image.
      # https://hub.docker.com/_/python
      FROM python:3.14-slim
      
      # Allow statements and log messages to immediately appear in the Cloud Run logs
      ENV PYTHONUNBUFFERED True
      
      # Copy application dependency manifests to the container image.
      # Copying this separately prevents re-running pip install on every code change.
      COPY requirements.txt ./
      
      # Install production dependencies.
      RUN pip install -r requirements.txt
      
      # Copy local code to the container image.
      ENV APP_HOME /app
      WORKDIR $APP_HOME
      COPY . ./
      
      # Run the web service on container startup. 
      # Use gunicorn webserver with one worker process and 8 threads.
      # For environments with multiple CPU cores, increase the number of workers
      # to be equal to the cores available.
      CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app

  3. יוצרים את קובץ אימג' של קונטיינר באמצעות Cloud Build ומעלים את קובץ אימג' של קונטיינר ל-Artifact Registry:

    export PROJECT_ID=$(gcloud config get-value project)
    export SERVICE_NAME=troubleshoot-service
    gcloud builds submit --tag $REGION-docker.pkg.dev/${PROJECT_ID}/REPOSITORY/${SERVICE_NAME}:v1
  4. פורסים את קובץ האימג' של הקונטיינר ב-Cloud Run:

    gcloud run deploy ${SERVICE_NAME} \
        --image $REGION-docker.pkg.dev/${PROJECT_ID}/REPOSITORY/${SERVICE_NAME}:v1 \
        --allow-unauthenticated

    אם הפריסה מצליחה, כתובת ה-URL של השירות מוצגת בשורת הפקודה.

יצירת טריגר

אחרי שפורסים שירות Cloud Run, מגדירים טריגר להאזנה לאירועים מ-Cloud Storage באמצעות יומני ביקורת.

  1. יוצרים טריגר Eventarc להאזנה לאירועים של Cloud Storage שמנותבים באמצעות יומני הביקורת של Cloud:

    gcloud eventarc triggers create troubleshoot-trigger \
        --destination-run-service=troubleshoot-service \
        --event-filters="type=google.cloud.audit.log.v1.written" \
        --event-filters="serviceName=storage.googleapis.com" \
        --event-filters="methodName=storage.objects.create" \
        --service-account=${PROJECT_NUMBER}-compute@developer.gserviceaccount.com
    

    הפעולה הזו יוצרת טריגר בשם troubleshoot-trigger.

  2. כדי לוודא שנוצר troubleshoot-trigger, מריצים את הפקודה:

    gcloud eventarc triggers list
    

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

    NAME: troubleshoot-trigger
    TYPE: google.cloud.audit.log.v1.written
    DESTINATION: Cloud Run service: troubleshoot-service
    ACTIVE: By 20:03:37
    LOCATION: us-central1
    

יצירה והצגה של אירוע

מוודאים שהפריסה של השירות בוצעה בהצלחה ושאפשר לקבל אירועים מ-Cloud Storage.

  1. יוצרים ומעלים קובץ לBUCKET1 קטגוריית האחסון:

     echo "Hello World" > random.txt
     gcloud storage cp random.txt gs://${BUCKET1}/random.txt
    
  2. עוקבים אחרי היומנים כדי לבדוק אם השירות קיבל אירוע. כדי לראות את רשומת היומן, פועלים לפי השלבים הבאים:

    1. מסננים את רשומות היומן ומחזירים את הפלט בפורמט JSON:

      gcloud logging read "resource.labels.service_name=troubleshoot-service \
          AND textPayload:random.txt" \
          --format=json
    2. מחפשים רשומה ביומן שדומה ל:

      "textPayload": "Detected change in Cloud Storage bucket: ..."
      

שימו לב: בהתחלה לא מוחזרת רשומה ביומן. השגיאה הזו מציינת שיש בעיה בהגדרה שצריך לבדוק.

בדיקת הבעיה

עוברים על תהליך הבדיקה כדי להבין למה השירות לא מקבל אירועים.

זמן האתחול

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

gcloud eventarc triggers list

הפלט מציין את הסטטוס של הטריגר. בדוגמה הבאה, הקמפיין troubleshoot-trigger יופעל עד השעה 14:16:56:

NAME                  TYPE                               DESTINATION_RUN_SERVICE  ACTIVE
troubleshoot-trigger  google.cloud.audit.log.v1.written  troubleshoot-service     By 14:16:56

אחרי שהטריגר פעיל, מעלים שוב קובץ לדלי האחסון. האירועים נכתבים ביומני השירות של Cloud Run. אם השירות לא מקבל אירועים, יכול להיות שהבעיה קשורה לגודל האירועים.

יומני ביקורת

במדריך הזה, אירועים ב-Cloud Storage מנותבים באמצעות יומני הביקורת של Cloud ונשלחים ל-Cloud Run. מוודאים שיומני הביקורת מופעלים ב-Cloud Storage.

  1. נכנסים לדף Audit logs במסוף Google Cloud .

    כניסה ליומני ביקורת

  2. מסמנים את תיבת הסימון Google Cloud Storage.
  3. מוודאים שסוגי היומנים Admin Read,‏ Data Read ו-Data Write מסומנים.

אחרי שמפעילים את יומני הביקורת של Cloud, מעלים שוב את הקובץ לקטגוריית האחסון ובודקים את היומנים. אם השירות עדיין לא מקבל אירועים, יכול להיות שהבעיה קשורה למיקום ההפעלה.

מיקום הטריגר

יכולים להיות כמה משאבים במיקומים שונים, ואתם צריכים לסנן אירועים ממקורות שנמצאים באותו אזור כמו יעד Cloud Run. מידע נוסף זמין במאמרים בנושא מיקומים שנתמכים על ידי Eventarc והסבר על מיקומי Eventarc.

במדריך הזה פרסתם את שירות Cloud Run אל us-central1. הגדרת את eventarc/location ל-us-central1, ולכן יצרת טריגר באותו מיקום.

אבל יצרתם שתי קטגוריות של Cloud Storage במיקומים us-east1 ו-us-west1. כדי לקבל אירועים מהמיקומים האלה, צריך ליצור טריגרים של Eventarc במיקומים האלה.

יוצרים טריגר Eventarc שנמצא ב-us-east1:

  1. מאשרים את המיקום של הטריגר הקיים:

    gcloud eventarc triggers describe troubleshoot-trigger
    
  2. מגדירים את המיקום והאזור ל-us-east1:

    gcloud config set eventarc/location us-east1
    gcloud config set run/region us-east1
    
  3. פורסים שוב את מקבל האירועים על ידי יצירה ופריסה של קובץ האימג' של הקונטיינר ב-Cloud Run.

  4. יוצרים טריגר חדש במיקום us-east1:

    gcloud eventarc triggers create troubleshoot-trigger-new \
      --destination-run-service=troubleshoot-service \
      --event-filters="type=google.cloud.audit.log.v1.written" \
      --event-filters="serviceName=storage.googleapis.com" \
      --event-filters="methodName=storage.objects.create" \
      --service-account=${PROJECT_NUMBER}-compute@developer.gserviceaccount.com
    
  5. בודקים שהטריגר נוצר:

    gcloud eventarc triggers list
    

    יכולות לעבור עד שתי דקות עד שהטריגר יאותחל ויתחיל לנתב אירועים.

  6. כדי לוודא שהטריגר נפרס עכשיו בצורה נכונה, יוצרים אירוע וצופים בו.

בעיות אחרות שאולי יקרו

יכול להיות שתיתקלו בבעיות אחרות כשמשתמשים ב-Eventarc.

גודל האירוע

האירועים שאתם שולחים לא יכולים לחרוג מהמגבלות על גודל האירוע.

טריגר שבעבר העביר אירועים הפסיק לפעול

  1. מוודאים שהמקור יוצר אירועים. בודקים את יומני הביקורת של Cloud ומוודאים שהשירות שבמעקב יוצר יומנים. אם היומנים נרשמים אבל האירועים לא מועברים, פנו לתמיכה.

  2. מוודאים שקיים נושא Pub/Sub עם אותו שם טריגר. ‫Eventarc משתמש ב-Pub/Sub כשכבת התעבורה שלו, והוא ישתמש בנושא Pub/Sub קיים או ייצור נושא באופן אוטומטי וינהל אותו בשבילכם.

    1. כדי לראות רשימה של טריגרים, אפשר לעיין במאמר gcloud eventarc triggers list.
    2. כדי להציג רשימה של נושאי Pub/Sub, מריצים את הפקודה:

      gcloud pubsub topics list
      
    3. מוודאים ששם הנושא ב-Pub/Sub כולל את השם של הטריגר שנוצר. לדוגמה:

      name: projects/PROJECT_ID/topics/eventarc-us-east1-troubleshoot-trigger-new-123

    אם נושא Pub/Sub חסר, צריך ליצור מחדש את הטריגר עבור ספק ספציפי, סוג אירוע ויעד Cloud Run.

  3. מוודאים שהטריגר הוגדר לשירות.

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

      כניסה לדף Services

    2. לוחצים על שם השירות כדי לפתוח את הדף פרטי השירות.

    3. לוחצים על הכרטיסייה טריגרים.

      הטריגר של Eventarc שמשויך לשירות אמור להופיע ברשימה.

  4. בודקים את תקינות הנושא והמינוי ב-Pub/Sub באמצעות סוגי המדדים של Pub/Sub.

    מידע נוסף זמין במאמר בנושא יצירת מדיניות התראות על סמך סף מדד.

הסרת המשאבים

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

מחיקת הפרויקט

הדרך הקלה ביותר לבטל את החיוב היא למחוק את הפרויקט שיצרתם בשביל המדריך הזה.

כדי למחוק את הפרויקט:

  1. במסוף Google Cloud , נכנסים לדף Manage resources.

    כניסה לדף Manage resources

  2. ברשימת הפרויקטים, בוחרים את הפרויקט שרוצים למחוק ולוחצים על Delete.
  3. כדי למחוק את הפרויקט, כותבים את מזהה הפרויקט בתיבת הדו-שיח ולוחצים על Shut down.

מחיקת משאבי הדרכה

  1. מוחקים את שירות Cloud Run שפרסתם במדריך הזה:

    gcloud run services delete SERVICE_NAME

    כאשר SERVICE_NAME הוא שם השירות שבחרתם.

    אפשר גם למחוק שירותים של Cloud Run מGoogle Cloud המסוף.

  2. מסירים את כל הגדרות ברירת המחדל של ה-CLI של gcloud שהוספתם במהלך ההגדרה של המדריך.

    לדוגמה:

    gcloud config unset run/region

    או

    gcloud config unset project

  3. מחיקת משאבים אחרים Google Cloud שנוצרו במדריך הזה:

    • מחיקת הטריגר של Eventarc:
      gcloud eventarc triggers delete TRIGGER_NAME
      
      מחליפים את TRIGGER_NAME בשם הטריגר.

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