Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

119 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

multinic-operator

MGMT ํด๋Ÿฌ์Šคํ„ฐ์—์„œ OpenstackConfig CR์„ ๊ฐ์‹œํ•˜๊ณ  OpenStack ๋„คํŠธ์›Œํฌ ์ •๋ณด๋ฅผ ์ˆ˜์ง‘ํ•œ ๋’ค MGMT ํด๋Ÿฌ์Šคํ„ฐ์— ๋ฐฐํฌ๋œ Viola API๋กœ ๋…ธ๋“œ๋ณ„ ์ธํ„ฐํŽ˜์ด์Šค ์ •๋ณด๋ฅผ ์ „์†กํ•˜๋Š” ์˜คํผ๋ ˆ์ดํ„ฐ์ž…๋‹ˆ๋‹ค.

๊ฐœ์š”

  • ์ž…๋ ฅ: OpenstackConfig CR (openstackProviderID, k8sProviderID, projectID, VM ID ๋ชฉ๋ก + settings/secrets)
  • ์ฒ˜๋ฆฌ: Contrabass โ†’ Keystone โ†’ Neutron ํฌํŠธ ์กฐํšŒ
  • ์ถœ๋ ฅ: Viola API๋กœ JSON POST (MultiNicNodeConfig ์ƒ์„ฑ์šฉ, subnetIDs ์šฐ์„ /์—†์œผ๋ฉด subnetID/subnetName)
  • ์ €์žฅ: ์˜คํผ๋ ˆ์ดํ„ฐ ๋‚ด๋ถ€ Inventory API + ํŒŒ์ผ ๊ธฐ๋ฐ˜ DB(JSON)์— ์ตœ์‹  ์ƒํƒœ upsert (UI ์กฐํšŒ์šฉ)

ํ•ต์‹ฌ ๊ธฐ๋Šฅ ์š”์•ฝ

  • ์„œ๋ธŒ๋„ท ์ง€์ •: subnetIDs > subnetID > subnetName ์šฐ์„ ์ˆœ์œ„ ์ ์šฉ
    • ์—ฌ๋Ÿฌ ์„œ๋ธŒ๋„ท ์ง€์ • ๊ฐ€๋Šฅ (์˜ˆ: subnetIDs: [subnet-a, subnet-b])
  • ์ธํ„ฐํŽ˜์ด์Šค ์ƒํ•œ: ๋…ธ๋“œ๋‹น ์ตœ๋Œ€ 10๊ฐœ (multinic0~multinic9)
  • ๊ธฐ์ค€ ์‹œ์ : OpenstackConfig ์ƒ์„ฑ ์‹œ๊ฐ ์ดํ›„์— ์ƒ์„ฑ๋œ ํฌํŠธ๋งŒ ์ฒ˜๋ฆฌ
  • ํฌํŠธ ํ•„ํ„ฐ: settings.openstackPortAllowedStatuses์— ํฌํ•จ๋œ ํฌํŠธ๋งŒ ์ฒ˜๋ฆฌ
  • Viola POST ํ•„์ˆ˜๊ฐ’: k8sProviderID๊ฐ€ ์žˆ์–ด์•ผ x-provider-id ํ—ค๋”๋กœ ์ „์†ก ๊ฐ€๋Šฅ
  • Agent ์ง€์› OS: Ubuntu(netplan), RHEL(NetworkManager) ๊ธฐ๋ฐ˜ ์˜์† ์„ค์ •
    • ์ƒ์„ธ ๋‚ด์šฉ์€ ../multinic-agent/README.md ์ฐธ๊ณ 

์ฃผ์˜:

  • subnetIDs > subnetID > subnetName ์ˆœ์„œ๋กœ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • subnetName์€ ๋„คํŠธ์›Œํฌ๋ช…์ด ์•„๋‹ˆ๋ผ ์„œ๋ธŒ๋„ท ์ด๋ฆ„์ž…๋‹ˆ๋‹ค. (๋™์ผ ์ด๋ฆ„์ด ์žˆ์œผ๋ฉด ์˜ค๋ฅ˜)
  • vmNames์—๋Š” VM ID(UUID) ๋ฅผ ๋„ฃ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • nodeName์€ Nova ์„œ๋ฒ„ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜๋ฉฐ, ํ•„์š” ์‹œ settings.openstackNodeNameMetadataKey๋กœ metadata ๊ฐ’์„ ์šฐ์„  ์‚ฌ์šฉํ•˜๋„๋ก ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํฌํŠธ ์ƒํƒœ๊ฐ€ settings.openstackPortAllowedStatuses์— ํฌํ•จ๋˜์ง€ ์•Š๊ฑฐ๋‚˜, ๋Œ€์ƒ ๋…ธ๋“œ์˜ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๋น„์–ด ์žˆ์œผ๋ฉด ํ•ด๋‹น ๋…ธ๋“œ๋Š” ์ „์†ก์—์„œ ์ œ์™ธ๋ฉ๋‹ˆ๋‹ค.
  • OpenstackConfig ์ƒ์„ฑ ์‹œ๊ฐ ์ดํ›„์— ์ƒ์„ฑ๋œ ํฌํŠธ๋งŒ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • DOWN ํฌํŠธ๊ฐ€ ๋‚จ์•„ ์žˆ์œผ๋ฉด ๋น ๋ฅธ ์žฌ์‹œ๋„ ํ›„(๊ธฐ๋ณธ 5ํšŒ) ๋А๋ฆฐ ์ฃผ๊ธฐ๋กœ ์žฌ์ „์†กํ•ฉ๋‹ˆ๋‹ค.
  • ์ธํ„ฐํŽ˜์ด์Šค๋Š” subnetIDs ์ˆœ์„œ๋Œ€๋กœ ์ •๋ ฌํ•œ ๋’ค normalize ๋‹จ๊ณ„์—์„œ MAC/PortID ๊ธฐ์ค€์œผ๋กœ ์žฌ์ •๋ ฌ๋ฉ๋‹ˆ๋‹ค. (ํ˜„์žฌ ๋™์ž‘: ์ตœ์ข… multinic ์ˆœ์„œ๋Š” MAC ๊ธฐ์ค€)

