๋‹จ์ผ ์ธ์Šคํ„ด์Šค ์Šคํ…Œ์ดํŠธํ’€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰ํ•˜๊ธฐ

์ด ํŽ˜์ด์ง€์—์„œ๋Š” ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํด๋Ÿฌ์Šคํ„ฐ์—์„œ ํผ์‹œ์Šคํ„ดํŠธ๋ณผ๋ฅจ(PersistentVolume)๊ณผ ๋””ํ”Œ๋กœ์ด๋จผํŠธ(Deployment)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ, ๋‹จ์ผ ์ธ์Šคํ„ด์Šค ์Šคํ…Œ์ดํŠธํ’€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์ธ๋‹ค. ํ•ด๋‹น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ MySQL์ด๋‹ค.

๋ชฉ์ 

  • ์‚ฌ์šฉ์ž ํ™˜๊ฒฝ์˜ ๋””์Šคํฌ๋ฅผ ์ฐธ์กฐํ•˜๋Š” ํผ์‹œ์Šคํ„ดํŠธ๋ณผ๋ฅจ ์ƒ์„ฑํ•˜๊ธฐ
  • MySQL ๋””ํ”Œ๋กœ์ด๋จผํŠธ ์ƒ์„ฑํ•˜๊ธฐ
  • ์•Œ๋ ค์ง„ DNS ์ด๋ฆ„์œผ๋กœ ํด๋Ÿฌ์Šคํ„ฐ์˜ ๋‹ค๋ฅธ ํŒŒ๋“œ์— MySQL ์„œ๋น„์Šค ๋…ธ์ถœํ•˜๊ธฐ

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

MySQL ๋ฐฐํฌํ•˜๊ธฐ

์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ๋””ํ”Œ๋กœ์ด๋จผํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ํผ์‹œ์Šคํ„ดํŠธ๋ณผ๋ฅจํด๋ ˆ์ž„(PersistentVolumeClaim)์„ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ์กด ํผ์‹œ์Šคํ„ดํŠธ๋ณผ๋ฅจ์— ์—ฐ๊ฒฐํ•˜์—ฌ ์Šคํ…Œ์ดํŠธํ’€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์Œ YAML ํŒŒ์ผ์€ MySQL์„ ์‹คํ–‰ํ•˜๊ณ  ํผ์‹œ์Šคํ„ดํŠธ๋ณผ๋ฅจํด๋ ˆ์ž„์„ ์ฐธ์กฐํ•˜๋Š” ๋””ํ”Œ๋กœ์ด๋จผํŠธ๋ฅผ ๊ธฐ์ˆ ํ•œ๋‹ค. ์ด ํŒŒ์ผ์€ /var/lib/mysql์— ๋Œ€ํ•œ ๋ณผ๋ฅจ ๋งˆ์šดํŠธ๋ฅผ ์ •์˜ํ•œ ํ›„์—, 20G์˜ ๋ณผ๋ฅจ์„ ์š”์ฒญํ•˜๋Š” ํผ์‹œํŠธํ„ดํŠธ๋ณผ๋ฅจํด๋ ˆ์ž„์„ ์ƒ์„ฑํ•œ๋‹ค. ์ด ํด๋ ˆ์ž„์€ ์š”๊ตฌ ์‚ฌํ•ญ์— ์ ํ•ฉํ•œ ๊ธฐ์กด ๋ณผ๋ฅจ์ด๋‚˜ ๋™์  ํ”„๋กœ๋น„์ €๋„ˆ์— ์˜ํ•ด์„œ ์ถฉ์กฑ๋œ๋‹ค.

์ฐธ๊ณ : config yaml ํŒŒ์ผ์— ์ •์˜๋œ ๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” ์•ˆ์ „ํ•˜์ง€ ์•Š๋‹ค. ๋” ์•ˆ์ „ํ•œ ํ•ด๊ฒฐ๋ฐฉ๋ฒ•์„ ์œ„ํ•ด ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ์‹œํฌ๋ฆฟ ์„ ๋ณด์ž

apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  ports:
  - port: 3306
  selector:
    app: mysql
  clusterIP: None
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - image: mysql:9
        name: mysql
        env:
          # Use secret in real usage
        - name: MYSQL_ROOT_PASSWORD
          value: password
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pv-claim
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv-volume
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 20Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi

  1. YAML ํŒŒ์ผ์˜ PV์™€ PVC๋ฅผ ๋ฐฐํฌํ•œ๋‹ค.

     kubectl apply -f https://k8s.io/examples/application/mysql/mysql-pv.yaml
    
  2. YAML ํŒŒ์ผ์˜ ๋‹ค๋ฅธ ์˜ค๋ธŒ์ ํŠธ๋“ค์„ ๋ฐฐํฌํ•œ๋‹ค.

     kubectl apply -f https://k8s.io/examples/application/mysql/mysql-deployment.yaml
    
  3. ๋””ํ”Œ๋กœ์ด๋จผํŠธ์— ๊ด€ํ•œ ์ •๋ณด๋ฅผ ํ™•์ธํ•œ๋‹ค.

     kubectl describe deployment mysql
    

    ์ถœ๋ ฅ์€ ๋‹ค์Œ๊ณผ ์œ ์‚ฌํ•˜๋‹ค.

     Name:                 mysql
     Namespace:            default
     CreationTimestamp:    Tue, 01 Nov 2016 11:18:45 -0700
     Labels:               app=mysql
     Annotations:          deployment.kubernetes.io/revision=1
     Selector:             app=mysql
     Replicas:             1 desired | 1 updated | 1 total | 0 available | 1 unavailable
     StrategyType:         Recreate
     MinReadySeconds:      0
     Pod Template:
       Labels:       app=mysql
       Containers:
        mysql:
         Image:      mysql:9
         Port:       3306/TCP
         Environment:
           MYSQL_ROOT_PASSWORD:      password
         Mounts:
           /var/lib/mysql from mysql-persistent-storage (rw)
       Volumes:
        mysql-persistent-storage:
         Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
         ClaimName:  mysql-pv-claim
         ReadOnly:   false
     Conditions:
       Type          Status  Reason
       ----          ------  ------
       Available     False   MinimumReplicasUnavailable
       Progressing   True    ReplicaSetUpdated
     OldReplicaSets:       <none>
     NewReplicaSet:        mysql-63082529 (1/1 replicas created)
     Events:
       FirstSeen    LastSeen    Count    From                SubobjectPath    Type        Reason            Message
       ---------    --------    -----    ----                -------------    --------    ------            -------
       33s          33s         1        {deployment-controller }             Normal      ScalingReplicaSet Scaled up replica set mysql-63082529 to 1
    
  4. ๋””ํ”Œ๋กœ์ด๋จผํŠธ๋กœ ์ƒ์„ฑ๋œ ํŒŒ๋“œ๋ฅผ ๋‚˜์—ดํ•œ๋‹ค.

     kubectl get pods -l app=mysql
    

    ์ถœ๋ ฅ์€ ๋‹ค์Œ๊ณผ ์œ ์‚ฌํ•˜๋‹ค.

     NAME                   READY     STATUS    RESTARTS   AGE
     mysql-63082529-2z3ki   1/1       Running   0          3m
    
  5. ํผ์‹œ์Šคํ„ดํŠธ๋ณผ๋ฅจํด๋ ˆ์ž„์„ ์‚ดํŽด๋ณธ๋‹ค.

     kubectl describe pvc mysql-pv-claim
    

    ์ถœ๋ ฅ์€ ๋‹ค์Œ๊ณผ ์œ ์‚ฌํ•˜๋‹ค.

     Name:         mysql-pv-claim
     Namespace:    default
     StorageClass:
     Status:       Bound
     Volume:       mysql-pv-volume
     Labels:       <none>
     Annotations:    pv.kubernetes.io/bind-completed=yes
                     pv.kubernetes.io/bound-by-controller=yes
     Capacity:     20Gi
     Access Modes: RWO
     Events:       <none>
    

MySQL ์ธ์Šคํ„ด์Šค ์ ‘๊ทผํ•˜๊ธฐ

์ด์ „์˜ YAML ํŒŒ์ผ์€ ํด๋Ÿฌ์Šคํ„ฐ์˜ ๋‹ค๋ฅธ ํŒŒ๋“œ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ์„œ๋น„์Šค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. clusterIP: None ์„œ๋น„์Šค ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ์„œ๋น„์Šค์˜ DNS ์ด๋ฆ„์„ ์ง์ ‘ ํŒŒ๋“œ์˜ IP ์ฃผ์†Œ๋กœ ํ•ด์„ํ•˜๋„๋ก ์ฒ˜๋ฆฌํ•œ๋‹ค. ์ด ๋ฐฉ๋ฒ•์€ ์„œ๋น„์Šค์—์„œ ์—ฐ๊ฒฐ๋˜๋Š” ํŒŒ๋“œ๊ฐ€ ์˜ค์ง ํ•˜๋‚˜ ๋ฟ์ด๊ณ , ํŒŒ๋“œ์˜ ์ˆ˜๋ฅผ ๋” ๋Š˜๋ฆด ํ•„์š”๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ์— ๊ฐ€์žฅ ์ ํ•ฉํ•˜๋‹ค.

์„œ๋ฒ„์— ์ ‘์†ํ•˜๊ธฐ ์œ„ํ•˜์—ฌ MySQL ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

kubectl run -it --rm --image=mysql:9 --restart=Never mysql-client -- mysql -h mysql -ppassword

์ด ๋ช…๋ น์–ด๋Š” MySQL ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ํŒŒ๋“œ๋ฅผ ํด๋Ÿฌ์Šคํ„ฐ์— ์ƒ์„ฑํ•˜๊ณ , ์„œ๋น„์Šค๋ฅผ ํ†ตํ•˜์—ฌ ์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•œ๋‹ค. ์—ฐ๊ฒฐ๋œ๋‹ค๋ฉด, ์Šคํ…Œ์ดํŠธํ’€ MySQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ์‹คํ–‰ ์ค‘์ž„์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

