Skip to content

Commit 6668eca

Browse files
committed
docs: enhance clarity and formatting in CA Certificate Bundle documentation for ImageStream backups
Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com>
1 parent 2a0c165 commit 6668eca

File tree

1 file changed

+55
-10
lines changed

1 file changed

+55
-10
lines changed

docs/config/ca-certificate-bundle-for-imagestream-backups.md

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,20 @@
1111
**How to disable**: Set `spec.backupImages: false` to skip CA mounting. See [Disabling](#disabling-imagestream-backup-ca-handling).
1212

1313
**Key components**:
14+
1415
- **ConfigMap**: `velero-ca-bundle` contains concatenated CA certificates
1516
- **Environment variable**: `AWS_CA_BUNDLE=/etc/velero/ca-certs/ca-bundle.pem`
1617
- **Control field**: `spec.backupImages` in DataProtectionApplication CR
1718

1819
**Quick facts**:
20+
1921
- Certificate updates sync within 1-2 minutes (kubelet sync period)
2022
- Changing `backupImages` setting restarts Velero pod
2123
- Only collects from AWS provider BSLs currently
2224
- Works with S3-compatible storage (MinIO, NooBaa, Ceph RGW)
2325

2426
**Jump to**:
27+
2528
- [Key Concepts](#key-concepts) - Understand how it works
2629
- [Configuration Examples](#configuration-examples) - Quick setup
2730
- [Troubleshooting](#troubleshooting) - Fix common issues
@@ -43,12 +46,14 @@ This section defines core concepts referenced throughout the document.
4346
This CA certificate mounting feature is **exclusively for OpenShift ImageStream backups**.
4447

4548
**ImageStream backups require special handling** because:
49+
4650
- They delegate to openshift-velero-plugin
4751
- The plugin uses docker-distribution S3 driver for image layer copying
4852
- The S3 driver can only read CA certificates from the `AWS_CA_BUNDLE` environment variable
4953
- It cannot access Velero's BSL `caCert` configuration directly
5054

5155
**Regular Velero backups (pods, PVCs, namespaces, etc.)** do NOT need this feature:
56+
5257
- Velero directly uses the `caCert` field from BackupStorageLocation spec
5358
- CA certificate validation happens within Velero's own code
5459
- No environment variable-based CA handling needed
@@ -90,13 +95,15 @@ OADP/Velero supports CA certificates through **two independent mechanisms**:
9095
The `spec.backupImages` field in DataProtectionApplication CR controls CA certificate mounting:
9196

9297
**When `true` (default)**:
98+
9399
- CA certificates collected from AWS BSLs
94100
- ConfigMap `velero-ca-bundle` created
95101
- Volume mounted at `/etc/velero/ca-certs`
96102
- `AWS_CA_BUNDLE` environment variable set
97103
- ImageStream backups work with custom CAs
98104

99105
**When `false`**:
106+
100107
- No CA certificate processing
101108
- No ConfigMap created
102109
- No volume mount added
@@ -112,6 +119,7 @@ See [Disabling ImageStream Backup CA Handling](#disabling-imagestream-backup-ca-
112119
Based on [Kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/configmap/) and [issue #20200](https://github.com/kubernetes/kubernetes/issues/20200):
113120

114121
**Update timing**:
122+
115123
- **ConfigMap update**: Instant (via `controllerutil.CreateOrPatch`)
116124
- **File sync to pod**: 1-2 minutes (kubelet sync period + cache TTL)
117125
- Kubelet sync period: 1 minute (default)
@@ -120,31 +128,36 @@ Based on [Kubernetes documentation](https://kubernetes.io/docs/concepts/configur
120128
- **Typical delay**: 60-90 seconds
121129

122130
**Important behavior**:
131+
123132
- ConfigMap updates do NOT restart pods automatically
124133
- Environment variables (like `AWS_CA_BUNDLE`) are NOT updated automatically
125134
- The `AWS_CA_BUNDLE` points to a file path - the file content is updated by kubelet
126135
- Applications must detect and reload configuration changes
127136

128137
**Implications for certificate updates**:
138+
129139
- New AWS SDK sessions (for new backup operations) use the updated certificate file
130140
- Existing AWS SDK sessions continue using old certificates until session recreated
131141
- **Practical effect**: Certificate updates available for new backups after kubelet sync period
132142

133143
### Pod Restart Triggers
134144

135145
**Velero pod WILL restart when**:
146+
136147
- `backupImages` changed from `false` to `true` (volume mount added)
137148
- `backupImages` changed from `true` to `false` (volume mount removed)
138149
- First CA certificate is added (volume mount added to deployment)
139150
- Last CA certificate is removed (volume mount removed from deployment)
140151
- `AWS_CA_BUNDLE` environment variable is added/removed
141152

142153
**Velero pod will NOT restart when**:
154+
143155
- CA certificate content is updated in existing BSL
144156
- ConfigMap data is modified (only file content changes)
145157
- `backupImages` remains unchanged
146158

147159
**Impact on running backups**:
160+
148161
- During ConfigMap update (no restart): Running backups may complete, new backups use updated certs
149162
- During pod restart: Running backups **will fail**, Velero marks as `PartiallyFailed`
150163
- **Recommendation**: Avoid changing `backupImages` or adding/removing CA certificates during active backups. For Non-DPA BSL discovery, use safe trigger mechanisms instead - see [Triggering Discovery of Non-DPA BSL Changes](#triggering-discovery-of-non-dpa-bsl-changes)
@@ -161,12 +174,14 @@ The AWS SDK and Docker Distribution S3 driver read CA certificates at **session
161174
### Certificate Collection Scope
162175

163176
**Currently collected from**:
177+
164178
- Only AWS provider BackupStorageLocations
165179
- BSLs defined in DPA `spec.backupLocations`
166180
- Additional BSLs in the same namespace (not in DPA spec)
167181
- System default CA certificates (appended for fallback)
168182

169183
**Not collected from**:
184+
170185
- Non-AWS provider BSLs (Azure, GCP, etc.)
171186
- BSLs in different namespaces
172187
- Manually created certificate files
@@ -177,7 +192,7 @@ The AWS SDK and Docker Distribution S3 driver read CA certificates at **session
177192

178193
### The ImageStream Backup Flow
179194

180-
```
195+
```doc
181196
┌─────────────────────────────────────────────────────────────────┐
182197
│ ImageStream Backup Flow │
183198
└─────────────────────────────────────────────────────────────────┘
@@ -211,22 +226,26 @@ The AWS SDK and Docker Distribution S3 driver read CA certificates at **session
211226

212227
### Code References
213228

214-
**1. OpenShift Velero Plugin - ImageStream Shared Code**
229+
#### 1. OpenShift Velero Plugin - ImageStream Shared Code
230+
215231
- Location: [`openshift-velero-plugin/velero-plugins/imagestream/shared.go:57`](https://github.com/openshift/openshift-velero-plugin/blob/64292f953c3e2ecd623e9388b2a65c08bb9cfbe2/velero-plugins/imagestream/shared.go#L57)
216232
- This code initiates the imagestream backup and relies on environment variables for configuration
217233

218-
**2. Docker Distribution S3 Driver**
234+
#### 2. Docker Distribution S3 Driver
235+
219236
- Location: [`openshift/docker-distribution/registry/storage/driver/s3-aws/s3.go`](https://github.com/openshift/docker-distribution/blob/release-4.19/registry/storage/driver/s3-aws/s3.go)
220237
- The S3 driver reads `AWS_CA_BUNDLE` from environment and configures AWS SDK accordingly
221238
- This is where the actual S3 operations happen for copying image layers
222239

223-
**3. AWS SDK Environment Configuration**
240+
#### 3. AWS SDK Environment Configuration
241+
224242
- Location: [`aws-sdk-go-v2/config/env_config.go:176-192`](https://github.com/aws/aws-sdk-go-v2/blob/1c707a7bc6b5b0bba75e5643d9e3be2f3f779bc1/config/env_config.go#L176-L192)
225243
- AWS SDK reads `AWS_CA_BUNDLE` environment variable
226244
- Loads custom CA certificates for TLS validation
227245
- Merges custom CAs into HTTP client's Transport
228246

229-
**4. OADP Controller Implementation**
247+
#### 4. OADP Controller Implementation
248+
230249
- Location: `internal/controller/velero.go:443`
231250
- Controls when CA certificate processing occurs based on `dpa.BackupImages()`
232251
- Calls `processCACertificatesForVelero()` only when imagestream backups are enabled
@@ -248,6 +267,7 @@ func (r *DataProtectionApplicationReconciler) processCACertForBSLs() (string, er
248267
```
249268

250269
**Collection Strategy**:
270+
251271
- Only collects from **AWS provider BSLs** (imagestream backup uses S3)
252272
- Scans DPA `spec.backupLocations` for CA certificates
253273
- Scans additional BSLs in namespace (not in DPA spec)
@@ -266,6 +286,7 @@ func (r *DataProtectionApplicationReconciler) processCACertificatesForVelero(
266286
```
267287

268288
**Deployment Configuration**:
289+
269290
```go
270291
// Volume mount
271292
Volume{
@@ -297,6 +318,7 @@ EnvVar{
297318
The CA bundle ConfigMap and volume mount are created based on the `spec.backupImages` field and presence of CA certificates in AWS BSLs:
298319

299320
**Creation conditions**:
321+
300322
1. `spec.backupImages` is `true` or `nil` (defaults to true)
301323
2. At least one AWS provider BSL has `caCert` configured
302324

@@ -309,6 +331,7 @@ The CA bundle ConfigMap and volume mount are created based on the `spec.backupIm
309331
From `tests/e2e/backup_restore_suite_test.go`:
310332

311333
**When `backupImages=true`** (line 638-649):
334+
312335
```go
313336
// Verify AWS_CA_BUNDLE is set when backing up images
314337
awsCABundleFound := false
@@ -324,6 +347,7 @@ gomega.Expect(awsCABundleFound).To(gomega.BeTrue(),
324347
```
325348

326349
**When `backupImages=false`** (line 606-615):
350+
327351
```go
328352
// Verify AWS_CA_BUNDLE is NOT set when NOT backing up images
329353
awsCABundleFound := false
@@ -374,24 +398,23 @@ spec:
374398
bucket: my-backup-bucket
375399
# caCert field can still be specified for Velero's native CA handling
376400
# but will NOT be mounted or used for AWS_CA_BUNDLE
377-
caCert: |
378-
-----BEGIN CERTIFICATE-----
379-
MIID...
380-
-----END CERTIFICATE-----
401+
caCert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUQuLi4KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
381402
config:
382403
region: us-east-1
383404
```
384405
385406
### API Definition
386407
387408
**Type Definition** (`api/v1alpha1/dataprotectionapplication_types.go:803-805`):
409+
388410
```go
389411
// backupImages is used to specify whether you want to deploy a registry for enabling backup and restore of images
390412
// +optional
391413
BackupImages *bool `json:"backupImages,omitempty"`
392414
```
393415

394416
**CRD Schema** (`config/crd/bases/oadp.openshift.io_dataprotectionapplications.yaml:56-58`):
417+
395418
```yaml
396419
backupImages:
397420
description: backupImages is used to specify whether you want to deploy a registry for enabling backup and restore of images
@@ -425,6 +448,7 @@ With `backupImages: false`:
425448
### Default Behavior
426449

427450
**When `backupImages` is not specified** (nil):
451+
428452
- Defaults to `true` via the `BackupImages()` method
429453
- CA certificate processing is enabled
430454
- ConfigMap and volume mount are created if CA certificates exist in BSLs
@@ -436,6 +460,7 @@ With `backupImages: false`:
436460
See [ConfigMap Sync Timing](#configmap-sync-timing) and [AWS SDK Session Behavior](#aws-sdk-session-behavior) in Key Concepts for how certificate updates propagate.
437461

438462
**Quick summary**:
463+
439464
- ConfigMap updates don't restart pods
440465
- Files sync to pods within 1-2 minutes (kubelet sync period)
441466
- New backup operations pick up updated certificates after sync completes
@@ -448,12 +473,14 @@ See [ConfigMap Sync Timing](#configmap-sync-timing) and [AWS SDK Session Behavio
448473
The OADP controller updates the `velero-ca-bundle` ConfigMap in response to several triggers:
449474

450475
**1. DPA Spec Changes**:
476+
451477
- User modifies `spec.backupLocations[*].velero.objectStorage.caCert`
452478
- User modifies `spec.backupLocations[*].cloudStorage.caCert`
453479
- User adds/removes backup locations with CA certificates
454480
- Controller watches DPA resource via `For(&oadpv1alpha1.DataProtectionApplication{})`
455481

456482
**2. BSL Resource Changes**:
483+
457484
- OADP-managed BSLs are created/updated via `controllerutil.CreateOrPatch`
458485
- Controller owns BSL resources via `Owns(&velerov1.BackupStorageLocation{})`
459486
- Any changes to owned BSLs trigger DPA reconciliation (via controller ownership)
@@ -462,20 +489,22 @@ The OADP controller updates the `velero-ca-bundle` ConfigMap in response to seve
462489
- Non-OADP BSLs are discovered via `r.List()` call in `processCACertForBSLs()` during each reconciliation
463490

464491
**3. Secret Label Changes**:
492+
465493
- Controller watches Secrets via `Watches(&corev1.Secret{}, &labelHandler{})`
466494
- Secrets with labels `openshift.io/oadp: "True"` and `dataprotectionapplication.name: <dpa-name>` trigger reconciliation
467495
- BSL credential secrets are automatically labeled by `UpdateCredentialsSecretLabels()` (bsl.go:371-407)
468496
- This enables detection of credential updates that might affect BSL configuration
469497

470498
**4. ConfigMap Lifecycle**:
499+
471500
- ConfigMap has controller reference to DPA: `controllerutil.SetControllerReference(dpa, configMap, r.Scheme)`
472501
- Controller owns ConfigMaps via `Owns(&corev1.ConfigMap{})`
473502
- ConfigMap updates use `controllerutil.CreateOrPatch` for idempotent updates
474503
- Only updates when certificate content actually changes (prevents unnecessary pod disruptions)
475504

476505
#### Complete Update Flow
477506

478-
```
507+
```doc
479508
Trigger Event (DPA change, BSL update, or Secret label change)
480509
481510
@@ -596,6 +625,7 @@ New Session Reads Updated Certificate File
596625
**Predicate Filtering** (from `predicate.go`):
597626

598627
The controller uses `veleroPredicate()` to filter events:
628+
599629
- **Update events**: Only trigger if `generation` changed (spec modification)
600630
- **Create events**: Trigger if resource has `openshift.io/oadp` label or is DPA
601631
- **Delete events**: Trigger if resource has `openshift.io/oadp` label or is DPA
@@ -622,22 +652,27 @@ Non-OADP BSLs (BackupStorageLocations created outside of DPA spec) are discovere
622652
**Safe trigger mechanisms** (ConfigMap-only update, no pod restart):
623653

624654
1. **DPA Annotation (Recommended)**:
655+
625656
```bash
626657
oc annotate dpa <dpa-name> -n openshift-adp reconcile=$(date +%s)
627658
```
659+
628660
- Triggers immediate reconciliation
629661
- Updates ConfigMap if certificates changed
630662
- Does NOT modify deployment spec
631663
- Does NOT restart Velero pod
632664

633665
2. **DPA Metadata Update (Alternative)**:
666+
634667
```bash
635668
oc patch dpa <dpa-name> -n openshift-adp --type=merge -p '{"metadata":{"labels":{"last-sync":"'$(date +%s)'"}}}'
636669
```
670+
637671
- Triggers reconciliation via metadata change
638672
- Safe - metadata changes don't affect deployment
639673

640674
**Unsafe mechanisms** (causes pod restart):
675+
641676
- ❌ Toggling `backupImages` setting
642677
- ❌ Adding/removing DPA `spec.backupLocations` unnecessarily
643678

@@ -677,6 +712,7 @@ spec:
677712
```
678713

679714
**Result**:
715+
680716
- ConfigMap `velero-ca-bundle` created with custom CA + system CAs
681717
- Velero pod has volume mount at `/etc/velero/ca-certs`
682718
- `AWS_CA_BUNDLE=/etc/velero/ca-certs/ca-bundle.pem` set
@@ -716,6 +752,7 @@ spec:
716752
```
717753

718754
**Result**:
755+
719756
- ConfigMap `velero-ca-bundle` **NOT** created
720757
- Velero pod **NO** volume mount at `/etc/velero/ca-certs`
721758
- `AWS_CA_BUNDLE` environment variable **NOT** set
@@ -760,6 +797,7 @@ spec:
760797
```
761798

762799
**Result**:
800+
763801
- ConfigMap contains: Production CA + DR CA + System CAs
764802
- All certificates concatenated and deduplicated
765803
- ImageStream backups to both locations work with their respective custom CAs
@@ -769,18 +807,21 @@ spec:
769807
### What This Feature Enables
770808

771809
✅ **ImageStream backups** in environments with:
810+
772811
- Custom Certificate Authorities (internal CAs)
773812
- Self-signed certificates on S3 endpoints
774813
- MITM proxy infrastructure
775814
- Air-gapped environments with internal CAs
776815

777816
✅ **Automatic certificate management**:
817+
778818
- Collection from all AWS BSLs
779819
- Deduplication of certificates
780820
- System CA fallback
781821
- ConfigMap lifecycle management
782822

783823
✅ **Opt-out capability**:
824+
784825
- Disable via `spec.backupImages: false`
785826
- Reduce overhead when imagestream backups not needed
786827

@@ -795,16 +836,19 @@ spec:
795836
See [Two CA Certificate Mechanisms](#two-ca-certificate-mechanisms) in Key Concepts for a complete explanation of how different components (velero-plugin-for-aws, imagestream backups, BSL validation) use CA certificates differently with `backupImages: true` vs `false`.
796837

797838
**Key points**:
839+
798840
- velero-plugin-for-aws: `AWS_CA_BUNDLE` overrides BSL `caCert` when both present (affects all AWS SDK operations)
799841
- ImageStream backups: REQUIRE `AWS_CA_BUNDLE` environment variable
800842
- Velero BSL validation: Uses velero-plugin-for-aws, so also affected by `AWS_CA_BUNDLE` override behavior
801843

802844
**When to disable** `backupImages: false`:
845+
803846
- No imagestream backups needed
804847
- BSL `caCert` sufficient for regular Velero backups
805848
- Reduce ConfigMap/volume mount overhead
806849

807850
**When to keep enabled** `backupImages: true` (default):
851+
808852
- Need imagestream backups with custom CAs
809853
- Want redundant CA mechanisms
810854
- Unsure and want maximum compatibility
@@ -950,6 +994,7 @@ oc get backupstoragelocation -n openshift-adp default -o jsonpath='{.spec.provid
950994
OADP automatically manages CA certificates for **OpenShift ImageStream backups** in environments with custom CAs.
951995

952996
**Quick Reference**:
997+
953998
- **Purpose**: Enable imagestream backups with custom CA certificates
954999
- **Scope**: See [ImageStream Backup Scope](#imagestream-backup-scope) - imagestream backups only
9551000
- **Mechanism**: See [Two CA Certificate Mechanisms](#two-ca-certificate-mechanisms) - mounts certificates via `AWS_CA_BUNDLE`

0 commit comments

Comments
 (0)