์ „์ œ

  • Go 1.25+
  • Kubernetes ํด๋Ÿฌ์Šคํ„ฐ ์ ‘๊ทผ ๊ถŒํ•œ
  • Contrabass/OpenStack API ์ ‘๊ทผ ๊ฐ€๋Šฅ

OpenstackConfig ์„ค์ •

์šด์˜ ํ™˜๊ฒฝ์—์„œ๋Š” Helm ๋ฐฐํฌ ์‹œ ์ด๋ฏธ์ง€ ์ •๋ณด๋งŒ ์„ค์ •ํ•˜๊ณ , ์‹ค์ œ ์ ‘์† ์ •๋ณด๋Š” OpenstackConfig CR๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

ํ•„์ˆ˜ ํ•„๋“œ:

  • subnetIDs ๋˜๋Š” subnetID ๋˜๋Š” subnetName (subnetIDs/subnetID ๊ถŒ์žฅ)
  • vmNames: VM ID(UUID) ๋ชฉ๋ก
  • credentials.openstackProviderID
  • credentials.k8sProviderID
  • credentials.projectID
  • Contrabass ์•”ํ˜ธํ™” ํ‚ค
    • secrets.contrabassEncryptKeySecretRef ๋˜๋Š” settings.contrabassEncryptKey

๋™์ž‘ ๊ทœ์น™:

  • subnetIDs๊ฐ€ ์žˆ์œผ๋ฉด subnetID/subnetName์€ ๋ฌด์‹œ๋ฉ๋‹ˆ๋‹ค.

์„ ํƒ ํ•„๋“œ:

  • settings: Contrabass/Viola/OpenStack/ํด๋ง ์˜ต์…˜
  • secrets.contrabassEncryptKeySecretRef (๊ถŒ์žฅ)

๊ธฐ๋ณธ ์•”ํ˜ธํ™” ํ‚ค:

  • <namespace>/contrabass-encrypt-key Secret์˜ CONTRABASS_ENCRYPT_KEY๋ฅผ ์ž๋™ ์‚ฌ์šฉ
  • Secret์ด ์—†์œผ๋ฉด settings.contrabassEncryptKey๋ฅผ ์‚ฌ์šฉ

Secret ์˜ˆ์‹œ:

apiVersion: v1
kind: Secret
metadata:
  name: contrabass-encrypt-key
  namespace: multinic-system
type: Opaque
stringData:
  CONTRABASS_ENCRYPT_KEY: "conbaEncrypt2025"

Viola API ์ฃผ์†Œ:

  • spec.settings.violaEndpoint๊ฐ€ ์žˆ์œผ๋ฉด CR๋ณ„๋กœ ์‚ฌ์šฉ
  • ์—†์œผ๋ฉด Helm values์˜ operatorConfig.violaEndpoint(= VIOLA_ENDPOINT)๋ฅผ ์‚ฌ์šฉ

OpenstackConfig ์˜ˆ์‹œ:

apiVersion: multinic.example.com/v1alpha1
kind: OpenstackConfig
metadata:
  name: openstackconfig-sample
  namespace: multinic-system
spec:
  subnetIDs:
    - "8f0d5f5b-8f3f-4b2b-9c4c-8c9f7c36d1f2" # OpenStack subnet ID
    - "dae4f6ea-76ae-4e56-b3a5-87e6df94a574" # OpenStack subnet ID
  vmNames:
    - "08186d75-754e-449c-b210-c0ea822727a7" # OpenStack VM ID(UUID)
    - "c863944f-5cfe-4e05-805f-7522f3e9b080" # OpenStack VM ID(UUID)
    - "fbfd0e4d-a4bb-4769-bceb-46cb4b0dc3c5" # OpenStack VM ID(UUID)
  credentials:
    openstackProviderID: "66da2e07-a09d-4797-b9c6-75a2ff91381e" # Contrabass Provider ID
    projectID: "0d5f63c52fc94aeeb767e69790fa73c8" # OpenStack Project(Tenant) ID
    k8sProviderID: "f5861c22-b252-42b5-a0c5-cfb1d245c819" # K8s Provider ID (Viola ๋ผ์šฐํŒ… ํ‚ค)
  settings:
    contrabassEndpoint: "https://expert.bf.okestro.cloud" # Contrabass API base URL
    violaEndpoint: "http://viola-api.multinic-system.svc.cluster.local:8080" # Viola API base URL
    openstackPortAllowedStatuses:
      - "ACTIVE" # ๋Œ€์ƒ ํฌํŠธ ์ƒํƒœ
      - "DOWN" # ๋Œ€์ƒ ํฌํŠธ ์ƒํƒœ
    pollFastInterval: "10s" # ๋ณ€๊ฒฝ ์งํ›„ ๋น ๋ฅธ ํด๋ง ์ฃผ๊ธฐ
    pollSlowInterval: "2m" # ์•ˆ์ • ๊ตฌ๊ฐ„ ํด๋ง ์ฃผ๊ธฐ
  secrets:
    contrabassEncryptKeySecretRef:
      name: contrabass-encrypt-key # adminPw ๋ณตํ˜ธํ™” ํ‚ค Secret ์ด๋ฆ„
      key: CONTRABASS_ENCRYPT_KEY # Secret data key

