Skip to content

NimTechnology

Trình bày các công nghệ CLOUD một cách dễ hiểu.

  • Kubernetes & Container
    • Docker
    • Kubernetes
      • Gateway API
      • Ingress
      • Pod
    • Helm Chart
    • OAuth2 Proxy
    • Isito-EnvoyFilter
    • Apache Kafka
      • Kafka
      • Kafka Connect
      • Lenses
    • Vault
    • Longhorn – Storage
    • VictoriaMetrics
    • MetalLB
    • Kong Gateway
  • CI/CD
    • ArgoCD
    • ArgoWorkflows
    • Argo Events
    • Spinnaker
    • Jenkins
    • Harbor
    • TeamCity
    • Git
      • Bitbucket
  • Coding
    • DevSecOps
    • Terraform
      • GCP – Google Cloud
      • AWS – Amazon Web Service
      • Azure Cloud
    • Golang
    • Laravel
    • Python
    • Jquery & JavaScript
    • Selenium
  • Log, Monitor & Tracing
    • DataDog
    • Prometheus
    • Grafana
    • ELK
      • Kibana
      • Logstash
  • BareMetal
    • NextCloud
  • Toggle search form

Komodo manages many Docker containers on many servers

Posted on July 27, 2026August 26, 2026 By nim No Comments on Komodo manages many Docker containers on many servers

Tạo folder bắt đâù cài đặt Komodo core:

mkdir komodo

cd komodo

sudo mkdir -p \
  ./data/mongo-db \
  ./data/mongo-configdb \
  ./data/repo-cache \
  ./backups

Bạn có thể dụng command để tạo chuỗi random dài:

openssl rand -hex 32
03af3ddcc5xxxxx60f40beb1ba6b1985ccb1d798c142f2bb06996d232

Create compose.env

TZ=Asia/Singapore

# Public URL Core mà browser và Periphery truy cập
KOMODO_HOST=http://192.168.101.36:9120

# MongoDB
KOMODO_DB_USERNAME=komodo
KOMODO_DB_PASSWORD=03af3ddcc5xxxxx60f40beb1ba6b1985ccb1d798c142f2bb06996d232

# Local authentication
KOMODO_LOCAL_AUTH=true
KOMODO_INIT_ADMIN_USERNAME=admin
KOMODO_INIT_ADMIN_PASSWORD=03af3ddcc5xxxxx60f40beb1ba6b1985ccb1d798c142f2bb06996d232
KOMODO_JWT_SECRET=03af3ddcc5xxxxx60f40beb1ba6b1985ccb1d798c142f2bb06996d232

# Core-to-Periphery và webhook secrets
KOMODO_PASSKEY=03af3ddcc5xxxxx60f40beb1ba6b1985ccb1d798c142f2bb06996d232
KOMODO_WEBHOOK_SECRET=03af3ddcc5xxxxx60f40beb1ba6b1985ccb1d798c142f2bb06996d232

Tạo file compose.yaml (version mới không cần tạo file docker-compse.yaml nữa)

services:
  mongo:
    image: mongo:8
    container_name: komodo-mongo
    restart: unless-stopped
    command: --quiet --wiredTigerCacheSizeGB 0.25
    environment:
      MONGO_INITDB_ROOT_USERNAME: ${KOMODO_DB_USERNAME}
      MONGO_INITDB_ROOT_PASSWORD: ${KOMODO_DB_PASSWORD}
    volumes:
      - ./data/mongo-db:/data/db
      - ./data/mongo-configdb:/data/configdb
    networks:
      - komodo-internal

  core:
    image: ghcr.io/moghtech/komodo-core:2.2.0
    container_name: komodo-core
    restart: unless-stopped
    depends_on:
      - mongo
    env_file:
      - ./compose.env
    environment:
      KOMODO_DATABASE_ADDRESS: mongo:27017
      KOMODO_DATABASE_USERNAME: ${KOMODO_DB_USERNAME}
      KOMODO_DATABASE_PASSWORD: ${KOMODO_DB_PASSWORD}
    ports:
      - "9120:9120"
    volumes:
      - ./data/repo-cache:/repo-cache
    networks:
      - komodo-internal

