Information in this document may be out of date

This document has an older update date than the original, so the information it contains may be out of date. If you're able to read English, see the English version for the most up-to-date information: Running ZooKeeper, A Distributed System Coordinator

๋ถ„์‚ฐ ์‹œ์Šคํ…œ ์ฝ”๋””๋„ค์ดํ„ฐ ZooKeeper ์‹คํ–‰ํ•˜๊ธฐ

์ด ํŠœํ† ๋ฆฌ์–ผ์€ ์•„ํŒŒ์น˜ ZooKeeper ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค์—์„œ ์Šคํ…Œ์ดํŠธํ’€์…‹๊ณผ PodDisruptionBudget๊ณผ ํŒŒ๋“œ์•ˆํ‹ฐ์–ดํ”ผ๋‹ˆํ‹ฐ(PodAntiAffinity)๋ฅผ ์ด์šฉํ•œ Apache Zookeeper ์‹คํ–‰์„ ์„ค๋ช…ํ•œ๋‹ค.

์‹œ์ž‘ํ•˜๊ธฐ ์ „์—

์ด ํŠœํ† ๋ฆฌ์–ผ์„ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ๋‹ค์Œ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ๊ฐœ๋…์— ์นœ์ˆ™ํ•ด์•ผ ํ•œ๋‹ค.

๋ฐ˜๋“œ์‹œ ์ตœ์†Œํ•œ 4๊ฐœ์˜ ๋…ธ๋“œ๊ฐ€ ์žˆ๋Š” ํด๋Ÿฌ์Šคํ„ฐ๊ฐ€ ํ•„์š”ํ•˜๋ฉฐ, ๊ฐ ๋…ธ๋“œ๋Š” ์ ์–ด๋„ 2 ๊ฐœ์˜ CPU์™€ 4 GiB ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๋‹ค. ์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ ํด๋Ÿฌ์Šคํ„ฐ ๋…ธ๋“œ๋ฅผ ํ†ต์ œ(cordon)ํ•˜๊ณ  ๋น„์šฐ๊ฒŒ(drain) ํ•  ๊ฒƒ์ด๋‹ค. ์ด๊ฒƒ์€ ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ์ข…๋ฃŒํ•˜์—ฌ ๋…ธ๋“œ์˜ ๋ชจ๋“  ํŒŒ๋“œ๋ฅผ ์ถ•์ถœ(evict)ํ•˜๋Š” ๊ฒƒ์œผ๋กœ, ๋ชจ๋“  ํŒŒ๋“œ๋Š” ์ž„์‹œ๋กœ ์–ธ์Šค์ผ€์ค„๋œ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค. ์ด ํŠœํ† ๋ฆฌ์–ผ์„ ์œ„ํ•ด ์ „์šฉ ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ์ด์šฉํ•˜๊ฑฐ๋‚˜, ๋‹ค๋ฅธ ํ…Œ๋„ŒํŠธ์— ๊ฐ„์„ญ์„ ํ•˜๋Š” ํ˜ผ๋ž€์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด ํŠœํ† ๋ฆฌ์–ผ์€ ํด๋Ÿฌ์Šคํ„ฐ๊ฐ€ ๋™์ ์œผ๋กœ ํผ์‹œ์Šคํ„ดํŠธ๋ณผ๋ฅจ์„ ํ”„๋กœ๋น„์ €๋‹ํ•˜๋„๋ก ๊ตฌ์„ฑํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•œ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ์„ค์ •๋˜์–ด ์žˆ์ง€ ์•Š๋‹ค๋ฉด ํŠœํ† ๋ฆฌ์–ผ์„ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ์ˆ˜๋™์œผ๋กœ 3๊ฐœ์˜ 20 GiB ๋ณผ๋ฅจ์„ ํ”„๋กœ๋น„์ €๋‹ํ•ด์•ผ ํ•œ๋‹ค.

๋ชฉ์ 

์ด ํŠœํ† ๋ฆฌ์–ผ์„ ๋งˆ์น˜๋ฉด ๋‹ค์Œ์— ๋Œ€ํ•ด ์•Œ๊ฒŒ ๋œ๋‹ค.

  • ์–ด๋–ป๊ฒŒ ์Šคํ…Œ์ดํŠธํ’€์…‹์„ ์ด์šฉํ•˜์—ฌ ZooKeeper ์•™์ƒ๋ธ”์„ ๋ฐฐํฌํ•˜๋Š”๊ฐ€.
  • ์–ด๋–ป๊ฒŒ ์•™์ƒ๋ธ”์„ ์ผ๊ด€๋˜๊ฒŒ ์„ค์ •ํ•˜๋Š”๊ฐ€.
  • ์–ด๋–ป๊ฒŒ ZooKeeper ์„œ๋ฒ„ ๋””ํ”Œ๋กœ์ด๋จผํŠธ๋ฅผ ์•™์ƒ๋ธ” ์•ˆ์—์„œ ํผ๋œจ๋ฆฌ๋Š”๊ฐ€.
  • ์–ด๋–ป๊ฒŒ PodDisruptionBudget์„ ์ด์šฉํ•˜์—ฌ ๊ณ„ํš๋œ ์ ๊ฒ€ ๊ธฐ๊ฐ„ ๋™์•ˆ ์„œ๋น„์Šค ๊ฐ€์šฉ์„ฑ์„ ๋ณด์žฅํ•˜๋Š”๊ฐ€.

ZooKeeper

์•„ํŒŒ์น˜ ZooKeeper๋Š” ๋ถ„์‚ฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์œ„ํ•œ ๋ถ„์‚ฐ ์˜คํ”ˆ ์†Œ์Šค ์ฝ”๋””๋„ค์ด์…˜ ์„œ๋น„์Šค์ด๋‹ค. ZooKeeper๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๊ณ  ์“ฐ๊ณ  ๊ฐฑ์‹ ์„ ์ง€์ผœ๋ณด๋„๋ก ํ•œ๋‹ค. ๋ฐ์ดํ„ฐ๋Š” ํŒŒ์ผ์‹œ์Šคํ…œ์ฒ˜๋Ÿผ ๊ณ„์ธต์ ์œผ๋กœ ๊ด€๋ฆฌ๋˜๊ณ  ์•™์ƒ๋ธ”(ZooKeeper ์„œ๋ฒ„์˜ ์ง‘ํ•ฉ) ๋‚ด์— ๋ชจ๋“  ZooKeeper์„œ๋ฒ„์— ๋ณต์ œ๋œ๋‹ค. ๋ฐ์ดํ„ฐ์— ๋ชจ๋“  ์—ฐ์‚ฐ์€ ์›์ž์ ์ด๊ณ  ์ˆœ์ฒ˜์ ์œผ๋กœ ์ผ๊ด€๋œ๋‹ค. ZooKeeper๋Š” Zab ํ•ฉ์˜ ํ”„๋กœํ† ์ฝœ์„ ์ด์šฉํ•˜์—ฌ ์•™์ƒ๋ธ” ๋‚ด์— ๋ชจ๋“  ์„œ๋ฒ„์— ๊ฑธ์ณ ์ƒํƒœ ๋จธ์‹ ์„ ๋ณต์ œํ•˜์—ฌ ์ด๋ฅผ ๋ณด์žฅํ•œ๋‹ค.

์•™์ƒ๋ธ”์€ ๋ฆฌ๋” ์„ ์ถœ์„ ์œ„ํ•ด Zab ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•˜๊ณ , ๋ฆฌ๋” ์„ ์ถœ๊ณผ ์„ ๊ฑฐ๊ฐ€ ์™„๋ฃŒ๋˜๊ธฐ ์ „๊นŒ์ง€ ์•™์ƒ๋ธ”์€ ๋ฐ์ดํ„ฐ๋ฅผ ์“ธ ์ˆ˜ ์—†๋‹ค. ์™„๋ฃŒ๋˜๋ฉด ์•™์ƒ๋ธ”์€ Zab์„ ์ด์šฉํ•˜์—ฌ ํ™•์ธํ•˜๊ณ  ํด๋ผ์ด์–ธํŠธ์— ๋ณด์ด๋„๋ก ๋ชจ๋“  ์“ฐ๊ธฐ๋ฅผ ์ฟผ๋Ÿผ(quorum)์— ๋ณต์ œํ•œ๋‹ค. ๊ฐ€์ค‘์น˜์žˆ๋Š” ์ฟผ๋Ÿผ๊ณผ ๊ด€๋ จ ์—†์ด, ์ฟผ๋Ÿผ์€ ํ˜„์žฌ ๋ฆฌ๋”๋ฅผ ํฌํ•จํ•˜๋Š” ์•™์ƒ๋ธ”์˜ ๋Œ€๋‹ค์ˆ˜ ์ปดํฌ๋„ŒํŠธ์ด๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์•™์ƒ๋ธ”์ด 3๊ฐœ ์„œ๋ฒ„์ธ ๊ฒฝ์šฐ, ๋ฆฌ๋”์™€ ๋‹ค๋ฅธ ์„œ๋ฒ„๋กœ ์ฟผ๋Ÿผ์„ ๊ตฌ์„ฑํ•œ๋‹ค. ์•™์ƒ๋ธ”์ด ์ฟผ๋Ÿผ์„ ๋‹ฌ์„ฑํ•  ์ˆ˜ ์—†๋‹ค๋ฉด, ์•™์ƒ๋ธ”์€ ๋ฐ์ดํ„ฐ๋ฅผ ์“ธ ์ˆ˜ ์—†๋‹ค.

ZooKeeper๋Š” ์ „์ฒด ์ƒํƒœ ๋จธ์‹ ์„ ๋ฉ”๋ชจ๋ฆฌ์— ๋ณด์กดํ•˜๊ณ  ๋ชจ๋“  ๋Œ์—ฐ๋ณ€์ด๋ฅผ ์ €์žฅ ๋ฏธ๋””์–ด์˜ ๋‚ด๊ตฌ์„ฑ ์žˆ๋Š” WAL(Write Ahead Log)์— ๊ธฐ๋กํ•œ๋‹ค. ์„œ๋ฒ„ ์žฅ์• ์‹œ WAL์„ ์žฌ์ƒํ•˜์—ฌ ์ด์ „ ์ƒํƒœ๋ฅผ ๋ณต์›ํ•  ์ˆ˜ ์žˆ๋‹ค. WAL์ด ๋ฌด์ œํ•œ์œผ๋กœ ์ปค์ง€๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ZooKeeper๋Š” ์ฃผ๊ธฐ์ ์œผ๋กœ ์ €์žฅ ๋ฏธ๋””์–ด์— ๋ฉ”๋ชจ๋ฆฌ ์ƒํƒœ์˜ ์Šค๋ƒ…์ƒท์„ ์ €์žฅํ•œ๋‹ค. ์ด ์Šค๋ƒ…์ƒท์€ ๋ฉ”๋ชจ๋ฆฌ์— ์ง์ ‘ ์ ์žฌํ•  ์ˆ˜ ์žˆ๊ณ  ์Šค๋ƒ…์ƒท ์ด์ „์˜ ๋ชจ๋“  WAL ํ•ญ๋ชฉ์€ ์‚ญ์ œ๋  ์ˆ˜ ์žˆ๋‹ค.

ZooKeeper ์•™์ƒ๋ธ” ์ƒ์„ฑํ•˜๊ธฐ

์•„๋ž˜ ๋งค๋‹ˆํŽ˜์ŠคํŠธ์—๋Š” ํ—ค๋“œ๋ฆฌ์Šค ์„œ๋น„์Šค, ์„œ๋น„์Šค, PodDisruptionBudget, ์Šคํ…Œ์ดํŠธํ’€์…‹์„ ํฌํ•จํ•œ๋‹ค.

apiVersion: v1
kind: Service
metadata:
  name: zk-hs
  labels:
    app: zk
spec:
  ports:
  - port: 2888
    name: server
  - port: 3888
    name: leader-election
  clusterIP: None
  selector:
    app: zk
---
apiVersion: v1
kind: Service
metadata:
  name: zk-cs
  labels:
    app: zk
spec:
  ports:
  - port: 2181
    name: client
  selector:
    app: zk
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: zk-pdb
spec:
  selector:
    matchLabels:
      app: zk
  maxUnavailable: 1
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: zk
spec:
  selector:
    matchLabels:
      app: zk
  serviceName: zk-hs
  replicas: 3
  updateStrategy:
    type: RollingUpdate
  podManagementPolicy: OrderedReady
  template:
    metadata:
      labels:
        app: zk
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: "app"
                    operator: In
                    values:
                    - zk
              topologyKey: "kubernetes.io/hostname"
      containers:
      - name: kubernetes-zookeeper
        imagePullPolicy: Always
        image: "registry.k8s.io/kubernetes-zookeeper:1.0-3.4.10"
        resources:
          requests:
            memory: "1Gi"
            cpu: "0.5"
        ports:
        - containerPort: 2181
          name: client
        - containerPort: 2888
          name: server
        - containerPort: 3888
          name: leader-election
        command:
        - sh
        - -c
        - "start-zookeeper \
          --servers=3 \
          --data_dir=/var/lib/zookeeper/data \
          --data_log_dir=/var/lib/zookeeper/data/log \
          --conf_dir=/opt/zookeeper/conf \
          --client_port=2181 \
          --election_port=3888 \
          --server_port=2888 \
          --tick_time=2000 \
          --init_limit=10 \
          --sync_limit=5 \
          --heap=512M \
          --max_client_cnxns=60 \
          --snap_retain_count=3 \
          --purge_interval=12 \
          --max_session_timeout=40000 \
          --min_session_timeout=4000 \
          --log_level=INFO"
        readinessProbe:
          exec:
            command:
            - sh
            - -c
            - "zookeeper-ready 2181"
          initialDelaySeconds: 10
          timeoutSeconds: 5
        livenessProbe:
          exec:
            command:
            - sh
            - -c
            - "zookeeper-ready 2181"
          initialDelaySeconds: 10
          timeoutSeconds: 5
        volumeMounts:
        - name: datadir
          mountPath: /var/lib/zookeeper
      securityContext:
        runAsUser: 1000
        fsGroup: 1000
  volumeClaimTemplates:
  - metadata:
      name: datadir
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 10Gi

