버전 비교

  • 이 줄이 추가되었습니다.
  • 이 줄이 삭제되었습니다.
  • 서식이 변경되었습니다.
목차

...

1. Resource Policies

2.1 Request / Limit (최소요구사항/최대 사용량)

  • 쿠버네티스에서 파드를 어느 노드에 배포할지 스케쥴링 할 때, 스케쥴링이 될 노드에 해당 파드가 동작할 수 있는 충분한 자원이 확보가 되어야 합니다.

  • 쿠버네티스에서 파드(컨테이너)에 필요한 리소스 양을 명시 할 수 있도록 설정을 지원합니다.

  • cpu/memory와 같은 컴퓨트 리소스 외에도 gpu/storage 리소스에 대한 쿼터도 지정 할 수 있습니다.

  • CPU는 m(밀리코어, 1코어=1000밀리코어) 단위로 지정하며, 해당 컨테이너에 어느정도의 CPU를 할당할 것인지를 지정합니다.

  • 메모리는 Mi(Mib)를 사용합니다.

8/00-pod-resource.yaml

코드 블럭
---
apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: app
    image: images.my-company.example/app:v4nginx:latest
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
  - name: log-aggregator
    image: images.my-company.examplerancher/log-aggregator:v6v0.1.8
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

...

코드 블럭
root@k8s-master01:~# kubectl -n kube-system top pod | sort -n -k 2
NAME                                       CPU(cores)   MEMORY(bytes)
nginx-proxy-k8s-worker01                   1m           16Mi
nginx-proxy-k8s-worker02                   1m           17Mi
dns-autoscaler-59b8867c86-hjkvs            2m           7Mi
kube-controller-manager-k8s-master02       4m           19Mi
kube-controller-manager-k8s-master03       4m           19Mi
nodelocaldns-rdkbl                         4m           15Mi
coredns-588bb58b94-9qcvw                   5m           16Mi
kube-scheduler-k8s-master02                5m           20Mi
nodelocaldns-sd99v                         5m           10Mi
coredns-588bb58b94-zcnvc                   6m           14Mi
kube-proxy-h584h                           7m           22Mi
kube-scheduler-k8s-master03                7m           19Mi
nodelocaldns-9vlvr                         7m           9Mi
nodelocaldns-b8gpm                         7m           9Mi
metrics-server-6f77f96b88-v5jjs            8m           17Mi
nodelocaldns-r4sjf                         8m           16Mi
kube-scheduler-k8s-master01                9m           21Mi
kube-proxy-x8gcq                           12m          22Mi
calico-kube-controllers-75748cc9fd-gqdzw   13m          21Mi
kube-proxy-w87v4                           13m          15Mi
kube-proxy-96tsm                           20m          15Mi
kube-proxy-tj8pv                           24m          14Mi
kube-controller-manager-k8s-master01       36m          52Mi
calico-node-87g22                          42m          85Mi
calico-node-kk5vn                          51m          84Mi
calico-node-wckv7                          51m          85Mi
calico-node-8278d                          64m          91Mi
etcd-k8s-master02                          70m          89Mi
calico-node-4hzx4                          71m          109Mi
kube-apiserver-k8s-master02                77m          303Mi
etcd-k8s-master03                          81m          84Mi
kube-apiserver-k8s-master01                94m          349Mi
etcd-k8s-master01                          99m          95Mi
kube-apiserver-k8s-master03                111m         310Mi

2.2 ResourceQuota

  • 쿠버네티스 운영 시 특정 팀에서 많은 리소스를 요구할 경우 ResourceQuota를 이용하여 네임스페이스별로 사용할 수 있는 리소스의 양을 정하고, 컨테이너 마다 사용 할 수 있는 양을 지정할 수 있습니다.

...

  • 쿼터 오브젝트를 생성하여 특정 우선 순위의 파드와 일치 시키며, "low(낮음)", "medium(중간)", "high(높음)"의 세 가지 우선 순위 클래스 중 하나를 가질 수도 있습니다.

...

8/01-resourcequota.yaml

코드 블럭
---
apiVersion: v1
kind: ResourceQuota
metadata:
  name: default
spec:
  hard:
    cpu: "1000"
    memory: 200Gi
    pods: "10"
#  scopeSelector:
#    matchExpressions:
#    - operator : In
#      scopeName: PriorityClass
#      values: ["high"]

8/02-resourcequota-test.yaml

코드 블럭
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.19
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: "64Mi"
            cpu: "250m"
          limits:
            memory: "128Mi"
            cpu: "500m"

