본문 바로가기

Container/Kubernetes

[K8S] Storage/Volume

CSI(Container Storage Interface)

CSI는 컨테이너 오케스트레이션 시스템에서 스토리지 솔루션을 통합하고 사용할 수 있게 해주는 표준 인터페이스이다. CSI 표준이 도입됨으로써 스토리지 제공자는 쿠버네티스와 독립적으로 CSI 플러그인을 개발할 수 있게 되었고, 이를 통해 다양한 스토리지 솔루션의 확장성과 호환성이 크게 개선되었다. 

 

Volume 

 

쿠버네티스에서 Pod는 일시적이며, Pod가 삭제되면 그 안의 데이터도 삭제된다. (컨테이너 내의 디스크에 있는 파일은 임시적이다.)

kubelet은 컨테이너를 다시 시작하지만 초기화된 상태가 되며, Pod에서 같이 실행되는 컨테이너간에 파일을 공유할 때 큰 문제가 발생할 수 있다.  이 때문에 Volume을 Pod에 붙여서 데이터를 저장한다. (Pod가 삭제되어도 데이터는 남아있을 수 있게 !! )

 

👉  PV는 스토리지의 생명 주기가 Pod의 생명 주기와 분리되어 있어, Pod 가 삭제되거나 다시 생성되더라도 데이터가 보존될 수 있다.

 

Volume은 Kubernetes 스토리지의 추상화 개념이다. 컨테이너는 Pod에 바인딩되는 볼륨을 마운트하고 마치 로컬 파일시스템에 있는 것처럼 스토리지에 접근한다.

 

# 선언
volume:    # 파드에 제공할 볼륨 지정
  -name: html
   hostPath:
   path: /hostdir_or_file # 로컬 디스크

# 컨테이너 단위로 mount   (컨테이너 안에서 원하는 디렉터리로 마운트하는 작업)
volumeMounts:
  - name: html
    mountPath: /usr/share/ngins/html
  • Kubernetes는 다양한 종류의 볼륨 타입을 지원한다.
    • iSCSI: 원격지에서 TCP/IP 기반으로 동작하는 스토리지
    • fc(fibre channel): SAN환경에서 동작하는 스토리지 - 보통 공유 스토리지로 사용
    • NFS 
    • EBS - AWS  → deprecated
    • GCE PD
    • Azure Disk/file → deprecated
  • VolumeMount시 특별히 지정하지 않으면 read/write 권한으로 볼륨이 생성된다.

📑 hostPath (노드의 Local Disk)

    • 노드의 파일시스템의 디렉토리나 파일을 컨테이너에 마운트
    • 노드에 디렉토리나 파일을 생성하여 마운트 가능
    • 공유(shared) 데이터를 운영하는 것은 적합하지 않다. (어느 노드에 저장될 지 알 수 없기 때문에 별도의 Shared Storage를 하나 만들어서 접근 가능하도록 해야 한다. → PV/PVC)
    • 보통 로그를 수집하는 Agent 프로그램을 hostPath로 구성한다
  • hostPath는 type 지시어를 통해 mount 구성의 요구를 추가할 수 있다. (생략 가능)
DirectoryOrCreate  주어진 경로에 아무것도 없다면, 필요에 따라 kubelet의 소유권, 권한을 0755로 설정한 빈 디렉터리를 생성한다.
Directory 주어진 경로에 디렉토리가 있어야 함
FileOrCreate 주어진 경로에 아무것도 없다면, 필요에 따라 kubelet의 소유권, 권한을 0755로 설정한 filed을 생성한다.
File 주어진 경로에 파일이 있어야 함
[master ~]$cat volume-hostpath.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: volume-hostpath
spec:
  containers:
  - name: volume-hostpath
    image: nginx
    volumeMounts:
    - mountPath: /test-volume
      name: hostpath-vol
    ports:
    - containerPort: 8080
  volumes:
  - name: hostpath-vol
    hostPath:
      path: /tmp
      type: Directory

 

📑 emptyDir: Pod 안에서 임시 저장소를 사용해야 할 때.

  • emptyDir 볼륨은 빈 디렉토리로 시작
  • Pod 내부에서 실행중인 애플리케이션은 필요한 모든 파일을 작성
  • Pod를 삭제하면 볼륨의 내용이 손실됨
  • 동일한 Pod에서 실행되는 컨테이너 간에 파일을 공유할 때 유용 : multi container / sidecar

 

📑  NFS (Network File System) 

  • 여러 개의 Pod들이 동일 데이터를 참조
  • K8S의 Shared Disk를 Pod 볼륨으로 사용
  • NFS 서버가 공유하고 있는 데이터 디렉토리를 worker node의 Pod들이 access할 수 있도록 지원
  • 사전 준비
    • NFS 서버는 애플리케이션이 사용할 공유 디렉토리를 지원하고 있어야 한다.
    • worker node는 NFS 클라이언트가 되어서 NFS Server가 지원하는 공유 폴더에 접근할 수 있어야 한다.
  • NFS Volume 사용
  volumes:
  - name: test-volume
    nfs:
      server: my-nfs-server.example.com
      path: /my-nfs-volume
      readOnly: true
# 운영체제 버전 정보
root@cloudshell:~$  lsb_release -d
Description:    Ubuntu 22.04.4 LTS

