AEWS 스터디에서는 AWS의 관리형 Kubernetes인 Elastic Kubernetes의 다양한 기능들을 실습해보면서 익혀본다. 이 글은 스터디를 참여하면서 학습한 내용을 정리하는 연재 글이다. 스터디 진도에 맞춰 글을 작성한다.
이 글에서는 EKS Storage와 Node 관리에 대해서 알아본다.
0. 실습환경 배포
스터디에서 가시다님이 공유해준 실습환경에는 IRSA를 eksctl 이 아닌 처음부터 aws-load-balancer-controller iam 생성되도록 되어 있다.
1
2
3
4
5
6
7
8
9
10
11
12
|
# YAML 파일 다운로드
curl -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/K8S/eks-oneclick2.yaml
# CloudFormation 스택 배포
예시) aws cloudformation deploy --template-file eks-oneclick2.yaml --stack-name myeks --parameter-overrides KeyName=kp-gasida SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32 MyIamUserAccessKeyID=AKIA5... MyIamUserSecretAccessKey='CVNa2...' ClusterBaseName=myeks --region ap-northeast-2
# CloudFormation 스택 배포 완료 후 작업용 EC2 IP 출력
aws cloudformation describe-stacks --stack-name myeks --query 'Stacks[*].Outputs[0].OutputValue' --output text
52.78.137.89
# 작업용 EC2 SSH 접속
ssh -i ~/.ssh/ygpark.pem ec2-user@$(aws cloudformation describe-stacks --stack-name myeks --query 'Stacks[*].Outputs[0].OutputValue' --output text)
|
cs |
기본 설정 및 EFS 확인
기본설정을 하고, EFS 확인해본다. Elastic File System에서 myeks-EFS 파일 시스템을 찾아 연결에 들어가면 EFS FS ID를 확인 할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
# default 네임스페이스 적용
kubectl ns default
# (옵션) context 이름 변경
NICK=<각자 자신의 닉네임>
NICK=ygpark
kubectl ctx
kubectl config rename-context admin@myeks.ap-northeast-2.eksctl.io $NICK@myeks
# EFS 확인 : AWS 관리콘솔 EFS 확인해보자
mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport fs-039ce649ee35cc947.efs.ap-northeast-2.amazonaws.com:/ /mnt/myefs
df -hT --type nfs4
Filesystem Type Size Used Avail Use% Mounted on
fs-0a2ada15affdc5867.efs.ap-northeast-2.amazonaws.com:/ nfs4 8.0E 0 8.0E 0% /mnt/myefs
mount | grep nfs4
echo "efs file test" > /mnt/myefs/memo.txt
cat /mnt/myefs/memo.txt
rm -f /mnt/myefs/memo.txt
|
cs |
노드의 정보를 환경변수에 설정해 놓고, 접근해놓는다.
실습에서는 gp2타입으로 EBS 기본 스토리지 클래스가 있긴하지만 쓰지 않고, EBS 클러스터 컨트롤러를 설치하여 gp3타입으로 설치할 예정이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
# 스토리지클래스 및 CSI 노드 확인
kubectl get sc
kubectl get sc gp2 -o yaml | yh
kubectl get csinodes
# 노드 정보 확인
kubectl get node --label-columns=node.kubernetes.io/instance-type,eks.amazonaws.com/capacityType,topology.kubernetes.io/zone
eksctl get iamidentitymapping --cluster myeks
# 노드 IP 확인 및 PrivateIP 변수 지정
N1=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2a -o jsonpath={.items[0].status.addresses[0].address})
N2=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2b -o jsonpath={.items[0].status.addresses[0].address})
N3=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2c -o jsonpath={.items[0].status.addresses[0].address})
echo "export N1=$N1" >> /etc/profile
echo "export N2=$N2" >> /etc/profile
echo "export N3=$N3" >> /etc/profile
echo $N1, $N2, $N3
192.168.1.122, 192.168.2.141, 192.168.3.34
# 노드 보안그룹 ID 확인
NGSGID=$(aws ec2 describe-security-groups --filters Name=group-name,Values=*ng1* --query "SecurityGroups[*].[GroupId]" --output text)
aws ec2 authorize-security-group-ingress --group-id $NGSGID --protocol '-1' --cidr 192.168.1.100/32
{
"Return": true,
"SecurityGroupRules": [
{
"SecurityGroupRuleId": "sgr-0278c509e486ed40d",
"GroupId": "sg-0a1f22e39719a0e26",
"GroupOwnerId": "991354587926",
"IsEgress": false,
"IpProtocol": "-1",
"FromPort": -1,
"ToPort": -1,
"CidrIpv4": "192.168.1.100/32"
}
]
}
# 워커 노드 SSH 접속
ssh ec2-user@$N1 hostname
ssh ec2-user@$N2 hostname
ssh ec2-user@$N3 hostname
# 노드에 툴 설치
ssh ec2-user@$N1 sudo yum install links tree jq tcpdump sysstat -y
ssh ec2-user@$N2 sudo yum install links tree jq tcpdump sysstat -y
ssh ec2-user@$N3 sudo yum install links tree jq tcpdump sysstat -y
|
cs |
AWS LB/ExternalDNS, kube-ops-view 설치
external DNS는 ExternalDNS Addon 설치를 하면 Kubernetes의 Service 또는 Ingress 생성 시에 Public Cloud의 DNS 서비스들 - AWS(Route 53), Azure(DNS), GCP(Cloud DNS)에 자동으로 A 레코드를 등록 / 삭제 해준다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
# AWS LB Controller
helm repo add eks https://aws.github.io/eks-charts
helm repo update
helm install aws-load-balancer-controller eks/aws-load-balancer-controller -n kube-system --set clusterName=$CLUSTER_NAME \
--set serviceAccount.create=false --set serviceAccount.name=aws-load-balancer-controller
# ExternalDNS
MyDomain=<자신의 도메인>
MyDomain=ygpark.net
MyDnzHostedZoneId=$(aws route53 list-hosted-zones-by-name --dns-name "${MyDomain}." --query "HostedZones[0].Id" --output text)
echo $MyDomain, $MyDnzHostedZoneId
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/aews/externaldns.yaml
MyDomain=$MyDomain MyDnzHostedZoneId=$MyDnzHostedZoneId envsubst < externaldns.yaml | kubectl apply -f -
# kube-ops-view
helm repo add geek-cookbook https://geek-cookbook.github.io/charts/
helm install kube-ops-view geek-cookbook/kube-ops-view --version 1.2.2 --set env.TZ="Asia/Seoul" --namespace kube-system
kubectl patch svc -n kube-system kube-ops-view -p '{"spec":{"type":"LoadBalancer"}}'
kubectl annotate service kube-ops-view -n kube-system "external-dns.alpha.kubernetes.io/hostname=kubeopsview.$MyDomain"
echo -e "Kube Ops View URL = http://kubeopsview.$MyDomain:8080/#scale=1.5"
|
cs |
kube-ops-view는 노드별로 파드의 배포 상태를 쉽게 모니터링 할 수 있도록 하는 툴이다. annotate에 dns 등록해서 CLB에 붙어있는 파드를 등록한 도메인을 사용해서 접근할 수 있다.
설치 정보 확인
1
2
3
4
5
6
7
8
9
10
|
# 이미지 정보 확인
kubectl get pods --all-namespaces -o jsonpath="{.items[*].spec.containers[*].image}" | tr -s '[[:space:]]' '\n' | sort | uniq -c
# eksctl 설치/업데이트 addon 확인
eksctl get addon --cluster $CLUSTER_NAME
# IRSA 확인
eksctl get iamserviceaccount --cluster $CLUSTER_NAME
NAMESPACE NAME ROLE ARN
kube-system aws-load-balancer-controller arn:aws:iam::991354587926:role/eksctl-myeks-addon-iamserviceaccount-kube-sy-Role1-151FDTGSDPUAY
|
cs |
1. Kubernetes 스토리지
Kubernetes 스토리지의 이해
파드는 모두 상태가 없는(Stateless) 애플리케이션이다. 즉, 내부의 데이터는 파드가 정지되면 모두 삭제된다. 파일시스템은 파드의 라이프사이클과 같이 삭제되어 버린다.
PV & PVC는 데이터베이스(파드)처럼 데이터 보존이 필요한 경우, 상태가 있는(Stateful) 애플리케이션을 사용하기 위해 만들어 졌다. PV는 별도의 저장소를 만들고, PVC로 Pod에 붙여 사용하게된다.
파드가 생성될 때 자동으로 볼륨을 마운트하여 파드에 연결하는 기능을 동적 프로비저닝(Dynamic Provisioning)이라고 한다. 볼륨에 대한 PV를 매번 만들어서 볼륨을 수 많은 Pod에 붙여 사용하기는 어려울 수 있기 때문에 세팅해 놓은 정책(스토리지 클래스) 에 따라 Provisioner가 PV를 생성하여 볼륨을 연결해준다.
설정해놓은 Reclaim Policy에 따라 퍼시스턴트 볼륨의 사용이 끝났을 때는 Retain(보존), Delete(삭제) 된다. Retain(보존) 시에는 수동으로 볼륨을 삭제해줘야 한다.
CSI (Contaier Storage Interface)
스토리지 제공업체는 Kubernetes에 대한 스토리지 지원을 쉽게 할 수 있도록 CSI Driver를 제공한다. CSI Driver사용 하면 K8S 의 공통화된 CSI 인터페이스를 사용하여 다양한 제공업체의 스토리지 자원을 사용할 수 있다.
Node-specific Volume Limits
Pod 생성 제한과 같이 attach해서 붙일 수 있는 개수, 한 워커노드당 최대 개수가 정해져있다. AWS EC2 Type에 따라 볼륨 최대 제한이 25개 ~ 39개이다.
- KUBE_MAX_PD_VOLS 환경 변수의 값을 설정한 후, 스케줄러를 재시작하여 이러한 한도를 변경 가능
1
2
3
4
|
# 확인
kubectl describe node | grep Allocatable: -A1
Allocatable:
attachable-volumes-aws-ebs: 25
|
cs |
3. 스토리지 기능 실습
기본 컨테이너 환경의 임시 파일시스템 사용
10초 간격으로 해당 텍스트 파일에 저장하는 어플리케이션을 배포해서 파일 시스템을 알아본다. 파드를 삭제하면 기록이 같이 삭제된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
# 파드 배포
# date 명령어로 현재 시간을 10초 간격으로 /home/pod-out.txt 파일에 저장
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/3/date-busybox-pod.yaml
cat date-busybox-pod.yaml | yh
apiVersion: v1
kind: Pod
metadata:
name: busybox
spec:
terminationGracePeriodSeconds: 3
containers:
- name: busybox
image: busybox
command:
- "/bin/sh"
- "-c"
- "while true; do date >> /home/pod-out.txt; cd /home; sync; sync; sleep 10; done"
kubectl apply -f date-busybox-pod.yaml
# 파일 확인
kubectl get pod
kubectl exec busybox -- tail -f /home/pod-out.txt
Sat Jan 28 15:33:11 UTC 2023
Sat Jan 28 15:33:21 UTC 2023
...
# 파드 삭제 후 다시 생성 후 파일 정보 확인 > 이전 기록이 보존되어 있는지?
kubectl delete pod busybox
kubectl apply -f date-busybox-pod.yaml
kubectl exec busybox -- tail -f /home/pod-out.txt
# 실습 완료 후 삭제
kubectl delete pod busybox
|
cs |
호스트 Path 를 사용하는 PV/PVC : local-path-provisioner 스트리지 클래스 배포
- local-path-provisioner 스토리지 클래스 배포
1
2
3
4
5
6
7
8
9
10
11
12
|
# 배포
curl -s -O https://raw.githubusercontent.com/rancher/local-path-provisioner/master/deploy/local-path-storage.yaml
kubectl apply -f local-path-storage.yaml
# 확인
kubectl get-all -n local-path-storage
kubectl get pod -n local-path-storage -owide
kubectl describe cm -n local-path-storage local-path-config
kubectl get sc
kubectl get sc local-path
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
local-path rancher.io/local-path Delete WaitForFirstConsumer false 34s
|
cs |
- PV/PVC 를 사용하는 파드 생성
위에서 만든 SC를 사용하는 PVC를 생성하고, PVC를 사용하는 파드 생성한다. 노드의 스토리지를 사용하기 때문에 Node Affinity가 처음으로 연결된 볼륨의 노드로 설정된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
# PVC 생성
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/3/localpath1.yaml
cat localpath1.yaml | yh
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: localpath-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: "local-path"
kubectl apply -f localpath1.yaml
# PVC 확인
kubectl get pvc
kubectl describe pvc
# 파드 생성
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/3/localpath2.yaml
cat localpath2.yaml | yh
kubectl apply -f localpath2.yaml
# 파드 확인
kubectl get pod,pv,pvc
kubectl describe pv # Node Affinity 확인
kubectl exec -it app -- tail -f /data/out.txt
Sun Jan 29 05:13:45 UTC 2023
...
# 워커노드 중 현재 파드가 배포되어 있다만, 아래 경로에 out.txt 파일 존재 확인
ssh ec2-user@$N1 tree /opt/local-path-provisioner
/opt/local-path-provisioner
└── pvc-f1615862-e4cd-47d0-b89c-8d0e99270678_default_localpath-claim
└── out.txt
# 해당 워커노드 자체에서 out.txt 파일 확인 : 아래 굵은 부분은 각자 실습 환경에 따라 다름
ssh ec2-user@$N1 tail -f /opt/local-path-provisioner/pvc-f1615862-e4cd-47d0-b89c-8d0e99270678_default_localpath-claim/out.txt
ssh ec2-user@$N3 tail -f /opt/local-path-provisioner/pvc-4beadd1c-d35d-4a34-954c-f54ca8f2fcc2_default_localpath-claim/out.txt
Sun Jan 29 05:13:45 UTC 2023
...
|
cs |
- 파드 삭제 후 파드 재생성해서 데이터 유지 되는지 확인
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
# 파드 삭제 후 PV/PVC 확인
kubectl delete pod app
kubectl get pod,pv,pvc
ssh ec2-user@$N3 tree /opt/local-path-provisioner
# 파드 다시 실행
kubectl apply -f localpath2.yaml
# 확인
kubectl exec -it app -- head /data/out.txt
kubectl exec -it app -- tail -f /data/out.txt
# 파드와 PVC 삭제
kubectl delete pod app
kubectl get pv,pvc
kubectl delete pvc localpath-claim
# 확인
kubectl get pv
ssh ec2-user@$N3 tree /opt/local-path-provisioner
|
cs |
'스터디 > Kubernetes' 카테고리의 다른 글
[AWES] EKS Storage 3/5 - AWS Volume SnapShots Controller (1) | 2023.05.14 |
---|---|
[AWES] EKS Storage 2/5 - AWS EBS Controller (1) | 2023.05.14 |
[AWES] EKS Networking - AWS LB Controller, Ingress (0) | 2023.05.07 |
[AWES] EKS Networking 특징과 네트워크 흐름 (0) | 2023.05.07 |
[AEWS] Amzaon EKS - Cluster Endpoint 구성 톱아보기 (0) | 2023.04.30 |