Skip to content

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

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

חשבו על סביבת פיתוח זמנית, על כמה מופעי AWS RDS לניסוי קצר או על אשכול Kafka ב־Kubernetes. הספרינט מסתיים והכרטיס נסגר, אבל משאבים עשויים להישאר. אחסון בלוקים שאינו מחובר, כתובות Elastic IP שאינן בשימוש, דליי S3 שאיש אינו עוקב אחריהם ותמונות קונטיינר ישנות עלולים להמשיך לצבור חיובים. גם הבעלות עליהם, התלויות ודרישות שמירת הנתונים עשויות להיות לא ברורות, וליצור סיכונים תפעוליים ואבטחתיים שראוי לבדוק.

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

למה מצטברים בתשתיות הענן ״חדרים נסתרים״

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

  • אחסון בלוקים יתום: אמצעי אחסון EBS במצב available הוא מועמד לבדיקה, ולא הוכחה לכך שננטש. אמצעי אחסון של מערכת ההפעלה שנוצר בעת הפעלת EC2 נמחק בדרך כלל בסיום המופע; ברירות מחדל אחרות תלויות באופן החיבור וב־DeleteOnTermination. כברירת מחדל, StatefulSet שומר PVCs, אך אפשר לשנות את מדיניות השמירה ואת הטיפול ב־PV.
  • תמונות ותוצרי בנייה שננטשו: תמונות יכולות להצטבר בלי מדיניות שמירה המתאימה לצורכי ההפצה והחזרה לגרסה קודמת. יש למדוד את האחסון, ולא להניח שטרה־בייטים מבוזבזים.
  • כתובות IPv4 ציבוריות ומאזני עומסים: AWS מפרסמת אותו תעריף של 0.005 דולר לשעה עבור כתובות IPv4 ציבוריות רגילות שנמצאות בשימוש או אינן בשימוש. יש לבדוק תעריפים וחריגים במחירון העדכני. גם ALB פועל מחויב לפי שעות ללא תעבורת יישום.
  • רשומות DNS ללא יעד בשליטה: רשומות המצביעות למשאבים שכבר אינם בשליטת הארגון עלולות ליצור סיכון להשתלטות אם גורם אחר יכול לקבל או לרשום את היעד. הסיכון המדויק תלוי בסוג הרשומה ובהתנהגות השירות.

המחיר הארכיטקטוני של מה שלא רואים

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

בהתאם לבעלות המוגדרת בתרשימי Helm, למדיניות מחיקה ולשינויים ידניים, אשכול Kubernetes עשוי לשמור משאבים שעומסי העבודה הנוכחיים אינם צריכים עוד. יש למפות ConfigMaps, Secrets ו־PVCs יחד עם בעליהם והגורמים המשתמשים בהם. חשיפת פרטי גישה תלויה בבקרות הגישה ובאפשרות לפגיעה בעומס העבודה; גיל המשאב לבדו אינו חולשה. בשדרוגים יש לבדוק תאימות API, ולא למחוק אובייקטים רק מפני שהם ישנים.

בונים ״לוכד רוחות״: איתור משאבים יתומים בעזרת Python ו־Boto3

כלי Python קטן שמשתמש ב־boto3, ערכת הפיתוח של AWS, יכול להציג אמצעי אחסון EBS במצב available וכתובות Elastic IP שאינן משויכות. הדוגמה שלהלן מיועדת לקריאה בלבד ומוגבלת לפרופיל ולאזור שנבחרו במפורש. התוצאות הן מועמדים לבדיקה, ולא הוכחה לכך שמשאב אינו נחוץ.

בסביבת Python מבודדת, הדוגמה דורשת Boto3. שורת ההתקנה שלהלן היא דוגמת הכנה, ולא פקודה שהורצה לצורך המאמר:

pip install boto3

דוגמת הקריאה בלבד שלהלן מציגה מועמדים לבדיקה בחשבון AWS ובאזור שנבחרו במפורש. היא אינה מערכת מלאי לסביבת ייצור ואינה כלי ניקוי. יש לוודא את החשבון והאזור, להשתמש בתפקיד מורשה עם ההרשאות ec2:DescribeVolumes ו־ec2:DescribeAddresses בלבד, לעבור על כל עמודי תוצאות האחסון ולטפל בשגיאות. לפני כל מחיקה יש לבדוק בעלות, דרישות שמירת נתונים ותלויות. העובדה שמשאב אינו מחובר אינה מוכיחה שאינו נחוץ. העלות תלויה באזור, בסוג האחסון, בביצועים שהוקצו, במשך הזמן ובתעריף החל; אין להתייחס לאומדנים הקבועים שבמקור כאל חשבון חיוב.