networks:
  komodo-internal:
    name: komodo-internal

Tiếp đến là câu lệnh run docker compose:

docker compose --env-file compose.env up -d

Bạn login vào IP-host:9120

Contents

Toggle
  • Install Komodo Peripheri
    • Bước 1: Gỡ cài đặt (Uninstall)
  • Cài đặt Komodo Core
  • Mô hình webhook của
  • Komodo Stack
  • Komodo Variables.
  • Komodo Actions

Install Komodo Peripheri

Trước tiên bạn cần tạo Onboarding key:

Bạn vào Setting -> Onboarding -> Click: New Onboarding Key

Bạn khai bao các thứ

Bạn copy the key và chuẩn bị cho công lệnh chạy trên Periphery

curl -sSL https://raw.githubusercontent.com/moghtech/komodo/main/scripts/setup-periphery.py \
 | python3 - \
 --core-address="http://komodo-core-domain-or-ip" \
 --connect-as="$(hostname)" \
 --onboarding-key="<ONBOARDING_KEY_CUA_BAN>"

Xoá Komodo Periphery

Bước 1: Gỡ cài đặt (Uninstall)

  1. Dừng và vô hiệu hóa service đang chạy:
sudo systemctl stop periphery
sudo systemctl disable periphery

Xóa file service của Systemd và tải lại daemon:

sudo rm /etc/systemd/system/periphery.service
sudo systemctl daemon-reload

Xóa file nhị phân (binary):
File thực thi của periphery thường được đặt ở thư mục /usr/local/bin/ (với tài khoản root).

sudo rm /usr/local/bin/periphery

Nếu bạn từng cài đặt với cờ --user bằng quyền user thường, file có thể nằm ở ~/.local/bin/periphery).

  1. Xóa thư mục cấu hình và khóa chứng thực (Keys):
    Periphery lưu các file cấu hình periphery.config.toml và các cặp khóa (public/private keys) tại /etc/komodo. Việc xóa thư mục này đảm bảo quá trình cài lại sẽ sinh ra cặp khóa mới hoàn toàn (rất quan trọng nếu bạn thay đổi Core).github+1
sudo rm -rf /etc/komodo

Cài đặt Komodo Core

Chúng ta sẽ cài đặt Komodo trên k8s.

#kustomizaion:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

namespace: komodo

resources:
  - komodo-auth-secret.json

helmCharts:
  - name: komodo
    includeCRDs: false
    releaseName: komodo
    version: 0.1.1
    repo: https://antiantiops.github.io/komodo-helm-chart
    valuesFile: values_helm.yaml
    namespace: komodo

# helm-values.yaml
###############
# Production values for the Komodo Helm chart.
# Credentials reside in the pre-created Kubernetes Secret komodo-auth, not Git.
existingSecret:
  name: komodo-auth

komodo:
  host: http://komodo.nimtechnology.com
  localAuth: true
  timezone: Asia/Ho_Chi_Minh
  ingress:
    enabled: true
    className: nginx
    annotations: {}
    hosts:
      - host: komodo.nimtechnology.com
        paths:
          - path: /
            pathType: Prefix
    tls: []
  persistence:
    config:
      enabled: true
      size: 1Gi
      storageClass: longhorn
    repoCache:
      enabled: true
      size: 10Gi
      storageClass: longhorn

mongo:
  persistence:
    enabled: true
    size: 10Gi
    storageClass: longhorn

Tiếp theo chúng ta tạo secret cấp cho mongodb, komodo.

