EKS Storage & Node 관리

kimchigood·2023년 5월 12일
0

AEWS Study

목록 보기
4/11
post-thumbnail

이번 포스팅에서는 EKS의 Storage에 대해 다뤄보겠다. 실습환경 배포는 스터디에서 제공한 CloudFormation 으로 세팅했다.

내용은 EKS 원클릭 배포를 참고하자.

Storage


참조: https://aws.amazon.com/ko/blogs/tech/persistent-storage-for-kubernetes/

Kubernetes 리소스 중 가장 기본단위인 Pod는 언제든 죽을수도(?) 있는 Stateless 리소스이다. 따라서 Pod 내부에 저장되어 있는 데이터들은 파드가 죽게되면 모두 소실이 된다. 이러한 데이터 유실 방지를 위해 Kubernetes에서는 PV, PVC 방식으로 Storage를 사용하게 된다. CSP에서는 PVC 생성 시 PV를 자동으로 생성해주는 Dynamic Provisioning 기능을 제공한다.

참조: https://aws.amazon.com/ko/blogs/tech/persistent-storage-for-kubernetes

처음 Kubernetes를 접할 때 내가 망상 비슷하게 했던게 Pod는 언제나 죽을 수 있는 리소스 라는 것이다. 그래서 Pod는 무조건 2개 이상 구동 시켜야 안전하다 라고 생각했었다. 사실 대규모로 여러 종류의 Application을 한 개의 클러스터에서 운영하게 되면, 다른 리소스들의 배포와 스케쥴링 우선순위 등에 의해 Evict(축출)될 수 있는 건 맞다.

축출되서 다른 노드로 옮겨질 수 도 있고, Pending에 빠질 수 도 있지만, 우선순위가 높은 Pod 이면서 클러스터의 리소스가 충분하다면 내부적으로 문제가 없는 Pod가 갑자기 죽거나 축출되지는 않는다^^;;

1. CSI?

The Container Storage Interface (CSI) is a standard for exposing arbitrary block and file storage systems to containerized workloads on Container Orchestration Systems (COs) like Kubernetes.

CSI는 Kubernetes에서 연결할 CSP(AWS, Azure 등)의 스토리지 연결을 위한 인터페이스이다. StorageClass 리소스를 통해 CSI 드라이버를 지정하고, 원하는 스토리지를 사용할 수 있다. CSI드라이버는 보통 kube-system 네임스페이스에서 Daemoset Pod로 구동된다.

2. EKS Storage

2-1. EKS Storage limitation

EKS의 경우 기본 세팅을 하면, Pod 수, 볼륨 최대 제한이 있다.

(kimchigood@myeks:default) [root@myeks-bastion-EC2 ~]# kubectl describe node | grep Allocatable: -A1

Allocatable:
  attachable-volumes-aws-ebs:  25
--
Allocatable:
  attachable-volumes-aws-ebs:  25
--
Allocatable:
  attachable-volumes-aws-ebs:  25

kubelet에서 환경 변수 세팅으로 조정이 가능하니 참고하자.

2-2. Storage 종류

Storage는 대표적으로 emptyDir, hostPath, PV/PVC를 통해 AWS EBS, EFS로 연동하는 방법 등이 있다. (물론 Azure, GCP 등의 스토리지 연동도 가능하다.)
참고: https://kubernetes.io/docs/concepts/storage/volumes

emptyDir

말 그대로 비어있는 디렉토리를 Volume으로 사용하는데, Pod가 사라지면 데이터도 같이 사라지는 특징이 있다.

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: registry.k8s.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir:
      sizeLimit: 500Mi

emptyDir이 배포가 되면, 기본적으로는 클러스터의 환경에 따라 노드의 Disk, SSD, Network Storage 등에 데이터가 저장된다. sizeLimit 을 설정할 수 도 있고, emptyDir.medium: Memory를 통해 노드의 tmpfs(RAM based filesystem)에 할당하여 속도를 빠르게 만들 수 도 있다.

hostPath

Pod의 Volume을 Node에 매핑시키는 방식이다. Pod가 죽고 다시 살아나면 데이터가 유실되지 않고 남아있게 되는데, 원래 Pod가 존재하던 Node에 생성되어야지 의미가 있다. 다른 Node 뜨면 데이터를 찾아 갈 수가 없다.

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: registry.k8s.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /test-pd
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      # directory location on host
      path: /data
      # this field is optional
      type: Directory

