You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -12,17 +12,11 @@ See [Functionality]({{% relref "/docs/5_architecture_and_components/porch-apiser
12
12
13
13
The Porch API Server implements Kubernetes' REST storage interface to provide custom storage backends for Porch resources. Unlike standard Kubernetes resources that store data in etcd, Porch resources delegate to the Engine which manages package data in Git repositories through the Cache.
14
14
15
-
**Storage interface characteristics:**
16
-
- Implements standard Kubernetes storage.Interface
The Storage Interface implements standard Kubernetes storage. It provides CRUD operations (Create, Get, List, Update, Delete), supports Watch for real-time change notifications and delegates all operations to CaD Engine. However, it has no direct etcd storage, as the packages are stored in Git.
-**Status validation**: Validates status subresource updates
29
+
The purpose of the this strategy is to validate resource specifications before persistence. It has three types: create, update and status. The create validation ensures that the fields present and the lifecycle constraints enforced. The update validation checks resource version, lifecycle transitions and immutability rules. And the status validation checks status subresource updates.
41
30
42
31
### Admission Strategy
43
32
44
-
**Purpose**: Applies admission control policies and defaults
45
-
46
-
**Admission operations:**
47
-
-**PrepareForCreate**: Sets defaults, generates names, initializes status
The purpose of this strategy is to apply admission control policies and defaults. There are three admission operations: PrepareForCreate, PrepareForUpdate and Canonicalize. PrepareForCreate sets defaults, generates names and initializes status. PrepareForUpdate validates resource version and enforces immutability. Canonicalize normalizes resource representation.
50
34
51
35
### Table Conversion Strategy
52
36
53
-
**Purpose**: Converts resources to table format for kubectl display
- Supports both list and individual resource views
37
+
The purpose of the table conversion strategy is to convert resources to table format for `kubectl` display. The table conversion defines columns for `kubectl` output (Name, Package, Workspace, Revision, Lifecycle), extracts values from resource specifications, and formats data for human-readable display. It supports both list and individual resource views.
60
38
61
39
## API Groups
62
40
@@ -69,33 +47,19 @@ The Porch API Server registers two API groups with Kubernetes:
69
47
-**PackageRevisionResources**: Contains the actual resource content of a package revision
70
48
-**Package**: Represents a package across all its revisions
71
49
72
-
**Versions:**
73
-
- v1alpha1: Current version with all resources
50
+
**Versions:** v1alpha1: Current version with all resources
74
51
75
-
**Characteristics:**
76
-
- Primary API group for package management
77
-
- All resources namespaced
78
-
- Served via Kubernetes API aggregation (not CRDs)
79
-
- Supports full CRUD and Watch operations
80
-
- Integrates with Engine for all operations
81
-
- Uses custom REST storage (Git-backed, not etcd)
52
+
**Characteristics:** The porch.kpt.dev API group is the primary API group for package management, and all its resources are namespaced. It is served via Kubernetes API aggregation, not CRDs, and supports full CRUD and Watch operations. This group integrates with Engine for all operations and uses custom REST storage, which is Git-backed, not etcd.
82
53
83
54
### config.porch.kpt.dev API Group (CRDs)
84
55
85
56
**Resources:**
86
57
-**Repository**: Configures Git repositories for package storage
87
58
-**PackageRev**: Internal metadata resource for tracking package revisions
88
59
89
-
**Versions:**
90
-
- v1alpha1: Current version for all resources
60
+
**Versions:** v1alpha1: Current version for all resources
91
61
92
-
**Characteristics:**
93
-
- Configuration API group for repository management
94
-
- All resources are namespaced
95
-
- Implemented as standard Kubernetes CRDs
96
-
- Managed by separate controllers, not directly by API server
97
-
- Stored in etcd (standard Kubernetes CRD storage)
98
-
- PackageRev is an internal resource used for metadata tracking
62
+
**Characteristics:** The config.porch.kpt.dev API group serves as the configuration API group for repository management, with all its resources being namespaced. It is implemented as standard Kubernetes CRDs and is managed by separate controllers, not directly by the API server. Its data is stored in etcd, which is the standard Kubernetes CRD storage. Within this group, PackageRev is used an internal resource specifically for metadata tracking.
99
63
100
64
## Background Operations
101
65
@@ -107,105 +71,52 @@ See [Functionality]({{% relref "/docs/5_architecture_and_components/porch-apiser
107
71
108
72
### REST Storage vs etcd
109
73
110
-
**Decision**: Implement custom REST storage that delegates to Engine instead of using etcd.
74
+
Instead of using etcd, custom REST storage is implemented that delegates to Engine.
111
75
112
-
**Rationale:**
113
-
- Package data naturally lives in Git repositories
114
-
- etcd not suitable for large package content
115
-
- Engine provides necessary abstraction over Git
116
-
- Enables draft-commit workflow for package modifications
76
+
Package data naturally lives in Git repositories, and etcd is not suitable for storing large package content. The Engine provides the necessary abstraction over Git, which enables a draft-commit workflow for package modifications.
117
77
118
-
**Alternatives considered:**
119
-
-**Store in etcd**: Would require duplicating package content, large storage overhead
120
-
-**Hybrid approach**: Metadata in etcd, content in Git - adds complexity
78
+
Using etcd would require duplicating package content, causing large storage overhead. As an alternative, a hybrid approach was considered as well. Metadata would be stored in etcd, content in Git. However, that would add complexity.
121
79
122
-
**Trade-offs:**
123
-
- Custom storage more complex than standard etcd
124
-
- Enables Git-native package management
125
-
- Better scalability for large packages
80
+
This decision has some trade-offs. Custom storage, while more complex than standard etcd, offers the significant advantages of enabling Git-native package management and providing better scalability for large packages.
126
81
127
82
### Strategy-Based Validation
128
83
129
-
**Decision**: Use Kubernetes strategy pattern for validation and admission control.
84
+
Kubernetes strategy pattern for validation and admission control is used.
130
85
131
-
**Rationale:**
132
-
- Follows Kubernetes conventions
133
-
- Separates validation logic from storage logic
134
-
- Enables reuse across different storage implementations
135
-
- Provides consistent validation behavior
86
+
Following Kubernetes conventions, this approach separates validation logic from storage logic, which enables reuse across different storage implementations and provides consistent validation behavior.
136
87
137
-
**Alternatives considered:**
138
-
-**Validation in Engine**: Would duplicate validation logic
139
-
-**Webhook-based validation**: Adds network overhead and complexity
88
+
Two alternatives were considered. Either validate in engine or webhook-based validation. However, validation in engine duplicated validation logic, while webhook-based validation adds network overhead and complexity.
140
89
141
-
**Trade-offs:**
142
-
- Strategy pattern adds abstraction layer
143
-
- Provides clean separation of concerns
144
-
- Enables testing validation independently
90
+
This decision has some trade-offs. The strategy pattern, while adding an abstraction layer, provides a clean separation of concerns and enables independent testing of validation.
145
91
146
92
### Watch via WatcherManager
147
93
148
-
**Decision**: Implement watch streams using Engine's WatcherManager.
94
+
Watch streams using Engine's WatcherManager is implemented.
149
95
150
-
**Rationale:**
151
-
- Engine knows when package revisions change
152
-
- WatcherManager provides efficient fan-out to multiple watchers
153
-
- Avoids polling or etcd watch overhead
154
-
- Enables real-time notifications
96
+
The engine knows when package revisions change. Combined with the WatcherManager's efficient fan-out, this solution enables real-time notifications while avoiding the overhead of polling or etcd watches.
155
97
156
-
**Alternatives considered:**
157
-
-**etcd watch**: Would require storing all data in etcd
158
-
-**Polling**: Inefficient and high latency
98
+
Two alternatives were considered, either etcd watch or polling. However, etcd watch requires storing all data in etcd, while polling is inefficient and causes high latency.
159
99
160
-
**Trade-offs:**
161
-
- Custom watch implementation more complex
162
-
- Provides efficient real-time updates
163
-
- Scales to many concurrent watchers
100
+
This decision has some trade-offs. A custom watch implementation, while more complex to develop, offers efficient real-time updates and scales effectively to support many concurrent watchers.
164
101
165
102
### Repository Management Pattern
166
103
167
-
**Decision**: Extract repository synchronization into a dedicated Repository Controller using controller-runtime framework.
168
-
169
-
**Rationale:**
170
-
- Separates concerns: API server handles requests, controller manages repository lifecycle
- Better separation of concerns and operational flexibility
184
-
- Improved observability with controller metrics and status
185
-
186
-
**Implementation:**
187
-
The Repository Controller manages Repository CRs through standard Kubernetes reconciliation:
188
-
- Watches Repository resources for spec changes
189
-
- Performs health checks and full syncs on configurable schedules
190
-
- Updates repository status with sync results and package metadata
191
-
- Handles repository deletion and cache cleanup
192
-
- See [Repository Controller]({{% relref "/docs/5_architecture_and_components/controllers/repository-controller/_index.md" %}}) for details
104
+
Repository synchronization is extracted into a dedicated Repository Controller using `controller-runtime` framework.
105
+
106
+
This design separates concerns by dedicating the API server to request handling and the controller to managing the repository lifecycle. Leveraging `controller-runtime` provides proven patterns for watch management, work queues, and leader election, leading to better scalability through concurrent reconciliation and rate limiting. This architecture also allows for independent deployment and scaling of repository management, and facilitates cleaner shutdown and error handling.
107
+
108
+
Three alternatives were considered: background goroutines in the API server, sync on demand or the implementation of custom controller. However, background goroutines mix request handling with background sync logic, sync on demand adds latency to API requests and custom controller implementation reinvents controller-runtime features.
109
+
110
+
This decision has some trade-offs. The introduction of a dedicated Repository Controller as an additional deployment component offers significant advantages, including a better separation of concerns, enhanced operational flexibility, and improved observability through specialized controller metrics and status reporting.
111
+
112
+
The Repository Controller manages Repository CRs through standard Kubernetes reconciliation to manage Repository Custom Resources (CRs). Its core functions include watching for changes in Repository specifications, conducting scheduled health checks and full synchronizations, updating the repository status with synchronization results and package metadata, and managing repository deletion and cache cleanup. For more information, see [Repository Controller]({{% relref "/docs/5_architecture_and_components/controllers/repository-controller/_index.md" %}}).
193
113
194
114
### Dependency Injection
195
115
196
-
**Decision**: Configure Engine, Cache, and clients through dependency injection.
116
+
Engine, Cache, and clients are configured through dependency injection.
197
117
198
-
**Rationale:**
199
-
- Enables testing with mock implementations
200
-
- Provides flexible configuration
201
-
- Separates construction from usage
202
-
- Supports different deployment scenarios
118
+
This approach is justified by its ability to enable testing with mock implementations, provide flexible configuration options, separate the construction of components from their usage, and support various deployment scenarios.
203
119
204
-
**Alternatives considered:**
205
-
-**Global singletons**: Hard to test and configure
206
-
-**Service locator**: Hides dependencies
120
+
Two alternatives were considered. Either global singletons or a service locator. However, global singletons are hard to test and configure, and a service locator hides dependencies.
207
121
208
-
**Trade-offs:**
209
-
- Requires explicit wiring during initialization
210
-
- Provides clear dependency graph
211
-
- Enables flexible testing and configuration
122
+
This decision has some trade-offs. While it requires explicit wiring during initialization, it offers the significant benefits of a clear dependency graph and enables flexible testing and configuration.
0 commit comments