הרצת שאילתות וצפייה ביומנים

שאילתות ביומנים ב-Google Distributed Cloud (GDC)‎ עם air gap מאפשרות לבדוק אירועים תפעוליים ואירועי ביקורת בעומסי העבודה של הפרויקט אחרי איסוף היומנים. אתם יכולים לסנן, להציג ולייצא זרמי יומנים בחלונית Log ב-Grafana באמצעות ביטויים של Log Query Language ‏(LogQL). בתהליכי עבודה פרוגרמטיים, שולחים שאילתה ל-Log Query API של הארגון באמצעות HTTP או gRPC, לפי השיטות הרגילות לגישה ל-API.

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

כדי לשלוח שאילתות ליומנים ולהציג אותם, אתם צריכים את ההרשאות הנדרשות.

בקשת תפקידים ב-IAM ברמת הארגון

כדי לבקש את התפקידים הבאים, פנו למנהל החשבון הארגוני ב-IAM:

  • צפייה ב-Grafana ברמת הארגון (organization-grafana-viewer): הצגה חזותית של נתונים גלויים שקשורים לארגון במרכזי הבקרה של מכונת הניטור של Grafana.
  • מגיש שאילתות ביומנים (log-query-api-querier-pa): גישה ל-Log Query API כדי להגיש שאילתות ביומני הפלטפורמה בפרויקט platform-obs.

בקשת תפקידי IAM בפרויקט

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

  • צפייה ב-Grafana בפרויקט (project-grafana-viewer): הצגה חזותית של נתוני ניטור שקשורים לפרויקט במרכזי הבקרה של מכונת הניטור של Grafana במרחב השמות של הפרויקט.
  • שאילתות ביומנים (log-query-api-querier): גישה ל-Log Query API כדי לשלוח שאילתות ליומני האפליקציות במרחב השמות של הפרויקט.

בטבלה הבאה מפורטות הדרישות של Role לגבי התפקידים של מנהל השותפים ובעל החשבון:

פרסונה אובייקט אשכול תפקיד מרחב שמות קבוצה/משתמש
PA grafana שרת API לניהול project-grafana-viewer platform-obs קבוצה
PA log-query-api שרת API לניהול log-query-api-querier-pa platform-obs קבוצה
PA grafana שרת API לניהול project-grafana-viewer platform-obs משתמש
PA log-query-api שרת API לניהול log-query-api-querier-pa platform-obs משתמש
AO grafana שרת API לניהול project-grafana-viewer PROJECT_NAMESPACE קבוצה
AO log-query-api שרת API לניהול log-query-api-querier PROJECT_NAMESPACE קבוצה
AO grafana שרת API לניהול project-grafana-viewer PROJECT_NAMESPACE משתמש
AO log-query-api שרת API לניהול log-query-api-querier PROJECT_NAMESPACE משתמש

בוחרים אחת מההגדרות הבאות כדי לתת ל-Grafana גישה לקבוצת משתמשים (Config 1) או למשתמש יחיד (Config 2) בשרת ה-API לניהול. בכל הגדרה, אתם יכולים להריץ את הפקודה kubectl כדי ליצור את RoleBinding ישירות, או לשמור את המניפסט של RoleBinding בפורמט YAML בנתיב הקובץ של תשתית כקוד (IaC) שצוין, כדי להחיל אותו באמצעות GitOps:

הגדרה 1

ההגדרה הזו נותנת לקבוצת משתמשים הרשאות גישה ל-PA ול-AO Grafana בשרת ה-API לניהול. אחרי שמסיימים את ההגדרה, אפשר לעיין בקטע לוחות הבקרה של Grafana במסמך הזה כדי לראות את היומנים ב-Grafana.

  • פקודת kubectl

    מריצים את הפקודה הבאה כדי ליצור את RoleBinding ישירות:

    kubectl --kubeconfig KUBECONFIG create rolebinding RULE_NAME -n platform-obs --group=GROUP_NAME --role=project-grafana-viewer
    

    לדוגמה:

    kubectl --kubeconfig KUBECONFIG_PATH create rolebinding project-grafana-viewers-binding --role=project-grafana-viewer --group=my-team --namespace=platform-obs
    
  • נתיב קובץ IaC

    לחלופין, כדי לנהל את RoleBinding באמצעות IaC, יוצרים את קובץ ה-YAML בנתיב הבא:

    /infrastructure/zonal/zones/ZONE/org-admin/rolebindings/GROUP_NAME/YAML_FILE
    
  • קובץ YAML

    שומרים את המניפסט הבא של RoleBinding בקובץ ה-YAML בנתיב הקובץ של ה-IaC:

    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: RULE_NAME
      namespace: platform-obs
    subjects:
    - kind: Group
      name: GROUP_NAME
      apiGroup: rbac.authorization.k8s.io
    roleRef:
      kind: Role
      name: project-grafana-viewer
      apiGroup: rbac.authorization.k8s.io
    