๋™์ž‘ ํ๋ฆ„

์ž์„ธํ•œ ํ๋ฆ„๋„/์•„ํ‚คํ…์ฒ˜/๋‹จ๊ณ„ ์„ค๋ช…์€ docs/FLOW.md ์ฐธ๊ณ .

์•„ํ‚คํ…์ฒ˜

flowchart LR
  subgraph MGMT["MGMT Cluster"]
    OP[Multinic Operator]
    VA[Viola API]
    INV[Inventory API]
    CAPI[Contrabass API]
  end

  subgraph OS["OpenStack"]
    KS[Keystone]
    NE[Neutron]
    NO[Nova]
  end

  subgraph BIZ["Biz Cluster"]
    KAPI[K8s API Server]
    CR[MultiNicNodeConfig CR]
  end

  OP -->|Provider ์กฐํšŒ| CAPI
  OP -->|Token ์š”์ฒญ| KS
  OP -->|Port ์กฐํšŒ| NE
  OP -->|NodeName ์กฐํšŒ| NO
  OP -->|๋…ธ๋“œ๋ณ„ ์ธํ„ฐํŽ˜์ด์Šค POST| VA
  VA -->|CR ์ ์šฉ ์š”์ฒญ| KAPI
  KAPI -->|CR ์ƒ์„ฑ/๊ฐฑ์‹ | CR
  OP -->|์ƒํƒœ ์ €์žฅ| INV
Loading

์‹œํ€€์Šค

sequenceDiagram
    autonumber
    participant CR as OpenstackConfig
    participant OP as Operator
    participant CB as Contrabass (MGMT)
    participant KS as Keystone
    participant NE as Neutron
    participant NO as Nova
    participant VA as Viola API (MGMT)
    participant K8S as Biz K8s API

    CR->>OP: CR ์ƒ์„ฑ/์ˆ˜์ •
    OP->>CB: Provider ์กฐํšŒ
    CB-->>OP: Keystone URL + Admin ๊ณ„์ •
    OP->>KS: ํ† ํฐ ์š”์ฒญ
    KS-->>OP: ํ† ํฐ + ์นดํƒˆ๋กœ๊ทธ
    OP->>NE: Port ์กฐํšŒ (device_id=VM ID)
    OP->>NO: ์„œ๋ฒ„ ์ •๋ณด ์กฐํšŒ (nodeName)
    OP->>VA: ๋…ธ๋“œ๋ณ„ ์ธํ„ฐํŽ˜์ด์Šค POST
    VA->>K8S: CR ์ ์šฉ ์š”์ฒญ
    K8S-->>VA: ์ ์šฉ ๊ฒฐ๊ณผ
Loading
  1. OpenstackConfig CR ์ด๋ฒคํŠธ ๋ฐœ์ƒ
  2. Contrabass provider ์กฐํšŒ ๋ฐ adminPw ๋ณตํ˜ธํ™”
  3. Keystone ํ† ํฐ ๋ฐœ๊ธ‰ (์„œ๋น„์Šค ์นดํƒˆ๋กœ๊ทธ ํฌํ•จ)
  4. Neutron ์—”๋“œํฌ์ธํŠธ ๊ฒฐ์ • (์นดํƒˆ๋กœ๊ทธ ๋˜๋Š” settings)
  5. subnetIDs/subnetID/subnetName โ†’ subnet/network ์กฐํšŒ (CIDR/MTU ํ™•๋ณด)
  6. Neutron ํฌํŠธ ์กฐํšŒ (device_id == VM ID)
  7. Nova ์„œ๋ฒ„ ์กฐํšŒ๋กœ nodeName ๊ฒฐ์ • (metadata key > server name > vmID)
  8. ๋Œ€์ƒ subnet์— ํฌํ•จ๋œ ํฌํŠธ๋งŒ ์„ ๋ณ„
  9. ๋…ธ๋“œ๋ณ„ ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌ์„ฑ
  10. Viola API POST
  11. ํŒŒ์ผ ๊ธฐ๋ฐ˜ DB(JSON) ์ตœ์‹  ์ƒํƒœ upsert (k8sProviderID + nodeName ๊ธฐ์ค€)
  12. ๋ณ€๊ฒฝ ์งํ›„ ๋น ๋ฅธ ํด๋ง โ†’ ์•ˆ์ • ๊ตฌ๊ฐ„์€ ๋А๋ฆฐ ํด๋ง

