Monthly Archives: January 2026

Cloud-Init file to create jumphost

ตัวอย่าง file cloud-init สำหรับสร้าง jumphost โดยใช้ rocky linux os

file นี้จะทำการสร้าง user nutanix ติดตั้ง docker, kubectl และ code server เพื่อให้สามารถใช้ shell ผ่าน vscode

Shell
#cloud-config
ssh_pwauth: true
users:
- name: nutanix
passwd: nutanix/4u
groups: users,wheel
shell: /bin/bash
lock-passwd: false
sudo: ['ALL=(ALL) NOPASSWD:ALL']
chpasswd:
list: |
nutanix:nutanix/4u
root:nutanix/4u
expire: False
runcmd:
- echo "Configuring SSH..."
# Ensure PasswordAuthentication is enabled
- sed -i '/^PasswordAuthentication/d' /etc/ssh/sshd_config # Delete existing line
- echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config # Add new line
# Ensure PermitRootLogin is set to yes
- sed -i '/^PermitRootLogin/d' /etc/ssh/sshd_config # Delete existing line
- echo "PermitRootLogin yes" >> /etc/ssh/sshd_config # Add new line
# Restart SSH Service
- systemctl restart sshd
- echo "SSH configuration updated and service restarted."
- '[ ! -f "/etc/yum.repos.d/nutanix_rocky9.repo" ] || mv -f /etc/yum.repos.d/nutanix_rocky9.repo /etc/yum.repos.d/nutanix_rocky9.repo.disabled'
- dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo
- dnf -y install git docker-ce docker-ce-cli containerd.io
- systemctl --now enable docker
- usermod -aG docker nutanix
- 'curl -Lo /usr/local/bin/kubectl https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl'
- chmod +x /usr/local/bin/kubectl
- 'curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash'
- 'su - nutanix -c "curl -fsSL https://raw.githubusercontent.com/pkhamdee/nkp-tools/main/install-tools.sh | bash"'
- eject

สำหรับ https://raw.githubusercontent.com/pkhamdee/nkp-tools/main/install-tools.sh จะเป็นการ deploy code server เพื่อใช้ linux terminal และจัดการไฟล์ผ่านทาง vscode ได้

Service Mesh with ISTIO

เพื่อที่จะใช้งาน istio ใน Nutanix Kubernetes Platform จะต้องทำการ enable service ที่เกี่ยวข้องคือ prometheus monitoring ใน menu application

จากนั้นทำการ enable istio ตามด้วย jaeger และ kiali

สำหรับ kiali จะต้อง copy configuration เพิ่มเติมโดยเข้าไปที่ view detail

และ copy ส่วนที่เป็น configuration ที่ menu overview ดังรูป

ในขั้นตอน enable ให้ใส่ configuration ก่อนที่จะ enable ดังรูป

หลังจาก enable เสร็จแล้วให้รอจนกว่า service จะ install เรียบร้อย ตรวจสอบได้จาก cli ตามตัวอย่าง

[nutanix@harbor ~]$ kubectl get pod -A | grep istio
istio-helm-gateway-ns istio-helm-ingressgateway-79df9868c8-5vkzb 1/1 Running 0 102m
istio-helm-gateway-ns istio-helm-ingressgateway-79df9868c8-6shfm 1/1 Running 0 102m
istio-helm-system istiod-istio-helm-545d9895f9-l56hv 1/1 Running 0 102m
istio-helm-system istiod-istio-helm-545d9895f9-p9bzq 1/1 Running 0 102m
istio-system jaeger-jaeger-operator-759ffd786-vf7wc 1/1 Running 0 104m
istio-system jaeger-jaeger-operator-jaeger-6cb7cfb9f-l4xph 1/1 Running 0 104m
istio-system kiali-kiali-operator-c6649cd8f-t7k98 1/1 Running 0 102m
kommander-default-workspace istio-helm-pre-install-kt59f 0/1 Completed 0 105m
kube-system istio-cni-node-cwff7 1/1 Running 0 103m
kube-system istio-cni-node-fhnz9 1/1 Running 0 103m
kube-system istio-cni-node-h8szk 1/1 Running 0 103m
kube-system istio-cni-node-s2qf4 1/1 Running 0 103m

เนื่องจาก istio และ jaeger อยู่ใน workspace ที่แตกต่างกัน จะต้องมีการ update configmap เพิ่มเติม โดยใช้ cli

kubectl edit cm istio-istio-helm -n istio-helm-system

เพิ่มส่วนของ tracing ตามตัวอย่าง

YAML
apiVersion: v1
kind: ConfigMap
data:
mesh: |-
enableTracing: true
defaultConfig:
discoveryAddress: istiod-istio-helm.istio-helm-system.svc:15012
# Tracing belongs here for global configuration
tracing:
sampling: 100.0
zipkin:
address: jaeger-jaeger-operator-jaeger-collector.istio-system.svc.cluster.local:9411
defaultProviders:
metrics:
- prometheus
enablePrometheusMerge: true
rootNamespace: istio-helm-system
trustDomain: cluster.local
# ... rest of metadata

ทดสอบใช้งาน istio ในแบบ sidecare auto injection จะต้องทำการ label name space ด้วย istio.io/rev=istio-helm

ทำการสร้าง project ใน nkp โดยกรอกข้อมูลและต้องกรอกข้อมูล namespace labels จากนั้นเลือก cluster ตามตัวอย่าง

เมื่อสร้างเสร็จแล้ว เข้าไป Continuous Deployment (CD) และกดปุ่ม Add GitOps Source

กรอกข้อมูลตามตัวอย่าง และกรอกข้อมูล Repository URL เป็น https://github.com/pkhamdee/sockshop จากนั้นกด Save

จากนั้น nkp จะทำการ deploy application ลงใน namespace demo (ชื่อตรงกับ project) โดย FluxCD ซึ่งเป็น service ที่ nkp ใช้สำหรับการทำ GitOps จะ download yaml file ตาม url ที่กำหนดและ deploy application ให้อัตโนมัติ

สามารถตรวจสอบสถานะการ deploy ได้จาก cli

[nutanix@harbor ~]$ kubectl get pod -n demo
NAME READY STATUS RESTARTS AGE
carts-88b4ddf98-p5gqh 2/2 Running 0 5m39s
carts-db-7d6d697d94-5cvxk 2/2 Running 0 5m39s
catalogue-84b5874db7-rtxkf 2/2 Running 0 5m39s
catalogue-db-64d88d46ff-nkrvb 2/2 Running 0 5m39s
front-end-d87486986-8n6pc 2/2 Running 0 5m39s
orders-8587749646-8m9wb 2/2 Running 0 5m39s
orders-db-8458b5ddb4-xtv5l 2/2 Running 0 5m38s
payment-6b49f65444-4hq97 2/2 Running 0 5m38s
queue-master-686b7bf644-fw2qq 2/2 Running 0 5m38s
rabbitmq-6d679fd595-sqhs5 3/3 Running 0 5m38s
session-db-6cfcf8985d-9hph4 2/2 Running 0 5m38s
shipping-5b674b9d94-42n48 2/2 Running 0 5m37s
user-57c89fbbf4-nzt4d 2/2 Running 0 5m37s
user-db-5c748bc594-mphsx 2/2 Running 0 5m37s

ตรวจสอบว่า envoy sidecar ทำงานปกติ ด้วย kubectl cli โดยจะต้องมี log แสดงว่า “Envoy proxy is ready”

