교육, 커뮤니티 후기/PKOS 쿠버네티스 스터디

PKOS 쿠버네티스 스터디 3주차 - Ingress & Storage

Somaz 2023. 2. 3. 23:14
728x90
반응형

출처 : 스터디원 이현수님

 

 

Overview

벌써 가시다님이 진행하시는 쿠버네티스 스터디 3주차가 되었다.

 

오늘은 Ingress와 Storage에 대해 공부를 하였다!

 

3주차 과제 내용

 

[과제1]

Ingress(with 도메인)에 PATH /mario 는 mario 게임 접속하게 설정하고, /tetris 는 tetris 게임에 접속하게 설정하고, SSL 적용 후 관련 스샷 올려주세요

  • 특히 ALB 규칙 Rules 를 상세히 보고, 의미를 이해해볼것

 

EC2 instance profiles 설정 및 AWS LoadBalancer 배포 & ExternalDNS 설치 및 배포

# 마스터/워커 노드에 EC2 IAM Role 에 Policy (AWSLoadBalancerControllerIAMPolicy) 추가

## IAM Policy 정책 생성 : 2주차에서 IAM Policy 를 미리 만들어두었으니 Skip
curl -o iam_policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.4.5/docs/install/iam_policy.json
aws iam create-policy --policy-name AWSLoadBalancerControllerIAMPolicy --policy-document file://iam_policy.json

# EC2 instance profiles 에 IAM Policy 추가(attach)
(somaz:N/A) [root@kops-ec2 ~]# aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --role-name masters.$KOPS_CLUSTER_NAME
(somaz:N/A) [root@kops-ec2 ~]# aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --role-name nodes.$KOPS_CLUSTER_NAME

# IAM Policy 정책 생성 : 2주차에서 IAM Policy 를 미리 만들어두었으니 Skip
curl -s -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/AKOS/externaldns/externaldns-aws-r53-policy.json
aws iam create-policy --policy-name AllowExternalDNSUpdates --policy-document file://externaldns-aws-r53-policy.json

# EC2 instance profiles 에 IAM Policy 추가(attach)
(somaz:N/A) [root@kops-ec2 ~]# aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AllowExternalDNSUpdates --role-name masters.$KOPS_CLUSTER_NAME
(somaz:N/A) [root@kops-ec2 ~]# aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AllowExternalDNSUpdates --role-name nodes.$KOPS_CLUSTER_NAME

# kOps 클러스터 편집 : 아래 내용 추가
(somaz:N/A) [root@kops-ec2 ~]# kops edit cluster
-----
spec:
  certManager:
    enabled: true
  awsLoadBalancerController:
    enabled: true
  externalDns:
    provider: external-dns
-----

# 업데이트 적용
(somaz:N/A) [root@kops-ec2 ~]# kops update cluster --yes && echo && sleep 3 && kops rolling-update cluster

 

Ingress(with 도메인)에 PATH /mario 는 mario 게임 접속하게 설정하고, /tetris 는 tetris 게임에 접속하게 설정

 

yaml 파일 설정

# 네임스페이스 생성 후 변경          
(somaz:default) [root@kops-ec2 ~]# k create ns games
namespace/games created

(somaz:default) [root@kops-ec2 ~]# k ns games
Context "somaz.link" modified.
Active namespace is "games".

# 변수지정 - 도메인, 도메인 인증서
(somaz:N/A) [root@kops-ec2 ~]# WEBDOMAIN=albweb.somaz.link
(somaz:games) [root@kops-ec2 ~]# CERT_ARN=`aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text`

# 변수 확인
(somaz:games) [root@kops-ec2 ~]# WEBDOMAIN=$WEBDOMAIN envsubst < ~/somazgames.yaml
...
spec:
  ingressClassName: alb
  rules:
    - host: albweb.somaz.link
...

(somaz:games) [root@kops-ec2 ~]# CERT_ARN=$CERT_ARN envsubst < ~/somazgames.yaml
...
alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:ap-northeast-2:xxxx # 이건 비밀!
...

# somazgames.yaml 파일 작성
(somaz:default) [root@kops-ec2 ~]# cat somazgames.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: games
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mario
  namespace: games
  labels:
    app: mario
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mario
  template:
    metadata:
      labels:
        app: mario
    spec:
      containers:
      - name: mario
        image: pengbai/docker-supermario
---
apiVersion: v1
kind: Service
metadata:
   name: mario
   namespace: games
   lables:
   annotations:
     alb.ingress.kubernetes.io/healthcheck-path: /mario/index.html
spec:
  selector:
    app: mario
  ports:
  - port: 80
    protocol: TCP
    targetPort: 8080
  type: NodePort
  externalTrafficPolicy: Local
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tetris
  namespace: games
  labels:
    app: tetris
spec:
  replicas: 1
  selector:
    matchLabels:
      app: tetris
  template:
    metadata:
      labels:
        app: tetris
    spec:
      containers:
      - name: tetris
        image: bsord/tetris
---
apiVersion: v1
kind: Service
metadata:
  name: tetris
  namespace: games
  annotations:
    alb.ingress.kubernetes.io/healthcheck-path: /tetris/index.html
spec:
  selector:
    app: tetris
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  type: NodePort
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  namespace: games
  name: ingress-games
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:ap-northeast-2:611..
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
    alb.ingress.kubernetes.io/healthcheck-protocol: HTTP
    alb.ingress.kubernetes.io/healthcheck-port: traffic-port
    alb.ingress.kubernetes.io/healthcheck-interval-seconds: '15'
    alb.ingress.kubernetes.io/healthcheck-timeout-seconds: '5'
    alb.ingress.kubernetes.io/success-codes: '200'
    alb.ingress.kubernetes.io/healthy-threshold-count: '2'
    alb.ingress.kubernetes.io/unhealthy-threshold-count: '2'