import argparse
import json
import sys
import boto3
from botocore.exceptions import BotoCoreError, ClientError

def inventory(ec2):
    volumes = []
    pages = ec2.get_paginator("describe_volumes").paginate(
        Filters=[{"Name": "status", "Values": ["available"]}]
    )
    for page in pages:
        for volume in page.get("Volumes", []):
            volumes.append({
                "VolumeId": volume["VolumeId"],
                "SizeGiB": volume["Size"],
                "Type": volume["VolumeType"],
                "Created": volume["CreateTime"].isoformat(),
                "Tags": volume.get("Tags", []),
            })
    addresses = [
        {"PublicIp": address.get("PublicIp"),
         "AllocationId": address.get("AllocationId"),
         "Tags": address.get("Tags", [])}
        for address in ec2.describe_addresses().get("Addresses", [])
        if not address.get("AssociationId")
    ]
    return {"available_volumes_for_review": volumes,
            "unassociated_addresses_for_review": addresses}

def main():
    parser = argparse.ArgumentParser(description="Read-only, single-Region inventory")
    parser.add_argument("--region", required=True)
    parser.add_argument("--profile", required=True)
    args = parser.parse_args()
    try:
        session = boto3.Session(profile_name=args.profile, region_name=args.region)
        result = inventory(session.client("ec2"))
    except (BotoCoreError, ClientError) as exc:
        print(f"Inventory failed; results are not complete: {exc}", file=sys.stderr)
        return 1
    print(json.dumps({"region": args.region, "profile": args.profile,
                      "note": "Candidates only. Not a cost estimate or deletion approval.",
                      **result}, indent=2))
    return 0

if __name__ == "__main__":
    raise SystemExit(main())

איך מונעים הצטברות של ״חדרים נסתרים״

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

1. תשתית כקוד עם מדיניות מחיקה שנבדקה

Terraform, OpenTofu ו־Pulumi יכולים לסייע במעקב אחר המשאבים שהם מנהלים; הם אינם יוצרים אוטומטית מלאי של כל החשבון. terraform destroy פועל על האובייקטים שמנוהלים בתצורה ובמצב הנוכחיים של Terraform, ועלול למחוק נתוני ייצור. לפני כל שינוי מורשה יש לבדוק תוכנית הריסה מקדימה, תלויות, כללי שמירה וגיבויים שנבדקו.

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

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

2. כללי מחזור חיים לאחסון אובייקטים

יש להגדיר מדיניות שמירה בהתאם לשירות ולצורכי ההפצה, החזרה לגרסה קודמת והציות של הארגון. ב־ECR, כללי מחזור חיים בוחרים תמונות לפי תגים וקריטריונים של גיל או כמות; פקיעת תמונה אינה שקולה למחיקת תג אחד בלבד. לפני החלה יש לבדוק תצוגה מקדימה של המדיניות המדויקת על המאגר, לרבות תמונות עם תגי הפצה ותגים זמניים גם יחד. אין להניח שהתג prod-latest לבדו מגן על תמונה.

3. תזמון הקיבולת של סביבות פיתוח

בסביבות מחשוב שאינן סביבות ייצור, שמותר לפרק ושהפעולה בהן אושרה, שינוי קיבולת מתוזמן יכול לצמצם שעות מופע. כיבוי יומי מ־19:00 עד 08:00 מסיר 13 מתוך 24 שעות, כ־54.2% משעות המופע המתוכננות לפני שיקולי חיוב ותפעול; זו אינה הבטחה לגבי החשבון הכולל. יש להגדיר קיבולת רצויה וגבולות מינימום ומקסימום תואמים, לציין אזור זמן ולהביא בחשבון זמני הפעלה וזמינות. צמצום קיבולת ב־EC2 Auto Scaling מסיים מופעים ואינו רק משהה אותם. אמצעי אחסון מתמידים, snapshots, כתובות IP ושירותים נוספים עשויים להישאר ולהמשיך לצבור חיובים; צמצום לאפס אינו מבטיח ניקוי של מצב זמני.

סיכום: מדליקים את האור

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

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

עכשיו תורכם: מהו המשאב הגדול ביותר שהיה ״חדר נסתר״ וגיליתם בסביבת הענן שלכם? האם זו הייתה מכונה וירטואלית סוררת בגודל 8XL שעמדה ללא שימוש מאז 2021, או מסד נתונים לבדיקות שעלה אלפים בכל חודש? ספרו לי בתגובות, או שתפו את הפוסט ב־Twitter/X או ב־LinkedIn!

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

מקורות לבדיקה נוספת

Post a Comment

Previous Post Next Post