코드 블럭
root@k8s-master01:~# kubectl get pod
NAME                               READY   STATUS    RESTARTS   AGE
nginx-deployment-5bccc488d-bqkvz   1/1     Running   0          18h
nginx-deployment-5bccc488d-r4s5d   1/1     Running   0          18h
nginx-deployment-5bccc488d-z29wp   1/1     Running   0          18h

root@k8s-master01:~# kubectl get quota
NAME      AGE   REQUEST                                         LIMIT
default   32s   cpu: 750m/1k, memory: 192Mi/200Gi, pods: 3/10

...

  • ResourceQuota를 사용하면 네임스페이스의 리소스를 제한하고, LimitRange는 네임스페이스 내 파드(컨테이너)의 리소스를 제한합니다.

  • 사용자가 컨테이너 리소스를 너무 크게 사용하면 특정 컨테이너가 많은 리소스를 점유하는 것을 방지할 수 있기 때문에 LimitRange를 사용합니다.

...

코드 블럭
# k delete quota/default                                              

...

 

...

     

...

       

...

 

...

  │INGW64 ~/project/2024
resourcequota 

...

코드 블럭
root@k8s-master01:~# cat LimitRange.yaml
"default" deleted 

2.3 LimitRange

  • ResourceQuota를 사용하면 네임스페이스의 리소스를 제한하고, LimitRange는 네임스페이스 내 파드(컨테이너)의 리소스를 제한합니다.

  • 사용자가 컨테이너 리소스를 너무 크게 사용하면 특정 컨테이너가 많은 리소스를 점유하는 것을 방지할 수 있기 때문에 LimitRange를 사용합니다.

8/03-limitrange.yaml

코드 블럭
apiVersion: v1
kind: LimitRange
metadata:
  name: cpu-min-max-demo-lr
  namespace: default
spec:
  limits:
  - max:
      cpu: "800m"
    min:
      cpu: "200m"
    type: Pod #Container

...

8/04-limitrange-test.yaml

코드 블럭
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.19
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: "64Mi"
            cpu: "1000m"
          limits:
            memory: "128Mi"
            cpu: "1500m"

경고

# kubectl get event --sort-by='lastTimestamp'
LAST SEEN TYPE REASON OBJECT MESSAGE
78s Warning FailedCreate replicaset/nginx-deployment-8579d7f98c Error creating: pods "nginx-deployment-8579d7f98c-mxw8q" is forbidden: maximum cpu usage per Pod is 800m, but limit is 1500m

2. Label & Selector

  • Label

    • Label은 Pod와 같은 객체에 연결된 키/값 쌍입니다.

    • 리소스를 논리적인 그룹으로 나누거나, 식별의 편의를 위해 붙이는 이름표입니다.

    • Label은 생성 시 객체에 첨부할 수 있으며 나중에 언제든지 추가 및 수정할 수 있습니다.

  • Selector

    • 특정 Label에 해당하는 객체를 식별하고 검색할 수 있습니다.

2.1 Node Label

...

코드 블럭
# Node Label 확인
kubectl get nodes --show-labels

# Node Label 추가
kubectl label nodes k8s-worker01 svc=web

2.2 Pod Selector

pod-label.yml

...

코드 블럭
# k delete limitrange/cpu-min-max-demo-lr                                             │INGW64 ~/project/2024
limitrange "cpu-min-max-demo-lr" deleted    
# k delete -f 04-limitrange-test.yaml                                                 │
deployment.apps "nginx-deployment" deleted

...

2. Label & Selector

  • 쿠버네티스 스케줄링에 포함된 내용입니다.

  • 노드-파드도 Label&Selector를 이용하여 노드의 리소스 관리를 할 수 있고, 서비스-파드도 Label&Selector를 이용하여 엔드포인트를 지정합니다.

  • Label

    • Label은 Pod와 같은 객체에 연결된 키/값 쌍입니다.

    • 리소스를 논리적인 그룹으로 나누거나, 식별의 편의를 위해 붙이는 이름표입니다.

    • Label은 생성 시 객체에 첨부할 수 있으며 나중에 언제든지 추가 및 수정할 수 있습니다.

  • Selector

    • 특정 Label에 해당하는 객체를 식별하고 검색할 수 있습니다.

2.1 Node Label

코드 블럭
# Node Label 확인
kubectl get nodes --show-labels

# Node Label 추가
kubectl label nodes w1-k8s svc=web

2.2 Pod Selector

8/05-pod-selector.yaml

코드 블럭
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:
    svc: web