ํ„ฐ๋ฏธ๋„์„ ์—ด๊ณ  kubectl apply ๋ช…๋ น์–ด๋กœ ๋งค๋‹ˆํŽ˜์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•˜์ž.

kubectl apply -f https://k8s.io/examples/application/zookeeper/zookeeper.yaml

์ด๋Š” zk-hs ํ—ค๋“œ๋ฆฌ์Šค ์„œ๋น„์Šค, zk-cs ์„œ๋น„์Šค, zk-pdb PodDisruptionBudget๊ณผ zk ์Šคํ…Œ์ดํŠธํ’€์…‹์„ ์ƒ์„ฑํ•œ๋‹ค.

service/zk-hs created
service/zk-cs created
poddisruptionbudget.policy/zk-pdb created
statefulset.apps/zk created

kubectl get์„ ์‚ฌ์šฉํ•˜์—ฌ ์Šคํ…Œ์ดํŠธํ’€์…‹ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์Šคํ…Œ์ดํŠธํ’€์…‹ ํŒŒ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.

kubectl get pods -w -l app=zk

zk-2 ํŒŒ๋“œ๊ฐ€ Running and Ready ์ƒํƒœ๊ฐ€ ๋˜๋ฉด, CTRL-C๋ฅผ ๋ˆŒ๋Ÿฌ kubectl์„ ์ข…๋ฃŒํ•˜์ž.

NAME      READY     STATUS    RESTARTS   AGE
zk-0      0/1       Pending   0          0s
zk-0      0/1       Pending   0         0s
zk-0      0/1       ContainerCreating   0         0s
zk-0      0/1       Running   0         19s
zk-0      1/1       Running   0         40s
zk-1      0/1       Pending   0         0s
zk-1      0/1       Pending   0         0s
zk-1      0/1       ContainerCreating   0         0s
zk-1      0/1       Running   0         18s
zk-1      1/1       Running   0         40s
zk-2      0/1       Pending   0         0s
zk-2      0/1       Pending   0         0s
zk-2      0/1       ContainerCreating   0         0s
zk-2      0/1       Running   0         19s
zk-2      1/1       Running   0         40s

์Šคํ…Œ์ดํŠธํ’€์…‹ ์ปจํŠธ๋กค๋Ÿฌ๋Š” 3๊ฐœ์˜ ํŒŒ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ๊ฐ ํŒŒ๋“œ๋Š” ZooKeeper ์„œ๋ฒ„๋ฅผ ํฌํ•จํ•œ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๊ฐ€์ง„๋‹ค.

๋ฆฌ๋” ์„ ์ถœ ์ด‰์ง„

์ต๋ช… ๋„คํŠธ์›Œํฌ์—์„œ ๋ฆฌ๋” ์„ ์ถœ์„ ์œ„ํ•œ ์ข…๋ฃŒ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์—†๊ธฐ์—, Zab์€ ๋ฆฌ๋” ์„ ์ถœ์„ ์œ„ํ•ด ๋ช…์‹œ์ ์ธ ๋ฉค๋ฒ„ ๊ตฌ์„ฑ์„ ํ•ด์•ผ ํ•œ๋‹ค. ์•™์ƒ๋ธ”์˜ ๊ฐ ์„œ๋ฒ„๋Š” ๊ณ ์œ  ์‹๋ณ„์ž๋ฅผ ๊ฐ€์ ธ์•ผ ํ•˜๊ณ , ๋ชจ๋“  ์„œ๋ฒ„๋Š” ์‹๋ณ„์ž ์ „์—ญ ์ง‘ํ•ฉ์„ ์•Œ์•„์•ผ ํ•˜๋ฉฐ, ๊ฐ ์‹๋ณ„์ž๋Š” ๋„คํŠธ์›Œํฌ ์ฃผ์†Œ์— ์—ฐ๊ด€๋˜์–ด์•ผ ํ•œ๋‹ค.

kubectl exec๋ฅผ ์ด์šฉํ•˜์—ฌ zk ์Šคํ…Œ์ดํŠธํ’€์…‹์˜ ํŒŒ๋“œ์˜ ํ˜ธ์ŠคํŠธ๋„ค์ž„์„ ์•Œ์•„๋‚ด์ž.

for i in 0 1 2; do kubectl exec zk-$i -- hostname; done

์Šคํ…Œ์ดํŠธํ’€์…‹ ์ปจํŠธ๋กค๋Ÿฌ๋Š” ๊ฐ ์ˆœ๋ฒˆ ์ธ๋ฑ์Šค์— ๊ธฐ์ดˆํ•˜์—ฌ ๊ฐ ํŒŒ๋“œ์— ๊ณ ์œ ํ•œ ํ˜ธ์ŠคํŠธ๋„ค์ž„์„ ๋ถ€์—ฌํ•œ๋‹ค. ๊ฐ ํ˜ธ์ŠคํŠธ๋„ค์ž„์€ <์Šคํ…Œ์ดํŠธํ’€์…‹ ์ด๋ฆ„>-<์ˆœ๋ฒˆ ์ธ๋ฑ์Šค> ํ˜•์‹์„ ์ทจํ•œ๋‹ค. zk ์Šคํ…Œ์ดํŠธํ’€์…‹์˜ replicas ํ•„๋“œ๋Š” 3์œผ๋กœ ์„ค์ •๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์—, ๊ทธ ์Šคํ…Œ์ดํŠธํ’€์…‹ ์ปจํŠธ๋กค๋Ÿฌ๋Š” 3๊ฐœ ํŒŒ๋“œ์˜ ํ˜ธ์ŠคํŠธ๋„ค์ž„์„ zk-0, zk-1, zk-2๋กœ ์ •ํ•œ๋‹ค.

zk-0
zk-1
zk-2

ZooKeeper ์•™์ƒ๋ธ”์— ์„œ๋ฒ„๋“ค์€ ๊ณ ์œ  ์‹๋ณ„์ž๋กœ์„œ ์ž์—ฐ์ˆ˜๋ฅผ ์ด์šฉํ•˜๊ณ  ์„œ๋ฒ„ ๋ฐ์ดํ„ฐ ๋””๋ ‰ํ„ฐ๋ฆฌ์— my ๋ผ๋Š” ํŒŒ์ผ๋กœ ์„œ๋ฒ„ ์‹๋ณ„์ž๋ฅผ ์ €์žฅํ•œ๋‹ค.

๊ฐ ์„œ๋ฒ„์—์„œ ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์ด์šฉํ•˜์—ฌ myid ํŒŒ์ผ์˜ ๋‚ด์šฉ์„ ํ™•์ธํ•˜์ž.

for i in 0 1 2; do echo "myid zk-$i";kubectl exec zk-$i -- cat /var/lib/zookeeper/data/myid; done

์‹๋ณ„์ž๋Š” ์ž์—ฐ์ˆ˜์ด๊ณ , ์ˆœ๋ฒˆ ์ธ๋ฑ์Šค๋“ค๋„ ์Œ์ˆ˜๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ, ์ˆœ๋ฒˆ์— 1์„ ๋”ํ•˜์—ฌ ์ˆœ๋ฒˆ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

myid zk-0
1
myid zk-1
2
myid zk-2
3

zk ์Šคํ…Œ์ดํŠธํ’€์…‹์˜ ๊ฐ ํŒŒ๋“œ Fully Qualified Domain Name (FQDN)์„ ์–ป๊ธฐ ์œ„ํ•ด ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์ด์šฉํ•˜์ž.

for i in 0 1 2; do kubectl exec zk-$i -- hostname -f; done

zk-hs ์„œ๋น„์Šค๋Š” ๋ชจ๋“  ํŒŒ๋“œ๋ฅผ ์œ„ํ•œ ๋„๋ฉ”์ธ์ธ zk-hs.default.svc.cluster.local์„ ๋งŒ๋“ ๋‹ค.

zk-0.zk-hs.default.svc.cluster.local
zk-1.zk-hs.default.svc.cluster.local
zk-2.zk-hs.default.svc.cluster.local

์ฟ ๋ฒ„๋„คํ‹ฐ์Šค DNS์˜ A ๋ ˆ์ฝ”๋“œ๋Š” FQDN์„ ํŒŒ๋“œ์˜ IP ์ฃผ์†Œ๋กœ ํ’€์–ด๋‚ธ๋‹ค. ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๊ฐ€ ํŒŒ๋“œ๋ฅผ ๋ฆฌ์Šค์ผ€์ค„ํ•˜๋ฉด, ํŒŒ๋“œ์˜ ์ƒˆ IP ์ฃผ์†Œ๋กœ A ๋ ˆ์ฝ”๋“œ๋ฅผ ๊ฐฑ์‹ ํ•˜์ง€๋งŒ, A ๋ ˆ์ฝ”๋“œ์˜ ์ด๋ฆ„์€ ๋ฐ”๋€Œ์ง€ ์•Š๋Š”๋‹ค.

ZooKeeper๋Š” ๊ทธ๊ฒƒ์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ™˜๊ฒฝ์„ค์ •์„ zoo.cfg ํŒŒ์ผ์— ์ €์žฅํ•œ๋‹ค. kubectl exec๋ฅผ ์ด์šฉํ•˜์—ฌ zk-0 ํŒŒ๋“œ์˜ zoo.cfg ๋‚ด์šฉ์„ ๋ณด์ž.

kubectl exec zk-0 -- cat /opt/zookeeper/conf/zoo.cfg

์•„๋ž˜ ํŒŒ์ผ์˜ server.1, server.2, server.3 ์†์„ฑ์—์„œ 1, 2, 3์€ ZooKeeper ์„œ๋ฒ„์˜ myid ํŒŒ์ผ์— ๊ตฌ๋ถ„์ž์™€ ์—ฐ๊ด€๋œ๋‹ค. ์ด๋“ค์€ zk ์Šคํ…Œ์ดํŠธํ’€์…‹์˜ ํŒŒ๋“œ์˜ FQDNS์„ ์„ค์ •ํ•œ๋‹ค.

clientPort=2181
dataDir=/var/lib/zookeeper/data
dataLogDir=/var/lib/zookeeper/log
tickTime=2000
initLimit=10
syncLimit=2000
maxClientCnxns=60
minSessionTimeout= 4000
maxSessionTimeout= 40000
autopurge.snapRetainCount=3
autopurge.purgeInterval=0
server.1=zk-0.zk-hs.default.svc.cluster.local:2888:3888
server.2=zk-1.zk-hs.default.svc.cluster.local:2888:3888
server.3=zk-2.zk-hs.default.svc.cluster.local:2888:3888

ํ•ฉ์˜ ๋‹ฌ์„ฑ

ํ•ฉ์˜ ํ”„๋กœํ† ์ฝœ์—์„œ ๊ฐ ์ฐธ๊ฐ€์ž์˜ ์‹๋ณ„์ž๋Š” ์œ ์ผํ•ด์•ผ ํ•œ๋‹ค. Zab ํ”„๋กœํ† ์ฝœ์—์„œ ๋™์ผํ•œ ๊ณ ์œ  ์‹๋ณ„์ž๋ฅผ ์š”์ฒญํ•˜๋Š” ์ฐธ๊ฐ€์ž๋Š” ์—†๋‹ค. ์ด๋Š” ์‹œ์Šคํ…œ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์–ด๋–ค ํ”„๋กœ์„ธ์Šค๊ฐ€ ์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฅผ ์ปค๋ฐ‹ํ–ˆ๋Š”์ง€ ๋™์˜ํ•˜๊ฒŒ ํ•˜๋Š”๋ฐ ํ•„์š”ํ•˜๋‹ค. 2๊ฐœ ํŒŒ๋“œ๋ฅผ ๋™์ผ ์ˆœ๋ฒˆ์œผ๋กœ ์‹œ์ž‘ํ•˜์˜€๋‹ค๋ฉด ๋‘ ๋Œ€์˜ ZooKeeper ์„œ๋ฒ„๋Š” ๋‘˜ ๋‹ค ์Šค์Šค๋กœ๋ฅผ ๋™์ผ ์„œ๋ฒ„๋กœ ์‹๋ณ„ํ•œ๋‹ค.