그러므로 Node가 없어져도 문제가 된다. 예전에 Kubernetes에서 구동하는 Jenkins를 구축한 적이 있는데, 이 Jenkins에서 빌드를 할 때 k8s agent Pod를 생성해서 빌드하는 방식이 있다. 이 때 Jenkins agent Pod를 hostPath를 사용해서 Node의 /var/lib/docker 와 매핑 시켜서 사용 했었는데, 보안상 현재는 추천하지 않는 방식이다.
(agent를 사용하지 말라는게 아니라 Docker in Dokcer 방식을 사용하면 안되는 것임)

AWS EBS Controller

AWS의 EBS를 Pod의 Volume으로 사용하는 방법인데, PV/PVC를 활용해서 구현을 하게된다. 구조는 아래 악분님 블로그의 그림을 참조하자.

참조: https://malwareanalysis.tistory.com/598

3.EKS Storage 실습

3-1. AWS EBS Controller

아래 스크립트를 통해 EBS CSI Driver를 설치해보자. addon으로 쉽게 설치가 가능한데 권한을 주기 위해 IRSA 세팅이 필요하다.

# 아래는 aws-ebs-csi-driver 전체 버전 정보와 기본 설치 버전(True) 정보 확인
aws eks describe-addon-versions \
    --addon-name aws-ebs-csi-driver \
    --kubernetes-version 1.24 \
    --query "addons[].addonVersions[].[addonVersion, compatibilities[].defaultVersion]" \
    --output text
v1.18.0-eksbuild.1
Tru
v1.17.0-eksbuild.1
False
...

# ISRA 설정 : AWS관리형 정책 AmazonEBSCSIDriverPolicy 사용
eksctl create iamserviceaccount \
  --name ebs-csi-controller-sa \
  --namespace kube-system \
  --cluster ${CLUSTER_NAME} \
  --attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy \
  --approve \
  --role-only \
  --role-name AmazonEKS_EBS_CSI_DriverRole

# ISRA 확인
kubectl get sa -n kube-system ebs-csi-controller-sa -o yaml | head -5
eksctl get iamserviceaccount --cluster myeks
NAMESPACE	    NAME				            ROLE ARN
kube-system 	ebs-csi-controller-sa		arn:aws:iam::911283464785:role/AmazonEKS_EBS_CSI_DriverRole
...

# Amazon EBS CSI driver addon 추가
eksctl create addon --name aws-ebs-csi-driver --cluster ${CLUSTER_NAME} --service-account-role-arn arn:aws:iam::${ACCOUNT_ID}:role/AmazonEKS_EBS_CSI_DriverRole --force

# 확인
eksctl get addon --cluster ${CLUSTER_NAME}
kubectl get deploy,ds -l=app.kubernetes.io/name=aws-ebs-csi-driver -n kube-system
kubectl get pod -n kube-system -l 'app in (ebs-csi-controller,ebs-csi-node)'
kubectl get pod -n kube-system -l app.kubernetes.io/component=csi-driver

# ebs-csi-controller 파드에 6개 컨테이너 확인
kubectl get pod -n kube-system -l app=ebs-csi-controller -o jsonpath='{.items[0].spec.containers[*].name}' ; echo
ebs-plugin csi-provisioner csi-attacher csi-snapshotter csi-resizer liveness-probe

# csinodes 확인
kubectl get csinodes

# gp3 스토리지 클래스 생성
kubectl get sc
cat <<EOT > gp3-sc.yaml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: gp3
allowVolumeExpansion: true
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
parameters:
  type: gp3
  allowAutoIOPSPerGBIncrease: 'true'
  encrypted: 'true'
  #fsType: ext4 # 기본값이 ext4 이며 xfs 등 변경 가능 >> 단 스냅샷 경우 ext4를 기본으로하여 동작하여 xfs 사용 시 문제가 될 수 있음 - 테스트해보자
EOT
kubectl apply -f gp3-sc.yaml
kubectl get sc
kubectl describe sc gp3 | grep Parameters

잘 설치가 되면, 아래 결과 화면과 같은 내용을 확인할 수 있다.

(kimchigood@myeks:default) [root@myeks-bastion-EC2 ~]# kubectl get sc

NAME            PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
gp2 (default)   kubernetes.io/aws-ebs   Delete          WaitForFirstConsumer   false                  80m
gp3             ebs.csi.aws.com         Delete          WaitForFirstConsumer   true                   3s

(kimchigood@myeks:default) [root@myeks-bastion-EC2 ~]# kubectl describe sc gp3 | grep Parameters
Parameters:            allowAutoIOPSPerGBIncrease=true,encrypted=true,type=gp3