הגדרה 2

ההגדרה הזו נותנת למשתמש הרשאות גישה ל-PA ול-AO Grafana בשרת ה-API לניהול. אחרי שמסיימים את ההגדרה, אפשר לעיין בקטע לוחות הבקרה של Grafana במסמך הזה כדי לראות את היומנים ב-Grafana.

  • פקודת kubectl

    מריצים את הפקודה הבאה כדי ליצור את RoleBinding ישירות:

    kubectl --kubeconfig KUBECONFIG create rolebinding RULE_NAME -n platform-obs --user=EMAIL_ADDRESS --role=project-grafana-viewer
    

    לדוגמה:

    kubectl --kubeconfig KUBECONFIG_PATH create rolebinding project-grafana-viewers-binding --role=project-grafana-viewer --user=my-email@example.com --namespace=platform-obs
    
  • נתיב קובץ IaC

    לחלופין, כדי לנהל את RoleBinding באמצעות IaC, יוצרים את קובץ ה-YAML בנתיב הבא:

    /infrastructure/zonal/zones/ZONE/org-admin/rolebindings/EMAIL_ADDRESS/YAML_FILE
    
  • קובץ YAML

    שומרים את המניפסט הבא של RoleBinding בקובץ ה-YAML בנתיב הקובץ של ה-IaC:

    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: RULE_NAME
      namespace: platform-obs
    subjects:
    - kind: User
      name: EMAIL_ADDRESS
      apiGroup: rbac.authorization.k8s.io
    roleRef:
      kind: Role
      name: project-grafana-viewer
      apiGroup: rbac.authorization.k8s.io
    

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

  • ‫KUBECONFIG: הנתיב לקובץ kubeconfig של האשכול הספציפי שמכיל את ה-NAMESPACE שבו חל ה-RoleBinding הזה.
  • ‫KUBECONFIG_PATH: הנתיב לקובץ kubeconfig בפקודות לדוגמה.
  • ‫RULE_NAME: השם הייחודי של המשאב RoleBinding במרחב השמות, למשל pa-project-grafana-viewer.
  • ‫NAMESPACE: מרחב השמות של Kubernetes שבו נוצר ומוחל ה-RoleBinding. חפשו את העמודה Namespace בטבלה הקודמת.
  • ‫EMAIL_ADDRESS: המזהה של המשתמש שמקבל את התפקיד, למשל application-operator@example.com.
  • ‫ROLE: השם של Role שמכיל את ההרשאות שרוצים לתת למשתמש. חפשו את התפקידים שזמינים בטבלה הקודמת.
  • ‫GROUP_NAME: השם של Group שאליו שייך המשתמש ב-PA, למשל pa-group.
  • ‫ZONE: שם האזור.
  • ‫YAML_FILE: השם של קובץ ה-YAML של המשאב RoleBinding.

למידע נוסף על התפקידים האלה, ראו הכנת הרשאות IAM.

שאילתות וסינון של היומנים

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

חלונית היומן של Grafana

בקטע הזה מוסבר איך לגשת ליומנים באמצעות החלונית Log ב-Grafana.

זיהוי נקודת הקצה (endpoint) של Grafana

כתובת ה-URL הבאה היא נקודת הקצה של המכונה של Grafana בפרויקט:

  https://GDC_URL/PROJECT_NAMESPACE/grafana

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

  • ‫GDC_URL: כתובת ה-URL של הארגון ב-GDC.
  • ‫PROJECT_NAMESPACE: מרחב השמות של הפרויקט.

    לדוגמה, נקודת הקצה של Grafana לפרויקט platform-obs בארגון org-1 היא https://org-1/platform-obs/grafana.

הצגת יומנים בממשק המשתמש של Grafana