ํ•ฉ์˜ ํ”„๋กœํ† ์ฝœ์—์„œ ๊ฐ ์ฐธ์—ฌ์ž์˜ ์‹๋ณ„์ž๋Š” ๊ณ ์œ ํ•ด์•ผ ํ•œ๋‹ค. Zab ํ”„๋กœํ† ์ฝœ์— ๋‘ ์ฐธ์—ฌ์ž๊ฐ€ ๋™์ผํ•œ ๊ณ ์œ  ์‹๋ณ„์ž๋กœ ์š”์ฒญํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค. ์ด๋Š” ์‹œ์Šคํ…œ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์–ด๋–ค ํ”„๋กœ์„ธ์Šค๊ฐ€ ์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฅผ ์ปค๋ฐ‹ํ–ˆ๋Š”์ง€ ๋™์˜ํ•˜๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด ํ•„์ˆ˜์ ์ด๋‹ค. ๋™์ผ ์ˆœ๋ฒˆ์œผ๋กœ ๋‘ ๊ฐœ์˜ ํŒŒ๋“œ๊ฐ€ ์‹คํ–‰ํ–ˆ๋‹ค๋ฉด ๋‘ ZooKeeper ์„œ๋ฒ„๋Š” ๋ชจ๋‘ ๋™์ผํ•œ ์„œ๋ฒ„๋กœ ์‹๋ณ„๋œ๋‹ค.

kubectl get pods -w -l app=zk
NAME      READY     STATUS    RESTARTS   AGE
zk-0      0/1       Pending   0          0s
zk-0      0/1       Pending   0         0s
zk-0      0/1       ContainerCreating   0         0s
zk-0      0/1       Running   0         19s
zk-0      1/1       Running   0         40s
zk-1      0/1       Pending   0         0s
zk-1      0/1       Pending   0         0s
zk-1      0/1       ContainerCreating   0         0s
zk-1      0/1       Running   0         18s
zk-1      1/1       Running   0         40s
zk-2      0/1       Pending   0         0s
zk-2      0/1       Pending   0         0s
zk-2      0/1       ContainerCreating   0         0s
zk-2      0/1       Running   0         19s
zk-2      1/1       Running   0         40s

๊ฐ ํŒŒ๋“œ์˜ A ๋ ˆ์ฝ”๋“œ๋Š” ํŒŒ๋“œ๊ฐ€ Ready ์ƒํƒœ๊ฐ€ ๋˜๋ฉด ์ž…๋ ฅ๋œ๋‹ค. ๋”ฐ๋ผ์„œ ZooKeeper ์„œ๋ฒ„์˜ FQDN์€ ๋‹จ์ผ ์—”๋“œํฌ์ธํŠธ๋กœ ํ™•์ธ๋˜๊ณ  ํ•ด๋‹น ์—”๋“œํฌ์ธํŠธ๋Š” myid ํŒŒ์ผ์— ๊ตฌ์„ฑ๋œ ์‹๋ณ„์ž๋ฅผ ๊ฐ€์ง„ ๊ณ ์œ ํ•œ ZooKeeper ์„œ๋ฒ„๊ฐ€ ๋œ๋‹ค.

zk-0.zk-hs.default.svc.cluster.local
zk-1.zk-hs.default.svc.cluster.local
zk-2.zk-hs.default.svc.cluster.local

์ด๊ฒƒ์€ ZooKeeper์˜ zoo.cfg ํŒŒ์ผ์— servers ์†์„ฑ์ด ์ •ํ™•ํžˆ ๊ตฌ์„ฑ๋œ ์•™์ƒ๋ธ”๋กœ ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒƒ์„ ๋ณด์ฆํ•œ๋‹ค.

server.1=zk-0.zk-hs.default.svc.cluster.local:2888:3888
server.2=zk-1.zk-hs.default.svc.cluster.local:2888:3888
server.3=zk-2.zk-hs.default.svc.cluster.local:2888:3888

์„œ๋ฒ„๊ฐ€ Zab ํ”„๋กœํ† ์ฝœ๋กœ ๊ฐ’์„ ์ปค๋ฐ‹ ์‹œ๋„ํ•˜๋ฉด, ํ•ฉ์˜๋ฅผ ์ด๋ฃจ์–ด ๊ฐ’์„ ์ปค๋ฐ‹ํ•˜๊ฑฐ๋‚˜(๋ฆฌ๋” ์„ ์ถœ์— ์„ฑ๊ณตํ–ˆ๊ณ  ๋‚˜๋จธ์ง€ ๋‘ ๊ฐœ ํŒŒ๋“œ๋„ Running๊ณผ Ready ์ƒํƒœ๋ผ๋ฉด) ์‹คํŒจํ•œ๋‹ค(์กฐ๊ฑด ์ค‘ ํ•˜๋‚˜๋ผ๋„ ์ถฉ์กฑํ•˜์ง€ ์•Š์œผ๋ฉด). ๋‹ค๋ฅธ ์„œ๋ฒ„๋ฅผ ๋Œ€์‹ ํ•˜์—ฌ ์“ฐ๊ธฐ๋ฅผ ์Šน์ธํ•˜๋Š” ์ƒํƒœ๋Š” ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.

์•™์ƒ๋ธ” ๋ฌด๊ฒฐ์„ฑ ํ…Œ์ŠคํŠธ

๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ํ…Œ์ŠคํŠธ๋Š” ํ•œ ZooKeeper ์„œ๋ฒ„์— ๋ฐ์ดํ„ฐ๋ฅผ ์“ฐ๊ณ  ๋‹ค๋ฅธ ZooKeeper ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๋Š” ๊ฒƒ์ด๋‹ค.

์•„๋ž˜ ๋ช…๋ น์–ด๋Š” ์•™์ƒ๋ธ” ๋‚ด์— zk-0 ํŒŒ๋“œ์—์„œ /hello ๊ฒฝ๋กœ๋กœ world๋ฅผ ์“ฐ๋Š” ์Šคํฌ๋ฆฝํŠธ์ธ zkCli.sh๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

kubectl exec zk-0 -- zkCli.sh create /hello world
WATCHER::

WatchedEvent state:SyncConnected type:None path:null
Created /hello

zk-1 ํŒŒ๋“œ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๊ธฐ ์œ„ํ•ด ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์ด์šฉํ•˜์ž.

kubectl exec zk-1 -- zkCli.sh get /hello

zk-0์—์„œ ์ƒ์„ฑํ•œ ๊ทธ ๋ฐ์ดํ„ฐ๋Š” ์•™์ƒ๋ธ” ๋‚ด์— ๋ชจ๋“  ์„œ๋ฒ„์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

WATCHER::

WatchedEvent state:SyncConnected type:None path:null
world
cZxid = 0x100000002
ctime = Thu Dec 08 15:13:30 UTC 2016
mZxid = 0x100000002
mtime = Thu Dec 08 15:13:30 UTC 2016
pZxid = 0x100000002
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0

๋‚ด๊ตฌ์„ฑ์žˆ๋Š” ์ €์žฅ์†Œ ์ œ๊ณต

ZooKeeper ๊ธฐ๋ณธ ์„น์…˜์—์„œ ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด ZooKeeper๋Š” ๋ชจ๋“  ํ•ญ๋ชฉ์„ ๋‚ด๊ตฌ์„ฑ์žˆ๋Š” WAL์— ์ปค๋ฐ‹ํ•˜๊ณ  ๋ฉ”๋ชจ๋ฆฌ ์ƒํƒœ์˜ ์Šค๋ƒ…์ƒท์„ ์ €์žฅ ๋ฏธ๋””์—์— ์ฃผ๊ธฐ์ ์œผ๋กœ ์ €์žฅํ•œ๋‹ค. ๋‚ด๊ตฌ์„ฑ์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด WAL์„ ์ด์šฉํ•˜๋Š” ๊ฒƒ์€ ๋ณต์ œ๋œ ์ƒํƒœ ๋จธ์‹ ์„ ์ด๋ฃจ๋Š” ํ•ฉ์˜ ํ”„๋กœํ† ์ฝœ์—์„œ ์ด์šฉํ•˜๋Š” ์ผ๋ฐ˜์ ์ธ ๊ธฐ๋ฒ•์ด๋‹ค.

kubectl delete ๋ช…๋ น์„ ์ด์šฉํ•˜์—ฌ zk ์Šคํ…Œ์ดํŠธํ’€์…‹์„ ์‚ญ์ œํ•˜์ž.

kubectl delete statefulset zk
statefulset.apps "zk" deleted

์Šคํ…Œ์ดํŠธํ’€์…‹์˜ ํŒŒ๋“œ๊ฐ€ ์ข…๋ฃŒ๋˜๋Š” ๊ฒƒ์„ ์ง€์ผœ๋ณด์ž.

kubectl get pods -w -l app=zk

zk-0์ด ์™„์ „ํžˆ ์ข…๋ฃŒ๋˜๋ฉด CTRL-C๋ฅผ ์ด์šฉํ•ด kubectl์„ ์ข…๋ฃŒํ•˜์ž.

zk-2      1/1       Terminating   0         9m
zk-0      1/1       Terminating   0         11m
zk-1      1/1       Terminating   0         10m
zk-2      0/1       Terminating   0         9m
zk-2      0/1       Terminating   0         9m
zk-2      0/1       Terminating   0         9m
zk-1      0/1       Terminating   0         10m
zk-1      0/1       Terminating   0         10m
zk-1      0/1       Terminating   0         10m
zk-0      0/1       Terminating   0         11m
zk-0      0/1       Terminating   0         11m
zk-0      0/1       Terminating   0         11m

zookeeper.yaml ๋งค๋‹ˆํŽ˜์ŠคํŠธ๋ฅผ ๋‹ค์‹œ ์ ์šฉํ•œ๋‹ค.

kubectl apply -f https://k8s.io/examples/application/zookeeper/zookeeper.yaml

zk ์Šคํ…Œ์ดํŠธํ’€์…‹ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•˜์ง€๋งŒ, ๋งค๋‹ˆํŽ˜์ŠคํŠธ์— ๋‹ค๋ฅธ API ์˜ค๋ธŒ์ ํŠธ๋Š” ์ด๋ฏธ ์กด์žฌํ•˜๋ฏ€๋กœ ์ˆ˜์ •๋˜์ง€ ์•Š๋Š”๋‹ค.

์Šคํ…Œ์ดํŠธํ’€์…‹ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์Šคํ…ŒํŠธํ’€์…‹์˜ ํŒŒ๋“œ๋ฅผ ์žฌ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•œ๋‹ค.

kubectl get pods -w -l app=zk

zk-2 ํŒŒ๋“œ๊ฐ€ Running๊ณผ Ready๊ฐ€ ๋˜๋ฉด CTRL-C๋ฅผ ์ด์šฉํ•˜์—ฌ kubectl์„ ์ข…๋ฃŒํ•œ๋‹ค.

NAME      READY     STATUS    RESTARTS   AGE
zk-0      0/1       Pending   0          0s
zk-0      0/1       Pending   0         0s
zk-0      0/1       ContainerCreating   0         0s
zk-0      0/1       Running   0         19s
zk-0      1/1       Running   0         40s
zk-1      0/1       Pending   0         0s
zk-1      0/1       Pending   0         0s
zk-1      0/1       ContainerCreating   0         0s
zk-1      0/1       Running   0         18s
zk-1      1/1       Running   0         40s
zk-2      0/1       Pending   0         0s
zk-2      0/1       Pending   0         0s
zk-2      0/1       ContainerCreating   0         0s
zk-2      0/1       Running   0         19s
zk-2      1/1       Running   0         40s

์•„๋ž˜ ๋ช…๋ น์–ด๋กœ ๋ฌด๊ฒฐ์„ฑ ํ…Œ์ŠคํŠธ์—์„œ ์ž…๋ ฅํ•œ ๊ฐ’์„ zk-2 ํŒŒ๋“œ์—์„œ ์–ป์–ด์˜จ๋‹ค.

kubectl exec zk-2 zkCli.sh get /hello

zk ์Šคํ…Œ์ดํŠธํ’€์…‹์˜ ๋ชจ๋“  ํŒŒ๋“œ๋ฅผ ์ข…๋ฃŒํ•˜๊ณ  ์žฌ์ƒ์„ฑํ–ˆ์Œ์—๋„, ์•™์ƒ๋ธ”์€ ์—ฌ์ „ํžˆ ์›๋ž˜ ๊ฐ’์„ ๋Œ๋ ค์ค€๋‹ค.

WATCHER::

WatchedEvent state:SyncConnected type:None path:null
world
cZxid = 0x100000002
ctime = Thu Dec 08 15:13:30 UTC 2016
mZxid = 0x100000002
mtime = Thu Dec 08 15:13:30 UTC 2016
pZxid = 0x100000002
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0

zk ์Šคํ…Œ์ดํŠธํ’€์…‹์˜ spec์— volumeClaimTemplates ํ•„๋“œ๋Š” ๊ฐ ํŒŒ๋“œ์— ํ”„๋กœ๋น„์ „๋  ํผ์‹œ์Šคํ„ดํŠธ๋ณผ๋ฅจ์„ ์ง€์ •ํ•œ๋‹ค.