# nfs 설치
https://scbyun.com/entry/%EB%A6%AC%EB%88%85%EC%8A%A4-NFSNetwork-File-Service-Server-%EC%84%A4%EC%B9%98

root@cloudshell:~$ exportfs
/sharedir/k8s
root@cloudshell:~$ cd /sharedir/k8s
root@cloudshell:/sharedir/k8s$ ls
index.html
root@cloudshell:/sharedir/k8s$ cat index.html
<h1> TTABAE-LEARN </h1>
root@cloudshell:~$ ip addr show dev eth0
나온 inet값 저장

# 파드에 등록
[master ~/Getting-Start-Kubernetes/14]$cat nfs.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: web-nfs
spec:
  containers:
  - image: nginx:1.14
    name: nginx
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
  volumes:
  - name: html
    nfs:
      server: 172.27.20.50 # eth0 inet 값 
      path: /sharedir/k8s # 공유하는 공간
      
[master ~/Getting-Start-Kubernetes/14]$kubectl apply -f nfs.yaml 
pod/web-nfs created
[master ~/Getting-Start-Kubernetes/14]$kubectl get pods -o wide
NAME      READY   STATUS              RESTARTS   AGE   IP       NODE                                       NOMINATED NODE   READINESS GATES
web-nfs   0/1     ContainerCreating   0          8s    <none>   gke-cluster-1-default-pool-697aeef7-xlub   <none>           <none>

[master ~/Getting-Start-Kubernetes/14]$curl IP
<h1> TTABAE-LEARN </h1>

 

참고:

 

[ 실습 - HostPath ]

controlplane $ cat > hostpath.yaml
apiVersion: v1
kind: Pod
metadata:
  name: web
spec:
  volumes:
  - name: html # (Type 선언) 원하는 이름
    hostPath:
      path: /webdata #스토리지 공간
  containers:
  - image: nginx:1.14
    name: nginx
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
      
controlplane $ kubectl apply -f hostpath.yaml 
pod/web created

controlplane $ kubectl get pods -o wide
NAME         READY   STATUS    RESTARTS   AGE     IP            NODE     NOMINATED NODE   READINESS GATES
my-pod-cka   1/1     Running   0          3m50s   192.168.1.5   node01   <none>           <none>
web          1/1     Running   0          2m10s   192.168.1.6   node01   <none>           <none>

[master ~]$kubectl apply -f hostpath.yaml 
pod/web created
controlplane $ kubectl exec -it web -- sh
# cd /usr/share/nginx/html
# cat > index.html
HI THIS IS HOSTPATH TEST
# exit

controlplane $ curl 192.168.1.6
HI THIS IS HOSTPATH TEST

 

[ 실습 - emptyDir ]

nginx 웹서버 pod가 생성한 로그파일을 받아서 STDOUT으로 출력하는 busybox 컨테이너 운영하기

apiVersion: v1
kind: Pod
metadata:
  name: weblog
spec:
  containers:
  - image: nginx:1.17
    name: web
    volumeMounts:
    - mountPath: /var/log/nginx
      name: log-volume
  - image: busybox
    name: log
    args: [/bin/sh, -c, "tail -n+1 -f /data/access.log"]
    volumeMounts:
    - mountPath: /data
      name: log-volume
      readOnly: true # default : readwrite
  volumes:
  - name: log-volume
    emptyDir: {}
    
controlplane:~$ kubectl get pods
NAME     READY   STATUS    RESTARTS   AGE
weblog   2/2     Running   0          42s

# container 로그 확인
controlplane:~$ kubectl logs weblog -c web
controlplane:~$ kubectl logs weblog -c log
172.30.2.2 - - [26/Feb/2025:14:00:15 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/8.5.0" "-"  # /data/access.log 가져오는 것 확인

 

[ 실습 - hostPath ]

도커 컨테이너 디렉토리 : /var/lib/docker/container

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
spec:
  selector:
    matchLabels:
      name: fluentd
  template:
    metadata:
      labels: 
        name: fluentd
    spec:
      containers:
      - name: fluentd
        image: fluentd
        volumeMounts:
        - mountPath: /var/lib/docker/containers
          name: docker-container-dir
        - mountPath: /var/log
          name: var-log-dir
      volumes:
      - name: docker-container-dir
        hostPath:
          path: /var/lib/docker/containers # directory location on host
      - name: var-log-dir
        hostPath:
          path: /var/log
          
controlplane:~$ kubectl get pods
NAME            READY   STATUS    RESTARTS   AGE
fluentd-nvj2q   1/1     Running   0          2m23s

controlplane:~$ kubectl describe pod fluentd-nvj2q
...
Volumes:
  docker-container-dir:
    Type:          HostPath (bare host directory volume)
    Path:          /var/lib/docker/containers
    HostPathType:  
  var-log-dir:
    Type:          HostPath (bare host directory volume)
    Path:          /var/log
    HostPathType:
반응형

'Container > Kubernetes' 카테고리의 다른 글

[K8S] CoreDNS  (0) 2024.04.21
[K8S] PV & PVC  (0) 2024.04.20
CKA 시험준비  (0) 2024.04.16
[K8S] RBAC  (0) 2024.04.15
[K8S] cordon & drain  (0) 2024.04.13