spec:
  ingressClassName: alb
  rules:
    - host: albweb.somaz.link
      http:
        paths:
        - path: /mario
          pathType: Prefix
          backend:
            service:
              name: mario
              port:
                number: 80
        - path: /tetris
          pathType: Prefix
          backend:
            service:
              name: tetris
              port:
                number: 80

 

애플리케이션 배포

# 애플리케이션 배포
(somaz:games) [root@kops-ec2 ~]# k apply -f somazgames.yaml


# 배포확인
(somaz:games) [root@kops-ec2 ~]# kubectl get ingress,svc,ep,pod -n games
NAME                                      CLASS   HOSTS               ADDRESS
                                                    PORTS   AGE
ingress.networking.k8s.io/ingress-games   alb     albweb.somaz.link   k8s-games-ingressg-dad1c7c3d1-566740660.ap-northeast-2.elb.amazonaws.com   80      99s

NAME             TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
service/mario    NodePort   100.64.228.211   <none>        80:30482/TCP   10m
service/tetris   NodePort   100.68.190.117   <none>        80:30852/TCP   10m

NAME               ENDPOINTS            AGE
endpoints/mario    172.30.88.128:8080   10m
endpoints/tetris   172.30.44.227:80     10m

NAME                          READY   STATUS    RESTARTS   AGE
pod/mario-687bcfc9cc-h7bwr    1/1     Running   0          10m
pod/tetris-7f86b95884-q92p8   1/1     Running   0          10m

 

Load Balancer 확인
슈퍼마리오!!!!
테트리스다~~~

삭제 및 삭제 확인

# 삭제
(somaz:games) [root@kops-ec2 ~]# kubectl delete ingress ingress-games -n games
ingress.networking.k8s.io "ingress-games" deleted

(somaz:games) [root@kops-ec2 ~]# kubectl delete svc mario tetris -n games && kubectl delete ns games
service "mario" deleted
service "tetris" deleted
namespace "games" deleted

# 삭제확인
(somaz:games) [root@kops-ec2 ~]# kubectl get ingress,svc,ep,pod -n games
No resources found in games namespace.

 

 

 

[과제2]

호스트 Path(local-path-provisioner) 실습 및 문제점 확인과 성능 측정 후 관련 스샷 올려주세요

 

 

호스트 Path(local-path-provisioner) 실습 및 문제점 확인

 

24단계 실습으로 정복하는 쿠버네티스(이정훈님) 책 171P 참고하여 진행하였다.

먼저 local hostpath 스토리지 클래스는 파드가 실행 중인 노드의 특정 디렉터리를 파드의 볼륨으로 할당한다.

따라서 파드의 데이터는 해당 노드에만 존재해서 다른 노드로 파드를 이동하는 것이 불가능하다. 볼륨을 가지지 않는 일반 OD(Stateless Pod)는 특정 노드에 장애가 발생해도 다른 노드로 이동이 가능하나 로컬 호스트패스를 스토리지 클래스로 가진 파드는 다른 노드로 이전이 불가능하다.(24단계 실습으로 정복하는 쿠버네티스(이정훈님) 책 171P 참고)

 

 

파드 배포된 워커노드 drain 해서 문제 확인

# 모니터링
(somaz:N/A) [root@kops-ec2 ~]# watch kubectl get pod,pv,pvc -owide
Every 2.0s: kubectl get pod,pv,pvc -owide                           Sun Jan 29 23:23:18 2023

# 디플로이먼트
(somaz:N/A) [root@kops-ec2 ~]# cat <<EOF | kubectl create -f -
> apiVersion: v1
> kind: PersistentVolumeClaim
> metadata:
>   name: localpath-claim
> spec:
>   accessModes:
>     - ReadWriteOnce
>   resources:
>     requests:
>       storage: 2Gi
>   storageClassName: "local-path"
> ---
> apiVersion: apps/v1
> kind: Deployment
> metadata:
>   name: date-pod
>   labels:
>     app: date
> spec:
>   replicas: 1
>   selector:
>     matchLabels:
>       app: date
>   template:
>     metadata:
>       labels:
>         app: date
>     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: pod-persistent-volume
>           mountPath: /data
>       volumes:
>       - name: pod-persistent-volume
>         persistentVolumeClaim:
>           claimName: localpath-claim
> EOF
persistentvolumeclaim/localpath-claim created
deployment.apps/date-pod created

# 모니터링 결과
Every 2.0s: kubectl get pod,pv,pvc -owide                                                                                                                           Sun Jan 29 23:23:58 2023

NAME                          READY   STATUS    RESTARTS   AGE   IP              NODE                  NOMINATED NODE   READINESS GATES
pod/date-pod-d95d6b8f-dxs6v   1/1     Running   0          15s   172.30.86.227   i-02c66212258a5124a   <none>           <none>

NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                     STORAGECLASS   REASON   AGE   VOLUMEMODE
persistentvolume/pvc-bac13fb8-a63a-490f-a745-d703ba80c1ee   2Gi        RWO            Delete           Bound    default/localpath-claim   local-path              11s   Filesystem

NAME                                    STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE   VOLUMEMODE
persistentvolumeclaim/localpath-claim   Bound    pvc-bac13fb8-a63a-490f-a745-d703ba80c1ee   2Gi        RWO            local-path     15s   Filesystem


