@girardmedia/bootspring 3.3.2 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/agents/accessibility-auditor.md +39 -0
- package/assets/agents/api-designer.md +40 -0
- package/assets/agents/auth-implementer.md +64 -0
- package/assets/agents/bug-hunter.md +42 -0
- package/assets/agents/bundle-analyzer.md +40 -0
- package/assets/agents/cache-optimizer.md +55 -0
- package/assets/agents/changelog-writer.md +55 -0
- package/assets/agents/ci-cd-builder.md +40 -0
- package/assets/agents/code-explainer.md +39 -0
- package/assets/agents/code-reviewer.md +39 -0
- package/assets/agents/cost-optimizer.md +57 -0
- package/assets/agents/cron-scheduler.md +51 -0
- package/assets/agents/data-seeder.md +56 -0
- package/assets/agents/database-architect.md +40 -0
- package/assets/agents/dependency-updater.md +40 -0
- package/assets/agents/deploy-checker.md +40 -0
- package/assets/agents/docker-optimizer.md +40 -0
- package/assets/agents/documentation-writer.md +40 -0
- package/assets/agents/email-builder.md +55 -0
- package/assets/agents/env-setup.md +40 -0
- package/assets/agents/error-handler.md +40 -0
- package/assets/agents/eslint-fixer.md +46 -0
- package/assets/agents/feature-flagger.md +69 -0
- package/assets/agents/git-detective.md +39 -0
- package/assets/agents/graphql-builder.md +60 -0
- package/assets/agents/incident-responder.md +59 -0
- package/assets/agents/log-analyzer.md +39 -0
- package/assets/agents/migration-planner.md +41 -0
- package/assets/agents/monorepo-navigator.md +39 -0
- package/assets/agents/nextjs-expert.md +57 -0
- package/assets/agents/notification-builder.md +56 -0
- package/assets/agents/onboarding-guide.md +39 -0
- package/assets/agents/performance-profiler.md +40 -0
- package/assets/agents/prisma-expert.md +57 -0
- package/assets/agents/rate-limiter.md +58 -0
- package/assets/agents/react-expert.md +58 -0
- package/assets/agents/refactorer.md +42 -0
- package/assets/agents/regex-builder.md +46 -0
- package/assets/agents/release-manager.md +40 -0
- package/assets/agents/s3-manager.md +58 -0
- package/assets/agents/schema-validator.md +40 -0
- package/assets/agents/search-builder.md +62 -0
- package/assets/agents/security-auditor.md +39 -0
- package/assets/agents/sitemap-generator.md +53 -0
- package/assets/agents/stripe-integrator.md +59 -0
- package/assets/agents/tailwind-expert.md +55 -0
- package/assets/agents/tech-debt-tracker.md +39 -0
- package/assets/agents/test-writer.md +42 -0
- package/assets/agents/type-fixer.md +45 -0
- package/assets/agents/webhook-builder.md +54 -0
- package/assets/rules/cpp.md +53 -0
- package/assets/rules/css.md +52 -0
- package/assets/rules/go.md +50 -0
- package/assets/rules/html.md +52 -0
- package/assets/rules/java.md +51 -0
- package/assets/rules/kotlin.md +50 -0
- package/assets/rules/php.md +51 -0
- package/assets/rules/python.md +51 -0
- package/assets/rules/ruby.md +51 -0
- package/assets/rules/rust.md +49 -0
- package/assets/rules/shell.md +52 -0
- package/assets/rules/sql.md +49 -0
- package/assets/rules/swift.md +50 -0
- package/assets/rules/typescript.md +52 -0
- package/assets/rules/yaml-json.md +51 -0
- package/assets/skills/accessibility.md +210 -0
- package/assets/skills/agent-patterns.md +387 -0
- package/assets/skills/ai-integration.md +263 -0
- package/assets/skills/animation-patterns.md +224 -0
- package/assets/skills/api-design.md +218 -0
- package/assets/skills/api-gateway.md +341 -0
- package/assets/skills/api-versioning.md +226 -0
- package/assets/skills/astro-patterns.md +233 -0
- package/assets/skills/auth-patterns.md +248 -0
- package/assets/skills/aws-patterns.md +171 -0
- package/assets/skills/background-jobs.md +162 -0
- package/assets/skills/browser-extensions.md +309 -0
- package/assets/skills/caching-patterns.md +253 -0
- package/assets/skills/ci-cd.md +251 -0
- package/assets/skills/cli-development.md +296 -0
- package/assets/skills/code-review.md +185 -0
- package/assets/skills/cron-patterns.md +327 -0
- package/assets/skills/data-fetching.md +231 -0
- package/assets/skills/database-migrations.md +346 -0
- package/assets/skills/database-patterns.md +219 -0
- package/assets/skills/debugging.md +281 -0
- package/assets/skills/design-system.md +289 -0
- package/assets/skills/django-patterns.md +182 -0
- package/assets/skills/docker-patterns.md +235 -0
- package/assets/skills/e2e-testing.md +287 -0
- package/assets/skills/edge-computing.md +268 -0
- package/assets/skills/electron-patterns.md +266 -0
- package/assets/skills/email-templates.md +206 -0
- package/assets/skills/error-handling.md +265 -0
- package/assets/skills/event-driven.md +232 -0
- package/assets/skills/express-patterns.md +239 -0
- package/assets/skills/fastapi-patterns.md +198 -0
- package/assets/skills/feature-flags.md +212 -0
- package/assets/skills/figma-to-code.md +298 -0
- package/assets/skills/file-upload.md +228 -0
- package/assets/skills/forms-patterns.md +264 -0
- package/assets/skills/gcp-patterns.md +189 -0
- package/assets/skills/git-workflow.md +187 -0
- package/assets/skills/golang-patterns.md +185 -0
- package/assets/skills/graphql-patterns.md +244 -0
- package/assets/skills/i18n-patterns.md +172 -0
- package/assets/skills/image-processing.md +350 -0
- package/assets/skills/java-springboot.md +226 -0
- package/assets/skills/kotlin-patterns.md +207 -0
- package/assets/skills/kubernetes-patterns.md +326 -0
- package/assets/skills/laravel-patterns.md +261 -0
- package/assets/skills/llm-fine-tuning.md +335 -0
- package/assets/skills/load-testing.md +303 -0
- package/assets/skills/logging-observability.md +228 -0
- package/assets/skills/markdown-processing.md +318 -0
- package/assets/skills/mcp-server-patterns.md +292 -0
- package/assets/skills/microservices.md +272 -0
- package/assets/skills/migration-patterns.md +239 -0
- package/assets/skills/mongodb-patterns.md +189 -0
- package/assets/skills/monorepo-patterns.md +287 -0
- package/assets/skills/nextjs-app-router.md +237 -0
- package/assets/skills/notification-patterns.md +348 -0
- package/assets/skills/oauth-patterns.md +246 -0
- package/assets/skills/payment-integration.md +222 -0
- package/assets/skills/pdf-generation.md +307 -0
- package/assets/skills/performance-optimization.md +277 -0
- package/assets/skills/php-patterns.md +210 -0
- package/assets/skills/prisma-patterns.md +241 -0
- package/assets/skills/prompt-engineering.md +193 -0
- package/assets/skills/pwa-patterns.md +247 -0
- package/assets/skills/python-patterns.md +158 -0
- package/assets/skills/python-testing.md +172 -0
- package/assets/skills/queue-patterns.md +295 -0
- package/assets/skills/rag-patterns.md +159 -0
- package/assets/skills/rate-limiting.md +319 -0
- package/assets/skills/react-components.md +201 -0
- package/assets/skills/react-native-patterns.md +299 -0
- package/assets/skills/real-time-patterns.md +181 -0
- package/assets/skills/redis-patterns.md +188 -0
- package/assets/skills/refactoring.md +218 -0
- package/assets/skills/regex-patterns.md +191 -0
- package/assets/skills/remix-patterns.md +262 -0
- package/assets/skills/responsive-design.md +199 -0
- package/assets/skills/ruby-rails-patterns.md +178 -0
- package/assets/skills/rust-patterns.md +211 -0
- package/assets/skills/search-patterns.md +227 -0
- package/assets/skills/security-hardening.md +237 -0
- package/assets/skills/seo-patterns.md +179 -0
- package/assets/skills/serverless-patterns.md +223 -0
- package/assets/skills/sql-optimization.md +154 -0
- package/assets/skills/state-management.md +254 -0
- package/assets/skills/storybook-patterns.md +330 -0
- package/assets/skills/svelte-patterns.md +258 -0
- package/assets/skills/swift-patterns.md +227 -0
- package/assets/skills/tailwind-patterns.md +272 -0
- package/assets/skills/tdd-workflow.md +199 -0
- package/assets/skills/terraform-patterns.md +270 -0
- package/assets/skills/testing-react.md +240 -0
- package/assets/skills/testing-vitest.md +232 -0
- package/assets/skills/typescript-strict.md +159 -0
- package/assets/skills/video-processing.md +340 -0
- package/assets/skills/vue-patterns.md +247 -0
- package/assets/skills/web-workers.md +327 -0
- package/assets/skills/webhooks-patterns.md +283 -0
- package/assets/skills/websocket-patterns.md +306 -0
- package/dist/cli/index.js +941 -958
- package/dist/core/index.d.ts +341 -11
- package/dist/core.js +58 -95
- package/dist/mcp/index.d.ts +33 -1
- package/dist/mcp-server.js +177 -255
- package/package.json +4 -1
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kotlin-patterns
|
|
3
|
+
description: Kotlin patterns for coroutines, sealed classes, extension functions, DSL builders, and null safety.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Kotlin Patterns
|
|
7
|
+
|
|
8
|
+
## When to Use
|
|
9
|
+
|
|
10
|
+
Apply these patterns when writing Kotlin code for Android, backend (Ktor, Spring),
|
|
11
|
+
or multiplatform projects. Use this skill for structured concurrency with coroutines,
|
|
12
|
+
modeling state with sealed classes, writing expressive DSLs, and leveraging Kotlin's
|
|
13
|
+
null safety system.
|
|
14
|
+
|
|
15
|
+
## How It Works
|
|
16
|
+
|
|
17
|
+
### Coroutines and Structured Concurrency
|
|
18
|
+
|
|
19
|
+
Use `coroutineScope` or `supervisorScope` for structured concurrency. Never use
|
|
20
|
+
`GlobalScope`. Launch coroutines within a scope that ties their lifecycle to a
|
|
21
|
+
parent component.
|
|
22
|
+
|
|
23
|
+
```kotlin
|
|
24
|
+
class UserRepository(private val api: UserApi, private val db: UserDao) {
|
|
25
|
+
suspend fun sync(ids: List<String>): List<User> = coroutineScope {
|
|
26
|
+
val deferred = ids.map { id ->
|
|
27
|
+
async { api.fetchUser(id) }
|
|
28
|
+
}
|
|
29
|
+
val users = deferred.awaitAll()
|
|
30
|
+
db.insertAll(users)
|
|
31
|
+
users
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// With timeout and cancellation
|
|
36
|
+
suspend fun fetchWithTimeout(url: String): String {
|
|
37
|
+
return withTimeout(10_000) {
|
|
38
|
+
httpClient.get(url).bodyAsText()
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Flow for Reactive Streams
|
|
44
|
+
|
|
45
|
+
Use `Flow` instead of callbacks or RxJava. Use `stateIn` to convert a Flow to a
|
|
46
|
+
`StateFlow` for UI observation. Apply operators like `map`, `filter`, `debounce`.
|
|
47
|
+
|
|
48
|
+
```kotlin
|
|
49
|
+
class SearchViewModel(private val repo: SearchRepo) : ViewModel() {
|
|
50
|
+
private val _query = MutableStateFlow("")
|
|
51
|
+
|
|
52
|
+
val results: StateFlow<List<Result>> = _query
|
|
53
|
+
.debounce(300)
|
|
54
|
+
.filter { it.length >= 2 }
|
|
55
|
+
.flatMapLatest { query -> repo.search(query) }
|
|
56
|
+
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList())
|
|
57
|
+
|
|
58
|
+
fun onQueryChanged(text: String) {
|
|
59
|
+
_query.value = text
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Sealed Classes and Interfaces
|
|
65
|
+
|
|
66
|
+
Use sealed classes/interfaces to model closed type hierarchies. Combine with
|
|
67
|
+
`when` expressions for exhaustive handling. The compiler enforces you handle
|
|
68
|
+
every variant.
|
|
69
|
+
|
|
70
|
+
```kotlin
|
|
71
|
+
sealed interface UiState<out T> {
|
|
72
|
+
data object Loading : UiState<Nothing>
|
|
73
|
+
data class Success<T>(val data: T) : UiState<T>
|
|
74
|
+
data class Error(val message: String, val retry: (() -> Unit)? = null) : UiState<Nothing>
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
fun <T> render(state: UiState<T>) {
|
|
78
|
+
when (state) {
|
|
79
|
+
is UiState.Loading -> showSpinner()
|
|
80
|
+
is UiState.Success -> showData(state.data)
|
|
81
|
+
is UiState.Error -> showError(state.message, state.retry)
|
|
82
|
+
// No else needed — compiler ensures exhaustive
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Extension Functions
|
|
88
|
+
|
|
89
|
+
Add behavior to existing types without inheritance. Keep extensions focused and
|
|
90
|
+
discoverable. Place them in a file named after the type they extend.
|
|
91
|
+
|
|
92
|
+
```kotlin
|
|
93
|
+
// StringExtensions.kt
|
|
94
|
+
fun String.truncate(maxLength: Int, suffix: String = "..."): String {
|
|
95
|
+
return if (length <= maxLength) this
|
|
96
|
+
else take(maxLength - suffix.length) + suffix
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
fun String.toSlug(): String {
|
|
100
|
+
return lowercase()
|
|
101
|
+
.replace(Regex("[^a-z0-9\\s-]"), "")
|
|
102
|
+
.replace(Regex("\\s+"), "-")
|
|
103
|
+
.trim('-')
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Usage reads naturally
|
|
107
|
+
val title = "A Very Long Article Title Here".truncate(20)
|
|
108
|
+
val slug = "My Blog Post!".toSlug() // "my-blog-post"
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### DSL Builders
|
|
112
|
+
|
|
113
|
+
Use `@DslMarker` to prevent scope leaks. Use receiver lambdas (`T.() -> Unit`)
|
|
114
|
+
to create nested builder syntax.
|
|
115
|
+
|
|
116
|
+
```kotlin
|
|
117
|
+
@DslMarker
|
|
118
|
+
annotation class HtmlDsl
|
|
119
|
+
|
|
120
|
+
@HtmlDsl
|
|
121
|
+
class HtmlBuilder {
|
|
122
|
+
private val elements = mutableListOf<String>()
|
|
123
|
+
|
|
124
|
+
fun head(block: HeadBuilder.() -> Unit) {
|
|
125
|
+
elements += HeadBuilder().apply(block).build()
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
fun body(block: BodyBuilder.() -> Unit) {
|
|
129
|
+
elements += BodyBuilder().apply(block).build()
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
fun build(): String = "<html>${elements.joinToString("")}</html>"
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
fun html(block: HtmlBuilder.() -> Unit): String {
|
|
136
|
+
return HtmlBuilder().apply(block).build()
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Usage
|
|
140
|
+
val page = html {
|
|
141
|
+
head { title("My Page") }
|
|
142
|
+
body { p("Hello, world!") }
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Null Safety
|
|
147
|
+
|
|
148
|
+
Use `?.` for safe calls, `?:` (Elvis) for defaults. Avoid `!!` except in tests.
|
|
149
|
+
Use `require` / `check` for preconditions that throw on violation.
|
|
150
|
+
|
|
151
|
+
```kotlin
|
|
152
|
+
fun processUser(user: User?) {
|
|
153
|
+
// Safe call chain
|
|
154
|
+
val city = user?.address?.city ?: "Unknown"
|
|
155
|
+
|
|
156
|
+
// Smart cast after null check
|
|
157
|
+
user ?: return
|
|
158
|
+
// user is now non-null below
|
|
159
|
+
println(user.name)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
fun createOrder(items: List<Item>) {
|
|
163
|
+
require(items.isNotEmpty()) { "Order must have at least one item" }
|
|
164
|
+
check(items.all { it.inStock }) { "All items must be in stock" }
|
|
165
|
+
// proceed with non-empty, validated items
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Examples
|
|
170
|
+
|
|
171
|
+
**Pattern: Result type for error handling without exceptions**
|
|
172
|
+
```kotlin
|
|
173
|
+
suspend fun fetchUser(id: String): Result<User> = runCatching {
|
|
174
|
+
val response = api.getUser(id)
|
|
175
|
+
response.toDomain()
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Caller
|
|
179
|
+
fetchUser("123")
|
|
180
|
+
.onSuccess { user -> display(user) }
|
|
181
|
+
.onFailure { error -> log(error) }
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Pattern: Delegation for composition**
|
|
185
|
+
```kotlin
|
|
186
|
+
class LoggingList<T>(
|
|
187
|
+
private val inner: MutableList<T> = mutableListOf()
|
|
188
|
+
) : MutableList<T> by inner {
|
|
189
|
+
override fun add(element: T): Boolean {
|
|
190
|
+
println("Adding: $element")
|
|
191
|
+
return inner.add(element)
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Checklist
|
|
197
|
+
|
|
198
|
+
- [ ] Coroutines use `coroutineScope` / `supervisorScope`, never `GlobalScope`
|
|
199
|
+
- [ ] `withTimeout` on all network/IO operations
|
|
200
|
+
- [ ] Sealed classes for closed type hierarchies with exhaustive `when`
|
|
201
|
+
- [ ] Extension functions in dedicated files named after the extended type
|
|
202
|
+
- [ ] DSLs use `@DslMarker` to prevent scope leaks
|
|
203
|
+
- [ ] Zero `!!` in production code (use `requireNotNull` or `checkNotNull` with messages)
|
|
204
|
+
- [ ] `StateFlow` for UI state, `SharedFlow` for events
|
|
205
|
+
- [ ] `data class` for value objects, `value class` for type-safe wrappers
|
|
206
|
+
- [ ] `require` / `check` for preconditions with descriptive messages
|
|
207
|
+
- [ ] `runCatching` / `Result` for operations that can fail without exceptions
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kubernetes-patterns
|
|
3
|
+
description: Kubernetes patterns for deployments, services, configmaps, secrets, HPA, health probes, and RBAC.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Kubernetes Patterns
|
|
7
|
+
|
|
8
|
+
## When to Use
|
|
9
|
+
|
|
10
|
+
Apply these patterns when deploying and managing applications on Kubernetes. Use
|
|
11
|
+
this skill for writing Deployment manifests, exposing services, managing
|
|
12
|
+
configuration and secrets, auto-scaling with HPA, configuring health probes, and
|
|
13
|
+
setting up role-based access control.
|
|
14
|
+
|
|
15
|
+
## How It Works
|
|
16
|
+
|
|
17
|
+
### Deployments
|
|
18
|
+
|
|
19
|
+
Define desired state declaratively. Use labels for selection and organization.
|
|
20
|
+
Set resource requests and limits. Use rolling update strategy for zero-downtime
|
|
21
|
+
deploys.
|
|
22
|
+
|
|
23
|
+
```yaml
|
|
24
|
+
apiVersion: apps/v1
|
|
25
|
+
kind: Deployment
|
|
26
|
+
metadata:
|
|
27
|
+
name: api-server
|
|
28
|
+
labels:
|
|
29
|
+
app: api-server
|
|
30
|
+
version: v1
|
|
31
|
+
spec:
|
|
32
|
+
replicas: 3
|
|
33
|
+
selector:
|
|
34
|
+
matchLabels:
|
|
35
|
+
app: api-server
|
|
36
|
+
strategy:
|
|
37
|
+
type: RollingUpdate
|
|
38
|
+
rollingUpdate:
|
|
39
|
+
maxSurge: 1
|
|
40
|
+
maxUnavailable: 0
|
|
41
|
+
template:
|
|
42
|
+
metadata:
|
|
43
|
+
labels:
|
|
44
|
+
app: api-server
|
|
45
|
+
version: v1
|
|
46
|
+
spec:
|
|
47
|
+
terminationGracePeriodSeconds: 30
|
|
48
|
+
containers:
|
|
49
|
+
- name: api
|
|
50
|
+
image: registry.example.com/api:1.2.3
|
|
51
|
+
ports:
|
|
52
|
+
- containerPort: 3000
|
|
53
|
+
protocol: TCP
|
|
54
|
+
resources:
|
|
55
|
+
requests:
|
|
56
|
+
cpu: 250m
|
|
57
|
+
memory: 256Mi
|
|
58
|
+
limits:
|
|
59
|
+
cpu: 500m
|
|
60
|
+
memory: 512Mi
|
|
61
|
+
envFrom:
|
|
62
|
+
- configMapRef:
|
|
63
|
+
name: api-config
|
|
64
|
+
- secretRef:
|
|
65
|
+
name: api-secrets
|
|
66
|
+
readinessProbe:
|
|
67
|
+
httpGet:
|
|
68
|
+
path: /readyz
|
|
69
|
+
port: 3000
|
|
70
|
+
initialDelaySeconds: 5
|
|
71
|
+
periodSeconds: 10
|
|
72
|
+
livenessProbe:
|
|
73
|
+
httpGet:
|
|
74
|
+
path: /healthz
|
|
75
|
+
port: 3000
|
|
76
|
+
initialDelaySeconds: 15
|
|
77
|
+
periodSeconds: 20
|
|
78
|
+
lifecycle:
|
|
79
|
+
preStop:
|
|
80
|
+
exec:
|
|
81
|
+
command: ["/bin/sh", "-c", "sleep 5"]
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Services
|
|
85
|
+
|
|
86
|
+
Use `ClusterIP` for internal communication, `LoadBalancer` for external traffic
|
|
87
|
+
(or use Ingress). Match selectors to pod labels exactly.
|
|
88
|
+
|
|
89
|
+
```yaml
|
|
90
|
+
apiVersion: v1
|
|
91
|
+
kind: Service
|
|
92
|
+
metadata:
|
|
93
|
+
name: api-server
|
|
94
|
+
spec:
|
|
95
|
+
type: ClusterIP
|
|
96
|
+
selector:
|
|
97
|
+
app: api-server
|
|
98
|
+
ports:
|
|
99
|
+
- port: 80
|
|
100
|
+
targetPort: 3000
|
|
101
|
+
protocol: TCP
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
apiVersion: networking.k8s.io/v1
|
|
105
|
+
kind: Ingress
|
|
106
|
+
metadata:
|
|
107
|
+
name: api-ingress
|
|
108
|
+
annotations:
|
|
109
|
+
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
|
110
|
+
nginx.ingress.kubernetes.io/rate-limit: "100"
|
|
111
|
+
spec:
|
|
112
|
+
ingressClassName: nginx
|
|
113
|
+
tls:
|
|
114
|
+
- hosts: [api.example.com]
|
|
115
|
+
secretName: api-tls
|
|
116
|
+
rules:
|
|
117
|
+
- host: api.example.com
|
|
118
|
+
http:
|
|
119
|
+
paths:
|
|
120
|
+
- path: /
|
|
121
|
+
pathType: Prefix
|
|
122
|
+
backend:
|
|
123
|
+
service:
|
|
124
|
+
name: api-server
|
|
125
|
+
port:
|
|
126
|
+
number: 80
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### ConfigMaps and Secrets
|
|
130
|
+
|
|
131
|
+
Use ConfigMaps for non-sensitive configuration. Use Secrets for credentials.
|
|
132
|
+
Mount as environment variables or files. Never commit Secrets to git.
|
|
133
|
+
|
|
134
|
+
```yaml
|
|
135
|
+
apiVersion: v1
|
|
136
|
+
kind: ConfigMap
|
|
137
|
+
metadata:
|
|
138
|
+
name: api-config
|
|
139
|
+
data:
|
|
140
|
+
NODE_ENV: production
|
|
141
|
+
LOG_LEVEL: info
|
|
142
|
+
PORT: "3000"
|
|
143
|
+
CORS_ORIGINS: "https://app.example.com"
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
apiVersion: v1
|
|
147
|
+
kind: Secret
|
|
148
|
+
metadata:
|
|
149
|
+
name: api-secrets
|
|
150
|
+
type: Opaque
|
|
151
|
+
stringData:
|
|
152
|
+
DATABASE_URL: postgresql://user:pass@db:5432/app
|
|
153
|
+
JWT_SECRET: your-secret-here
|
|
154
|
+
API_KEY: external-service-key
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**External Secrets Operator** for production:
|
|
158
|
+
```yaml
|
|
159
|
+
apiVersion: external-secrets.io/v1beta1
|
|
160
|
+
kind: ExternalSecret
|
|
161
|
+
metadata:
|
|
162
|
+
name: api-secrets
|
|
163
|
+
spec:
|
|
164
|
+
refreshInterval: 1h
|
|
165
|
+
secretStoreRef:
|
|
166
|
+
name: aws-secrets-manager
|
|
167
|
+
kind: ClusterSecretStore
|
|
168
|
+
target:
|
|
169
|
+
name: api-secrets
|
|
170
|
+
data:
|
|
171
|
+
- secretKey: DATABASE_URL
|
|
172
|
+
remoteRef:
|
|
173
|
+
key: production/api/database-url
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Health Probes
|
|
177
|
+
|
|
178
|
+
Three types: startup (initial boot), readiness (can serve traffic), liveness
|
|
179
|
+
(is the process healthy). Get the order and timing right.
|
|
180
|
+
|
|
181
|
+
```yaml
|
|
182
|
+
# Startup probe: wait for slow-starting apps
|
|
183
|
+
startupProbe:
|
|
184
|
+
httpGet:
|
|
185
|
+
path: /healthz
|
|
186
|
+
port: 3000
|
|
187
|
+
failureThreshold: 30 # 30 * 10s = 5 minutes to start
|
|
188
|
+
periodSeconds: 10
|
|
189
|
+
|
|
190
|
+
# Readiness probe: should this pod receive traffic?
|
|
191
|
+
readinessProbe:
|
|
192
|
+
httpGet:
|
|
193
|
+
path: /readyz
|
|
194
|
+
port: 3000
|
|
195
|
+
initialDelaySeconds: 5
|
|
196
|
+
periodSeconds: 10
|
|
197
|
+
failureThreshold: 3
|
|
198
|
+
|
|
199
|
+
# Liveness probe: is the process stuck?
|
|
200
|
+
livenessProbe:
|
|
201
|
+
httpGet:
|
|
202
|
+
path: /healthz
|
|
203
|
+
port: 3000
|
|
204
|
+
initialDelaySeconds: 15
|
|
205
|
+
periodSeconds: 20
|
|
206
|
+
failureThreshold: 3
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
**Critical rules:**
|
|
210
|
+
- Readiness checks downstream dependencies (DB, cache). Liveness does not.
|
|
211
|
+
- If liveness fails, Kubernetes kills the pod. Make it lightweight.
|
|
212
|
+
- Set `initialDelaySeconds` higher than your app's boot time.
|
|
213
|
+
|
|
214
|
+
### Horizontal Pod Autoscaler (HPA)
|
|
215
|
+
|
|
216
|
+
Scale based on CPU, memory, or custom metrics. Set `minReplicas` and `maxReplicas`
|
|
217
|
+
to bound scaling. Ensure resource `requests` are set on pods.
|
|
218
|
+
|
|
219
|
+
```yaml
|
|
220
|
+
apiVersion: autoscaling/v2
|
|
221
|
+
kind: HorizontalPodAutoscaler
|
|
222
|
+
metadata:
|
|
223
|
+
name: api-server
|
|
224
|
+
spec:
|
|
225
|
+
scaleTargetRef:
|
|
226
|
+
apiVersion: apps/v1
|
|
227
|
+
kind: Deployment
|
|
228
|
+
name: api-server
|
|
229
|
+
minReplicas: 3
|
|
230
|
+
maxReplicas: 20
|
|
231
|
+
metrics:
|
|
232
|
+
- type: Resource
|
|
233
|
+
resource:
|
|
234
|
+
name: cpu
|
|
235
|
+
target:
|
|
236
|
+
type: Utilization
|
|
237
|
+
averageUtilization: 70
|
|
238
|
+
- type: Resource
|
|
239
|
+
resource:
|
|
240
|
+
name: memory
|
|
241
|
+
target:
|
|
242
|
+
type: Utilization
|
|
243
|
+
averageUtilization: 80
|
|
244
|
+
behavior:
|
|
245
|
+
scaleDown:
|
|
246
|
+
stabilizationWindowSeconds: 300
|
|
247
|
+
policies:
|
|
248
|
+
- type: Percent
|
|
249
|
+
value: 10
|
|
250
|
+
periodSeconds: 60
|
|
251
|
+
scaleUp:
|
|
252
|
+
stabilizationWindowSeconds: 30
|
|
253
|
+
policies:
|
|
254
|
+
- type: Percent
|
|
255
|
+
value: 50
|
|
256
|
+
periodSeconds: 60
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### RBAC
|
|
260
|
+
|
|
261
|
+
Principle of least privilege. Create ServiceAccounts per workload. Bind Roles
|
|
262
|
+
to ServiceAccounts, not users. Use ClusterRole only for cluster-wide resources.
|
|
263
|
+
|
|
264
|
+
```yaml
|
|
265
|
+
apiVersion: v1
|
|
266
|
+
kind: ServiceAccount
|
|
267
|
+
metadata:
|
|
268
|
+
name: api-server
|
|
269
|
+
namespace: production
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
apiVersion: rbac.authorization.k8s.io/v1
|
|
273
|
+
kind: Role
|
|
274
|
+
metadata:
|
|
275
|
+
name: api-server-role
|
|
276
|
+
namespace: production
|
|
277
|
+
rules:
|
|
278
|
+
- apiGroups: [""]
|
|
279
|
+
resources: ["configmaps", "secrets"]
|
|
280
|
+
verbs: ["get", "list"]
|
|
281
|
+
- apiGroups: [""]
|
|
282
|
+
resources: ["pods"]
|
|
283
|
+
verbs: ["get", "list", "watch"]
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
apiVersion: rbac.authorization.k8s.io/v1
|
|
287
|
+
kind: RoleBinding
|
|
288
|
+
metadata:
|
|
289
|
+
name: api-server-binding
|
|
290
|
+
namespace: production
|
|
291
|
+
subjects:
|
|
292
|
+
- kind: ServiceAccount
|
|
293
|
+
name: api-server
|
|
294
|
+
roleRef:
|
|
295
|
+
kind: Role
|
|
296
|
+
name: api-server-role
|
|
297
|
+
apiGroup: rbac.authorization.k8s.io
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
## Examples
|
|
301
|
+
|
|
302
|
+
**Pattern: Pod Disruption Budget for high availability**
|
|
303
|
+
```yaml
|
|
304
|
+
apiVersion: policy/v1
|
|
305
|
+
kind: PodDisruptionBudget
|
|
306
|
+
metadata:
|
|
307
|
+
name: api-server
|
|
308
|
+
spec:
|
|
309
|
+
minAvailable: 2
|
|
310
|
+
selector:
|
|
311
|
+
matchLabels:
|
|
312
|
+
app: api-server
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
## Checklist
|
|
316
|
+
|
|
317
|
+
- [ ] Resource `requests` and `limits` set on every container
|
|
318
|
+
- [ ] Rolling update with `maxUnavailable: 0` for zero-downtime deploys
|
|
319
|
+
- [ ] Readiness probe checks downstream dependencies; liveness probe is lightweight
|
|
320
|
+
- [ ] Startup probe for slow-starting applications
|
|
321
|
+
- [ ] `preStop` hook with sleep to allow load balancer drain
|
|
322
|
+
- [ ] ConfigMaps for config, Secrets for credentials (never in git)
|
|
323
|
+
- [ ] External Secrets Operator for production secret management
|
|
324
|
+
- [ ] HPA with CPU/memory targets and scale-down stabilization window
|
|
325
|
+
- [ ] ServiceAccount per workload with minimal RBAC permissions
|
|
326
|
+
- [ ] PodDisruptionBudget to maintain availability during node maintenance
|