๋‹จ๊ณ„ ์ƒ์„ธ

  • ์‹œ์ž‘ ์กฐ๊ฑด: OpenstackConfig CR ์ƒ์„ฑ/์ˆ˜์ • ๋˜๋Š” VM ํฌํŠธ ๋ถ€์ฐฉ
    • CR ์ƒ์„ฑ ์‹œ๊ฐ ์ดํ›„์— ์ƒ์„ฑ๋œ ํฌํŠธ๋งŒ ์ฒ˜๋ฆฌ (๊ธฐ์กด ํฌํŠธ ์ œ์™ธ)
  • OpenstackConfig ์ž…๋ ฅ ์˜๋ฏธ:
    • subnetIDs/subnetID/subnetName: ๋ฉ€ํ‹ฐ NIC ๋Œ€์ƒ ์„œ๋ธŒ๋„ท ์ง€์ •
    • vmNames: ํฌํŠธ ์กฐํšŒ ๋Œ€์ƒ VM ID(device_id ๋งค์นญ)
    • credentials.openstackProviderID: Contrabass ์กฐํšŒ์šฉ Provider ID
    • credentials.projectID: Keystone ํ† ํฐ ๋ฐœ๊ธ‰ ๋Œ€์ƒ Project ID
    • credentials.k8sProviderID: Viola ๋ผ์šฐํŒ… ํ‚ค(x-provider-id)
    • settings.violaEndpoint: Viola API POST ์ฃผ์†Œ
    • contrabassEncryptKey: adminPw ๋ณตํ˜ธํ™” ํ‚ค(Secret ๋˜๋Š” settings)
  • Token/Service Catalog:
    • Keystone ํ† ํฐ์€ Neutron/Nova ํ˜ธ์ถœ ์ธ์ฆ์— ํ•„์š”
    • Service Catalog๋Š” ์„œ๋น„์Šค๋ณ„ ์—”๋“œํฌ์ธํŠธ URL ๊ฒฐ์ •์— ์‚ฌ์šฉ
  • Port/NodeName ์กฐํšŒ:
    • Neutron์—์„œ VM ID ๊ธฐ๋ฐ˜ ํฌํŠธ๋ฅผ ์กฐํšŒ ํ›„ ์„œ๋ธŒ๋„ท/์ƒํƒœ ํ•„ํ„ฐ ์ ์šฉ
    • Nova ์กฐํšŒ๋กœ K8s nodeName ๊ฒฐ์ • (metadata key ์šฐ์„ , ์—†์œผ๋ฉด ์„œ๋ฒ„ ์ด๋ฆ„)

Viola API ์š”์ฒญ ์ŠคํŽ™

Operator๊ฐ€ OpenStack ํฌํŠธ ์ •๋ณด๋ฅผ ์ˆ˜์ง‘ํ•œ ๋’ค MGMT ํด๋Ÿฌ์Šคํ„ฐ์— ๋ฐฐํฌ๋œ Viola API๋กœ POST ์š”์ฒญ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค. Viola API ์ฃผ์†Œ๋Š” spec.settings.violaEndpoint๊ฐ€ ์šฐ์„ ์ด๋ฉฐ, ์—†์œผ๋ฉด Helm values์˜ operatorConfig.violaEndpoint๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

  • Endpoint: POST /v1/k8s/multinic/node-configs
  • Headers:
    • x-provider-id (string, required): OpenstackConfig.spec.credentials.k8sProviderID
  • Request Body: ๋…ธ๋“œ๋ณ„ MultiNicNodeConfig ๋ชฉ๋ก(JSON ๋ฐฐ์—ด)

์š”์ฒญ ํ•„๋“œ:

๊ตฌ๋ถ„ key type required description
Body nodeName string O K8s ๋…ธ๋“œ๋ช…
Body instanceId string O OpenStack VM ID
Body interfaces array O ๋…ธ๋“œ์— ๋ถ€์ฐฉ๋œ ์ธํ„ฐํŽ˜์ด์Šค ๋ชฉ๋ก
Body interfaces[].id int O 0~9
Body interfaces[].name string O multinic0~multinic9
Body interfaces[].macAddress string O MAC ์ฃผ์†Œ
Body interfaces[].address string O IPv4 ์ฃผ์†Œ
Body interfaces[].cidr string O ์„œ๋ธŒ๋„ท CIDR
Body interfaces[].mtu int O MTU

x-provider-id ๊ฐ’์€ OpenstackConfig.spec.credentials.k8sProviderID๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ (์š”์ฒญ ํ—ค๋” ํฌํ•จ, 2๊ฐœ ๋…ธ๋“œ/๊ฐ 3๊ฐœ ์ธํ„ฐํŽ˜์ด์Šค):

POST /v1/k8s/multinic/node-configs HTTP/1.1
Host: viola-api.example.com
Content-Type: application/json
x-provider-id: f5861c22-b252-42b5-a0c5-cfb1d245c819

[
  {
    "nodeName": "worker-1",
    "instanceId": "i-0123456789abcdef0",
    "interfaces": [
      {
        "id": 0,
        "name": "multinic0",
        "macAddress": "00:1A:2B:3C:4D:5E",
        "address": "192.168.1.100",
        "cidr": "192.168.1.0/24",
        "mtu": 1500
      },
      {
        "id": 1,
        "name": "multinic1",
        "macAddress": "00:1A:2B:3C:4D:5F",
        "address": "192.168.1.101",
        "cidr": "192.168.1.0/24",
        "mtu": 1500
      },
      {
        "id": 2,
        "name": "multinic2",
        "macAddress": "00:1A:2B:3C:4D:60",
        "address": "192.168.1.102",
        "cidr": "192.168.1.0/24",
        "mtu": 1500
      }
    ]
  },
  {
    "nodeName": "worker-2",
    "instanceId": "i-0fedcba9876543210",
    "interfaces": [
      {
        "id": 0,
        "name": "multinic0",
        "macAddress": "00:1A:2B:3C:4D:61",
        "address": "192.168.2.10",
        "cidr": "192.168.2.0/24",
        "mtu": 1500
      },
      {
        "id": 1,
        "name": "multinic1",
        "macAddress": "00:1A:2B:3C:4D:62",
        "address": "192.168.2.11",
        "cidr": "192.168.2.0/24",
        "mtu": 1500
      },
      {
        "id": 2,
        "name": "multinic2",
        "macAddress": "00:1A:2B:3C:4D:63",
        "address": "192.168.2.12",
        "cidr": "192.168.2.0/24",
        "mtu": 1500
      }
    ]
  }
]