volumeClaimTemplates:
  - metadata:
      name: datadir
      annotations:
        volume.alpha.kubernetes.io/storage-class: anything
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 20Gi

์Šคํ…Œ์ดํŠธํ’€์…‹ ์ปจํŠธ๋กค๋Ÿฌ๋Š” ์Šคํ…Œ์ดํŠธํ’€์…‹์˜ ๊ฐ ํŒŒ๋“œ์— ๋Œ€ํ•œ ํผ์‹œ์Šคํ„ดํŠธ๋ณผ๋ฅจํด๋ ˆ์ž„์„ ์ƒ์„ฑํ•œ๋‹ค.

๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์ด์šฉํ•˜์—ฌ ์Šคํ…Œ์ดํŠธํ’€์…‹์˜ ํผ์‹œ์Šคํ„ดํŠธ๋ณผ๋ฅจํด๋ ˆ์ž„์„ ์‚ดํŽด๋ณด์ž.

kubectl get pvc -l app=zk

์Šคํ…Œ์ดํŠธํ’€์…‹์˜ ํŒŒ๋“œ๋ฅผ ์žฌ์ƒ์„ฑํ•  ๋•Œ์— ํŒŒ๋“œ์˜ ํผ์‹œ์Šคํ„ดํŠธ๋ณผ๋ฅจ๋„ ๋‹ค์‹œ ๋งˆ์šดํŠธํ•œ๋‹ค.

NAME           STATUS    VOLUME                                     CAPACITY   ACCESSMODES   AGE
datadir-zk-0   Bound     pvc-bed742cd-bcb1-11e6-994f-42010a800002   20Gi       RWO           1h
datadir-zk-1   Bound     pvc-bedd27d2-bcb1-11e6-994f-42010a800002   20Gi       RWO           1h
datadir-zk-2   Bound     pvc-bee0817e-bcb1-11e6-994f-42010a800002   20Gi       RWO           1h

์Šคํ…Œ์ดํŠธํ’€์…‹์˜ ์ปจํ…Œ์ด๋„ˆ template์˜ volumeMounts ๋ถ€๋ถ„์ด ZooKeeper ์„œ๋ฒ„์˜ ๋ฐ์ดํ„ฐ ๋””๋ ‰ํ„ฐ๋ฆฌ์— ํผ์‹œ์Šคํ„ดํŠธ๋ณผ๋ฅจ ๋งˆ์šดํŠธํ•˜๋Š” ๋‚ด์šฉ์ด๋‹ค.

volumeMounts:
- name: datadir
  mountPath: /var/lib/zookeeper

zk ์Šคํ…Œ์ดํŠธํ’€์…‹์ด (์žฌ)์Šค์ผ€์ค„๋ง๋  ๋•Œ ํ•ญ์ƒ ๋™์ผํ•œ ํผ์‹œ์Šคํ„ดํŠธ๋ณผ๋ฅจ์„ ZooKeeper์˜ ์„œ๋ฒ„ ๋””๋ ‰ํ„ฐ๋ฆฌ์— ๋งˆ์šดํŠธํ•œ๋‹ค. ํŒŒ๋“œ๋ฅผ ์žฌ์Šค์ผ€์ค„ํ•  ๋•Œ์—๋„ ZooKeeper์˜ WAL์„ ํ†ตํ•ด ์ด๋ค„์ง„ ๋ชจ๋“  ์“ฐ๊ธฐ์™€ ๋ชจ๋“  ๊ทธ ์Šค๋ƒ…์ƒท๋„ ๋‚ด๊ตฌ์„ฑ์„ ์œ ์ง€ํ•œ๋‹ค.

์ผ๊ด€๋œ ๊ตฌ์„ฑ ๋ณด์žฅํ•˜๊ธฐ

๋ฆฌ๋” ์„ ์ถœ ์ด‰์ง„๊ณผ ํ•ฉ์˜ ๋‹ฌ์„ฑ ์„น์…˜์—์„œ ์•Œ๋ ธ๋“ฏ์ด, ZooKeeper ์•™์ƒ๋ธ”์— ์„œ๋ฒ„๋Š” ๋ฆฌ๋” ์„ ์ถœ๊ณผ ์ฟผ๋Ÿผ์„ ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ์ผ๊ด€๋œ ์„ค์ •์ด ํ•„์š”ํ•˜๋‹ค. ๋˜ํ•œ Zab ํ”„๋กœํ† ์ฝœ์˜ ์ผ๊ด€๋œ ์„ค์ •๋„ ๋„คํŠธ์›Œํฌ์— ๊ฑธ์ณ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋™์ž‘ํ•˜๊ธฐ ์œ„ํ•ด์„œ ํ•„์š”ํ•˜๋‹ค. ์ด ์˜ˆ์‹œ์—์„œ๋Š” ๋งค๋‹ˆํŽ˜์ŠคํŠธ์— ๊ตฌ์„ฑ์„ ์ง์ ‘ ํฌํ•จ์‹œ์ผœ์„œ ์ผ๊ด€๋œ ๊ตฌ์„ฑ์„ ๋‹ฌ์„ฑํ•œ๋‹ค.

zk ์Šคํ…Œ์ดํŠธํ’€์…‹์„ ์‚ดํŽด๋ณด์ž.

kubectl get sts zk -o yaml
โ€ฆ
command:
      - sh
      - -c
      - "start-zookeeper \
        --servers=3 \
        --data_dir=/var/lib/zookeeper/data \
        --data_log_dir=/var/lib/zookeeper/data/log \
        --conf_dir=/opt/zookeeper/conf \
        --client_port=2181 \
        --election_port=3888 \
        --server_port=2888 \
        --tick_time=2000 \
        --init_limit=10 \
        --sync_limit=5 \
        --heap=512M \
        --max_client_cnxns=60 \
        --snap_retain_count=3 \
        --purge_interval=12 \
        --max_session_timeout=40000 \
        --min_session_timeout=4000 \
        --log_level=INFO"
โ€ฆ

ZooKeeper ์„œ๋ฒ„๋ฅผ ์‹œ์ž‘ํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•œ ๋ช…๋ น์–ด๋Š” ์ปค๋งจ๋“œ๋ผ์ธ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ํ™˜๊ฒฝ ๊ตฌ์„ฑ์„ ์ „๋‹ฌํ–ˆ๋‹ค. ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์ด์šฉํ•˜์—ฌ์„œ๋„ ์•™์ƒ๋ธ”์— ํ™˜๊ฒฝ ๊ตฌ์„ฑ์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค.

๋กœ๊น… ์„ค์ •ํ•˜๊ธฐ

zkGenConfig.sh ์Šคํฌ๋ฆฝํŠธ๋กœ ์ƒ์„ฑ๋œ ํŒŒ์ผ ์ค‘ ํ•˜๋‚˜๋Š” ZooKeeper์˜ ๋กœ๊น…์„ ์ œ์–ดํ•œ๋‹ค. ZooKeeper๋Š” Log4j๋ฅผ ์ด์šฉํ•˜๋ฉฐ ๊ธฐ๋ณธ ๋กœ๊น… ๊ตฌ์„ฑ์œผ๋กœ๋Š” ์‹œ๊ฐ„๊ณผ ํŒŒ์ผ ํฌ๊ธฐ ๊ธฐ์ค€์˜ ๋กค๋ง ํŒŒ์ผ ์–ดํŽœ๋”๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

zk ์Šคํ…Œ์ดํŠธํ’€์…‹์˜ ํ•œ ํŒŒ๋“œ์—์„œ ๋กœ๊น… ์„ค์ •์„ ์‚ดํŽด๋ณด๋Š” ์•„๋ž˜ ๋ช…๋ น์–ด๋ฅผ ์ด์šฉํ•˜์ž.

kubectl exec zk-0 cat /usr/etc/zookeeper/log4j.properties

์•„๋ž˜ ๋กœ๊น… ๊ตฌ์„ฑ์€ ZooKeeper๊ฐ€ ๋ชจ๋“  ๋กœ๊ทธ๋ฅผ ํ‘œ์ค€ ์ถœ๋ ฅ ์ŠคํŠธ๋ฆผ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ํ•œ๋‹ค.

zookeeper.root.logger=CONSOLE
zookeeper.console.threshold=INFO
log4j.rootLogger=${zookeeper.root.logger}
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Threshold=${zookeeper.console.threshold}
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L] - %m%n

์ด๋Š” ์ปจํ…Œ์ด๋„ˆ ๋‚ด์—์„œ ์•ˆ์ „ํ•˜๊ฒŒ ๋กœ๊น…ํ•˜๋Š” ๊ฐ€์žฅ ๋‹จ์ˆœํ•œ ๋ฐฉ๋ฒ•์ด๋‹ค. ํ‘œ์ค€ ์ถœ๋ ฅ์œผ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ๊ทธ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด, ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๋Š” ๋กœ๊ทธ ๋กœํ…Œ์ด์…˜์„ ์ฒ˜๋ฆฌํ•œ๋‹ค. ๋˜ํ•œ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ํ‘œ์ค€ ์ถœ๋ ฅ๊ณผ ํ‘œ์ค€ ์˜ค๋ฅ˜์— ์“ฐ์ธ ๋กœ๊ทธ๋กœ ์ธํ•˜์—ฌ ๋กœ์ปฌ ์ €์žฅ ๋ฏธ๋””์–ด๊ฐ€ ๊ณ ๊ฐˆ๋˜์ง€ ์•Š๋„๋ก ๋ณด์žฅํ•˜๋Š” ์ •์ƒ์ ์ธ ๋ณด์กด ์ •์ฑ…์„ ๊ตฌํ˜„ํ•œ๋‹ค.

ํŒŒ๋“œ์˜ ๋งˆ์ง€๋ง‰ 20์ค„์˜ ๋กœ๊ทธ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” kubectl logs ๋ช…๋ น์„ ์ด์šฉํ•˜์ž.

kubectl logs zk-0 --tail 20

kubectl logs๋ฅผ ์ด์šฉํ•˜๊ฑฐ๋‚˜ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ๋Œ€์‹œ๋ณด๋“œ์—์„œ ํ‘œ์ค€ ์ถœ๋ ฅ๊ณผ ํ‘œ์ค€ ์˜ค๋ฅ˜๋กœ ์“ฐ์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ๊ทธ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

2016-12-06 19:34:16,236 [myid:1] - INFO  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxn@827] - Processing ruok command from /127.0.0.1:52740
2016-12-06 19:34:16,237 [myid:1] - INFO  [Thread-1136:NIOServerCnxn@1008] - Closed socket connection for client /127.0.0.1:52740 (no session established for client)
2016-12-06 19:34:26,155 [myid:1] - INFO  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxnFactory@192] - Accepted socket connection from /127.0.0.1:52749
2016-12-06 19:34:26,155 [myid:1] - INFO  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxn@827] - Processing ruok command from /127.0.0.1:52749
2016-12-06 19:34:26,156 [myid:1] - INFO  [Thread-1137:NIOServerCnxn@1008] - Closed socket connection for client /127.0.0.1:52749 (no session established for client)
2016-12-06 19:34:26,222 [myid:1] - INFO  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxnFactory@192] - Accepted socket connection from /127.0.0.1:52750
2016-12-06 19:34:26,222 [myid:1] - INFO  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxn@827] - Processing ruok command from /127.0.0.1:52750
2016-12-06 19:34:26,226 [myid:1] - INFO  [Thread-1138:NIOServerCnxn@1008] - Closed socket connection for client /127.0.0.1:52750 (no session established for client)
2016-12-06 19:34:36,151 [myid:1] - INFO  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxnFactory@192] - Accepted socket connection from /127.0.0.1:52760
2016-12-06 19:34:36,152 [myid:1] - INFO  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxn@827] - Processing ruok command from /127.0.0.1:52760
2016-12-06 19:34:36,152 [myid:1] - INFO  [Thread-1139:NIOServerCnxn@1008] - Closed socket connection for client /127.0.0.1:52760 (no session established for client)
2016-12-06 19:34:36,230 [myid:1] - INFO  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxnFactory@192] - Accepted socket connection from /127.0.0.1:52761
2016-12-06 19:34:36,231 [myid:1] - INFO  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxn@827] - Processing ruok command from /127.0.0.1:52761
2016-12-06 19:34:36,231 [myid:1] - INFO  [Thread-1140:NIOServerCnxn@1008] - Closed socket connection for client /127.0.0.1:52761 (no session established for client)
2016-12-06 19:34:46,149 [myid:1] - INFO  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxnFactory@192] - Accepted socket connection from /127.0.0.1:52767
2016-12-06 19:34:46,149 [myid:1] - INFO  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxn@827] - Processing ruok command from /127.0.0.1:52767
2016-12-06 19:34:46,149 [myid:1] - INFO  [Thread-1141:NIOServerCnxn@1008] - Closed socket connection for client /127.0.0.1:52767 (no session established for client)
2016-12-06 19:34:46,230 [myid:1] - INFO  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxnFactory@192] - Accepted socket connection from /127.0.0.1:52768
2016-12-06 19:34:46,230 [myid:1] - INFO  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxn@827] - Processing ruok command from /127.0.0.1:52768
2016-12-06 19:34:46,230 [myid:1] - INFO  [Thread-1142:NIOServerCnxn@1008] - Closed socket connection for client /127.0.0.1:52768 (no session established for client)

์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๋Š” ๋งŽ์€ ๋กœ๊ทธ ์†”๋ฃจ์…˜๊ณผ ํ†ตํ•ฉ๋œ๋‹ค. ํด๋Ÿฌ์Šคํ„ฐ์™€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๊ฐ€์žฅ ์ ํ•ฉํ•œ ๋กœ๊ทธ ์†”๋ฃจ์…˜์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋‹ค. ํด๋Ÿฌ์Šคํ„ฐ ์ˆ˜์ค€์˜ ๋กœ๊ทธ ์ ์žฌ(ship)์™€ ํ†ตํ•ฉ์„ ์œ„ํ•ด์„œ๋Š” ๋กœ๊ทธ ์ˆœํ™˜๊ณผ ์ ์žฌ๋ฅผ ์œ„ํ•ด ์‚ฌ์ด๋“œ์นด ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋ฐฐํฌํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•œ๋‹ค.

๊ถŒํ•œ ์—†๋Š” ์‚ฌ์šฉ์ž๋ฅผ ์œ„ํ•ด ๊ตฌ์„ฑํ•˜๊ธฐ

์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€์˜ ๊ถŒํ•œ์žˆ๋Š” ์œ ์ €๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ์ตœ์ƒ์˜ ๋ฐฉ๋ฒ•์€ ๋…ผ์Ÿ๊ฑฐ๋ฆฌ์ด๋‹ค. ์กฐ์ง์—์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ถŒํ•œ ์—†๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์‹คํ–‰ํ•œ๋‹ค๋ฉด, ์ง„์ž…์ ์„ ์‹คํ–‰ํ•  ์‚ฌ์šฉ์ž๋ฅผ ์ œ์–ดํ•˜๊ธฐ ์œ„ํ•ด ์‹œํ๋ฆฌํ‹ฐ์ปจํ…์ŠคํŠธ๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

zk ์Šคํ…Œ์ดํŠธํ’€์…‹์˜ ํŒŒ๋“œ template์€ SecurityContext๋ฅผ ํฌํ•จํ•œ๋‹ค.

securityContext:
  runAsUser: 1000
  fsGroup: 1000

ํŒŒ๋“œ ์ปจํ…Œ์ด๋„ˆ์—์„œ UID 1000์€ ZooKeeper ์‚ฌ์šฉ์ž์ด๋ฉฐ, GID 1000์€ ZooKeeper์˜ ๊ทธ๋ฃน์— ํ•ด๋‹นํ•œ๋‹ค.

zk-0 ํŒŒ๋“œ์—์„œ ํ”„๋กœ์„ธ์Šค ์ •๋ณด๋ฅผ ์–ป์–ด์˜ค์ž.

kubectl exec zk-0 -- ps -elf

securityContext ์˜ค๋ธŒ์ ํŠธ์˜ runAsUser ํ•„๋“œ ๊ฐ’์ด 1000 ์ด๋ฏ€๋กœ ๋ฃจํŠธ ์‚ฌ์šฉ์ž๋กœ ์‹คํ–‰ํ•˜๋Š” ๋Œ€์‹  ZooKeeper ํ”„๋กœ์„ธ์Šค๋Š” ZooKeeper ์‚ฌ์šฉ์ž๋กœ ์‹คํ–‰๋œ๋‹ค.