이제 PV, PVC와 연동하여 Pod에서 AWS EBS를 Volume으로 사용이 가능하다.

# 워커노드에서 파드에 추가한 EBS 볼륨 모니터링
while true; do aws ec2 describe-volumes --filters Name=tag:ebs.csi.aws.com/cluster,Values=true --query "Volumes[].{VolumeId: VolumeId, VolumeType: VolumeType, InstanceId: Attachments[0].InstanceId, State: Attachments[0].State}" --output text; date; sleep 1; done

# PVC 생성
cat <<EOT > awsebs-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ebs-claim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 4Gi
  storageClassName: gp3
EOT
kubectl apply -f awsebs-pvc.yaml
kubectl get pvc,pv

# 파드 생성
cat <<EOT > awsebs-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  terminationGracePeriodSeconds: 3
  containers:
  - name: app
    image: centos
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo \$(date -u) >> /data/out.txt; sleep 5; done"]
    volumeMounts:
    - name: persistent-storage
      mountPath: /data
  volumes:
  - name: persistent-storage
    persistentVolumeClaim:
      claimName: ebs-claim
EOT
kubectl apply -f awsebs-pod.yaml

# PVC, 파드 확인
kubectl get pvc,pv,pod

(kimchigood@myeks:default) [root@myeks-bastion-EC2 ~]# kubectl get VolumeAttachment
NAME                                                                   ATTACHER          PV                                         NODE                                              ATTACHED   AGE
csi-4628b9bdcc3ca8d863f578ea99e1f342bcbcf0354f58e3a352759a040552a6d7   ebs.csi.aws.com   pvc-d571631d-78f0-45c4-b2ba-c578f16663c4   ip-192-168-3-13.ap-northeast-2.compute.internal   true       7s

# 추가된 EBS 볼륨 상세 정보 확인 
aws ec2 describe-volumes --volume-ids $(kubectl get pv -o jsonpath="{.items[0].spec.csi.volumeHandle}") | jq

# PV 상세 확인 : nodeAffinity 내용의 의미는?
kubectl get pv -o yaml | yh
...
    nodeAffinity:
      required:
        nodeSelectorTerms:
        - matchExpressions:
          - key: topology.ebs.csi.aws.com/zone
            operator: In
            values:
            - ap-northeast-2b
...

여기까지 잘 따라왔으면 별 다른 문제없이 AWS EBS와 연동이 될 것이다. 몇가지 확인을 해보자.


3-2. topology.ebs.csi.aws.com/zone,topology.kubernetes.io/zone

(kimchigood@myeks:default) [root@myeks-bastion-EC2 ~]# kubectl get node --label-columns=topology.ebs.csi.aws.com/zone,topology.kubernetes.io/zone

NAME                                              STATUS   ROLES    AGE    VERSION                ZONE              ZONE
ip-192-168-1-88.ap-northeast-2.compute.internal   Ready    <none>   135m   v1.24.11-eks-a59e1f0   ap-northeast-2a   ap-northeast-2a
ip-192-168-2-47.ap-northeast-2.compute.internal   Ready    <none>   135m   v1.24.11-eks-a59e1f0   ap-northeast-2b   ap-northeast-2b
ip-192-168-3-13.ap-northeast-2.compute.internal   Ready    <none>   135m   v1.24.11-eks-a59e1f0   ap-northeast-2c   ap-northeast-2c

이 레이블들은 어떤걸까? 공식문서를 참조하면 CSP에서 운영되는 Kubenetes에서 사용가능한 레이블로, Node, PV에 사용된다고 나와있다.

위 내용을보면 추측컨데, 각 Node가 배포되어야할 zone과 해당 Node와 관련된 ESB의 위치가 아닐까 싶다. 그럼 이게 무엇인지 확인을 해보자.

$ kubectl describe nodes
topology.ebs.csi.aws.com/zone=ap-northeast-2c
topology.kubernetes.io/region=ap-northeast-2

Node를 describe 해보면 Labels들이 붙어 있다. 문서를 참조해보면,

On Node: The kubelet or the external cloud-controller-manager populates this with the information as provided by the cloudprovider. This will be set only if you are using a cloudprovider. However, you should consider setting this on nodes if it makes sense in your topology.

On PersistentVolume: topology-aware volume provisioners will automatically set node affinity constraints on PersistentVolumes.