# 배포 확인
(somaz:N/A) [root@kops-ec2 ~]# kubectl exec deploy/date-pod -- cat /data/out.txt
Sun Jan 29 14:23:50 UTC 2023
Sun Jan 29 14:23:55 UTC 2023
Sun Jan 29 14:24:00 UTC 2023
....

# 파드가 배포된 워커노드 변수 지정
(somaz:N/A) [root@kops-ec2 ~]# PODNODE=$(kubectl get pod -l app=date -o jsonpath={.items[0].spec.nodeName})

# 파드가 배포된 워커노드에 장애유지 보수를 위한 drain 설정
(somaz:N/A) [root@kops-ec2 ~]# kubectl drain $PODNODE --force --ignore-daemonsets && kubectl get pod -w
node/i-02c66212258a5124a cordoned
Warning: ignoring DaemonSet-managed Pods: kube-system/aws-node-wjxxn, kube-system/ebs-csi-node-spqmz
evicting pod kube-system/snapshot-validation-deployment-cc4945dc5-zjrbc
evicting pod default/date-pod-d95d6b8f-dxs6v
evicting pod kube-system/coredns-6897c49dc4-wffqb
evicting pod kube-system/coredns-autoscaler-5685d4f67b-6zzpq
evicting pod kube-system/snapshot-controller-6688b87c58-c4lls
pod/coredns-autoscaler-5685d4f67b-6zzpq evicted
pod/snapshot-controller-6688b87c58-c4lls evicted
pod/snapshot-validation-deployment-cc4945dc5-zjrbc evicted
pod/date-pod-d95d6b8f-dxs6v evicted
pod/coredns-6897c49dc4-wffqb evicted
node/i-02c66212258a5124a drained
NAME                      READY   STATUS    RESTARTS   AGE
date-pod-d95d6b8f-vljbx   0/1     Pending   0          6s

# 상태 확인
Every 2.0s: kubectl get pod,pv,pvc -owide                                                                                                                           Sun Jan 29 23:25:48 2023

NAME                          READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED NODE   READINESS GATES
pod/date-pod-d95d6b8f-vljbx   0/1     Pending   0          43s   <none>   <none>   <none>           <none>

NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                     STORAGECLASS   REASON   AGE    VOLUMEMODE
persistentvolume/pvc-bac13fb8-a63a-490f-a745-d703ba80c1ee   2Gi        RWO            Delete           Bound    default/localpath-claim   local-path              2m1s   Filesystem

NAME                                    STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE    VOLUMEMODE
persistentvolumeclaim/localpath-claim   Bound    pvc-bac13fb8-a63a-490f-a745-d703ba80c1ee   2Gi        RWO            local-path     2m5s   Filesystem


(somaz:N/A) [root@kops-ec2 ~]# kubectl get nodes
NAME                  STATUS                     ROLES           AGE    VERSION
i-02c66212258a5124a   Ready,SchedulingDisabled   node            156m   v1.24.9
i-051149039465749c9   Ready                      node            156m   v1.24.9
i-0d3b83f8b17358e3d   Ready                      control-plane   158m   v1.24.9

(somaz:N/A) [root@kops-ec2 ~]# kubectl get deploy/date-pod
NAME       READY   UP-TO-DATE   AVAILABLE   AGE
date-pod   0/1     1            0           2m28s

(somaz:N/A) [root@kops-ec2 ~]# kubectl describe pod -l app=date | grep Events: -A5
Events:
  Type     Reason            Age   From               Message
  ----     ------            ----  ----               -------
  Warning  FailedScheduling  77s   default-scheduler  0/3 nodes are available: 1 node(s) had untolerated taint {node-role.kubernetes.io/control-plane: }, 1 node(s) had untolerated taint {node.kubernetes.io/unschedulable: }, 1 node(s) were unschedulable, 2 node(s) had volume node affinity conflict. preemption: 0/3 nodes are available: 3 Preemption is not helpful for scheduling.
  
# local-path 스토리지클래스에서 생성되는 PV 에 Node Affinity 설정 확인
(somaz:N/A) [root@kops-ec2 ~]# kubectl describe pv
...
Node Affinity:
  Required Terms:
    Term 0:        kubernetes.io/hostname in [i-02c66212258a5124a]

 

 

파드 배포된 워커노드 uncordon해서 정상 상태로 원복

(somaz:N/A) [root@kops-ec2 ~]# kubectl uncordon $PODNODE &&  kubectl get pod -w
node/i-02c66212258a5124a uncordoned
NAME                      READY   STATUS              RESTARTS   AGE
date-pod-d95d6b8f-vljbx   0/1     ContainerCreating   0          3m19s
date-pod-d95d6b8f-vljbx   1/1     Running             0          3m21s

(somaz:N/A) [root@kops-ec2 ~]# kubectl exec deploy/date-pod -- cat /data/out.txt
Sun Jan 29 14:23:50 UTC 2023
Sun Jan 29 14:23:55 UTC 2023
Sun Jan 29 14:24:00 UTC 2023
...
Sun Jan 29 14:28:26 UTC 2023
Sun Jan 29 14:28:31 UTC 2023
Sun Jan 29 14:28:36 UTC 2023
...

(somaz:N/A) [root@kops-ec2 ~]# kubectl get nodes
NAME                  STATUS   ROLES           AGE    VERSION
i-02c66212258a5124a   Ready    node            160m   v1.24.9
i-051149039465749c9   Ready    node            160m   v1.24.9
i-0d3b83f8b17358e3d   Ready    control-plane   161m   v1.24.9