코드 블럭
8# k get pod -o wide
NAME                                      READY   STATUS        RESTARTS       AGE     IP               NODE     NOMINATED NODE   READINESS GATES
frontend                                  2/2     Running       2 (3h3m ago)   4h50m   172.16.132.5     w3-k8s   <none>           <none>
nfs-client-provisioner-5cf87f6995-rdkfr   1/1     Running       40 (14m ago)   14h     172.16.221.136   w1-k8s   <none>           <none>
nginx                                     1/1     Running       0              5m3s    172.16.221.140   w1-k8s   <none>           <none>

...

3. 쿠버네티스 볼륨

지금까지 우리는 많은 실습을 통해 Pod를 배포하고 Service를 만들어 접속 할 수 있게 되었습니다.

...

이러한 데이터의 유지를 위하여 volume을 사용 합니다.

3.1 emptyDir

  • emptyDir 볼륨은 파드가 노드에 할당될 때 처음 생성되며, 해당 노드에서 파드가 실행되는 동안에만 존재합니다.

  • 이름에서 알 수 있듯이 emptyDir 볼륨은 처음에는 비어있습니다.

  • 파드 내 모든 컨테이너는 emptyDir 볼륨에서 동일한 파일을 읽고 쓸 수 있지만, 해당 볼륨은 각각의 컨테이너에서 동일하거나 다른 경로에 마운트 될 수 있습니다.

  • 노드에서 파드가 제거되면 emptyDir 의 데이터가 영구적으로 삭제됩니다.

  • emptyDir은 주로 Pod내부에서 실행 중인 애플리케이션 간의 휘발성 파일을 공유할 때 유용하게 사용 됩니다.

  • 공유가 필요 없는 볼륨이라면 굳이 emptyDir를 사용 할 필요는 없습니다 명시하지 않은 모든 볼륨의 데이터는 휘발성입니다 (이미지에 존재하지 않는 mountpath생성을 위한 용도로는 사용할 될 수 있습니다)

...

  • nginx pod내 empytidir 을 /cache볼륨으로 마운트 하는 yaml입니다

012.nginx-vol-1.yml8/06-volume-emptydir.yaml

코드 블럭
languageyaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-vol-1
  labels:
    app: nginx-vol-1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-vol-1
  template:
    metadata:
      labels:
        app: nginx-vol-1
    spec:
      containers:
      - name: nginx-vol-1
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: cache-volume
          mountPath: /cache
      volumes:
      - name: cache-volume
        emptyDir: {}

...

코드 블럭
languagebash
[root@m-k8s vagrant]# k apply -f 012.nginx06-volvolume-1emptydir.ymlyaml 
deployment.apps/nginx-vol-1 created
[root@m-k8s vagrant]# k get pods
NAME                           READY   STATUS    RESTARTS   AGE
nginx-vol-1-77d6454655-xscpd   1/1     Running   0          38s

 
위와같이 Running 상태가 되면 pod내 볼륨이 정상적으로 mount되었는지 확인 합니다
 
[root@m-k8s vagrant]# k exec -it nginx-vol-1-77d6454655-xscpd -- df -h
Filesystem                   Size  Used Avail Use% Mounted on
overlay                       37G  5.4G   32G  15% /
tmpfs                         64M     0   64M   0% /dev
tmpfs                        1.5G     0  1.5G   0% /sys/fs/cgroup
/dev/mapper/centos_k8s-root   37G  5.4G   32G  15% /cache
shm                           64M     0   64M   0% /dev/shm
tmpfs                        2.9G   12K  2.9G   1% /run/secrets/kubernetes.io/serviceaccount
tmpfs                        1.5G     0  1.5G   0% /proc/acpi
tmpfs                        1.5G     0  1.5G   0% /proc/scsi
tmpfs                        1.5G     0  1.5G   0% /sys/firmware
 
# 마운트 확인 
/dev/mapper/centos_k8s-root   37G  5.4G   32G  15% /cache 가 정상적으로 마운트 되었습니다

/dev/mapper/centos_k8s-root은 worker node의 root disk입니다
 
[root@mroot@cp-k8s mapper]# ssh vagrant@w1-k8s
vagrant@w1-k8s's password: 
[vagrant@w1-k8s ~]$ ls -al /dev/mapper/centos_k8s-root 
lrwxrwxrwx. 1 root root 7 Sep 12 13:49 /dev/mapper/centos_k8s-root -> ../dm-0



# 파일을 쓰고 파드를 삭제하여 데이터가 존재하는지 확인 합니다
[root@m-k8s mapper]# k get pods
NAME                           READY   STATUS    RESTARTS   AGE
nginx-vol-1-77d6454655-xscpd   1/1     Running   0          4m34s
[root@m-k8s mapper]# k exec -it nginx-vol-1-77d6454655-xscpd -- bash -c "echo 'test' > /cache/test.txt "