Node에서는 cloud-controller-manager를 통해 CSP에 정보를 전달해주고, PV에서는 node affinity세팅을 한다고 되어있다.
PV도 describe 보자.

(kimchigood@myeks:default) [root@myeks-bastion-EC2 ~]# k describe pv
Name:              pvc-d571631d-78f0-45c4-b2ba-c578f16663c4
Labels:            <none>
Annotations:       pv.kubernetes.io/provisioned-by: ebs.csi.aws.com
                   volume.kubernetes.io/provisioner-deletion-secret-name:
                   volume.kubernetes.io/provisioner-deletion-secret-namespace:
Finalizers:        [kubernetes.io/pv-protection external-attacher/ebs-csi-aws-com]
StorageClass:      gp3
Status:            Bound
Claim:             default/ebs-claim
Reclaim Policy:    Delete
Access Modes:      RWO
VolumeMode:        Filesystem
Capacity:          4Gi
Node Affinity:
  Required Terms:
    Term 0:        topology.ebs.csi.aws.com/zone in [ap-northeast-2c]

topology.ebs.csi.aws.com/zone in [ap-northeast-2c] 설명대로 Node Affinity가 붙어 있다. 그럼 왜 하필 ap-northeast-2c일까?
이 PV가 붙어있는 Pod를 다시 describe 해보자.

(kimchigood@myeks:default) [root@myeks-bastion-EC2 ~]# k describe po
Name:             app
Namespace:        default
Priority:         0
Service Account:  default
Node:             ip-192-168-3-13.ap-northeast-2.compute.internal/192.168.3.13
Start Time:       Fri, 12 May 2023 13:36:27 +0900

자, 이제 답이 나온 것 같다. Pod가 배포된 Node의 topology 내용을 PV가 참조하여 세팅이 되는 것이다. 실제로 EBS도 포털에서 확인하면 ap-northeast-2c에 배포가 되어있다.

myeks-dynamic-pvc로 되어있는 부분을 참고하자.

3-2. AWS Volume SnapShots Controller

시스템 운영 중 정말 중요한 데이터는 스냅샷을 떠두어서 데이터 유실 시 대응이 필요하다. EKS에서 SnapShot Controller를 사용해서 데이터 복구 시나리오를 테스트 해보자.

3-2-1. AWS Volume SnapShots Controller 설치하기

설치는 먼저 Snapshot 관련 crd들을 모두 설치하고, Controller를 설치하는 순으로 진행을 하면 된다.

# (참고) EBS CSI Driver에 snapshots 기능 포함 될 것으로 보임
kubectl describe pod -n kube-system -l app=ebs-csi-controller

# Install Snapshot CRDs
curl -s -O https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshots.yaml
curl -s -O https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml
curl -s -O https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml
kubectl apply -f snapshot.storage.k8s.io_volumesnapshots.yaml,snapshot.storage.k8s.io_volumesnapshotclasses.yaml,snapshot.storage.k8s.io_volumesnapshotcontents.yaml
kubectl get crd | grep snapshot
kubectl api-resources  | grep snapshot

# Install Common Snapshot Controller
curl -s -O https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/deploy/kubernetes/snapshot-controller/rbac-snapshot-controller.yaml
curl -s -O https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/deploy/kubernetes/snapshot-controller/setup-snapshot-controller.yaml
kubectl apply -f rbac-snapshot-controller.yaml,setup-snapshot-controller.yaml
kubectl get deploy -n kube-system snapshot-controller
kubectl get pod -n kube-system -l app=snapshot-controller

# Install Snapshotclass
curl -s -O https://raw.githubusercontent.com/kubernetes-sigs/aws-ebs-csi-driver/master/examples/kubernetes/snapshot/manifests/classes/snapshotclass.yaml
kubectl apply -f snapshotclass.yaml
kubectl get vsclass # 혹은 volumesnapshotclasses

이제 EBS를 PV/PVC, Pod와 함께 배포한 후 Snapshot을 연결해보자. 코드는 위에 EBS 예제코드를 사용한다.

# PVC 생성
kubectl apply -f awsebs-pvc.yaml

# 파드 생성
kubectl apply -f awsebs-pod.yaml

# 파일 내용 추가 저장 확인
kubectl exec app -- tail -f /data/out.txt

# VolumeSnapshot 생성 : Create a VolumeSnapshot referencing the PersistentVolumeClaim name >> EBS 스냅샷 확인
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/3/ebs-volume-snapshot.yaml
cat ebs-volume-snapshot.yaml | yh
kubectl apply -f ebs-volume-snapshot.yaml