(somaz:N/A) [root@kops-ec2 ~]# kubectl get deploy/date-pod
NAME       READY   UP-TO-DATE   AVAILABLE   AGE
date-pod   1/1     1            1           5m56s

 

 

성능 측정

# kubestr 툴 다운로드

(somaz:N/A) [root@kops-ec2 ~]# wget https://github.com/kastenhq/kubestr/releases/download/v0.4.36/kubestr_0.4.36_Linux_amd64.tar.gz
(somaz:N/A) [root@kops-ec2 ~]# tar xvfz kubestr_0.4.36_Linux_amd64.tar.gz && mv kubestr /usr/local/bin/ && chmod +x /usr/local/bin/kubestr

# 워커 노드 Public IP 확인
(somaz:N/A) [root@kops-ec2 ~]# aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value}" --filters Name=instance-state-name,Values=running --output table
-----------------------------------------------------------------
|                       DescribeInstances                       |
+--------------------------------------------+------------------+
|                InstanceName                |   PublicIPAdd    |
+--------------------------------------------+------------------+
|  nodes-ap-northeast-2c.somaz.link          |  43.200.175.34   |
|  kops-ec2                                  |  3.34.40.20      |
|  master-ap-northeast-2a.masters.somaz.link |  3.36.49.142     |
|  nodes-ap-northeast-2a.somaz.link          |  13.124.124.156  |
+--------------------------------------------+------------------+
(somaz:N/A) [root@kops-ec2 ~]# W1PIP=13.124.124.156
(somaz:N/A) [root@kops-ec2 ~]# W2PIP=43.200.175.34


# 모니터링
(somaz:N/A) [root@kops-ec2 ~]# ssh -i ~/.ssh/id_rsa ubuntu@$W1PIP iostat -xmdz 1 -p nvme0n1p1
Linux 4.14.301-224.520.amzn2.x86_64 (kops-ec2)  01/29/2023      _x86_64_        (1 CPU)
...
Device            r/s     rMB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wMB/s   wrqm/s  %wrqm w_await wareq-sz     d/s     dMB/s   drqm/s  %drqm d_await dareq-sz  aqu-sz  %util
nvme0n1p1     3000.00     11.72     0.00   0.00   19.34     4.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00   58.00 100.00


# Read 측정
(somaz:N/A) [root@kops-ec2 ~]# curl -s -O https://raw.githubusercontent.com/wikibook/kubepractice/main/ch10/fio-read.fio
-f fio-read.fio -s local-path --size 10G

(somaz:N/A) [root@kops-ec2 ~]# kubestr fio -f fio-read.fio -s local-path --size 10G
PVC created kubestr-fio-pvc-hhrt4
Pod created kubestr-fio-pod-69m4p
Running FIO test (fio-read.fio) on StorageClass (local-path) with a PVC of Size (10G)
|                                                                                                                                                                                       Elapsed time- 2m32.739061164s
FIO test results:

FIO version - fio-3.30
Global options - ioengine=libaio verify= direct=1 gtod_reduce=

JobName:
  blocksize= filesize= iodepth= rw=
read:
  IOPS=3022.338135 BW(KiB/s)=12089
  iops: min=2556 max=8998 avg=3023.497803
  bw(KiB/s): min=10224 max=35992 avg=12093.991211

Disk stats (read/write):
  nvme0n1: ios=362100/331 merge=0/155 ticks=6626285/6682 in_queue=6632968, util=99.955780%
  -  OK

# Write 측정

(somaz:N/A) [root@kops-ec2 ~]# curl -s -O https://raw.githubusercontent.com/wikibook/kubepractice/main/ch10/fio-write.fio

(somaz:N/A) [root@kops-ec2 ~]# kubestr fio -f fio-write.fio -s local-path --size 10G
(somaz:N/A) [root@kops-ec2 ~]# kubestr fio -f fio-write.fio -s local-path --size 10G
PVC created kubestr-fio-pvc-wbv4p
Pod created kubestr-fio-pod-j475p
Running FIO test (fio-write.fio) on StorageClass (local-path) with a PVC of Size (10G)
Elapsed time- 4m10.719724343s
FIO test results:

FIO version - fio-3.30
Global options - ioengine=libaio verify= direct=1 gtod_reduce=

JobName:
  blocksize= filesize= iodepth= rw=
write:
  IOPS=3022.220215 BW(KiB/s)=12088
  iops: min=1084 max=8636 avg=3021.448242
  bw(KiB/s): min=4336 max=34545 avg=12085.796875

Disk stats (read/write):
  -  OK
  • Read ,Write IOPS 측정 완료

 

 

[과제3]

AWS EBS를 PVC로 사용 후 온라인 볼륨 증가 후 관련 스샷 올려주세요.

 

 

PV / PVC 파드 테스트

# kOps 설치 시 기본 배포
(somaz:N/A) [root@kops-ec2 ~]# kubectl get pod -n kube-system -l app.kubernetes.io/instance=aws-ebs-csi-driver
NAME                                  READY   STATUS    RESTARTS   AGE
ebs-csi-controller-6997dbb57f-9v595   6/6     Running   0          35m
ebs-csi-node-spqmz                    3/3     Running   0          106m
ebs-csi-node-t5tgq                    3/3     Running   0          106m
ebs-csi-node-xpdz9                    3/3     Running   0          107m

