feat(images): add DVCR image presence monitoring
Description
Implements periodic monitoring of DVCR (Deckhouse Virtualization Container Registry) image presence for VirtualImage and ClusterVirtualImage resources.
Key components:
-
ImageChecker: New component (pkg/dvcr/image_checker.go) that verifies image existence in DVCR registry using go-containerregistry
- Performs lightweight HEAD requests to check image manifests
-
Periodic Reconciliation: Uses controller-runtime's CronSource to trigger reconciliation on a configurable schedule
- Default: hourly (0 * * * *)
- Configurable via module config: dvcr.imageMonitorSchedule
- Can be disabled by setting empty string
-
Phase Management: New ImageLost phase added to track when images are deleted from DVCR
- ImageLost: Image manifest not found in DVCR registry
- ImagePVCLost: PVC backing the image was deleted (existing, renamed from PVCLost)
-
Optimizations:
- Custom field indexes (IndexVIByPhaseAndStorage, IndexCVIByPhase) to filter resources at API level
Why do we need it, and what problem does it solve?
When images are deleted from DVCR (either manually or due to storage issues), the VirtualImage/ClusterVirtualImage resources continue to show Ready phase even though the underlying image data is gone. This creates a misleading state where users think images are available but VM creation fails.
This feature provides automated detection of missing images and updates resource status accordingly, giving users accurate visibility into image availability.
What is the expected result?
Checklist
- [ ] The code is covered by unit tests.
- [ ] e2e tests passed.
- [ ] Documentation updated according to the changes.
- [ ] Changes were tested in the Kubernetes cluster manually.
Changelog entries
section: images
type: feature
summary: Added monitoring of DVCR image presence for VirtualImage and ClusterVirtualImage
Reviewer's Guide
Introduces a periodic DVCR image presence monitor for VirtualImage and ClusterVirtualImage using the existing GC framework and minimal API surface changes.
Sequence diagram for periodic DVCR image presence monitoring
sequenceDiagram
participant CronScheduler
participant ImageMonitorManager
participant DVCRRegistry
participant K8sAPI
CronScheduler->>ImageMonitorManager: Trigger ListForDelete()
ImageMonitorManager->>K8sAPI: List VirtualImage/ClusterVirtualImage
loop For each Ready image
ImageMonitorManager->>DVCRRegistry: CheckImageExists(registryURL)
alt Image exists
ImageMonitorManager-->>CronScheduler: No action
else Image missing
ImageMonitorManager->>K8sAPI: Update Status.Phase to ImageLost
ImageMonitorManager->>K8sAPI: Set Condition Reason=ImageLost
end
end
ER diagram for updated VirtualImage and ClusterVirtualImage status phases
erDiagram
VIRTUALIMAGE {
string id
ImagePhase phase
string progress
string registry_url
}
CLUSTERVIRTUALIMAGE {
string id
ImagePhase phase
string progress
string registry_url
}
IMAGEPHASE {
string name
}
VIRTUALIMAGE ||--o| IMAGEPHASE : "has phase"
CLUSTERVIRTUALIMAGE ||--o| IMAGEPHASE : "has phase"
IMAGEPHASE {
Pending
Provisioning
WaitForUserUpload
Ready
Failed
Terminating
ImageLost
PVCLost
}
Class diagram for DVCR image presence monitoring
classDiagram
class VirtualImage {
+Status: VirtualImageStatus
+Spec: VirtualImageSpec
}
class ClusterVirtualImage {
+Status: ClusterVirtualImageStatus
+Spec: ClusterVirtualImageSpec
}
class VirtualImageStatus {
+Phase: ImagePhase
+Progress: string
+Conditions: []Condition
+Target: TargetInfo
}
class ClusterVirtualImageStatus {
+Phase: ImagePhase
+Progress: string
+Conditions: []Condition
+Target: TargetInfo
}
class ImagePhase {
<<enum>>
Pending
Provisioning
WaitForUserUpload
Ready
Failed
Terminating
ImageLost
PVCLost
}
class ImageMonitorManager {
+client: Client
+dvcrSettings: DVCRSettings
+New()
+ShouldBeDeleted(obj)
+ListForDelete(ctx, now)
+checkImage(ctx, registryURL)
+markImageLost(ctx, obj, registryURL)
+getAuthCredentials(ctx)
}
class DVCRSettings {
+AuthSecret: string
+AuthSecretNamespace: string
+InsecureTLS: string
}
class ImageChecker {
<<interface>>
+CheckImageExists(ctx, imageURL)
}
class DefaultImageChecker {
+username: string
+password: string
+insecure: bool
+CheckImageExists(ctx, imageURL)
}
VirtualImageStatus --> ImagePhase
ClusterVirtualImageStatus --> ImagePhase
ImageMonitorManager --> DVCRSettings
ImageMonitorManager --> ImageChecker
DefaultImageChecker ..|> ImageChecker
File-Level Changes
| Change | Details | Files |
|---|---|---|
| Extend GC settings to include image monitor schedule |
|
pkg/config/load_gc_settings.go |
| Implement image-monitor controllers for VI and CVI |
|
pkg/controller/vi/image_monitor.gopkg/controller/cvi/image_monitor.go |
| Provide DVCR ImageChecker |
|
pkg/dvcr/checker.go |
| Enhance CRDs with ImageLost/PVCLost semantics |
|
api/core/v1alpha2/virtual_image.goapi/core/v1alpha2/cluster_virtual_image.goapi/core/v1alpha2/image_status.goapi/core/v1alpha2/vicondition/condition.goapi/core/v1alpha2/cvicondition/condition.go |
| Align PVC source controller with PVCLost |
|
pkg/controller/vi/internal/source/step/ready_pvc_step.gopkg/controller/vi/internal/source/sources.gopkg/controller/vi/internal/source/object_ref_vdsnapshot_pvc_test.go |
| Report new phases in metrics |
|
pkg/monitoring/metrics/vi/scraper.gopkg/monitoring/metrics/cvi/scraper.go |
| Bump dependencies for image checking |
|
go.mod |
Tips and commands
Interacting with Sourcery
-
Trigger a new review: Comment
@sourcery-ai reviewon the pull request. - Continue discussions: Reply directly to Sourcery's review comments.
-
Generate a GitHub issue from a review comment: Ask Sourcery to create an
issue from a review comment by replying to it. You can also reply to a
review comment with
@sourcery-ai issueto create an issue from it. -
Generate a pull request title: Write
@sourcery-aianywhere in the pull request title to generate a title at any time. You can also comment@sourcery-ai titleon the pull request to (re-)generate the title at any time. -
Generate a pull request summary: Write
@sourcery-ai summaryanywhere in the pull request body to generate a PR summary at any time exactly where you want it. You can also comment@sourcery-ai summaryon the pull request to (re-)generate the summary at any time. -
Generate reviewer's guide: Comment
@sourcery-ai guideon the pull request to (re-)generate the reviewer's guide at any time. -
Resolve all Sourcery comments: Comment
@sourcery-ai resolveon the pull request to resolve all Sourcery comments. Useful if you've already addressed all the comments and don't want to see them anymore. -
Dismiss all Sourcery reviews: Comment
@sourcery-ai dismisson the pull request to dismiss all existing Sourcery reviews. Especially useful if you want to start fresh with a new review - don't forget to comment@sourcery-ai reviewto trigger a new review!
Customizing Your Experience
Access your dashboard to:
- Enable or disable review features such as the Sourcery-generated pull request summary, the reviewer's guide, and others.
- Change the review language.
- Add, remove or edit custom review instructions.
- Adjust other review settings.
Getting Help
- Contact our support team for questions or feedback.
- Visit our documentation for detailed guides and information.
- Keep in touch with the Sourcery team by following us on X/Twitter, LinkedIn or GitHub.
Workflow has started. Follow the progress here: Workflow Run
The target step completed with status: failure.
Workflow has started. Follow the progress here: Workflow Run
The target step completed with status: failure.