3주차 eks 스터디는 스토리지 및 노드 관리이다.

 

 

3주차 실습 환경 구성은 앞선 2주차와 마찬가지로 클라우드 포메이션을 통해 배포를 진행한다.

2주차

https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/K8S/eks-oneclick.yaml

3주차

https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/K8S/eks-oneclick2.yaml

 

2주차 3주차 각각 다운받아서 diff로 비교해보면 efs 쪽 설정이 추가된것을 확인할수있다.

  • Amazon EKS 윈클릭 배포 (EFS 생성 추가) & 기본 설정
    • 기본 설정 및 EFS 확인
    # default 네임스페이스 적용
    **kubectl ns default**
    
    # (옵션) context 이름 변경
    NICK=<각자 자신의 닉네임>
    **NICK=gasida**
    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 ***<자신의 EFS FS ID>***.efs.ap-northeast-2.amazonaws.com:/ **/mnt/myefs**
    **df -hT --type nfs4**
    mount | grep nfs4
    **echo "efs file test" > /mnt/myefs/memo.txt**
    cat /mnt/myefs/memo.txt
    **rm -f /mnt/myefs/memo.txt**
    
    # 스토리지클래스 및 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
    
    # 노드 보안그룹 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
    
    # 워커 노드 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
    
    • AWS LB/ExternalDNS, kube-ops-view 설치
    # 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=gasida.link**
    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"
    
    • 설치 정보 확인
    # 이미지 정보 확인
    **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**
    

 

 

2주차와 마찬가지(efs 및 2주차에서 실습 진행했떤 ALB등은 추가돼있음)로 위와같이 진행하면 3주차 실습 준비 완료

 

 

첫번째 사진처럼 파드안의 컨테이너 내 tmpFS가 있는경우 컨테이너가 종료되면 tmpFS내 데이터도 삭제된다.

마찬가지로 두번째 사진처럼 파드내에 볼륨이 있고 두개의 컨테이너가 해당 볼륨을 공유해서 사용하여도 파드가 종료되면 볼륨내 데이터도 삭제가 된다.

따라서 컨테이너, 파드의 종료여부와 상관없이 데이터를 보존하기 위해 PV/PVC가 필요하다.

앞서 PV/PVC를 이용하지 않는다면(즉 컨테이너 내에 임시의 파일시스템을 이용한다면)데이터가 보존되지 않는다고했는데 이를 실제로 확인해보면 아래와 같다.

10초간격으로 date를 찍는 busybox를 deployment로 배포하고 pod-out.txt 확인하면 10초에 한번씩 찍힌것을 볼수있다.

이후 busybox 파드를 종료후 다시 확인해보면 이전에 찍혔던 date(즉 기존 데이터)는 보존되지 않은것을 확인할수있다.

 

이번에는 local-path-provisioner 스트리지 클래스를 사용하여 데이터 보존성을 확인해보자.

위와같이 local-path-provisioner 사용하기 위해 localpth claim 을 생성해주고

위와같이 앞서 생성한 PVC를 마운트하여 파드를 실행하고 아까와같이 파드를 재시작하여 데이터 보존유무를 확인해보자.

위와같이 파드를 종료하여도 데이터가 없어지지않고 기존 데이터가 보존되는것을 확인할수있다.

실제 데이터는 node1에 저장돼있는것을 확인할수있다.

 

여기까지 eks 클러스터내의 파드를 이용한 볼륨 마운트를 알아보았는데 지금부터는 AWS EBS 마운트를 알아보도록 하자.

 

```bash
# 아래는 **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
```

-

2주차때 했던것처럼 IRSA 설정해서 AWS EBS와 EKS 클러스터간에 통신이 가능하도록 해줘야 한다. 

ebs 테스트 준비 완료

 

이제 아까처럼 pv/pvc 로 마운트하여 테스트해보자.

기존

위와같이 pvc 생성하고 해당 pvc를 마운트하는 파드를 새로 생성하면 아래와같이 새로운 볼륨이 생성된것을 확인할수있다.

이와같이 파드에 EBS를 마운트하여 사용할수있다. 또한 기존 aws ebs와 마찬가지로 용량 증설도 가능하다.(반대로 축소는 불가능)

 

이번엔 볼륨 스냅샷에 대해 알아보자. 이또한 EKS의 개념이 아닌 aws내 ebs 의 스냅샷 기능을 이용하는것.

 

```bash
# (참고) 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
```

 위와같이 준비 진행

 