# 스토리지 클래스 확인
(somaz:N/A) [root@kops-ec2 ~]# kubectl get sc kops-csi-1-21 kops-ssd-1-17
NAME                      PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
kops-csi-1-21 (default)   ebs.csi.aws.com         Delete          WaitForFirstConsumer   true                   108m
kops-ssd-1-17             kubernetes.io/aws-ebs   Delete          WaitForFirstConsumer   true                   108m

(somaz:N/A) [root@kops-ec2 ~]# kubectl describe sc kops-csi-1-21 | grep Parameters
Parameters:            encrypted=true,type=gp3

(somaz:N/A) [root@kops-ec2 ~]# kubectl describe sc kops-ssd-1-17 | grep Parameters
Parameters:            encrypted=true,type=gp2

# 워커노드에서 파드에 추가한 EBS 볼륨 모니터링
(somaz:N/A) [root@kops-ec2 ~]# 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 생성
(somaz:N/A) [root@kops-ec2 ~]# cat <<EOF | kubectl create -f -
> apiVersion: v1
> kind: PersistentVolumeClaim
> metadata:
>   name: ebs-claim
> spec:
>   accessModes:
>     - ReadWriteOnce
>   resources:
>     requests:
>       storage: 4Gi
> EOF
persistentvolumeclaim/ebs-claim created

# 파드 생성
(somaz:N/A) [root@kops-ec2 ~]# cat <<EOF | kubectl create -f -
> 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
> EOF
pod/app created

# PVC, 파드 확인
(somaz:N/A) [root@kops-ec2 ~]# kubectl get pvc,pv,pod
NAME                              STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS    AGE
persistentvolumeclaim/ebs-claim   Bound    pvc-17afc343-23db-4b09-8a6e-7c49cb06953f   4Gi        RWO            kops-csi-1-21   103s

NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               STORAGECLASS    REASON   AGE
persistentvolume/pvc-17afc343-23db-4b09-8a6e-7c49cb06953f   4Gi        RWO            Delete           Bound    default/ebs-claim   kops-csi-1-21            27s

NAME      READY   STATUS    RESTARTS   AGE
pod/app   1/1     Running   0          30s

(somaz:N/A) [root@kops-ec2 ~]# kubectl df-pv

 PV NAME                                   PVC NAME   NAMESPACE  NODE NAME            POD NAME  VOLUME MOUNT NAME   SIZE  USED  AVAILABLE  %USED  IUSED  IFREE   %IUSED
 pvc-17afc343-23db-4b09-8a6e-7c49cb06953f  ebs-claim  default    i-02c66212258a5124a  app       persistent-storage  3Gi   28Ki  3Gi        0.00   12     262132  0.00

