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
삭제 및 삭제 확인
# 삭제
(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
볼륨 증가 테스트
# 현재 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
}
]
}
- 주의할점 : 볼륨을 늘릴수는 있어도 줄일수는 없다!
삭제
(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
볼륨 / PVC 제거
(somaz:N/A) [root@kops-ec2 ~]# kubectl delete pod app && kubectl delete pvc ebs-claim
pod "app" deleted
persistentvolumeclaim "ebs-claim" deleted
스냅샷으로 복원
# 복원
(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
스터디 주요 내용
1. Ingress
클러스터 내부의 서비스(ClusterIP, NodePort, LoadBalancer)를 외부로 노출(HTTP/HTTPS) 하는 역할을 한다.
2022.08.08 - [Container Orchestration/Kubernetes] - Ingress(인그레스)
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를 마운트해준다.
- PV
그리고 다양한 볼륨을 사용한다.
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 인터페이스를 통해 다양한 프로바이더를 사용할 수 있다.
일반적인 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
증분 스냅샷의 작동 방식
5. AWS EFS Controllers
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://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
'교육, 커뮤니티 후기 > PKOS 쿠버네티스 스터디' 카테고리의 다른 글
PKOS 쿠버네티스 스터디 6주차 - 얼럿매니저 로깅시스템 (0) | 2023.02.19 |
---|---|
PKOS 쿠버네티스 스터디 5주차 - 프로메테우스 그라파나 (0) | 2023.02.14 |
PKOS 쿠버네티스 스터디 4주차 - Harbor Gitlab Argocd (2) | 2023.02.06 |
PKOS 쿠버네티스 스터디 2주차 - 쿠버네티스 네트워크 (0) | 2023.01.16 |
PKOS 쿠버네티스 스터디 1주차 - kOps 클러스터 배포 (2) | 2023.01.08 |