[nutanix@harbor ~]$ kubectl logs carts-88b4ddf98-p5gqh -c istio-proxy -n demo
2026-01-30T14:08:29.823282Z info FLAG: --concurrency="0"
2026-01-30T14:08:29.823327Z info FLAG: --domain="demo.svc.cluster.local"
2026-01-30T14:08:29.823332Z info FLAG: --help="false"
2026-01-30T14:08:29.823335Z info FLAG: --log_as_json="false"
2026-01-30T14:08:29.823337Z info FLAG: --log_caller=""
2026-01-30T14:08:29.823339Z info FLAG: --log_output_level="default:info"
2026-01-30T14:08:29.823341Z info FLAG: --log_rotate=""
2026-01-30T14:08:29.823344Z info FLAG: --log_rotate_max_age="30"
2026-01-30T14:08:29.823346Z info FLAG: --log_rotate_max_backups="1000"
2026-01-30T14:08:29.823348Z info FLAG: --log_rotate_max_size="104857600"
2026-01-30T14:08:29.823350Z info FLAG: --log_stacktrace_level="default:none"
2026-01-30T14:08:29.823356Z info FLAG: --log_target="[stdout]"
2026-01-30T14:08:29.823358Z info FLAG: --meshConfig="./etc/istio/config/mesh"
2026-01-30T14:08:29.823361Z info FLAG: --outlierLogPath=""
2026-01-30T14:08:29.823363Z info FLAG: --profiling="true"
2026-01-30T14:08:29.823365Z info FLAG: --proxyComponentLogLevel="misc:error"
2026-01-30T14:08:29.823368Z info FLAG: --proxyLogLevel="warning"
2026-01-30T14:08:29.823370Z info FLAG: --serviceCluster="istio-proxy"
2026-01-30T14:08:29.823372Z info FLAG: --stsPort="0"
2026-01-30T14:08:29.823375Z info FLAG: --templateFile=""
2026-01-30T14:08:29.823378Z info FLAG: --tokenManagerPlugin=""
2026-01-30T14:08:29.823387Z info FLAG: --vklog="0"
2026-01-30T14:08:29.823392Z info Version 1.23.6-6a112a28410654328342c68f82da48920e34f062-Clean
2026-01-30T14:08:29.823398Z info Set max file descriptors (ulimit -n) to: 1048576
2026-01-30T14:08:29.823719Z info Proxy role ips=[192.168.2.124] type=sidecar id=carts-88b4ddf98-p5gqh.demo domain=demo.svc.cluster.local
2026-01-30T14:08:29.823783Z info Apply proxy config from env {"discoveryAddress":"istiod-istio-helm.istio-helm-system.svc:15012","tracing":{"zipkin":{"address":"jaeger-jaeger-operator-jaeger-collector.istio-system.svc.cluster.local:9411"},"sampling":100}}
2026-01-30T14:08:29.825955Z info cpu limit detected as 2, setting concurrency
2026-01-30T14:08:29.827354Z info Effective config: binaryPath: /usr/local/bin/envoy
concurrency: 2
configPath: ./etc/istio/proxy
controlPlaneAuthPolicy: MUTUAL_TLS
discoveryAddress: istiod-istio-helm.istio-helm-system.svc:15012
drainDuration: 45s
proxyAdminPort: 15000
serviceCluster: istio-proxy
statNameLength: 189
statusPort: 15020
terminationDrainDuration: 5s
tracing:
sampling: 100
zipkin:
address: jaeger-jaeger-operator-jaeger-collector.istio-system.svc.cluster.local:9411
2026-01-30T14:08:29.827376Z info JWT policy is third-party-jwt
2026-01-30T14:08:29.827380Z info using credential fetcher of JWT type in cluster.local trust domain
2026-01-30T14:08:30.028797Z info Opening status port 15020
2026-01-30T14:08:30.028831Z info Starting default Istio SDS Server
2026-01-30T14:08:30.028850Z info CA Endpoint istiod-istio-helm.istio-helm-system.svc:15012, provider Citadel
2026-01-30T14:08:30.028879Z info Using CA istiod-istio-helm.istio-helm-system.svc:15012 cert with certs: var/run/secrets/istio/root-cert.pem
2026-01-30T14:08:30.029620Z info xdsproxy Initializing with upstream address "istiod-istio-helm.istio-helm-system.svc:15012" and cluster "Kubernetes"
2026-01-30T14:08:30.031212Z info Pilot SAN: [istiod-istio-helm.istio-helm-system.svc]
2026-01-30T14:08:30.033350Z info sds Starting SDS grpc server
2026-01-30T14:08:30.033374Z info sds Starting SDS server for workload certificates, will listen on "var/run/secrets/workload-spiffe-uds/socket"
2026-01-30T14:08:30.033503Z info starting Http service at 127.0.0.1:15004
2026-01-30T14:08:30.035641Z info Starting proxy agent
2026-01-30T14:08:30.035691Z info Envoy command: [-c etc/istio/proxy/envoy-rev.json --drain-time-s 45 --drain-strategy immediate --local-address-ip-version v4 --file-flush-interval-msec 1000 --disable-hot-restart --allow-unknown-static-fields -l warning --component-log-level misc:error --concurrency 2]
2026-01-30T14:08:30.112678Z warning envoy main external/envoy/source/server/server.cc:936 There is no configured limit to the number of allowed active downstream connections. Configure a limit in `envoy.resource_monitors.downstream_connections` resource monitor. thread=14
2026-01-30T14:08:30.114850Z warning envoy main external/envoy/source/server/server.cc:843 Usage of the deprecated runtime key overload.global_downstream_max_connections, consider switching to `envoy.resource_monitors.downstream_connections` instead.This runtime key will be removed in future. thread=14
2026-01-30T14:08:30.123541Z info xdsproxy connected to delta upstream XDS server: istiod-istio-helm.istio-helm-system.svc:15012 id=1
2026-01-30T14:08:30.156633Z info cache generated new workload certificate resourceName=default latency=126.712884ms ttl=23h59m59.843374146s
2026-01-30T14:08:30.156685Z info cache Root cert has changed, start rotating root cert
2026-01-30T14:08:30.156825Z info cache returned workload trust anchor from cache ttl=23h59m59.843176367s
2026-01-30T14:08:30.192919Z info ads ADS: new connection for node:1
2026-01-30T14:08:30.193043Z info cache returned workload certificate from cache ttl=23h59m59.806958673s
2026-01-30T14:08:30.193482Z info ads ADS: new connection for node:2
2026-01-30T14:08:30.193672Z info cache returned workload trust anchor from cache ttl=23h59m59.806329146s
2026-01-30T14:08:31.182561Z info Readiness succeeded in 1.360041593s
2026-01-30T14:08:31.183121Z info Envoy proxy is ready

เข้าใช้งาน application ผ่านทาง load balancer ip โดยหา load balancer ip ได้จาก cli

[nutanix@harbor ~]$ kubectl get svc front-end -n demo
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
front-end LoadBalancer 10.108.248.153 10.38.37.21 80:32763/TCP 9m19s

สามารถ monitor service ได้จาก kiali โดยไปที่ cluster แล้วเลือกเปิด kiali ตามภาพ

เลือก Traffic Graph และ namespace เป็น demo

หรือสามารถดู​ service tracing จาก Jaeger โดยเข้าจากหน้า cluster หลังจากเข้ามาที่หน้าจอหลัก เลือก service ที่ต้องการ

กดที่เหตุการที่สนใจ jaeger จะแสดงรายละเอียดของ process ดังรูปภาพ

Rook Ceph cluster

การใช้งาน rook ceph cluster ใน Nutanix Kubernetes Platform เพื่อให้บริการ s3 storage สำหรับ application โดย rook ceph ได้ถูกติดตั้งใน mode high availability มาให้ซึ่งต้องมีจำนวน worker node อย่างน้อย 3 worker node เพื่อให้ rook ceph cluster สามารถทำงานได้ การเปิดใช้งานให้เข้าไปที่ menu application และเลือก enable Rook Ceph และ Rook Ceph Cluster ตามลำดับ

ตรวจสอบว่า Rook Ceph ได้ติดตั้งเรียบร้อยแล้วจาก cli โดยเลือก namespace ตาม namespace ของ kubernetes cluster ที่เราติดตั้ง

[nutanix@harbor ~]$ kubectl get deployment -n kommander-default-workspace
NAME READY UP-TO-DATE AVAILABLE AGE
ceph-cosi-driver 1/1 1 1 4m29s
gatekeeper-audit 1/1 1 1 27h
gatekeeper-controller-manager 2/2 2 2 27h
kommander-default-workspace-reloader-reloader 1/1 1 1 27h
kommander-traefik 2/2 2 2 27h
kube-oidc-proxy 1/1 1 1 27h
rook-ceph-crashcollector-dev2-md-0-rm6kd-f4xbb-8bgsj 1/1 1 1 2m56s
rook-ceph-crashcollector-dev2-md-0-rm6kd-f4xbb-h9zqd 1/1 1 1 2m39s
rook-ceph-crashcollector-dev2-md-0-rm6kd-f4xbb-hrl4t 1/1 1 1 2m59s
rook-ceph-exporter-dev2-md-0-rm6kd-f4xbb-8bgsj 1/1 1 1 2m56s
rook-ceph-exporter-dev2-md-0-rm6kd-f4xbb-h9zqd 1/1 1 1 2m39s
rook-ceph-exporter-dev2-md-0-rm6kd-f4xbb-hrl4t 1/1 1 1 2m59s
rook-ceph-mgr-a 1/1 1 1 2m56s
rook-ceph-mgr-b 1/1 1 1 2m56s
rook-ceph-mon-a 1/1 1 1 4m53s
rook-ceph-mon-b 1/1 1 1 4m17s
rook-ceph-mon-c 1/1 1 1 3m39s
rook-ceph-operator 1/1 1 1 35m
rook-ceph-osd-0 1/1 1 1 117s
rook-ceph-osd-1 1/1 1 1 115s
rook-ceph-osd-2 1/1 1 1 116s
rook-ceph-osd-3 1/1 1 1 90s
rook-ceph-tools 1/1 1 1 5m29s
traefik-forward-auth 1/1 1 1 27h

เปิดหน้าจอ rook ceph clusterโดยเลือกจาก cluster

ใช้ default user คือ admin และใช้ cli เพื่อแสดงค่า default password

[nutanix@harbor ~]$ kubectl -n kommander-default-workspace get secret rook-ceph-dashboard-password -ojsonpath='{.data.password}' | base64 -d
6-$9>^PZj1^E!-*XKCdw

เมื่อ login เข้ามาแล้วจะได้หน้าจอดังนี้

เข้าไปที่เมนู Object และสร้าง user ใหม่

จากนั้นเลือก Bucket และ create new bucket

เข้าไปที่ Users อีกครั้งเพื่อ copy secret key และ access key สำหรับใช้ในการใช้งาน bucket ที่สร้างขึ้น

เลือก user และที่ Key section แล้วเลือกที่ username

กดปุ่ม show ก็จะแสดง username , Access Key และ Secret key สำหรับใช้ในการ access bucket

Create kubernetes work cluster from NKP CLI

นอกจากจะ create kubernetes ผ่านทาง GUI แล้วเรายังสามารถสร้าง kuberntes จาก nkp cli ได้ และข้อดีของการใช้ cli จะทำให้เราสามารถเลือก image สำหรับ worker node และ master node ที่ไม่อยู่ใน release ที่ NKP version provide ให้ เช่น nkp 2.17.0 จะมาพร้อมกับ kubernetes version 1.34.1 แต่ถ้าเราจะสร้าง kubernetes version 1.29.6 ก็จะไม่สามารถทำได้เนื่องจาก GUI ไม่มี drop down ให้เลือก ซึ่งกรณีนี้ต้องใช้ CLI ในการสร้าง

ก่อนที่จะใช้ CLI ต้องทำการ upload VM Image สำหรับ kuberntes ก่อน โดยตัวอย่างนี้ เรา download จาก Nutanix portal และได้ upload เข้าไปใน Prism Central

ใช้ CLI เพื่อสร้างไฟล์ metadata (yaml) สำหรับ create kubernetes cluster

Shell
nkp create cluster nutanix --cluster-name dev1 \
--namespace kommander-default-workspace \
--endpoint https://10.38.37.7:9440 \
--control-plane-prism-element-cluster PHX-POC265 \
--control-plane-subnets primary-PHX-POC265 \
--control-plane-replicas 1 \
--control-plane-endpoint-ip 10.38.37.14 \
--control-plane-vm-image nkp-rocky-9.4-release-1.29.6-20250609212843.qcow2 \
--worker-subnets primary-PHX-POC265 \
--worker-replicas=3 \
--worker-vm-image nkp-rocky-9.4-release-1.29.6-20250609212843.qcow2 \
--worker-prism-element-cluster PHX-POC265 \
--csi-storage-container default \
--kubernetes-service-load-balancer-ip-range 10.38.37.15-10.38.37.17 \
--registry-mirror-url https://10.38.37.51/nkp2120 \
--registry-mirror-username admin \
--registry-mirror-password Harbor12345 \
--registry-mirror-cacert /home/nutanix/harbor/certs/harbor.local.crt \
--ssh-public-key-file /home/nutanix/id_ed25519.pub \
--ssh-username nutanix \
--airgapped \
--insecure \
--verbose 5 \
--timeout 0 \
--dry-run \
--skip-preflight-checks=NutanixVMImageKubernetesVersion \
--output=yaml > dev1-cluster.yaml

ค่า parameter จะแตกต่างกันไปขึ้นอยู่กับ environment โดยตัวอย่างนี้ได้ทำการติดตั้ง harbor เป็น container registry สำหรับใช้ภายใน เนื่องจาก environment ไม่สามารถเชื่อต่อ internet ได้ ขั้นตอนการเตรียม harbor และ package bundle สามารถดูได้จากบทความก่อนหน้า

ทำการเปิดไฟล์ metadata ที่สร้างขึ้นและแก้ไข version ของ kubernetes ให้ตรงกับ version ของ vm image

สร้าง kubernetes cluster ด้วย cli

[nutanix@harbor ~]$ kubectl apply -f dev1-cluster.yaml
secret/dev1-pc-credentials created
secret/dev1-pc-credentials-for-csi created
secret/dev1-image-registry-mirror-credentials created
Warning: Cluster has skipped preflight check "NutanixVMImageKubernetesVersion"
cluster.cluster.x-k8s.io/dev1 created

ตรวจสอบสถานะการสร้าง cluster จาก GUI จะพบว่ามีการสร้าง kubernetes ตามที่ระบุใน spec ของ yaml file

Kubernetes node auto scaler

Nutanix Kubernetes Platform (NKP) สามารถกำหนดให้ Kubernetes worker node ทำการ scale ตัวเองโดยการเพิ่มจำนวน worker ได้อัตโนมัติเมื่อพบว่า cpu หรือ memory ไม่เพียงพอสำหรับการ start workload โดยสามารถเข้าไปที่ kubernetes cluster เลือก node pool และ edit worker ตามรูป

ตัวอย่างนี้กำหนด minimum ไว้ 3 node และ scale เพิ่มเป็น 5 node ถ้า resource ไม่เพียงพอสำหรับการ deploy workload ใหม่ ใน version ปัจจุบันยังเป็น autoscaling ตาม schedules ถ้า resource ไม่เพียงพอ ถ้าต้องการ Event driven autoscaling เช่น เมื่อ transaction เกิดค่าที่กำหนด โดยใช้ metric ที่ได้จาก prometheus ทำการ Trigger ให้ KEDA ทำการ scale POD ซึ่งเมื่อ resource ไม่เพียงพอ Node AutoScaler ก็จะทำงาน

หลังจาก set ค่า autoscaling แล้วตรวจสอบได้ด้วย kubectl cli

[nutanix@harbor ~]$ kubectl get cm cluster-autoscaler-status -n kube-system -o yaml
apiVersion: v1
data:
status: |
time: 2026-01-30 06:46:25.136551666 +0000 UTC
autoscalerStatus: Running
clusterWide:
health:
status: Healthy
nodeCounts:
registered:
total: 4
ready: 4
notStarted: 0
longUnregistered: 0
unregistered: 0
lastProbeTime: "2026-01-30T06:46:25.136551666Z"
lastTransitionTime: "2026-01-30T01:45:13.531234277Z"
scaleUp:
status: NoActivity
lastProbeTime: "2026-01-30T06:46:25.136551666Z"
lastTransitionTime: "2026-01-30T01:45:13.531234277Z"
scaleDown:
status: NoCandidates
lastProbeTime: "2026-01-30T06:46:25.136551666Z"
lastTransitionTime: "2026-01-30T01:45:13.531234277Z"
nodeGroups:
- name: MachineDeployment/kommander-default-workspace/dev2-md-0-rm6kd
health:
status: Healthy
nodeCounts:
registered:
total: 3
ready: 3
notStarted: 0
longUnregistered: 0
unregistered: 0
cloudProviderTarget: 3
minSize: 3
maxSize: 5
lastProbeTime: "2026-01-30T06:46:25.136551666Z"
lastTransitionTime: "2026-01-30T01:45:13.531234277Z"
scaleUp:
status: NoActivity
lastProbeTime: "2026-01-30T06:46:25.136551666Z"
lastTransitionTime: "2026-01-30T01:45:13.531234277Z"
scaleDown:
status: NoCandidates
lastProbeTime: "2026-01-30T06:46:25.136551666Z"
lastTransitionTime: "2026-01-30T01:45:13.531234277Z"
kind: ConfigMap
metadata:
annotations:
cluster-autoscaler.kubernetes.io/last-updated: 2026-01-30 06:46:25.136551666 +0000
UTC
creationTimestamp: "2026-01-30T01:40:46Z"
name: cluster-autoscaler-status
namespace: kube-system
resourceVersion: "882305"
uid: 06b9b1e0-de1d-477b-b691-cbc172803f93

เพื่อทดสอบต้อง deploy workload ที่จอง resource มากกว่าที่ kubernetes จะสามารถจัดสรรให้ได้ ตามตัวอย่าง

[nutanix@harbor ~]$ more stress-test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: resource-test
spec:
replicas: 10
selector:
matchLabels:
app: resource-test
template:
metadata:
labels:
app: resource-test
spec:
containers:
- name: stress-test
image: polinux/stress
resources:
requests:
memory: "1Gi"
cpu: "5000m"
limits:
memory: "2Gi"
cpu: "10000m"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "512M", "--timeout", "600s"]

ทำการ deploy ด้วย kubectl cli

[nutanix@harbor ~]$ kubectl apply -f stress-test.yaml

ตรวจสอบว่า workload สามารถ running ได้ แต่ไม่สามารถ running ได้ทั้งหมดเนื่องจาก resource ไม่พอ ระบบจะต้องทำการ scale node เพิ่ม

[nutanix@harbor ~]$ kubectl get pod
NAME READY STATUS RESTARTS AGE
resource-test-655798b6c9-6j852 0/1 Pending 0 34s
resource-test-655798b6c9-7c8np 0/1 Pending 0 34s
resource-test-655798b6c9-7rj8x 0/1 Pending 0 34s
resource-test-655798b6c9-7vwvr 0/1 Pending 0 34s
resource-test-655798b6c9-fbk9f 1/1 Running 0 34s
resource-test-655798b6c9-gj8wk 0/1 Pending 0 34s
resource-test-655798b6c9-m9clc 1/1 Running 0 34s
resource-test-655798b6c9-qc8sn 1/1 Running 0 34s
resource-test-655798b6c9-vhbdh 0/1 Pending 0 34s
resource-test-655798b6c9-xd8nf 0/1 Pending 0 34s

ตรวจสอบจำนวน node ปัจจุบัน

[nutanix@harbor ~]$ kubectl get node
NAME STATUS ROLES AGE VERSION
dev2-hh42l-kc65c Ready control-plane 5h5m v1.34.1
dev2-md-0-rm6kd-f4xbb-8bgsj Ready <none> 4h58m v1.34.1
dev2-md-0-rm6kd-f4xbb-h9zqd Ready <none> 5h2m v1.34.1
dev2-md-0-rm6kd-f4xbb-hrl4t Ready <none> 5h v1.34.1

ตรวจสอบอีกครั้งเพื่อดูจำนวนว่า node ได้เพิ่มขึ้นเป็น 5 node ตามที่กำหนดค่าไว้

[nutanix@harbor ~]$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
dev2-hh42l-kc65c Ready control-plane 5h8m v1.34.1
dev2-md-0-rm6kd-f4xbb-8bgsj Ready <none> 5h1m v1.34.1
dev2-md-0-rm6kd-f4xbb-cp7z4 Ready <none> 98s v1.34.1
dev2-md-0-rm6kd-f4xbb-h9zqd Ready <none> 5h5m v1.34.1
dev2-md-0-rm6kd-f4xbb-hrl4t Ready <none> 5h3m v1.34.1
dev2-md-0-rm6kd-f4xbb-lbx84 Ready <none> 101s v1.34.1

การ auto ลดลงเมื่อ resource กลับมาสู่ภาวะปกติ จะมีหลายปัจจัยเช่น resource โดยรวมจะต้องน้อยกว่า 50% เป็นต้น ข้อมูลเพิ่มเติมสามารถศึกษาเพิ่มเติมได้จาก Kubernetes Node Autoscaler

Bring your own app to NKP App Catalog

Nutanix Kubernetes Platform สามารถที่จะนำเข้า kubernetes application package ทั้งที่เป็น helm chart หรือ kustomization โดยสามารถดูรายละเอียดการสร้าง git project ได้จาก https://github.com/pkhamdee/nkp-demo-catalog-applications การสร้าง project ต้องสร้าง folder services และมี list ของ service ที่ต้องการให้แสดงที่ app catalog ตามโครงสร้างดังนี้

ภายใน folder service ต้องสร้างไฟล์ metadata.yaml ที่มีรายละเอียดของ application ตามตัวอย่าง โดยข้อมูลนี้จะแสดงในหน้า catalog

YAML
displayName: Anything LLM
description: all-in-one AI application with built-in RAG, AI agents, and more.
category:
- AI
type: catalog
allowMultipleInstances: false
scope:
- workspace
licensing:
- Ultimate
- Enterprise
certifications:
overview: |-
## Product Overview
AnythingLLM is a full-stack application where you can use commercial off-the-shelf LLMs or popular open source LLMs and vectorDB solutions to build a private ChatGPT with no compromises that you can run locally as well as host remotely and be able to chat intelligently with any documents you provide it.
AnythingLLM divides your documents into objects called `workspaces`. A Workspace functions a lot like a thread, but with the addition of containerization of your documents. Workspaces can share documents, but they do not talk to each other so you can keep your context for each workspace clean.
### Cool features of AnythingLLM
- 🆕 [**Custom AI Agents**](https://docs.anythingllm.com/agent/custom/introduction)
- 🖼️ **Multi-modal support (both closed and open-source LLMs!)**
- 👤 Multi-user instance support and permissioning _Docker version only_
- 🦾 Agents inside your workspace (browse the web, run code, etc)
- 💬 [Custom Embeddable Chat widget for your website](./embed/README.md) _Docker version only_
- 📖 Multiple document type support (PDF, TXT, DOCX, etc)
- Simple chat UI with Drag-n-Drop funcitonality and clear citations.
- 100% Cloud deployment ready.
- Works with all popular [closed and open-source LLM providers](#supported-llms-embedder-models-speech-models-and-vector-databases).
- Built-in cost & time-saving measures for managing very large documents compared to any other chat UI.
- Full Developer API for custom integrations!
- Much more...install and find out!
icon: PHN2ZyB3aWR0aD0iOTMiIGhlaWdodD0iOTMiIHZpZXdCb3g9IjAgMCA5MyA5MyIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgZmlsdGVyPSJ1cmwoI2ZpbHRlcjBfZF80NzAzXzEwMTg4KSI+CjxyZWN0IHg9IjQiIHdpZHRoPSI4NC4xODc1IiBoZWlnaHQ9Ijg0LjE4NzUiIHJ4PSIyMCIgZmlsbD0iIzFCMUIxRSIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTUwLjgyNjkgNTAuNDA5N0M1MC4yOTY0IDUxLjA5NSA1MC4yODM0IDUyLjA1NjYgNTAuODE2OCA1Mi43NTFMNTUuMjUzNSA1OC45MTU1TDU1LjI2ODMgNTguOTM0MkM1Ni4yNDU3IDYwLjE2NDQgNTcuNzE5NSA2MC44NzAxIDU5LjI4OTggNjAuODcwMUg2OS4yMDNDNzIuMDEzOCA2MC44NzAxIDc0LjMxMSA1OC42MTA5IDc0LjMxMSA1NS44MDlWMjkuNzg0OEM3NC4zMTEgMjYuOTg2OCA3Mi4wMTQzIDI0LjcyMzYgNjkuMjAzIDI0LjcyMzZINTkuMjg5OEM1Ny43MTUzIDI0LjcyMzYgNTYuMjQ0MyAyNS40MzAzIDU1LjI2NyAyNi42NjQ2TDQ2LjI1NzkgMzguMDUwMkwzMi42MzcxIDU1LjI2MUgyMy41MjU4VjMwLjMzNjJIMzIuNjE5N0wzNy41Nzc5IDM3LjAzNTRMMzcuNTg3NyAzNy4wNDc3QzM4LjM2MDUgMzguMDI2IDM5Ljg0MzMgMzguMDIwMSA0MC42MTU5IDM3LjA1MTNMNDEuNzYxNCAzNS42MDMyTDQxLjc2NzggMzUuNTk0OUM0Mi4yOTkzIDM0LjkwODQgNDIuMzEyNCAzMy45NDIzIDQxLjc2ODkgMzMuMjQ2M0wzNi45Mjk2IDI2LjY3NzlMMzYuOTE4OCAyNi42NjQzQzM1Ljk0MTggMjUuNDMwNCAzNC40NzQ3IDI0LjcyMzYgMzIuODk2MiAyNC43MjM2SDIyLjk4M0MyMC4xODMyIDI0LjcyMzYgMTcuODc1IDI2Ljk4OTEgMTcuODc1IDI5Ljc4NDhWNTUuODEyNEMxNy44NzUgNTguNjA3NSAyMC4xNzkyIDYwLjg3MzUgMjIuOTgzIDYwLjg3MzVIMzIuODk2MkMzNC40NzQ0IDYwLjg3MzUgMzUuOTQwOSA2MC4xNjcxIDM2LjkxNzcgNTguOTM3Nkw1OS41NTE3IDMwLjMzMjhINjguNjYwMlY1NS4yNTc1SDU5LjU2NDZMNTUuMDIyOSA0OC45NjlMNTUuMDA4MyA0OC45NTA3QzU0LjIzNzMgNDcuOTgyIDUyLjc1NjEgNDcuOTgyIDUxLjk4NTIgNDguOTUwN0w1MC44MzQ0IDUwLjQwMDFMNTAuODI2OSA1MC40MDk3Wk0zMy4yNTY0IDU2LjA4OThMNDAuMTE4MSA0Ny40MTk2TDQ3LjA0MjEgMzguNjcwN0w1Ni4wNTEyIDI3LjI4NTFMMzMuMjU2NCA1Ni4wODk4WiIgZmlsbD0idXJsKCNwYWludDBfbGluZWFyXzQ3MDNfMTAxODgpIi8+CjxnIGZpbHRlcj0idXJsKCNmaWx0ZXIxX2JpXzQ3MDNfMTAxODgpIj4KPG1hc2sgaWQ9InBhdGgtMy1vdXRzaWRlLTFfNDcwM18xMDE4OCIgbWFza1VuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeD0iMTQuODc1IiB5PSIyMS43MjM2IiB3aWR0aD0iNjMiIGhlaWdodD0iNDMiIGZpbGw9ImJsYWNrIj4KPHJlY3QgZmlsbD0id2hpdGUiIHg9IjE0Ljg3NSIgeT0iMjEuNzIzNiIgd2lkdGg9IjYzIiBoZWlnaHQ9IjQzIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNTAuODI2OSA1MC40MDk3QzUwLjI5NjQgNTEuMDk1IDUwLjI4MzQgNTIuMDU2NiA1MC44MTY4IDUyLjc1MUw1NS4yNTM1IDU4LjkxNTVMNTUuMjY4MyA1OC45MzQyQzU2LjI0NTcgNjAuMTY0NCA1Ny43MTk1IDYwLjg3MDEgNTkuMjg5OCA2MC44NzAxSDY5LjIwM0M3Mi4wMTM4IDYwLjg3MDEgNzQuMzExIDU4LjYxMDkgNzQuMzExIDU1LjgwOVYyOS43ODQ4Qzc0LjMxMSAyNi45ODY4IDcyLjAxNDMgMjQuNzIzNiA2OS4yMDMgMjQuNzIzNkg1OS4yODk4QzU3LjcxNTMgMjQuNzIzNiA1Ni4yNDQzIDI1LjQzMDMgNTUuMjY3IDI2LjY2NDZMNDYuMjU3OSAzOC4wNTAyTDMyLjYzNzEgNTUuMjYxSDIzLjUyNThWMzAuMzM2MkgzMi42MTk3TDM3LjU3NzkgMzcuMDM1NEwzNy41ODc3IDM3LjA0NzdDMzguMzYwNSAzOC4wMjYgMzkuODQzMyAzOC4wMjAxIDQwLjYxNTkgMzcuMDUxM0w0MS43NjE0IDM1LjYwMzJMNDEuNzY3OCAzNS41OTQ5QzQyLjI5OTMgMzQuOTA4NCA0Mi4zMTI0IDMzLjk0MjMgNDEuNzY4OSAzMy4yNDYzTDM2LjkyOTYgMjYuNjc3OUwzNi45MTg4IDI2LjY2NDNDMzUuOTQxOCAyNS40MzA0IDM0LjQ3NDcgMjQuNzIzNiAzMi44OTYyIDI0LjcyMzZIMjIuOTgzQzIwLjE4MzIgMjQuNzIzNiAxNy44NzUgMjYuOTg5MSAxNy44NzUgMjkuNzg0OFY1NS44MTI0QzE3Ljg3NSA1OC42MDc1IDIwLjE3OTIgNjAuODczNSAyMi45ODMgNjAuODczNUgzMi44OTYyQzM0LjQ3NDQgNjAuODczNSAzNS45NDA5IDYwLjE2NzEgMzYuOTE3NyA1OC45Mzc2TDU5LjU1MTcgMzAuMzMyOEg2OC42NjAyVjU1LjI1NzVINTkuNTY0Nkw1NS4wMjI5IDQ4Ljk2OUw1NS4wMDgzIDQ4Ljk1MDdDNTQuMjM3MyA0Ny45ODIgNTIuNzU2MSA0Ny45ODIgNTEuOTg1MiA0OC45NTA3TDUwLjgzNDQgNTAuNDAwMUw1MC44MjY5IDUwLjQwOTdaTTMzLjI1NjQgNTYuMDg5OEw0MC4xMTgxIDQ3LjQxOTZMNDcuMDQyMSAzOC42NzA3TDU2LjA1MTIgMjcuMjg1MUwzMy4yNTY0IDU2LjA4OThaIi8+CjwvbWFzaz4KPHBhdGggZD0iTTUwLjgxNjggNTIuNzUxTDUzLjI1MTcgNTAuOTk4NUw1My4yMjQ0IDUwLjk2MDVMNTMuMTk1OSA1MC45MjM0TDUwLjgxNjggNTIuNzUxWk01MC44MjY5IDUwLjQwOTdMNTMuMTk5MiA1Mi4yNDYyTDUzLjE5OTUgNTIuMjQ1OEw1MC44MjY5IDUwLjQwOTdaTTU1LjI1MzUgNTguOTE1NUw1Mi44MTg2IDYwLjY2OEw1Mi44NjAzIDYwLjcyNjFMNTIuOTA0OCA2MC43ODJMNTUuMjUzNSA1OC45MTU1Wk01NS4yNjgzIDU4LjkzNDJMNTcuNjE3MiA1Ny4wNjc5TDU3LjYxNjkgNTcuMDY3N0w1NS4yNjgzIDU4LjkzNDJaTTU1LjI2NyAyNi42NjQ2TDUyLjkxNSAyNC44MDIzTDUyLjkxNDUgMjQuODAzTDU1LjI2NyAyNi42NjQ2Wk00Ni4yNTc5IDM4LjA1MDJMNDguNjEwMyAzOS45MTE5TDQ4LjYxMDUgMzkuOTExN0w0Ni4yNTc5IDM4LjA1MDJaTTMyLjYzNzEgNTUuMjYxVjU4LjI2MUgzNC4wODg2TDM0Ljk4OTUgNTcuMTIyN0wzMi42MzcxIDU1LjI2MVpNMjMuNTI1OCA1NS4yNjFIMjAuNTI1OFY1OC4yNjFIMjMuNTI1OFY1NS4yNjFaTTIzLjUyNTggMzAuMzM2MlYyNy4zMzYySDIwLjUyNThWMzAuMzM2MkgyMy41MjU4Wk0zMi42MTk3IDMwLjMzNjJMMzUuMDMxMSAyOC41NTE1TDM0LjEzMTcgMjcuMzM2MkgzMi42MTk3VjMwLjMzNjJaTTM3LjU3NzkgMzcuMDM1NEwzNS4xNjY1IDM4LjgyMDFMMzUuMTk0NiAzOC44NThMMzUuMjIzOSAzOC44OTVMMzcuNTc3OSAzNy4wMzU0Wk0zNy41ODc3IDM3LjA0NzdMMzUuMjMzNiAzOC45MDc0TDM1LjIzMzcgMzguOTA3NEwzNy41ODc3IDM3LjA0NzdaTTQwLjYxNTkgMzcuMDUxM0w0Mi45NjE1IDM4LjkyMTdMNDIuOTY4NyAzOC45MTI1TDQwLjYxNTkgMzcuMDUxM1pNNDEuNzYxNCAzNS42MDMyTDQ0LjExNDIgMzcuNDY0NEw0NC4xMjM5IDM3LjQ1MjJMNDQuMTMzNSAzNy40Mzk4TDQxLjc2MTQgMzUuNjAzMlpNNDEuNzY3OCAzNS41OTQ5TDQ0LjEzOTkgMzcuNDMxNkw0NC4xNDAxIDM3LjQzMTNMNDEuNzY3OCAzNS41OTQ5Wk00MS43Njg5IDMzLjI0NjNMMzkuMzUzNiAzNS4wMjU4TDM5LjM3ODYgMzUuMDU5NkwzOS40MDQ0IDM1LjA5MjdMNDEuNzY4OSAzMy4yNDYzWk0zNi45Mjk2IDI2LjY3NzlMMzkuMzQ0OCAyNC44OTg1TDM5LjMxMzkgMjQuODU2NEwzOS4yODE0IDI0LjgxNTVMMzYuOTI5NiAyNi42Nzc5Wk0zNi45MTg4IDI2LjY2NDNMMzQuNTY2OCAyOC41MjY2TDM0LjU2NjkgMjguNTI2OEwzNi45MTg4IDI2LjY2NDNaTTM2LjkxNzcgNTguOTM3NkwzOS4yNjY2IDYwLjgwMzhMMzkuMjcwMyA2MC43OTkxTDM2LjkxNzcgNTguOTM3NlpNNTkuNTUxNyAzMC4zMzI4VjI3LjMzMjhINTguMDk5OUw1Ny4xOTkxIDI4LjQ3MTNMNTkuNTUxNyAzMC4zMzI4Wk02OC42NjAyIDMwLjMzMjhINzEuNjYwMlYyNy4zMzI4SDY4LjY2MDJWMzAuMzMyOFpNNjguNjYwMiA1NS4yNTc1VjU4LjI1NzVINzEuNjYwMlY1NS4yNTc1SDY4LjY2MDJaTTU5LjU2NDYgNTUuMjU3NUw1Ny4xMzI1IDU3LjAxNEw1OC4wMzA2IDU4LjI1NzVINTkuNTY0NlY1NS4yNTc1Wk01NS4wMjI5IDQ4Ljk2OUw1Ny40NTQ5IDQ3LjIxMjVMNTcuNDEzOCA0Ny4xNTU3TDU3LjM3MDEgNDcuMTAwOEw1NS4wMjI5IDQ4Ljk2OVpNNTUuMDA4MyA0OC45NTA3TDUyLjY2MDkgNTAuODE4OUw1Mi42NjEgNTAuODE5TDU1LjAwODMgNDguOTUwN1pNNTEuOTg1MiA0OC45NTA3TDQ5LjYzNzggNDcuMDgyNkw0OS42MzU3IDQ3LjA4NTNMNTEuOTg1MiA0OC45NTA3Wk01MC44MzQ0IDUwLjQwMDFMNDguNDg0OSA0OC41MzQ2TDQ4LjQ3MzMgNDguNTQ5Mkw0OC40NjE5IDQ4LjU2NEw1MC44MzQ0IDUwLjQwMDFaTTMzLjI1NjQgNTYuMDg5OEwzMC45MDM5IDU0LjIyODFMMzUuNjA4OCA1Ny45NTE1TDMzLjI1NjQgNTYuMDg5OFpNNDAuMTE4MSA0Ny40MTk2TDM3Ljc2NTYgNDUuNTU3OUwzNy43NjU2IDQ1LjU1NzlMNDAuMTE4MSA0Ny40MTk2Wk00Ny4wNDIxIDM4LjY3MDdMNDkuMzk0NSA0MC41MzI0TDQ5LjM5NDcgNDAuNTMyMkw0Ny4wNDIxIDM4LjY3MDdaTTU2LjA1MTIgMjcuMjg1MUw1OC40MDM4IDI5LjE0NjZMNTMuNjk4OCAyNS40MjM0TDU2LjA1MTIgMjcuMjg1MVpNNTMuMTk1OSA1MC45MjM0QzUzLjUwODcgNTEuMzMwNyA1My40ODcxIDUxLjg3NDIgNTMuMTk5MiA1Mi4yNDYyTDQ4LjQ1NDcgNDguNTczM0M0Ny4xMDU3IDUwLjMxNTkgNDcuMDU4MSA1Mi43ODI1IDQ4LjQzNzcgNTQuNTc4NUw1My4xOTU5IDUwLjkyMzRaTTU3LjY4ODQgNTcuMTYzMUw1My4yNTE3IDUwLjk5ODVMNDguMzgxOCA1NC41MDM0TDUyLjgxODYgNjAuNjY4TDU3LjY4ODQgNTcuMTYzMVpNNTcuNjE2OSA1Ny4wNjc3TDU3LjYwMjEgNTcuMDQ5TDUyLjkwNDggNjAuNzgyTDUyLjkxOTYgNjAuODAwN0w1Ny42MTY5IDU3LjA2NzdaTTU5LjI4OTggNTcuODcwMUM1OC42MjczIDU3Ljg3MDEgNTguMDIxIDU3LjU3NjMgNTcuNjE3MiA1Ny4wNjc5TDUyLjkxOTQgNjAuODAwNEM1NC40NzA0IDYyLjc1MjQgNTYuODExNyA2My44NzAxIDU5LjI4OTggNjMuODcwMVY1Ny44NzAxWk02OS4yMDMgNTcuODcwMUg1OS4yODk4VjYzLjg3MDFINjkuMjAzVjU3Ljg3MDFaTTcxLjMxMSA1NS44MDlDNzEuMzExIDU2LjkyMTYgNzAuMzg5NiA1Ny44NzAxIDY5LjIwMyA1Ny44NzAxVjYzLjg3MDFDNzMuNjM3OSA2My44NzAxIDc3LjMxMSA2MC4zMDAzIDc3LjMxMSA1NS44MDlINzEuMzExWk03MS4zMTEgMjkuNzg0OFY1NS44MDlINzcuMzExVjI5Ljc4NDhINzEuMzExWk02OS4yMDMgMjcuNzIzNkM3MC4zODg0IDI3LjcyMzYgNzEuMzExIDI4LjY3NDQgNzEuMzExIDI5Ljc4NDhINzcuMzExQzc3LjMxMSAyNS4yOTkxIDczLjY0MDIgMjEuNzIzNiA2OS4yMDMgMjEuNzIzNlYyNy43MjM2Wk01OS4yODk4IDI3LjcyMzZINjkuMjAzVjIxLjcyMzZINTkuMjg5OFYyNy43MjM2Wk01Ny42MTkgMjguNTI2OUM1OC4wMjMzIDI4LjAxNjMgNTguNjI1NCAyNy43MjM2IDU5LjI4OTggMjcuNzIzNlYyMS43MjM2QzU2LjgwNTEgMjEuNzIzNiA1NC40NjU0IDIyLjg0NDMgNTIuOTE1IDI0LjgwMjNMNTcuNjE5IDI4LjUyNjlaTTQ4LjYxMDUgMzkuOTExN0w1Ny42MTk2IDI4LjUyNjFMNTIuOTE0NSAyNC44MDNMNDMuOTA1MyAzNi4xODg2TDQ4LjYxMDUgMzkuOTExN1pNMzQuOTg5NSA1Ny4xMjI3TDQ4LjYxMDMgMzkuOTExOUw0My45MDU0IDM2LjE4ODRMMzAuMjg0NiA1My4zOTkyTDM0Ljk4OTUgNTcuMTIyN1pNMjMuNTI1OCA1OC4yNjFIMzIuNjM3MVY1Mi4yNjFIMjMuNTI1OFY1OC4yNjFaTTIwLjUyNTggMzAuMzM2MlY1NS4yNjFIMjYuNTI1OFYzMC4zMzYySDIwLjUyNThaTTMyLjYxOTcgMjcuMzM2MkgyMy41MjU4VjMzLjMzNjJIMzIuNjE5N1YyNy4zMzYyWk0zOS45ODkzIDM1LjI1MDZMMzUuMDMxMSAyOC41NTE1TDMwLjIwODMgMzIuMTIwOUwzNS4xNjY1IDM4LjgyMDFMMzkuOTg5MyAzNS4yNTA2Wk0zOS45NDE3IDM1LjE4OEwzOS45MzIgMzUuMTc1N0wzNS4yMjM5IDM4Ljg5NUwzNS4yMzM2IDM4LjkwNzRMMzkuOTQxNyAzNS4xODhaTTM4LjI3MDQgMzUuMTgwOUMzOC42OTExIDM0LjY1MzIgMzkuNTA1OCAzNC42MzYyIDM5Ljk0MTcgMzUuMTg4TDM1LjIzMzcgMzguOTA3NEMzNy4yMTUzIDQxLjQxNTcgNDAuOTk1NiA0MS4zODcgNDIuOTYxNSAzOC45MjE3TDM4LjI3MDQgMzUuMTgwOVpNMzkuNDA4NiAzMy43NDJMMzguMjYzMSAzNS4xOUw0Mi45Njg3IDM4LjkxMjVMNDQuMTE0MiAzNy40NjQ0TDM5LjQwODYgMzMuNzQyWk0zOS4zOTU4IDMzLjc1ODNMMzkuMzg5MyAzMy43NjY1TDQ0LjEzMzUgMzcuNDM5OEw0NC4xMzk5IDM3LjQzMTZMMzkuMzk1OCAzMy43NTgzWk0zOS40MDQ0IDM1LjA5MjdDMzkuMDgzNiAzNC42ODE5IDM5LjEwNyAzNC4xMzEzIDM5LjM5NTYgMzMuNzU4NUw0NC4xNDAxIDM3LjQzMTNDNDUuNDkxNiAzNS42ODU1IDQ1LjU0MTEgMzMuMjAyNyA0NC4xMzM0IDMxLjRMMzkuNDA0NCAzNS4wOTI3Wk0zNC41MTQzIDI4LjQ1NzRMMzkuMzUzNiAzNS4wMjU4TDQ0LjE4NDIgMzEuNDY2OEwzOS4zNDQ4IDI0Ljg5ODVMMzQuNTE0MyAyOC40NTc0Wk0zNC41NjY5IDI4LjUyNjhMMzQuNTc3NyAyOC41NDA0TDM5LjI4MTQgMjQuODE1NUwzOS4yNzA3IDI0LjgwMTlMMzQuNTY2OSAyOC41MjY4Wk0zMi44OTYyIDI3LjcyMzZDMzMuNTYzMyAyNy43MjM2IDM0LjE2MjEgMjguMDE1NSAzNC41NjY4IDI4LjUyNjZMMzkuMjcwOCAyNC44MDJDMzcuNzIxNSAyMi44NDUzIDM1LjM4NiAyMS43MjM2IDMyLjg5NjIgMjEuNzIzNlYyNy43MjM2Wk0yMi45ODMgMjcuNzIzNkgzMi44OTYyVjIxLjcyMzZIMjIuOTgzVjI3LjcyMzZaTTIwLjg3NSAyOS43ODQ4QzIwLjg3NSAyOC42ODAyIDIxLjgwNTYgMjcuNzIzNiAyMi45ODMgMjcuNzIzNlYyMS43MjM2QzE4LjU2MDggMjEuNzIzNiAxNC44NzUgMjUuMjk4IDE0Ljg3NSAyOS43ODQ4SDIwLjg3NVpNMjAuODc1IDU1LjgxMjRWMjkuNzg0OEgxNC44NzVWNTUuODEyNEgyMC44NzVaTTIyLjk4MyA1Ny44NzM1QzIxLjgwMzMgNTcuODczNSAyMC44NzUgNTYuOTE4MSAyMC44NzUgNTUuODEyNEgxNC44NzVDMTQuODc1IDYwLjI5NjkgMTguNTU1IDYzLjg3MzUgMjIuOTgzIDYzLjg3MzVWNTcuODczNVpNMzIuODk2MiA1Ny44NzM1SDIyLjk4M1Y2My44NzM1SDMyLjg5NjJWNTcuODczNVpNMzQuNTY4OSA1Ny4wNzEzQzM0LjE2MzggNTcuNTgxMSAzMy41NjM4IDU3Ljg3MzUgMzIuODk2MiA1Ny44NzM1VjYzLjg3MzVDMzUuMzg0OSA2My44NzM1IDM3LjcxNzkgNjIuNzUzIDM5LjI2NjYgNjAuODAzOEwzNC41Njg5IDU3LjA3MTNaTTU3LjE5OTEgMjguNDcxM0wzNC41NjUxIDU3LjA3NjFMMzkuMjcwMyA2MC43OTkxTDYxLjkwNDMgMzIuMTk0M0w1Ny4xOTkxIDI4LjQ3MTNaTTY4LjY2MDIgMjcuMzMyOEg1OS41NTE3VjMzLjMzMjhINjguNjYwMlYyNy4zMzI4Wk03MS42NjAyIDU1LjI1NzVWMzAuMzMyOEg2NS42NjAyVjU1LjI1NzVINzEuNjYwMlpNNTkuNTY0NiA1OC4yNTc1SDY4LjY2MDJWNTIuMjU3NUg1OS41NjQ2VjU4LjI1NzVaTTUyLjU5MDggNTAuNzI1NUw1Ny4xMzI1IDU3LjAxNEw2MS45OTY2IDUzLjUwMTFMNTcuNDU0OSA0Ny4yMTI1TDUyLjU5MDggNTAuNzI1NVpNNTIuNjYxIDUwLjgxOUw1Mi42NzU2IDUwLjgzNzJMNTcuMzcwMSA0Ny4xMDA4TDU3LjM1NTYgNDcuMDgyNUw1Mi42NjEgNTAuODE5Wk01NC4zMzI1IDUwLjgxODlDNTMuOTAyNCA1MS4zNTkzIDUzLjA5MSA1MS4zNTkzIDUyLjY2MDkgNTAuODE4OUw1Ny4zNTU3IDQ3LjA4MjZDNTUuMzgzNiA0NC42MDQ3IDUxLjYwOTggNDQuNjA0NyA0OS42Mzc4IDQ3LjA4MjZMNTQuMzMyNSA1MC44MTg5Wk01My4xODM5IDUyLjI2NTVMNTQuMzM0NiA1MC44MTYyTDQ5LjYzNTcgNDcuMDg1M0w0OC40ODQ5IDQ4LjUzNDZMNTMuMTgzOSA1Mi4yNjU1Wk01My4xOTk1IDUyLjI0NThMNTMuMjA3IDUyLjIzNjFMNDguNDYxOSA0OC41NjRMNDguNDU0NCA0OC41NzM3TDUzLjE5OTUgNTIuMjQ1OFpNMzUuNjA4OCA1Ny45NTE1TDQyLjQ3MDUgNDkuMjgxM0wzNy43NjU2IDQ1LjU1NzlMMzAuOTA0IDU0LjIyOEwzNS42MDg4IDU3Ljk1MTVaTTQyLjQ3MDUgNDkuMjgxM0w0OS4zOTQ1IDQwLjUzMjRMNDQuNjg5NiAzNi44MDg5TDM3Ljc2NTYgNDUuNTU3OUw0Mi40NzA1IDQ5LjI4MTNaTTQ5LjM5NDcgNDAuNTMyMkw1OC40MDM4IDI5LjE0NjZMNTMuNjk4NyAyNS40MjM1TDQ0LjY4OTUgMzYuODA5MUw0OS4zOTQ3IDQwLjUzMjJaTTUzLjY5ODggMjUuNDIzNEwzMC45MDM5IDU0LjIyODFMMzUuNjA4OSA1Ny45NTE0TDU4LjQwMzcgMjkuMTQ2N0w1My42OTg4IDI1LjQyMzRaIiBmaWxsPSJ1cmwoI3BhaW50MV9saW5lYXJfNDcwM18xMDE4OCkiIGZpbGwtb3BhY2l0eT0iMC4xIiBtYXNrPSJ1cmwoI3BhdGgtMy1vdXRzaWRlLTFfNDcwM18xMDE4OCkiLz4KPC9nPgo8L2c+CjxkZWZzPgo8ZmlsdGVyIGlkPSJmaWx0ZXIwX2RfNDcwM18xMDE4OCIgeD0iMCIgeT0iMCIgd2lkdGg9IjkyLjE4NzUiIGhlaWdodD0iOTIuMTg3NSIgZmlsdGVyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBjb2xvci1pbnRlcnBvbGF0aW9uLWZpbHRlcnM9InNSR0IiPgo8ZmVGbG9vZCBmbG9vZC1vcGFjaXR5PSIwIiByZXN1bHQ9IkJhY2tncm91bmRJbWFnZUZpeCIvPgo8ZmVDb2xvck1hdHJpeCBpbj0iU291cmNlQWxwaGEiIHR5cGU9Im1hdHJpeCIgdmFsdWVzPSIwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAxMjcgMCIgcmVzdWx0PSJoYXJkQWxwaGEiLz4KPGZlT2Zmc2V0IGR5PSI0Ii8+CjxmZUdhdXNzaWFuQmx1ciBzdGREZXZpYXRpb249IjIiLz4KPGZlQ29tcG9zaXRlIGluMj0iaGFyZEFscGhhIiBvcGVyYXRvcj0ib3V0Ii8+CjxmZUNvbG9yTWF0cml4IHR5cGU9Im1hdHJpeCIgdmFsdWVzPSIwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwLjI1IDAiLz4KPGZlQmxlbmQgbW9kZT0ibm9ybWFsIiBpbjI9IkJhY2tncm91bmRJbWFnZUZpeCIgcmVzdWx0PSJlZmZlY3QxX2Ryb3BTaGFkb3dfNDcwM18xMDE4OCIvPgo8ZmVCbGVuZCBtb2RlPSJub3JtYWwiIGluPSJTb3VyY2VHcmFwaGljIiBpbjI9ImVmZmVjdDFfZHJvcFNoYWRvd180NzAzXzEwMTg4IiByZXN1bHQ9InNoYXBlIi8+CjwvZmlsdGVyPgo8ZmlsdGVyIGlkPSJmaWx0ZXIxX2JpXzQ3MDNfMTAxODgiIHg9IjEyLjIyNTUiIHk9IjE5LjA3NDEiIHdpZHRoPSI2Ny43MzY1IiBoZWlnaHQ9IjQ3LjQ0ODkiIGZpbHRlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgY29sb3ItaW50ZXJwb2xhdGlvbi1maWx0ZXJzPSJzUkdCIj4KPGZlRmxvb2QgZmxvb2Qtb3BhY2l0eT0iMCIgcmVzdWx0PSJCYWNrZ3JvdW5kSW1hZ2VGaXgiLz4KPGZlR2F1c3NpYW5CbHVyIGluPSJCYWNrZ3JvdW5kSW1hZ2VGaXgiIHN0ZERldmlhdGlvbj0iMS4zMjQ3NSIvPgo8ZmVDb21wb3NpdGUgaW4yPSJTb3VyY2VBbHBoYSIgb3BlcmF0b3I9ImluIiByZXN1bHQ9ImVmZmVjdDFfYmFja2dyb3VuZEJsdXJfNDcwM18xMDE4OCIvPgo8ZmVCbGVuZCBtb2RlPSJub3JtYWwiIGluPSJTb3VyY2VHcmFwaGljIiBpbjI9ImVmZmVjdDFfYmFja2dyb3VuZEJsdXJfNDcwM18xMDE4OCIgcmVzdWx0PSJzaGFwZSIvPgo8ZmVDb2xvck1hdHJpeCBpbj0iU291cmNlQWxwaGEiIHR5cGU9Im1hdHJpeCIgdmFsdWVzPSIwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAxMjcgMCIgcmVzdWx0PSJoYXJkQWxwaGEiLz4KPGZlT2Zmc2V0IGR5PSIwLjQ0MTU4NCIvPgo8ZmVHYXVzc2lhbkJsdXIgc3RkRGV2aWF0aW9uPSIwLjY2MjM3NiIvPgo8ZmVDb21wb3NpdGUgaW4yPSJoYXJkQWxwaGEiIG9wZXJhdG9yPSJhcml0aG1ldGljIiBrMj0iLTEiIGszPSIxIi8+CjxmZUNvbG9yTWF0cml4IHR5cGU9Im1hdHJpeCIgdmFsdWVzPSIwIDAgMCAwIDEgMCAwIDAgMCAxIDAgMCAwIDAgMSAwIDAgMCAwLjE1IDAiLz4KPGZlQmxlbmQgbW9kZT0ibm9ybWFsIiBpbjI9InNoYXBlIiByZXN1bHQ9ImVmZmVjdDJfaW5uZXJTaGFkb3dfNDcwM18xMDE4OCIvPgo8L2ZpbHRlcj4KPGxpbmVhckdyYWRpZW50IGlkPSJwYWludDBfbGluZWFyXzQ3MDNfMTAxODgiIHgxPSIxOC44NzUiIHkxPSIyNS43MjM2IiB4Mj0iNzcuNTI1IiB5Mj0iNDkuNDYyNCIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPgo8c3RvcCBzdG9wLWNvbG9yPSIjNzVBNUZGIi8+CjxzdG9wIG9mZnNldD0iMC43MDMxMjUiIHN0b3AtY29sb3I9IiMyM0U1RkYiLz4KPC9saW5lYXJHcmFkaWVudD4KPGxpbmVhckdyYWRpZW50IGlkPSJwYWludDFfbGluZWFyXzQ3MDNfMTAxODgiIHgxPSIxOS42Mzg2IiB5MT0iMjYuMzY2OCIgeDI9Ijc0LjMxMSIgeTI9IjI2LjM2NjgiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KPHN0b3Agc3RvcC1jb2xvcj0iIzNDREVCNiIvPgo8c3RvcCBvZmZzZXQ9IjAuNjU2MjUiIHN0b3AtY29sb3I9IiMzNjRBRkYiLz4KPC9saW5lYXJHcmFkaWVudD4KPC9kZWZzPgo8L3N2Zz4K

ภายใน folder service สร้าง folder version และสร้าง file kustomization.yaml เพื่อให้เชื่อมไปยัง kubernetes application package ที่ต้องการ deploy เมื่อมีการ enable app ผ่าน nkp app catalog

ตัวอย่าง file kustomization.yaml

YAML
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- helmrelease.yaml
- ../../../helm-repositories/la-cc.github.io/la-cc.github.io

ใช้ nkp cli เพื่อนำเข้า app catalog ตามตัวอย่าง

Shell
nkp create catalog-application nkp-demo-catalog-applications \
-w kommander-workspace \
--branch main \
--url https://github.com/pkhamdee/nkp-demo-catalog-applications

หลังจากนั้นตรวจสอบ application ที่แสดงใน workspace ตามที่ระบุใน cli ทั้งนี้เราสามารถเลือกได้ว่าจะให้ app แสดงใน workspace ไหนได้ใน cli