위와같이 볼륨 스냅샷을 apply하면 아래와같이 스냅샷이 생성된것을 확인할수있다.

 

 

그럼 장애를 재연해서 스냅샷으로 복원해보도록 하자.

위와같이 실수록 삭제한 상황에서

우선 위와같이 datasource를 ebs볼륨 스냅샷을 가지고 pvc를 생성해주고

위와같이 스냅샷을 이용하여 생성한 pvc를 가지고 파드를 생성해주면 

위와같이 기존에 가지고 있떤 스냅샷을 가지고 ebs를 생성된것이 확인된다.

 

이번엔 efs에 대해 진행할것이다.

우선 efs의 구성 및 아키텍쳐는 다음과 같다.

(처음 efs 에 대해 공부할때 AWS에 있는 NFS로 이해했었다.)

 

# EFS 정보 확인 
aws efs describe-file-systems --query "FileSystems[*].FileSystemId" --output text

# IAM 정책 생성
curl -s -O <https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/master/docs/**iam-policy-example.json**>
aws iam create-policy --policy-name **AmazonEKS_EFS_CSI_Driver_Policy** --policy-document file://iam-policy-example.json

# ISRA 설정 : 고객관리형 정책 AmazonEKS_EFS_CSI_Driver_Policy 사용
eksctl create **iamserviceaccount** \\
  --name **efs-csi-controller-sa** \\
  --namespace kube-system \\
  --cluster ${CLUSTER_NAME} \\
  --attach-policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/AmazonEKS_EFS_CSI_Driver_Policy \\
  --approve

****# ISRA 확인
kubectl get sa -n kube-system efs-csi-controller-sa -o yaml | head -5
****eksctl get iamserviceaccount --cluster myeks

# EFS Controller 설치
helm repo add aws-efs-csi-driver <https://kubernetes-sigs.github.io/aws-efs-csi-driver/>
helm repo update
helm upgrade -i aws-efs-csi-driver aws-efs-csi-driver/aws-efs-csi-driver \\
    --namespace kube-system \\
    --set image.repository=602401143452.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/eks/aws-efs-csi-driver \\
    --set controller.serviceAccount.create=false \\
    --set controller.serviceAccount.name=efs-csi-controller-sa

# 확인
helm list -n kube-system
kubectl get pod -n kube-system -l "app.kubernetes.io/name=aws-efs-csi-driver,app.kubernetes.io/instance=aws-efs-csi-driver"

LB나 EBS와 마찬가지로 IRSA 셋팅해준다.

이제 efs를 마운트한 파드를 배포해보자.

 

위와같이 EFS가 연결돼있는 PV/PVC를 생성해주고

 

위와같이 파드 2개를 생성해준다.

위와같이 2개의 파드와 맨 처음 해당 실습을 진행했을때 배스천호스트에 마운트해놨던 efs까지 확인할수있다.

 

즉 현재 방금 배포한 2개의 파드와 실습용ec2 인스턴스는 한개의 efs 볼륨을 공유해서 사용하고있는상황
(예전 온프레미스 환경에서 NFS는 실시간 동기화필요할때(업로드 디렉토리처럼) 많이 사용했었음)

 

'job > eks' 카테고리의 다른 글

eks 6주차  (0) 2023.05.31
eks 5주차  (0) 2023.05.23
4주차 eks 스터디  (0) 2023.05.16
eks 2주차  (0) 2023.05.02
eks 교육 1  (0) 2023.04.24

목표

EKS 네트워크의 이해
각각의 노드내 파드에서의 통신(내/외부) 흐름 이해

 

 

 

1. 실습 환경 배포

https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/K8S/eks-oneclick.yaml 을 통해 실습환경구축

Stackname, keyName, Accesskey, secret key 입력

SgIngressSshCidr 은 본인 아이피 입력

나머지는 자동

 

ps.

비용아끼겠다고 t3말고 t2로 하면 1시간도 더 걸린다. 그러니 그냥 t3로 진행할것

 

관리용 ec2 접속

에러는 아직 클라우드 포메이션이 전부 배포가 되지 않았기 때문이다.

클라우드 포메이션으로 생성중

 

배포완료
/root/myeks.yml 파일에서 배포정보를 확인가능

 

# default 네임스페이스 적용 kubectl ns default



# 노드 정보 확인 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

# 노드 보안그룹 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



# 워커 노드 SSH 접속

ssh ec2-user@$N1 hostname

ssh ec2-user@$N2 hostname

ssh ec2-user@$N3 hostname

 

위 작업들을 순서대로 진행하면 N1, N2, N3(노드1,2,3)서버로 접속이 가능해진다.

default name space 적용
노드 정보 확인
노드별로 N1,2,3 에 아이피 지정
노드 보안그룹 ID 확인
설치된 addon들
AWS 웹 콘솔에서도 설치된 에드온 확인이 가능하다.
node1,2,3 의 ssh 접속 및 hostname 확인

여기까지 하면 2주차 실습 준비 완료

 

 

온프레미스 k8s에 가장 많이 사용되는 CNI인 Calico와 AWS EKS에 가장 많이 사용되는 AWS VPC CNI의 차이점은 다음과 같다.

- Calico의 경우 파드와 노드의 대역이 다르지만 AWS VPC CNI는 네트워크 통신 최적화를 위해 파드와 노드의 대역이 같다.

- Calico는 오버레이(인캡슐 디캡슐진행) 통신을 하고 AWS VPC CNI는 동일대역으로 직접 통신

AWS VPC CNI를 구축할때 주의할점은 네트워크 대역을 보통 24비트로 하는경우가 많을텐데(나만 그런가...) AWS VPC CNI의 경우 파드 네트워크와 노드 네트워크가 공유되기때문에 네트워크 대역을 여유롭게 22비트 정도로 주는게 좋다.

위와같이 노드1,3에는 eni~로 가상의 네트워크가 추가돼있는데 이것들이 각각 노드1,3에 추가돼있는 파드의 네트워크 정보이다.

 

t3.medium의 경우 ENI별로 6개의 아이피를 할당받을수있는데 아래와같이 node1,3은 ENI가 2개라 보조 프라이빗 IP까지 총 12개가 할당된것을 볼수있고 node2는 6개가 할당된것을 볼수있다.

위와같이 노드1,3에는 보조 프라이빗 ip주소가 생성돼있는걸 확인할수있는데 노드2에는 파드가 추가돼있지 않아서 기본적으로 할당되는 6개(1개는 프라이빗으로 실제 할당이됐고 나머지5개)만 할당돼있는걸 확인할 수 있다.

 

여기서 replicas 3을 줘서 각각의 노드에 파드를 1개씩 추가로 생성되도록 해보면 결과는 아래와 같다.

보는것처럼 각각의 노드에 ENI가 1개씩 추가된것을 확인할수있다.

그럼 실제 할당된 아이피 갯수는 몇개일까

보는것처럼 노드2는 6개의 아이피가 추가된것을 확인할수있다. 다만 노드1,3은 아까와 동일하다.

그렇다. 파드가 추가(ENI가 생성)된다고 해서 무조건 새로운 아이피가 할당되는게 아니다.

ENI 가 생성되는 프로세스는 다음과같다.

IP POOL에 내용이 없으면 세컨더리 ENI를 생성(방금 노드2번의 경우) 그게 아니라면 기존 IP POOL에서 아이피를 할당하는것이다.

이렇게 IP POOL이 부족하면 새로운 ENI를 생성하는건데 무제한으로 생성되지 않는다.

 

 

 

온프레미스에서는 iptables의 NAT 구성으로 트래픽을 포워딩 해주는데  eks는 하나의 네트워크 대역에 들어가니까 확실히 calico(온프레미스용 CNI)보다 네트워크 구성을 이해하기가 더 좋은거같다. 그렇기 때문에 문제가 발생했을경우 어떤구간에서 문제가 발생했는지 좀더 직관적(동일 네트워크이기에 원인 파악이 쉬움)으로 트러블 슈팅이 가능할것이다.

 

실제로 노드내 파드끼리, 통신을 해보자.

https://github.com/aws/amazon-vpc-cni-k8s/blob/master/docs/cni-proposal.md

 

GitHub - aws/amazon-vpc-cni-k8s: Networking plugin repository for pod networking in Kubernetes using Elastic Network Interfaces

Networking plugin repository for pod networking in Kubernetes using Elastic Network Interfaces on AWS - GitHub - aws/amazon-vpc-cni-k8s: Networking plugin repository for pod networking in Kubernete...

github.com

위와같은 플로우로 진행이 되는데 실제로 실습을 해보고자 한다.

위와같이 파드2에서 ping 하여 tcpdump 해보면 pod1의 아이피로 통신하는것을 확인할수 있다.

 

이번엔 파드에서 외부로 나가는 통신을 확인해보자.

위와같이 파드1에서 google.com 으로 통신을 한 결과이다.

일단 ping이 정상적인거보면 통신은되는데... 172.217.31.132가 실제 구글 아이피는 아니다.

google의 아이피는 172.217.31.132가 아닌데 tcpdump의 결과는 172.217.31.132로 통신을 보내고있다.

그러면 172.217.31.132 에서 또 다른곳으로 NAT를 통해 실제 google로 통신이 되고 있는것이다.

다시 말하자면 파드의 실제 외부아이피(즉 외부 인터넷(구글)과 통신할 아이피)는 사설망 아이피(192나 172.로 시작하는게 아닌)가 아닌 외부 아이피로 통신을 해야한다. 

이건 iptables의 SNAT를 통해 통신이 된다.

iptables 설정은 위와같다.

위와같이 192.168(클러스터 내 파드들의 대역)은 AWS SNAT-CHAIN으로 통신을 하고 그 외 나머지는 192.168.1.190아이피 달고 가라. 그럼 라우팅 설정에 의해 외부(인터넷)으로 통신이 되는것이다.

 

위와같이 각 pod별로 아이피가 할당이되고 통신되는것을 알아보았는데. 파드에 할당되는 아이피는 설정한 대역내 랜덤으로 아이피가 할당된다. 그럼 실제 서비스를 하기위해 파드로의 통신은 어떻게 해야할까.

service 라는 리소스 오브젝트로 VIP를 만들어서 파드로 통신이 가능하다.

서비스 종류는 다음과 같다.

이중 NLB+AWS VPC CNI의 경우 앞단의 NLB에서 파드로 바로 통신이 가능하다. 이것이 가능한 이유는 node의 아이피대역과 파드의 아이피 대역이 같은 AWS VPC CNI의 특징때문이다. 

즉 노드내 iptables나 contrack와 같은 자원을 사용하지 않아 불필요한 자원이 사용되지 않고 통신구간이 줄어드는 장점이 있다.

다만 k8s와 AWS 로드밸런서(NLB)간에 어떠한 통신을하며 k8s 파드가 늘거나 혹은 줄어듬에 따라 NLB에서 대상타깃이 추가/제거가 필요하기 때문이다. 이는 k8s 클러스터내에 존재하는 load balancer controller 파드와 AWS의 서비스인 로드밸런서(NLB)간에 인증(OIDC)절차가 진행/완료되어 파드 IP등 지속적인 정보를 제공해주도록 해야한다.

인증 절차 진행을 위한 작업 IRSA 으로 진행한다.

더보기

IRSA는 AWS에서 제공하는 IAM Role을 Kubernetes Service Account와 연결하는 방법입니다. Kubernetes에서 Pod에서 사용하는 인증 방식 중 Service Account를 사용하는데, 이를 통해 Pod가 AWS 리소스에 접근할 수 있습니다. 하지만 이 때 Pod 내부에서 AWS SDK를 사용해 AWS API를 호출하면, 이 Pod는 AWS 인증 정보를 갖지 않아서 AWS API를 호출할 권한이 없습니다. 이 때 IRSA를 사용하면 Kubernetes Service Account를 IAM Role과 연결하여 Pod에서 AWS 리소스에 접근할 수 있게 됩니다. 이를 통해 보안성을 높일 수 있고, AWS IAM의 역할을 더욱 세분화하여 Pod에게 필요한 권한만 부여할 수 있습니다.

인증 방법은 아래와같다.

# OIDC 확인
aws eks describe-cluster --name $CLUSTER_NAME --query "cluster.identity.oidc.issuer" --output text
aws iam list-open-id-connect-providers | jq

# IAM Policy (AWSLoadBalancerControllerIAMPolicy) 생성
curl -o iam_policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.4.7/docs/install/iam_policy.json
aws iam create-policy --policy-name AWSLoadBalancerControllerIAMPolicy --policy-document file://iam_policy.json

# 혹시 이미 IAM 정책이 있지만 예전 정책일 경우 아래 처럼 최신 업데이트 할 것
# aws iam update-policy ~~~

# 생성된 IAM Policy Arn 확인
aws iam list-policies --scope Local
aws iam get-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy
aws iam get-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --query 'Policy.Arn'

우선 OIDC 를 설정(클라우드 포메이션으로 자동 설정)하면 아래와 같이 EKS 클러스터에서 OIDC 가 설정돼있음을 확인할수있고

 

IAM 폴리시를 생성하면

 

위와같이 IAM 폴리시가 추가된것을 확인할수 있다.

여기까지하면 aws EKS에서는 OIDC를 통해 인증을 진행할 준비가 됐고 IAM 폴리시를 추가하여 EKS 클러스터에서 AWS 로드밸런서를 컨트롤할수있는 권한을 가져올 준비가 끝났다.

 

이제 IRSA를 통해 컨트롤이 가능하도록 구성하면된다.

방법은 아래와 같다.

# AWS Load Balancer Controller를 위한 ServiceAccount를 생성 >> 자동으로 매칭되는 IAM Role 을 CloudFormation 으로 생성됨!
# IAM 역할 생성. AWS Load Balancer Controller의 kube-system 네임스페이스에 aws-load-balancer-controller라는 Kubernetes 서비스 계정을 생성하고 IAM 역할의 이름으로 Kubernetes 서비스 계정에 주석을 답니다
eksctl create iamserviceaccount --cluster=$CLUSTER_NAME --namespace=kube-system --name=aws-load-balancer-controller \
--attach-policy-arn=arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --override-existing-serviceaccounts --approve

## IRSA 정보 확인
eksctl get iamserviceaccount --cluster $CLUSTER_NAME

## 서비스 어카운트 확인
kubectl get serviceaccounts -n kube-system aws-load-balancer-controller -o yaml | yh

eksctl을 통해 서비스 어카운트를 생성하고 이는 클라우드포메이션을 통해 추가로 배포된다.

IRSA 확인

이제 모든 준비가 끝났으니 로드밸런서 컨트롤러를 EKS 클러스터에 헬름차트를 통해 배포하여 사용해보자.

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

이후 로드밸런싱이 어떻게 구성되는지 확인하기 위해 아래와같이 테스트로 서비스와 파드를 배포하면

curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/2/echo-service-nlb.yaml
cat echo-service-nlb.yaml | yh
kubectl apply -f echo-service-nlb.yaml

아래와같이 enpoint가 두개(192.168.2.101, 192.168.3.75)로 로드밸런싱되도록 배포 된것을 확인할수 있다.

여기서 중요한부분은 앞서 말한것처럼 NLB에서 다이렉트로 파드의 아이피로 간다는것이다. 

이것이 가능한이유는 AWS VPC CNI의 장점인 노드아이피와 파드의 아이피가 동일한 대역이라 가능하기 때문이다.

 

실제 AWS 로드밸런서를 확인해보면

위와같이 eks 클러스터에서 AWS 로드밸런서 서비스가 생성된것을 확인할수있다.

이것이 가능한것은 앞서 클러스터에서는 OIDC, AWS에는 IAM 정책을 생성해줬고 이를 IRSA로 설정해줬기 때문이다.

 

실습 완료후 자원 삭제 

aws cloudformation delete-stack --stack-name eksctl-$CLUSTER_NAME-addon-iamserviceaccount-kube-system-aws-load-balancer-controller

 

'job > eks' 카테고리의 다른 글

eks 6주차  (0) 2023.05.31
eks 5주차  (0) 2023.05.23
4주차 eks 스터디  (0) 2023.05.16
3주차 eks 스터디  (0) 2023.05.13
eks 교육 1  (0) 2023.04.24

텔레포트란 ?
Teleport is an open-source tool that provides zero-trust access to servers and cloud applications using SSH, Kubernetes and HTTPS. It eliminates the complexity of setting up VPNs by providing a secure gateway to applications, servers and Kubernetes clusters. It was open-sourced by Gravitational Inc

 

 



시스템엔지니어나 IT담당자. 데브옵스엔지니어등 사내 인프라담당자, 관리자들은 여러 서비스에 접근이 필요하다.

1. 관리하고 있는 온프렘의 수십 수백대의 서버.

2. pgsql, mariadb등 수많은 디비들
3. k8s 
4. 각종 어플리케이션

5. aws등

위와같이 여러 서비스를 관리해야하기에 각각의 로그인 창구가 필요하다. 이를 하나의 창구로 통일시키면 다음과 같은 장점이 생긴다.

1. 편리함 - SSH를통한 서버로의 접속이나 클러스터, 데이터베이스, 리모트데스크톱, 웹 애플리케이션등에 액세스할때 각각의 로그인 창구가 아니라 Teleport 하나의 단일 솔루션으로 로그인 하니까.

2. 보안 향상
2-1) 세션 레코딩
2-2) 제로 트러스트

2-3) 감사 로그

 

 

 

+ Recent posts