{
  "apiVersion": "v1",
  "kind": "Secret",
  "metadata": {
    "name": "komodo-auth",
    "namespace": "komodo"
  },
  "type": "Opaque",
  "data": {
    "komodo-init-admin-password": "TlE5cnNuOXFycmlCSxxxxx1CMlA3MDZaU0RQNk4=",
    "komodo-jwt-secret": "bVIvc1VwUlpHSXpmd2phcCt1V29DY2czMkdpcWXXXXNaUUFJQVZ2b1d1MVZhNWNjbFg4QTFrUWxUNQ==",
    "komodo-passkey": "ZU9SNG1KaWMxbXBrc1XXXXnh4U3d3QUFIU2NodGl1OGtqMDZLR3RrST0=",
    "komodo-webhook-secret": "UzE5NDRNZkZlWlXXXXN0JFbzZRcDFkd1VQVzA3QllCRXZrVDk1UT0=",
    "mongo-root-password": "VktFNFF3bndVWURkcFXXXXXb1dRZTFhSUExTzZyT3Zub1Uraz0="
  }
}

Mô hình webhook của

Cách lấy file python theo release:

TAG=v2.3.1
COMMIT="$(git ls-remote https://github.com/moghtech/komodo.git "refs/tags/${TAG}" | awk '{print $1}')"
CHECKSUM="$(curl --fail --silent --show-error --location \
  "https://raw.githubusercontent.com/moghtech/komodo/${COMMIT}/scripts/setup-periphery.py" \
  | shasum -a 256 | awk '{print $1}')"

printf 'commit=%s\nchecksum=sha256:%s\nversion=%s\n' \
  "$COMMIT" "$CHECKSUM" "$TAG"

Komodo Stack

Sau khi stack deploy cái docker compose.
thì nó cần run 1 lệnh là docker compose config để lưu lại lần mới nhất komodo đã deploy thử gì.

và nếu lần sau bạn change trên github thì bạn có thấy được bạn đã thay đổi gì so với lần gần nhất mà komodo đã deploy.

Điều này cho chúng ta thấy một khái niệm là project trong docker.

chúng ta sẽ cần run command để show các docker đang chạy trong hosts

docker ps -a

Hoặc lệnh

docker compose ls
NAME                STATUS              CONFIG FILES
hihi                running(1)          /opt/hihi/docker-compose.yml
node-exporter       running(2)          /opt/data/node-exporter/docker-compose.yml

Chúng ta sẽ dùng lệnh

docker inspect node-exporter --format '{{ index .Config.Labels "com.docker.compose.project" }}'
node-exporter
docker network inspect node-exporter_node-exporter_network \
  --format '{{range .IPAM.Config}}{{.Subnet}} {{.Gateway}}{{end}}'

192.168.112.0/24 192.168.112.1

bạn thấy project nối vào network name

Vì stack là nim-devops-host nên bạn không cần khai báo project name trong config stack.
như ảnh dưới

nếu project_name để trống komodo sẽ lấy name của stack làm project name

Komodo Variables.

services:
  nginx:
    image: nginx:1.20-alpine
    container_name: komodo-demo-nginx
    restart: unless-stopped
    environment:
      TEST_VAR: this_is_secret
    ports:
      - "8080:80"
    labels:
      app.kubernetes.io/managed-by: komodo
      demo: gitops
      check: status
      komodo.gitops.probe: "2026-07-21T18:22:00Z"

Bạn thấy đó khi mà chúng ta environment chứa secret.
Nhưng giờ nếu chúng ta muốn push docker compose này lên github thi hoàn toàn không được vì nó chưa credential.

đầu tiên bạn sử dụng tính năng variables trong settings của komodo

tiếp đến bạn cần ghi nhận variable secret trong toml file.

[[stack]]
name = "demo-nginx"
description = "Nginx Docker Compose application managed by Komodo"
tags = ["demo", "gitops", "komodo-periphery"]
deploy = true

[stack.config]
server = "periphery-181"
git_account = "mrnim94"
repo = "mrnim94/komodo-gitops-demo"
branch = "master"
git_provider = "github.com"
file_paths = ["stacks/office-hcm/periphery-181/nginx-demo/compose.yaml"]
environment = """
TEST_VAR = [[TEST_VAR]]
"""

tiếp đến là khai báo trong docker-compose.yaml

ame: nginx-ahihi
services:
  nginx:
    image: nginx:1.20-alpine
    container_name: komodo-demo-nginx
    restart: unless-stopped
    environment:
      TEST_VAR: ${TEST_VAR}
    ports:
      - "8080:80"
    labels:
      app.kubernetes.io/managed-by: komodo
      demo: gitops
      check: status
      komodo.gitops.probe: "2026-07-21T18:22:00Z"

