ONTAP REST API로 클러스터 구성 — 콘솔 없이 끝까지

ONTAP REST API로 클러스터를 세우고 SVM·볼륨·export policy까지 만들어봤습니다. 콘솔에 한 글자도 입력하지 않고 끝냈습니다.

계기는 단순했습니다. 가상 랩에서 ONTAP 콘솔에 키 입력이 안 들어가는 상황이 있었고, cluster setup 마법사를 넘길 방법이 없었습니다. 그런데 첫 부팅 화면을 자세히 보니 이런 안내가 있었습니다.

******************************************************************************
PLEASE LOGIN TO SYSTEM MANAGER AND SETUP CLUSTER USING.
https://192.168.126.135

FOR CONFIGURING A 2-NODE CLUSTER PLEASE REFER TO THE DOCUMENTATION
BEFORE PROCEEDING WITH CLUSTER SETUP
******************************************************************************

노드가 이미 DHCP로 IP를 받고 관리 인터페이스를 열어둔 상태였습니다. 콘솔이 유일한 경로가 아니었던 겁니다. 이 글은 거기서부터 API만으로 끝까지 간 기록입니다.

이 글의 실습 환경

이 글은 ONTAP Simulator 9.17.1 기반 가상 랩에서 직접 실행하고 그 출력을 근거로 작성했습니다. 실제 장비(FAS/AFF)와는 지원 기능·성능·하드웨어 동작에서 차이가 있으며, ONTAP 버전에 따라 API 스키마도 달라집니다.

1. precluster 상태에서는 대부분의 API가 막힌다

클러스터를 세우기 전 노드에 그냥 GET 을 날려보면 이렇게 돌아옵니다.

$ curl -sk -u "admin:" https://192.168.126.135/api/cluster

{
  "error": {
    "message": "Only POST/OPTIONS on /api/cluster, GET/HEAD/OPTIONS on
                /api/cluster/nodes, or calls on /api/cluster/jobs are
                available in precluster.",
    "code": "9241607"
  }
}
HTTP: 405

이 에러 메시지가 사실상 설명서입니다. precluster 상태에서 쓸 수 있는 것이 정확히 나열돼 있습니다 — POST /api/cluster 로 클러스터를 만들거나, GET /api/cluster/nodes 로 노드를 보거나, job을 조회하거나.

401 이 아니라 405 라는 점도 중요합니다. 인증은 이미 통과했다는 뜻입니다. 초기 상태의 admin 계정은 비밀번호가 비어 있습니다.

2. 클러스터 생성 — 스키마에서 세 번 막혔다

POST /cluster 문서를 보고 요청을 만들었는데, 순서대로 세 번 거부당했습니다. 거부 메시지가 매번 다음 단서를 줬습니다.

내가 보낸 것돌아온 응답
nodes[].management_interface.ip.netmaskUnexpected argument "nodes[0].management_interface.ip.netmask"
netmask를 "255.255.255.0" 으로같은 위치에서 계속 거부
최상위 management_interface, netmask "24"The IP address, netmask, and gateway must all be provided

정리하면 세 가지였습니다.

  • 관리 인터페이스는 노드 밑이 아니라 최상위에 하나만 둔다
  • netmask는 "255.255.255.0" 이 아니라 프리픽스 문자열 "24"
  • address·netmask·gateway 셋을 모두 줘야 한다. 하나라도 빠지면 거부

그리고 single_node_clustercreate_recommended_aggregates본문이 아니라 쿼리 파라미터입니다. 이걸 본문에 넣으면 조용히 무시됩니다.

curl -sk -u "admin:" -X POST "https://192.168.126.135/api/cluster?single_node_cluster=true&create_recommended_aggregates=true" -H "Content-Type: application/json" -d '{
    "name": "capcluster",
    "password": "********",
    "dns_domains": ["lab.example.com"],
    "name_servers": ["192.168.126.40"],
    "management_interface": {
      "ip": {
        "address": "192.168.126.150",
        "netmask": "24",
        "gateway": "192.168.126.2"
      }
    }
  }'

HTTP: 202
{ "job": { "uuid": "a5678faa-a252-11f1-9ad0-000c292e85fe" } }

202 Accepted 는 “접수했다”이지 “끝났다”가 아닙니다. 클러스터 생성은 노드 재부팅을 동반하므로 몇 분 걸립니다. 반환된 job UUID로 진행 상황을 볼 수 있습니다.

결과 — 관리 IP가 요청한 값이 아니다

재부팅이 끝나고 확인해보니 클러스터는 정상이었습니다.

여기서부터 URL의 ...앞에서 쓴 관리 주소를 줄여 적은 것입니다. 그대로 복사하면 동작하지 않으니 자기 환경의 주소(https://<관리 IP>)로 바꿔 넣으세요.

$ curl -sk -u "admin:***" "https://.../api/cluster/nodes?fields=name,serial_number,model,state"

"name": "capcluster-01"
"serial_number": "4082368-50-7"
"model": "SIMBOX"
"state": "up"

그런데 관리 LIF를 192.168.126.150 으로 요청했는데 실제로는 기존 DHCP 주소로 응답했습니다.

$ curl -sk -u "admin:***" ".../api/network/ip/interfaces?services=management_core"

"name": "capcluster-01_mgmt_auto"
"address": "192.168.126.135"

이름이 _mgmt_auto 로 끝나는 자동 생성 LIF가 기존 주소를 유지하고 있었습니다. 제가 준 게이트웨이(192.168.126.2)가 VMnet8 실제 게이트웨이와 달랐을 가능성이 있는데, 이 부분은 확인하지 못했습니다. 다만 실무적으로 기억할 점은 분명합니다 — 요청한 IP가 아니라 실제로 붙은 IP를 조회해서 확인해야 합니다.

3. ⭐ 라이선스를 먼저 넣지 않으면 SVM 생성이 통째로 롤백된다

여기가 이 글에서 가장 중요한 부분입니다.

클러스터가 섰으니 NFS용 SVM을 만들려고 했습니다. 스키마 문제 세 개를 더 넘긴 뒤(root_volume 불가, home_port 안에 node 불가, services 지정 불가) 드디어 요청이 통과했는데 — 이번엔 500이 났습니다.

HTTP: 500
{
  "error": {
    "message": "[Job 30] Job failed: You do not have a valid license for \"NFS\".
                Reason: Package \"NFS\" is not licensed in the cluster.",
    "uuid": "f322650a-a253-11f1-9ad0-000c292e85fe"
  }
}

문제는 SVM이 부분적으로라도 남지 않았다는 점입니다.

$ curl -sk -u "admin:***" ".../api/svm/svms?fields=name,state"
"num_records": 0

SVM 생성은 job으로 처리되고, 중간에 실패하면 전체가 롤백됩니다. LIF까지 만들어졌다가 NFS 활성화에서 막히자 통째로 되돌아갔습니다. “일단 만들고 라이선스는 나중에”가 통하지 않습니다.

순서를 바꿔 라이선스를 먼저 넣었습니다. 시뮬레이터 라이선스 파일에서 해당 노드 시리얼 그룹의 28자 키를 뽑아 배열로 보냅니다.

curl -sk -u "admin:***" -X POST ".../api/cluster/licensing/licenses" -H 'Content-Type: application/json' -d '{"keys":["YVUCRRRRYVHXCFABGAAAAAAAAAAA","MBXNQRRRYVHXCFABGAAAAAAAAAAA", ...]}'

HTTP: 201

12개가 한 번에 들어갔습니다.

$ curl -sk -u "admin:***" ".../api/cluster/licensing/licenses?fields=name"

cifs      fcp        flexclone   insight_balance
iscsi     nfs        snaplock    snapmanagersuite
snapmirror  snapprotectapps  snaprestore  snapvault

4. SVM 생성 — 문서에 없으면 거부 메시지를 읽는다

라이선스가 들어간 뒤 같은 요청을 다시 보내니 통과했습니다. 여기까지 오면서 부딪힌 POST /svm/svms 스키마 제약을 정리하면 이렇습니다.

시도결과
root_volume 지정Unexpected argument "root_volume" — 루트 볼륨은 자동 생성된다
home_port 안에 nodeUnexpected argument "...home_port.node"포트 이름만 받는다
ip_interfaces[].servicescannot be set in this operation기본 서비스로 생성된다
{
  "name": "nfs_svm",
  "language": "c.utf_8",
  "nfs": { "enabled": true },
  "aggregates": [ { "name": "capcluster_01_FC_1" } ],
  "ip_interfaces": [
    {
      "name": "nfs_lif1",
      "ip": { "address": "192.168.126.160", "netmask": "24" },
      "location": {
        "broadcast_domain": { "name": "Default" },
        "home_port": { "name": "e0c" }
      }
    }
  ]
}

HTTP: 201

SVM·데이터 LIF·NFS 활성화가 한 번의 요청으로 끝났습니다. CLI로 하면 서너 개 명령으로 나뉘는 작업입니다.

5. 볼륨과 export policy

볼륨은 nas.path 로 junction을, nas.security_style 로 스타일을 지정합니다.

POST /api/storage/volumes
{
  "name": "nfs_vol1",
  "svm": { "name": "nfs_svm" },
  "aggregates": [ { "name": "capcluster_01_FC_1" } ],
  "size": "1GB",
  "nas": { "path": "/nfs_vol1", "security_style": "unix" }
}

HTTP: 201

여기서 갓 만든 SVM의 export policy 상태를 확인해봤습니다. 루트 볼륨과 데이터 볼륨 둘 다 default 정책이 붙어 있는데 — 그 정책에 룰이 하나도 없습니다.

$ curl -sk -u "admin:***" ".../api/protocols/nfs/export-policies?svm.name=nfs_svm&fields=name,rules"

"name": "default"
"num_records": 1
# rules 배열 자체가 없다

이 상태로 마운트하면 access denied by server 가 납니다. 그 증상과 원인은 NFS 마운트가 “access denied by server”로 거부될 때에서 자세히 다뤘습니다. API로 만들어도 똑같은 기본 상태로 시작한다는 것이 여기서 확인됩니다.

POST /api/protocols/nfs/export-policies/12884901889/rules
{
  "clients":   [ { "match": "0.0.0.0/0" } ],
  "ro_rule":   ["any"],
  "rw_rule":   ["any"],
  "superuser": ["any"],
  "protocols": ["nfs"]
}

HTTP: 201  →  index: 1

랩이니까 0.0.0.0/0 을 썼습니다. 운영에서는 접근하는 서버나 대역을 지정하는 것이 원칙입니다.

6. 프로토콜 버전은 기본이 전부 켜져 있다

만들어진 NFS 서버를 확인해보면 이렇습니다.

"enabled":     true
"v3_enabled":  true
"v40_enabled": true
"v41_enabled": true

기본 셋업은 v3와 v4가 모두 활성입니다. v3만 쓰는 환경이라면 명시적으로 꺼야 합니다.

PATCH /api/protocols/nfs/services/{svm.uuid}
{ "protocol": { "v40_enabled": false, "v41_enabled": false } }

HTTP: 200

NFS 서비스의 리소스 키가 SVM의 UUID와 같다는 점을 알아두면 편합니다. 별도 ID를 찾을 필요가 없습니다.

정리 — API로 갈 때 기억할 것

지점내용
precluster405 응답이 쓸 수 있는 엔드포인트를 알려준다. 401 이 아니면 인증은 된 것
netmask"255.255.255.0" 이 아니라 프리픽스 "24"
관리 인터페이스address·netmask·gateway 셋 모두 필수. 최상위에 하나만
쿼리 vs 본문single_node_cluster, create_recommended_aggregates쿼리 파라미터
라이선스SVM보다 먼저. 나중에 하면 SVM 생성이 통째로 롤백된다
202 응답접수됐을 뿐. job으로 완료를 확인해야 한다
결과 확인요청한 값이 아니라 실제로 만들어진 값을 조회해서 본다

API 스키마에서 막힐 때마다 거부 메시지가 다음 단서를 줬습니다. Unexpected argument 는 필드 위치를, must all be provided 는 빠진 항목을 정확히 짚어줍니다. 문서를 먼저 보되, 막히면 응답을 읽는 편이 빠를 때가 많습니다.

이 시리즈의 앞선 글들도 같은 구조입니다 — 2노드 클러스터에서 HA가 안 켜질 때는 에러가 노드 수를 탓했지만 실제 원인은 디스크 배선이었고, CIFS 조인이 LDAP Error로 실패할 때는 진짜 원인이 역방향 DNS였습니다.

댓글 남기기