מדריך קלוד קוד בעברית

תיעוד 76

פריסת Claude apps gateway ב-AWS

דוגמה מעשית להרצת Claude apps gateway ב-AWS: ECS Fargate או EKS, Amazon RDS for PostgreSQL, AWS Secrets Manager, ואימות מבוסס תפקיד IAM מול Amazon Bedrock.

הערה: דף זה מדגים דרך אחת להריץ את Claude apps gateway ב-AWS. התצורה היא דוגמה עובדת עבור תשתית בניהול הלקוח ולא פריסת ייצור רשמית עם תמיכה. השתמשו בה כדי לראות כיצד החלקים מתחברים יחד לפני שתתאימו אותה לסביבה שלכם. לדרישות שאינן תלויות פלטפורמה, עיינו במדריך הפריסה.

דוגמה זו מקצה את Claude apps gateway ב-AWS עם Amazon Bedrock כספק המודל במעלה הזרם (upstream), תוך שימוש ב-Amazon ECS על גבי AWS Fargate או ב-Amazon EKS למחשוב. Okta משמש כספק הזהויות (IdP) לדוגמה, אך כל IdP התואם ל-OpenID Connect (OIDC) יעבוד. עיינו בהגדרת ספק זהויות לפרטים עבור כל IdP.

הערה: Bedrock אינו ה-upstream היחיד עבור Claude ב-AWS. השער תומך גם ב-Claude Platform on AWS, ה-API של Claude המופעל על ידי Anthropic עם אימות של AWS וחיוב דרך AWS Marketplace, במקום Bedrock או לצידו. רשומת ה-upstream שלו, פרטי ההזדהות שלו והרשאות ה-IAM שלו שונים מאלה המוגדרים בדף זה עבור Bedrock. המדריך לתצורת upstream של Claude Platform on AWS מפרט מה משתנה, ושאר הדף חל ללא שינוי.

#ארכיטקטורה

תרשים של Claude apps gateway ב-AWS: לקוחות Claude Code מתחברים ב-HTTPS ל-Application Load Balancer פנימי שנמצא לפני השער (ECS Fargate או EKS), הפועל ברשתות משנה פרטיות לצד מופע Amazon RDS for PostgreSQL עבור מצב ההפעלות. השער מחבר משתמשים באמצעות OIDC מול ה-IdP הארגוני, קורא סודות מ-AWS Secrets Manager, מעביר בקשות מודל ל-Amazon Bedrock באמצעות תפקיד ה-IAM שלו, ומושך את התמונה שלו מ-Amazon ECR בעת הפריסה.

ארכיטקטורת הדוגמה, עם Amazon Bedrock כ-upstream של המודל. רכיב Claude Platform on AWS במעלה הזרם תופס את אותו המיקום.

השער פועל כנקודת קצה פרטית ב-HTTPS ברשת שלכם, שמפתחים מתחברים אליה דרך ה-IdP שלכם. הפעלות ה-Claude Code שלהם מגיעות למודלים של Claude ב-Amazon Bedrock דרך תפקיד ה-IAM של השער, כך ששום פרטי הזדהות של המודל אינם מגיעים למכונות של המפתחים. תצורת הייחוס מקצה:

  • שירות Amazon ECS on AWS Fargate או פריסת (Deployment) של Amazon EKS המריצים את מכולת השער
  • מאגר Amazon ECR עבור תמונת השער
  • מופע Amazon RDS for PostgreSQL ברשתות משנה פרטיות, ללא גישה ציבורית, עבור ה-store של השער
  • סודות ב-AWS Secrets Manager עבור מפתח החתימה של ה-JWT, סוד הלקוח של OIDC (client secret), וכתובת ה-URL של Postgres
  • תפקיד IAM עם הרשאות bedrock:InvokeModel ו-bedrock:InvokeModelWithResponseStream, המצורף כתפקיד משימת ECS (task role) או מקושר דרך IAM Roles for Service Accounts (IRSA) ב-EKS
  • Application Load Balancer פנימי עבור HTTPS

#דרישות מוקדמות

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

  • חשבון AWS עם הרשאות ליצירת המשאבים שלמעלה
  • ה-AWS CLI v2 מותקן ומאומת, ו-Docker מותקן מקומית
  • VPC עם לפחות שתי רשתות משנה פרטיות באזורי זמינות (Availability Zones) שונים, עם גישה יוצאת לאינטרנט דרך NAT gateway. מאזן העומסים הפנימי זקוק לרשתות משנה בשני אזורי זמינות, והשער זקוק לחיבור יוצא (egress) ל-Bedrock ול-IdP שלכם
  • יישום אינטרנט Okta OIDC עם כתובת URI להפניה מחדש (redirect URI): https://<gateway-host>/oauth/callback. עיינו בהגדרת ספק זהויות
  • שם מארח TLS עבור השער, בדרך כלל שם DNS פנימי ב-Route 53 private hosted zone המצביע על מאזן העומסים, עם תעודת ACM עבור שם זה, שיובאה או הונפקה על ידי AWS Private CA

#הגדרת משתני הסביבה שלך

כל פקודה בדף זה קוראת ארבעה ערכים מהמעטפת (shell) שלכם: AWS_REGION, ACCOUNT_ID, VPC_ID, ו-PRIVATE_SUBNETS.

בחרו אזור בארצות הברית (US region) שבו Bedrock מגיש את המודלים של Claude הדרושים לכם. המדריך מסתמך על קטלוג המודלים המובנה של השער, אשר פותר לפרופילי הסקה us.anthropic.*, ומדיניות ה-IAM מעניקה הרשאות עבור ה-ARNs האלה. באזור שאינו בארצות הברית, הוסיפו בלוק models: עם מזהי פרופילי ההסקה של אותו אזור גיאוגרפי ושנו את קידומת ה-ARN במדיניות ה-IAM בהתאם.

אם מזהה ה-VPC אינו זמין עבורכם, הציגו את ה-VPCs שלכם באמצעות aws ec2 describe-vpcs, ולאחר מכן הציגו את רשתות המשנה של אותו VPC כדי למצוא שתי רשתות פרטיות באזורי זמינות שונים:

aws ec2 describe-subnets --filters "Name=vpc-id,Values=<your-vpc-id>" \
  --query 'Subnets[].{ID:SubnetId,AZ:AvailabilityZone,CIDR:CidrBlock}' --output table

בצעו export לארבעתם לפני שתמשיכו:

export AWS_REGION=us-east-1   
# a US region where Bedrock serves the Claude models you need
export ACCOUNT_ID="$(aws sts get-caller-identity --query Account --output text)"
export VPC_ID=<your-vpc-id>
export PRIVATE_SUBNETS="<subnet-id-a> <subnet-id-b>"

#פריסת השער

השלבים שלהלן מקצים את הפריסה המלאה באמצעות פקודות aws.

  1. יצירת קבוצות האבטחה (Create the security groups)

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

    • ב-ECS Fargate, שלב הפריסה מצרף את $ALB_SG למאזן העומסים ואת $GW_SG לשירות.
    • ב-EKS, ה-AWS Load Balancer Controller יוצר קבוצת אבטחה קדמית משלו עבור ה-ALB, כך שאין שימוש ב-$ALB_SG וב-$GW_SG: ההערה inbound-cidrs של שלב הפריסה מגבילה את המאזין (listener) לרשת הארגונית שלכם, וקבוצת האבטחה של מסד הנתונים מקבלת במקום זאת את קבוצת האבטחה של האשכול.
    ALB_SG="$(aws ec2 create-security-group --group-name claude-gateway-alb \
      --description "Claude gateway ALB" --vpc-id "$VPC_ID" \
      --query GroupId --output text)"
    GW_SG="$(aws ec2 create-security-group --group-name claude-gateway-svc \
      --description "Claude gateway service" --vpc-id "$VPC_ID" \
      --query GroupId --output text)"
    DB_SG="$(aws ec2 create-security-group --group-name claude-gateway-db \
      --description "Claude gateway Postgres" --vpc-id "$VPC_ID" \
      --query GroupId --output text)"
    
    aws ec2 authorize-security-group-ingress --group-id "$ALB_SG" \
      --protocol tcp --port 443 --cidr <your-corporate-cidr>
    aws ec2 authorize-security-group-ingress --group-id "$GW_SG" \
      --protocol tcp --port 8080 --source-group "$ALB_SG"
    aws ec2 authorize-security-group-ingress --group-id "$DB_SG" \
      --protocol tcp --port 5432 --source-group "$GW_SG"
  2. יצירת תפקידי IAM והגשת טופס תרחיש השימוש (Create the IAM roles and submit the use case form)

    השער פועל עם תפקיד משימה (task role) ייעודי שההרשאה היחידה שלו היא הפעלת מודלים של Claude ב-Bedrock. בהתאם למדריך לתצורת upstream של Bedrock, המדיניות חייבת לכסות הן את ה-ARNs של פרופילי הסקה חוצי-אזורים (cross-region inference-profile) והן את ה-ARNs של מודלי הבסיס (foundation-model) שמתחתם:

    cat > bedrock-invoke.json <<EOF
    {
      "Version": "2012-10-17",
      "Statement": [{
        "Effect": "Allow",
        "Action": ["bedrock:InvokeModel", "bedrock:InvokeModelWithResponseStream"],
        "Resource": [
          "arn:aws:bedrock:${AWS_REGION}:${ACCOUNT_ID}:inference-profile/us.anthropic.*",
          "arn:aws:bedrock:*::foundation-model/anthropic.*"
        ]
      }]
    }
    EOF
    cat > ecs-trust.json <<'EOF'
    {
      "Version": "2012-10-17",
      "Statement": [{
        "Effect": "Allow",
        "Principal": { "Service": "ecs-tasks.amazonaws.com" },
        "Action": "sts:AssumeRole"
      }]
    }
    EOF
    
    aws iam create-role --role-name claude-gateway-task \
      --assume-role-policy-document file://ecs-trust.json
    aws iam put-role-policy --role-name claude-gateway-task \
      --policy-name bedrock-invoke --policy-document file://bedrock-invoke.json

    ECS זקוק גם לתפקיד ביצוע (execution role), שסוכן ה-ECS עצמו משתמש בו כדי למשוך את התמונה מ-ECR ולהזריק את ערכי Secrets Manager שייווצרו בהמשך. הוא נפרד מתפקיד המשימה (task role) שבו משתמש ה-SDK של AWS של השער בזמן ריצה:

    aws iam create-role --role-name claude-gateway-execution \
      --assume-role-policy-document file://ecs-trust.json
    aws iam attach-role-policy --role-name claude-gateway-execution \
      --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
    cat > secrets-read.json <<EOF
    {
      "Version": "2012-10-17",
      "Statement": [{
        "Effect": "Allow",
        "Action": ["secretsmanager:GetSecretValue", "secretsmanager:DescribeSecret"],
        "Resource": [
          "arn:aws:secretsmanager:${AWS_REGION}:${ACCOUNT_ID}:secret:gateway-jwt-secret-??????",
          "arn:aws:secretsmanager:${AWS_REGION}:${ACCOUNT_ID}:secret:gateway-oidc-client-secret-??????",
          "arn:aws:secretsmanager:${AWS_REGION}:${ACCOUNT_ID}:secret:gateway-postgres-url-??????"
        ]
      }]
    }
    EOF
    aws iam put-role-policy --role-name claude-gateway-execution \
      --policy-name read-gateway-secrets --policy-document file://secrets-read.json

    המדיניות מציינת ARN אחד לכל סוד במקום תו כללי חשוף gateway-*, שבחשבון משותף היה מתאים גם לסודות שאינם קשורים. הסיומת -?????? מתאימה בדיוק לסיומת האקראית בת ששת התווים ש-Secrets Manager מוסיף ל-ARN של כל סוד. סיומת -* הייתה מהווה התאמת קידומת רגילה והייתה מתאימה גם לשמות ארוכים יותר כגון gateway-postgres-url-prod.

    מדיניות ה-IAM מעניקה לשער הרשאה לקרוא ל-Bedrock, ו-Bedrock מאפשר גישה למודל כברירת מחדל באזורים מסחריים. החסם הנותר ברמת החשבון הוא טופס תרחיש השימוש החד-פעמי של Anthropic: אם אף אחד בחשבון שלכם לא הגיש אותו עדיין, פתחו את מסוף Amazon Bedrock, בחרו מודל Anthropic מתוך קטלוג המודלים (Model catalog), והשלימו את הטופס. הגישה ניתנת מיד לאחר ההגשה. עיינו ב-Claude Code ב-Amazon Bedrock עבור טופס AWS Organizations והרשאות ה-IAM שהמגיש זקוק להן.

    מסלול EKS עושה שימוש חוזר בשני מסמכי המדיניות על גבי תפקיד IRSA במקום שני תפקידי ה-ECS. ראו את שלב הפריסה.

  3. הקצאת Amazon RDS for PostgreSQL (Provision Amazon RDS for PostgreSQL)

    המופע רץ ברשתות המשנה הפרטיות ללא כתובת ציבורית ועם הצפנת אחסון מופעלת. גרסת המנוע מקובעת ל-Postgres 16, מה שעונה על הרף המינימלי הנתמך של השער (PostgreSQL 14) ומבטיח שמשפחת קבוצת הפרמטרים להלן תתאים למופע.

    תחילה, צרו את קבוצת רשתות המשנה (subnet group) שממקמת את מסד הנתונים ברשתות המשנה הפרטיות, וקבוצת פרמטרים עם rds.force_ssl=1 כך שהשרת ידחה חיבורים שאינם מוצפנים. גרסת המנוע מקובעת פעם אחת מכיוון שמשפחת קבוצת הפרמטרים חייבת להתאים לגרסה הראשית (major version) של המנוע שהמופע מריץ:

    aws rds create-db-subnet-group --db-subnet-group-name claude-gateway-db \
      --db-subnet-group-description "Claude gateway" --subnet-ids $PRIVATE_SUBNETS
    
    PG_VERSION=16
    PG_FAMILY="postgres${PG_VERSION}"
    aws rds create-db-parameter-group --db-parameter-group-name claude-gateway-db \
      --db-parameter-group-family "$PG_FAMILY" \
      --description "Claude gateway - require TLS on every connection"
    aws rds modify-db-parameter-group --db-parameter-group-name claude-gateway-db \
      --parameters "ParameterName=rds.force_ssl,ParameterValue=1,ApplyMethod=immediate"

    לאחר מכן צרו את המופע עם סיסמת ראשי (master password) שנוצרה:

    PGPASS="$(openssl rand -hex 24)"
    aws rds create-db-instance --db-instance-identifier claude-gateway-db \
      --engine postgres --engine-version "$PG_VERSION" \
      --db-instance-class db.t4g.micro \
      --allocated-storage 20 --db-name claude_gateway \
      --master-username gateway --master-user-password "$PGPASS" \
      --db-subnet-group-name claude-gateway-db \
      --db-parameter-group-name claude-gateway-db \
      --vpc-security-group-ids "$DB_SG" \
      --no-publicly-accessible --storage-encrypted

    הארגומנט המילולי --master-user-password גלוי בטבלת התהליכים וביומני ביקורת/EDR בזמן שהפקודה רצה, אותה חשיפה שההערה בשלב הסודות מכסה. במארח משותף או מנוטר, העבירו את הסיסמה דרך --cli-input-json מתוך קובץ בהרשאות 0600 במקום זאת, כפי שנעשה ב-setup.sh של החבילה.

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

    aws rds wait db-instance-available --db-instance-identifier claude-gateway-db
    DB_HOST="$(aws rds describe-db-instances --db-instance-identifier claude-gateway-db \
      --query 'DBInstances[0].Endpoint.Address' --output text)"
    GATEWAY_POSTGRES_URL="postgres://gateway:${PGPASS}@${DB_HOST}:5432/claude_gateway?sslmode=verify-full"

    הפרמטר sslmode=verify-full גורם לשער לאמת את שרשרת תעודת שרת ה-RDS ואת שם המארח, ולא רק להצפין. עוגן האמון (trust anchor) הוא חבילת התעודות של AWS RDS, ששלב בניית התמונה להלן מעתיק אל /etc/claude/rds-global-bundle.pem ונותן בה אמון דרך NODE_EXTRA_CA_CERTS. אל תוסיפו פרמטר sslrootcert= בסגנון libpq לכתובת ה-URL: מנהל ההתקן (driver) של השער קורא רק את sslmode ממחרוזת השאילתה ויעביר את sslrootcert ל-Postgres כפרמטר אתחול, שהשרת דוחה.

    שירות ה-ECS או תרמילי ה-EKS (pods) חייבים לרוץ ב-VPC הזה כדי שיוכלו להגיע לנקודת הקצה הפרטית של המופע, וקבוצת האבטחה claude-gateway-db מאשרת רק את קבוצת האבטחה של השער.

  4. כתיבת gateway.yaml (Write gateway.yaml)

    בלוק ה-upstreams מצביע על Bedrock עם auth: {}, כך שהשער מבצע אימות דרך שרשרת פרטי ההזדהות של ברירת המחדל של AWS מתפקיד המשימה (task role) ב-ECS או מתפקיד ה-IRSA ב-EKS. עיינו במדריך התצורה עבור כל שדה ושדה.

    שני שדות ב-listen מתארים מה עומד בחזית השער:

    • public_url: מקור ה-https:// החיצוני, הנדרש עבור כל האזנה שאינה loopback. עיינו במדריך ל-listen. השער בונה את ה-redirect_uri של ה-IdP ואת מסמך הגילוי (discovery document) שלו אך ורק מערך זה, לעולם לא מכותרות X-Forwarded-*.
    • trusted_proxies: טווחי המקור של רכיב החזית (front end). השער מכבד את X-Forwarded-For רק כאשר עמית ה-TCP נמצא ברשימה זו, ולאחר מכן מתקדם לאורך השרשרת מעבר לדילוגים מהימנים, כך שמגבלות קצב כניסה לפי IP ואירועי ביקורת יתעדו את כתובות ה-IP של המפתחים במקום את כתובת מאזן העומסים.

    בשני המסלולים רכיב החזית הוא ALB פנימי, בין אם נוצר ישירות ובין אם על ידי ה-AWS Load Balancer Controller, וצמתי ה-ALB מקבלים כתובות מרשתות המשנה שאליהן הוא מחובר, לכן הגדירו את trusted_proxies לטווחי ה-CIDR של אותן רשתות משנה. הגדרה זו מעניקה אמון לכל מארח ברשתות המשנה הללו כפרוקסי. ודאו שמקור הכניסה (ingress) של ה-ALB, שהוא ה-CIDR הארגוני שלכם, אינו חופף אליהן, ואל תשתפו את רשתות המשנה עם עומסי עבודה בלתי מהימנים שעלולים לזייף כתובות IP של לקוחות באמצעות X-Forwarded-For.

    listen:
      host: 0.0.0.0
      port: 8080
      public_url: https://claude-gateway.internal.example.com
      trusted_proxies: [<your-alb-subnet-cidrs>]
    
    oidc:
      issuer: https://example.okta.com
      client_id: 0oa1example2
      client_secret: ${OIDC_CLIENT_SECRET}