Waiting for pod default/mysql-client-274442439-zyp6i to be running, status is Pending, pod ready: false
If you don't see a command prompt, try pressing enter.

mysql>

์—…๋ฐ์ดํŠธํ•˜๊ธฐ

kubectl apply ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ธฐ์กด๊ณผ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ ๋””ํ”Œ๋กœ์ด๋จผํŠธ์˜ ์ด๋ฏธ์ง€๋‚˜ ๋‹ค๋ฅธ ๋ถ€๋ถ„์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค. ์Šคํ…Œ์ดํŠธํ’€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ๊ด€๋ จํ•˜์—ฌ ๋ช‡ ๊ฐ€์ง€ ์ฃผ์˜ ์‚ฌํ•ญ์ด ์žˆ๋‹ค.

  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์Šค์ผ€์ผ๋งํ•˜์ง€ ์•Š๋Š”๋‹ค. ์ด ์„ค์ •์€ ๋‹จ์ผ ์ธ์Šคํ„ด์Šค ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์šฉ์ด๋‹ค. ๊ธฐ๋ณธ์ ์ธ ํผ์‹œ์Šคํ„ดํŠธ๋ณผ๋ฅจ์€ ํ•˜๋‚˜์˜ ํŒŒ๋“œ์—์„œ๋งŒ ๋งˆ์šดํŠธํ•  ์ˆ˜ ์žˆ๋‹ค. ํด๋Ÿฌ์Šคํ„ฐ ํ˜•ํƒœ์˜ ์Šคํ…Œ์ดํŠธํ’€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋Œ€ํ•ด์„œ๋Š” ์Šคํ…Œ์ดํŠธํ’€์…‹์„ ๋ณด์ž.
  • ๋””ํ”Œ๋กœ์ด๋จผํŠธ ๊ตฌ์„ฑ YAML ํŒŒ์ผ์—์„œ strategy: type: Recreate ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์ด๋Š” ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๊ฐ€ ๋กค๋ง ์—…๋ฐ์ดํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋„๋ก ์ง€์‹œํ•œ๋‹ค. ๋™์‹œ์— ๋‘ ๊ฐœ ์ด์ƒ์˜ ํŒŒ๋“œ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ, ๋กค๋ง ์—…๋ฐ์ดํŠธ๋Š” ์ผ์–ด๋‚˜์ง€ ์•Š๊ฒŒ ๋œ๋‹ค. Recreate ์ „๋žต์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ณ€๊ฒฝ๋œ ๊ตฌ์„ฑ์œผ๋กœ ์ƒˆ๋กœ์šด ํŒŒ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ์— ์•ž์„œ ๊ธฐ์กด์˜ ํŒŒ๋“œ๋ฅผ ์ค‘๋‹จํ•œ๋‹ค.

๋””ํ”Œ๋กœ์ด๋จผํŠธ ์‚ญ์ œํ•˜๊ธฐ

์ด๋ฆ„์œผ๋กœ ๋ฐฐํฌ๋œ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์‚ญ์ œํ•œ๋‹ค.

kubectl delete deployment,svc mysql
kubectl delete pvc mysql-pv-claim
kubectl delete pv mysql-pv-volume

ํผ์‹œ์Šคํ„ดํŠธ๋ณผ๋ฅจ์„ ์ˆ˜๋™์œผ๋กœ ํ”„๋กœ๋น„์ €๋‹ํ•œ ๊ฒฝ์šฐ๋ผ๋ฉด, ๋™์ผํ•˜๊ฒŒ ์ˆ˜๋™์œผ๋กœ ์‚ญ์ œํ•˜๊ณ  ๊ธฐ๋ณธ ๋ฆฌ์†Œ์Šค๋„ ํ•ด์ œํ•ด์•ผ ํ•œ๋‹ค. ๋™์  ํ”„๋กœ๋น„์ €๋„ˆ๋ฅผ ์‚ฌ์šฉํ•œ ๊ฒฝ์šฐ, ํผ์‹œ์Šคํ„ดํŠธ๋ณผ๋ฅจํด๋ ˆ์ž„์ด ์‚ญ์ œ๋˜์—ˆ์„ ๋•Œ์— ํผ์‹œ์Šคํ„ดํŠธ๋ณผ๋ฅจ ๋˜ํ•œ ์ž๋™์œผ๋กœ ์‚ญ์ œ๋œ๋‹ค. ์ผ๋ถ€ ๋™์  ํ”„๋กœ๋น„์ €๋„ˆ(EBS ์™€ PD์™€ ๊ฐ™์€)๋Š” ํผ์‹œ์Šคํ„ดํŠธ๋ณผ๋ฅจ์„ ์‚ญ์ œํ•  ๋•Œ์— ๊ธฐ๋ณธ ๋ฆฌ์†Œ์Šค๋„ ํ•ด์ œํ•œ๋‹ค.

๋‹ค์Œ ๋‚ด์šฉ

์ตœ์ข… ์ˆ˜์ • May 07, 2025 at 11:35 AM PST: [ko] Upgrade mysql image version used by Single-Instance Stateful tutorial (d5add27b0c)