יומני שאילתות בממשק המשתמש של Grafana:

  1. בוחרים את הפרויקט במסוף GDC.
  2. בתפריט הניווט, לוחצים על Operations > Logging.
  3. לוחצים על View all in Grafana Loki.

    דף חדש פותח את נקודת הקצה של Grafana ומציג את ממשק המשתמש.

  4. בממשק המשתמש, לוחצים על explore Explore בתפריט הניווט כדי לפתוח את הדף Explore.

  5. בתפריט שבסרגל Explore, בוחרים מקור נתונים כדי לאחזר יומנים, בהתאם לסוג היקום:

    • סביבות עם אזור אחד: בוחרים אחד ממקורות הנתונים הבאים כדי להציג נתוני רישום ביומן מהאזור היחיד בסביבה:

      • יומנים תפעוליים: הצגת יומנים תפעוליים.
      • יומני ביקורת: הצגת יומני ביקורת.
    • יקומים עם כמה אזורים: Grafana יכולה להתחבר לאזורים שונים ולהציג נתונים מאזורים שונים. כדי להציג נתוני רישום ביומן מכל אזור ב-Universe, בלי קשר לאזור שאליו נכנסתם, אתם יכולים לבחור אחד ממקורות הנתונים הבאים:

      • ‫Operational logs ZONE_NAME: הצגת יומני פעילות מאזור מסוים.
      • יומני ביקורת ZONE_NAME: הצגת יומני ביקורת מאזור מסוים.

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

  6. מזינים שאילתה כדי לחפש יומנים מהחלונית Log באמצעות ביטויי LogQL (שפת שאילתות של יומנים). אפשר לבצע את השלב הזה באחת מהדרכים הבאות:

    • משתמשים בממשק האינטראקטיבי של הכלי ליצירת שאילתות. אחר כך לוחצים על Run query.
    • מזינים את השאילתה ישירות בשדה הטקסט ולוחצים על Shift+Enter כדי להריץ אותה.

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

    האפשרות "יומני ביקורת" נבחרת בדף "ניתוח" כדי לקבל יומני ביקורת.

    איור 1. אפשרות בתפריט לשליחת שאילתות על יומני ביקורת מממשק המשתמש של Grafana.

    בתמונה 1, האפשרות Audit logs מציגה את הממשק שמאפשר ליצור שאילתות מ-Grafana כדי לאחזר יומני ביקורת.

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

בחירת טווח תאריכים ליומנים

כדי לשלוח שאילתה על יומנים בטווח זמן מסוים, פועלים לפי השלבים הבאים:

  1. לוחצים על התפריט Time Picker ב-Grafana.

  2. בתפריט, מבצעים אחת מהפעולות הבאות:

    • בוחרים אפשרויות של טווח זמן יחסי, למשל 30 הדקות האחרונות.
    • כדי להגדיר טווחי זמן מוחלטים בהתאמה אישית, בוחרים תאריכים ושעות ספציפיים ביומן ולוחצים על Apply time range.
  3. אם רוצים, לוחצים על Change time settings כדי לשנות את ההגדרות של Timezone ו-Fiscal year מהפקדים של טווח התאריכים.

    הגדרות הזמן נשמרות לכל מרכז בקרה בנפרד. מידע נוסף על שאילתות בטווח זמן מסוים זמין בכתובת https://grafana.com/docs/loki/latest/reference/api/#query-loki-over-a-range-of-time.

Log Query API

בקטע הזה מוסבר איך לגשת ליומנים באמצעות Log Query API.

זיהוי נקודת קצה ל-API של Log Query

Log Query API חושף את שתי נקודות הקצה הבאות כדי לשלוח שאילתות ליומני הביקורת וליומנים התפעוליים:

  • נקודת קצה של יומן ביקורת:

    audit-log-query-api.ORG_DOMAIN
    
  • נקודת קצה (endpoint) של יומן תפעולי:

    operational-log-query-api.ORG_DOMAIN
    

מחליפים את ORG_DOMAIN בשם הדומיין של הארגון. אפשר לראות את המאפיין הזה באמצעות הפקודה gdcloud config list. שם הדומיין חייב להיות בפורמט org-name.zone.google.gdch.com. לדוגמה, לארגון בשם org-1, באזור zone1 ובסביבת בדיקה, יש דומיין כמו org-1.zone1.google.gdch.test.

ל-Log Query API יש שלוש אפשרויות של נקודות קצה:

  • ‫labels: הצגת רשימה של כל התוויות בפרויקט.
  • ‫labels/labels/LABEL/values: הצגת רשימה של ערכי תוויות ספציפיים לפרויקט.
  • ‫logs: הצגת רשימה של יומנים בפרויקט ספציפי.

מידע נוסף זמין במאמרי העזרה של ה-API.

שליחת שאילתה

שולחים שאילתה לנקודת קצה ל-API של יומן שאילתות באמצעות לקוחות HTTP או gRPC.

HTTP

פועלים לפי ההוראות לגישה ישירה ל-API באמצעות צד הלקוח ב-HTTP. אתם יכולים להסתמך על kubectl כדי לנהל את האימות או לטפל באימות בעצמכם.