#EKS: ${file:/secrets/oidc-client-secret}

 allowed_email_domains: [example.com]

#The Okta org authorization server returns a thin id_token that omits

#email and groups; the gateway fills them from /userinfo.

 userinfo_fallback: true

#Okta emits groups only when the groups scope is requested and the

#app's groups claim filter allows them.

 scopes: [openid, profile, email, offline_access, groups]

session: jwt_secret: ${GATEWAY_JWT_SECRET}

#EKS: ${file:/secrets/jwt-secret}

 ttl_hours: 8                                   

#bounds deprovision latency; lower

#toward 1 for tighter revocation

store: postgres_url: ${GATEWAY_POSTGRES_URL}

#EKS: ${file:/secrets/postgres-url}

upstreams: - provider: bedrock region:

#match $AWS_REGION so the IAM

#policy's ARNs cover it

   auth: {}                                     

#AWS default credential chain:

#ECS task role, or IRSA on EKS


> **הערה:** רק בלוק ה-`oidc` הוא ספציפי ל-Okta. כדי להשתמש ב-Microsoft Entra ID במקום זאת, הגדירו את `issuer` ל-`https://login.microsoftonline.com/<tenant-id>/v2.0`, הסירו את `userinfo_fallback` ואת ה-scope של `groups`, ושימו לב ש-Entra פולט מזהי Object ID של קבוצות ולא שמות, כך ש-[`managed.policies`](/docs/en/claude-apps-gateway-config#managed) חייב לבצע התאמה על ה-GUIDs, או על App Roles עם `oidc.groups_claim: roles`. עיינו ב[הגדרת ספק זהויות](/docs/en/claude-apps-gateway-deploy#identity-provider-setup).

5. **אחסון סודות ב-AWS Secrets Manager (Store secrets in AWS Secrets Manager)**

צרו שלושה סודות. תפקיד הביצוע (execution role) משלב ה-IAM כבר יכול לקרוא אותם:

```bash
aws secretsmanager create-secret --name gateway-jwt-secret \
  --secret-string "$(openssl rand -base64 32)"
aws secretsmanager create-secret --name gateway-oidc-client-secret \
  --secret-string '<your-okta-client-secret>'
aws secretsmanager create-secret --name gateway-postgres-url \
  --secret-string "$GATEWAY_POSTGRES_URL"

שימו לב ל-ARN שכל קריאה מדפיסה: הגדרת משימת ה-ECS (task definition) מפנה לסודות לפי ARN.

הערה: ארגומנטים מילוליים של --secret-string גלויים בטבלת התהליכים וביומני ביקורת/EDR בזמן שכל פקודה רצה. במארח משותף או מנוטר, הניחו את הערך בקובץ בהרשאות 0600 והעבירו --secret-string file://<path> במקום זאת. קובץ ה-setup.sh של החבילה שומר על ערכי סודות מחוץ ל-argv של התהליך באותו אופן, באמצעות העברת קבצים זמניים בהרשאות 0600 אל --cli-input-json.

שלא כמו הסודות, הקובץ gateway.yaml עצמו אינו מכיל ערכים סודיים, מכיוון שכל פרט הזדהות נפתר בעת האתחול באמצעות הרחבת ${VAR} או ${file:...}. האופן שבו הכל מגיע למכולה שונה בין המסלולים:

  • ב-ECS, הבנייה בשלב הבא מעתיקה את gateway.yaml לתוך התמונה בנתיב /etc/claude/gateway.yaml, והגדרת המשימה (task definition) מזריקה את שלושת הסודות כמשתני סביבה דרך השדה secrets שלה, כך שה-YAML מתייחס אל ${GATEWAY_JWT_SECRET}, ${OIDC_CLIENT_SECRET}, ו-${GATEWAY_POSTGRES_URL}.
  • ב-EKS, עגנו (mount) את gateway.yaml מתוך ConfigMap ואת הסודות כקבצים בנתיב /secrets, עם הפניה כ-${file:/secrets/...}. קחו את ה-Kubernetes Secrets מתוך Secrets Manager באמצעות External Secrets Operator או ספק ה-AWS של Secrets Store CSI driver, או צרו אותם ישירות באמצעות kubectl.
  1. בניית התמונה ודחיפתה ל-Amazon ECR (Build and push the image to Amazon ECR)

    בנו את התמונה בהתאם לדרישות תמונת המכולה, והניחו את הבינארי של linux-x64 glibc בנתיב ./claude בהקשר הבנייה (build context). כתבו Dockerfile משלכם בהתאם לדרישות אלו או התחילו מה-Dockerfile של החבילה, שמעתיק את gateway.yaml הממולא מהשלבים הקודמים לתוך התמונה בנתיב /etc/claude/gateway.yaml. ב-ECS העותק המוטמע הזה הוא האופן שבו התצורה מגיעה למכולה, ולכן הבנייה מגיעה לאחר שהקובץ נכתב. מסלול EKS מעגן במקום זאת את gateway.yaml מתוך ConfigMap בעת הפריסה, כך שהעותק המוטמע אינו בשימוש שם.

    התמונה נושאת גם את חבילת התעודות של AWS RDS כעוגן האמון עבור sslmode=verify-full של מחרוזת החיבור, לכן הורידו אותה תחילה לתוך הקשר הבנייה. AWS מבצעת סבב תעודות (רוטציה) לחבילה (נוספים גורמי אישור אזוריים חדשים), לכן הורידו אותה בכל בנייה במקום לקבע חתימת checksum או להכניס אותה למאגר (commit):

    curl -fL --proto '=https' -o rds-global-bundle.pem \
      https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem

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

    COPY rds-global-bundle.pem /etc/claude/rds-global-bundle.pem
    ENV NODE_EXTRA_CA_CERTS=/etc/claude/rds-global-bundle.pem

    צרו את מאגר ה-ECR והתחברו אליו עם Docker. תגיות בלתי ניתנות לשינוי (immutable tags) מבטיחות שלא ניתן יהיה להפנות מאוחר יותר בשקט את התגית <version>, ששלב הפריסה מקבע, לתמונה אחרת:

    aws ecr create-repository --repository-name claude-gateway \
      --image-tag-mutability IMMUTABLE \
      --image-scanning-configuration scanOnPush=true
    aws ecr get-login-password --region "$AWS_REGION" \
      | docker login --username AWS --password-stdin \
        "${ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com"

    בנו ודחפו את התמונה. הגדרת המשימה להלן מריצה linux/amd64, לכן הפלטפורמה חייבת להתאים כאן. עבור Fargate ב-ARM64 (Graviton), בנו linux/arm64 עם הבינארי של linux-arm64 והגדירו את cpuArchitecture ל-ARM64 במקום זאת:

    docker build --platform=linux/amd64 \
      -t "${ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/claude-gateway:<version>" .
    docker push "${ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/claude-gateway:<version>"
  2. פריסה (Deploy)

    מסלול ECS Fargate:

    צרו את האשכול וקבוצת יומנים (log group) עבור ה-stderr של השער, שנושא הן את אירועי הביקורת והן את היומנים התפעוליים שלו. שמירת יומנים (retention) היא קריאה נפרדת, ובלעדיה CloudWatch שומר את היומנים לנצח. התאימו את 90 הימים למדיניות שמירת הביקורת שלכם:

    aws ecs create-cluster --cluster-name claude-gateway
    aws logs create-log-group --log-group-name /ecs/claude-gateway
    aws logs put-retention-policy --log-group-name /ecs/claude-gateway \
      --retention-in-days 90

    כתבו את הגדרת המשימה (task definition). תפקיד המשימה נושא את הרשאת Bedrock ותפקיד הביצוע מזריק את הסודות. השתמשו ב-ARNs של הסודות משלב ה-Secrets Manager:

    {
      "family": "claude-gateway",
      "networkMode": "awsvpc",
      "requiresCompatibilities": ["FARGATE"],
      "cpu": "1024",
      "memory": "2048",
      "runtimePlatform": { "cpuArchitecture": "X86_64", "operatingSystemFamily": "LINUX" },
      "executionRoleArn": "arn:aws:iam::<account-id>:role/claude-gateway-execution",
      "taskRoleArn": "arn:aws:iam::<account-id>:role/claude-gateway-task",
      "containerDefinitions": [
        {
          "name": "gateway",
          "image": "<account-id>.dkr.ecr.<region>.amazonaws.com/claude-gateway:<version>",
          "portMappings": [{ "containerPort": 8080 }],
          "secrets": [
            { "name": "GATEWAY_JWT_SECRET",   "valueFrom": "<gateway-jwt-secret ARN>" },
            { "name": "OIDC_CLIENT_SECRET",   "valueFrom": "<gateway-oidc-client-secret ARN>" },
            { "name": "GATEWAY_POSTGRES_URL", "valueFrom": "<gateway-postgres-url ARN>" }
          ],
          "logConfiguration": {
            "logDriver": "awslogs",
            "options": {
              "awslogs-group": "/ecs/claude-gateway",
              "awslogs-region": "<region>",
              "awslogs-stream-prefix": "gateway"
            }
          }
        }
      ]
    }

    רשמו אותה:

    aws ecs register-task-definition --cli-input-json file://claude-gateway-task.json

    הציבו ALB פנימי בחזית עם קבוצת יעד (target group) שמבצעת בדיקת תקינות (health check) לשער. הבחירה ב---ip-address-type ipv4 חשובה: ALB פנימי בעל תמיכה כפולה (dual-stack) מפרסם רשומות AAAA בטווח הציבורי, ובדיקת הרשת הפרטית של /login דוחה אותן:

    ALB_ARN="$(aws elbv2 create-load-balancer --name claude-gateway \
      --scheme internal --type application --ip-address-type ipv4 \
      --subnets $PRIVATE_SUBNETS --security-groups "$ALB_SG" \
      --query 'LoadBalancers[0].LoadBalancerArn' --output text)"
    
    TG_ARN="$(aws elbv2 create-target-group --name claude-gateway \
      --protocol HTTP --port 8080 --vpc-id "$VPC_ID" --target-type ip \
      --health-check-path /readyz \
      --query 'TargetGroups[0].TargetGroupArn' --output text)"

    הוסיפו את מאזין ה-HTTPS (listener). הדגל --ssl-policy מקבע רף TLS מודרני, שכן השמטתו גורמת לנסיגה לברירת המחדל הישנה ELBSecurityPolicy-2016-08, שעדיין מקבלת TLS 1.0/1.1.

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

    aws elbv2 create-listener --load-balancer-arn "$ALB_ARN" \
      --protocol HTTPS --port 443 \
      --ssl-policy ELBSecurityPolicy-TLS13-1-2-2021-06 \
      --certificates CertificateArn=<your-acm-certificate-arn> \
      --default-actions Type=forward,TargetGroupArn="$TG_ARN"
    
    aws elbv2 modify-load-balancer-attributes --load-balancer-arn "$ALB_ARN" \
      --attributes Key=idle_timeout.timeout_seconds,Value=3600

    צרו את השירות. מנגנון מפסק הפריסה (deployment circuit breaker) מחזיר פריסה שמשימותיה נכשלות שוב ושוב (בשל תמונה לא תקינה או תצורה שאינה יכולה לעלות) למצב היציב האחרון במקום להפעיל מחדש משימות כושלות לנצח:

    aws ecs create-service --cluster claude-gateway --service-name claude-gateway \
      --task-definition claude-gateway --desired-count 1 --launch-type FARGATE \
      --deployment-configuration "deploymentCircuitBreaker={enable=true,rollback=true}" \
      --health-check-grace-period-seconds 60 \
      --network-configuration "awsvpcConfiguration={subnets=[$(echo $PRIVATE_SUBNETS | tr ' ' ',')],securityGroups=[$GW_SG],assignPublicIp=DISABLED}" \
      --load-balancers "targetGroupArn=$TG_ARN,containerName=gateway,containerPort=8080"

    תקופת החסד בת 60 השניות מעניקה למשימה קרה זמן למשוך את התמונה, להתחבר למאגר הנתונים (store) ולענות על בדיקת התקינות הראשונה שלה לפני ש-ECS מתחיל לספור כשלונות כנגד הפריסה. בדיקת התקינות של קבוצת היעד על GET /readyz מוודאת שה-store נגיש, כך שמשימה שאינה יכולה להגיע ל-Postgres לעולם אינה נכנסת לסבב הפעילות. עיינו בהתנהגות בזמן השבתה לגבי הפשרות והחלופה של /healthz.

    המשימות רצות ברשתות משנה פרטיות ללא כתובת IP ציבורית, כך שכל התעבורה היוצאת (אל Bedrock, ה-IdP שלכם, Secrets Manager, ECR ו-CloudWatch Logs) עוברת דרך ה-NAT gateway. כדי לשמור על תעבורת Bedrock מחוץ לנתיב הציבורי, צרו נקודת קצה של ממשק VPC מסוג bedrock-runtime והפנו את ה-base_url של ה-upstream אליה, כפי שמוצג במדריך לתצורת upstream של Bedrock. ה-IdP עדיין זקוק ליציאה לאינטרנט.

    סיימו במתן שם מארח הניתן לפתרון פרטי למפתחים: בתוך Route 53 private hosted zone, הגדירו כינוי (alias) של שם ה-DNS הפנימי של השער ל-ALB, והגדירו את listen.public_url לשם מארח זה. השם *.elb.amazonaws.com של ה-ALB עצמו פותר לכתובות פרטיות ב-ALB פנימי, אך הוא אינו יכול לשאת את תעודת ה-ACM שלכם, לכן השתמשו בשם שלכם.

    עדכנו את ה-redirect URI המורשה של לקוח ה-OAuth ל-<public_url>/oauth/callback לפני הכניסה הראשונה. לאחר שינוי public_url, בנו ודחפו מחדש את התמונה תחת תגית חדשה, רשמו גרסה חדשה של הגדרת המשימה (task definition), ופרסו מחדש. ב-ECS ההגדרה נמצאת בקובץ gateway.yaml המוטמע בתמונה, והשער בונה את המקור הציבורי שלו אך ורק מהגדרה זו, תוך התעלמות מ-X-Forwarded-Host ומ-X-Forwarded-Proto. בכותרת X-Forwarded-For נעשה שימוש עבור כתובות IP של לקוחות רק כאשר listen.trusted_proxies מוגדר.

    מסלול EKS:

    מסלול זה דורש ש-kubectl ו-eksctl יהיו מותקנים מקומית, וכן אשכול EKS קיים עם ספק IAM OIDC ו-AWS Load Balancer Controller מותקנים. האשכול חייב להיות ב-$VPC_ID כדי שתרמילים (pods) יוכלו להגיע לנקודת הקצה הפרטית של RDS, וקבוצת האבטחה claude-gateway-db חייבת לאשר את קבוצת האבטחה של התרמילים או של הצמתים באשכול במקום $GW_SG.

    ב-EKS השער מקבל את פרטי ההזדהות שלו ל-Bedrock דרך IRSA במקום תפקידי ה-ECS. מדיניות האמון ecs-tasks.amazonaws.com משלב ה-IAM אינה חלה כאן. IRSA זקוק לתפקיד שמדיניות האמון שלו מבוססת פדרציה על ספק ה-OIDC של האשכול, בתחום של system:serviceaccount:claude-gateway:gateway. הפקודה eksctl create iamserviceaccount יוצרת את התפקיד הזה, מצרפת את המדיניות ומוסיפה הערה (annotation) לחשבון השירות (service account) של Kubernetes עם ה-ARN של התפקיד בצעד אחד. הפכו את שני מסמכי המדיניות משלב ה-IAM למדיניות מנוהלת שניתן לצרף:

    BEDROCK_POLICY_ARN="$(aws iam create-policy --policy-name claude-gateway-bedrock-invoke \
      --policy-document file://bedrock-invoke.json --query Policy.Arn --output text)"
    SECRETS_POLICY_ARN="$(aws iam create-policy --policy-name claude-gateway-secrets-read \
      --policy-document file://secrets-read.json --query Policy.Arn --output text)"
    
    kubectl create namespace claude-gateway
    eksctl create iamserviceaccount --cluster <your-cluster> --region "$AWS_REGION" \
      --namespace claude-gateway --name gateway --role-name claude-gateway \
      --attach-policy-arn "$BEDROCK_POLICY_ARN" \
      --attach-policy-arn "$SECRETS_POLICY_ARN" \
      --approve

    מדיניות הסודות נדרשת רק כאשר התרמילים קוראים את Secrets Manager בעצמם, כפי שעושה ספק ה-AWS של Secrets Store CSI driver באמצעות חשבון השירות של התרמיל המעגן. השמיטו אותה אם אתם יוצרים את ה-Kubernetes Secrets בדרך אחרת. הספק זקוק לשתי הפעולות של המדיניות: הוא קורא ל-DescribeSecret בעת עדכון וסנכרון סודות שעברו סבב (רוטציה), לכן הרשאה של GetSecretValue בלבד תעגן בפריסה הראשונה אך תפסיק לקלוט עדכוני רוטציה.

    פרסו את השער כ-Deployment רגיל בתוספת Service ו-Ingress, כמתואר בפריסת Kubernetes, עם:

    • serviceAccountName: gateway
    • gateway.yaml מעוגן מתוך ConfigMap והסודות מעוגנים ב-/secrets
    • בדיקת המוכנות (readiness probe) מכוונת ל-GET /readyz

    עבור רכיב החזית, Ingress המנוהל על ידי ה-AWS Load Balancer Controller מקצה את ה-ALB הפנימי. הוסיפו לו את ההערות (annotations) הבאות:

    • alb.ingress.kubernetes.io/scheme: internal ו-alb.ingress.kubernetes.io/target-type: ip
    • alb.ingress.kubernetes.io/ip-address-type: ipv4, כך שלא יפורסמו רשומות AAAA בטווח הציבורי שבדיקת הרשת הפרטית של /login תדחה
    • alb.ingress.kubernetes.io/inbound-cidrs: <your-corporate-cidr>, כך שקבוצת האבטחה הקדמית המנוהלת על ידי הבקר תקבל רק את הרשת הארגונית שלכם במקום ברירת המחדל שלה 0.0.0.0/0
    • alb.ingress.kubernetes.io/certificate-arn עם תעודת ה-ACM
    • alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-TLS13-1-2-2021-06, כך שהמאזין לא ייסוג למדיניות ברירת המחדל הישנה שמקבלת TLS 1.0 ו-1.1
    • alb.ingress.kubernetes.io/load-balancer-attributes: idle_timeout.timeout_seconds=3600, מרווח ביטחון מעל ה-keepalive של זרימת השער. ראו פתרון בעיות

    עם IRSA, ה-SDK של AWS קורא טוקן מוקרן של חשבון שירות (projected service-account token) ומחליף אותו מול AWS STS, כך שהתרמיל לעולם אינו זקוק לשירות מטא-דאטה של מופעי EC2. מדיניות רשת יוצאת (egress NetworkPolicy) יכולה לחסום את 169.254.169.254 עבור תרמילי השער. בעיית מגבלת הדילוגים (hop-limit) של הצומת בפתרון בעיות להלן חלה רק על אשכולות שמדלגים על IRSA ומסתמכים על תפקידי מופע (instance roles) של הצומת.

  3. דחיפת כתובת ה-URL של השער למחשבי המפתחים (Push the gateway URL to developer machines)

    השער פועל כעת, אך מפתחים אינם יכולים להגיע אליו מתוך /login עד שכתובת ה-URL של השער תוגדר במחשבים שלהם. הגדירו את forceLoginMethod ואת forceLoginGatewayUrl בקובץ ההגדרות המנוהל שאתם פורסים לכל מכשיר באמצעות MDM. אין אפשרות לבחירת שער בתפריט הכניסה שמפתח יכול לבחור ידנית.

#הפניה ל-Terraform

החבילה הנלווית בנתיב examples/gateway/aws אורזת את הדף הזה כקוד:

  • setup.sh מתסרט את תהליך ההקצאה שלמעלה עם אותן פקודות aws, במסלול ECS Fargate. הוא אידמפוטנטי: משאבים קיימים מזוהים ומדולגים, כך שהרצה חוזרת היא בטוחה, וניתן לדרוס כל ברירת מחדל באמצעות משתנה סביבה. עליכם עדיין ליצור בעצמכם את סוד הלקוח של Okta OIDC ואת תעודת ה-ACM: הרצה בלעדיהם מדלגת על פריסת ה-ECS/ALB, מציינת את הקלטים החסרים ומדפיסה את פקודת create-secret. צרו את שניהם והריצו שוב. טופס תרחיש השימוש של Bedrock וכינוי ה-Route 53 מודפסים כשלבים הבאים ולא רצים אוטומטית, ודחיפת ה-MDM ללקוחות נשארת שלב ידני מדף זה.
  • gateway.yaml.example הוא תבנית התצורה משלב ה-gateway.yaml, כאשר המפתחות האופציונליים כלולים בהערה. העתיקו אותו אל gateway.yaml והחליפו כל REPLACE_ME לפני הבנייה.
  • Dockerfile בונה את תמונת זמן הריצה מהבינארי המוכן של linux-x64 ומעתיק פנימה את gateway.yaml הממולא שלכם בנתיב /etc/claude/gateway.yaml, בתוספת חבילת התעודות של AWS RDS שמעגנת את sslmode=verify-full של ה-store. הקובץ setup.sh מוריד את החבילה רק כאשר אינה קיימת כבר בהקשר הבנייה. מחקו את הקובץ ובנו מחדש תחת תגית חדשה כדי לקלוט רוטציה של ה-CA ב-AWS. קובץ התצורה אינו מכיל ערכים סודיים, שכן כל פרט הזדהות נפתר בעת האתחול באמצעות הרחבת ${VAR}. לכן, עריכת תצורה פירושה בנייה מחדש תחת תגית חדשה. setup.sh ממכן זאת על ידי תיוג תמונות עם גיבוב (hash) של הקובץ.
  • terraform/ מקצה את אותו היקף של ECS Fargate באופן דקלרטיבי: קבוצות האבטחה, תפקידי IAM, מאגר ECR, מופע RDS, סודות Secrets Manager, ושירות ה-ECS שמאחורי ה-ALB הפנימי. ה-VPC ורשתות המשנה הפרטיות נשארים דרישות מוקדמות ומועברים כמשתנים. Terraform יוצרת את מאגר ה-ECR אך אינה בונה את התמונה, והגדרת השירות מפנה לתמונה, לכן ה-apply מתבצע בשני סבבים: apply ממוקד עבור המאגר, לאחר מכן הבנייה והדחיפה, ולאחר מכן ה-apply המלא. הקובץ terraform/README.md בחבילה מכסה את המשתנים, ה-remote state וההסרה (teardown).

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

#פתרון בעיות

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

תסמיןסיבהפתרון
/login ב-CLI: Gateway hosts must be on your organization's private network; <host> resolves to the public (or unrecognized) address <ip>שם השער פותר לכתובת ציבורית אחת לפחות. ALB פנימי בעל תמיכה כפולה (dual-stack) מפרסם רשומות AAAA בטווח הציבורי, ובדיקת הרשת הפרטית דורשת שכל כתובת שנפתרה תהיה פרטית.צרו את ה-ALB עם --ip-address-type ipv4, או הגישו שם DNS פנימי בלבד נפרד ללא רשומת AAAA ציבורית.
כל בקשת Bedrock מחזירה 502; היומן מציג Could not load credentials from any providersהמשימה רצה בסוג ההפעלה EC2 של ECS ללא תפקיד משימה (task role), או שהתרמיל רץ בצומת EKS ללא IRSA, כך שפרטי ההזדהות מגיעים ממטא-דאטה של המופע, ומגבלת הדילוגים (hop limit) ברירת המחדל 1 של IMDSv2 עוצרת בתוך מכולה. אף אחד מהמסלולים בדף זה אינו מושפע מכך: תפקידי משימה ב-Fargate ו-IRSA אינם משתמשים במטא-דאטה של המופע.העדיפו תפקידי משימה ו-IRSA. במקומות שבהם פרטי הזדהות של המופע הם בלתי נמנעים, העלו את מגבלת הדילוגים באמצעות aws ec2 modify-instance-metadata-options --instance-id <id> --http-put-response-hop-limit 2. הטבלה שאינה תלויה בפלטפורמה מכסה את הפשרות.
בקשות Bedrock מחזירות 403 AccessDeniedExceptionהחשבון לא הגיש את טופס תרחיש השימוש החד-פעמי של Anthropic, המנוי האוטומטי ב-AWS Marketplace שמתחיל בהפעלה הראשונה של החשבון טרם הסתיים, או שממדיניות תפקיד המשימה חסרים ה-ARNs של פרופילי ההסקה או של מודלי הבסיס.הגישו את טופס תרחיש השימוש מתוך קטלוג המודלים (Model catalog) במסוף Bedrock. אם הוא הוגש זה עתה או שזו הפעלתו הראשונה של החשבון, נסו שוב לאחר מספר דקות. העניקו הרשאות bedrock:InvokeModel ו-bedrock:InvokeModelWithResponseStream בשתי משפחות ה-ARN.
Bedrock מחזיר ValidationException המציין שקצב עיבוד לפי דרישה (on-demand throughput) אינו נתמךרשומת models: מותאמת אישית ממופה למזהה מודל בסיס חשוף שהאזור מגיש רק דרך פרופילי הסקה.מפו את המודל למזהה פרופיל ההסקה חוצה-האזורים שלו (us.anthropic.*) במקום זאת. הקטלוג המובנה כבר עושה זאת.
משימת ECS נעצרת עם ResourceInitializationError לפני שהשער רושם משהו ביומןתפקיד הביצוע (execution role) אינו יכול לקרוא את סודות Secrets Manager, או שלרשתות המשנה הפרטיות אין נתיב אל Secrets Manager או ECR.העניקו הרשאת secretsmanager:GetSecretValue על ה-ARNs של שלושת סודות ה-gateway- לתפקיד הביצוע, וספקו חיבור יוצא דרך ה-NAT gateway, או, בהיעדרו, נקודות קצה של ממשק (interface endpoints) עבור Secrets Manager, ECR ו-CloudWatch Logs, שמנהל ההתקן awslogs זקוק להם באותו שלב, בתוספת נקודת קצה של שער (gateway endpoint) עבור S3.
אתחול השער נסגר עם שגיאת פסק זמן בחיבור ל-Postgres (connection-timeout error)קבוצת האבטחה של מסד הנתונים אינה מאשרת את קבוצת האבטחה של השער ביציאה 5432, או שהשירות רץ מחוץ ל-VPC של מסד הנתונים. ה-store מפסיק להמתין לאחר 5 שניות.אפשרו גישה ביציאה 5432 מקבוצת האבטחה של השער בקבוצת האבטחה של מסד הנתונים, והריצו את השירות באותו VPC כמו קבוצת רשתות המשנה של מסד הנתונים (DB subnet group).
אתחול השער נסגר עם שגיאת אימות תעודת TLS של Postgresמחרוזת החיבור מגדירה sslmode=verify-full אך התמונה אינה נותנת אמון בחבילת ה-CA של RDS: החבילה לא הועתקה לתוך התמונה, או ש-NODE_EXTRA_CA_CERTS אינו מצביע עליה.הוסיפו את שתי שורות ה-Dockerfile משלב הבנייה שמעתיקות את החבילה ומגדירות את NODE_EXTRA_CA_CERTS, לאחר מכן בנו מחדש, דחפו תחת תגית חדשה ופרסו מחדש.
תגובות זרימה (streaming responses) נשמטות באמצע הזרימה לאחר תקופת שקטשער ישן יותר מגרסה v2.1.229 עם upstream של Bedrock או Claude Platform on AWS אינו שולח דבר בזמן שה-upstream שקט, למשל במהלך חשיבה ממושכת (extended thinking) ללא פלט זורם. ה-ALB סוגר חיבור כברירת מחדל לאחר 60 שניות ללא נתונים, ולכן הוא קוטע את הזרימה במרווח הזה. שערים מגרסה v2.1.229 ואילך שומרים על זרימה שקטה מתחת למגבלת זמן זו: ברכיבי upstream אלה השער פולט אירוע SSE מסוג ping ברגע שחולפות כ-15 שניות ללא נתוני זרימה, וב-upstream של Anthropic API הוא מעביר הלאה את הפינגים של ה-API עצמו.עדכנו את השער לגרסה v2.1.229 ואילך, או הגדירו את התכונה idle_timeout.timeout_seconds ל-3600, באמצעות modify-load-balancer-attributes או דרך ההערה load-balancer-attributes ב-Ingress ב-EKS.

#טלמטריה

השער מספק לכם מדדי שימוש לפי מפתח ללא שום צורך בהגדרת OTEL לכל מכונה. Claude Code פולט מדדים, יומנים ומעקבים (traces, בהצטרפות יזומה) של OpenTelemetry (OTLP). הדף ניטור שימוש מכסה את כל מה שה-CLI מדווח. בהפעלות דרך השער, ה-CLI מחתים כל ייצוא עם מאפייני הזהות המאומתים מה-IdP: user.id, user.email, ו-user.groups, כך שהשימוש מצטבר לפי מפתח ללא צורך בהגדרות של OTEL_RESOURCE_ATTRIBUTES.

השער עצמו הוא ממסר (relay) OTLP מאומת. הגדירו את telemetry.forward_to יחד עם listen.public_url, והוא דוחף את הגדרות ה-exporter של OTEL לכל לקוח מחובר ומעביר את תעבורת ה-OTLP שלהם ללא שינוי לכל יעד שציינתם. כל יעד בוחר לקבל מדדים, יומנים ומעקבים באופן עצמאי, וברירת המחדל היא מדדים בלבד. עיינו במדריך ל-telemetry לגבי השדות עבור כל אות (signal) והפשרות מבחינת רגישות המידע. השער אינו מבצע חציצה (buffer), צבירה או אחסון של טלמטריה, כך שהמקום שבו הנתונים נשמרים תלוי לחלוטין בתצורת ה-exporter של ה-collector.

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

#מדדים, יומנים ומעקבים של לקוחות

כוונו את telemetry.forward_to אל OpenTelemetry collector, כגון ה-collector של AWS Distro for OpenTelemetry (ADOT), וייצאו משם אל Amazon CloudWatch, אל Amazon Managed Service for Prometheus, או לכל backend התומך ב-OTLP.

הריצו את ה-collector כשירות פנימי משלו הנגיש מעל https://. המדריך ל-telemetry מכסה את החריג עבור loopback ואת CLAUDE_GATEWAY_ALLOW_LOOPBACK.

#יומני השער

ב-ECS Fargate אין צורך בהגדרה נוספת: מנהל ההתקן awslogs מעביר את ה-stderr של השער, הנושא את אירועי הביקורת ואת היומנים התפעוליים שלו, אל קבוצת היומנים /ecs/claude-gateway שנוצרה לעיל. ב-EKS יומני תרמילים אינם מגיעים ל-CloudWatch כברירת מחדל, כך שנתיב הביקורת (audit trail) אובד עד שתתקינו איסוף יומנים: תוסף Amazon CloudWatch Observability עם לכידת יומני מכולות מופעלת, או DaemonSet של Fluent Bit. בכל אחד מהמסלולים, תשאלו את היומנים באמצעות CloudWatch Logs Insights והפעילו התראות מתוך מסנני מדדים (metric filters).

#מדדי מכולה

הפעילו את Container Insights באשכול באמצעות aws ecs update-cluster-settings --cluster claude-gateway --settings name=containerInsights,value=enabled עבור נתוני מעבד (CPU), זיכרון ורשת לכל משימה. ב-EKS, התקינו את התוסף Amazon CloudWatch Observability.

#הוצאות

טלמטריה מציגה שימוש בדיעבד. מגבלות הוצאה הן התצוגה והאכיפה החיה של השער לכל מפתח על גבי פרטי ההזדהות המשותפים מול ה-upstream.

#הצעדים הבאים