[root@m-k8s mapper]# k exec -it nginx-vol-1-77d6454655-xscpd -- ls -al /cache
total 4
drwxrwxrwx. 2 root root 22 Sep 13 00:33 .
drwxr-xr-x. 1 root root 52 Sep 13 00:28 ..
-rw-r--r--. 1 root root  5 Sep 13 00:33 test.txt


[root@m-k8s vagrant]# k get pod
NAME                           READY   STATUS    RESTARTS   AGE
nginx-vol-1-77d6454655-xscpd   1/1     Running   0          8s
[root@m-k8s vagrant]# k delete pod/nginx-vol-1-77d6454655-xscpd 
pod "nginx-vol-1-77d6454655-xscpd" deleted


# deploy로 pod가 재배포 되길 기다립니다
[root@m-k8s vagrant]# k get pod
NAME                           READY   STATUS    RESTARTS   AGE
nginx-vol-1-77d6454655-fd9tg   1/1     Running   0          6s


# 새로운 pod가 배포 되었습니다
# 이후 해당 pod에 마운트된 /cache볼륨에 이전에 생성한 파일이 남아있는지 확인 합니다.
[root@m-k8s vagrant]# kubectl  exec -it nginx-vol-1-77d6454655-fd9tg -- ls -al /cache
total 0
drwxrwxrwx. 2 root root  6 Sep 13 02:01 .
drwxr-xr-x. 1 root root 52 Sep 13 02:01 ..
 
 
이전에 만든 test.txt가 존재하지 않습니다(Pod가 제거되면 emptydir속성의 볼륨도 삭제)
 
# 다음 실습을 위해 환경을 정리 합니다.
[root@m-k8s vagrant]# k delete -f 012.nginx06-volvolume-1emptydir.ymlyaml 
deployment.apps "nginx-vol-1" deleted
 

...

(2) 멀티 컨테이너를 가지는 파드에서의 emptyDir 볼륨 파일공유를 확인합니다.

012.nginx-vol-2.yml8/07-volume-emptydir-multicon.yaml

코드 블럭
languageyaml
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx-vol-2
spec:
  containers:
  - image: nginx
    name: nginx
    volumeMounts:
    - name: cache-volume
      mountPath: /cache
      readOnly: true           #cache 디렉토리를 read only로 마운트 한다
  - image: luksa/fortune
    name: fortune
    volumeMounts:
    - name: cache-volume
      mountPath: /cache
  volumes:
  - name: cache-volume

...

코드 블럭
languagebash
kubectl apply -f 012.nginx-vol-2.yml07-volume-emptydir-multicon.yaml 
pod/nginx-vol-2 created
 
kubectl get pod
NAME          READY   STATUS    RESTARTS   AGE
nginx-vol-2   2/2     Running   0          8s
 
# 확인하면 포드내 컨테이너가 2개로 보입니다
# 생성된 컨테이너를 확인합니다
 
# 컨테이너가 2개 이상인경우 get pod 명령어를 활용해서 컨테이너를 식별하고 제어하지 못합니다.
$ kubectl describe pod/nginx-vol-2
......
Containers:
  nginx:
    Container ID:   containerd://a9eac4ae13b2a8f052fe9bf6eca53c93e95c0de7ce4352cf1e77a0c4d2e1c5bb
    Image:          nginx
    Image ID:       docker.io/library/nginx@sha256:6926dd802f40e5e7257fded83e0d8030039642e4e10c4a98a6478e9c6fe06153
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Wed, 13 Sep 2023 11:05:21 +0900
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /cache from cache-volume (ro)
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-pjccg (ro)
  fortune:
    Container ID:   containerd://6e343b738170e0b1d0b0fa18fe641c0cd0b1257ae3cab9d7fc75fff041f09084
    Image:          luksa/fortune
    Image ID:       docker.io/luksa/fortune@sha256:814dd72ecc4b431560ca6ede8649fc4862c401ba5b6d37520e6672e0657deea9
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Wed, 13 Sep 2023 11:05:33 +0900
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /cache from cache-volume (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-pjccg (ro)
 
Volumes:
  cache-volume:
    Type:       EmptyDir (a temporary directory that shares a pod's lifetime)
    Medium:     
    SizeLimit:  <unset>
 

# 두번째 yml을 보면 volume type을 EmptyDir로 선언하는것을 생략하였습니다 아무런 type이 없으면 기본값으로 EmptyDir를 사용 하게 됩니다
  .....
 
 
# nginx와 fortune 2개의 컨테이너가 생성된것을 확인 할수 있습니다
# rw로 마운트된 fortune에서 파일을 생성하고 nginx컨테이너에서 파일을 볼수 있는지 실습 해봅시다
 
 
# pod내 컨테이너 선택은 -c옵션을 이용합니다
# fortune 컨테이너에서 만든 파일을 같은 pod내에 있는 nginx컨테이너테서 확인 할 수 있습니다.
[root@m-k8s vagrant]# kubectl exec nginx-vol-2 -c fortune  -- bash -c ' echo "test" > /cache/test.txt '
[root@m-k8s vagrant]# kubectl exec nginx-vol-2 -c fortune  -- ls -l /cache
total 4
-rw-r--r--. 1 root root 5 Sep 13 02:19 test.txt
[root@m-k8s vagrant]# kubectl exec nginx-vol-2 -c nginx  -- ls -l /cache
total 4
-rw-r--r--. 1 root root 5 Sep 13 02:19 test.txt
 
# 아래와 같이 nginx는 ro권한밖에 없으므로, 실제 write는 불가능합니다.
[root@m-k8s vagrant]# kubectl exec nginx-vol-2 -c nginx  -- bash -c 'echo "test" > /cache/test2.txt'
bash: line 1: /cache/test2.txt: Read-only file system
command terminated with exit code 1
 
# 실습환경을 정리합니다. 
kubectl delete -f 012.nginx-vol-2.yml07-volume-emptydir-multicon.yaml 
pod "nginx-vol-2" deleted
 
 
*기본적으로 emptydir은 worker노드에 디스크(파일시스템)에 생성되지만 상황에따라 memory나 fc disk등에 생성 할 수도 있습니다.

3.2 hostpath

  • hostPath 볼륨은 호스트 노드의 파일시스템에 있는 파일이나 디렉터리를 파드에 마운트 합니다.

  • emptydir과 달리 pod를 삭제하여도 워커노드의 파일은 삭제되지 않습니다.

  • 각 워커노드의 파일이 다를 수 있으므로 사용에 주의하도록 합니다.

    • node seletor를 이용하여 필요한 볼륨이 있는 node만 스케줄되게 하거나 모든 node가 동일한 파일을 가지거나 등의 조치를 하지 않고 배포 시 문제가 발생 할 수 있습니다.

...

(2) 해당 hostpath를 사용하는 yaml을 작성합니다.

012.nginx-vol-38/08-volume-hostpath.yaml

코드 블럭
languageyaml
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx-vol-3
spec:
  containers:
  - name: nginx-vol-3
    image: nginx
    volumeMounts:
    - name: host-path-volume
      mountPath: /usr/share/nginx/html
  nodeName: w1-k8s             #노드네임을 이용하여 woker1번에서 구동되도록 만든다. 본인 서버의 워크 노드 이름으로 변경한다. 
  volumes:
  - name: host-path-volume
    hostPath:
      path: /hostpath        # Path를 잘못 입력하여 못찾는 경우 컨테이너가 기동되지 않는다.
      type: Directory

...

코드 블럭
languagebash
# yaml 파일을 적용합니다.
kubectl apply -f 012.nginx08-volvolume-3hostpath.ymlyaml
 
# 생성된 파드에서 마운트 된 경로의 파일을 확인합니다.
kubectl exec -it nginx-vol-3 -- ls -l /usr/share/nginx/html
total 4
-rw-r--r-- 1 root root 9 Apr 28 01:17 index.html

# 파일 내용을 확인합니다.
kubectl exec -it nginx-vol-3 -- cat /usr/share/nginx/html/index.html
hihihihi
 

[root@m-k8s vagrant]# kubectl get pod -o wide
NAME          READY   STATUS    RESTARTS   AGE    IP               NODE     NOMINATED NODE   READINESS GATES
nginx-vol-3   1/1     Running   0          107s   172.16.221.185   w1-k8s   <none>           <none>
[root@m-k8s vagrant]# 
[root@m-k8s vagrant]# curl 172.16.221.185
hihihihi
 
 
# node에서 생성한 파일이 pod에 hostpath를 이용해 마운트 된것을 확인 할 수 있습니다. 
# hostpath의 경우 권한이 다르면 사용할수 없으므로 컨테이너 내 사용자로 권한을 바꾸거나 root사용자로 구동되도록 하여야 합니다.
 
 
# 실습을 위해 실습환경을 정리합니다.
[root@m-k8s vagrant]# kubectl delete -f 012.nginx08-volvolume-3hostpath.ymlyaml
pod "nginx-vol-3" deleted

3.3 NFS

  • NFS를 volume으로 사용할 수 있습니다.

  • NFS를 이용하면 여러 pod에 동일한 volume을 마운트 할 수 있고, 여러 노드가 읽고 쓸 수 있으므로 파일 공유에 많은 이점이 있습니다.

(1) 실습을 위하여 worker2번 w2-k8s번 노드에 nfs서버를 임시로 구성하여 진행 합니다

코드 블럭
# nfs-utils 패키지를 설치 합니다
yumapt install -y nfs-utilsserver
 
 
# nfs 공유로 사용할 폴더를 생성하고 테스트에 사용할 index.html 파일을 생성합니다
mkdir /nfs
chmod 777 /nfs 
echo "hihihi" > /nfs/index.html
 
# nfs공유 설정을 해줍니다.
cat <<EOF | tee /etc/exports
/nfs *(rw,no_root_squash)
EOF
 
 
# nfs서버 서비스를 실행하고 활성화 합니다.
systemctl enable nfs-server --now
Created symlink from /etc/systemd/system/multi-user.target.wants/nfs-server.service to /usr/lib/systemd/system/nfs-server.service.
 
# 확인
# 출력값이 없으면 [systemctl restart nfs-server] 실행합니다.
systemctl restart nfs-server  

[root@w2-k8s ~]# exportfs
/nfs            w2-k8s
 
# nfs설정이 정상인지 worker1번에서 마운트 하여 테스트 합니다 
ssh w1-k8s
 
# 모든 마스터/워커노드에서 nfs 패키지를 설치합니다.
yumapt install nfs-utils -ycommon
 
mkdir /nfs
mount w2-k8s:/nfs /nfs
df -h
Filesystem      Size  Used Avail Use% Mounted on
.....
192.168.1.102:/nfs           38770304 4569856  34200448  12% /nfs
.....
 
 
[root@w1-k8s /]# ll /nfs
total 4
-rw-r--r--. 1 root root 6 Sep 13 12:47 index.html
 
#nfs서버가 정상 작동되는것을 확인 했으니 이제 실습을 진행 합니다.

#/nfs 폴더를 umount 해줍니다.
umount /nfs        
 
이제 설정이 완료된 nfs볼륨을 이용하여 pod를 생성하여 줍니다
 

(2) 설정이 완료된 NFS 볼륨을 이용하여 마운트하는 파드 yaml 파일을 작성합니다.

012.nginx-vol-4.yml8/09-volume-nfs.yaml

코드 블럭
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx-vol-4
spec:
  nodeName: w1-k8s
  containers:
  - name: nginx-vol-4
    image: nginx
    volumeMounts:
    - name: nfs-volume
      mountPath: /usr/share/nginx/html
  volumes:
  - name: nfs-volume
    nfs:
      path: /nfs
      server: w2-k8s

...

(3) 생성된 yaml을 적용하여 파드를 생성 합니다

코드 블럭
kubectl apply -f 012.nginx09-volvolume-4nfs.yaml
pod/nginx-vol-4 created
 
[root@m-k8s vagrant]# k get pod -o wide
NAME          READY   STATUS    RESTARTS   AGE   IP               NODE     NOMINATED NODE   READINESS GATES
nginx-vol-4   1/1     Running   0          53s   172.16.221.186   w1-k8s   <none>           <none>
 
[root@m-k8s vagrant]# curl 172.16.221.186
hiihi
 
kubectl exec -it nginx-vol-4 -- df -h
Filesystem      Size  Used Avail Use% Mounted on
...
w2-k8s:/nfs                   37G  4.4G   33G  12% /usr/share/nginx/html
...
 
 
# pod가 구동중인 worker1의 마운트 상태 확인
[root@w1-k8s /]# df -h
Filesystem      Size  Used Avail Use% Mounted on
 
w2-k8s:/nfs                   37G  4.4G   33G  12% /var/lib/kubelet/pods/23229ac8-acb5-4aa0-b
0f1-6d8f36236366/volumes/kubernetes.io~nfs/nfs-volume 
 
#hostpath의 경우 해당파일이 존재하는 워커노드에서만 수행되도록 설정하였으나 nfs사용시에는 어느 노드에서 구동되어도 상관이 없습니다
 
 
# 다음 실습을 위해 실습환경을 정리 합니다.
kubectl delete -f 012.nginx09-volvolume-4nfs.ymlyaml
pod "nginx-vol-4" deleted

3.4 Persistent Volume(PV)

  • PV(PersistentVolume): PV는 관리자가 프로비저닝했거나 스토리지 클래스를 사용해 동적으로 프로비저닝한 클러스터의 스토리지입니다. PV는 볼륨과 같은 볼륨 플러그인이지만 PV를 사용하는 개별 Pod와 독립적인 수명 주기를 가집니다.

  • PVC(PersistentVolumeClaim): PVC는 사용자가 볼륨을 사용하기 위해 PV에 하는 스토리지 요청입니다. Pod와 유사하게 Pod는 노드 리소스를 소비하고, PVC는 PV 리소스를 소비합니다.

...

(3) 마지막 실습한 nfs를 단순 pv로 만들어 사용하는 실습을 진행합니다.

012.nginx-vol-5.yml8/10-volume-pv.yaml

코드 블럭
languageyaml
---
apiVersion: v1
kind: PersistentVolume              # PersistenVolume형태로 kind정의
metadata:
  name: nginx-vol-pv-5
  labels:
    release: stable
    capacity: 1Gi
spec:
  capacity:
    storage: 1Gi                  # 1G 사이즈로 생성
  accessModes:               
  - ReadWriteOnce
  - ReadOnlyMany
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /nfs
    server: w2-k8s            

...

코드 블럭
[root@m-k8s vagrant]# kubectl apply -f 012.nginx10-volvolume-5pv.ymlyaml
persistentvolume/nginx-vol-pv-5 created
[root@m-k8s vagrant]# k get pv
NAME             CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
nginx-vol-pv-5   1Gi        RWO,ROX,RWX    Retain           Available                                   6s


 

  • PV가 설정한대로 생성되면, 해당 PV를 사용하는 PVC를 생성하는 yaml 파일을 작성합니다.

012.nginx-vol-58/11-volume-pvc.ymlyaml

코드 블럭
languageyaml
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nginx-pvc-1
spec:
  storageClassName: ""
  accessModes:
    - ReadWriteOnce     # 서로 매칭되는 클래스를 사용하겠다는 의미
  resources:
    requests:
      storage: 1Gi

...

  • yaml 파일을 적용하여 PVC를 생성 합니다.

코드 블럭
kubectl apply -f 012.nginx-vol-511-volume-pvc.yml yaml
 
 
# 생성된 pvc를 확인합니다.
[root@m-k8s vagrant]# k get pvc
NAME          STATUS   VOLUME           CAPACITY   ACCESS MODES   STORAGECLASS   AGE
nginx-pvc-1   Bound    nginx-vol-pv-5   1Gi        RWO,ROX,RWX                   7s

# 앞서 STATUS가 Available의 값과 CLAIM이 비어있던 것이 PVC에 바인딩 된 것을 아래와 같이 볼 수 있습니다.
[root@m-k8s vagrant]# k get pv
NAME             CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                 STORAGECLASS   REASON   AGE
nginx-vol-pv-5   1Gi        RWO,ROX,RWX    Retain           Bound    default/nginx-pvc-1                           2m44s
 
# 해당 pvc가 요청하는 조건에 맞는 pv가 이미 생성되었으므로 Bound(할당) 되었습니다. Pod는 PV를 사용하는 것이 아니라 PVC를 사용하는 것입니다.

...

  • 해당 PVC를 사용하는 파드를 생성하는 yaml 파일을 작성합니다.

012.nginx-vol-6.yml8/12-volume-pvc-pod.yaml

코드 블럭
languageyaml
--- 
apiVersion: v1
kind: Pod
metadata:
  name: nginx-vol-6
spec:
  containers:
  - name: nginx-container
    image: nginx
    volumeMounts:
    - mountPath: /vol
      name: nginx-volume
  volumes:
    - name:  nginx-volume
      persistentVolumeClaim:
        claimName: nginx-pvc-1

 

  • yaml 파일을 적용하여 파드를 생성합니다.

코드 블럭
# 파드를 생성합니다.
kubectl apply -f 012.nginx-vol-6.yml12-volume-pvc-pod.yaml
pod/nginx-vol-6 created
 
# 컨테이너 안에서 마운트 상태를 확인합니다.
kubectl exec -it nginx-vol-6 -- df -h
 
Filesystem      Size  Used Avail Use% Mounted on
w2-k8s:/nfs                   37G  4.4G   33G  12% /vol
 
 
# 정상적으로 마운트 된것을 확인 할수 있습니다
 
## 실습 환경을 정리 합니다
# 파드 삭제
kubectl delete pod nginx-vol-6
pod "nginx-vol-6" deleted
 
# PVC 삭제 
kubectl delete pvc/nginx-pvc-1
persistentvolumeclaim "nginx-pvc-1" deleted
 
# PV 삭제 
kubectl delete pv/nginx-vol-pv-5
persistentvolume "nginx-vol-pv-5" deleted

3.5 동적 프로비저닝 + 프로덕션 환경 테스트

정보

Dynamic 프로비저닝을 하려면 CSI를 제공하는 스토리지가 필요합니다. 보통 운영환경에서는 모두 이 방식을 사용합니다.

동적 프로비저닝의 의미는 PV를 PVC요청에 따라 동적으로 할당 한다는 것을 의미 합니다.

...

(1) 동적 프로비저닝으로 nfs를 가지고 실습합니다.

기존의 세팅값을 지웁니다.

  • NFS 프로비저너를 설치합니다.

코드 블럭
[root@mroot@cp-k8s vagrant]# git clone https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner.git
[root@mroot@cp-k8s vagrant]# cd nfs-subdir-external-provisioner/deploy

...

  • pvc만 지정하여 구성하면, 자동적으로 하드웨어에 용량이 할당되는 형태의 서비스가 시작됩니다.

  • deployment.yaml 파일 수정

코드 블럭
...         
          env:
            - name: PROVISIONER_NAME
              value: k8s-sigs.io/nfs-subdir-external-provisioner
            - name: NFS_SERVER
              value: w2-k8s      #수정
            - name: NFS_PATH
              value: /nfs        #수정
      volumes:
        - name: nfs-client-root
          nfs:
            server: w2-k8s       #수정
            path: /nfs           #수정
코드 블럭
[root@m-k8s deploy]# k apply -f rbac.yaml
[root@m-k8s deploy]# k apply -f deployment.yaml 
[root@m-k8s deploy]# k apply -f class.yaml 

...

  • pvc만 지정하여 구성하면, 자동적으로 하드웨어에 용량이 할당되는 형태의 서비스가 시작됩니다.

012.mypvc8/13-volume-dynamic-pvc.yaml

코드 블럭
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mypvc-dynamic
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1G
  storageClassName: 'nfs-client'
코드 블럭
[root@m-k8s deploy]# k apply -f 012.mypvc13-volume-dynamic-pvc.yaml 
코드 블럭
[root@m-k8s deploy]# k get pv,pvc
NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                   STORAGECLASS   REASON   AGE
persistentvolume/pvc-45758961-7542-4f32-a959-d5ee0bdc17e8   1G         RWX            Delete           Bound    default/mypvc-dynamic   nfs-client              4s

NAME                                  STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/mypvc-dynamic   Bound    pvc-45758961-7542-4f32-a959-d5ee0bdc17e8   1G         RWX            nfs-client     4s

[root@m-k8s deploy]# k get sc
NAME         PROVISIONER                                   RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs-client   k8s-sigs.io/nfs-subdir-external-provisioner   Delete          Immediate           false                  49m

...

  • 정상적으로 volume을 사용할 수 있는지 확인합니다.

012.8/14-volume-nfs-pvc.ymlyaml

코드 블럭
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: nfs-client

...

  • 해당 pvc를 이용하여 pod를 구동해 정상적으로 volume이 attach 되는지 확인 합니다.

012.nginx8/15-volume-nfs-pvcpod.ymlyaml

코드 블럭
apiVersion: v1
kind: Pod
metadata:
  name: nginx-nfs-pvc
spec:
  containers:
  - name: nginx-nfs-pvc
    image: nginx
    volumeMounts:
    - mountPath: /vol
      name: nginx-volume
  volumes:
    - name:  nginx-volume
      persistentVolumeClaim:
        claimName: nfs-pvc
코드 블럭
[root@m-k8s vagrant]# k apply -f 012.nginx15-volume-nfs-pvcpod.ymlyaml 
pod/nginx-nfs-pvc created
[root@m-k8s vagrant]# k get pods
NAME                                     READY   STATUS              RESTARTS   AGE
gitea-66bc89d659-z577q                   1/1     Running             0          6h15m
nfs-client-provisioner-554d86f86-jlgt6   1/1     Running             0          64m
nginx-nfs-pvc                            0/1     ContainerCreating   0          3s
[root@m-k8s vagrant]# k get pods
NAME                                     READY   STATUS    RESTARTS   AGE
gitea-66bc89d659-z577q                   1/1     Running   0          6h15m
nfs-client-provisioner-554d86f86-jlgt6   1/1     Running   0          64m
nginx-nfs-pvc                            1/1     Running   0          8s

...

코드 블럭
[root@m-k8s vagrant]# k delete pvc/nfs-pvc
persistentvolumeclaim "nfs-pvc" deleted
[root@m-k8s vagrant]# k get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                   STORAGECLASS   REASON   AGE
git-pv-volume                              2Gi        RWO            Retain           Bound    default/git-volume                              6h18m
pvc-45758961-7542-4f32-a959-d5ee0bdc17e8   1G         RWX            Delete           Bound    default/mypvc-dynamic   nfs-client  

...