@@ -491,124 +491,3 @@ spec:
491
491
# replacement: '...'
492
492
` ` `
493
493
494
- # # Technical Details
495
-
496
- The following sections go into more details of the behind the scenes magic.
497
-
498
- # ## Synchronization
499
-
500
- Even though the whole configuration is written from the standpoint of the service owner, the actual
501
- synchronization logic considers the kcp side as the canonical source of truth. The Sync Agent
502
- continuously tries to make the local objects look like the ones in kcp, while pushing status updates
503
- back into kcp (if the given `PublishedResource` (i.e. CRD) has a `status` subresource enabled).
504
-
505
- # ## Local <-> Remote Connection
506
-
507
- The Sync Agent tries to keep sync-related metadata on the service cluster, away from the consumers.
508
- This is both to prevent vandalism and to hide implementation details.
509
-
510
- To ensure stability against future changes, once the Sync Agent has determined how a local object
511
- should be named, it will remember this decision in the object's metadata. This is so that on future
512
- reconciliations, the (potentially costly, but probably not) renaming logic does not need to be
513
- applied again. This allows the Sync Agent to change defaults and also allows the service owner to make
514
- changes to the naming rules without breaking existing objects.
515
-
516
- Since we do not want to store metadata on the kcp side, we instead rely on label selectors on
517
- the local objects. Each object on the service cluster has a label for the remote cluster name,
518
- namespace and object name, and when trying to find the matching local object, the Sync Agent simply
519
- does a label-based search.
520
-
521
- There is currently no sync-related metadata available on source objects (in kcp workspaces), as this
522
- would either be annotations (untyped strings...) or require schema changes to allow additional
523
- fields in basically random CRDs.
524
-
525
- Note that fields like `generation` or `resourceVersion` are not relevant for any of the sync logic.
526
-
527
- # ## Reconcile Loop
528
-
529
- The sync loop can be divided into 5 parts :
530
-
531
- 1. find the local object
532
- 2. handle deletion
533
- 3. ensure the destination object exists
534
- 4. ensure the destination object's content matches the source object
535
- 5. synchronize related resources the same way (repeat 1-4 for each related resource)
536
-
537
- # ### Phase 1: Find the Local Object
538
-
539
- For this, as mentioned in the connection chapter above, the Sync Agent tries to follow label selectors
540
- on the service cluster. This helps prevent cluttering with consumer workspaces with sync metadata.
541
- If no object is found to match the labels, that's fine and the loop will continue with phase 2,
542
- in which a possible Conflict error (if labels broke) is handled gracefully.
543
-
544
- The remote object in the workspace becomes the `source object` and its local equivalent on the
545
- service cluster is called the `destination object`.
546
-
547
- # ### Phase 2: Handle Deletion
548
-
549
- A finalizer is used in the kcp workspaces to prevent orphans in the service cluster side. This
550
- is the only real evidence in the kcp side that the Sync Agent is even doing things. When a remote
551
- (source) object is deleted, the corresponding local object is deleted as well. Once the local object
552
- is gone, the finalizer is removed from the source object.
553
-
554
- # ### Phase 3: Ensure Object Existence
555
-
556
- We have a source object and now need to create the destination. This chart shows what's happening.
557
-
558
- ` ` ` mermaid
559
- graph TB
560
- A(source object):::state --> B([cleanup if in deletion]):::step
561
- B --> C([ensure finalizer on source object]):::step
562
- C --> D{exists local object?}
563
-
564
- D -- yes --> I("continue with next phase…"):::state
565
- D -- no --> E([apply projection]):::step
566
-
567
- subgraph "ensure dest object exists"
568
- E --> G([ensure resulting namespace exists]):::step
569
- G --> H([create local object]):::step
570
- H --> H_err{Errors?}
571
- H_err -- Conflict --> J([attempt to adopt existing object]):::step
572
- end
573
-
574
- H_err -- success --> I
575
- J --> I
576
-
577
- classDef step color:#77F
578
- classDef state color:#F77
579
- ` ` `
580
-
581
- After we followed through with these steps, both the source and destination objects exists and we
582
- can continue with phase 4.
583
-
584
- Resource adoption happens when creation of the initial local object fails. This can happen when labels
585
- get mangled. If such a conflict happens, the Sync Agent will "adopt" the existing local object by
586
- adding / fixing the labels on it, so that for the next reconciliation it will be found and updated.
587
-
588
- # ### Phase 4: Content Synchronization
589
-
590
- Content synchronization is rather simple, really.
591
-
592
- First the source "spec" is used to patch the local object. Note that this step is called "spec", but
593
- should actually be called "all top-level elements besides `apiVersion`, `kind`, `status` and
594
- ` metadata` , but still including some labels and annotations"; so if you were to publish RBAC objects,
595
- the syncer would include `roleRef` field, for example).
596
-
597
- To allow proper patch generation, the last known state is kept on the local object, similar to how
598
- ` kubectl` creates an annotation for it. This is required for the Sync Agent to properly detect changes
599
- made by mutation webhooks on the service cluster.
600
-
601
- If the published resource (CRD) has a `status` subresource enabled (not just a `status` field in its
602
- scheme, it must be a real subresource), then the Sync Agent will copy the status from the local object
603
- back up to the remote (source) object.
604
-
605
- # ### Phase 5: Sync Related Resources
606
-
607
- The same logic for synchronizing the main published resource applies to their related resources as
608
- well. The only difference is that the source side can be either remote (workspace) or local
609
- (service cluster).
610
-
611
- Since the Sync Agent tries its best to keep sync-related data out of kcp workspaces, the last known
612
- state for related resources is _not_ kept together with the destination object in the kcp workspaces.
613
- Instead all known states (from the main object and all related resources) is kept in a single Secret
614
- on the service cluster side.
0 commit comments