# VolumeSnapshot 확인
kubectl get volumesnapshot
kubectl get volumesnapshot ebs-volume-snapshot -o jsonpath={.status.boundVolumeSnapshotContentName} ; echo
kubectl describe volumesnapshot.snapshot.storage.k8s.io ebs-volume-snapshot
kubectl get volumesnapshotcontents

# VolumeSnapshot ID 확인 
kubectl get volumesnapshotcontents -o jsonpath='{.items[*].status.snapshotHandle}' ; echo

# AWS EBS 스냅샷 확인
aws ec2 describe-snapshots --owner-ids self | jq
aws ec2 describe-snapshots --owner-ids self --query 'Snapshots[]' --output table

실제로 Console에도 Snapshot 생성이 완료되었다.

SnapShot을 붙이는 코드는 간단하다.

(kimchigood@myeks:default) [root@myeks-bastion-EC2 ~]# cat ebs-volume-snapshot.yaml | yh
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: ebs-volume-snapshot
spec:
  volumeSnapshotClassName: csi-aws-vsc
  source:
    persistentVolumeClaimName: ebs-claim

PVC Name을 세팅해주면 해당되는 PVC와 연결된 EBS의 Snapshot을 뜨게 된다.

3-2-2. Snapshot으로 복구하기

Pod와 PVC를 모두 삭제해버리면, ReclainPolicy가 Delete인 경우, EBS까지 날아가는 불상사가 벌어진다. 의도된거면 상관이 없으나, 실수로 지워버렸다면 큰일이다! 하지만 Snapshot을 떠놨기 때문에 쉽게 복구가 가능하다. 구동 중인 파드는 5초마다 날짜를 찍고 있음을 확인하자.

(kimchigood@myeks:default) [root@myeks-bastion-EC2 ~]# kubectl delete pod app && kubectl delete pvc ebs-claim
pod "app" deleted
persistentvolumeclaim "ebs-claim" deleted

복구하기
콘솔에서 확인해보면, EBS가 삭제된 상태이다.

kubectl get pvc,pv
cat <<EOT > ebs-snapshot-restored-claim.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ebs-snapshot-restored-claim
spec:
  storageClassName: gp3
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 4Gi
  dataSource:
    name: ebs-volume-snapshot
    kind: VolumeSnapshot
    apiGroup: snapshot.storage.k8s.io
EOT
cat ebs-snapshot-restored-claim.yaml | yh
kubectl apply -f ebs-snapshot-restored-claim.yaml

# 확인
kubectl get pvc,pv

# 파드 생성
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/3/ebs-snapshot-restored-pod.yaml
cat ebs-snapshot-restored-pod.yaml | yh
kubectl apply -f ebs-snapshot-restored-pod.yaml

# 파일 내용 저장 확인 : 파드 삭제 전까지의 저장 기록이 남아 있다. 이후 파드 재생성 후 기록도 잘 저장되고 있다
kubectl exec app -- cat /data/out.txt

먼저 PVC의 dataSource를 보면 Snapshot이 지정되있는걸 볼 수 있다. ebs-volume-snapshot은 최초에 세팅한 Snapshot의 이름이다.

Pod의 내용도 살펴보면, PVC를 방금 생성한 PVC로 지정하였다. 그러면 Volume을 Snapshot으로 쓴다는 것인데,

  volumes:
  - name: persistent-storage
    persistentVolumeClaim:
      claimName: ebs-snapshot-restored-claim

Pod 실행 후 out.txt 파일 조회해보면, 이전 기록들이 남아 있다. 복구가 된 것이다. 콘솔에서도 다시 EBS가 생긴 것을 확인 할 수 있다!

물론, Snapshot을 그냥 콘솔들어가서 세팅하고, 사라지면 다시 복구하면 되지만, k8s 리소스를 통해서 쉽게 복구가 가능한 장점이 있다. 콘솔작업은 실수를 할 수 도 있고, 이렇게 코드를 통해 복구를 하는게 좀 더 편하고 안전해 보인다.

EFS 의 경우도 EBS와 세팅이 진배없다. 단 한가지 특징은 EFS 특성상 여러 Pod에서 읽고 쓰기가 가능한 차이점이 있으니 참고하자. (Azure는 EFS size up & down이 된다.)

4. Node Group 실습하기