שליחת שאילתות ל-Log Query API באמצעות צד הלקוח ב-HTTP כמו curl,‏ wget או צד הלקוח ב-HTTP שאתם יוצרים ומנהלים. בדוגמה הבאה משתמשים בכלי curl כדי לשלוח שאילתה ל-API, ואפשר להשתמש בפורמט דומה לפקודות wget:

  1. מאמתים את בקשת ה-cURL:

    1. מורידים ומתקינים את ה-CLI של gdcloud.
    2. מגדירים את המאפיין core/organization_console_url של gdcloud:

      gdcloud config set core/organization_console_url https://GDC_URL
      

      מחליפים את GDC_URL בכתובת ה-URL של הארגון ב-GDC.

    3. נכנסים באמצעות ספק הזהויות שהוגדר:

      gdcloud auth login
      
    4. משתמשים בשם המשתמש ובסיסמה כדי לאמת את החשבון ולהיכנס אליו.

    5. מייצאים את אסימון הזהות של החשבון שצוין למשתנה סביבה:

      export TOKEN="$($HOME/gdcloud auth print-identity-token --audiences=https://LOG_QUERY_API_ENDPOINT)"
      

      מחליפים את LOG_QUERY_API_ENDPOINT בנקודת הקצה ל-API של Log Query שממנה רוצים לשלוח שאילתות ליומנים, ובדומיין שאליו רוצים להתחבר. לכן, הערך של הדגל audiences יכול להיות, לדוגמה, https://operational-log-query-api.org-1.zone1.google.gdch.test.

      אחרי ההתחברות, אפשר להשתמש בכותרת ההרשאה בבקשת ה-cURL באמצעות הפקודה gdcloud auth print-identity-token. מידע נוסף זמין במאמר gdcloud auth print-identity-token.

  2. כדי להציג את כל התוויות של פרויקט, שולחים את השאילתה הבאה:

    curl -H "Authorization: Bearer ${TOKEN}" \
    https://LOG_QUERY_API_ENDPOINT/v1/projects/PROJECT_NAMESPACE/labels \
    -H "Content-Type: application/json" -v
    

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

    • ‫LOG_QUERY_API_ENDPOINT: נקודת קצה ל-API של Log Query שממנה רוצים לשלוח שאילתות ליומנים.
    • ‫PROJECT_NAMESPACE: מרחב השמות של הפרויקט.
  3. כדי להציג רשימה של ערכי תוויות ספציפיים לפרויקט, שולחים את השאילתה הבאה:

    curl -H "Authorization: Bearer ${TOKEN}" \
    https://LOG_QUERY_API_ENDPOINT/v1/projects/PROJECT_NAMESPACE/labels/labels/LABEL/values \
    -H "Content-Type: application/json" -v
    

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

    • ‫LOG_QUERY_API_ENDPOINT: נקודת קצה ל-API של Log Query שממנה רוצים לשלוח שאילתות ליומנים.
    • ‫PROJECT_NAMESPACE: מרחב השמות של הפרויקט.
    • ‫LABEL: התווית הספציפית שרוצים לשלוח שאילתה לגבי הערך שלה.
  4. אם רוצים לשלוח שאילתה ליומנים של פרויקט ספציפי, צריך ליצור שאילתת logs_filter ולכלול אותה בגוף הבקשה:

    curl -X GET -H "Authorization: Bearer ${TOKEN}" \
    https://LOG_QUERY_API_ENDPOINT/v1/projects/PROJECT_NAMESPACE/logs \
    -H "Content-Type: application/json" -d \
    '{"logs_filter": {"labels_equal": {"LABEL": "LABEL_VALUE"}}}' -v
    

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

    • ‫LOG_QUERY_API_ENDPOINT: נקודת קצה ל-API של Log Query שממנה רוצים לשלוח שאילתות ליומנים.
    • ‫PROJECT_NAMESPACE: מרחב השמות של הפרויקט.
    • ‫LABEL: התווית הספציפית שרוצים לשלוח שאילתה ליומנים שלה.
    • ‫LABEL_VALUE: ערך התווית שלגביו רוצים לשלוח שאילתה ליומנים.

    במאמרי העזרה של ה-API מפורטות כל האפשרויות ליצירת שאילתת logs_filter.

gRPC

‫gRPC נתמך באופן נרחב בשפות תכנות, ומספק שיטת תקשורת יעילה יותר בהשוואה לצד הלקוח ב-HTTP.

