underpost 2.8.71 → 2.8.77
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/.vscode/extensions.json +34 -1
- package/README.md +2 -2
- package/bin/deploy.js +116 -5
- package/cli.md +9 -2
- package/docker-compose.yml +1 -1
- package/manifests/deployment/adminer/service.yaml +1 -1
- package/manifests/deployment/spark/spark-pi-py.yaml +21 -0
- package/manifests/kubelet-config.yaml +65 -0
- package/package.json +1 -1
- package/src/cli/cluster.js +59 -18
- package/src/cli/deploy.js +4 -2
- package/src/cli/image.js +14 -2
- package/src/cli/index.js +7 -0
- package/src/cli/repository.js +9 -6
- package/src/index.js +1 -1
- package/manifests/calico-custom-resources.yaml +0 -25
package/.vscode/extensions.json
CHANGED
|
@@ -5,15 +5,48 @@
|
|
|
5
5
|
"codeium.codeium",
|
|
6
6
|
"eamodio.gitlens",
|
|
7
7
|
"esbenp.prettier-vscode",
|
|
8
|
+
"formulahendry.code-runner",
|
|
8
9
|
"foxundermoon.shell-format",
|
|
10
|
+
"github.codespaces",
|
|
9
11
|
"github.vscode-github-actions",
|
|
10
12
|
"golang.go",
|
|
11
13
|
"google.geminicodeassist",
|
|
14
|
+
"gruntfuggly.todo-tree",
|
|
15
|
+
"mechatroner.rainbow-csv",
|
|
16
|
+
"mindaro-dev.file-downloader",
|
|
17
|
+
"mindaro.mindaro",
|
|
18
|
+
"ms-azuretools.vscode-containers",
|
|
19
|
+
"ms-azuretools.vscode-docker",
|
|
20
|
+
"ms-kubernetes-tools.vscode-kubernetes-tools",
|
|
12
21
|
"ms-python.black-formatter",
|
|
13
22
|
"ms-python.debugpy",
|
|
14
23
|
"ms-python.python",
|
|
15
24
|
"ms-python.vscode-pylance",
|
|
25
|
+
"oderwat.indent-rainbow",
|
|
26
|
+
"pleiades.java-extension-pack-jdk",
|
|
27
|
+
"ravioshankar.scala-gurus",
|
|
28
|
+
"redhat.java",
|
|
29
|
+
"redhat.vscode-xml",
|
|
30
|
+
"redhat.vscode-yaml",
|
|
31
|
+
"ritwickdey.liveserver",
|
|
32
|
+
"scala-lang.scala",
|
|
33
|
+
"scala-lang.scala-snippets",
|
|
34
|
+
"scalameta.metals",
|
|
35
|
+
"shardulm94.trailing-spaces",
|
|
16
36
|
"streetsidesoftware.code-spell-checker",
|
|
17
|
-
"
|
|
37
|
+
"tamasfe.even-better-toml",
|
|
38
|
+
"tobermory.es6-string-html",
|
|
39
|
+
"visualstudioexptteam.intellicode-api-usage-examples",
|
|
40
|
+
"visualstudioexptteam.vscodeintellicode",
|
|
41
|
+
"vmware.vscode-boot-dev-pack",
|
|
42
|
+
"vmware.vscode-spring-boot",
|
|
43
|
+
"vscjava.vscode-gradle",
|
|
44
|
+
"vscjava.vscode-java-debug",
|
|
45
|
+
"vscjava.vscode-java-dependency",
|
|
46
|
+
"vscjava.vscode-java-pack",
|
|
47
|
+
"vscjava.vscode-java-test",
|
|
48
|
+
"vscjava.vscode-maven",
|
|
49
|
+
"vscjava.vscode-spring-boot-dashboard",
|
|
50
|
+
"vscjava.vscode-spring-initializr"
|
|
18
51
|
]
|
|
19
52
|
}
|
package/README.md
CHANGED
|
@@ -68,7 +68,7 @@ Run dev client server
|
|
|
68
68
|
npm run dev
|
|
69
69
|
```
|
|
70
70
|
<!-- -->
|
|
71
|
-
## underpost ci/cd cli v2.8.
|
|
71
|
+
## underpost ci/cd cli v2.8.77
|
|
72
72
|
|
|
73
73
|
### Usage: `underpost [options] [command]`
|
|
74
74
|
```
|
|
@@ -80,7 +80,7 @@ Commands:
|
|
|
80
80
|
new <app-name> Create a new project
|
|
81
81
|
start [options] <deploy-id> [env] Start up server, build pipelines, or services
|
|
82
82
|
clone [options] <uri> Clone github repository
|
|
83
|
-
pull <path> <uri>
|
|
83
|
+
pull [options] <path> <uri> Pull github repository
|
|
84
84
|
cmt [options] <path> <commit-type> [module-tag] [message] Commit github repository
|
|
85
85
|
push [options] <path> <uri> Push github repository
|
|
86
86
|
env <deploy-id> [env] Set environment variables files and conf related to <deploy-id>
|
package/bin/deploy.js
CHANGED
|
@@ -816,8 +816,8 @@ try {
|
|
|
816
816
|
shellExec(`node bin/deploy update-dependencies`);
|
|
817
817
|
shellExec(`auto-changelog`);
|
|
818
818
|
shellExec(`node bin/build dd`);
|
|
819
|
-
shellExec(`node bin deploy --build-manifest --sync --info-router --replicas 1 dd`);
|
|
820
|
-
shellExec(`node bin deploy --build-manifest --sync --info-router --replicas 1 dd production`);
|
|
819
|
+
shellExec(`node bin deploy --kubeadm --build-manifest --sync --info-router --replicas 1 dd`);
|
|
820
|
+
shellExec(`node bin deploy --kubeadm --build-manifest --sync --info-router --replicas 1 dd production`);
|
|
821
821
|
break;
|
|
822
822
|
}
|
|
823
823
|
|
|
@@ -1000,6 +1000,8 @@ EOF`);
|
|
|
1000
1000
|
shellExec(`sudo chmod 700 ~/.ssh/`);
|
|
1001
1001
|
shellExec(`sudo chmod 600 ~/.ssh/authorized_keys`);
|
|
1002
1002
|
shellExec(`sudo chmod 644 ~/.ssh/known_hosts`);
|
|
1003
|
+
shellExec(`sudo chmod 600 ~/.ssh/id_rsa`);
|
|
1004
|
+
shellExec(`sudo chmod 600 /etc/ssh/ssh_host_ed25519_key`);
|
|
1003
1005
|
shellExec(`chown -R ${user}:${user} ~/.ssh`);
|
|
1004
1006
|
|
|
1005
1007
|
shellExec(`ufw allow ${port}/tcp`);
|
|
@@ -2218,7 +2220,7 @@ EOF`);
|
|
|
2218
2220
|
const args = [
|
|
2219
2221
|
`node bin dockerfile-image-build --path ${path}/backend/`,
|
|
2220
2222
|
`--image-name=${imageName} --image-path=${path}`,
|
|
2221
|
-
`--podman-save
|
|
2223
|
+
`--podman-save --${process.argv.includes('kubeadm') ? 'kubeadm' : 'kind'}-load --no-cache`,
|
|
2222
2224
|
];
|
|
2223
2225
|
shellExec(args.join(' '));
|
|
2224
2226
|
}
|
|
@@ -2230,7 +2232,7 @@ EOF`);
|
|
|
2230
2232
|
const args = [
|
|
2231
2233
|
`node bin dockerfile-image-build --path ${path}/frontend/`,
|
|
2232
2234
|
`--image-name=${imageName} --image-path=${path}`,
|
|
2233
|
-
`--podman-save
|
|
2235
|
+
`--podman-save --${process.argv.includes('kubeadm') ? 'kubeadm' : 'kind'}-load --no-cache`,
|
|
2234
2236
|
];
|
|
2235
2237
|
shellExec(args.join(' '));
|
|
2236
2238
|
}
|
|
@@ -2268,6 +2270,10 @@ EOF`);
|
|
|
2268
2270
|
}
|
|
2269
2271
|
|
|
2270
2272
|
case 'conda': {
|
|
2273
|
+
// set -e
|
|
2274
|
+
// ENV_NAME="${1:-cuda_env}"
|
|
2275
|
+
// eval "$(conda shell.bash hook)"
|
|
2276
|
+
// conda activate "${ENV_NAME}"
|
|
2271
2277
|
shellExec(
|
|
2272
2278
|
`export PATH="/root/miniconda3/bin:$PATH" && conda init && conda config --set auto_activate_base false`,
|
|
2273
2279
|
);
|
|
@@ -2279,7 +2285,10 @@ EOF`);
|
|
|
2279
2285
|
// https://medium.com/@martin.hodges/deploying-kafka-on-a-kind-kubernetes-cluster-for-development-and-testing-purposes-ed7adefe03cb
|
|
2280
2286
|
const imageName = `doughgle/kafka-kraft`;
|
|
2281
2287
|
shellExec(`docker pull ${imageName}`);
|
|
2282
|
-
|
|
2288
|
+
if (!process.argv.includes('kubeadm'))
|
|
2289
|
+
shellExec(
|
|
2290
|
+
`${process.argv.includes('kubeadm') ? `ctr -n k8s.io images import` : `kind load docker-image`} ${imageName}`,
|
|
2291
|
+
);
|
|
2283
2292
|
shellExec(`kubectl create namespace kafka`);
|
|
2284
2293
|
shellExec(`kubectl apply -f ./manifests/deployment/kafka/deployment.yaml`);
|
|
2285
2294
|
// kubectl logs kafka-0 -n kafka | grep STARTED
|
|
@@ -2294,6 +2303,108 @@ EOF`);
|
|
|
2294
2303
|
// kafka-console-consumer.sh --bootstrap-server kafka-svc:9092 --topic my-topic
|
|
2295
2304
|
break;
|
|
2296
2305
|
}
|
|
2306
|
+
|
|
2307
|
+
case 'nvidia-gpu-operator': {
|
|
2308
|
+
// https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html
|
|
2309
|
+
shellExec(`curl -s -L https://nvidia.github.io/libnvidia-container/stable/rpm/nvidia-container-toolkit.repo | \
|
|
2310
|
+
sudo tee /etc/yum.repos.d/nvidia-container-toolkit.repo`);
|
|
2311
|
+
|
|
2312
|
+
const NVIDIA_CONTAINER_TOOLKIT_VERSION = '1.17.8-1';
|
|
2313
|
+
|
|
2314
|
+
shellExec(`sudo dnf install -y \
|
|
2315
|
+
nvidia-container-toolkit-${NVIDIA_CONTAINER_TOOLKIT_VERSION} \
|
|
2316
|
+
nvidia-container-toolkit-base-${NVIDIA_CONTAINER_TOOLKIT_VERSION} \
|
|
2317
|
+
libnvidia-container-tools-${NVIDIA_CONTAINER_TOOLKIT_VERSION} \
|
|
2318
|
+
libnvidia-container1-${NVIDIA_CONTAINER_TOOLKIT_VERSION}`);
|
|
2319
|
+
|
|
2320
|
+
// https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/getting-started.html
|
|
2321
|
+
|
|
2322
|
+
shellExec(`kubectl create ns gpu-operator`);
|
|
2323
|
+
shellExec(`kubectl label --overwrite ns gpu-operator pod-security.kubernetes.io/enforce=privileged`);
|
|
2324
|
+
|
|
2325
|
+
shellExec(`helm repo add nvidia https://helm.ngc.nvidia.com/nvidia \
|
|
2326
|
+
&& helm repo update`);
|
|
2327
|
+
|
|
2328
|
+
// shellExec(`helm install --wait --generate-name \
|
|
2329
|
+
// -n gpu-operator --create-namespace \
|
|
2330
|
+
// nvidia/gpu-operator \
|
|
2331
|
+
// --version=v25.3.1 \
|
|
2332
|
+
// --set toolkit.version=v1.16.1-ubi8`);
|
|
2333
|
+
|
|
2334
|
+
shellExec(`helm install --wait --generate-name \
|
|
2335
|
+
-n gpu-operator --create-namespace \
|
|
2336
|
+
nvidia/gpu-operator \
|
|
2337
|
+
--version=v25.3.1 \
|
|
2338
|
+
--set driver.enabled=false \
|
|
2339
|
+
--set driver.repository=nvcr.io/nvidia \
|
|
2340
|
+
--set cdi.enabled=true \
|
|
2341
|
+
--set cdi.default=true \
|
|
2342
|
+
--set toolkit.env[0].name=CONTAINERD_CONFIG \
|
|
2343
|
+
--set toolkit.env[0].value=/etc/containerd/config.toml \
|
|
2344
|
+
--set toolkit.env[1].name=CONTAINERD_SOCKET \
|
|
2345
|
+
--set toolkit.env[1].value=/run/containerd/containerd.sock \
|
|
2346
|
+
--set toolkit.env[2].name=CONTAINERD_RUNTIME_CLASS \
|
|
2347
|
+
--set toolkit.env[2].value=nvidia \
|
|
2348
|
+
--set-string toolkit.env[3].name=CONTAINERD_SET_AS_DEFAULT \
|
|
2349
|
+
--set-string toolkit.env[3].value=true`);
|
|
2350
|
+
|
|
2351
|
+
// Check gpu drivers
|
|
2352
|
+
shellExec(
|
|
2353
|
+
`break;kubectl get nodes -o json | jq '.items[].metadata.labels | keys | any(startswith("feature.node.kubernetes.io"))'`,
|
|
2354
|
+
);
|
|
2355
|
+
break;
|
|
2356
|
+
}
|
|
2357
|
+
|
|
2358
|
+
case 'kubeflow-spark-operator': {
|
|
2359
|
+
// Use case:
|
|
2360
|
+
// Data Processing Pipelines: Used for ETL tasks where Spark can handle large data volumes efficiently.
|
|
2361
|
+
// Real-Time Analytics: Processing data from streaming sources (e.g., Kafka) for real-time analytics.
|
|
2362
|
+
// Machine Learning and Data Science: Training and deploying machine learning models at scale using Spark MLlib.
|
|
2363
|
+
|
|
2364
|
+
shellExec(`helm repo add spark-operator https://kubeflow.github.io/spark-operator`);
|
|
2365
|
+
shellExec(`helm install spark-operator spark-operator/spark-operator \
|
|
2366
|
+
--namespace spark-operator \
|
|
2367
|
+
--create-namespace \
|
|
2368
|
+
--wait`);
|
|
2369
|
+
|
|
2370
|
+
const image = `spark:3.5.5`;
|
|
2371
|
+
shellExec(`sudo docker pull ${image}`);
|
|
2372
|
+
if (!process.argv.includes('kubeadm'))
|
|
2373
|
+
shellExec(
|
|
2374
|
+
`sudo ${
|
|
2375
|
+
process.argv.includes('kubeadm') ? `ctr -n k8s.io images import` : `kind load docker-image`
|
|
2376
|
+
} ${image}`,
|
|
2377
|
+
);
|
|
2378
|
+
shellExec(`kubectl apply -f ./manifests/deployment/spark/spark-pi-py.yaml`);
|
|
2379
|
+
|
|
2380
|
+
// Check the status of the Spark job:
|
|
2381
|
+
// kubectl get sparkapplications.sparkoperator.k8s.io -n default
|
|
2382
|
+
// kubectl get sparkapplication
|
|
2383
|
+
|
|
2384
|
+
// Check case log:
|
|
2385
|
+
// kubectl logs -f spark-pi-python-driver
|
|
2386
|
+
// kubectl logs -f spark-pi-python-driver | grep Pi
|
|
2387
|
+
// kubectl describe sparkapplication spark-gpu-test
|
|
2388
|
+
|
|
2389
|
+
// Uninstall:
|
|
2390
|
+
// kubectl delete sparkapplications.sparkoperator.k8s.io spark-pi-python -n default
|
|
2391
|
+
// helm delete spark-operator -n spark-operator
|
|
2392
|
+
|
|
2393
|
+
// Gpu plugins:
|
|
2394
|
+
// https://github.com/NVIDIA/spark-rapids
|
|
2395
|
+
// RAPIDS Accelerator
|
|
2396
|
+
break;
|
|
2397
|
+
}
|
|
2398
|
+
|
|
2399
|
+
case 'sbt': {
|
|
2400
|
+
// https://www.scala-sbt.org/1.x/docs/Installing-sbt-on-Linux.html
|
|
2401
|
+
|
|
2402
|
+
// sudo rm -f /etc/yum.repos.d/bintray-rpm.repo
|
|
2403
|
+
// curl -L https://www.scala-sbt.org/sbt-rpm.repo > sbt-rpm.repo
|
|
2404
|
+
// sudo mv sbt-rpm.repo /etc/yum.repos.d/
|
|
2405
|
+
// sudo yum install sbt
|
|
2406
|
+
break;
|
|
2407
|
+
}
|
|
2297
2408
|
}
|
|
2298
2409
|
} catch (error) {
|
|
2299
2410
|
logger.error(error, error.stack);
|
package/cli.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
## underpost ci/cd cli v2.8.
|
|
1
|
+
## underpost ci/cd cli v2.8.77
|
|
2
2
|
|
|
3
3
|
### Usage: `underpost [options] [command]`
|
|
4
4
|
```
|
|
@@ -10,7 +10,7 @@ Commands:
|
|
|
10
10
|
new <app-name> Create a new project
|
|
11
11
|
start [options] <deploy-id> [env] Start up server, build pipelines, or services
|
|
12
12
|
clone [options] <uri> Clone github repository
|
|
13
|
-
pull <path> <uri>
|
|
13
|
+
pull [options] <path> <uri> Pull github repository
|
|
14
14
|
cmt [options] <path> <commit-type> [module-tag] [message] Commit github repository
|
|
15
15
|
push [options] <path> <uri> Push github repository
|
|
16
16
|
env <deploy-id> [env] Set environment variables files and conf related to <deploy-id>
|
|
@@ -79,6 +79,7 @@ Arguments:
|
|
|
79
79
|
|
|
80
80
|
Options:
|
|
81
81
|
--bare Clone only .git files
|
|
82
|
+
-g8 Use g8 repo extension
|
|
82
83
|
-h, --help display help for command
|
|
83
84
|
|
|
84
85
|
```
|
|
@@ -95,6 +96,7 @@ Arguments:
|
|
|
95
96
|
uri e.g. username/repository
|
|
96
97
|
|
|
97
98
|
Options:
|
|
99
|
+
-g8 Use g8 repo extension
|
|
98
100
|
-h, --help display help for command
|
|
99
101
|
|
|
100
102
|
```
|
|
@@ -134,6 +136,7 @@ Arguments:
|
|
|
134
136
|
|
|
135
137
|
Options:
|
|
136
138
|
-f Force push overwriting repository
|
|
139
|
+
-g8 Use g8 repo extension
|
|
137
140
|
-h, --help display help for command
|
|
138
141
|
|
|
139
142
|
```
|
|
@@ -203,9 +206,11 @@ Options:
|
|
|
203
206
|
--valkey Init with valkey service
|
|
204
207
|
--contour Init with project contour base HTTPProxy and envoy
|
|
205
208
|
--cert-manager Init with letsencrypt-prod ClusterIssuer
|
|
209
|
+
--dedicated-gpu Init with dedicated gpu base resources env
|
|
206
210
|
--info Get all kinds objects deployed
|
|
207
211
|
--full Init with all statefulsets and services available
|
|
208
212
|
--ns-use <ns-name> Switches current context to namespace
|
|
213
|
+
--kubeadm Init with kubeadm controlplane management
|
|
209
214
|
--dev init with dev cluster
|
|
210
215
|
--list-pods Display list pods information
|
|
211
216
|
--info-capacity display current total machine capacity info
|
|
@@ -244,6 +249,7 @@ Options:
|
|
|
244
249
|
--disable-update-deployment Disable update deployments
|
|
245
250
|
--info-traffic get traffic conf form current resources
|
|
246
251
|
deployments
|
|
252
|
+
--kubeadm Enable kubeadm context
|
|
247
253
|
--rebuild-clients-bundle Inside container, rebuild clients bundle,
|
|
248
254
|
only static public or storage client files
|
|
249
255
|
-h, --help display help for command
|
|
@@ -282,6 +288,7 @@ Options:
|
|
|
282
288
|
--dockerfile-name [dockerfile-name] set Dockerfile name
|
|
283
289
|
--podman-save Export tar file from podman
|
|
284
290
|
--kind-load Import tar image to Kind cluster
|
|
291
|
+
--kubeadm-load Import tar image to Kubeadm cluster
|
|
285
292
|
--secrets Dockerfile env secrets
|
|
286
293
|
--secrets-path [secrets-path] Dockerfile custom path env secrets
|
|
287
294
|
--no-cache Build without using cache
|
package/docker-compose.yml
CHANGED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
apiVersion: sparkoperator.k8s.io/v1beta2
|
|
2
|
+
kind: SparkApplication
|
|
3
|
+
metadata:
|
|
4
|
+
name: spark-pi-python
|
|
5
|
+
namespace: default
|
|
6
|
+
spec:
|
|
7
|
+
type: Python
|
|
8
|
+
pythonVersion: '3'
|
|
9
|
+
mode: cluster
|
|
10
|
+
image: spark:3.5.5
|
|
11
|
+
imagePullPolicy: IfNotPresent
|
|
12
|
+
mainApplicationFile: local:///opt/spark/examples/src/main/python/pi.py
|
|
13
|
+
sparkVersion: 3.5.5
|
|
14
|
+
driver:
|
|
15
|
+
cores: 1
|
|
16
|
+
memory: 512m
|
|
17
|
+
serviceAccount: spark-operator-spark
|
|
18
|
+
executor:
|
|
19
|
+
instances: 1
|
|
20
|
+
cores: 1
|
|
21
|
+
memory: 512m
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
apiVersion: v1
|
|
2
|
+
data:
|
|
3
|
+
kubelet: |
|
|
4
|
+
apiVersion: kubelet.config.k8s.io/v1beta1
|
|
5
|
+
authentication:
|
|
6
|
+
anonymous:
|
|
7
|
+
enabled: false
|
|
8
|
+
webhook:
|
|
9
|
+
cacheTTL: 0s
|
|
10
|
+
enabled: true
|
|
11
|
+
x509:
|
|
12
|
+
clientCAFile: /etc/kubernetes/pki/ca.crt
|
|
13
|
+
authorization:
|
|
14
|
+
mode: Webhook
|
|
15
|
+
webhook:
|
|
16
|
+
cacheAuthorizedTTL: 0s
|
|
17
|
+
cacheUnauthorizedTTL: 0s
|
|
18
|
+
cgroupDriver: systemd
|
|
19
|
+
clusterDNS:
|
|
20
|
+
- 10.96.0.10
|
|
21
|
+
clusterDomain: cluster.local
|
|
22
|
+
containerRuntimeEndpoint: unix:///run/containerd/containerd.sock
|
|
23
|
+
cpuManagerReconcilePeriod: 0s
|
|
24
|
+
crashLoopBackOff: {}
|
|
25
|
+
evictionHard:
|
|
26
|
+
imagefs.available: "5%" # Adjusted for more tolerance
|
|
27
|
+
memory.available: "100Mi"
|
|
28
|
+
nodefs.available: "5%" # Adjusted for more tolerance
|
|
29
|
+
nodefs.inodesFree: "5%"
|
|
30
|
+
evictionPressureTransitionPeriod: 0s
|
|
31
|
+
fileCheckFrequency: 0s
|
|
32
|
+
healthzBindAddress: 127.0.0.1
|
|
33
|
+
healthzPort: 10248
|
|
34
|
+
httpCheckFrequency: 0s
|
|
35
|
+
imageMaximumGCAge: 0s
|
|
36
|
+
imageMinimumGCAge: 0s
|
|
37
|
+
kind: KubeletConfiguration
|
|
38
|
+
logging:
|
|
39
|
+
flushFrequency: 0
|
|
40
|
+
options:
|
|
41
|
+
json:
|
|
42
|
+
infoBufferSize: "0"
|
|
43
|
+
text:
|
|
44
|
+
infoBufferSize: "0"
|
|
45
|
+
verbosity: 0
|
|
46
|
+
memorySwap: {}
|
|
47
|
+
nodeStatusReportFrequency: 0s
|
|
48
|
+
nodeStatusUpdateFrequency: 0s
|
|
49
|
+
rotateCertificates: true
|
|
50
|
+
runtimeRequestTimeout: 0s
|
|
51
|
+
shutdownGracePeriod: 0s
|
|
52
|
+
shutdownGracePeriodCriticalPods: 0s
|
|
53
|
+
staticPodPath: /etc/kubernetes/manifests
|
|
54
|
+
streamingConnectionIdleTimeout: 0s
|
|
55
|
+
syncFrequency: 0s
|
|
56
|
+
volumeStatsAggPeriod: 0s
|
|
57
|
+
kind: ConfigMap
|
|
58
|
+
metadata:
|
|
59
|
+
annotations:
|
|
60
|
+
kubeadm.kubernetes.io/component-config.hash: sha256:26488e9fc7c5cb5fdda9996cda2e6651a9af5febce07ea02de11bd3ef3f49e9c
|
|
61
|
+
creationTimestamp: "2025-06-30T12:42:00Z"
|
|
62
|
+
name: kubelet-config
|
|
63
|
+
namespace: kube-system
|
|
64
|
+
resourceVersion: "204"
|
|
65
|
+
uid: a85321a8-f3e0-40fa-8e4e-9d33b8842e7a
|
package/package.json
CHANGED
package/src/cli/cluster.js
CHANGED
|
@@ -3,6 +3,7 @@ import { loggerFactory } from '../server/logger.js';
|
|
|
3
3
|
import { shellExec } from '../server/process.js';
|
|
4
4
|
import UnderpostDeploy from './deploy.js';
|
|
5
5
|
import UnderpostTest from './test.js';
|
|
6
|
+
import os from 'os';
|
|
6
7
|
|
|
7
8
|
const logger = loggerFactory(import.meta);
|
|
8
9
|
|
|
@@ -27,10 +28,12 @@ class UnderpostCluster {
|
|
|
27
28
|
infoCapacityPod: false,
|
|
28
29
|
istio: false,
|
|
29
30
|
pullImage: false,
|
|
31
|
+
dedicatedGpu: false,
|
|
32
|
+
kubeadm: false,
|
|
30
33
|
},
|
|
31
34
|
) {
|
|
32
35
|
// sudo dnf update
|
|
33
|
-
// 1) Install kind, kubeadm, docker, podman
|
|
36
|
+
// 1) Install kind, kubeadm, docker, podman, helm
|
|
34
37
|
// 2) Check kubectl, kubelet, containerd.io
|
|
35
38
|
// 3) Install Nvidia drivers from Rocky Linux docs
|
|
36
39
|
// 4) Install LXD with MAAS from Rocky Linux docs
|
|
@@ -38,7 +41,8 @@ class UnderpostCluster {
|
|
|
38
41
|
const npmRoot = getNpmRootPath();
|
|
39
42
|
const underpostRoot = options?.dev === true ? '.' : `${npmRoot}/underpost`;
|
|
40
43
|
if (options.infoCapacityPod === true) return logger.info('', UnderpostDeploy.API.resourcesFactory());
|
|
41
|
-
if (options.infoCapacity === true)
|
|
44
|
+
if (options.infoCapacity === true)
|
|
45
|
+
return logger.info('', UnderpostCluster.API.getResourcesCapacity(options.kubeadm));
|
|
42
46
|
if (options.reset === true) return await UnderpostCluster.API.reset();
|
|
43
47
|
if (options.listPods === true) return console.table(UnderpostDeploy.API.get(podName ?? undefined));
|
|
44
48
|
|
|
@@ -66,6 +70,7 @@ class UnderpostCluster {
|
|
|
66
70
|
shellExec(
|
|
67
71
|
`kubectl get pods --all-namespaces -o=jsonpath='{range .items[*]}{"\\n"}{.metadata.name}{":\\t"}{range .spec.containers[*]}{.image}{", "}{end}{end}'`,
|
|
68
72
|
);
|
|
73
|
+
shellExec(`sudo crictl images`);
|
|
69
74
|
console.log();
|
|
70
75
|
logger.info('contour -------------------------------------------------');
|
|
71
76
|
for (const _k of ['Cluster', 'HTTPProxy', 'ClusterIssuer', 'Certificate']) {
|
|
@@ -106,23 +111,44 @@ class UnderpostCluster {
|
|
|
106
111
|
// shellExec(
|
|
107
112
|
// `wget https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/custom-resources.yaml`,
|
|
108
113
|
// );
|
|
109
|
-
shellExec(`sudo kubectl apply -f
|
|
114
|
+
shellExec(`sudo kubectl apply -f ${underpostRoot}/manifests/kubeadm-calico-config.yaml`);
|
|
110
115
|
shellExec(`sudo systemctl restart containerd`);
|
|
116
|
+
const nodeName = os.hostname();
|
|
117
|
+
shellExec(`kubectl taint nodes ${nodeName} node-role.kubernetes.io/control-plane:NoSchedule-`);
|
|
111
118
|
} else {
|
|
112
119
|
shellExec(`sudo systemctl restart containerd`);
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
120
|
+
if (options.full === true || options.dedicatedGpu === true) {
|
|
121
|
+
// https://kubernetes.io/docs/tasks/manage-gpus/scheduling-gpus/
|
|
122
|
+
shellExec(`cd ${underpostRoot}/manifests && kind create cluster --config kind-config-cuda.yaml`);
|
|
123
|
+
} else {
|
|
124
|
+
shellExec(
|
|
125
|
+
`cd ${underpostRoot}/manifests && kind create cluster --config kind-config${
|
|
126
|
+
options?.dev === true ? '-dev' : ''
|
|
127
|
+
}.yaml`,
|
|
128
|
+
);
|
|
129
|
+
}
|
|
118
130
|
shellExec(`sudo chown $(id -u):$(id -g) $HOME/.kube/config**`);
|
|
119
131
|
}
|
|
120
132
|
} else logger.warn('Cluster already initialized');
|
|
121
133
|
|
|
134
|
+
// shellExec(`sudo kubectl apply -f ${underpostRoot}/manifests/kubelet-config.yaml`);
|
|
135
|
+
|
|
136
|
+
if (options.full === true || options.dedicatedGpu === true) {
|
|
137
|
+
shellExec(`node ${underpostRoot}/bin/deploy nvidia-gpu-operator`);
|
|
138
|
+
shellExec(
|
|
139
|
+
`node ${underpostRoot}/bin/deploy kubeflow-spark-operator${options.kubeadm === true ? ' kubeadm' : ''}`,
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
122
143
|
if (options.full === true || options.valkey === true) {
|
|
123
144
|
if (options.pullImage === true) {
|
|
124
145
|
shellExec(`docker pull valkey/valkey`);
|
|
125
|
-
|
|
146
|
+
if (!options.kubeadm)
|
|
147
|
+
shellExec(
|
|
148
|
+
`sudo ${
|
|
149
|
+
options.kubeadm === true ? `ctr -n k8s.io images import` : `kind load docker-image`
|
|
150
|
+
} valkey/valkey:latest`,
|
|
151
|
+
);
|
|
126
152
|
}
|
|
127
153
|
shellExec(`kubectl delete statefulset service-valkey`);
|
|
128
154
|
shellExec(`kubectl apply -k ${underpostRoot}/manifests/valkey`);
|
|
@@ -140,17 +166,27 @@ class UnderpostCluster {
|
|
|
140
166
|
if (options.full === true || options.postgresql === true) {
|
|
141
167
|
if (options.pullImage === true) {
|
|
142
168
|
shellExec(`docker pull postgres:latest`);
|
|
143
|
-
|
|
169
|
+
if (!options.kubeadm)
|
|
170
|
+
shellExec(
|
|
171
|
+
`sudo ${
|
|
172
|
+
options.kubeadm === true ? `ctr -n k8s.io images import` : `kind load docker-image`
|
|
173
|
+
} docker-image postgres:latest`,
|
|
174
|
+
);
|
|
144
175
|
}
|
|
145
176
|
shellExec(
|
|
146
177
|
`sudo kubectl create secret generic postgres-secret --from-file=password=/home/dd/engine/engine-private/postgresql-password`,
|
|
147
178
|
);
|
|
148
|
-
shellExec(`kubectl apply -k
|
|
179
|
+
shellExec(`kubectl apply -k ${underpostRoot}/manifests/postgresql`);
|
|
149
180
|
}
|
|
150
181
|
if (options.mongodb4 === true) {
|
|
151
182
|
if (options.pullImage === true) {
|
|
152
183
|
shellExec(`docker pull mongo:4.4`);
|
|
153
|
-
|
|
184
|
+
if (!options.kubeadm)
|
|
185
|
+
shellExec(
|
|
186
|
+
`sudo ${
|
|
187
|
+
options.kubeadm === true ? `ctr -n k8s.io images import` : `kind load docker-image`
|
|
188
|
+
} docker-image mongo:4.4`,
|
|
189
|
+
);
|
|
154
190
|
}
|
|
155
191
|
shellExec(`kubectl apply -k ${underpostRoot}/manifests/mongodb-4.4`);
|
|
156
192
|
|
|
@@ -342,10 +378,10 @@ class UnderpostCluster {
|
|
|
342
378
|
|
|
343
379
|
// Step 14: Remove the 'kind' Docker network.
|
|
344
380
|
// This cleans up any network bridges or configurations specifically created by Kind.
|
|
345
|
-
shellExec(`docker network rm kind`);
|
|
381
|
+
// shellExec(`docker network rm kind`);
|
|
346
382
|
},
|
|
347
383
|
|
|
348
|
-
getResourcesCapacity() {
|
|
384
|
+
getResourcesCapacity(kubeadm = false) {
|
|
349
385
|
const resources = {};
|
|
350
386
|
const info = false
|
|
351
387
|
? `Capacity:
|
|
@@ -362,10 +398,15 @@ Allocatable:
|
|
|
362
398
|
hugepages-2Mi: 0
|
|
363
399
|
memory: 11914720Ki
|
|
364
400
|
pods: `
|
|
365
|
-
: shellExec(
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
401
|
+
: shellExec(
|
|
402
|
+
`kubectl describe node ${
|
|
403
|
+
kubeadm === true ? os.hostname() : 'kind-worker'
|
|
404
|
+
} | grep -E '(Allocatable:|Capacity:)' -A 6`,
|
|
405
|
+
{
|
|
406
|
+
stdout: true,
|
|
407
|
+
silent: true,
|
|
408
|
+
},
|
|
409
|
+
);
|
|
369
410
|
info
|
|
370
411
|
.split('Allocatable:')[1]
|
|
371
412
|
.split('\n')
|
package/src/cli/deploy.js
CHANGED
|
@@ -21,13 +21,13 @@ const logger = loggerFactory(import.meta);
|
|
|
21
21
|
class UnderpostDeploy {
|
|
22
22
|
static NETWORK = {};
|
|
23
23
|
static API = {
|
|
24
|
-
sync(deployList, { versions, replicas }) {
|
|
24
|
+
sync(deployList, { versions, replicas, kubeadm = false }) {
|
|
25
25
|
const deployGroupId = 'dd.router';
|
|
26
26
|
fs.writeFileSync(`./engine-private/deploy/${deployGroupId}`, deployList, 'utf8');
|
|
27
27
|
const totalPods = deployList.split(',').length * versions.split(',').length * parseInt(replicas);
|
|
28
28
|
const limitFactor = 0.8;
|
|
29
29
|
const reserveFactor = 0.05;
|
|
30
|
-
const resources = UnderpostCluster.API.getResourcesCapacity();
|
|
30
|
+
const resources = UnderpostCluster.API.getResourcesCapacity(kubeadm);
|
|
31
31
|
const memory = parseInt(resources.memory.value / totalPods);
|
|
32
32
|
const cpu = parseInt(resources.cpu.value / totalPods);
|
|
33
33
|
UnderpostRootEnv.API.set(
|
|
@@ -269,6 +269,8 @@ kubectl get ippools -o yaml
|
|
|
269
269
|
kubectl get node <node-name> -o jsonpath='{.spec.podCIDR}'
|
|
270
270
|
kubectl patch ippool default-ipv4-ippool --type='json' -p='[{"op": "replace", "path": "/spec/cidr", "value": "10.244.0.0/16"}]'
|
|
271
271
|
kubectl patch ippool default-ipv4-ippool --type='json' -p='[{"op": "replace", "path": "/spec/cidr", "value": "192.168.0.0/24"}]'
|
|
272
|
+
sudo podman run --rm localhost/<image-name>:<image-version> <command>
|
|
273
|
+
kubectl get configmap kubelet-config -n kube-system -o yaml > kubelet-config.yaml
|
|
272
274
|
`);
|
|
273
275
|
if (deployList === 'dd' && fs.existsSync(`./engine-private/deploy/dd.router`))
|
|
274
276
|
deployList = fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8');
|
package/src/cli/image.js
CHANGED
|
@@ -23,13 +23,24 @@ class UnderpostImage {
|
|
|
23
23
|
dockerfileName: '',
|
|
24
24
|
podmanSave: false,
|
|
25
25
|
kindLoad: false,
|
|
26
|
+
kubeadmLoad: false,
|
|
26
27
|
secrets: false,
|
|
27
28
|
secretsPath: '',
|
|
28
29
|
noCache: false,
|
|
29
30
|
},
|
|
30
31
|
) {
|
|
31
|
-
const {
|
|
32
|
-
|
|
32
|
+
const {
|
|
33
|
+
path,
|
|
34
|
+
imageName,
|
|
35
|
+
imagePath,
|
|
36
|
+
dockerfileName,
|
|
37
|
+
podmanSave,
|
|
38
|
+
secrets,
|
|
39
|
+
secretsPath,
|
|
40
|
+
kindLoad,
|
|
41
|
+
noCache,
|
|
42
|
+
kubeadmLoad,
|
|
43
|
+
} = options;
|
|
33
44
|
const podManImg = `localhost/${imageName}`;
|
|
34
45
|
if (imagePath && typeof imagePath === 'string' && !fs.existsSync(imagePath))
|
|
35
46
|
fs.mkdirSync(imagePath, { recursive: true });
|
|
@@ -59,6 +70,7 @@ class UnderpostImage {
|
|
|
59
70
|
|
|
60
71
|
if (podmanSave === true) shellExec(`podman save -o ${tarFile} ${podManImg}`);
|
|
61
72
|
if (kindLoad === true) shellExec(`sudo kind load image-archive ${tarFile}`);
|
|
73
|
+
if (kubeadmLoad === true) shellExec(`sudo ctr -n k8s.io images import ${tarFile}`);
|
|
62
74
|
},
|
|
63
75
|
},
|
|
64
76
|
};
|
package/src/cli/index.js
CHANGED
|
@@ -34,6 +34,7 @@ program
|
|
|
34
34
|
.command('clone')
|
|
35
35
|
.argument(`<uri>`, 'e.g. username/repository')
|
|
36
36
|
.option('--bare', 'Clone only .git files')
|
|
37
|
+
.option('-g8', 'Use g8 repo extension')
|
|
37
38
|
.description('Clone github repository')
|
|
38
39
|
.action(Underpost.repo.clone);
|
|
39
40
|
|
|
@@ -42,6 +43,7 @@ program
|
|
|
42
43
|
.argument('<path>', 'Absolute or relative directory')
|
|
43
44
|
.argument(`<uri>`, 'e.g. username/repository')
|
|
44
45
|
.description('Pull github repository')
|
|
46
|
+
.option('-g8', 'Use g8 repo extension')
|
|
45
47
|
.action(Underpost.repo.pull);
|
|
46
48
|
|
|
47
49
|
program
|
|
@@ -61,6 +63,7 @@ program
|
|
|
61
63
|
.argument('<path>', 'Absolute or relative directory')
|
|
62
64
|
.argument(`<uri>`, 'e.g. username/repository')
|
|
63
65
|
.option('-f', 'Force push overwriting repository')
|
|
66
|
+
.option('-g8', 'Use g8 repo extension')
|
|
64
67
|
.description('Push github repository')
|
|
65
68
|
.action(Underpost.repo.push);
|
|
66
69
|
|
|
@@ -96,9 +99,11 @@ program
|
|
|
96
99
|
.option('--valkey', 'Init with valkey service')
|
|
97
100
|
.option('--contour', 'Init with project contour base HTTPProxy and envoy')
|
|
98
101
|
.option('--cert-manager', 'Init with letsencrypt-prod ClusterIssuer')
|
|
102
|
+
.option('--dedicated-gpu', 'Init with dedicated gpu base resources env')
|
|
99
103
|
.option('--info', 'Get all kinds objects deployed')
|
|
100
104
|
.option('--full', 'Init with all statefulsets and services available')
|
|
101
105
|
.option('--ns-use <ns-name>', 'Switches current context to namespace')
|
|
106
|
+
.option('--kubeadm', 'Init with kubeadm controlplane management')
|
|
102
107
|
.option('--dev', 'init with dev cluster')
|
|
103
108
|
.option('--list-pods', 'Display list pods information')
|
|
104
109
|
.option('--info-capacity', 'display current total machine capacity info')
|
|
@@ -124,6 +129,7 @@ program
|
|
|
124
129
|
.option('--traffic <traffic-versions>', 'Comma separated custom deployment traffic')
|
|
125
130
|
.option('--disable-update-deployment', 'Disable update deployments')
|
|
126
131
|
.option('--info-traffic', 'get traffic conf form current resources deployments')
|
|
132
|
+
.option('--kubeadm', 'Enable kubeadm context')
|
|
127
133
|
.option(
|
|
128
134
|
'--rebuild-clients-bundle',
|
|
129
135
|
'Inside container, rebuild clients bundle, only static public or storage client files',
|
|
@@ -154,6 +160,7 @@ program
|
|
|
154
160
|
.option('--dockerfile-name [dockerfile-name]', 'set Dockerfile name')
|
|
155
161
|
.option('--podman-save', 'Export tar file from podman')
|
|
156
162
|
.option('--kind-load', 'Import tar image to Kind cluster')
|
|
163
|
+
.option('--kubeadm-load', 'Import tar image to Kubeadm cluster')
|
|
157
164
|
.option('--secrets', 'Dockerfile env secrets')
|
|
158
165
|
.option('--secrets-path [secrets-path]', 'Dockerfile custom path env secrets')
|
|
159
166
|
.option('--no-cache', 'Build without using cache')
|
package/src/cli/repository.js
CHANGED
|
@@ -12,23 +12,25 @@ const logger = loggerFactory(import.meta);
|
|
|
12
12
|
|
|
13
13
|
class UnderpostRepository {
|
|
14
14
|
static API = {
|
|
15
|
-
clone(gitUri = 'underpostnet/pwa-microservices-template', options = { bare: false }) {
|
|
15
|
+
clone(gitUri = 'underpostnet/pwa-microservices-template', options = { bare: false, g8: false }) {
|
|
16
|
+
const gExtension = options.g8 === true ? '.g8' : '.git';
|
|
16
17
|
const repoName = gitUri.split('/').pop();
|
|
17
18
|
if (fs.existsSync(`./${repoName}`)) fs.removeSync(`./${repoName}`);
|
|
18
19
|
shellExec(
|
|
19
20
|
`git clone ${options?.bare === true ? ` --bare ` : ''}https://${
|
|
20
21
|
process.env.GITHUB_TOKEN ? `${process.env.GITHUB_TOKEN}@` : ''
|
|
21
|
-
}github.com/${gitUri}
|
|
22
|
+
}github.com/${gitUri}${gExtension}`,
|
|
22
23
|
{
|
|
23
24
|
disableLog: true,
|
|
24
25
|
},
|
|
25
26
|
);
|
|
26
27
|
},
|
|
27
|
-
pull(repoPath = './', gitUri = 'underpostnet/pwa-microservices-template') {
|
|
28
|
+
pull(repoPath = './', gitUri = 'underpostnet/pwa-microservices-template', options = { g8: false }) {
|
|
29
|
+
const gExtension = options.g8 === true ? '.g8' : '.git';
|
|
28
30
|
shellExec(
|
|
29
31
|
`cd ${repoPath} && git pull https://${
|
|
30
32
|
process.env.GITHUB_TOKEN ? `${process.env.GITHUB_TOKEN}@` : ''
|
|
31
|
-
}github.com/${gitUri}
|
|
33
|
+
}github.com/${gitUri}${gExtension}`,
|
|
32
34
|
{
|
|
33
35
|
disableLog: true,
|
|
34
36
|
},
|
|
@@ -57,9 +59,10 @@ class UnderpostRepository {
|
|
|
57
59
|
shellExec(`cd ${repoPath} && git commit ${options?.empty ? `--allow-empty ` : ''}-m "${_message}"`);
|
|
58
60
|
},
|
|
59
61
|
|
|
60
|
-
push(repoPath = './', gitUri = 'underpostnet/pwa-microservices-template', options = { f: false }) {
|
|
62
|
+
push(repoPath = './', gitUri = 'underpostnet/pwa-microservices-template', options = { f: false, g8: false }) {
|
|
63
|
+
const gExtension = options.g8 === true ? '.g8' : '.git';
|
|
61
64
|
shellExec(
|
|
62
|
-
`cd ${repoPath} && git push https://${process.env.GITHUB_TOKEN}@github.com/${gitUri}
|
|
65
|
+
`cd ${repoPath} && git push https://${process.env.GITHUB_TOKEN}@github.com/${gitUri}${gExtension}${
|
|
63
66
|
options?.f === true ? ' --force' : ''
|
|
64
67
|
}`,
|
|
65
68
|
{
|
package/src/index.js
CHANGED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# This section includes base Calico installation configuration.
|
|
2
|
-
# For more information, see: https://projectcalico.docs.tigera.io/master/reference/installation/api#operator.tigera.io/v1.Installation
|
|
3
|
-
apiVersion: operator.tigera.io/v1
|
|
4
|
-
kind: Installation
|
|
5
|
-
metadata:
|
|
6
|
-
name: default
|
|
7
|
-
spec:
|
|
8
|
-
# Configures Calico networking.
|
|
9
|
-
calicoNetwork:
|
|
10
|
-
# Note: The ipPools section cannot be modified post-install.
|
|
11
|
-
ipPools:
|
|
12
|
-
- blockSize: 26
|
|
13
|
-
cidr: 192.168.0.0/16
|
|
14
|
-
encapsulation: VXLANCrossSubnet
|
|
15
|
-
natOutgoing: Enabled
|
|
16
|
-
nodeSelector: all()
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
# This section configures the Calico API server.
|
|
20
|
-
# For more information, see: https://projectcalico.docs.tigera.io/master/reference/installation/api#operator.tigera.io/v1.APIServer
|
|
21
|
-
apiVersion: operator.tigera.io/v1
|
|
22
|
-
kind: APIServer
|
|
23
|
-
metadata:
|
|
24
|
-
name: default
|
|
25
|
-
spec: {}
|