F S UID        PID  PPID  C PRI  NI ADDR SZ WCHAN  STIME TTY          TIME CMD
4 S zookeep+     1     0  0  80   0 -  1127 -      20:46 ?        00:00:00 sh -c zkGenConfig.sh && zkServer.sh start-foreground
0 S zookeep+    27     1  0  80   0 - 1155556 -    20:46 ?        00:00:19 /usr/lib/jvm/java-8-openjdk-amd64/bin/java -Dzookeeper.log.dir=/var/log/zookeeper -Dzookeeper.root.logger=INFO,CONSOLE -cp /usr/bin/../build/classes:/usr/bin/../build/lib/*.jar:/usr/bin/../share/zookeeper/zookeeper-3.4.9.jar:/usr/bin/../share/zookeeper/slf4j-log4j12-1.6.1.jar:/usr/bin/../share/zookeeper/slf4j-api-1.6.1.jar:/usr/bin/../share/zookeeper/netty-3.10.5.Final.jar:/usr/bin/../share/zookeeper/log4j-1.2.16.jar:/usr/bin/../share/zookeeper/jline-0.9.94.jar:/usr/bin/../src/java/lib/*.jar:/usr/bin/../etc/zookeeper: -Xmx2G -Xms2G -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=false org.apache.zookeeper.server.quorum.QuorumPeerMain /usr/bin/../etc/zookeeper/zoo.cfg

๊ธฐ๋ณธ์ ์œผ๋กœ ํŒŒ๋“œ์˜ ํผ์‹œ์Šคํ„ดํŠธ๋ณผ๋ฅจ์€ ZooKeeper ์„œ๋ฒ„์˜ ๋ฐ์ดํ„ฐ ๋””๋ ‰ํ„ฐ๋ฆฌ์— ๋งˆ์šดํŠธ๋˜๊ณ , ๋ฃจํŠธ ์‚ฌ์šฉ์ž๋งŒ์ด ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๋‹ค. ์ด ๊ตฌ์„ฑ์€ ZooKeeper ํ”„๋กœ์„ธ์Šค๊ฐ€ WAL์— ๊ธฐ๋กํ•˜๊ณ  ์Šค๋ƒ…์ƒท์„ ์ €์žฅํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•œ๋‹ค.

zk-0 ํŒŒ๋“œ์˜ ZooKeeper ๋ฐ์ดํ„ฐ ๋””๋ ‰ํ„ฐ๋ฆฌ์˜ ๊ถŒํ•œ์„ ์–ป์–ด์˜ค๋Š” ์•„๋ž˜ ๋ช…๋ น์–ด๋ฅผ ์ด์šฉํ•˜์ž.

kubectl exec -ti zk-0 -- ls -ld /var/lib/zookeeper/data

securityContext ์˜ค๋ธŒ์ ํŠธ์˜ fsGroup ํ•„๋“œ ๊ฐ’์ด 1000 ์ด๋ฏ€๋กœ, ํŒŒ๋“œ์˜ ํผ์‹œ์Šคํ„ดํŠธ ๋ณผ๋ฅจ์˜ ์†Œ์œ ๊ถŒ์€ ZooKeeper ๊ทธ๋ฃน์œผ๋กœ ์ง€์ •๋˜์–ด ZooKeeper ํ”„๋กœ์„ธ์Šค์—์„œ ์ฝ๊ณ  ์“ธ ์ˆ˜ ์žˆ๋‹ค.

drwxr-sr-x 3 zookeeper zookeeper 4096 Dec  5 20:45 /var/lib/zookeeper/data

ZooKeeper ํ”„๋กœ์„ธ์Šค ๊ด€๋ฆฌํ•˜๊ธฐ

ZooKeeper ๋ฌธ์„œ์—์„œ๋Š” "ZooKeeper์˜ ์„œ๋ฒ„ ํ”„๋กœ์„ธ์Šค(JVM)์„ ๊ด€๋ฆฌํ•  ๊ฐ๋… ํ”„๋กœ์„ธ์Šค๋ฅผ ํ•„์š”ํ•  ๊ฒƒ์ด๋‹ค."๋ผ๊ณ  ๋งํ•œ๋‹ค. ์™€์น˜๋…(๊ฐ๋… ํ”„๋กœ์„ธ์Šค)๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์‹คํŒจํ•œ ํ”„๋กœ์„ธ์Šค๋ฅผ ์žฌ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์€ ๋ถ„์‚ฐ์‹œ์Šคํ…œ์—์„œ ์ผ๋ฐ˜์ ์ธ ๋ฐฉ์‹์ด๋‹ค. ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค์—์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋ฐฐํฌํ•  ๋•Œ์—๋Š” ๊ฐ๋… ํ”„๋กœ์„ธ์Šค๋กœ ์™ธ๋ถ€ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ๋ณด๋‹ค ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๋ฅผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์™€์น˜๋…์œผ๋กœ์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

์•™์ƒ๋ธ” ๊ด€๋ฆฌํ•˜๊ธฐ

zk ์Šคํ…Œ์ดํŠธํ’€์…‹์€ RollingUpdate ์—…๋ฐ์ดํŠธ ์ „๋žต์„ ์ด์šฉํ•˜๋„๋ก ๊ตฌ์„ฑ๋˜์—ˆ๋‹ค.

kubectl patch๋กœ ์„œ๋ฒ„์— ํ• ๋‹น๋œ cpu ์ˆ˜๋ฅผ ๊ฐฑ์‹ ํ•  ์ˆ˜ ์žˆ๋‹ค.

kubectl patch sts zk --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/resources/requests/cpu", "value":"0.3"}]'
statefulset.apps/zk patched

์—…๋ฐ์ดํŠธ ์ƒํ™ฉ์„ ์ง€์ผœ๋ณด๊ธฐ ์œ„ํ•ด kubectl rollout status ์ด์šฉํ•˜์ž.

kubectl rollout status sts/zk
waiting for statefulset rolling update to complete 0 pods at revision zk-5db4499664...
Waiting for 1 pods to be ready...
Waiting for 1 pods to be ready...
waiting for statefulset rolling update to complete 1 pods at revision zk-5db4499664...
Waiting for 1 pods to be ready...
Waiting for 1 pods to be ready...
waiting for statefulset rolling update to complete 2 pods at revision zk-5db4499664...
Waiting for 1 pods to be ready...
Waiting for 1 pods to be ready...
statefulset rolling update complete 3 pods at revision zk-5db4499664...

์ด๊ฒƒ์€ ํŒŒ๋“œ๋ฅผ ์—ญ์ˆœ์œผ๋กœ ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์”ฉ ์ข…๋ฃŒํ•˜๊ณ , ์ƒˆ๋กœ์šด ๊ตฌ์„ฑ์œผ๋กœ ์žฌ์ƒ์„ฑํ•œ๋‹ค. ์ด๋Š” ๋กค๋ง์—…๋ฐ์ดํŠธ ๋™์•ˆ์— ์ฟผ๋Ÿผ์„ ์œ ์ง€ํ•˜๋„๋ก ๋ณด์žฅํ•œ๋‹ค.

์ด๋ ฅ๊ณผ ์ด์ „ ๊ตฌ์„ฑ์„ ๋ณด๊ธฐ ์œ„ํ•ด kubectl rollout history ๋ช…๋ น์„ ์ด์šฉํ•˜์ž.

kubectl rollout history sts/zk

์ถœ๋ ฅ์€ ๋‹ค์Œ๊ณผ ๋น„์Šทํ•  ๊ฒƒ์ด๋‹ค.

statefulsets "zk"
REVISION
1
2

์ˆ˜์ •์‚ฌํ•ญ์„ ๋กค๋ฐฑํ•˜๊ธฐ ์œ„ํ•ด kubectl rollout undo ๋ช…๋ น์„ ์ด์šฉํ•˜์ž.

kubectl rollout undo sts/zk

์ถœ๋ ฅ์€ ๋‹ค์Œ๊ณผ ๋น„์Šทํ•  ๊ฒƒ์ด๋‹ค.

statefulset.apps/zk rolled back

ํ”„๋กœ์„ธ์Šค ์žฅ์•  ๊ด€๋ฆฌํ•˜๊ธฐ

์žฌ์‹œ์ž‘ ์ •์ฑ…์€ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๊ฐ€ ํŒŒ๋“œ ๋‚ด์— ์ปจํ…Œ์ด๋„ˆ์˜ ์ง„์ž…์ ์—์„œ ํ”„๋กœ์„ธ์Šค ์‹คํŒจ๋ฅผ ์–ด๋–ป๊ฒŒ ๋‹ค๋ฃจ๋Š”์ง€ ์ œ์–ดํ•œ๋‹ค. ์Šคํ…Œ์ดํŠธํ’€์…‹์˜ ํŒŒ๋“œ์—์„œ ์˜ค์ง ์ ์ ˆํ•œ ์žฌ์‹œ์ž‘ ์ •์ฑ…๋Š” Always์ด๋ฉฐ ์ด๊ฒƒ์ด ๊ธฐ๋ณธ ๊ฐ’์ด๋‹ค. ์ƒํƒœ๊ฐ€ ์œ ์ง€๋˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์œ„ํ•ด ๊ธฐ๋ณธ ์ •์ฑ…์„ ์ ˆ๋Œ€๋กœ ๋ณ€๊ฒฝํ•˜์ง€ ๋ง์ž.

zk-0 ํŒŒ๋“œ์—์„œ ์‹คํ–‰ ์ค‘์ธ ZooKeeper ์„œ๋ฒ„์—์„œ ํ”„๋กœ์„ธ์Šค ํŠธ๋ฆฌ๋ฅผ ์‚ดํŽด๋ณด๊ธฐ ์œ„ํ•ด ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์ด์šฉํ•˜์ž.

kubectl exec zk-0 -- ps -ef

์ปจํ…Œ์ด๋„ˆ์˜ ์—”ํŠธ๋ฆฌ ํฌ์ธํŠธ๋กœ PID 1 ์ธ ๋ช…๋ น์ด ์‚ฌ์šฉ๋˜์—ˆ์œผ๋ฉฐ ZooKeeper ํ”„๋กœ์„ธ์Šค๋Š” ์—”ํŠธ๋ฆฌ ํฌ์ธํŠธ์˜ ์ž์‹ ํ”„๋กœ์„ธ์Šค๋กœ PID 27 ์ด๋‹ค.

UID        PID  PPID  C STIME TTY          TIME CMD
zookeep+     1     0  0 15:03 ?        00:00:00 sh -c zkGenConfig.sh && zkServer.sh start-foreground
zookeep+    27     1  0 15:03 ?        00:00:03 /usr/lib/jvm/java-8-openjdk-amd64/bin/java -Dzookeeper.log.dir=/var/log/zookeeper -Dzookeeper.root.logger=INFO,CONSOLE -cp /usr/bin/../build/classes:/usr/bin/../build/lib/*.jar:/usr/bin/../share/zookeeper/zookeeper-3.4.9.jar:/usr/bin/../share/zookeeper/slf4j-log4j12-1.6.1.jar:/usr/bin/../share/zookeeper/slf4j-api-1.6.1.jar:/usr/bin/../share/zookeeper/netty-3.10.5.Final.jar:/usr/bin/../share/zookeeper/log4j-1.2.16.jar:/usr/bin/../share/zookeeper/jline-0.9.94.jar:/usr/bin/../src/java/lib/*.jar:/usr/bin/../etc/zookeeper: -Xmx2G -Xms2G -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=false org.apache.zookeeper.server.quorum.QuorumPeerMain /usr/bin/../etc/zookeeper/zoo.cfg

๋‹ค๋ฅธ ํ„ฐ๋ฏธ๋„์—์„œ ๋‹ค์Œ ๋ช…๋ น์–ด๋กœ zk ์Šคํ…Œ์ดํŠธํ’€์…‹์˜ ํŒŒ๋“œ๋ฅผ ํ™•์ธํ•œ๋‹ค.

kubectl get pod -w -l app=zk

๋˜ ๋‹ค๋ฅธ ํ„ฐ๋ฏธ๋„์—์„œ ๋‹ค์Œ ๋ช…๋ น์–ด๋กœ zk-0 ํŒŒ๋“œ์˜ ZooKeeper ํ”„๋กœ์„ธ์Šค๋ฅผ ์ข…๋ฃŒ์‹œํ‚จ๋‹ค.

kubectl exec zk-0 -- pkill java

ZooKeeper ํ”„๋กœ์„ธ์Šค์˜ ์ข…๋ฃŒ๋Š” ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค์˜ ์ข…๋ฃŒ๋ฅผ ์ผ์œผํ‚จ๋‹ค. ์ปจํ…Œ์ด๋„ˆ ์žฌ์‹œ์ž‘์ •์ฑ…์ด Always์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค๋ฅผ ์žฌ์‹œ์ž‘ํ–ˆ๋‹ค.

NAME      READY     STATUS    RESTARTS   AGE
zk-0      1/1       Running   0          21m
zk-1      1/1       Running   0          20m
zk-2      1/1       Running   0          19m
NAME      READY     STATUS    RESTARTS   AGE
zk-0      0/1       Error     0          29m
zk-0      0/1       Running   1         29m
zk-0      1/1       Running   1         29m

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์Šคํฌ๋ฆฝํŠธ(zkServer.sh ๊ฐ™์€)๋ฅผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋น„์ง€๋‹ˆ์Šค ๋กœ์ง์„ ๊ตฌํ˜„ํ•œ ํ”„๋กœ์„ธ์Šค๋ฅผ ์‹œ์ž‘ํ•˜๊ธฐ ์œ„ํ•ด ์ด์šฉํ•œ๋‹ค๋ฉด, ๊ทธ ์Šคํฌ๋ฆฝํŠธ๋Š” ์ž์‹ ํ”„๋กœ์„ธ์Šค์™€ ํ•จ๊ป˜ ๋ฐ˜๋“œ์‹œ ์ข…๋ฃŒ๋˜์–ด์•ผ ํ•œ๋‹ค. ์ด๋Š” ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๊ฐ€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋น„์ง€๋‹ˆ์Šค ๋กœ์ง์„ ๊ตฌํ˜„ํ•œ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‹คํŒจํ•  ๋•Œ์— ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์žฌ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์„ ๋ณด์ฆํ•œ๋‹ค.

ํ™œ์„ฑ๋„(Liveness) ํ…Œ์ŠคํŠธํ•˜๊ธฐ

์‹คํŒจํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์žฌ์‹œ์ž‘ํ•˜๋„๋ก ๊ตฌ์„ฑํ•˜๋Š” ๊ฒƒ์€ ๋ถ„์‚ฐ ์‹œ์Šคํ…œ์„ ๊ฑด๊ฐ•ํ•˜๊ฒŒ ์œ ์ง€ํ•˜๋Š”๋ฐ ์ถฉ๋ถ„ํ•˜์ง€ ์•Š๋‹ค. ์‹œ์Šคํ…œ์˜ ํ”„๋กœ์„ธ์Šค๋Š” ์‚ด์•„์žˆ์ง€๋งŒ ์‘๋‹ต์ด ์—†์„ ์ˆ˜ ์žˆ๊ณ , ํ˜น์€ ๋‹ค๋ฅธ ๊ฑด๊ฐ•ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ์˜ ์‹œ๋‚˜๋ฆฌ์˜ค๊ฐ€ ์žˆ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๊ฑด๊ฐ•ํ•˜์ง€ ์•Š๊ณ  ์žฌ์‹œ์ž‘ํ•ด์•ผ๋งŒ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค์—๊ฒŒ ์•Œ๋ฆฌ๋„๋ก ํ™œ์„ฑ๋„ ๊ฒ€์‚ฌ๋ฅผ ์ด์šฉํ•ด์•ผ ํ•œ๋‹ค.

zk ์Šคํ…Œ์ดํŠธํ’€์…‹์— ํŒŒ๋“œ template์— ํ™œ์„ฑ๋„ ๊ฒ€์‚ฌ๋ฅผ ๋ช…์‹œํ•œ๋‹ค.

  livenessProbe:
    exec:
      command:
      - sh
      - -c
      - "zookeeper-ready 2181"
    initialDelaySeconds: 15
    timeoutSeconds: 5

๊ฒ€์‚ฌ๋Š” ZooKeeper์˜ ruok 4 ๊ธ€์ž ๋‹จ์–ด๋ฅผ ์ด์šฉํ•ด์„œ ์„œ๋ฒ„์˜ ๊ฑด๊ฐ•์„ ํ…Œ์ŠคํŠธํ•˜๋Š” ๋ฐฐ์‰ฌ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

OK=$(echo ruok | nc 127.0.0.1 $1)
if [ "$OK" == "imok" ]; then
    exit 0
else
    exit 1
fi

ํ•œ ํ„ฐ๋ฏธ๋„์—์„œ zk ์Šคํ…Œ์ดํŠธํ’€์…‹์˜ ํŒŒ๋“œ๋ฅผ ์ง€์ผœ๋ณด๊ธฐ ์œ„ํ•ด ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์ด์šฉํ•˜์ž.

kubectl get pod -w -l app=zk

๋‹ค๋ฅธ ์ฐฝ์—์„œ zk-0 ํŒŒ๋“œ์˜ ํŒŒ์ผ์‹œ์Šคํ…œ์—์„œ zookeeper-ready ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ญ์ œํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์ด์šฉํ•˜์ž.

kubectl exec zk-0 -- rm /opt/zookeeper/bin/zookeeper-ready

ZooKeeper์˜ ํ™œ์„ฑ๋„ ๊ฒ€์‚ฌ์— ์‹คํŒจํ•˜๋ฉด, ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๋Š” ์ž๋™์œผ๋กœ ํ”„๋กœ์„ธ์Šค๋ฅผ ์žฌ์‹œ์ž‘ํ•˜์—ฌ ์•™์ƒ๋ธ”์— ๊ฑด๊ฐ•ํ•˜์ง€ ์•Š์€ ํ”„๋กœ์„ธ์Šค๋ฅผ ์žฌ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์„ ๋ณด์ฆํ•œ๋‹ค.

kubectl get pod -w -l app=zk
NAME      READY     STATUS    RESTARTS   AGE
zk-0      1/1       Running   0          1h
zk-1      1/1       Running   0          1h
zk-2      1/1       Running   0          1h
NAME      READY     STATUS    RESTARTS   AGE
zk-0      0/1       Running   0          1h
zk-0      0/1       Running   1         1h
zk-0      1/1       Running   1         1h

์ค€๋น„๋„ ํ…Œ์ŠคํŠธ

์ค€๋น„๋„๋Š” ํ™œ์„ฑ๋„์™€ ๋™์ผํ•˜์ง€ ์•Š๋‹ค. ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‚ด์•„ ์žˆ๋‹ค๋ฉด, ์Šค์ผ€์ค„๋ง๋˜๊ณ  ๊ฑด๊ฐ•ํ•˜๋‹ค. ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ค€๋น„๋˜๋ฉด ์ž…๋ ฅ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. ํ™œ์„ฑ๋„๋Š” ํ•„์ˆ˜์ ์ด๋‚˜ ์ค€๋น„๋„์˜ ์กฐ๊ฑด์œผ๋กœ๋Š” ์ถฉ๋ถ„ํ•˜์ง€ ์•Š๋‹ค. ๋ช‡๋ช‡ ๊ฒฝ์šฐ ํŠน๋ณ„ํžˆ ์ดˆ๊ธฐํ™”์™€ ์ข…๋ฃŒ ์‹œ์— ํ”„๋กœ์„ธ์Šค๋Š” ์‚ด์•„์žˆ์ง€๋งŒ ์ค€๋น„๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค.

์ค€๋น„๋„ ๊ฒ€์‚ฌ๋ฅผ ์ง€์ •ํ•˜๋ฉด, ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๋Š” ์ค€๋น„๋„๊ฐ€ ํ†ต๊ณผํ•  ๋•Œ๊นŒ์ง€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋„คํŠธ์›Œํฌ ํŠธ๋ž˜ํ”ฝ์„ ์ˆ˜์‹ ํ•˜์ง€ ์•Š๊ฒŒ ํ•œ๋‹ค.

ZooKeeper ์„œ๋ฒ„์—์„œ๋Š” ์ค€๋น„๋„๊ฐ€ ํ™œ์„ฑ๋„๋ฅผ ๋‚ดํฌํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ zookeeper.yaml ๋งค๋‹ˆํŽ˜์ŠคํŠธ์—์„œ ์ค€๋น„๋„ ๊ฒ€์‚ฌ๋Š” ํ™œ์„ฑ๋„ ๊ฒ€์‚ฌ์™€ ๋™์ผํ•˜๋‹ค.

  readinessProbe:
    exec:
      command:
      - sh
      - -c
      - "zookeeper-ready 2181"
    initialDelaySeconds: 15
    timeoutSeconds: 5

ํ™œ์„ฑ๋„์™€ ์ค€๋น„๋„ ๊ฒ€์‚ฌ๊ฐ€ ๋™์ผํ•จ์—๋„ ๋‘˜ ๋‹ค ์ง€์ •ํ•˜๋Š” ๊ฒƒ์€ ์ค‘์š”ํ•˜๋‹ค. ์ด๋Š” ZooKeeper ์•™์ƒ๋ธ”์— ๊ฑด๊ฐ•ํ•œ ์„œ๋ฒ„๋งŒ ์•„๋‹ˆ๋ผ ๋„คํŠธ์›Œํฌ ํŠธ๋ž˜ํ”ฝ์„ ์ˆ˜์‹ ํ•˜๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•œ๋‹ค.

๋…ธ๋“œ ์‹คํŒจ ๋ฐฉ์ง€

ZooKeeper๋Š” ๋ณ€์กฐ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ์ปค๋ฐ‹ํ•˜๊ธฐ ์œ„ํ•œ ์„œ๋ฒ„์˜ ์ฟผ๋Ÿผ์ด ํ•„์š”ํ•˜๋‹ค. 3๊ฐœ์˜ ์„œ๋ฒ„ ์•™์ƒ๋ธ”์—์„œ ์„ฑ๊ณต์ ์œผ๋กœ ์ €์žฅํ•˜๋ ค๋ฉด 2๊ฐœ ์„œ๋ฒ„๋Š” ๋ฐ˜๋“œ์‹œ ๊ฑด๊ฐ•ํ•ด์•ผ ํ•œ๋‹ค. ์ฟผ๋Ÿผ ๊ธฐ๋ฐ˜ ์‹œ์Šคํ…œ์—์„œ, ๋ฉค๋ฒ„๋Š” ๊ฐ€์šฉ์„ฑ์„ ๋ณด์žฅํ•˜๋Š” ์‹คํŒจ ์˜์—ญ์— ๊ฑธ์ณ ๋ฐฐํฌ๋œ๋‹ค. ์ค‘๋‹จ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๊ฐœ๋ณ„ ์‹œ์Šคํ…œ์˜ ์†์‹ค๋กœ ์ธํ•ด ๋ชจ๋ฒ” ์‚ฌ๋ก€์—์„œ๋Š” ๋™์ผํ•œ ์‹œ์Šคํ…œ์— ์—ฌ๋Ÿฌ ์ธ์Šคํ„ด์Šค์˜ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ํ•จ๊ป˜ ๋ฐฐ์น˜ํ•˜๋Š” ๊ฒƒ์„ ๋ฐฐ์ œํ•œ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๋Š” ๋™์ผ ๋…ธ๋“œ์ƒ์— ์Šคํ…Œ์ดํŠธํ’€์…‹์˜ ํŒŒ๋“œ๋ฅผ ์œ„์น˜์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค. ์ƒ์„ฑํ•œ 3๊ฐœ์˜ ์„œ๋ฒ„ ์•™์ƒ๋ธ”์—์„œ 2๊ฐœ์˜ ์„œ๋ฒ„๊ฐ€ ๊ฐ™์€ ๋…ธ๋“œ์— ์žˆ๋‹ค๋ฉด, ๊ทธ ๋…ธ๋“œ๋Š” ์‹คํŒจํ•˜๊ณ  ZooKeeper ์„œ๋น„์Šค ํด๋ผ์ด์–ธํŠธ๋Š” ๊ทธ ํŒŒ๋“œ๋“ค์˜ ์ตœ์†Œ ํ•˜๋‚˜๊ฐ€ ์žฌ์Šค์ผ€์ค„๋ง๋  ๋•Œ๊นŒ์ง€ ์ž‘๋™ ์ค‘๋‹จ์„ ๊ฒฝํ—˜ํ•  ๊ฒƒ์ด๋‹ค.

๋…ธ๋“œ ์‹คํŒจํ•˜๋Š” ์‚ฌ๊ฑด ์ค‘์—๋„ ์ค‘์š” ์‹œ์Šคํ…œ์˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์žฌ์Šค์ผ€์ค„๋  ์ˆ˜ ์žˆ๊ฒŒ ํ•ญ์ƒ ์ถ”๊ฐ€์ ์ธ ์šฉ๋Ÿ‰์„ ํ”„๋กœ๋น„์ „ํ•ด์•ผ ํ•œ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ZooKeeper ์„œ๋ฒ„ ํ•˜๋‚˜๋ฅผ ๋‹ค์‹œ ์Šค์ผ€์ค„ํ•˜๋Š” ๋™์•ˆ๊นŒ์ง€๋งŒ ์ž‘๋™ ์ค‘๋‹จ๋  ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์„œ๋น„์Šค์—์„œ ๋…ธ๋“œ ์‹คํŒจ๋กœ ์ธํ•œ ๋‹ค์šดํƒ€์ž„์„ ๋ฐฉ์ง€ํ•˜๋ ค ํ•œ๋‹ค๋ฉด, ํŒŒ๋“œ์•ˆํ‹ฐ์–ดํ”ผ๋‹ˆํ‹ฐ๋ฅผ ์„ค์ •ํ•ด์•ผ ํ•œ๋‹ค.

zk ์Šคํ…Œ์ดํŠธํ’€์…‹์˜ ํŒŒ๋“œ์˜ ๋…ธ๋“œ๋ฅผ ์•Œ์•„๋ณด๊ธฐ ์œ„ํ•ด ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์ด์šฉํ•˜์ž.

for i in 0 1 2; do kubectl get pod zk-$i --template {{.spec.nodeName}}; echo ""; done

zk ์Šคํ…Œ์ดํŠธํ’€์…‹์— ๋ชจ๋“  ํŒŒ๋“œ๋Š” ๋‹ค๋ฅธ ๋…ธ๋“œ์— ๋ฐฐํฌ๋œ๋‹ค.

kubernetes-node-cxpk
kubernetes-node-a5aq
kubernetes-node-2g2d

์ด๋Š” zk ์Šคํ…Œ์ดํŠธํ’€์…‹์˜ ํŒŒ๋“œ์— ํŒŒ๋“œ์•ˆํ‹ฐ์–ดํ”ผ๋‹ˆํ‹ฐ(PodAntiAffinity)๋ฅผ ์ง€์ •ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

affinity:
  podAntiAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
            - key: "app"
              operator: In
              values:
                - zk
        topologyKey: "kubernetes.io/hostname"

requiredDuringSchedulingIgnoredDuringExecution ํ•„๋“œ๋Š” ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ์Šค์ผ€์ค„๋Ÿฌ์— topologyKey๋กœ ์ •์˜๋œ ๋„๋ฉ”์ธ์—์„œ app์ด zk๋ผ๊ณ  ๋ ˆ์ด๋ธ”๋ง๋œ ๋‘ ๊ฐœ ํŒŒ๋“œ๊ฐ€ ์œ„์น˜ํ•˜์ง€ ์•Š๋„๋ก ํ•œ๋‹ค. topologyKey kubernetes.io/hostname์€ ๋„๋ฉ”์ธ์ด ๊ฐœ๋ณ„ ๋…ธ๋“œ์ž„์„ ๋‚˜ํƒ€๋‚ธ๋‹ค. ๋‹ค๋ฅธ ๊ทœ์น™๊ณผ ๋ ˆ์ด๋ธ”, ์…€๋ ‰ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์•™์ƒ๋ธ”์„ ๋ฌผ๋ฆฌ์ ์ธ, ๋„คํŠธ์›Œํฌ, ์ „์› ์žฅ์•  ๋ถ„์•ผ์— ๊ฑธ์ณ ํ™•์‚ฐํ•˜๋„๋ก ์ด ๊ธฐ๋ฒ•์„ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.

์ƒ์กด ์œ ์ง€

์ด ์„น์…˜์—์„œ๋Š” ๋…ธ๋“œ๋ฅผ ํ†ต์ œ(cordon)ํ•˜๊ณ  ๋น„์šด๋‹ค(drain). ๊ณต์œ ๋œ ํด๋Ÿฌ์Šคํ„ฐ์—์„œ ์ด ํŠœํ† ๋ฆฌ์–ผ์„ ์ง„ํ–‰ํ•œ๋‹ค๋ฉด, ๋‹ค๋ฅธ ํ…Œ๋„ŒํŠธ์— ๋ถ€์ •์ ์ธ ์˜ํ–ฅ์„ ๋น„์น˜์ง€ ์•Š์Œ์„ ๋ณด์ฆํ•ด์•ผ ํ•œ๋‹ค.

์ด์ „ ์„น์…˜์€ ๊ณ„ํš๋˜์ง€ ์•Š์€ ๋…ธ๋“œ ์‹คํŒจ์—์„œ ์‚ด์•„๋‚จ๋„๋ก ์–ด๋–ป๊ฒŒ ํŒŒ๋“œ๋ฅผ ํ™•์‚ฐํ•  ๊ฒƒ์ธ๊ฐ€์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์•˜๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ณ„ํš๋œ ์ ๊ฒ€์œผ๋กœ ์ธํ•ด ๋ฐœ์ƒํ•˜๋Š” ์ผ์‹œ์ ์ธ ๋…ธ๋“œ ์‹คํŒจ์— ๋Œ€ํ•œ ๊ณ„ํš๋„ ํ•„์š”ํ•˜๋‹ค.

ํด๋Ÿฌ์Šคํ„ฐ์—์„œ ๋‹ค์Œ ๋ช…๋ น์œผ๋กœ ๋…ธ๋“œ๋ฅผ ์‚ดํŽด๋ณด์ž.

kubectl get nodes

์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” ํด๋Ÿฌ์Šคํ„ฐ๊ฐ€ ์ตœ์†Œ 4๊ฐœ์˜ ๋…ธ๋“œ๋กœ ๊ตฌ์„ฑ๋˜์—ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•œ๋‹ค. ํด๋Ÿฌ์Šคํ„ฐ์˜ ๋…ธ๋“œ๊ฐ€ 4๊ฐœ๋ณด๋‹ค ๋งŽ๋‹ค๋ฉด, kubectl cordon ๋ช…๋ น์„ ์ด์šฉํ•˜์—ฌ 4๊ฐœ ๋…ธ๋“œ๋ฅผ ์ œ์™ธํ•˜๊ณ  ๋‹ค๋ฅธ ๋ชจ๋“  ๋…ธ๋“œ๋ฅผ ํ†ต์ œ(cordon)ํ•œ๋‹ค. ์ด๋ ‡๊ฒŒ 4๊ฐœ ๋…ธ๋“œ๋งŒ ์‚ฌ์šฉํ•˜๋„๋ก ์ œํ•œํ•˜์—ฌ, ๋‹ค์Œ์˜ ์œ ์ง€๋ณด์ˆ˜ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์˜ˆ์‹œ์—์„œ ์ฃผํ‚คํผ ํŒŒ๋“œ๋ฅผ ์Šค์ผ€์ค„๋งํ•  ๋•Œ ์–ดํ”ผ๋‹ˆํ‹ฐ์™€ PodDisruptionBudget ์ œ์•ฝ์ด ๋ฐœ์ƒํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ๋‹ค.

kubectl cordon <๋…ธ๋“œ-์ด๋ฆ„>

zk-pdb PodDisruptionBudget์„ ์‚ดํŽด๋ณด๊ณ ์ž ์ด ๋ช…๋ น์–ด๋ฅผ ์ด์šฉํ•˜์ž.

kubectl get pdb zk-pdb

max-unavailable ํ•„๋“œ๋Š” ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๊ฐ€ zk ์Šคํ…Œ์ดํŠธํ’€์…‹์—์„œ ์ตœ๋Œ€ 1๊ฐœ์˜ ํŒŒ๋“œ๋Š” ์–ธ์ œ๋“ ์ง€ ๊ฐ€์šฉํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Œ์„ ๋‚˜ํƒ€๋‚ธ๋‹ค.

NAME      MIN-AVAILABLE   MAX-UNAVAILABLE   ALLOWED-DISRUPTIONS   AGE
zk-pdb    N/A             1                 1

ํ•œ ํ„ฐ๋ฏธ๋„์—์„œ zk ์Šคํ…Œ์ดํŠธํ’€์…‹์˜ ํŒŒ๋“œ๋ฅผ ์ง€์ผœ๋ณด๋Š” ์ด ๋ช…๋ น์–ด๋ฅผ ์ด์šฉํ•˜์ž.

kubectl get pods -w -l app=zk

๋‹ค๋ฅธ ํ„ฐ๋ฏธ๋„์—์„œ ํ˜„์žฌ ์Šค์ผ€์ค„๋˜๋Š” ํŒŒ๋“œ์˜ ๋…ธ๋“œ๋ฅผ ์‚ดํŽด๋ณด์ž.

for i in 0 1 2; do kubectl get pod zk-$i --template {{.spec.nodeName}}; echo ""; done

์ถœ๋ ฅ์€ ๋‹ค์Œ๊ณผ ๋น„์Šทํ•  ๊ฒƒ์ด๋‹ค.

kubernetes-node-pb41
kubernetes-node-ixsl
kubernetes-node-i4c4

zk-0ํŒŒ๋“œ๊ฐ€ ์Šค์ผ€์ค„๋˜๋Š” ๋…ธ๋“œ๋ฅผ ํ†ต์ œํ•˜๊ธฐ ์œ„ํ•ด kubectl drain๋ฅผ ์ด์šฉํ•˜์ž.

kubectl drain $(kubectl get pod zk-0 --template {{.spec.nodeName}}) --ignore-daemonsets --force --delete-emptydir-data

์ถœ๋ ฅ์€ ๋‹ค์Œ๊ณผ ๋น„์Šทํ•  ๊ฒƒ์ด๋‹ค.

node "kubernetes-node-group-pb41" cordoned

WARNING: Deleting pods not managed by ReplicationController, ReplicaSet, Job, or DaemonSet: fluentd-cloud-logging-kubernetes-node-group-pb41, kube-proxy-kubernetes-node-group-pb41; Ignoring DaemonSet-managed pods: node-problem-detector-v0.1-o5elz
pod "zk-0" deleted
node "kubernetes-node-group-pb41" drained

ํด๋Ÿฌ์Šคํ„ฐ์— 4๊ฐœ ๋…ธ๋“œ๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— kubectl drain์ด ์„ฑ๊ณตํ•˜์—ฌ zk-0์„ ๋‹ค๋ฅธ ๋…ธ๋“œ๋กœ ์žฌ์Šค์ผ€์ค„๋ง ๋œ๋‹ค.

NAME      READY     STATUS    RESTARTS   AGE
zk-0      1/1       Running   2          1h
zk-1      1/1       Running   0          1h
zk-2      1/1       Running   0          1h
NAME      READY     STATUS        RESTARTS   AGE
zk-0      1/1       Terminating   2          2h
zk-0      0/1       Terminating   2         2h
zk-0      0/1       Terminating   2         2h
zk-0      0/1       Terminating   2         2h
zk-0      0/1       Pending   0         0s
zk-0      0/1       Pending   0         0s
zk-0      0/1       ContainerCreating   0         0s
zk-0      0/1       Running   0         51s
zk-0      1/1       Running   0         1m

๊ณ„์†ํ•ด์„œ ์Šคํ…Œ์ดํŠธํ’€์…‹์˜ ํŒŒ๋“œ๋ฅผ ์ฒซ ํ„ฐ๋ฏธ๋„์—์„œ ์ง€์ผœ๋ณด๊ณ  zk-1 ์ด ์Šค์ผ€์ค„๋œ ๋…ธ๋“œ๋ฅผ ๋น„์›Œ๋ณด์ž.

kubectl drain $(kubectl get pod zk-1 --template {{.spec.nodeName}}) --ignore-daemonsets --force --delete-emptydir-data

์ถœ๋ ฅ์€ ๋‹ค์Œ๊ณผ ๋น„์Šทํ•  ๊ฒƒ์ด๋‹ค.

"kubernetes-node-ixsl" cordoned
WARNING: Deleting pods not managed by ReplicationController, ReplicaSet, Job, or DaemonSet: fluentd-cloud-logging-kubernetes-node-ixsl, kube-proxy-kubernetes-node-ixsl; Ignoring DaemonSet-managed pods: node-problem-detector-v0.1-voc74
pod "zk-1" deleted
node "kubernetes-node-ixsl" drained

zk-1 ํŒŒ๋“œ๋Š” ์Šค์ผ€์ค„๋˜์ง€ ์•Š๋Š”๋ฐ ์ด๋Š” zk StatefulSet์ด ์˜ค์ง 2๊ฐœ ๋…ธ๋“œ๊ฐ€ ์Šค์ผ€์ค„๋˜๋„๋ก ํŒŒ๋“œ๋ฅผ ์œ„์น˜์‹œํ‚ค๋Š” ๊ฒƒ์„ ๊ธˆํ•˜๋Š” PodAntiAffinity ๊ทœ์น™์„ ํฌํ•จํ•˜์˜€๊ธฐ ๋•Œ๋ฌธ์ด๊ณ  ๊ทธ ํŒŒ๋“œ๋Š” Pending ์ƒํƒœ๋กœ ๋‚จ์„ ๊ฒƒ์ด๋‹ค.

kubectl get pods -w -l app=zk

์ถœ๋ ฅ์€ ๋‹ค์Œ๊ณผ ๋น„์Šทํ•  ๊ฒƒ์ด๋‹ค.

NAME      READY     STATUS    RESTARTS   AGE
zk-0      1/1       Running   2          1h
zk-1      1/1       Running   0          1h
zk-2      1/1       Running   0          1h
NAME      READY     STATUS        RESTARTS   AGE
zk-0      1/1       Terminating   2          2h
zk-0      0/1       Terminating   2         2h
zk-0      0/1       Terminating   2         2h
zk-0      0/1       Terminating   2         2h
zk-0      0/1       Pending   0         0s
zk-0      0/1       Pending   0         0s
zk-0      0/1       ContainerCreating   0         0s
zk-0      0/1       Running   0         51s
zk-0      1/1       Running   0         1m
zk-1      1/1       Terminating   0         2h
zk-1      0/1       Terminating   0         2h
zk-1      0/1       Terminating   0         2h
zk-1      0/1       Terminating   0         2h
zk-1      0/1       Pending   0         0s
zk-1      0/1       Pending   0         0s

๊ณ„์†ํ•ด์„œ ์Šคํ…Œ์ดํŠธํ’€์…‹์˜ ํŒŒ๋“œ๋ฅผ ์ง€์ผœ๋ณด๊ณ  zk-2๊ฐ€ ์Šค์ผ€์ค„๋œ ๋…ธ๋“œ๋ฅผ ๋น„์›Œ๋ณด์ž.

kubectl drain $(kubectl get pod zk-2 --template {{.spec.nodeName}}) --ignore-daemonsets --force --delete-emptydir-data

์ถœ๋ ฅ์€ ๋‹ค์Œ๊ณผ ๋น„์Šทํ•  ๊ฒƒ์ด๋‹ค.

node "kubernetes-node-i4c4" cordoned

WARNING: Deleting pods not managed by ReplicationController, ReplicaSet, Job, or DaemonSet: fluentd-cloud-logging-kubernetes-node-i4c4, kube-proxy-kubernetes-node-i4c4; Ignoring DaemonSet-managed pods: node-problem-detector-v0.1-dyrog
WARNING: Ignoring DaemonSet-managed pods: node-problem-detector-v0.1-dyrog; Deleting pods not managed by ReplicationController, ReplicaSet, Job, or DaemonSet: fluentd-cloud-logging-kubernetes-node-i4c4, kube-proxy-kubernetes-node-i4c4
There are pending pods when an error occurred: Cannot evict pod as it would violate the pod's disruption budget.
pod/zk-2

kubectl ์„ ์ข…๋ฃŒํ•˜๊ธฐ ์œ„ํ•ด CTRL-C๋ฅผ ์ด์šฉํ•˜์ž.

zk-2๋ฅผ ์ถ”์ถœํ•˜๋Š” ๊ฒƒ์€ zk-budget์„ ์œ„๋ฐ˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์…‹์งธ ๋…ธ๋“œ๋ฅผ ๋น„์šธ ์ˆ˜ ์—†๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ทธ ๋…ธ๋“œ๋Š” ํ†ต์ œ ์ƒํƒœ๋กœ ๋‚จ๋Š”๋‹ค.

zk-0์—์„œ ์˜จ์ „์„ฑ ํ…Œ์ŠคํŠธ ๋•Œ์— ์ž…๋ ฅํ•œ ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๋Š” zkCli.sh๋ฅผ ์ด์šฉํ•˜์ž.

kubectl exec zk-0 zkCli.sh get /hello

PodDisruptionBudget์ด ์กด์ค‘๋˜๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋น„์Šค๋Š” ์—ฌ์ „ํžˆ ๊ฐ€์šฉํ•˜๋‹ค.

WatchedEvent state:SyncConnected type:None path:null
world
cZxid = 0x200000002
ctime = Wed Dec 07 00:08:59 UTC 2016
mZxid = 0x200000002
mtime = Wed Dec 07 00:08:59 UTC 2016
pZxid = 0x200000002
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0

kubectl uncordon ์ด์šฉํ•˜์—ฌ ์ฒซ ๋…ธ๋“œ์˜ ํ†ต์ œ๋ฅผ ํ’€์ž.

kubectl uncordon kubernetes-node-pb41

์ถœ๋ ฅ์€ ๋‹ค์Œ๊ณผ ๋น„์Šทํ•  ๊ฒƒ์ด๋‹ค.

node "kubernetes-node-pb41" uncordoned

zk-1์€ ์ด ๋…ธ๋“œ์—์„œ ์žฌ์Šค์ผ€์ค„๋œ๋‹ค. zk-1์ด Running๊ณผ Ready๊ฐ€ ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ์ž.

kubectl get pods -w -l app=zk

์ถœ๋ ฅ์€ ๋‹ค์Œ๊ณผ ๋น„์Šทํ•  ๊ฒƒ์ด๋‹ค.

NAME      READY     STATUS    RESTARTS   AGE
zk-0      1/1       Running   2          1h
zk-1      1/1       Running   0          1h
zk-2      1/1       Running   0          1h
NAME      READY     STATUS        RESTARTS   AGE
zk-0      1/1       Terminating   2          2h
zk-0      0/1       Terminating   2         2h
zk-0      0/1       Terminating   2         2h
zk-0      0/1       Terminating   2         2h
zk-0      0/1       Pending   0         0s
zk-0      0/1       Pending   0         0s
zk-0      0/1       ContainerCreating   0         0s
zk-0      0/1       Running   0         51s
zk-0      1/1       Running   0         1m
zk-1      1/1       Terminating   0         2h
zk-1      0/1       Terminating   0         2h
zk-1      0/1       Terminating   0         2h
zk-1      0/1       Terminating   0         2h
zk-1      0/1       Pending   0         0s
zk-1      0/1       Pending   0         0s
zk-1      0/1       Pending   0         12m
zk-1      0/1       ContainerCreating   0         12m
zk-1      0/1       Running   0         13m
zk-1      1/1       Running   0         13m

zk-2๊ฐ€ ์Šค์ผ€์ค„๋œ ๋…ธ๋“œ๋ฅผ ๋น„์›Œ๋ณด์ž.

kubectl drain $(kubectl get pod zk-2 --template {{.spec.nodeName}}) --ignore-daemonsets --force --delete-emptydir-data

์ถœ๋ ฅ์€ ๋‹ค์Œ๊ณผ ๋น„์Šทํ•  ๊ฒƒ์ด๋‹ค.

node "kubernetes-node-i4c4" already cordoned
WARNING: Deleting pods not managed by ReplicationController, ReplicaSet, Job, or DaemonSet: fluentd-cloud-logging-kubernetes-node-i4c4, kube-proxy-kubernetes-node-i4c4; Ignoring DaemonSet-managed pods: node-problem-detector-v0.1-dyrog
pod "heapster-v1.2.0-2604621511-wht1r" deleted
pod "zk-2" deleted
node "kubernetes-node-i4c4" drained

์ด๋ฒˆ์—” kubectl drain ์ด ์„ฑ๊ณตํ•œ๋‹ค.

zk-2๊ฐ€ ์žฌ์Šค์ผ€์ค„๋˜๋„๋ก ๋‘ ๋ฒˆ์งธ ๋…ธ๋“œ์˜ ํ†ต์ œ๋ฅผ ํ’€์–ด๋ณด์ž.

kubectl uncordon kubernetes-node-ixsl

์ถœ๋ ฅ์€ ๋‹ค์Œ๊ณผ ๋น„์Šทํ•  ๊ฒƒ์ด๋‹ค.

node "kubernetes-node-ixsl" uncordoned

kubectl drain์„ PodDisruptionBudget๊ณผ ๊ฒฐํ•ฉํ•˜๋ฉด ์œ ์ง€๋ณด์ˆ˜ ์ค‘์—๋„ ์„œ๋น„์Šค๋ฅผ ๊ฐ€์šฉํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค. drain์œผ๋กœ ๋…ธ๋“œ๋ฅผ ํ†ต์ œํ•˜๊ณ  ์œ ์ง€๋ณด์ˆ˜๋ฅผ ์œ„ํ•ด ๋…ธ๋“œ๋ฅผ ์˜คํ”„๋ผ์ธํ•˜๊ธฐ ์ „์— ํŒŒ๋“œ๋ฅผ ์ถ”์ถœํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์„œ๋น„์Šค๋Š” ํ˜ผ๋ž€ ์˜ˆ์‚ฐ์„ ํ‘œ๊ธฐํ•œ ์„œ๋น„์Šค๋Š” ๊ทธ ์˜ˆ์‚ฐ์ด ์กด์ค‘์€ ์กด์ค‘๋  ๊ฒƒ์ด๋‹ค. ํŒŒ๋“œ๊ฐ€ ์ฆ‰๊ฐ์ ์œผ๋กœ ์žฌ์Šค์ผ€์ค„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ญ์ƒ ์ค‘์š” ์„œ๋น„์Šค๋ฅผ ์œ„ํ•œ ์ถ”๊ฐ€ ์šฉ๋Ÿ‰์„ ํ• ๋‹นํ•ด์•ผ ํ•œ๋‹ค.

์ •๋ฆฌํ•˜๊ธฐ

  • kubectl uncordon์€ ํด๋Ÿฌ์Šคํ„ฐ ๋‚ด์— ๋ชจ๋“  ๋…ธ๋“œ๋ฅผ ํ†ต์ œ ํ•ด์ œํ•œ๋‹ค.
  • ๋ฐ˜๋“œ์‹œ ์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ ์‚ฌ์šฉํ•œ ํผ์‹œ์Šคํ„ดํŠธ ๋ณผ๋ฅจ์„ ์œ„ํ•œ ํผ์‹œ์Šคํ„ดํŠธ ์Šคํ† ๋ฆฌ์ง€ ๋ฏธ๋””์–ด๋ฅผ ์‚ญ์ œํ•˜์ž. ๊ท€ํ•˜์˜ ํ™˜๊ฒฝ๊ณผ ์Šคํ† ๋ฆฌ์ง€ ๊ตฌ์„ฑ๊ณผ ํ”„๋กœ๋น„์ €๋‹ ๋ฐฉ๋ฒ•์—์„œ ํ•„์š”ํ•œ ์ ˆ์ฐจ๋ฅผ ๋”ฐ๋ผ์„œ ๋ชจ๋“  ์Šคํ† ๋ฆฌ์ง€๊ฐ€ ์žฌํ™•๋ณด๋˜๋„๋ก ํ•˜์ž.
์ตœ์ข… ์ˆ˜์ • August 12, 2022 at 1:44 PM PST: [ko] sync the documents using comment (40bc0a1513)