Lúc này mình execute vào trong container thì sẽ thấy environment là TEST_VAR

Komodo Actions

Một tính năng tự động hóa nâng cao cho phép viết kịch bản TypeScript để tương tác trực tiếp với Komodo API.

Dưới đây là thiết kế giải pháp và Template Action trên Komodo để triển khai hot patching/security update hàng loạt trên 10 máy chủ Debian, đồng thời kiểm tra tiến trình và trạng thái hệ thống theo thời gian thực.

Chúng ta có 2 cách là chạy command trên các server đã gắn tag

Ví dụ bạn install komodo periphery trên client nhưng quên gắn tag thì bạn có thể ấn tạo tag trên UI hoặc dụng file toml để tạo tag cho server.

Bạn có thế lấy convert của server này ra file toml và update để không bị mất config nào

[[server]]
name = "periphery-181"
tags = ["hotpatch-group", "office-hcm"]
[server.config]
enabled = true

Lúc này file action watch các server có tag là hotpatch-group

#file name: hotpatch-action.toml

[[action]]
name = "debian-hotpatching"

[action.config]
# Lên lịch chạy tự động (ví dụ: 03:00 sáng Chủ nhật hàng tuần)
schedule = "0 3 * * 0"

# Nội dung kịch bản TypeScript
script = """
const servers = await komodo.read("ListServers", {
  query: { tags: ["hotpatch-group"] },
});

for (const server of servers) {
  const hotPatchCommand = [
    "export DEBIAN_FRONTEND=noninteractive",
    "sudo apt update -q",
    "sudo apt-get --with-new-pkgs upgrade -y -q",
    "sudo apt install -y needrestart",
    "echo '--- [1] PROCESS RESTART STATUS ---'",
    "sudo needrestart -b || true",
    "echo '--- [2] UPTIME ---'",
    "uptime",
    "echo '--- [3] KERNEL ---'",
    "uname -r",
  ].join(" && ");

  await komodo.execute_server_terminal(
    {
      server: server.name,
      terminal: "hotpatch-job",
      command: hotPatchCommand,
      init: {
        command: "bash",
        recreate: "Always",
      },
    },
    {
      onLine: (line) => console.log(`[${server.name}] ${line}`),
      onFinish: (code) => console.log(`[${server.name}] Finished code: ${code}`),
    }
  );
}
"""

Hoặc bạn muốn chạy thẳng trên server chúng ta đã có:

[[action]]
name = "debian-hotpatching"

[action.config]
# Lên lịch chạy tự động (03:00 sáng Chủ nhật hàng tuần)
#schedule_format = "Cron"
#schedule = "0 0 3 * * 0"
#schedule_enabled = true

# Nội dung kịch bản TypeScript
file_contents = """
// Khai báo danh sách server cần hotpatch
const serverNames = ["periphery-181"];

for (const name of serverNames) {
  const server = { name };
  const hotPatchCommand = [
    "export DEBIAN_FRONTEND=noninteractive",
    "sudo apt update -q",
    "sudo apt-get --with-new-pkgs upgrade -y -q",
    "sudo apt install -y needrestart",
    "echo '--- [1] PROCESS RESTART STATUS ---'",
    "sudo needrestart -b || true",
    "echo '--- [2] UPTIME ---'",
    "uptime",
    "echo '--- [3] KERNEL ---'",
    "uname -r",
  ].join(" && ");

  await komodo.execute_server_terminal(
    {
      server: server.name,
      terminal: "hotpatch-job",
      command: hotPatchCommand,
      init: {
        command: "bash",
        recreate: "Always",
      },
    },
    {
      onLine: (line) => console.log(`[${server.name}] ${line}`),
      onFinish: (code) => console.log(`[${server.name}] Finished code: ${code}`),
    }
  );
}
"""

stdout sau khi chúng ta ấn run.

Bạn cũng có thể query các thông tin khác như là:
Bạn muốn chạy patching trên con server mà có Kernel: 6.12.94+deb13-amd64

[[action]]
name = "debian-hotpatching"
description = "Hotpatch servers running kernel 6.12.94+deb13-amd64"

[action.config]
# Schedule tắt — chạy tay qua Komodo UI khi cần
schedule_format = "Cron"
schedule = "0 0 3 * * 0"
schedule_enabled = false

# Nội dung kịch bản TypeScript
file_contents = """
const targetKernel = "6.12.94+deb13-amd64";
const servers = await komodo.read("ListServers", {});
const matchedServerNames: string[] = [];

for (const server of servers) {
  const systemInfo = await komodo.read("GetSystemInformation", {
    server: server.name,
  });
  const kernel = systemInfo.kernel ?? systemInfo.kernel_version ?? systemInfo.uname?.release;

  console.log(`[${server.name}] kernel: ${kernel ?? "unknown"}`);

  if (kernel === targetKernel) {
    matchedServerNames.push(server.name);
  }
}

console.log(`Matched ${matchedServerNames.length} server(s): ${matchedServerNames.join(", ") || "none"}`);

const hotPatchCommand = [
  "export DEBIAN_FRONTEND=noninteractive",
  "sudo apt update -q",
  "sudo apt-get --with-new-pkgs upgrade -y -q",
  "sudo apt install -y needrestart",
  "echo '--- [1] PROCESS RESTART STATUS ---'",
  "sudo needrestart -b || true",
  "echo '--- [2] UPTIME ---'",
  "uptime",
  "echo '--- [3] KERNEL ---'",
  "uname -r",
].join(" && ");

for (const serverName of matchedServerNames) {
  await komodo.execute_server_terminal(
    {
      server: serverName,
      terminal: "hotpatch-job",
      command: hotPatchCommand,
      init: {
        command: "bash",
        recreate: "Always",
      },
    },
    {
      onLine: (line) => console.log(`[${serverName}] ${line}`),
      onFinish: (code) => console.log(`[${serverName}] Finished code: ${code}`),
    }
  );
}
"""
  1. Query glibc từng server.
  2. Tạo matchedServerNames.
  3. In list server có glibc 2.41.
  4. Chỉ chạy command hostname và uptime trên list đó.
[[action]]
name = "debian-hotpatching"
description = "List servers running glibc 2.41 with hostname and uptime"

[action.config]
# Schedule tắt — chạy tay qua Komodo UI khi cần
schedule_format = "Cron"
schedule = "0 0 3 * * 0"
schedule_enabled = false

# Nội dung kịch bản TypeScript
file_contents = """
const targetGlibc = "2.41";
const servers = await komodo.read("ListServers", {});
const matchedServerNames: string[] = [];

// Pha 1: chỉ query glibc, chưa chạy hostname hoặc uptime.
for (const server of servers) {
  let glibc = "";

  await komodo.execute_server_terminal(
    {
      server: server.name,
      terminal: "glibc-check-job",
      command: "dpkg-query -W -f='${Version}' libc6 2>/dev/null || true",
      init: {
        command: "bash",
        recreate: "Always",
      },
    },
    {
      onLine: (line) => {
        const value = line.trim();
        if (value && !value.includes("Finished code")) glibc = value;
      },
      onFinish: (code) => console.log(`[glibc-check:${server.name}] ${glibc || "unavailable"} (code: ${code})`),
    }
  );

  if (glibc.split("-")[0] === targetGlibc) matchedServerNames.push(server.name);
}

console.log(`glibc ${targetGlibc} servers: ${matchedServerNames.join(", ") || "none"}`);

// Pha 2: chỉ server đã nằm trong list mới query hostname và uptime.
for (const serverName of matchedServerNames) {
  await komodo.execute_server_terminal(
    {
      server: serverName,
      terminal: "glibc-info-job",
      command: "printf 'hostname: '; hostname; printf 'uptime: '; uptime -p",
      init: {
        command: "bash",
        recreate: "Always",
      },
    },
    {
      onLine: (line) => console.log(`[server:${serverName}] ${line}`),
      onFinish: (code) => console.log(`[server:${serverName}] Finished code: ${code}`),
    }
  );
}
"""
Kubernetes & Container

Post navigation

Previous Post: [Crunchy] Install PostgreSQL on the k8s cluster via Crunchy Postgres.
Next Post: [Kong Gateway] Guide line migrate from Kong Gatway legacy to modern one

More Related Articles

[Cosign/Kyverno]Signing And Verifying Container Images With Sigstore Cosign And Kyverno Kubernetes
[Udemy] Download khóa học Udemy giá rẻ chỉ với 50k/khóa Kubernetes & Container
[Kubernestes] I waiting too long but my workload is still unavailable Kubernetes & Container
[HPA/Kubernetes] Scale Up As Usual, Scale Down Very Gradually – behavior in HPA K8s Kubernetes
[Kubernetes] Lesson1: k8s easy – Kubernetes architecture and components Kubernetes & Container
[Helm Chart] Tìm hiểu – (gạch giữa), _ (gạch dưới), dấu chấm “.” trong helm chart Helm Chart

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Tham Gia Group DevOps nhé!
Để Nim có nhiều động lực ra nhiều bài viết.
Để nhận được những thông báo mới nhất.

Recent Posts

  • [Polkit] Apply the Least Privilege principle to service accounts with Polkit. August 27, 2026
  • [Kong Gateway] Guide line migrate from Kong Gatway legacy to modern one August 16, 2026
  • Komodo manages many Docker containers on many servers July 27, 2026
  • [Crunchy] Install PostgreSQL on the k8s cluster via Crunchy Postgres. July 27, 2026
  • [podman] Run a Docker container without using Docker July 15, 2026

Archives

  • August 2026
  • July 2026
  • June 2026
  • April 2026
  • March 2026
  • February 2026
  • January 2026
  • December 2025
  • November 2025
  • October 2025
  • September 2025
  • August 2025
  • July 2025
  • June 2025
  • May 2025
  • April 2025
  • March 2025
  • February 2025
  • January 2025
  • December 2024
  • November 2024
  • October 2024
  • September 2024
  • August 2024
  • July 2024
  • June 2024
  • May 2024
  • April 2024
  • March 2024
  • February 2024
  • January 2024
  • December 2023
  • November 2023
  • October 2023
  • September 2023
  • August 2023
  • July 2023
  • June 2023
  • May 2023
  • April 2023
  • March 2023
  • February 2023
  • January 2023
  • December 2022
  • November 2022
  • October 2022
  • September 2022
  • August 2022
  • July 2022
  • June 2022
  • May 2022
  • April 2022
  • March 2022
  • February 2022
  • January 2022
  • December 2021
  • November 2021
  • October 2021
  • September 2021
  • August 2021
  • July 2021
  • June 2021

Categories

  • AI
    • OpenClaw
  • BareMetal
    • NextCloud
  • CI/CD
    • Argo Events
    • ArgoCD
    • ArgoWorkflows
    • Git
      • Bitbucket
    • Harbor
    • Jenkins
    • Spinnaker
    • TeamCity
  • Coding
    • DevSecOps
    • Golang
    • Jquery & JavaScript
    • Laravel
    • NextJS 14 & ReactJS & Type Script
    • Python
    • Selenium
    • Terraform
      • AWS – Amazon Web Service
      • Azure Cloud
      • GCP – Google Cloud
  • Kubernetes & Container
    • Apache Kafka
      • Kafka
      • Kafka Connect
      • Lenses
    • Docker
    • Helm Chart
    • Isito-EnvoyFilter
    • Kong Gateway
    • Kubernetes
      • Gateway API
      • Ingress
      • Pod
    • Longhorn – Storage
    • MetalLB
    • OAuth2 Proxy
    • Vault
    • VictoriaMetrics
  • Log, Monitor & Tracing
    • DataDog
    • ELK
      • Kibana
      • Logstash
    • Fluent
    • Grafana
    • Prometheus
  • Uncategorized
  • Admin

Copyright © 2026 NimTechnology.

Powered by PressBook Blog WordPress theme