Helm ๋ฐฐํฌ

์ฐจํŠธ ๊ฒฝ๋กœ: deployments/helm

Helm values์—๋Š” ์ด๋ฏธ์ง€ ์ •๋ณด๊ฐ€ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค. Viola API ์ฃผ์†Œ๋Š” CR์—์„œ ์ง€์ •ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ์—๋งŒ Helm values๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

๋ฐฐํฌ ์˜ˆ์‹œ:

helm upgrade --install multinic-operator deployments/helm \
  -n multinic-operator-system --create-namespace \
  --set image.repository=nexus.okestro-k8s.com:50000/multinic-operator \
  --set image.tag=dev-20260113062309 \
  --set image.pullSecrets[0].name=nexus-regcred

values.yaml ์ž‘์„ฑ ์˜ˆ์‹œ(ํ•„์ˆ˜):

image:
  repository: nexus.okestro-k8s.com:50000/multinic-operator
  tag: "dev-20260113062309"
  pullSecrets:
    - name: nexus-regcred
operatorConfig:
  # CR์—์„œ violaEndpoint๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์„ ๋•Œ๋งŒ ์‚ฌ์šฉ
  violaEndpoint: "https://viola-api.example.com"

values.yaml ์ž‘์„ฑ ์˜ˆ์‹œ(์„ ํƒ):

inventory:
  enabled: true
  service:
    port: 18081
persistence:
  enabled: false

spec.settings.violaEndpoint๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด CR๋ณ„๋กœ Viola API ์ฃผ์†Œ๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. CR์— ๊ฐ’์ด ์—†์œผ๋ฉด operatorConfig.violaEndpoint๋ฅผ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋ฐฐํฌ ์ˆœ์„œ ์˜ˆ์‹œ:

  1. deployments/helm/values.yaml ํŽธ์ง‘
  2. helm upgrade --install ... -f values.yaml๋กœ ๋ฐฐํฌ
  3. contrabass-encrypt-key Secret ์ƒ์„ฑ
  4. OpenstackConfig CR ์ ์šฉ

์˜คํ”„๋ผ์ธ ์ด๋ฏธ์ง€ ๋ฐฐํฌ

์‚ฌ๋‚ด๋ง์—์„œ ์ธํ„ฐ๋„ท ์ ‘๊ทผ์ด ๋ถˆ๊ฐ€๋Šฅํ•  ๋•Œ๋Š” ์ด๋ฏธ์ง€ tar๋ฅผ ์˜ฎ๊ฒจ์„œ ๋กœ๋“œํ•œ ๋’ค ์‚ฌ๋‚ด Nexus๋กœ pushํ•˜๊ณ  Helm values์— ๋ฐ˜์˜ํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฏธ์ง€ tar ๊ฒฝ๋กœ:

  • images/multinic-operator_dev-20260113062309.tar

์˜ˆ์‹œ:

# ์ด๋ฏธ์ง€ ๋กœ๋“œ
nerdctl load -i images/multinic-operator_dev-20260113062309.tar

# Nexus์— ํƒœ๊ทธ/ํ‘ธ์‹œ
nerdctl tag multinic-operator:dev-20260113062309 nexus.okestro-k8s.com:50000/multinic-operator:dev-20260113062309
nerdctl push nexus.okestro-k8s.com:50000/multinic-operator:dev-20260113062309

Interfaces API (์˜คํผ๋ ˆ์ดํ„ฐ ๋‚ด์žฅ)

์˜คํผ๋ ˆ์ดํ„ฐ๊ฐ€ ๊ณ„์‚ฐํ•œ ์ตœ์‹  ๋…ธ๋“œ๋ณ„ ์ธํ„ฐํŽ˜์ด์Šค ์Šค๋ƒ…์ƒท์„ ์กฐํšŒํ•˜๋Š” ๋‚ด๋ถ€ API์ž…๋‹ˆ๋‹ค. UI ์กฐํšŒ/๋””๋ฒ„๊น… ์šฉ๋„๋กœ ์‚ฌ์šฉํ•˜๋ฉฐ, ์‹ค์ œ ์ ์šฉ ์ƒํƒœ๋Š” Biz ํด๋Ÿฌ์Šคํ„ฐ์˜ MultiNicNodeConfig๊ฐ€ ๊ธฐ์ค€์ž…๋‹ˆ๋‹ค.

