@fjall/components-infrastructure 10.1.2 → 11.0.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/dist/lib/patterns/aws/clickhouseDatabase.d.ts +13 -7
- package/dist/lib/patterns/aws/clickhouseDatabase.js +21 -16
- package/dist/lib/patterns/aws/computeEcs.js +7 -1
- package/dist/lib/resources/aws/compute/ecs.js +1 -1
- package/dist/lib/resources/aws/compute/ecsConstants.d.ts +36 -0
- package/dist/lib/resources/aws/compute/ecsConstants.js +113 -0
- package/dist/lib/resources/aws/compute/ecsTaskDefinition.js +8 -2
- package/dist/lib/resources/aws/compute/ecsValidation.d.ts +69 -1
- package/dist/lib/resources/aws/compute/ecsValidation.js +113 -2
- package/dist/lib/resources/aws/database/clickhouseConstants.d.ts +24 -9
- package/dist/lib/resources/aws/database/clickhouseConstants.js +32 -23
- package/dist/lib/resources/aws/database/clickhouseSchemas.d.ts +20 -0
- package/dist/lib/resources/aws/database/clickhouseSchemas.js +20 -77
- package/dist/lib/resources/aws/database/clickhouseTuning.d.ts +64 -0
- package/dist/lib/resources/aws/database/clickhouseTuning.js +182 -0
- package/dist/lib/resources/aws/database/clickhouseUserData.d.ts +7 -0
- package/dist/lib/resources/aws/database/clickhouseUserData.js +87 -52
- package/dist/lib/resources/aws/database/clickhouseXmlRenderer.js +10 -0
- package/package.json +3 -3
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { CLICKHOUSE_DATA_MOUNT_PATH, CLICKHOUSE_EBS_DEVICE_NAME, CLICKHOUSE_CONFIG_SUBDIR, CLICKHOUSE_USERS_SUBDIR, CLICKHOUSE_ECS_RESERVED_MEMORY_MIB, CLICKHOUSE_HOST_METRICS, CLICKHOUSE_HTTP_PORT, CLICKHOUSE_HTTPS_PORT, CLICKHOUSE_TCP_SECURE_PORT, CLICKHOUSE_TLS_CERT_MOUNT_PATH, CLICKHOUSE_PROMETHEUS_PORT, CLICKHOUSE_UID, clickHousePasswordSha256Snippet } from "./clickhouseConstants.js";
|
|
2
|
+
import { deriveClickHouseServerTuning, MAX_SERVER_MEMORY_RAM_RATIO, SYSTEM_LOG_TTL } from "./clickhouseTuning.js";
|
|
2
3
|
import { renderUsersXml } from "./clickhouseXmlRenderer.js";
|
|
3
4
|
export function generateServerConfigXml(options) {
|
|
4
5
|
const { backupBucketName, backupBucketRegion, coldTier } = options;
|
|
5
6
|
const tlsActive = options.tls !== undefined;
|
|
7
|
+
const tuning = deriveClickHouseServerTuning(options.instanceType);
|
|
6
8
|
const storageBlock = coldTier !== undefined
|
|
7
9
|
? ` <storage_configuration>
|
|
8
10
|
<!-- Same CH 26 rule as the no-cold-tier branch: a <local_ssd> disk
|
|
@@ -15,6 +17,15 @@ export function generateServerConfigXml(options) {
|
|
|
15
17
|
<endpoint>https://${coldTier.bucketName}.s3.${coldTier.region}.amazonaws.com/cold/</endpoint>
|
|
16
18
|
<use_environment_credentials>true</use_environment_credentials>
|
|
17
19
|
<metadata_path>/var/lib/clickhouse/disks/s3_cold/</metadata_path>
|
|
20
|
+
<!-- Blob garbage collection defaults to a 1 s wake — pure
|
|
21
|
+
schedule-pool churn on this workload (prod 2026-08-12:
|
|
22
|
+
353,035 runs removed 1 blob). Cold-tier parts move on a
|
|
23
|
+
TTL measured in days, so a 60 s cadence loses nothing.
|
|
24
|
+
Key: DiskObjectStorage reads
|
|
25
|
+
<disk>.data_background_cleanup.interval_sec (CH 26.3). -->
|
|
26
|
+
<data_background_cleanup>
|
|
27
|
+
<interval_sec>60</interval_sec>
|
|
28
|
+
</data_background_cleanup>
|
|
18
29
|
</s3_cold>
|
|
19
30
|
</disks>
|
|
20
31
|
<policies>
|
|
@@ -89,65 +100,67 @@ export function generateServerConfigXml(options) {
|
|
|
89
100
|
work, but explicit beats implicit and keeps the listener identical
|
|
90
101
|
across network modes. -->
|
|
91
102
|
<listen_host>0.0.0.0</listen_host>
|
|
92
|
-
<!--
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
<!-- 0.75 ratio gives the kernel
|
|
100
|
-
|
|
103
|
+
<!-- Small-node tuning philosophy: trade RAM for CPU — size caches
|
|
104
|
+
generously so dashboard reads hit cache rather than rescanning, and
|
|
105
|
+
let a single query use most of the budget if needed. Every pool,
|
|
106
|
+
cache and concurrency value below is derived from the instance type
|
|
107
|
+
by deriveClickHouseServerTuning (clickhouseTuning.ts) — the
|
|
108
|
+
pre-derivation shape (hand-tuned m7g.medium constants) silently
|
|
109
|
+
stopped fitting when the instance moved to r8g.medium. -->
|
|
110
|
+
<!-- 0.75 ratio gives the kernel a cushion on the cgroup for CH's
|
|
111
|
+
untracked allocations (libc allocator, executable image, malloc
|
|
101
112
|
fragmentation, jemalloc virtual reservations on ARM64). The default
|
|
102
|
-
0.9 left only ~300 MB and OOM-killed the process
|
|
103
|
-
+ thread init pushed the cgroup over the limit
|
|
104
|
-
Computed at runtime from the cgroup limit so it
|
|
105
|
-
|
|
106
|
-
<max_server_memory_usage_to_ram_ratio
|
|
113
|
+
0.9 left only ~300 MB on the 4 GiB host and OOM-killed the process
|
|
114
|
+
at boot when cache + thread init pushed the cgroup over the limit
|
|
115
|
+
(exit 137 in CW). Computed at runtime from the cgroup limit so it
|
|
116
|
+
tracks instance size. -->
|
|
117
|
+
<max_server_memory_usage_to_ram_ratio>${MAX_SERVER_MEMORY_RAM_RATIO}</max_server_memory_usage_to_ram_ratio>
|
|
107
118
|
<!-- Per-query caps (max_memory_usage, max_bytes_before_external_sort,
|
|
108
119
|
max_bytes_before_external_group_by) live in the profile blocks of
|
|
109
120
|
users.xml — ClickHouse 26.3.10 rejects them at top level with
|
|
110
121
|
UNKNOWN_ELEMENT_IN_CONFIG. The default localhost user inherits
|
|
111
122
|
ClickHouse's built-in defaults; workload users (app_writer,
|
|
112
123
|
audit_writer, backup_reader, schema_admin) carry explicit caps. -->
|
|
113
|
-
<!--
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
<mark_cache_size
|
|
118
|
-
<index_mark_cache_size
|
|
124
|
+
<!-- Mark + index-mark caches scale linearly with instance memory
|
|
125
|
+
(384 MiB + 128 MiB at the 4 GiB baseline). CH counts these against
|
|
126
|
+
max_server_memory_usage. On a single-tenant dashboard workload they
|
|
127
|
+
pay back fast — same queries repeat, mark hits avoid index re-scans. -->
|
|
128
|
+
<mark_cache_size>${tuning.markCacheBytes}</mark_cache_size>
|
|
129
|
+
<index_mark_cache_size>${tuning.indexMarkCacheBytes}</index_mark_cache_size>
|
|
119
130
|
<!-- Filesystem page cache handles uncompressed-block warmth on the
|
|
120
131
|
host side; an in-CH uncompressed cache would just duplicate it. -->
|
|
121
132
|
<uncompressed_cache_size>0</uncompressed_cache_size>
|
|
122
|
-
<!-- Server-wide cap across ALL users
|
|
123
|
-
high_throughput_ingest's per-user cap
|
|
124
|
-
fires 6-10 queries per page load and
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
<
|
|
136
|
-
<
|
|
137
|
-
<
|
|
133
|
+
<!-- Server-wide cap across ALL users, 8 per vCPU (raised 4→8 2026-07-28
|
|
134
|
+
alongside high_throughput_ingest's per-user cap 2→6: the webapp
|
|
135
|
+
overview fires 6-10 queries per page load and CH rejects rather than
|
|
136
|
+
queues past the cap). On a 1 vCPU host the slots time-slice rather
|
|
137
|
+
than parallelise — acceptable for short cache-hot dashboard reads. -->
|
|
138
|
+
<max_concurrent_queries>${tuning.maxConcurrentQueries}</max_concurrent_queries>
|
|
139
|
+
<background_pool_size>${tuning.backgroundPoolSize}</background_pool_size>
|
|
140
|
+
<!-- Floored at 8 regardless of size: CH >= 25.9 caps same-type
|
|
141
|
+
background tasks at floor(pool * 0.8) and logs a warning on every
|
|
142
|
+
deferred task start — a pool of 2 (cap 1) flooded prod with ~35k
|
|
143
|
+
warnings/hour and serialised all background scheduling
|
|
144
|
+
(2026-08-12). The cap is computed once at pool creation, so this
|
|
145
|
+
value only changes behaviour after a server restart. -->
|
|
146
|
+
<background_schedule_pool_size>${tuning.backgroundSchedulePoolSize}</background_schedule_pool_size>
|
|
147
|
+
<background_merges_mutations_concurrency_ratio>${tuning.mergesMutationsConcurrencyRatio}</background_merges_mutations_concurrency_ratio>
|
|
148
|
+
<background_move_pool_size>${tuning.backgroundMovePoolSize}</background_move_pool_size>
|
|
149
|
+
<background_fetches_pool_size>${tuning.backgroundFetchesPoolSize}</background_fetches_pool_size>
|
|
150
|
+
<background_message_broker_schedule_pool_size>${tuning.backgroundMessageBrokerSchedulePoolSize}</background_message_broker_schedule_pool_size>
|
|
138
151
|
<merge_tree>
|
|
139
152
|
<max_suspicious_broken_parts>5</max_suspicious_broken_parts>
|
|
140
153
|
<parts_to_delay_insert>150</parts_to_delay_insert>
|
|
141
154
|
<parts_to_throw_insert>300</parts_to_throw_insert>
|
|
142
155
|
<!-- ClickHouse 26.3.10 sanity-checks the free-pool thresholds against
|
|
143
156
|
background_pool_size * background_merges_mutations_concurrency_ratio
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
<number_of_free_entries_in_pool_to_execute_mutation
|
|
149
|
-
<number_of_free_entries_in_pool_to_lower_max_size_of_merge
|
|
150
|
-
<number_of_free_entries_in_pool_to_execute_optimize_entire_partition
|
|
157
|
+
and trips BAD_ARGUMENTS at startup when a threshold exceeds the
|
|
158
|
+
slot count (the CH defaults 20/8/25 all exceed a small pool).
|
|
159
|
+
Derived as max(1, slots/4) so the invariant holds by
|
|
160
|
+
construction at every instance size. -->
|
|
161
|
+
<number_of_free_entries_in_pool_to_execute_mutation>${tuning.freeEntriesToExecuteMutation}</number_of_free_entries_in_pool_to_execute_mutation>
|
|
162
|
+
<number_of_free_entries_in_pool_to_lower_max_size_of_merge>${tuning.freeEntriesToLowerMaxSizeOfMerge}</number_of_free_entries_in_pool_to_lower_max_size_of_merge>
|
|
163
|
+
<number_of_free_entries_in_pool_to_execute_optimize_entire_partition>${tuning.freeEntriesToExecuteOptimizeEntirePartition}</number_of_free_entries_in_pool_to_execute_optimize_entire_partition>
|
|
151
164
|
</merge_tree>
|
|
152
165
|
${tlsActive
|
|
153
166
|
? ` <https_port>${CLICKHOUSE_HTTPS_PORT}</https_port>
|
|
@@ -170,38 +183,60 @@ ${tlsActive
|
|
|
170
183
|
<database>system</database>
|
|
171
184
|
<table>query_log</table>
|
|
172
185
|
<flush_interval_milliseconds>7500</flush_interval_milliseconds>
|
|
173
|
-
<ttl
|
|
186
|
+
<ttl>${SYSTEM_LOG_TTL}</ttl>
|
|
174
187
|
</query_log>
|
|
175
188
|
<!-- All system log tables need bounded retention on 80GB EBS (mirror query_log's 14-day policy). -->
|
|
176
189
|
<asynchronous_metric_log>
|
|
177
190
|
<database>system</database>
|
|
178
191
|
<table>asynchronous_metric_log</table>
|
|
179
|
-
<ttl
|
|
192
|
+
<ttl>${SYSTEM_LOG_TTL}</ttl>
|
|
180
193
|
</asynchronous_metric_log>
|
|
181
194
|
<metric_log>
|
|
182
195
|
<database>system</database>
|
|
183
196
|
<table>metric_log</table>
|
|
184
|
-
<ttl
|
|
197
|
+
<ttl>${SYSTEM_LOG_TTL}</ttl>
|
|
185
198
|
</metric_log>
|
|
186
199
|
<part_log>
|
|
187
200
|
<database>system</database>
|
|
188
201
|
<table>part_log</table>
|
|
189
|
-
<ttl
|
|
202
|
+
<ttl>${SYSTEM_LOG_TTL}</ttl>
|
|
190
203
|
</part_log>
|
|
191
204
|
<error_log>
|
|
192
205
|
<database>system</database>
|
|
193
206
|
<table>error_log</table>
|
|
194
|
-
<ttl
|
|
207
|
+
<ttl>${SYSTEM_LOG_TTL}</ttl>
|
|
195
208
|
</error_log>
|
|
209
|
+
<!-- CH creates these three by default with NO retention — the trace_log
|
|
210
|
+
family alone reached 3.5 GiB on prod before TTLs landed (2026-08-12).
|
|
211
|
+
Adding <ttl> changes the storage definition: on first boot after this
|
|
212
|
+
change CH renames each existing table to a *_N sibling and creates a
|
|
213
|
+
fresh one with the TTL. The renamed tables keep their data and need a
|
|
214
|
+
manual DROP TABLE to reclaim the disk. -->
|
|
215
|
+
<text_log>
|
|
216
|
+
<database>system</database>
|
|
217
|
+
<table>text_log</table>
|
|
218
|
+
<ttl>${SYSTEM_LOG_TTL}</ttl>
|
|
219
|
+
</text_log>
|
|
220
|
+
<trace_log>
|
|
221
|
+
<database>system</database>
|
|
222
|
+
<table>trace_log</table>
|
|
223
|
+
<ttl>${SYSTEM_LOG_TTL}</ttl>
|
|
224
|
+
</trace_log>
|
|
225
|
+
<background_schedule_pool_log>
|
|
226
|
+
<database>system</database>
|
|
227
|
+
<table>background_schedule_pool_log</table>
|
|
228
|
+
<ttl>${SYSTEM_LOG_TTL}</ttl>
|
|
229
|
+
</background_schedule_pool_log>
|
|
196
230
|
${storageBlock}
|
|
197
231
|
${backupEndpointBlock}
|
|
198
|
-
<!--
|
|
199
|
-
|
|
200
|
-
|
|
232
|
+
<!-- Query cache scales with instance memory (256 MiB at the 4 GiB
|
|
233
|
+
baseline). Single-tenant dashboard pattern means the same queries
|
|
234
|
+
repeat at fixed cadences (5/15min refresh, manual reloads); a hit
|
|
235
|
+
returns in microseconds instead of re-scanning. Sized generously
|
|
201
236
|
relative to other caches because the workload pattern is uniquely
|
|
202
237
|
cache-friendly. -->
|
|
203
238
|
<query_cache>
|
|
204
|
-
<max_size_in_bytes
|
|
239
|
+
<max_size_in_bytes>${tuning.queryCacheBytes}</max_size_in_bytes>
|
|
205
240
|
<max_entries>1024</max_entries>
|
|
206
241
|
<max_entry_size_in_bytes>1048576</max_entry_size_in_bytes>
|
|
207
242
|
</query_cache>
|
|
@@ -95,6 +95,16 @@ export function renderUsersXml(opts) {
|
|
|
95
95
|
box that's a merge-pool starvation event. Keep TTL changes lazy: parts
|
|
96
96
|
re-evaluate TTL on their next natural merge, no forced rewrite. -->
|
|
97
97
|
<materialize_ttl_after_modify>0</materialize_ttl_after_modify>
|
|
98
|
+
<!-- Official builds sample every running query's stacks at 1 s
|
|
99
|
+
into system.trace_log. Nothing in the Fjall offering reads
|
|
100
|
+
those samples, and on a 1-vCPU node the sampling costs CPU
|
|
101
|
+
and disk (trace_log was the fastest-growing system table on
|
|
102
|
+
prod, 2026-08-12). The default profile is the server-wide
|
|
103
|
+
base, so this disables the profiler for every user; re-enable
|
|
104
|
+
per session (SET query_profiler_real_time_period_ns = 1000000000)
|
|
105
|
+
when actively profiling. -->
|
|
106
|
+
<query_profiler_real_time_period_ns>0</query_profiler_real_time_period_ns>
|
|
107
|
+
<query_profiler_cpu_time_period_ns>0</query_profiler_cpu_time_period_ns>
|
|
98
108
|
</default>`;
|
|
99
109
|
const profileBlocks = Object.entries(opts.profiles)
|
|
100
110
|
.map(([name, spec]) => renderProfileBlock(name, spec))
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fjall/components-infrastructure",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "11.0.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/fjall-tech/fjall.git",
|
|
@@ -80,8 +80,8 @@
|
|
|
80
80
|
},
|
|
81
81
|
"dependencies": {
|
|
82
82
|
"@aws-sdk/client-organizations": "^3.1098.0",
|
|
83
|
-
"@fjall/generator": "^
|
|
84
|
-
"@fjall/util": "^
|
|
83
|
+
"@fjall/generator": "^11.0.0",
|
|
84
|
+
"@fjall/util": "^11.0.0",
|
|
85
85
|
"constructs": "^10.7.2"
|
|
86
86
|
},
|
|
87
87
|
"overrides": {
|