Prow Job Analyze Install Failure
This skill helps debug OpenShift installation failures in CI jobs by downloading and analyzing installer logs, log bundles, and sosreports from Google Cloud Storage.
When to Use This Skill
Use this skill when:
- A CI job fails with "install should succeed" test failure
- You need to debug installation failures at specific stages (bootstrap, install-complete, etc.)
- You need to analyze installer logs and log bundles from failed CI jobs
Prerequisites
Before starting, verify these prerequisites:
gcloud CLI Installation
gcloud Authentication (Optional)
- The
test-platform-results bucket is publicly accessible
- No authentication is required for read access
- Skip authentication checks
Input Format
The user will provide:
- Prow job URL - URL to the failed CI job
- Example:
https://prow.ci.openshift.org/view/gs/test-platform-results/logs/periodic-ci-openshift-release-master-ci-4.21-e2e-aws-ovn-techpreview/1983307151598161920
- The URL should contain
test-platform-results/
Understanding Job Types from Names
Job names contain important clues about the test environment and what to look for:
Upgrade Jobs (names containing "upgrade")
- These jobs perform a fresh installation first, then upgrade
- Minor upgrade jobs: Contain "upgrade-from-stable-4.X" in the name - upgrade from previous minor version (e.g., 4.21 job installs 4.20, then upgrades to 4.21)
- Example:
periodic-ci-openshift-release-master-ci-4.21-upgrade-from-stable-4.20-e2e-gcp-ovn-rt-upgrade
- Micro upgrade jobs: Have "upgrade" in the name but NO "upgrade-from-stable" - upgrade within the same minor version (e.g., earlier 4.21 to newer 4.21)
- Example:
periodic-ci-openshift-release-master-nightly-4.21-e2e-aws-ovn-upgrade-fips
- Example:
periodic-ci-openshift-release-master-ci-4.21-e2e-azure-ovn-upgrade
- If installation fails, the upgrade never happens
- Key point: Installation failures in upgrade jobs are still installation failures, not upgrade failures
FIPS Jobs (names containing "fips")
- FIPS mode enabled for cryptographic operations
- Pay special attention to errors related to:
- Cryptography libraries
- TLS/SSL handshakes
- Certificate validation
- Hash algorithms
IPv6 and Dualstack Jobs (names containing "ipv6" or "dualstack")
- Using IPv6 or dual IPv4/IPv6 networking stack
- Most IPv6 jobs are disconnected (no internet access)
- Use a locally-hosted mirror registry for images
- Pay attention to:
- Network connectivity errors
- DNS resolution issues
- Mirror registry logs
- IPv6 address configuration
Metal Jobs with IPv6 (names containing "metal" and "ipv6")
- Disconnected environment with additional complexity
- The metal install failure skill will analyze squid proxy logs and disconnected environment configuration
Single-Node Jobs (names containing "single-node")
- All control plane and compute workloads on one node
- More prone to resource exhaustion
- Pay attention to CPU, memory, and disk pressure
Platform-Specific Indicators
aws, gcp, azure: Cloud platform used
metal, baremetal: Bare metal environment (uses specialized metal install failure skill)
ovn: OVN-Kubernetes networking (standard)
Implementation Steps
Step 1: Parse and Validate URL
Extract bucket path
- Find
test-platform-results/ in URL
- Extract everything after it as the GCS bucket relative path
- If not found, error: "URL must contain 'test-platform-results/'"
Extract build_id
- Search for pattern
/(\d{10,})/ in the bucket path
- build_id must be at least 10 consecutive decimal digits
- Handle URLs with or without trailing slash
- If not found, error: "Could not find build ID (10+ digits) in URL"
Determine job type
- Check if job name contains "metal" (case-insensitive)
- Metal jobs: Set
is_metal_job = true
- Other jobs: Set
is_metal_job = false
Construct GCS paths
- Bucket:
test-platform-results
- Base GCS path:
gs://test-platform-results/{bucket-path}/
- Ensure path ends with
/
Step 2: Create Working Directory
- Create directory structure
mkdir -p .work/prow-job-analyze-install-failure/{build_id}/logs
mkdir -p .work/prow-job-analyze-install-failure/{build_id}/analysis
- Use
.work/prow-job-analyze-install-failure/ as the base directory (already in .gitignore)
- Use build_id as subdirectory name
- Create
logs/ subdirectory for all downloads
- Create
analysis/ subdirectory for analysis files
- Working directory:
.work/prow-job-analyze-install-failure/{build_id}/
Step 3: Download prowjob.json and Identify Target
Use the fetch-prowjob-json skill to fetch the prowjob.json for this job. See plugins/ci/skills/fetch-prowjob-json/SKILL.md for complete implementation details.
- Fetch prowjob.json using the Prow job URL (convert to gcsweb URL per the
fetch-prowjob-json skill)
- Save locally to
.work/prow-job-analyze-install-failure/{build_id}/logs/prowjob.json
- Parse and validate
- Search for pattern:
--target=([a-zA-Z0-9-]+) in the ci-operator args
- If not found:
- Display: "This is not a ci-operator job. The prowjob cannot be analyzed by this skill."
- Explain: ci-operator jobs have a --target argument specifying the test target
- Exit skill
- Extract target name
- Capture the target value (e.g.,
e2e-aws-ovn-techpreview)
- Store for constructing artifact paths
Step 4: Download JUnit XML to Identify Failure Stage
Note on install-status.txt: You may see an install-status.txt file in the artifacts. This file contains only the installer's exit code (a single number). The junit_install.xml file translates this exit code into a human-readable failure mode, so always prefer junit_install.xml for determining the failure stage.
Find junit_install.xml
- Use recursive listing to find the file anywhere in the job artifacts:
gcloud storage ls -r gs://test-platform-results/{bucket-path}/artifacts/ 2>&1 | grep "junit_install.xml"
- The file location varies by job configuration - don't assume any specific path
Download junit_install.xml
- Download from the discovered location:
# Download from wherever it was found
gcloud storage cp {full-gcs-path-to-junit_install.xml} .work/prow-job-analyze-install-failure/{build_id}/logs/junit_install.xml --no-user-output-enabled
- If file not found, continue anyway (older jobs or early failures may not have this file)
Parse junit_install.xml to find failure stage
- Look for failed test cases with pattern
install should succeed: <stage>
- Installation failure modes:
cluster bootstrap - Early install failure where we failed to bootstrap the cluster. Bootstrap is typically an ephemeral VM that runs a temporary kube apiserver. Check bootkube logs in the bundle.
infrastructure - Early failure before we're able to create all cloud resources. Often but not always due to cloud quota, rate limiting, or outages. Check installer log for cloud API errors.
cluster creation - Usually means one or more operators was unable to stabilize. Check operator logs in gather-must-gather artifacts.
configuration - Extremely rare failure mode where we failed to create the install-config.yaml for one reason or another. Check installer log for validation errors.
cluster operator stability - Operators never stabilized (available=True, progressing=False, degraded=False). Check specific operator logs to determine why they didn't reach stable state.
other - Unknown install failure, could be for one of the previously declared reasons, or an unknown one. Requires full log analysis.
- Extract the failure stage for targeted log analysis
- Use the failure mode to guide which logs to prioritize
Step 4b: Check for Known Symptom Labels
The CI system may attach symptom labels to job runs — machine-detected patterns (e.g., "test failures during high CPU events") stored as JSON artifacts. These are not root causes but provide useful environmental context that may help explain failures when no other cause is found.
List the job_labels directory
gcloud storage ls "gs://test-platform-results/{bucket-path}/artifacts/job_labels/" 2>/dev/null
- If the directory does not exist or returns an error, skip this step silently
Download any JSON symptom files (exclude label-summary.html)
gcloud storage cp "gs://test-platform-results/{bucket-path}/artifacts/job_labels/*.json" \
.work/prow-job-analyze-install-failure/{build_id}/logs/job_labels/ --no-user-output-enabled 2>/dev/null || true
Parse symptom labels — each JSON file describes a detected symptom with a summary and explanation. Collect all symptom summaries for inclusion in the report.
Use symptoms as investigative context — symptoms are environmental observations, NOT definitive causes. They should inform your investigation but you must still perform thorough root cause analysis. Include them in the "Known Symptoms Seen" section of the report.
Step 5: Locate and Download Installer Logs
List all artifacts to find installer logs
- Installer logs follow the pattern
.openshift_install*.log
- IMPORTANT: Exclude deprovision logs - they are from cluster teardown, not installation
- Use recursive listing to find all installer logs:
gcloud storage ls -r gs://test-platform-results/{bucket-path}/artifacts/ 2>&1 | grep -E "\.openshift_install.*\.log$" | grep -v "deprovision"
- This will find installer logs regardless of which CI step created them
Download all installer logs found
# For each installer log found in the listing (excluding deprovision)
gcloud storage cp {full-gcs-path-to-installer-log} .work/prow-job-analyze-install-failure/{build_id}/logs/ --no-user-output-enabled
- Download all installer logs found that are NOT from deprovision steps
- If multiple installer logs exist, download all of them (they may be from different install phases)
- Deprovision logs are from cluster cleanup and not relevant for installation failures
Step 6: Locate and Download Log Bundle
List all artifacts to find log bundle
- Log bundles are
.tar files (NOT .tar.gz) starting with log-bundle-
- IMPORTANT: Prefer non-deprovision log bundles over deprovision ones
- Use recursive listing to find all log bundles:
# Find all log bundles, preferring non-deprovision
gcloud storage ls -r gs://test-platform-results/{bucket-path}/artifacts/ 2>&1 | grep -E "log-bundle.*\.tar$"
- This will find log bundles regardless of which CI step created them
Download log bundle
# If non-deprovision log bundles exist, download one of those (prefer most recent by timestamp)
# Otherwise, download deprovision log bundle if that's the only one available
gcloud storage cp {full-gcs-path-to-log-bundle} .work/prow-job-analyze-install-failure/{build_id}/logs/ --no-user-output-enabled
- Prefer log bundles NOT from deprovision steps (they capture the failure state during installation)
- Deprovision log bundles may also contain useful info if no other bundle exists
- If multiple log bundles exist, prefer the one from a non-deprovision step
- If no log bundle found, continue with installer log analysis only (early failures may not produce log bundles)
Extract log bundle
tar -xf .work/prow-job-analyze-install-failure/{build_id}/logs/log-bundle-{timestamp}.tar -C .work/prow-job-analyze-install-failure/{build_id}/logs/
Step 7: Invoke Metal Install Failure Skill (Metal Jobs Only)
IMPORTANT: Only perform this step if is_metal_job = true
Metal IPI jobs use dev-scripts with Metal3 and Ironic to install OpenShift on bare metal. These require specialized analysis.
Invoke the metal install failure skill
- Use the Skill tool to invoke:
ci:prow-job-analyze-metal-install-failure
- Pass the following information:
- Build ID:
{build_id}
- Bucket path:
{bucket-path}
- Target name:
{target}
- Working directory already created:
.work/prow-job-analyze-install-failure/{build_id}/
The metal skill will:
- Download and analyze dev-scripts logs (setup process before OpenShift installation)
- Download and analyze libvirt console logs (VM/node boot sequence)
- Download and analyze optional artifacts (sosreport, squid logs)
- Determine if failure was in dev-scripts setup or cluster installation
- Generate metal-specific analysis report
Continue with standard analysis:
- After metal skill completes, continue with Step 8 (Analyze Installer Logs)
- The metal skill provides additional context about dev-scripts and console logs
- Standard installer log analysis is still relevant for understanding cluster creation failures
Step 8: Analyze Installer Logs
CRITICAL: Understanding OpenShift's Eventual Consistency
OpenShift installations exhibit "eventual consistency" behavior, which means:
- Components may report errors while waiting for dependencies to become ready
- Example: Ingress operator may error waiting for networking, which errors waiting for other components
- These intermediate errors are expected and normal during installation
- Early errors in the log often resolve themselves and are NOT the root cause
Error Analysis Strategy:
- Start with the NEWEST/FINAL errors - Work backwards in time
- Focus on errors that persisted until installation timeout
- Track backwards from final errors to identify the dependency chain
- Early errors are only relevant if they directly relate to the final failure state
- Don't chase errors that occurred early and then disappeared - they likely resolved
Example: If installation fails at 40 minutes with "kube-apiserver not available", an error at 5 minutes saying "ingress operator degraded" is likely irrelevant because it probably resolved. Focus on what was still broken when the timeout occurred.
Read installer log
- The installer log is a sequential log file with timestamp, log level, and message
- Format:
time="YYYY-MM-DDTHH:MM:SSZ" level=<level> msg="<message>"
Identify key failure indicators (WORK BACKWARDS FROM END)
- Start at the end of the log - Look at final error/fatal messages
- Error messages: Lines with
level=error or level=fatal near the end of the log
- Last status messages: The final "Still waiting for" or "Cluster operators X, Y, Z are not available" messages
- Warning messages: Lines with
level=warning near the failure time that may indicate problems
- Then work backwards to find when the failing component first started having issues
- Ignore errors from early in the log unless they persist to the end
Extract relevant log sections (prioritize recent errors)
- For bootstrap failures:
- Search for: "bootstrap", "bootkube", "kube-apiserver", "etcd" in the last 20% of the log
- For install-complete failures:
- Search for: "Cluster operators", "clusteroperator", "degraded", "available" in the final messages
- For timeout failures:
- Search for: "context deadline exceeded", "timeout", "timed out"
- Look at what component was being waited for when timeout occurred
Create installer log summary
- Extract final/last error or fatal message (most important)
- Extract the last "Still waiting for..." message showing what didn't stabilize
- Extract surrounding context (10-20 lines before and after final errors)
- Optionally note early errors only if they relate to the final failure
- Save to:
.work/prow-job-analyze-install-failure/{build_id}/analysis/installer-summary.txt
Step 9: Analyze Log Bundle
Skip this step if no log bundle was downloaded
Understand log bundle structure
log-bundle-{timestamp}/
bootstrap/journals/ - Journal logs from bootstrap node
bootkube.log - Bootkube service that starts initial control plane
kubelet.log - Kubelet service logs
crio.log - Container runtime logs
journal.log.gz - Complete system journal (gzipped)
bootstrap/network/ - Network configuration
ip-addr.txt - IP addresses
ip-route.txt - Routing table
hostname.txt - Hostname
serial/ - Serial console logs from all nodes
{cluster-name}-bootstrap-serial.log - Bootstrap node console
{cluster-name}-master-N-serial.log - Master node consoles
clusterapi/ - Cluster API resources
*.yaml - Kubernetes resource definitions
etcd.log - etcd logs
kube-apiserver.log - API server logs
failed-units.txt - List of systemd units that failed
gather.log - Log bundle collection process log
Analyze based on failure mode from junit_install.xml
For "cluster bootstrap" failures:
Bootstrap failures are varied and complex. You MUST thoroughly examine the log bundle to build a complete timeline — do not guess the root cause from a single error.
- Read
bootstrap/journals/bootkube.log thoroughly. Identify every process that started, crashed, or errored, noting timestamps to build a chronological sequence.
- For any crashed process (non-zero exit status, ContainerDied), read its stderr/stdout in the surrounding lines. Exit codes tell you that it crashed; the error output tells you why. Treat a crash as a potential bug but validate the termination reason (OOM, host restart, killed by signal, resource limits, etc.) by examining container exit status, kernel messages, and host metrics before assigning root cause. Consult surrounding logs and infra signals — exit codes, ContainerDied event details, dmesg/journal entries, and resource utilization — to distinguish software defects from infra/resource-induced terminations.
- Pursue errors: read surrounding context, follow references to other components' logs, and trace the chain of causation back to the originating failure. The first error is often a symptom, not the cause.
- Check supporting logs:
clusterapi/kube-apiserver.log, clusterapi/etcd.log, bootstrap/journals/kubelet.log. Cross-reference timestamps with bootkube.log.
- Check
serial/{cluster-name}-bootstrap-serial.log for kernel panics, ignition failures, disk errors.
- Check
failed-units.txt for failed systemd units.
For "infrastructure" failures:
- Primary focus on installer log, not log bundle (failure happens before bootstrap)
- Search installer log for cloud provider API errors
- Look for quota exceeded messages (e.g., "QuotaExceeded", "LimitExceeded")
- Look for rate limiting errors (e.g., "RequestLimitExceeded", "Throttling")
- Check for authentication/permission errors
- Infrastructure provisioning methods (varies by OpenShift version):
- Newer versions: Use Cluster API (CAPI) to provision infrastructure
- Look for errors in ClusterAPI-related logs and resources
- Check for Machine/MachineSet/MachineDeployment errors
- Search for "clusterapi" or "machine-api" related errors
- Older versions: Use Terraform to provision infrastructure
- Look for "terraform" in log entries
- Check for terraform state errors or apply failures
- Search for terraform-related error messages
- Log bundle may not exist or be incomplete for this failure mode
For "cluster creation" failures:
- Check if must-gather was successfully collected:
- Look for
must-gather*.tar files in the gather-must-gather step directory
- If NO .tar file exists, must-gather collection failed (cluster was too unstable)
- Do NOT suggest downloading must-gather if the .tar file doesn't exist
- If must-gather exists, check for operator logs
- Look for degraded cluster operators
- Check operator-specific logs to see why they couldn't stabilize
- Review cluster operator status conditions
- This indicates cluster bootstrapped but operators failed to deploy
For "configuration" failures:
- Focus entirely on installer log
- Look for install-config.yaml validation errors
- Check for missing required fields or invalid values
- This is a very early failure before any infrastructure is created
- Log bundle will not exist for this failure mode
For "cluster operator stability" failures:
- Similar to "cluster creation" but operators are stuck in unstable state
- Check if must-gather was successfully collected (look for
must-gather*.tar files)
- If must-gather doesn't exist, rely on installer log and log bundle only
- Check for operators with available=False, progressing=True, or degraded=True
- Review operator logs in gather-must-gather (if it exists)
- Check for resource conflicts or dependency issues
- Look at time-series of operator status changes
For "other" failures:
- Perform comprehensive analysis of all available logs
- Check installer log for any errors or fatal messages
- Review log bundle if available
- Look for unusual patterns or timeout messages
Extract key information
- If
failed-units.txt exists, read it to find failed services
- For each failed service, find corresponding journal log
- Extract error messages from journal logs
- Save findings to:
.work/prow-job-analyze-install-failure/{build_id}/analysis/log-bundle-summary.txt
Step 10: Generate Analysis Report
Create comprehensive analysis report
- Combine findings from all sources:
- Installer log analysis
- Log bundle analysis
- sosreport analysis (if applicable)
Report structure
OpenShift Installation Failure Analysis
========================================
Job: {job-name}
Build ID: {build_id}
Job Type: {metal/cloud}
Prow URL: {original-url}
Failure Stage: {stage from junit_install.xml}
Known Symptoms Seen (only if symptom labels found in Step 4b — omit if none)
---------------------
- {symptom summary}: {symptom explanation}
Note: Symptoms are machine-detected environmental observations, not definitive
causes. They add context to help explain failures when correlated with other evidence.
Summary
-------
{High-level summary of the failure}
Installer Log Analysis
----------------------
{Key findings from installer log}
First Error:
{First error message with timestamp}
Context:
{Surrounding log lines}
Log Bundle Analysis
-------------------
{Findings from log bundle}
Failed Units:
{List from failed-units.txt}
Key Journal Errors:
{Important errors from journal logs}
Metal Installation Analysis (Metal Jobs Only)
-----------------------------------------
{Summary from metal install failure skill}
- Dev-scripts setup status
- Console log findings
- Key metal-specific errors
See detailed metal analysis: .work/prow-job-analyze-install-failure/{build_id}/analysis/metal-analysis.txt
Recommended Next Steps
----------------------
{Actionable debugging steps based on failure mode:
For "configuration" failures:
- Review install-config.yaml validation errors
- Check for missing required fields
- Verify credential format and availability
For "infrastructure" failures:
- Check cloud provider quota and limits
- Review cloud provider service status for outages
- Verify API credentials and permissions
- Check for rate limiting in cloud API calls
For "cluster bootstrap" failures:
- Review bootkube logs for control plane startup issues
- Check etcd cluster formation in etcd.log
- Examine kube-apiserver startup in kube-apiserver.log
- Review bootstrap VM serial console for boot issues
For "cluster creation" failures:
- Identify which operators failed to deploy
- Check if must-gather was collected (look for must-gather*.tar files)
- If must-gather exists: Review specific operator logs in gather-must-gather
- If must-gather doesn't exist: Cluster was too unstable to collect diagnostics; rely on installer log and log bundle
- Check for resource conflicts or missing dependencies
For "cluster operator stability" failures:
- Identify operators not reaching stable state
- Check operator conditions (available, progressing, degraded)
- Check if must-gather exists before suggesting to review it
- Review operator logs for stuck operations (if must-gather available)
- Look for time-series of operator status changes
For "other" failures:
- Perform comprehensive log review
- Look for timeout or unusual error patterns
- Check all available artifacts systematically
}
Artifacts Location
------------------
All artifacts downloaded to:
.work/prow-job-analyze-install-failure/{build_id}/logs/
- Installer logs: .openshift_install*.log
- Log bundle: log-bundle-*/
- sosreport: sosreport-*/ (metal jobs only)
Save report
- Save to:
.work/prow-job-analyze-install-failure/{build_id}/analysis/report.txt
Step 11: Present Results to User
Display summary
- Show the analysis report to the user
- Highlight the most critical findings
- Provide file paths for further investigation
Offer next steps
- Based on the failure type, suggest specific debugging actions:
- For bootstrap failures: Check API server and etcd logs
- For install-complete failures: Check cluster operator status
- For network issues: Review network configuration
- For metal job failures: Examine VM console logs
- IMPORTANT: Only suggest reviewing must-gather if you verified the .tar file exists
- Don't suggest downloading must-gather if no .tar file was found
- If must-gather doesn't exist, note that the cluster was too unstable to collect it
Provide artifact locations
- List all downloaded files with their paths
- Note whether must-gather was successfully collected or not
- Explain how to explore the logs further
- Mention that artifacts are cached for faster re-analysis
Installation Stages Reference
Understanding the installation stages helps target analysis:
Pre-installation (Failure mode: "configuration")
- Validation of install-config.yaml
- Credential checks
- Image resolution
- Common failures: Invalid install-config.yaml, missing required fields, validation errors
Infrastructure Creation (Failure mode: "infrastructure")
- Creating cloud resources (VMs, networks, storage)
- For metal: VM provisioning on hypervisor
- Common failures: Cloud quota exceeded, rate limiting, API outages, permission errors
Bootstrap (Failure mode: "cluster bootstrap")
- Bootstrap node boots with temporary control plane
- Bootstrap API server and etcd start
- Bootstrap creates master nodes
- Common failures: API server won't start, etcd formation issues, bootkube errors
Master Node Bootstrap
- Master nodes boot and join bootstrap etcd
- Masters form permanent control plane
- Bootstrap control plane transfers to masters
- Common failures: Masters can't reach bootstrap, network issues, ignition failures
Bootstrap Complete
- Bootstrap node is no longer needed
- Masters are running permanent control plane
- Cluster operators begin initialization
- Common failures: Control plane not transferring, master nodes not ready
Cluster Operators Initialization (Failure mode: "cluster creation")
- Core cluster operators start
- Operators begin deployment
- Initial operator stabilization
- Common failures: Operators can't deploy, resource conflicts, dependency issues
Cluster Operators Stabilization (Failure mode: "cluster operator stability")
- Operators reach stable state (available=True, progressing=False, degraded=False)
- Worker nodes can join
- Common failures: Operators stuck progressing, degraded state, availability issues
Install Complete
- All cluster operators are available and stable
- Cluster is fully functional
- Installation successful
Failure Mode Mapping
| JUnit Failure Mode |
Installation Stage |
Where to Look |
Artifacts Available |
configuration |
Pre-installation |
Installer log only |
No log bundle |
infrastructure |
Infrastructure Creation |
Installer log, cloud API errors |
Partial or no log bundle |
cluster bootstrap |
Bootstrap |
Log bundle (bootkube, etcd, kube-apiserver) |
Full log bundle |
cluster creation |
Operators Initialization |
gather-must-gather, operator logs |
Full artifacts |
cluster operator stability |
Operators Stabilization |
gather-must-gather, operator status |
Full artifacts |
other |
Unknown |
All available logs |
Varies |
Key Files Reference
Installer Logs
- Location:
.openshift_install-{timestamp}.log
- Format: Structured log with timestamp, level, message
- Key patterns:
level=error - Error messages
level=fatal - Fatal errors that stop installation
waiting for - Timeout/waiting messages
Log Bundle Structure
- bootstrap/journals/bootkube.log: Bootstrap control plane initialization
- bootstrap/journals/kubelet.log: Bootstrap kubelet (container orchestration)
- clusterapi/kube-apiserver.log: API server logs
- clusterapi/etcd.log: etcd cluster logs
- serial/*.log: Node console output
- failed-units.txt: systemd services that failed
Metal Job Artifacts
Metal installations are handled by the prow-job-analyze-metal-install-failure skill.
See that skill's documentation for details on dev-scripts, libvirt logs, sosreport, and squid logs.
Tips
- CRITICAL: Work backwards from the end of the installer log, not forwards from the beginning
- Early errors often resolve themselves due to eventual consistency - focus on final errors
- Always start by checking the installer log for the LAST error, not the first
- The log bundle provides detailed node-level diagnostics
- Serial console logs show the actual boot sequence and can reveal kernel panics
- Failed systemd units in failed-units.txt are strong indicators of the problem
- Bootstrap failures are often etcd or API server related
- Install-complete failures are usually cluster operator issues
- Metal jobs use a specialized skill for analysis (prow-job-analyze-metal-install-failure)
- Cache artifacts in
.work/prow-job-analyze-install-failure/{build_id}/ for re-analysis
- Use grep with relevant keywords to filter large log files
- Timeline of events from installer log helps correlate issues across logs
- Pay attention to job name clues: fips, ipv6, dualstack, metal, single-node, upgrade
- IPv6 jobs are often disconnected and use mirror registries
- Only suggest must-gather if the .tar file exists; if not, cluster was too unstable
- TechPreview jobs (names containing "techpreview") enable additional feature gates not active in Default clusters. Bootstrap failures in TechPreview jobs may be in TechPreview-gated code paths (e.g., on-cluster layering, OS image management) that won't reproduce in Default clusters. Note this in your analysis when relevant.
Important Notes
Bootstrap Failures Require Log Bundle Analysis
- Bootstrap timeout failures can have many causes — always download and examine the installer log bundle to determine the actual root cause
- Do not classify bootstrap failures without examining the logs
Eventual Consistency Behavior
- OpenShift installations exhibit eventual consistency
- Components report errors while waiting for dependencies
- Early errors are EXPECTED and usually resolve automatically
- Always analyze backwards from the final timeout, not forwards from the start
- Only errors that persist until failure are relevant root causes
Upgrade Jobs and Installation
- Jobs with "upgrade" in the name perform installation FIRST, then upgrade
- If you're analyzing an installation failure in an upgrade job, it never got to the upgrade phase
- "minor" upgrade: Installs 4.n-1 version (e.g., 4.20 for a 4.21 upgrade job)
- "micro" upgrade: Installs earlier payload in same stream
Log Bundle Availability
- Not all jobs produce log bundles
- Older jobs may not have this feature
- Installation must reach a certain point to generate log bundle
Must-Gather Availability
- Must-gather only exists if a
must-gather*.tar file is present
- If no .tar file exists, the cluster was too unstable to collect diagnostics
- Never suggest downloading must-gather unless you verified the .tar file exists
Metal Job Specifics
- Metal jobs are analyzed using the specialized
prow-job-analyze-metal-install-failure skill
- That skill handles dev-scripts, libvirt console logs, sosreport, and squid logs
- See the metal skill documentation for details
Debugging Workflow
- Start with installer log to find LAST error (not first)
- Use failure stage to guide which logs to examine
- Log bundle provides node-level details
- For metal jobs, invoke the metal-specific skill for additional analysis
- Work backwards in time to trace dependency chains
Common Failure Patterns
- Bootstrap etcd not starting: Check etcd.log and bootkube.log
- API server not responding: Check kube-apiserver.log
- Masters not joining: Check master serial logs
- Operators degraded: Check specific operator logs in must-gather (if it exists)
- Network issues: Check network configuration in bootstrap/network/
File Formats
- Installer log: Plain text, structured format
- Journal logs: systemd journal format (plain text export)
- Serial logs: Raw console output
- YAML files: Kubernetes resource definitions
- Compressed files: .gz (gzip), .xz (xz)
Converted and distributed by TomeVault — claim your Tome and manage your conversions.
1---2name: prow-job-analyze-install-failure3description: Analyze OpenShift installation failures in Prow CI jobs by examining installer logs, log bundles, and sosreports. Use when CI job fails "install should succeed" tests at bootstrap, cluster creation or other stages. Use when this capability is needed.4---56# Prow Job Analyze Install Failure78This skill helps debug OpenShift installation failures in CI jobs by downloading and analyzing installer logs, log bundles, and sosreports from Google Cloud Storage.910## When to Use This Skill1112Use this skill when:13- A CI job fails with "install should succeed" test failure14- You need to debug installation failures at specific stages (bootstrap, install-complete, etc.)15- You need to analyze installer logs and log bundles from failed CI jobs1617## Prerequisites1819Before starting, verify these prerequisites:20211. **gcloud CLI Installation**22 - Check if installed: `which gcloud`23 - If not installed, provide instructions for the user's platform24 - Installation guide: https://cloud.google.com/sdk/docs/install25262. **gcloud Authentication (Optional)**27 - The `test-platform-results` bucket is publicly accessible28 - No authentication is required for read access29 - Skip authentication checks3031## Input Format3233The user will provide:341. **Prow job URL** - URL to the failed CI job35 - Example: `https://prow.ci.openshift.org/view/gs/test-platform-results/logs/periodic-ci-openshift-release-master-ci-4.21-e2e-aws-ovn-techpreview/1983307151598161920`36 - The URL should contain `test-platform-results/`3738## Understanding Job Types from Names3940Job names contain important clues about the test environment and what to look for:41421. **Upgrade Jobs** (names containing "upgrade")43 - These jobs perform a **fresh installation first**, then upgrade44 - **Minor upgrade jobs**: Contain "upgrade-from-stable-4.X" in the name - upgrade from previous minor version (e.g., 4.21 job installs 4.20, then upgrades to 4.21)45 - Example: `periodic-ci-openshift-release-master-ci-4.21-upgrade-from-stable-4.20-e2e-gcp-ovn-rt-upgrade`46 - **Micro upgrade jobs**: Have "upgrade" in the name but NO "upgrade-from-stable" - upgrade within the same minor version (e.g., earlier 4.21 to newer 4.21)47 - Example: `periodic-ci-openshift-release-master-nightly-4.21-e2e-aws-ovn-upgrade-fips`48 - Example: `periodic-ci-openshift-release-master-ci-4.21-e2e-azure-ovn-upgrade`49 - If installation fails, the upgrade never happens50 - **Key point**: Installation failures in upgrade jobs are still installation failures, not upgrade failures51522. **FIPS Jobs** (names containing "fips")53 - FIPS mode enabled for cryptographic operations54 - Pay special attention to errors related to:55 - Cryptography libraries56 - TLS/SSL handshakes57 - Certificate validation58 - Hash algorithms59603. **IPv6 and Dualstack Jobs** (names containing "ipv6" or "dualstack")61 - Using IPv6 or dual IPv4/IPv6 networking stack62 - Most IPv6 jobs are **disconnected** (no internet access)63 - Use a locally-hosted mirror registry for images64 - Pay attention to:65 - Network connectivity errors66 - DNS resolution issues67 - Mirror registry logs68 - IPv6 address configuration69704. **Metal Jobs with IPv6** (names containing "metal" and "ipv6")71 - Disconnected environment with additional complexity72 - The metal install failure skill will analyze squid proxy logs and disconnected environment configuration73745. **Single-Node Jobs** (names containing "single-node")75 - All control plane and compute workloads on one node76 - More prone to resource exhaustion77 - Pay attention to CPU, memory, and disk pressure78796. **Platform-Specific Indicators**80 - `aws`, `gcp`, `azure`: Cloud platform used81 - `metal`, `baremetal`: Bare metal environment (uses specialized metal install failure skill)82 - `ovn`: OVN-Kubernetes networking (standard)8384## Implementation Steps8586### Step 1: Parse and Validate URL87881. **Extract bucket path**89 - Find `test-platform-results/` in URL90 - Extract everything after it as the GCS bucket relative path91 - If not found, error: "URL must contain 'test-platform-results/'"92932. **Extract build_id**94 - Search for pattern `/(\d{10,})/` in the bucket path95 - build_id must be at least 10 consecutive decimal digits96 - Handle URLs with or without trailing slash97 - If not found, error: "Could not find build ID (10+ digits) in URL"98993. **Determine job type**100 - Check if job name contains "metal" (case-insensitive)101 - Metal jobs: Set `is_metal_job = true`102 - Other jobs: Set `is_metal_job = false`1031044. **Construct GCS paths**105 - Bucket: `test-platform-results`106 - Base GCS path: `gs://test-platform-results/{bucket-path}/`107 - Ensure path ends with `/`108109### Step 2: Create Working Directory1101111. **Create directory structure**112 ```bash113 mkdir -p .work/prow-job-analyze-install-failure/{build_id}/logs114 mkdir -p .work/prow-job-analyze-install-failure/{build_id}/analysis115 ```116 - Use `.work/prow-job-analyze-install-failure/` as the base directory (already in .gitignore)117 - Use build_id as subdirectory name118 - Create `logs/` subdirectory for all downloads119 - Create `analysis/` subdirectory for analysis files120 - Working directory: `.work/prow-job-analyze-install-failure/{build_id}/`121122### Step 3: Download prowjob.json and Identify Target123124Use the `fetch-prowjob-json` skill to fetch the prowjob.json for this job. See `plugins/ci/skills/fetch-prowjob-json/SKILL.md` for complete implementation details.1251261. **Fetch prowjob.json** using the Prow job URL (convert to gcsweb URL per the `fetch-prowjob-json` skill)1272. **Save locally** to `.work/prow-job-analyze-install-failure/{build_id}/logs/prowjob.json`1283. **Parse and validate**129 - Search for pattern: `--target=([a-zA-Z0-9-]+)` in the ci-operator args130 - If not found:131 - Display: "This is not a ci-operator job. The prowjob cannot be analyzed by this skill."132 - Explain: ci-operator jobs have a --target argument specifying the test target133 - Exit skill1344. **Extract target name**135 - Capture the target value (e.g., `e2e-aws-ovn-techpreview`)136 - Store for constructing artifact paths137138### Step 4: Download JUnit XML to Identify Failure Stage139140**Note on install-status.txt**: You may see an `install-status.txt` file in the artifacts. This file contains only the installer's exit code (a single number). The junit_install.xml file translates this exit code into a human-readable failure mode, so always prefer junit_install.xml for determining the failure stage.1411421. **Find junit_install.xml**143 - Use recursive listing to find the file anywhere in the job artifacts:144 ```bash145 gcloud storage ls -r gs://test-platform-results/{bucket-path}/artifacts/ 2>&1 | grep "junit_install.xml"146 ```147 - The file location varies by job configuration - don't assume any specific path1481492. **Download junit_install.xml**150 - Download from the discovered location:151 ```bash152 # Download from wherever it was found153 gcloud storage cp {full-gcs-path-to-junit_install.xml} .work/prow-job-analyze-install-failure/{build_id}/logs/junit_install.xml --no-user-output-enabled154 ```155 - If file not found, continue anyway (older jobs or early failures may not have this file)1561573. **Parse junit_install.xml to find failure stage**158 - Look for failed test cases with pattern `install should succeed: <stage>`159 - Installation failure modes:160 - **`cluster bootstrap`** - Early install failure where we failed to bootstrap the cluster. Bootstrap is typically an ephemeral VM that runs a temporary kube apiserver. Check bootkube logs in the bundle.161 - **`infrastructure`** - Early failure before we're able to create all cloud resources. Often but not always due to cloud quota, rate limiting, or outages. Check installer log for cloud API errors.162 - **`cluster creation`** - Usually means one or more operators was unable to stabilize. Check operator logs in gather-must-gather artifacts.163 - **`configuration`** - Extremely rare failure mode where we failed to create the install-config.yaml for one reason or another. Check installer log for validation errors.164 - **`cluster operator stability`** - Operators never stabilized (available=True, progressing=False, degraded=False). Check specific operator logs to determine why they didn't reach stable state.165 - **`other`** - Unknown install failure, could be for one of the previously declared reasons, or an unknown one. Requires full log analysis.166 - Extract the failure stage for targeted log analysis167 - Use the failure mode to guide which logs to prioritize168169### Step 4b: Check for Known Symptom Labels170171The CI system may attach **symptom labels** to job runs — machine-detected patterns (e.g., "test failures during high CPU events") stored as JSON artifacts. These are **not root causes** but provide useful environmental context that may help explain failures when no other cause is found.1721731. **List the job_labels directory**174 ```bash175 gcloud storage ls "gs://test-platform-results/{bucket-path}/artifacts/job_labels/" 2>/dev/null176 ```177 - If the directory does not exist or returns an error, skip this step silently1781792. **Download any JSON symptom files** (exclude `label-summary.html`)180 ```bash181 gcloud storage cp "gs://test-platform-results/{bucket-path}/artifacts/job_labels/*.json" \182 .work/prow-job-analyze-install-failure/{build_id}/logs/job_labels/ --no-user-output-enabled 2>/dev/null || true183 ```1841853. **Parse symptom labels** — each JSON file describes a detected symptom with a summary and explanation. Collect all symptom summaries for inclusion in the report.1861874. **Use symptoms as investigative context** — symptoms are environmental observations, NOT definitive causes. They should inform your investigation but you must still perform thorough root cause analysis. Include them in the "Known Symptoms Seen" section of the report.188189### Step 5: Locate and Download Installer Logs1901911. **List all artifacts to find installer logs**192 - Installer logs follow the pattern `.openshift_install*.log`193 - **IMPORTANT**: Exclude deprovision logs - they are from cluster teardown, not installation194 - Use recursive listing to find all installer logs:195 ```bash196 gcloud storage ls -r gs://test-platform-results/{bucket-path}/artifacts/ 2>&1 | grep -E "\.openshift_install.*\.log$" | grep -v "deprovision"197 ```198 - This will find installer logs regardless of which CI step created them1992002. **Download all installer logs found**201 ```bash202 # For each installer log found in the listing (excluding deprovision)203 gcloud storage cp {full-gcs-path-to-installer-log} .work/prow-job-analyze-install-failure/{build_id}/logs/ --no-user-output-enabled204 ```205 - Download all installer logs found that are NOT from deprovision steps206 - If multiple installer logs exist, download all of them (they may be from different install phases)207 - Deprovision logs are from cluster cleanup and not relevant for installation failures208209### Step 6: Locate and Download Log Bundle2102111. **List all artifacts to find log bundle**212 - Log bundles are `.tar` files (NOT `.tar.gz`) starting with `log-bundle-`213 - **IMPORTANT**: Prefer non-deprovision log bundles over deprovision ones214 - Use recursive listing to find all log bundles:215 ```bash216 # Find all log bundles, preferring non-deprovision217 gcloud storage ls -r gs://test-platform-results/{bucket-path}/artifacts/ 2>&1 | grep -E "log-bundle.*\.tar$"218 ```219 - This will find log bundles regardless of which CI step created them2202212. **Download log bundle**222 ```bash223 # If non-deprovision log bundles exist, download one of those (prefer most recent by timestamp)224 # Otherwise, download deprovision log bundle if that's the only one available225 gcloud storage cp {full-gcs-path-to-log-bundle} .work/prow-job-analyze-install-failure/{build_id}/logs/ --no-user-output-enabled226 ```227 - Prefer log bundles NOT from deprovision steps (they capture the failure state during installation)228 - Deprovision log bundles may also contain useful info if no other bundle exists229 - If multiple log bundles exist, prefer the one from a non-deprovision step230 - If no log bundle found, continue with installer log analysis only (early failures may not produce log bundles)2312323. **Extract log bundle**233 ```bash234 tar -xf .work/prow-job-analyze-install-failure/{build_id}/logs/log-bundle-{timestamp}.tar -C .work/prow-job-analyze-install-failure/{build_id}/logs/235 ```236237### Step 7: Invoke Metal Install Failure Skill (Metal Jobs Only)238239**IMPORTANT: Only perform this step if `is_metal_job = true`**240241Metal IPI jobs use **dev-scripts** with **Metal3** and **Ironic** to install OpenShift on bare metal. These require specialized analysis.2422431. **Invoke the metal install failure skill**244 - Use the Skill tool to invoke: `ci:prow-job-analyze-metal-install-failure`245 - Pass the following information:246 - Build ID: `{build_id}`247 - Bucket path: `{bucket-path}`248 - Target name: `{target}`249 - Working directory already created: `.work/prow-job-analyze-install-failure/{build_id}/`2502512. **The metal skill will**:252 - Download and analyze dev-scripts logs (setup process before OpenShift installation)253 - Download and analyze libvirt console logs (VM/node boot sequence)254 - Download and analyze optional artifacts (sosreport, squid logs)255 - Determine if failure was in dev-scripts setup or cluster installation256 - Generate metal-specific analysis report2572583. **Continue with standard analysis**:259 - After metal skill completes, continue with Step 8 (Analyze Installer Logs)260 - The metal skill provides additional context about dev-scripts and console logs261 - Standard installer log analysis is still relevant for understanding cluster creation failures262263### Step 8: Analyze Installer Logs264265**CRITICAL: Understanding OpenShift's Eventual Consistency**266267OpenShift installations exhibit "eventual consistency" behavior, which means:268- Components may report errors while waiting for dependencies to become ready269- Example: Ingress operator may error waiting for networking, which errors waiting for other components270- These intermediate errors are **expected and normal** during installation271- Early errors in the log often resolve themselves and are NOT the root cause272273**Error Analysis Strategy**:2741. **Start with the NEWEST/FINAL errors** - Work backwards in time2752. Focus on errors that persisted until installation timeout2763. Track backwards from final errors to identify the dependency chain2774. Early errors are only relevant if they directly relate to the final failure state2785. Don't chase errors that occurred early and then disappeared - they likely resolved279280**Example**: If installation fails at 40 minutes with "kube-apiserver not available", an error at 5 minutes saying "ingress operator degraded" is likely irrelevant because it probably resolved. Focus on what was still broken when the timeout occurred.2812821. **Read installer log**283 - The installer log is a sequential log file with timestamp, log level, and message284 - Format: `time="YYYY-MM-DDTHH:MM:SSZ" level=<level> msg="<message>"`2852862. **Identify key failure indicators (WORK BACKWARDS FROM END)**287 - **Start at the end of the log** - Look at final error/fatal messages288 - **Error messages**: Lines with `level=error` or `level=fatal` near the end of the log289 - **Last status messages**: The final "Still waiting for" or "Cluster operators X, Y, Z are not available" messages290 - **Warning messages**: Lines with `level=warning` near the failure time that may indicate problems291 - **Then work backwards** to find when the failing component first started having issues292 - Ignore errors from early in the log unless they persist to the end2932943. **Extract relevant log sections (prioritize recent errors)**295 - For bootstrap failures:296 - Search for: "bootstrap", "bootkube", "kube-apiserver", "etcd" in the **last 20% of the log**297 - For install-complete failures:298 - Search for: "Cluster operators", "clusteroperator", "degraded", "available" in the **final messages**299 - For timeout failures:300 - Search for: "context deadline exceeded", "timeout", "timed out"301 - Look at what component was being waited for when timeout occurred3023034. **Create installer log summary**304 - Extract **final/last** error or fatal message (most important)305 - Extract the last "Still waiting for..." message showing what didn't stabilize306 - Extract surrounding context (10-20 lines before and after final errors)307 - Optionally note early errors only if they relate to the final failure308 - Save to: `.work/prow-job-analyze-install-failure/{build_id}/analysis/installer-summary.txt`309310### Step 9: Analyze Log Bundle311312**Skip this step if no log bundle was downloaded**3133141. **Understand log bundle structure**315 - `log-bundle-{timestamp}/`316 - `bootstrap/journals/` - Journal logs from bootstrap node317 - `bootkube.log` - Bootkube service that starts initial control plane318 - `kubelet.log` - Kubelet service logs319 - `crio.log` - Container runtime logs320 - `journal.log.gz` - Complete system journal (gzipped)321 - `bootstrap/network/` - Network configuration322 - `ip-addr.txt` - IP addresses323 - `ip-route.txt` - Routing table324 - `hostname.txt` - Hostname325 - `serial/` - Serial console logs from all nodes326 - `{cluster-name}-bootstrap-serial.log` - Bootstrap node console327 - `{cluster-name}-master-N-serial.log` - Master node consoles328 - `clusterapi/` - Cluster API resources329 - `*.yaml` - Kubernetes resource definitions330 - `etcd.log` - etcd logs331 - `kube-apiserver.log` - API server logs332 - `failed-units.txt` - List of systemd units that failed333 - `gather.log` - Log bundle collection process log3343352. **Analyze based on failure mode from junit_install.xml**336337 **For "cluster bootstrap" failures:**338339 Bootstrap failures are varied and complex. You MUST thoroughly examine the log bundle to build a complete timeline — do not guess the root cause from a single error.340341 - Read `bootstrap/journals/bootkube.log` thoroughly. Identify every process that started, crashed, or errored, noting timestamps to build a chronological sequence.342 - For any crashed process (non-zero exit status, ContainerDied), read its stderr/stdout in the surrounding lines. Exit codes tell you *that* it crashed; the error output tells you *why*. Treat a crash as a potential bug but validate the termination reason (OOM, host restart, killed by signal, resource limits, etc.) by examining container exit status, kernel messages, and host metrics before assigning root cause. Consult surrounding logs and infra signals — exit codes, ContainerDied event details, dmesg/journal entries, and resource utilization — to distinguish software defects from infra/resource-induced terminations.343 - Pursue errors: read surrounding context, follow references to other components' logs, and trace the chain of causation back to the originating failure. The first error is often a symptom, not the cause.344 - Check supporting logs: `clusterapi/kube-apiserver.log`, `clusterapi/etcd.log`, `bootstrap/journals/kubelet.log`. Cross-reference timestamps with bootkube.log.345 - Check `serial/{cluster-name}-bootstrap-serial.log` for kernel panics, ignition failures, disk errors.346 - Check `failed-units.txt` for failed systemd units.347348 **For "infrastructure" failures:**349 - Primary focus on installer log, not log bundle (failure happens before bootstrap)350 - Search installer log for cloud provider API errors351 - Look for quota exceeded messages (e.g., "QuotaExceeded", "LimitExceeded")352 - Look for rate limiting errors (e.g., "RequestLimitExceeded", "Throttling")353 - Check for authentication/permission errors354 - **Infrastructure provisioning methods** (varies by OpenShift version):355 - **Newer versions**: Use **Cluster API (CAPI)** to provision infrastructure356 - Look for errors in ClusterAPI-related logs and resources357 - Check for Machine/MachineSet/MachineDeployment errors358 - Search for "clusterapi" or "machine-api" related errors359 - **Older versions**: Use **Terraform** to provision infrastructure360 - Look for "terraform" in log entries361 - Check for terraform state errors or apply failures362 - Search for terraform-related error messages363 - Log bundle may not exist or be incomplete for this failure mode364365 **For "cluster creation" failures:**366 - Check if must-gather was successfully collected:367 - Look for `must-gather*.tar` files in the gather-must-gather step directory368 - If NO .tar file exists, must-gather collection failed (cluster was too unstable)369 - Do NOT suggest downloading must-gather if the .tar file doesn't exist370 - If must-gather exists, check for operator logs371 - Look for degraded cluster operators372 - Check operator-specific logs to see why they couldn't stabilize373 - Review cluster operator status conditions374 - This indicates cluster bootstrapped but operators failed to deploy375376 **For "configuration" failures:**377 - Focus entirely on installer log378 - Look for install-config.yaml validation errors379 - Check for missing required fields or invalid values380 - This is a very early failure before any infrastructure is created381 - Log bundle will not exist for this failure mode382383 **For "cluster operator stability" failures:**384 - Similar to "cluster creation" but operators are stuck in unstable state385 - Check if must-gather was successfully collected (look for `must-gather*.tar` files)386 - If must-gather doesn't exist, rely on installer log and log bundle only387 - Check for operators with available=False, progressing=True, or degraded=True388 - Review operator logs in gather-must-gather (if it exists)389 - Check for resource conflicts or dependency issues390 - Look at time-series of operator status changes391392 **For "other" failures:**393 - Perform comprehensive analysis of all available logs394 - Check installer log for any errors or fatal messages395 - Review log bundle if available396 - Look for unusual patterns or timeout messages3973983. **Extract key information**399 - If `failed-units.txt` exists, read it to find failed services400 - For each failed service, find corresponding journal log401 - Extract error messages from journal logs402 - Save findings to: `.work/prow-job-analyze-install-failure/{build_id}/analysis/log-bundle-summary.txt`403404### Step 10: Generate Analysis Report4054061. **Create comprehensive analysis report**407 - Combine findings from all sources:408 - Installer log analysis409 - Log bundle analysis410 - sosreport analysis (if applicable)4114122. **Report structure**413 ```414 OpenShift Installation Failure Analysis415 ========================================416417 Job: {job-name}418 Build ID: {build_id}419 Job Type: {metal/cloud}420 Prow URL: {original-url}421422 Failure Stage: {stage from junit_install.xml}423424 Known Symptoms Seen (only if symptom labels found in Step 4b — omit if none)425 ---------------------426 - {symptom summary}: {symptom explanation}427 Note: Symptoms are machine-detected environmental observations, not definitive428 causes. They add context to help explain failures when correlated with other evidence.429430 Summary431 -------432 {High-level summary of the failure}433434 Installer Log Analysis435 ----------------------436 {Key findings from installer log}437438 First Error:439 {First error message with timestamp}440441 Context:442 {Surrounding log lines}443444 Log Bundle Analysis445 -------------------446 {Findings from log bundle}447448 Failed Units:449 {List from failed-units.txt}450451 Key Journal Errors:452 {Important errors from journal logs}453454 Metal Installation Analysis (Metal Jobs Only)455 -----------------------------------------456 {Summary from metal install failure skill}457 - Dev-scripts setup status458 - Console log findings459 - Key metal-specific errors460461 See detailed metal analysis: .work/prow-job-analyze-install-failure/{build_id}/analysis/metal-analysis.txt462463 Recommended Next Steps464 ----------------------465 {Actionable debugging steps based on failure mode:466467 For "configuration" failures:468 - Review install-config.yaml validation errors469 - Check for missing required fields470 - Verify credential format and availability471472 For "infrastructure" failures:473 - Check cloud provider quota and limits474 - Review cloud provider service status for outages475 - Verify API credentials and permissions476 - Check for rate limiting in cloud API calls477478 For "cluster bootstrap" failures:479 - Review bootkube logs for control plane startup issues480 - Check etcd cluster formation in etcd.log481 - Examine kube-apiserver startup in kube-apiserver.log482 - Review bootstrap VM serial console for boot issues483484 For "cluster creation" failures:485 - Identify which operators failed to deploy486 - Check if must-gather was collected (look for must-gather*.tar files)487 - If must-gather exists: Review specific operator logs in gather-must-gather488 - If must-gather doesn't exist: Cluster was too unstable to collect diagnostics; rely on installer log and log bundle489 - Check for resource conflicts or missing dependencies490491 For "cluster operator stability" failures:492 - Identify operators not reaching stable state493 - Check operator conditions (available, progressing, degraded)494 - Check if must-gather exists before suggesting to review it495 - Review operator logs for stuck operations (if must-gather available)496 - Look for time-series of operator status changes497498 For "other" failures:499 - Perform comprehensive log review500 - Look for timeout or unusual error patterns501 - Check all available artifacts systematically502 }503504 Artifacts Location505 ------------------506 All artifacts downloaded to:507 .work/prow-job-analyze-install-failure/{build_id}/logs/508509 - Installer logs: .openshift_install*.log510 - Log bundle: log-bundle-*/511 - sosreport: sosreport-*/ (metal jobs only)512 ```5135143. **Save report**515 - Save to: `.work/prow-job-analyze-install-failure/{build_id}/analysis/report.txt`516517### Step 11: Present Results to User5185191. **Display summary**520 - Show the analysis report to the user521 - Highlight the most critical findings522 - Provide file paths for further investigation5235242. **Offer next steps**525 - Based on the failure type, suggest specific debugging actions:526 - For bootstrap failures: Check API server and etcd logs527 - For install-complete failures: Check cluster operator status528 - For network issues: Review network configuration529 - For metal job failures: Examine VM console logs530 - **IMPORTANT**: Only suggest reviewing must-gather if you verified the .tar file exists531 - Don't suggest downloading must-gather if no .tar file was found532 - If must-gather doesn't exist, note that the cluster was too unstable to collect it5335343. **Provide artifact locations**535 - List all downloaded files with their paths536 - Note whether must-gather was successfully collected or not537 - Explain how to explore the logs further538 - Mention that artifacts are cached for faster re-analysis539540## Installation Stages Reference541542Understanding the installation stages helps target analysis:5435441. **Pre-installation** (Failure mode: "configuration")545 - Validation of install-config.yaml546 - Credential checks547 - Image resolution548 - **Common failures**: Invalid install-config.yaml, missing required fields, validation errors5495502. **Infrastructure Creation** (Failure mode: "infrastructure")551 - Creating cloud resources (VMs, networks, storage)552 - For metal: VM provisioning on hypervisor553 - **Common failures**: Cloud quota exceeded, rate limiting, API outages, permission errors5545553. **Bootstrap** (Failure mode: "cluster bootstrap")556 - Bootstrap node boots with temporary control plane557 - Bootstrap API server and etcd start558 - Bootstrap creates master nodes559 - **Common failures**: API server won't start, etcd formation issues, bootkube errors5605614. **Master Node Bootstrap**562 - Master nodes boot and join bootstrap etcd563 - Masters form permanent control plane564 - Bootstrap control plane transfers to masters565 - **Common failures**: Masters can't reach bootstrap, network issues, ignition failures5665675. **Bootstrap Complete**568 - Bootstrap node is no longer needed569 - Masters are running permanent control plane570 - Cluster operators begin initialization571 - **Common failures**: Control plane not transferring, master nodes not ready5725736. **Cluster Operators Initialization** (Failure mode: "cluster creation")574 - Core cluster operators start575 - Operators begin deployment576 - Initial operator stabilization577 - **Common failures**: Operators can't deploy, resource conflicts, dependency issues5785797. **Cluster Operators Stabilization** (Failure mode: "cluster operator stability")580 - Operators reach stable state (available=True, progressing=False, degraded=False)581 - Worker nodes can join582 - **Common failures**: Operators stuck progressing, degraded state, availability issues5835848. **Install Complete**585 - All cluster operators are available and stable586 - Cluster is fully functional587 - Installation successful588589## Failure Mode Mapping590591| JUnit Failure Mode | Installation Stage | Where to Look | Artifacts Available |592|-------------------|-------------------|---------------|-------------------|593| `configuration` | Pre-installation | Installer log only | No log bundle |594| `infrastructure` | Infrastructure Creation | Installer log, cloud API errors | Partial or no log bundle |595| `cluster bootstrap` | Bootstrap | Log bundle (bootkube, etcd, kube-apiserver) | Full log bundle |596| `cluster creation` | Operators Initialization | gather-must-gather, operator logs | Full artifacts |597| `cluster operator stability` | Operators Stabilization | gather-must-gather, operator status | Full artifacts |598| `other` | Unknown | All available logs | Varies |599600## Key Files Reference601602### Installer Logs603- **Location**: `.openshift_install-{timestamp}.log`604- **Format**: Structured log with timestamp, level, message605- **Key patterns**:606 - `level=error` - Error messages607 - `level=fatal` - Fatal errors that stop installation608 - `waiting for` - Timeout/waiting messages609610### Log Bundle Structure611- **bootstrap/journals/bootkube.log**: Bootstrap control plane initialization612- **bootstrap/journals/kubelet.log**: Bootstrap kubelet (container orchestration)613- **clusterapi/kube-apiserver.log**: API server logs614- **clusterapi/etcd.log**: etcd cluster logs615- **serial/*.log**: Node console output616- **failed-units.txt**: systemd services that failed617618### Metal Job Artifacts619620Metal installations are handled by the `prow-job-analyze-metal-install-failure` skill.621See that skill's documentation for details on dev-scripts, libvirt logs, sosreport, and squid logs.622623## Tips624625- **CRITICAL**: Work backwards from the end of the installer log, not forwards from the beginning626- Early errors often resolve themselves due to eventual consistency - focus on final errors627- Always start by checking the installer log for the **LAST** error, not the first628- The log bundle provides detailed node-level diagnostics629- Serial console logs show the actual boot sequence and can reveal kernel panics630- Failed systemd units in failed-units.txt are strong indicators of the problem631- Bootstrap failures are often etcd or API server related632- Install-complete failures are usually cluster operator issues633- Metal jobs use a specialized skill for analysis (prow-job-analyze-metal-install-failure)634- Cache artifacts in `.work/prow-job-analyze-install-failure/{build_id}/` for re-analysis635- Use grep with relevant keywords to filter large log files636- Timeline of events from installer log helps correlate issues across logs637- Pay attention to job name clues: fips, ipv6, dualstack, metal, single-node, upgrade638- IPv6 jobs are often disconnected and use mirror registries639- Only suggest must-gather if the .tar file exists; if not, cluster was too unstable640- **TechPreview jobs** (names containing "techpreview") enable additional feature gates not active in Default clusters. Bootstrap failures in TechPreview jobs may be in TechPreview-gated code paths (e.g., on-cluster layering, OS image management) that won't reproduce in Default clusters. Note this in your analysis when relevant.641642## Important Notes6436441. **Bootstrap Failures Require Log Bundle Analysis**645 - Bootstrap timeout failures can have many causes — always download and examine the installer log bundle to determine the actual root cause646 - Do not classify bootstrap failures without examining the logs6476482. **Eventual Consistency Behavior**649 - OpenShift installations exhibit eventual consistency650 - Components report errors while waiting for dependencies651 - Early errors are EXPECTED and usually resolve automatically652 - **Always analyze backwards from the final timeout, not forwards from the start**653 - Only errors that persist until failure are relevant root causes6546553. **Upgrade Jobs and Installation**656 - Jobs with "upgrade" in the name perform installation FIRST, then upgrade657 - If you're analyzing an installation failure in an upgrade job, it never got to the upgrade phase658 - "minor" upgrade: Installs 4.n-1 version (e.g., 4.20 for a 4.21 upgrade job)659 - "micro" upgrade: Installs earlier payload in same stream6606614. **Log Bundle Availability**662 - Not all jobs produce log bundles663 - Older jobs may not have this feature664 - Installation must reach a certain point to generate log bundle6656665. **Must-Gather Availability**667 - Must-gather only exists if a `must-gather*.tar` file is present668 - If no .tar file exists, the cluster was too unstable to collect diagnostics669 - **Never suggest downloading must-gather unless you verified the .tar file exists**6706716. **Metal Job Specifics**672 - Metal jobs are analyzed using the specialized `prow-job-analyze-metal-install-failure` skill673 - That skill handles dev-scripts, libvirt console logs, sosreport, and squid logs674 - See the metal skill documentation for details6756767. **Debugging Workflow**677 - Start with installer log to find **LAST** error (not first)678 - Use failure stage to guide which logs to examine679 - Log bundle provides node-level details680 - For metal jobs, invoke the metal-specific skill for additional analysis681 - Work backwards in time to trace dependency chains6826838. **Common Failure Patterns**684 - **Bootstrap etcd not starting**: Check etcd.log and bootkube.log685 - **API server not responding**: Check kube-apiserver.log686 - **Masters not joining**: Check master serial logs687 - **Operators degraded**: Check specific operator logs in must-gather (if it exists)688 - **Network issues**: Check network configuration in bootstrap/network/6896909. **File Formats**691 - Installer log: Plain text, structured format692 - Journal logs: systemd journal format (plain text export)693 - Serial logs: Raw console output694 - YAML files: Kubernetes resource definitions695 - Compressed files: .gz (gzip), .xz (xz)696697---698> Converted and distributed by [TomeVault](https://tomevault.io/claim/openshift-eng) — claim your Tome and manage your conversions.699<!-- tomevault:4.0:skill_md:2026-04-11 -->