כדי לשלוח שאילתות ליומנים באמצעות gRPC, צריך לעמוד בדרישות המוקדמות הבאות:

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

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

בדוגמה הבאה מוסבר איך לשלוח שאילתות ליומנים מתוכנית Go באמצעות לקוח gRPC לא מאומת. בדוגמה הזו, נניח שיצרתם חבילת golang שכוללת קובץ build של Bazel כדי לייבא יחסי תלות של קוד:

  1. שומרים את הקוד הבא בתוכנית Go בשם client.go:

    package main
    import (
            "context"
            "crypto/tls"
            "flag"
            "fmt"
            "google.golang.org/grpc/credentials"
            "google.golang.org/grpc/metadata"
            pb "<import path to generated log query api protos>/pkg/apis/public/logging/v1/proto"
            "google.golang.org/grpc"
    )
    
    var serverAddr = flag.String("server", "localhost:8080", "server address")
    
    func main() {
            flag.Parse()
            tc := credentials.NewTLS(&tls.Config{InsecureSkipVerify: true})
            conn, err := grpc.Dial(*serverAddr, grpc.WithTransportCredentials(tc))
    
            if err != nil {
                    panic(error.Error(fmt.Errorf("create client connection failed: %v", err)))
            }
            defer conn.Close()
    
            c := pb.NewLogsClient(conn)
            md := metadata.Pairs("clienttest", "test")
            ctx := metadata.NewOutgoingContext(context.Background(), md)
    
            err = listLabels(ctx, c, "project-foo")
            if err != nil {
                    panic(error.Error(err))
            }
    
            if err := listLabelValues(ctx, c, "project-foo", "resource-bar"); err != nil {
                    panic(error.Error(err))
            }
    
            if err := listLogs(ctx, c, "project-foo", &pb.ListLogsFilter{
                    LabelsEqual:    map[string]string{"resource-bar": "resource-bar-value"},
                    OrderAscending: true,
            }); err != nil {
                    panic(error.Error(err))
            }
    }
    
    // List all labels for a project.
    
    func listLabels(ctx context.Context, c pb.LogsClient, project string) error {
            lbr := &pb.ListLabelsRequest{
                    Parent:   project,
                    PageSize: 1000, // PageSize can be configured to limit the number of responses per page.
            }
            resp, err := c.ListLabels(ctx, lbr)
            if err != nil {
                    return fmt.Errorf("list labels: %v", err)
            }
            fmt.Printf("%v", resp)
            return nil
    }
    
    // List specific label values for a project.
    
    func listLabelValues(ctx context.Context, c pb.LogsClient, project string, label string) error {
            lbr := &pb.ListLabelValuesRequest{
                    Parent:   project,
                    Label:    label,
                    PageSize: 1000, // PageSize can be configured to limit the number of responses per page.
            }
            resp, err := c.ListLabelValues(ctx, lbr)
            if err != nil {
                    return fmt.Errorf("list label values: %v", err)
            }
            fmt.Printf("%v", resp)
            return nil
    }
    
    // List logs for a specific project.
    
    func listLogs(ctx context.Context, c pb.LogsClient, project string, lf *pb.ListLogsFilter) error {
            lbr := &pb.ListLogsRequest{
                    Parent:     project,
                    LogsFilter: lf,
                    PageSize:   5, // PageSize can be configured to limit the number of responses per page.
            }
            resp, err := c.ListLogs(ctx, lbr)
            if err != nil {
                    return fmt.Errorf("list logs: %v", err)
            }
            fmt.Printf("logs: %v", resp)
            return nil
    }
    
  2. מריצים את תוכנית Go:

    go run PATH_TO_API/client.go -server=LOG_QUERY_API_ENDPOINT:443
    

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

    אם לא מציינים את דגל השרת, בקשת ברירת המחדל מגיעה אל localhost.

שאילתות ותוויות לדוגמה

אלה כמה מהתוויות שמוגדרות כברירת מחדל, שבהן אפשר להשתמש כדי לשלוח שאילתות ליומנים:

  • ‫cluster: שם האשכול.
  • ‫namespace: מרחב השמות של הפרויקט.
  • ‫node: שם הצומת.
  • ‫pod: שם ה-Pod.
  • ‫container: שם המאגר.

דוגמאות הקוד הבאות מראות איך להשתמש בתוויות ובערכים כדי לשלוח שאילתות ליומנים שונים:

  • בחירת יומני שרת:

    {cluster="admin", namespace="kube-system", resources="k8s_container", container="kube-apiserver"}
    
  • בחירת יומני ביקורת של אשכולות:

    {cluster="admin", resources="k8s_audit"}