๋…ธ์ถœ API (3๊ฐœ):

  • ํด๋Ÿฌ์Šคํ„ฐ(Provider) ์š”์•ฝ ์กฐํšŒ: GET /v1/interfaces/providers
  • ํŠน์ • ํด๋Ÿฌ์Šคํ„ฐ ์ „์ฒด ๋…ธ๋“œ ์กฐํšŒ: GET /v1/interfaces/node-configs?providerId=...
    • providerId๋Š” k8sProviderID์ด๋ฉฐ ํ•„์ˆ˜
  • instanceId ๋‹จ๊ฑด ์กฐํšŒ: GET /v1/interfaces/node-configs/by-instance/{instanceId}?providerId=...
    • instanceId ํ•„์ˆ˜, providerId๋Š” ์ค‘๋ณต ๋ฐฉ์ง€๋ฅผ ์œ„ํ•ด ๊ถŒ์žฅ

Kubernetes Service:

  • Kustomize: inventory-service (port 18081, namespace system)
  • Helm: <release>-multinic-operator-inventory (port 18081)

์ฃผ์˜: ํŒŒ์ผ ๊ธฐ๋ฐ˜ ์ €์žฅ์†Œ์ด๋ฏ€๋กœ ์˜คํผ๋ ˆ์ดํ„ฐ๋Š” 1๊ฐœ replica๋กœ ์šด์˜ํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. ์ง€์† ์ €์žฅ์ด ํ•„์š”ํ•˜๋ฉด config/manager/manager.yaml์˜ emptyDir๋ฅผ PVC๋กœ ๊ต์ฒดํ•˜์‹ญ์‹œ์˜ค.

Swagger ๋ฌธ์„œ(Operator -> Viola POST ํŽ˜์ด๋กœ๋“œ):

  • GET /openapi.yaml
  • GET /docs (Swagger UI, CDN ์‚ฌ์šฉ)
    • POST(viola) + Interfaces API(์กฐํšŒ์šฉ)๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.
    • Swagger๋Š” ํ˜„์žฌ ์ ‘์†ํ•œ ์ฃผ์†Œ(ํ˜ธ์ŠคํŠธ/ํฌํŠธ)๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

Inventory API ํ™•์ธ ์˜ˆ์‹œ

kubectl -n multinic-operator-system port-forward svc/<inventory-service-name> 18081:18081
curl -s "http://127.0.0.1:18081/v1/interfaces/providers"
curl -s "http://127.0.0.1:18081/v1/interfaces/node-configs?providerId=<k8s-provider-id>"
curl -s "http://127.0.0.1:18081/v1/interfaces/node-configs/by-instance/<instanceId>?providerId=<k8s-provider-id>"

์ถ”์ฒœ ์กฐํšŒ ํ๋ฆ„:

  1. /v1/interfaces/providers๋กœ providerId ๋ชฉ๋ก ํ™•์ธ
  2. ํ•ด๋‹น providerId๋กœ /v1/interfaces/node-configs ์กฐํšŒ
  3. ํ•„์š”ํ•œ instanceId๋กœ /v1/interfaces/node-configs/by-instance/{instanceId} ์กฐํšŒ
    • ๋™์ผ instanceId๊ฐ€ ๊ฒน์น˜๋ฉด providerId๋ฅผ ์ถ”๊ฐ€

/v1/interfaces/providers ์‘๋‹ต ์˜ˆ์‹œ:

{
  "providers": [
    {
      "providerId": "f5861c22-b252-42b5-a0c5-cfb1d245c819",
      "nodeCount": 3,
      "updatedAt": "2026-01-12T02:51:32Z",
      "nodes": [
        {
          "providerId": "f5861c22-b252-42b5-a0c5-cfb1d245c819",
          "nodeName": "infra01",
          "instanceId": "ec4bdcc1-dbcc-4c5d-88a4-581a14beca2d",
          "interfaceCount": 3,
          "updatedAt": "2026-01-12T02:51:32Z"
        }
      ]
    }
  ]
}

๋…ธ๋“œ ์ƒ์„ธ ์‘๋‹ต ์˜ˆ์‹œ (/v1/interfaces/node-configs, /by-instance):

[
  {
    "providerId": "f5861c22-b252-42b5-a0c5-cfb1d245c819",
    "nodeName": "manager01",
    "instanceId": "08186d75-754e-449c-b210-c0ea822727a7",
    "config": {
      "nodeName": "manager01",
      "instanceId": "08186d75-754e-449c-b210-c0ea822727a7",
      "interfaces": [
        {
          "id": 0,
          "name": "multinic0",
          "macAddress": "fa:16:3e:aa:bb:cc",
          "address": "10.0.0.10",
          "cidr": "10.0.0.0/24",
          "mtu": 1450
        }
      ]
    },
    "lastConfigHash": "a69f59021cf9a8f7",
    "updatedAt": "2026-01-11T01:23:45Z"
  }
]

์‘๋‹ต ์ฝ”๋“œ:

  • 200 OK: ์กฐํšŒ ์„ฑ๊ณต
  • 400 Bad Request: nodeName ๋ˆ„๋ฝ ๋“ฑ ์š”์ฒญ ์˜ค๋ฅ˜
  • 404 Not Found: ์กฐ๊ฑด์— ๋งž๋Š” ๋ฐ์ดํ„ฐ ์—†์Œ
  • 503 Service Unavailable: inventory ์ €์žฅ์†Œ ๋น„ํ™œ์„ฑ

Status Conditions