# 추가된 EBS 볼륨 상세 정보 확인
(somaz:N/A) [root@kops-ec2 ~]# aws ec2 describe-volumes --volume-ids $(kubectl get pv -o jsonpath="{.items[0].spec.csi.volumeHandle}") | jq
{
  "Volumes": [
    {
      "Attachments": [
        {
          "AttachTime": "2023-01-29T13:41:43+00:00",
          "Device": "/dev/xvdba",
          "InstanceId": "i-02c66212258a5124a",
          "State": "attached",
          "VolumeId": "vol-0c79e59961767023c",
          "DeleteOnTermination": false
        }
...
      "VolumeType": "gp3",
      "MultiAttachEnabled": false,
      "Throughput": 125
    }
  ]
}

# 파일 내용 추가 저장 확인
(somaz:N/A) [root@kops-ec2 ~]# kubectl exec app -- tail -f /data/out.txt
Sun Jan 29 13:42:41 UTC 2023
Sun Jan 29 13:42:46 UTC 2023
Sun Jan 29 13:42:51 UTC 2023
Sun Jan 29 13:42:56 UTC 2023
Sun Jan 29 13:43:01 UTC 2023
...

# 파드 내에서 볼륨 정보 확인
(somaz:N/A) [root@kops-ec2 ~]# kubectl exec -it app -- sh -c 'df -hT --type=ext4'
Filesystem     Type  Size  Used Avail Use% Mounted on
/dev/nvme2n1   ext4  3.8G   28K  3.8G   1% /data		# 확인완료
/dev/root      ext4  124G  4.1G  120G   4% /etc/hosts

 

AWS console에서 확인한 볼륨 증가 전 사진

 

볼륨 증가 테스트

# 현재 pv 의 이름을 기준하여 4G > 10G 로 증가 : 4Gi 두 군데를 10Gi 로 변경

(somaz:N/A) [root@kops-ec2 ~]# kubectl edit pvc ebs-claim
...
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
-      storage: 4Gi					# 제거
+      storage: 10Gi					# 추가
  storageClassName: kops-csi-1-21
  volumeMode: Filesystem
  volumeName: pvc-d812ffc7-d3c5-4d0f-a1a7-c2e306234209
status:
  accessModes:
  - ReadWriteOnce
  capacity:
-    storage: 4Gi				# 제거
+    storage: 10Gi				# 추가
  phase: Bound
persistentvolumeclaim/ebs-claim edited

# 확인
(somaz:N/A) [root@kops-ec2 ~]# kubectl exec -it app -- sh -c 'df -hT --type=ext4'
Filesystem     Type  Size  Used Avail Use% Mounted on
/dev/nvme2n1   ext4  9.8G   28K  9.7G   1% /data
/dev/root      ext4  124G  4.1G  120G   4% /etc/hosts

(somaz:N/A) [root@kops-ec2 ~]# kubectl df-pv

 PV NAME                                   PVC NAME   NAMESPACE  NODE NAME            POD NAME  VOLUME MOUNT NAME   SIZE  USED  AVAILABLE  %USED  IUSED  IFREE   %IUSED
 pvc-17afc343-23db-4b09-8a6e-7c49cb06953f  ebs-claim  default    i-02c66212258a5124a  app       persistent-storage  9Gi   28Ki  9Gi        0.00   12     655348  0.00
 
 (somaz:N/A) [root@kops-ec2 ~]# aws ec2 describe-volumes --volume-ids $(kubectl get pv -o jsonpath="{.items[0].spec.csi.volumeHandle}") | jq
{
  "Volumes": [
    {
      "Attachments": [
        {
          "AttachTime": "2023-01-29T13:41:43+00:00",
          "Device": "/dev/xvdba",
          "InstanceId": "i-02c66212258a5124a",
          "State": "attached",
          "VolumeId": "vol-0c79e59961767023c",
          "DeleteOnTermination": false
        }
 ...
      "VolumeType": "gp3",
      "MultiAttachEnabled": false,
      "Throughput": 125
    }
  ]
}
  • 주의할점 : 볼륨을 늘릴수는 있어도 줄일수는 없다!

 

AWS console에서 확인한 볼륨 증가 후 사진

 

삭제

(somaz:N/A) [root@kops-ec2 ~]# kubectl delete pod app & kubectl delete pvc ebs-claim
[1] 21187
persistentvolumeclaim "ebs-claim" deleted
pod "app" deleted

 

 

 

[과제4]

AWS Volume SnapShots 실습 후 관련 스샷 올려주세요.

 

 

스냅샷 컨트롤러 설치

# kops 클러스터 편집
(somaz:N/A) [root@kops-ec2 ~]# kops edit cluster
...
spec:
  snapshotController:
    enabled: true
  certManager:  # 이미 설치됨
    enabled: true  # 이미 설치됨
....

# 업데이트 적용
(somaz:N/A) [root@kops-ec2 ~]# kops update cluster --yes && sleep 3 && kops rolling-update cluster

# 확인 >> 배포 시 3분 정도 소요됨
(somaz:N/A) [root@kops-ec2 ~]# kubectl get crd | grep volumesnapshot
volumesnapshotclasses.snapshot.storage.k8s.io    2023-01-29T13:00:26Z
volumesnapshotcontents.snapshot.storage.k8s.io   2023-01-29T13:00:26Z
volumesnapshots.snapshot.storage.k8s.io          2023-01-29T13:00:26Z

# vsclass 생성
(somaz:N/A) [root@kops-ec2 ~]# kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-ebs-csi-driver/master/examples/kubernetes/snapshot/manifests/classes/snapshotclass.yaml

(somaz:N/A) [root@kops-ec2 ~]# kubectl get volumesnapshotclass
NAME          DRIVER            DELETIONPOLICY   AGE
csi-aws-vsc   ebs.csi.aws.com   Delete           52m

 

 

테스트 PVC/파드 생성

# PVC 생성
(somaz:N/A) [root@kops-ec2 ~]# cat <<EOF | kubectl create -f -
> apiVersion: v1
> kind: PersistentVolumeClaim
> metadata:
>   name: ebs-claim
> spec:
>   accessModes:
>     - ReadWriteOnce
>   resources:
>     requests:
>       storage: 4Gi
> EOF
persistentvolumeclaim/ebs-claim created

# 파드 생성
(somaz:N/A) [root@kops-ec2 ~]# cat <<EOF | kubectl create -f -
> apiVersion: v1
> kind: Pod
> metadata:
>   name: app
> spec:
>   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
> EOF
pod/app created

# Create a VolumeSnapshot referencing the PersistentVolumeClaim name
(somaz:N/A) [root@kops-ec2 ~]# cat <<EOF | kubectl create -f -
> apiVersion: snapshot.storage.k8s.io/v1
> kind: VolumeSnapshot
> metadata:
>   name: ebs-volume-snapshot
> spec:
>   volumeSnapshotClassName: csi-aws-vsc
>   source:
>     persistentVolumeClaimName: ebs-claim
> EOF
volumesnapshot.snapshot.storage.k8s.io/ebs-volume-snapshot created

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

# 스냅샷 생성 확인
(somaz:N/A) [root@kops-ec2 ~]# kubectl get volumesnapshot
NAME                  READYTOUSE   SOURCEPVC   SOURCESNAPSHOTCONTENT   RESTORESIZE   SNAPSHOTCLASS   SNAPSHOTCONTENT                                    CREATIONTIME   AGE
ebs-volume-snapshot   false        ebs-claim                           4Gi           csi-aws-vsc     snapcontent-38b84004-7290-4019-9928-9693a69ee4a9   51s            51s

(somaz:N/A) [root@kops-ec2 ~]# kubectl get volumesnapshot ebs-volume-snapshot -o jsonpath={.status.boundVolumeSnapshotContentName}
snapcontent-38b84004-7290-4019-9928-9693a69ee4a9

AWS Console에서 스냅샷 생성확인
AWS Console에서&nbsp;볼륨 생성 확인

볼륨 / PVC 제거

(somaz:N/A) [root@kops-ec2 ~]# kubectl delete pod app && kubectl delete pvc ebs-claim
pod "app" deleted
persistentvolumeclaim "ebs-claim" deleted

AWS Console에서 볼륨 제거 확인

 

 

스냅샷으로 복원

# 복원
(somaz:N/A) [root@kops-ec2 ~]# cat <<EOF | kubectl create -f -
> apiVersion: v1
> kind: PersistentVolumeClaim
> metadata:
>   name: ebs-snapshot-restored-claim
> spec:
>   accessModes:
>     - ReadWriteOnce
>   resources:
>     requests:
>       storage: 4Gi
>   dataSource:
>     name: ebs-volume-snapshot
>     kind: VolumeSnapshot
>     apiGroup: snapshot.storage.k8s.io
> EOF
persistentvolumeclaim/ebs-snapshot-restored-claim created

# 확인
(somaz:N/A) [root@kops-ec2 ~]# k get pvc,pv
NAME                                                STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS    AGE
persistentvolumeclaim/ebs-snapshot-restored-claim   Pending
     kops-csi-1-21   19s

# 파드 생성
(somaz:N/A) [root@kops-ec2 ~]# cat <<EOF | kubectl create -f -
> apiVersion: v1
> kind: Pod
> metadata:
>   name: app
> spec:
>   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-snapshot-restored-claim
> EOF
pod/app created

# 다시 확인
(somaz:N/A) [root@kops-ec2 ~]# k get pvc,pv
NAME                                                STATUS   VOLUME
            CAPACITY   ACCESS MODES   STORAGECLASS    AGE
persistentvolumeclaim/ebs-snapshot-restored-claim   Bound    pvc-5e3ca4b2-cb86-4086-af8e-730c96e55bcc   4Gi        RWO            kops-csi-1-21   65s

NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                 STORAGECLASS    REASON   AGE
persistentvolume/pvc-5e3ca4b2-cb86-4086-af8e-730c96e55bcc   4Gi        RWO            Delete           Bound    default/ebs-snapshot-restored-claim   kops-csi-1-21            14s

# 파일 내용 저장 확인 : 파드 삭제전 기록도 남아있다.
(somaz:N/A) [root@kops-ec2 ~]# kubectl exec app -- cat /data/out.txt
Sun Jan 29 13:58:14 UTC 2023
Sun Jan 29 13:58:19 UTC 2023
...
Sun Jan 29 14:04:14 UTC 2023
Sun Jan 29 14:04:19 UTC 2023
Sun Jan 29 14:04:24 UTC 2023

 

AWS Console에서 다시 볼륨 생성 확인

 

해당 볼륨 상세 정보

 

스터디 주요 내용

 

1. Ingress

클러스터 내부의 서비스(ClusterIP, NodePort, LoadBalancer)를 외부로 노출(HTTP/HTTPS) 하는 역할을 한다.

출처 : 가시다님 스터디 노션

2022.08.08 - [Container Orchestration/Kubernetes] - Ingress(인그레스)

 

Ingress(인그레스)

Oveview 오늘은 ingress에 대해서 공부해보려고 한다. 용어 이 가이드는 용어의 명확성을 위해 다음과 같이 정의한다. 노드(Node): 클러스터의 일부이며, 쿠버네티스에 속한 워커 머신. 클러스터(Cluster

somaz.tistory.com

 

2. 쿠버네티스 스토리지

 

쿠버네티스 스토리지 배경

쿠버네티스 스토리지가 나온 배경은 데이터의 보존의 필요성을 느끼면서 나오게 되었다.

따라서, Pod의 데이터의 보존이 필요한 것들을 (statefulset)으로 생성한 후 PV(Persistent Volume)을 붙인다.

(ex. DB, elasticsearch, prometheus, rabbitmq, redis 등)

 

스토리지 소개

볼륨의 종류에는 emptyDir, hostPath, PVC / PV 가 있다.

출처 : 김태민 기술 블로그

  • emptyDir 
    • 파드가 생성될때 함께 생성되는 볼륨이다.
    • 이름에서 알 수 있듯이 처음에는 비어있다.
    • 파드 내의 컨테이너간 emptyDir볼륨의 동일한 파일을 읽고 쓸 수 있다.
    • pod 가 제거되면 emptyDir도 함께 영구 삭제된다.
    • emptyDir의 생명주기는 pod단위다. pod 내의 컨테이너가 충돌하여 재시작하여도 emptDir은 삭제되지 않는다.(pod를 제거해야 삭제된다.)
  • hostPath:
    • hostPath 볼륨은 노드의 로컬 디스크를 pod에 마운트해서 사용한다.
    • 각 Node의 Path을 사용하고 Node 추가시 Mount를 걸어준다.
    • 같은 hostPath에 있는 볼륨을 여러 pod간 공유되어 사용 가능하다.
    • (emptyDir은 pod 내의 컨테이너간 공유가 가능했지만 hostPath은 Pod간 공유 가능)
    • Pod가 삭제되더라도 hostPath에 있는 파일들은 삭제되지 않는다.
  • PVC / PV
    • PV
      • 일반적인 Volume은 Pod과 동일한 라이프사이클을 가지지만 PV는 리소스를 사용하는 Pod과 별개의 라이프사이클을 가진다.
      • 따라서 Pod이 종료되어도 PV에 기록된 데이터는 삭제되지 않고 남아있다.
    • PVC
      • PVC는 해당 리소스에 대한 요청이며 리소스에 대한 클레임 검사 역할을 한다.
      • PVC를 명시하면 쿠버네티스는 적정한 크기와 접근 모드의 PV를 찾고 PVC를 PV에 할당한다.
    • PVC / PV 생성방법
      • PV 정의 생성
      • PVC 생성
      • 그리고 PV를 연결
      • Pod 생성시 PVC를 마운트해준다.

 

그리고 다양한 볼륨을 사용한다.

K8S 자체 제공(hostPath, local), 온프렘 솔루션(ceph 등), NFS, 클라우드 스토리지(AWS EBS 등)

2022.07.29 - [Understand different OS Concepts/Memory,Storage] - Ceph 란?

출처 : 가시다님 스터디 노션

 

 

동적 프로비저닝 & 볼륨 상태, ReclaimPolicy

출처 : 가시다님 스터디 노션

 

CSI란?

CSI (Container Storage Interface)란 Kubernetes가 컨테이너화된 워크로드에 임의의 스토리지 시스템을 노출할 수 있게 해주는 개방형 표준 API 이다.

CSI 를 사용하면, K8S 의 공통화된 CSI 인터페이스를 통해 다양한 프로바이더를 사용할 수 있다.

출처 : AWS 문서

일반적인 CSI driver의 구조입니다.

AWS EBS CSI driver 역시 아래와 같은 구조를 가지는데, 오른쪽 StatefulSet 또는 Deployment로 배포된 controller Pod이 AWS API를 사용하여 실제 EBS volume을 생성하는 역할을 합니다.

왼쪽 DaemonSet으로 배포된 node Pod은 AWS API를 사용하여 Kubernetes node (EC2 instance)에 EBS volume을 attach 해줍니다.

출처 : 가시다님 스터디 노션

 

3. AWS EBS Controller

EBS CSI driver 동작 : 볼륨 생성 및 파드에 볼륨 연결

출처 : 가시다님 스터디 노션

 

 

4. AWS Volume SnapShots Controllers

지정 시간 스냅샷을 만들어 Amazon S3에 Amazon EBS 볼륨의 데이터를 백업할 수 있다.

스냅샷은 증분식 백업이어서 마지막 스냅샷 이후 변경된 디바이스의 블록만이 저장된다.

그러면 스냅샷을 만드는 데 필요한 시간이 최소화되며 데이터를 복제하지 않으므로 스토리지 비용이 절약된다.

각 스냅샷에는 (스냅샷을 만든 시점의) 데이터를 새 EBS 볼륨에 복원하는 데 필요한 모든 정보가 들어 있다.

 

 

스냅샷 컨트롤러 설치

# kOps 클러스터 편집
kops edit cluster
-----
spec:
  snapshotController:
    enabled: true
  certManager:  # 이미 설치됨
    enabled: true  # 이미 설치됨
-----

# 업데이트 적용
kops update cluster --yes && sleep 3 && kops rolling-update cluster

# 확인 >> 배포 시 3분 정도 소요됨
watch kubectl get pod -n kube-system
kubectl get crd | grep volumesnapshot
volumesnapshotclasses.snapshot.storage.k8s.io    2022-07-19T13:45:26Z
volumesnapshotcontents.snapshot.storage.k8s.io   2022-07-19T13:45:26Z
volumesnapshots.snapshot.storage.k8s.io          2022-07-19T13:45:26Z

# vsclass 생성
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-ebs-csi-driver/master/examples/kubernetes/snapshot/manifests/classes/snapshotclass.yaml
kubectl get volumesnapshotclass
NAME          DRIVER            DELETIONPOLICY   AGE
csi-aws-vsc   ebs.csi.aws.com   Delete           6s

 

증분 스냅샷의 작동 방식

출처 :&nbsp;https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/EBSSnapshots.html

 

5. AWS EFS Controllers

출처 :&nbsp;https://dev.to/awscommunity-asean/aws-eks-with-efs-csi-driver-and-irsa-using-cdk-dgc

Amazon Elastic Block Store(Amazon EBS) CSI(Container Storage Interface) 드라이버에서는 Amazon Elastic Kubernetes Service(Amazon EKS) 클러스터가 영구 볼륨을 위해 Amazon EBS 볼륨의 수명 주기를 관리할 수 있게 한다.

Amazon EBS CSI 드라이버 사용에 대해 고려해야 할 몇 가지 사항이 있다.

  • Amazon EBS CSI 플러그 인이 사용자를 대신하여 AWS API를 호출하려면 IAM 권한이 필요하다. 
  • Fargate에서 Amazon EBS CSI 컨트롤러를 실행할 수 있지만 Fargate pods에 볼륨을 탑재할 수는 없다.
  • Amazon EKS 클러스터에서는 Amazon EBS CSI 드라이버의 알파 기능을 지원하지 않다.

 

EFS 파일시스템 생성 및 EFS Controller 설치 - 링크 Github Helm

EFS 파일시스템을 다수의 파드가 사용하게 설정 : Add empty StorageClasses from static example - 링크

EFS access points 를 이용하여 Dynamic Provisioning - 링크 Docs

 

 

스터디 3주차 후기

3주차에는 쿠버네티스 Ingress와 Storage에 대해서 중점적으로 배웠다.

이번주에는 회사 업무가 밀려오면서 스터디 공부에 시간을 많이 사용하지 못하였다.

그래서 결국 과제1번은 혼자만의 힘으로 해결하지 못하였고, 다른 스터디원분들이 정리한 내용들을 보면서 공부할 수 밖에 없었다.

다음주부터는 다시 집중해보도록 하겠습니다. 

 

Reference

https://kubernetes.io/blog/2018/07/12/resizing-persistent-volumes-using-kubernetes/

https://aws.amazon.com/ko/blogs/containers/how-to-expose-multiple-applications-on-amazon-eks-using-a-single-application-load-balancer/

https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/EBSSnapshots.html

https://dev.to/awscommunity-asean/aws-eks-with-efs-csi-driver-and-irsa-using-cdk-dgc

728x90
반응형