Kubernetes 클러스터를 운영하다보면, 성격이나 조건에 맞게 Node를 운영해야할 일이 생긴다. 예를들면, 일반적인 Pod들이 구동되는 Node 도 필요하고, cpu가 많이 필요한 Node, Memory가 많이필요한 Node 등 여러 조건들이 생긴다. 이 때 사용하면 좋은게 Node Group이다.

# 신규 노드 그룹 생성
eksctl create nodegroup --help
eksctl create nodegroup -c $CLUSTER_NAME -r $AWS_DEFAULT_REGION --subnet-ids "$PubSubnet1","$PubSubnet2","$PubSubnet3" --ssh-access \
  -n ng2 -t c5d.large -N 1 -m 1 -M 1 --node-volume-size=30 --node-labels disk=nvme --max-pods-per-node 100 --dry-run > myng2.yaml

cat <<EOT > nvme.yaml
  preBootstrapCommands:
    - |
      # Install Tools
      yum install nvme-cli links tree jq tcpdump sysstat -y

      # Filesystem & Mount
      mkfs -t xfs /dev/nvme1n1
      mkdir /data
      mount /dev/nvme1n1 /data

      # Get disk UUID
      uuid=\$(blkid -o value -s UUID mount /dev/nvme1n1 /data) 

      # Mount the disk during a reboot
      echo /dev/nvme1n1 /data xfs defaults,noatime 0 2 >> /etc/fstab
EOT
sed -i -n -e '/volumeType/r nvme.yaml' -e '1,$p' myng2.yaml
eksctl create nodegroup -f myng2.yaml

# 노드 보안그룹 ID 확인
NG2SGID=$(aws ec2 describe-security-groups --filters Name=group-name,Values=*ng2* --query "SecurityGroups[*].[GroupId]" --output text)
aws ec2 authorize-security-group-ingress --group-id $NG2SGID --protocol '-1' --cidr 192.168.1.100/32

# 워커 노드 SSH 접속
N4=192.168.3.160
ssh ec2-user@$N4 hostname

# 확인
ssh ec2-user@$N4 sudo nvme list
ssh ec2-user@$N4 sudo lsblk -e 7 -d
ssh ec2-user@$N4 sudo df -hT -t xfs
ssh ec2-user@$N4 sudo tree /data
ssh ec2-user@$N4 sudo cat /etc/fstab

위 예제대로 세팅하면 preBootstrapCommands 를 통해 신규 Node Group이 생성될 때, 필요한 tool이나, mount 세팅들을 할 수 있다. N4 부분에는 실제로 신규로 생성된 Node의 Public IP를 넣어줘야 한다.

(kimchigood@myeks:default) [root@myeks-bastion-EC2 ~]# ssh ec2-user@$N4 sudo nvme list
Node             SN                   Model                                    Namespace Usage                      Format           FW Rev
---------------- -------------------- ---------------------------------------- --------- -------------------------- ---------------- --------
/dev/nvme0n1     vol0e952c7acbe6c37e1 Amazon Elastic Block Store               1          32.21  GB /  32.21  GB    512   B +  0 B   1.0
/dev/nvme1n1     AWSEBCC0D6B5C5730E16 Amazon EC2 NVMe Instance Storage         1          50.00  GB /  50.00  GB    512   B +  0 B   0

현업에서는 AKS를 쓰고 있는데, NodePool 이라는 용어를 사용한다. 보다 더 안정적인 운용을 위해 kube-system 네임스페이스는 Systempool에 두고, 모니터링이나 devops 관련 Nodepool, 실제로 크리티컬한 어플리케이션들이 구동되는 Nodepooleh 성격에 맞에 여러개로 운용 중이다.

그리고 batch 성이나 대규모 테스트가 필요한 경우, Spot Instance Nodepool을 사용하면 비용을 90% 이상 절감 시킬 수 있으니 꼭 써보자!!!

Wrap up

이번 포스팅에서는 Kubernetes Storage에 대해 알아보았다. 실제로 어플리케이션에 쓰임에 따라 써야하는 Storage도 제각각이다. 어플리케이션 개발만 할 때는 인프라팀에서 이런 부분들은 알아서 해줬는데, Kubernetes를 사용하면서, 어떤 스펙의 디스크가 필요한지, 디스크 종류는 어떤 걸 써야하는지 결정해야할 사항들이 많아 졌다. 항상 느끼는거지만 컴공의 기초가 없는 비전공자 입장에서 Kubernetes를 하다보면 정말 스토리지, 네트워크, 운영체제 등 많은 부분을 알 수 있어서 좋다.

profile
Shout out to Kubernetes⎈

0개의 댓글