OpenstackConfig์—๋Š” ๋™๊ธฐํ™” ์ƒํƒœ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” Conditions๊ฐ€ ๊ฐฑ์‹ ๋ฉ๋‹ˆ๋‹ค.

  • Ready: ๋™๊ธฐํ™” ์„ฑ๊ณต ์—ฌ๋ถ€
  • Degraded: ์˜ค๋ฅ˜ ๋ฐœ์ƒ ์—ฌ๋ถ€

์ถ”๊ฐ€ ์ƒํƒœ ํ•„๋“œ:

  • lastSyncedAt: ๋งˆ์ง€๋ง‰ ์„ฑ๊ณต ๋™๊ธฐํ™” ์‹œ๊ฐ(Reason=Synced/NoChange์ผ ๋•Œ ๊ฐฑ์‹ )
  • lastError: ๋งˆ์ง€๋ง‰ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€

์„ค์น˜/๋ฐฐํฌ (๊ธฐ๋ณธ)

make install
make deploy IMG=<registry>/multinic-operator:tag

์ƒ˜ํ”Œ CR ์ ์šฉ:

kubectl apply -k config/samples/

ํ…Œ์ŠคํŠธ์šฉ Viola API

Viola ๊ฐœ๋ฐœ API๊ฐ€ ์ค€๋น„๋˜๊ธฐ ์ „๊นŒ์ง€ ์•„๋ž˜ ํ…Œ์ŠคํŠธ์šฉ API๋ฅผ ๋ฐฐํฌํ•ด POST ์ˆ˜์‹  ๋ฐ CR ์ƒ์„ฑ๊นŒ์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

# ๋ผ์šฐํŒ… Secret(viola-api-routing)์„ ๋จผ์ € ์ค€๋น„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
kubectl apply -f config/test/viola-test-api.yaml

๋™์ž‘ ๋ฐฉ์‹:

  • POST payload๋ฅผ MultiNicNodeConfig๋กœ ๋ณ€ํ™˜
  • kubectl apply -f๋กœ CR ์ƒ์„ฑ/๊ฐฑ์‹ 

API ๋ฌธ์„œ(ํ…Œ์ŠคํŠธ์šฉ):

  • GET /healthz

    • Response: 200 OK + ok (plain text)
  • GET /openapi.yaml

    • OpenAPI ์ŠคํŽ™ (YAML)
  • GET /docs

    • Swagger UI (CDN ์‚ฌ์šฉ, ์˜คํ”„๋ผ์ธ์—์„œ๋Š” ๋™์ž‘ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Œ)
  • POST /v1/k8s/multinic/node-configs

    • Headers:
      • Content-Type: application/json
      • x-provider-id (required, ๋ผ์šฐํŒ… ํ‚ค)
    • Request Body: []NodeConfig (JSON ๋ฐฐ์—ด)
    • Response 200 OK:
      {"applied":3,"output":"multinicnodeconfig.multinic.io/node-1 configured"}
    • Response 400 Bad Request:
      • ์ž˜๋ชป๋œ JSON/ํ•„์ˆ˜ ํ•„๋“œ ๋ˆ„๋ฝ/๋ผ์šฐํŒ… ์„ค์ • ์˜ค๋ฅ˜
    • Response 500 Internal Server Error:
      • kubectl apply ์‹คํŒจ(๊ฒ€์ฆ ์‹คํŒจ/์ ‘์† ์‹คํŒจ ๋“ฑ)

๋ผ์šฐํŒ…(ํ…Œ์ŠคํŠธ์šฉ):

  • ์š”์ฒญ ํ—ค๋” x-provider-id๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋Œ€์ƒ ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
    • ๊ฐ’์€ OpenstackConfig.spec.credentials.k8sProviderID๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ROUTING_CONFIG์— ๋ผ์šฐํŒ… ํŒŒ์ผ์„ ์ง€์ •ํ•˜๋ฉด providerId๋ณ„๋กœ ๋Œ€์ƒ ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
  • ๋ชจ๋“œ:
    • ssh(ํ…Œ์ŠคํŠธ ๊ถŒ์žฅ): ์›๊ฒฉ Bastion์— SSH๋กœ ์ ‘์†ํ•ด kubectl apply.
    • local: kubeApiServer/kubeToken/kubeCaPath๋กœ ์›๊ฒฉ ํด๋Ÿฌ์Šคํ„ฐ์— kubectl apply.
  • ์ƒ˜ํ”Œ ํŒŒ์ผ: config/test/viola-routing.sample.yaml
  • strict: true๋กœ ์„ค์ •ํ•˜๋ฉด providerId๊ฐ€ ์—†๊ฑฐ๋‚˜ ๋งค์นญ ์‹คํŒจ ์‹œ 400์œผ๋กœ ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค.
  • SSH ๋ชจ๋“œ๋Š” sshpass๊ฐ€ ํ•„์š”ํ•˜๋ฉฐ ํ…Œ์ŠคํŠธ์šฉ Viola API ์ด๋ฏธ์ง€์—๋Š” ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

๋ผ์šฐํŒ… Secret ์ƒ์„ฑ ์˜ˆ์‹œ(ํ…Œ์ŠคํŠธ์šฉ):

# routing.yaml๊ณผ ca.crt๋ฅผ ์ค€๋น„ํ•œ ๋’ค Secret ์ƒ์„ฑ
kubectl -n multinic-system create secret generic viola-api-routing \
  --from-file=routing.yaml=./routing.yaml \
  --from-file=ca.crt=./ca.crt

๋ผ์šฐํŒ… ์˜ˆ์‹œ:

strict: true
targets:
  - providerId: "f5861c22-b252-42b5-a0c5-cfb1d245c819"
    mode: ssh
    namespace: "multinic-system"
    sshHost: "192.168.3.170"
    sshUser: "root"
    sshPort: 22
    sshPass: "cloud1234"
    kubectlPath: "kubectl"

์ด๋ฏธ์ง€ ๋นŒ๋“œ ์˜ˆ์‹œ:

nerdctl build -f Dockerfile.viola-test-api -t <registry>/multinic-viola-test-api:dev .

QA ํ…Œ์ŠคํŠธ ์ฒดํฌ๋ฆฌ์ŠคํŠธ

  • 3๊ฐœ ๋…ธ๋“œ์— 3๊ฐœ ํฌํŠธ์”ฉ ์ผ๊ด„ ์ถ”๊ฐ€ ํ›„ CR ๋ฐ˜์˜ ํ™•์ธ
  • ํฌํŠธ ์ œ๊ฑฐ ์‹œ CR ๋ฐ˜์˜ ํ™•์ธ
  • DOWN ํฌํŠธ ํ•„ํ„ฐ๋ง(openstackPortAllowedStatuses=ACTIVE) ๋™์ž‘ ํ™•์ธ
  • ์„ค์ • ๋ˆ„๋ฝ ์‹œ ConfigError ๋ฐœ์ƒ/๋ณต๊ตฌ ํ™•์ธ (contrabassEndpoint)
  • ์ค‘๋ณต ๋ณ€๊ฒฝ ์Šคํ‚ต(no changes detected) ํ™•์ธ
  • ์ž˜๋ชป๋œ VM ID/Project ID ์ž…๋ ฅ ์‹œ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ ํ™•์ธ
  • Viola API ์žฅ์• /timeout ์‹œ ์žฌ์‹œ๋„ ๋™์ž‘ ํ™•์ธ
  • Inventory API ์กฐํšŒ ์‘๋‹ต ํ™•์ธ
  • Interfaces API: providerId ๋ฏธ์ž…๋ ฅ ์‹œ 400 ํ™•์ธ
  • Interfaces API: ์ž˜๋ชป๋œ instanceId ์กฐํšŒ ์‹œ 404 ํ™•์ธ
  • Viola API: x-provider-id ๋ˆ„๋ฝ ์‹œ 400 ํ™•์ธ
  • Viola API: ์ •์ƒ payload POST 200 ํ™•์ธ
  • ๋ฉ€ํ‹ฐ ์„œ๋ธŒ๋„ท(test/test2) ๋™์‹œ ๋ถ€์ฐฉ ๋™์ž‘ ํ™•์ธ
  • worker/master ๋‹ค์ค‘ ๋…ธ๋“œ ๋™์‹œ ์ ์šฉ ํ™•์ธ
  • Viola API ๋ผ์šฐํŒ…(ssh) ์ ์šฉ ํ™•์ธ
  • OpenstackConfig ์ƒ์„ฑ ์‹œ๊ฐ ์ดํ›„ ํฌํŠธ๋งŒ ์ฒ˜๋ฆฌ๋˜๋Š”์ง€ ํ™•์ธ
  • ๋…ธ๋“œ๋‹น ์ธํ„ฐํŽ˜์ด์Šค 10๊ฐœ ์ดˆ๊ณผ ์‹œ 10๊ฐœ๋งŒ ์ „์†ก( multinic0~9 ) ํ™•์ธ
  • subnetIDs ์ˆœ์„œ๋Œ€๋กœ ์ธํ„ฐํŽ˜์ด์Šค ๋งคํ•‘๋˜๋Š”์ง€ ํ™•์ธ
  • subnetIDs ์ˆœ์„œ ๋ณ€๊ฒฝ ์‹œ ์ตœ์ข… ์ธํ„ฐํŽ˜์ด์Šค ์ˆœ์„œ๊ฐ€ MAC ๊ธฐ์ค€์œผ๋กœ ์œ ์ง€๋จ(ํ˜„ ๋™์ž‘)
  • OpenstackConfig์—์„œ vmNames ์ œ๊ฑฐ ์‹œ ๊ธฐ์กด Inventory/CR ์‚ญ์ œ๋Š” ํ•˜์ง€ ์•Š์Œ(ํ˜„ ๋™์ž‘)
  • Viola API ์—”๋“œํฌ์ธํŠธ ์˜ค๋ฅ˜ ์‹œ Ready/Degraded ๊ฐฑ์‹  ํ™•์ธ
  • Viola API ์žฅ์•  ๋ณต๊ตฌ ํ›„ ์ •์ƒ ๋™๊ธฐํ™” ํ™•์ธ
  • ์ค‘๋ณต OpenstackConfig ์ƒ์„ฑ ์‹œ baseline ์ด์ „ ํฌํŠธ๋Š” ์ „์†ก๋˜์ง€ ์•Š์Œ(ํ˜„ ๋™์ž‘)
  • DOWN ํฌํŠธ๊ฐ€ ACTIVE๋กœ ์ „ํ™˜๋˜๋ฉด ์ •์ƒ ์ „์†ก๋จ์„ ํ™•์ธ
  • ์˜คํผ๋ ˆ์ดํ„ฐ ์žฌ์‹œ์ž‘ ํ›„ Inventory๊ฐ€ ์žฌ๋™๊ธฐํ™”๋จ์„ ํ™•์ธ

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages