FEATURE: Add zk deploy command#42
Conversation
| writeIfNotZero(&sb, "tickTime", cfg.TickTime) | ||
| writeIfNotZero(&sb, "initLimit", cfg.InitLimit) | ||
| writeIfNotZero(&sb, "syncLimit", cfg.SyncLimit) | ||
| writeIfNotEmpty(&sb, "dataDir", fmt.Sprintf("%s/zk%d", cfg.DataDir, server.MyID)) | ||
| writeIfNotEmpty(&sb, "dataLogDir", cfg.DataLogDir) |
There was a problem hiding this comment.
zoo.cfg파일에 이 속성 명시하지 않아도 ZK 서버 구동에 문제 없나요?
(내부적으로 어떠한 default 값을 사용하게 되나요?)
mergeConfig 이후 (또는 mergeConfig 내부에서) cfg 각 값에 대한 validation이 필요해 보입니다.
필수 속성이 명시되지 않은 경우 default 값을 채워 넣거나, 에러 발생시키는 것이 좋겠습니다.
그리고 나서, 실제 설정 파일을 구성할 때는 별도의 value 확인 없이 그대로 쓰면 됩니다.
There was a problem hiding this comment.
zoo.cfg 파일에 명시하지 않았을 때 문제가 되는 옵션들이 존재합니다.
옵션 설명
| 옵션 | 내부 기본값 | 설명 |
|---|---|---|
| clientPort | 없음 | 명시 필수, 미지정 시 시작 실패 |
| dataDir | 없음 | 명시 필수, 미지정 시 시작 실패 |
| tickTime | 3000ms | 미지정해도 시작 됨 |
| initLimit | 없음 | 클러스터 모드에서 미지정 시 quorum 형성 실패 |
| syncLimit | 없음 | 클러스터 모드에서 미지정 시 follower 동기화 실패 |
| dataLogDir | dataDir로 사용됨 | 별도 설정 권장 |
클러스터 모드를 강제하고 있어 위 옵션을 minimum configuration으로 확인했고, 다음과 같이 처리하려고 합니다.
clientPort: address에서 자동 추출 (현재 구현)dataDir,initLimit,syncLimit: 필수 값으로 검증 (미지정 시 에러)tickTime,dataLogDir: 선택 (ZK 기본값 사용)
추가로 검증해야 할 옵션이 있을까요?
There was a problem hiding this comment.
path 관련 설정의 경우 사용자가 필수로 입력하도록 해도 문제 없을 것 같은데,
initLimit, syncLimit 같은 설정은 사용자가 어떤 값을 사용해야 할지 알기 어려울 것입니다.
필수로 입력하도록 하되 별도로 가이드 문서를 제공하거나, 미입력 시 arcusctl 수준에서 기본값을 정의하는 것이 좋겠습니다.
참고사항으로, 현재 사용 중인 전체 설정은 아래와 같습니다.
https://github.com/naver/arcus-zookeeper/blob/arcus-3.5.9/conf/zoo_sample.cfg
There was a problem hiding this comment.
아래와 같이 zk-sample-topology.yml 파일을 만들어서 프로젝트에서 관리하는 형태로 제공해도 좋을 것 같습니다.
zk-sample-topology.yml example
# For more configuration options, see:
# https://zookeeper.apache.org/doc/r3.5.9/zookeeperAdmin.html#sc_configuration
name: my-ensemble # required
path: /home/arcus/zookeeper # required
servers:
- myid: 1 # required
address: zk1:2181:2888:3888 # required (host:clientPort:quorumPort:electionPort)
config: # optional - per-node override
data_log_dir: /data/zk1-txlog
- myid: 2
address: zk2:2181:2888:3888
- myid: 3
address: zk3:2181:2888:3888
global_config:
# optional (default: 2000)
tick_time: 2000
# optional (default: 10) - ticks for follower to sync to leader
init_limit: 10
# optional (default: 5) - ticks between request and ack
sync_limit: 5
# required
data_dir: /var/lib/zk/data
# optional (default: data_dir) - dedicated disk recommended
data_log_dir: /var/lib/zk/datalog
# optional - other ZK options (string values only)
properties:
maxClientCnxns: "60"
autopurge.snapRetainCount: "10"
autopurge.purgeInterval: "24"위 예시 파일 기준에 맞춰 코드 구성(필수 및 기본 값 처리)을 변경하겠습니다.
c1bfb73 to
90b7f45
Compare
동작 흐름 정리 |
oliviarla
left a comment
There was a problem hiding this comment.
리뷰 완료입니다. cluster deploy 구현 시에 여기와 유사한 형태가 될 것 같아서 미리 구조나 용어 차원에서 리뷰를 진행했습니다.
| if store.ZKExists(topo.Name) { | ||
| return nil, nil, fmt.Errorf("ZooKeeper ensemble %q already exists", topo.Name) | ||
| } |
There was a problem hiding this comment.
LoadZK 직후에 이부분을 가장 먼저 수행할 수 있나요?
| ) | ||
|
|
||
| func Deploy(version string, topologyPath string) error { | ||
| topo, rawData, err := prepare(topologyPath) |
There was a problem hiding this comment.
함수와 반환 타입을 보고 어떤 작업을 하게 되는지 알기가 조금 어려운데, 네이밍이나 변수명을 좀더 읽기 쉽게 만들 수 있을까요?
| return topo, rawData, nil | ||
| } | ||
|
|
||
| func installAll(topo *topology.ZKTopology, version string, localTarPath string) ([]topology.ZKServer, error) { |
There was a problem hiding this comment.
이 메서드는 install.go에 두지 않는 이유가 무엇인가요?
| return input == "y" || input == "yes" | ||
| } | ||
|
|
||
| func validate(topo *topology.ZKTopology) error { |
There was a problem hiding this comment.
이 메서드는 topology 패키지 내에 있는게 낫지 않나요?
| host, clientPort, _, _ := s.ParseAddress() | ||
| addrs[i] = fmt.Sprintf("%s:%s", host, clientPort) | ||
| } | ||
| return strings.Join(addrs, ",") |
| return fmt.Errorf("write myid on %s: %w", host, err) | ||
| } | ||
|
|
||
| cfgContent := buildZKConfig(server, topo) |
There was a problem hiding this comment.
buildZKConfig 에서 ZK는 빼도 되지 않을까요? (zk package 하위이므로)
buildZKConfig에서 나온 결과의 변수명도 적절하게 일치화하면 좋겠습니다.
buildZKDynamicConfig도 마찬가지로 살펴주세요.
| startCmd := fmt.Sprintf("%s/bin/zkServer.sh start %s/zoo.cfg", topo.Path, confDir) | ||
| if err := ssh.Run(host, startCmd); err != nil { | ||
| return fmt.Errorf("start ZK on %s: %w", host, err) | ||
| } |
There was a problem hiding this comment.
deploy 명령에서 start까지 시킬지 말지는 미리 결정해야 했던 사항인데요, 설계에서 자세히 적혀있지 않아 이렇게 구현하신 것 같습니다.
tiup 에서는 deploy 명령에서 start까지 하지 않고 있고, 여기서도 start하고 quorum 형성 확인하는 작업을 줄이면 install.go 파일의 의미가 좀 더 명확해질 것 같습니다. (현재는 install.go 에서 start까지 하고 있어 조금 어색합니다.)
@namsic @jhpark816 혹시 다른 의견 있다면 코멘트 남겨주세요.
| localPath := filepath.Join(dir, filename) | ||
|
|
||
| if _, err := os.Stat(localPath); err == nil { | ||
| fmt.Printf("Using cached file: %s\n", localPath) |
There was a problem hiding this comment.
cached -> existing 표현이 낫지 않을까요?
🔗 Related Issue
⌨️ What I did
arcusctl zk deploy <version> <topology.yml >명령어를 구현했습니다.동작 흐름
topology.yml파싱 및 검증~/.arcusctl/images/zookeeper)에서 ZK tar 파일 확인, 없으면wget으로 다운로드~/.arcusctl/clusters/zk/<name>/) 저장에러 처리
관련 파일
internal/zk/deploy.go: 전체 배포 흐름internal/zk/validate.go: topology 검증internal/zk/config.go: zoo.cfg / zoo.cfg.dynamic 생성internal/zk/download.go: ZK tar.gz 다운로드internal/zk/install.go: 노드별 설치internal/zk/znode.go: ZK 연결 문자열 생성참고