카이도스의 Tech Blog

EKS 1주차 - Amzaon EKS 설치 및 기본 사용 본문

EKS

EKS 1주차 - Amzaon EKS 설치 및 기본 사용

카이도스 2023. 4. 26. 13:52
728x90
반응형

CloudNet@-가시다(Gasida)님의 EKS 스터디를 기준으로 작성됩니다.


Amazon EKS 소개 - 참고링크

  • Amazon Elastic Kubernetes Service는 자체 Kubernetes 컨트롤 플레인 또는 노드를 설치, 운영 및 유지 관리할 필요 없이 Kubernetes 실행에 사용할 수 있는 관리형 서비스
  • 여러 AWS 가용 영역에 걸쳐 Kubernetes 컨트롤 플레인을 실행하고 크기를 조정하여 높은 가용성을 보장
  • 컨트롤 플레인은 제어 영역 인스턴스의 크기를 자동으로 조정하고, 비정상 제어 영역 인스턴스를 감지하고 교체하며, 자동화된 버전 업데이트 및 패치를 제공
  • 여러 AWS 서비스와 통합 : 컨테이너 이미지 저장소 Amazon ECR, 로드 분산을 위한 ELB, 인증 IAM, 격리를 위한 Amazon VPC
  • 오픈 소스 Kubernetes 소프트웨어의 최신 버전을 실행하므로 Kubernetes 커뮤니티에서 모든 기존 플러그 인과 도구를 사용할 수 있습니다. 필요한 코드를 수정하지 않고 표준 Kubernetes 애플리케이션을 Amazon EKS로 쉽게 마이그레이션할 수 있습니다.
  • 지원 버전 : 보통 4개의 마이너 버전 지원(현재 1.22~1.26), 평균 3개월마다 새 버전 제공, 각 버전은 12개월 정도 지원 - 링크
    • v1.24.2 → Major.Minor.Patch ⇒ Major(Breaking Changes) . Minor(New Features) . Patch(Bug fixes Security)

  • EKS 아키텍처
    • EKS 컨트롤 플레인 : AWS Managed VPC - 3개 AZ, API NLB, ETCD ELB - 링크

  • EKS 데이터 플레인 : Customer VPC - EKS owned ENI?, 노드 유형(Managed node groups, Self-managed nodes, AWS Fargate) - 링크

  • Managed node groups (관리형 노드 그룹) : 최신 EKS Optimized AMI를 사용 - 링크, AWS에서 AMI 관리, Capacity(On-Demand, Spot) - 링크
  • Self-managed nodes : Custom AMI를 사용, ASG 직접 관리, OS 기본구성/패치를 고객이 직접 관리 - 링크
  • AWS Fargate (서버리스) : 고객은 별도의 EC2관리할 필요 없이, AWS Fargate 환경에서 제공하는 Micro VM을 이용하여 PodVM 할당 - 링크


[심화 내용] 카타 컨테이너 (Kata Container) - 링크

  • 카타 컨테이너란? 
  • 컨테이너 처럼 느껴지게 작동하는 경량 VM으로 HW 를 통한 강력한 workload 격리로 안전한 컨테이너를 제공하는 기술
  • 특징 : 보안(개별적인 전용 kernel), 분리된 (Network I/O Memory) 제공 → 하드웨어 강제격리 제공, VM처럼 성능의 소모 없이 분리된 환경을 제공
  • 지원하는 하이퍼바이저 : qemu, cloud-hypervisor, firecracker, ACRN - 링크

  • EKS Cluster Endpoint - Public : 제어부 → (EKS owned ENI) 워커노드 kubelet, 워커노드 → (퍼블릭 도메인) 제어부, 사용자 kubectl → (퍼블릭 도메인) 제어부


  • EKS Cluster Endpoint - Public Private : 제어부 → (EKS owned ENI) 워커노드 kubelet, 워커노드 → (프라이빗 도메인, EKS owned ENI) 제어부, 사용자 kubectl → (퍼블릭 도메인) 제어부


  • EKS Cluster Endpoint - Private : 제어부 → (EKS owned ENI) 워커노드 kubelet, 워커노드,사용자 kubectl → (프라이빗 도메인, EKS owned ENI) 제어부


  • EKS 배포 방식 : 웹 관리 콘솔, eksctl, IaC(CDK, CloudFormation, Terraform 등)
    • eksctl : EKS 클러스터 구축 및 관리를 하기 위한 오프소스 명령줄 도구 - 링크


직접 처음부터 EKS 배포해보기

 

EKS 스터디 - 1주차 3편 - eksctl로 EKS생성

1. eksctl란? AWS에서 공식으로 지원하는 eks관리 CLI입니다. kubectl처럼 eks를 관리하고 싶으신 분들에게 매우 좋습니다. eksctl의 단점은 eks만 관리합니다. aws다른 리소스를 관리하지 못합니다. 개인적

malwareanalysis.tistory.com

더보기

AWS EKS Workshop에서 배포에 사용하는 테라폼 코드를 사용하지 않는 이유?

⇒ 모든 기능이 전부 활성화되서 배포되어 비용과 시간이 필요하고 오히려 복잡해서 이해에 어려움

AWS EKS Workshop에서 사용하는 Cloud9 IDE를 사용하지 않는 이유?

⇒ 최대한의 비용 절감과 SSH로 접속 후 사용해도 실습에 문제 없음

EKS 배치 시 보통 PrivateSubnetNAT GW를 사용하는데, 스터디 실습에서 사용하지 않는 이유?

⇒ 역시 최대한의 비용 절감을 위함

EKS 배치 시 보통 3개의 Subnet을 사용하는데, 스터디 실습에서는 2개의 Subnet을 사용하는 이유?

⇒ 복잡하지 않게 최대한 간결한 환경에서 실습 진행을 위해

EKS 버전을 v1.24 선정한 이유?

⇒ EKS 지원 add-on호환되고 검증된 애플리케이션이 가장 많은 버전

  • Amazon EKS now supports Kubernetes version 1.24 - 링크

  • 기본 인프라 배포 - 링크 ← AWS CloudFormation 페이지로 연결되며, 파라미터 입력 후 스택 실행

파라미터 : 아래 빨간색 부분은 설정해주는어야 할 것, 그외 부분은 기본값 사용을 권장

  1. <<<<< EKSCTL MY EC2 >>>>>
    1. ClusterBaseName: EKS 클러스터의 기본 이름 (생성되는 리소스들의 주석에 접두어로 활용), EKS 클러스터 이름에 '_(밑줄)' 사용 불가!
    2. KeyName: EC2 접속에 사용하는 SSH 키페어 지정
    3. SgIngressSshCidr: eksctl 작업을 수행할 EC2 인스턴스를 접속할 수 있는 IP 주소 입력 (집 공인IP/32 입력)
    4. MyInstanceType: eksctl 작업을 수행할 EC2 인스턴스의 타입 (기본 t3.medium)
  2. <<<<< Region AZ >>>>> : 리전과 가용영역을 지정
  3. <<<<< VPC Subnet >>>>> : VPC, 서브넷 정보 지정

  • 기본 정보 확인
# (옵션) cloud-init 실행 과정 로그 확인
sudo tail -f /var/log/cloud-init-output.log

# 사용자 확인
sudo su -
whoami

# 기본 툴 및 SSH 키 설치 등 확인
kubectl version --client=true -o yaml | yh
  gitVersion: v1.25.7-eks-a59e1f0

eksctl version
0.138.0

aws --version
aws-cli/2.11.15 Python/3.11.3 Linux/4.14.311-233.529.amzn2.x86_64 exe/x86_64.amzn.2 prompt/off

ls /root/.ssh/id_rsa*

# 도커 엔진 설치 확인
docker info
  • IAM User 자격 증명 설정 및 VPC 확인 및 변수 지정
# 자격 구성 설정 없이 확인
aws ec2 describe-instances

# IAM User 자격 구성 : 실습 편리를 위해 administrator 권한을 가진 IAM User 의 자격 증명 입력
aws configure
AWS Access Key ID [None]: AKIA....
AWS Secret Access Key [None]: SX+....
Default region name [None]: ap-northeast-2
Default output format [None]: json

# 자격 구성 적용 확인 : 노드 IP 확인
aws ec2 describe-instances

# EKS 배포할 VPC 정보 확인
aws ec2 describe-vpcs --filters "Name=tag:Name,Values=$CLUSTER_NAME-VPC" | jq
aws ec2 describe-vpcs --filters "Name=tag:Name,Values=$CLUSTER_NAME-VPC" | jq Vpcs[]
aws ec2 describe-vpcs --filters "Name=tag:Name,Values=$CLUSTER_NAME-VPC" | jq Vpcs[].VpcId
aws ec2 describe-vpcs --filters "Name=tag:Name,Values=$CLUSTER_NAME-VPC" | jq -r .Vpcs[].VpcId
export VPCID=$(aws ec2 describe-vpcs --filters "Name=tag:Name,Values=$CLUSTER_NAME-VPC" | jq -r .Vpcs[].VpcId)
echo "export VPCID=$VPCID" >> /etc/profile
echo $VPCID
vpc-0e569bd7086741cf0

# EKS 배포할 VPC에 속한 Subnet 정보 확인
aws ec2 describe-subnets --filters "Name=vpc-id,Values=$VPCID" --output json | jq
aws ec2 describe-subnets --filters "Name=vpc-id,Values=$VPCID" --output yaml | yh

## 퍼블릭 서브넷 ID 확인
aws ec2 describe-subnets --filters Name=tag:Name,Values="$CLUSTER_NAME-PublicSubnet1" | jq
aws ec2 describe-subnets --filters Name=tag:Name,Values="$CLUSTER_NAME-PublicSubnet1" --query "Subnets[0].[SubnetId]" --output text
export PubSubnet1=$(aws ec2 describe-subnets --filters Name=tag:Name,Values="$CLUSTER_NAME-PublicSubnet1" --query "Subnets[0].[SubnetId]" --output text)
export PubSubnet2=$(aws ec2 describe-subnets --filters Name=tag:Name,Values="$CLUSTER_NAME-PublicSubnet2" --query "Subnets[0].[SubnetId]" --output text)
echo "export PubSubnet1=$PubSubnet1" >> /etc/profile
echo "export PubSubnet2=$PubSubnet2" >> /etc/profile
echo $PubSubnet1
subnet-06bff0d6abad36888
echo $PubSubnet2
subnet-06b74c41eb14d3983

Amazon EKS 배포 실습

# 변수 확인
echo $AWS_DEFAULT_REGION
ap-northeast-2
echo $CLUSTER_NAME
myeks
echo $VPCID
vpc-0e569bd7086741cf0
echo $PubSubnet1,$PubSubnet2
subnet-06bff0d6abad36888,subnet-06b74c41eb14d3983

# 옵션 [터미널1] EC2 생성 모니터링
#while true; do aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,PrivateIPAdd:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output text ; echo "------------------------------" ; sleep 1; done
aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,PrivateIPAdd:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output table

# eks 클러스터 & 관리형노드그룹 배포 전 정보 확인
eksctl create cluster --name $CLUSTER_NAME --region=$AWS_DEFAULT_REGION --nodegroup-name=$CLUSTER_NAME-nodegroup --node-type=t3.medium \
--node-volume-size=30 --vpc-public-subnets "$PubSubnet1,$PubSubnet2" --version 1.24 --ssh-access --external-dns-access --dry-run | yh
...
vpc: 
  autoAllocateIPv6: false
  cidr: 192.168.0.0/16
  clusterEndpoints: 
    privateAccess: false
    publicAccess: true
  id: vpc-0e569bd7086741cf0
  manageSharedNodeSecurityGroupRules: true
  nat: 
    gateway: Disable
  subnets: 
    public: 
      ap-northeast-2a: 
        az: ap-northeast-2a
        cidr: 192.168.1.0/24
        id: subnet-06bff0d6abad36888
      ap-northeast-2c: 
        az: ap-northeast-2c
        cidr: 192.168.2.0/24
        id: subnet-06b74c41eb14d3983


# eks 클러스터 & 관리형노드그룹 배포: 총 16분(13분+3분) 소요 
eksctl create cluster --name $CLUSTER_NAME --region=$AWS_DEFAULT_REGION --nodegroup-name=$CLUSTER_NAME-nodegroup --node-type=t3.medium \
--node-volume-size=30 --vpc-public-subnets "$PubSubnet1,$PubSubnet2" --version 1.24 --ssh-access --external-dns-access --verbose 4
...


  • eks 정보 확인
# krew 플러그인 확인
kubectl krew list
kubectl ctx
kubectl ns
kubectl ns default

# eks 클러스터 정보 확인
kubectl cluster-info
Kubernetes control plane is running at https://CAC19E22B40287952AB9500656027E71.yl4.ap-northeast-2.eks.amazonaws.com
...

eksctl get cluster
aws eks describe-cluster --name $CLUSTER_NAME | jq
aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint
https://CAC19E22B40287952AB9500656027E71.yl4.ap-northeast-2.eks.amazonaws.com

## dig 조회 : 해당 IP 소유 리소스는 어떤것일까요?
dig +short CAC19E22B40287952AB9500656027E71.yl4.ap-northeast-2.eks.amazonaws.com
3.36.168.67
15.165.143.131

# eks API 접속 시도
curl -k -s $(aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint)
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "forbidden: User \"system:anonymous\" cannot get path \"/\"",
  "reason": "Forbidden",
  "details": {},
  "code": 403
}
curl -k -s $(aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint)/version | jq
{
  "major": "1",
  "minor": "24+",
  "gitVersion": "v1.24.12-eks-ec5523e",
  "gitCommit": "393.....",
  "gitTreeState": "clean",
  "buildDate": "2023-03-20T21:30:46Z",
  "goVersion": "go1.19.7",
  "compiler": "gc",
  "platform": "linux/amd64"
}

# eks 노드 그룹 정보 확인
eksctl get nodegroup --cluster $CLUSTER_NAME --name $CLUSTER_NAME-nodegroup
CLUSTER	NODEGROUP	STATUS	CREATED			MIN SIZE	MAX SIZE	DESIRED CAPACITY	INSTANCE TYPE	IMAGE ID	ASG NAME							TYPE
myeks	myeks-nodegroup	ACTIVE	2023-04-28T03:52:03Z	2		2		2			t3.medium	AL2_x86_64	eks-myeks-nodegroup-8ec3e2fe-9d2e-39ea-8121-3b29007ecc5e	managed

aws eks describe-nodegroup --cluster-name $CLUSTER_NAME --nodegroup-name $CLUSTER_NAME-nodegroup | jq

# 노드 정보 확인 : OS와 컨테이너런타임 확인
kubectl describe nodes | grep "node.kubernetes.io/instance-type"
kubectl get node
kubectl get node -owide
kubectl get node -v=6
I0428 13:00:42.331400    4965 loader.go:374] Config loaded from file:  /root/.kube/config
I0428 13:00:43.305778    4965 round_trippers.go:553] GET https://CAC19E22B40287952AB9500656027E71.yl4.ap-northeast-2.eks.amazonaws.com/api/v1/nodes?limit=500 200 OK in 968 milliseconds
....

# 인증 정보 확인 : 자세한 정보는 6주차(보안)에서 다룸
cat /root/.kube/config | yh
aws eks get-token --cluster-name $CLUSTER_NAME --region $AWS_DEFAULT_REGION

# 파드 정보 확인 : 온프레미스 쿠버네티스의 파드 배치와 다른점은? , 파드의 IP의 특징이 어떤가요? 자세한 네트워크는 2주차에서 다룸
kubectl get pod -n kube-system
kubectl get pod -n kube-system -o wide

kubectl get pod -A
NAMESPACE     NAME                      READY   STATUS    RESTARTS   AGE
kube-system   aws-node-2ptf9            1/1     Running   0          8m11s
kube-system   aws-node-z7zl9            1/1     Running   0          8m10s
kube-system   coredns-dc4979556-5wz88   1/1     Running   0          16m
kube-system   coredns-dc4979556-7rqfk   1/1     Running   0          16m
kube-system   kube-proxy-l6nh7          1/1     Running   0          8m10s
kube-system   kube-proxy-vd48h          1/1     Running   0          8m11s

# kube-system 네임스페이스에 모든 리소스 확인
kubectl get-all -n kube-system

# 모든 파드의 컨테이너 이미지 정보 확인
kubectl get pods --all-namespaces -o jsonpath="{.items[*].spec.containers[*].image}" | tr -s '[[:space:]]' '\n' | sort | uniq -c
      2 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/amazon-k8s-cni:v1.11.4-eksbuild.1
      2 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/eks/coredns:v1.8.7-eksbuild.3
      2 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/eks/kube-proxy:v1.24.7-minimal-eksbuild.2

# AWS ECR에서 컨테이너 이미지 가져오기 시도
docker pull 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/eks/coredns:v1.8.7-eksbuild.3

노드 정보 상세 확인

  • 노드 SSH 접속
# 노드 IP 확인 및 PrivateIP 변수 지정
aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,PrivateIPAdd:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output table
------------------------------------------------------------------------------
|                              DescribeInstances                             |
+-----------------------------+----------------+-----------------+-----------+
|        InstanceName         | PrivateIPAdd   |   PublicIPAdd   |  Status   |
+-----------------------------+----------------+-----------------+-----------+
|  myeks-myeks-nodegroup-Node |  192.168.2.58  |  13.125.132.120 |  running  |
|  myeks-host                 |  192.168.1.100 |  3.38.168.8     |  running  |
|  myeks-myeks-nodegroup-Node |  192.168.1.67  |  52.78.137.53   |  running  |
+-----------------------------+----------------+-----------------+-----------+

N1=192.168.2.58
N2=192.168.1.67

# eksctl-host 에서 노드의IP나 coredns 파드IP로 ping 테스트(Ping 테스트 안됨)
ping <IP>
ping -c 2 $N1
ping -c 2 $N2

# 노드 보안그룹 ID 확인
aws ec2 describe-security-groups --filters Name=group-name,Values=*nodegroup* --query "SecurityGroups[*].[GroupId]" --output text
NGSGID=$(aws ec2 describe-security-groups --filters Name=group-name,Values=*nodegroup* --query "SecurityGroups[*].[GroupId]" --output text)
echo $NGSGID
sg-0895bccf05145b817

# 노드 보안그룹에 eksctl-host 에서 노드(파드)에 접속 가능하게 룰(Rule) 추가 설정
aws ec2 authorize-security-group-ingress --group-id $NGSGID --protocol '-1' --cidr 192.168.1.100/32

# eksctl-host 에서 노드의IP나 coredns 파드IP로 ping 테스트(Ping 테스트 정상)
ping -c 2 $N1
ping -c 2 $N2

# 워커 노드 SSH 접속
ssh -i ~/.ssh/id_rsa ec2-user@$N1 hostname
ssh -i ~/.ssh/id_rsa ec2-user@$N2 hostname
ssh -i ~/.ssh/id_rsa ec2-user@$N1 
exit
ssh -i ~/.ssh/id_rsa ec2-user@$N2
exit
  • 노드 네트워크 정보 확인
# AWS VPC CNI 사용 확인
kubectl -n kube-system get ds aws-node
kubectl describe daemonset aws-node --namespace kube-system | grep Image | cut -d "/" -f 2

# 파드 IP 확인
kubectl get pod -n kube-system -o wide
kubectl get pod -n kube-system -l k8s-app=kube-dns -owide
NAME                      READY   STATUS    RESTARTS   AGE   IP              NODE                                              NOMINATED NODE   READINESS GATES
coredns-dc4979556-5wz88   1/1     Running   0          30m   192.168.1.62    ip-192-168-1-67.ap-northeast-2.compute.internal   <none>           <none>
coredns-dc4979556-7rqfk   1/1     Running   0          30m   192.168.1.142   ip-192-168-1-67.ap-northeast-2.compute.internal   <none>           <none>

ssh -i ~/.ssh/id_rsa ec2-user@$N1 sudo ip -c addr
ssh -i ~/.ssh/id_rsa ec2-user@$N2 sudo ip -c addr
ssh -i ~/.ssh/id_rsa ec2-user@$N1 sudo ip -c route
default via 192.168.2.1 dev eth0 
169.254.169.254 dev eth0 
192.168.2.0/24 dev eth0 proto kernel scope link src 192.168.2.58 

ssh -i ~/.ssh/id_rsa ec2-user@$N2 sudo ip -c route
default via 192.168.1.1 dev eth0 
169.254.169.254 dev eth0 
192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.67 
192.168.1.62 dev eni2162d33d3e9 scope link 
192.168.1.142 dev eni6833a4b1a60 scope link 

ssh -i ~/.ssh/id_rsa ec2-user@$N1 sudo iptables -t nat -S
ssh -i ~/.ssh/id_rsa ec2-user@$N2 sudo iptables -t nat -S
  • 노드 프로세스 정보 확인
ssh -i ~/.ssh/id_rsa ec2-user@$N1 sudo systemctl status kubelet
ssh -i ~/.ssh/id_rsa ec2-user@$N1 sudo pstree
ssh -i ~/.ssh/id_rsa ec2-user@$N1 sudo ps afxuwww
ssh -i ~/.ssh/id_rsa ec2-user@$N1 sudo ps axf |grep /usr/bin/containerd
ssh -i ~/.ssh/id_rsa ec2-user@$N1 sudo ls /etc/kubernetes/manifests/

ssh -i ~/.ssh/id_rsa ec2-user@$N2 sudo systemctl status kubelet
ssh -i ~/.ssh/id_rsa ec2-user@$N2 sudo pstree
ssh -i ~/.ssh/id_rsa ec2-user@$N2 sudo ps afxuwww
ssh -i ~/.ssh/id_rsa ec2-user@$N2 sudo ps axf |grep /usr/bin/containerd
ssh -i ~/.ssh/id_rsa ec2-user@$N2 sudo ls /etc/kubernetes/manifests/
  • 노드 스토리지 정보 확인
ssh -i ~/.ssh/id_rsa ec2-user@$N1 lsblk
NAME          MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme0n1       259:0    0  30G  0 disk 
├─nvme0n1p1   259:1    0  30G  0 part /
└─nvme0n1p128 259:2    0   1M  0 part 
ssh -i ~/.ssh/id_rsa ec2-user@$N1 df -hT --type xfs
Filesystem     Type  Size  Used Avail Use% Mounted on
/dev/nvme0n1p1 xfs    30G  2.8G   28G  10% /

ssh -i ~/.ssh/id_rsa ec2-user@$N2 lsblk
ssh -i ~/.ssh/id_rsa ec2-user@$N2 df -hT --type xfs
  • EKS owned ENI 확인

# kubelet, kube-proxy 통신 Peer Address는 어딘인가요?
ssh -i ~/.ssh/id_rsa ec2-user@$N1 sudo ss -tnp
State Recv-Q Send-Q Local Address:Port    Peer Address:Port Process                                                 
ESTAB 0      0       192.168.2.58:36604 15.165.143.131:443   users:(("kubelet",pid=2842,fd=43))                     
ESTAB 0      0       192.168.2.58:46190   52.95.194.61:443   users:(("ssm-agent-worke",pid=2452,fd=13))             
ESTAB 0      0       192.168.2.58:22     192.168.1.100:60376 users:(("sshd",pid=19931,fd=3),("sshd",pid=19899,fd=3))
ESTAB 0      0       192.168.2.58:52610     10.100.0.1:443   users:(("aws-k8s-agent",pid=3351,fd=7))                
ESTAB 0      0       192.168.2.58:47740    3.36.168.67:443   users:(("kube-proxy",pid=3093,fd=11))                  
ESTAB 0      0       192.168.2.58:35738   52.95.195.99:443   users:(("ssm-agent-worke",pid=2452,fd=16))    

ssh -i ~/.ssh/id_rsa ec2-user@$N2 sudo ss -tnp
State Recv-Q Send-Q Local Address:Port    Peer Address:Port Process                                                 
ESTAB 0      0       192.168.1.67:59290     10.100.0.1:443   users:(("aws-k8s-agent",pid=3344,fd=7))                
ESTAB 0      0       192.168.1.67:56580  52.95.195.121:443   users:(("ssm-agent-worke",pid=2440,fd=15))             
ESTAB 0      0       192.168.1.67:22     192.168.1.100:46630 users:(("sshd",pid=12577,fd=3),("sshd",pid=12545,fd=3))
ESTAB 0      0       192.168.1.67:40340 15.165.143.131:443   users:(("kubelet",pid=2842,fd=44))                     
ESTAB 0      0       192.168.1.67:36810   52.95.194.61:443   users:(("ssm-agent-worke",pid=2440,fd=10))             
ESTAB 0      0       192.168.1.67:51806    3.36.168.67:443   users:(("kube-proxy",pid=3090,fd=11))     

# [터미널] aws-node 데몬셋 파드 1곳에 bash 실행해두기 
kubectl exec daemonsets/aws-node -it -n kube-system -c aws-node -- bash

# exec 실행으로 추가된 연결 정보의 Peer Address는 어딘인가요? >> AWS 네트워크 인터페이스 ENI에서 해당 IP 정보 확인
ssh -i ~/.ssh/id_rsa ec2-user@$N1 sudo ss -tnp
State Recv-Q Send-Q Local Address:Port    Peer Address:Port Process                                                 
ESTAB 0      0       192.168.2.58:36604 15.165.143.131:443   users:(("kubelet",pid=2842,fd=43))                     
ESTAB 0      0       192.168.2.58:52610     10.100.0.1:443   users:(("aws-k8s-agent",pid=3351,fd=7))                
ESTAB 0      0       192.168.2.58:55818   52.95.194.65:443   users:(("ssm-agent-worke",pid=2452,fd=13))             
ESTAB 0      0       192.168.2.58:47740    3.36.168.67:443   users:(("kube-proxy",pid=3093,fd=11))                  
ESTAB 0      0       192.168.2.58:22     192.168.1.100:59390 users:(("sshd",pid=20706,fd=3),("sshd",pid=20651,fd=3))
ESTAB 0      0       192.168.2.58:35738   52.95.195.99:443   users:(("ssm-agent-worke",pid=2452,fd=16))    

ssh -i ~/.ssh/id_rsa ec2-user@$N2 sudo ss -tnp
State Recv-Q Send-Q         Local Address:Port           Peer Address:Port Process                                                 
ESTAB 0      0               192.168.1.67:59290            10.100.0.1:443   users:(("aws-k8s-agent",pid=3344,fd=7))                
ESTAB 0      0               192.168.1.67:56580         52.95.195.121:443   users:(("ssm-agent-worke",pid=2440,fd=15))             
ESTAB 0      0                  127.0.0.1:36044             127.0.0.1:37965 users:(("kubelet",pid=2842,fd=17))                     
ESTAB 0      0               192.168.1.67:40340        15.165.143.131:443   users:(("kubelet",pid=2842,fd=44))                     
ESTAB 0      0                  127.0.0.1:37965             127.0.0.1:36044 users:(("containerd",pid=2729,fd=51))                  
ESTAB 0      56              192.168.1.67:22            192.168.1.100:51564 users:(("sshd",pid=13442,fd=3),("sshd",pid=13410,fd=3))
ESTAB 0      0               192.168.1.67:55576          52.95.194.54:443   users:(("ssm-agent-worke",pid=2440,fd=10))             
ESTAB 0      0               192.168.1.67:51806           3.36.168.67:443   users:(("kube-proxy",pid=3090,fd=11))                  
ESTAB 0      0      [::ffff:192.168.1.67]:10250 [::ffff:192.168.1.53]:33564 users:(("kubelet",pid=2842,fd=7))

  • EKS owned ENI : 관리형 노드 그룹의 워커 노드는 내 소유지만, 연결된 ENI(NIC)의 인스턴스(관리형 노드)는 AWS 소유이다

  • EC2 메타데이터 확인(IAM Role) : 상세한 내용은 보안에서 다룸 - 링크
ssh -i ~/.ssh/id_rsa ec2-user@$N1 curl -s http://169.254.169.254/latest/
ssh -i ~/.ssh/id_rsa ec2-user@$N1 curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/
ssh -i ~/.ssh/id_rsa ec2-user@$N1 curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/eksctl-myeks-nodegroup-myeks-node-NodeInstanceRole-34TI58O9ISKO | jq
{
  "Code": "Success",
  "LastUpdated": "2023-04-28T04:40:30Z",
  "Type": "AWS-HMAC",
  "AccessKeyId": "ASIATAXWBCFMPLTYSMZS",
  "SecretAccessKey": "kGHL46D++9q3M+CvjUXxa6FV0zh3M9BFhWDGlUZU",
  "Token": "IQoJb.....",
  "Expiration": "2023-04-28T10:51:49Z"
}

ssh -i ~/.ssh/id_rsa ec2-user@$N2 curl -s http://169.254.169.254/latest/
ssh -i ~/.ssh/id_rsa ec2-user@$N2 curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/
ssh -i ~/.ssh/id_rsa ec2-user@$N2 curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/eksctl-myeks-nodegroup-myeks-node-NodeInstanceRole-34TI58O9ISKO | jq
{
  "Code": "Success",
  "LastUpdated": "2023-04-28T04:30:37Z",
  "Type": "AWS-HMAC",
  "AccessKeyId": "ASIATAXWBCFMFP233DM3",
  "SecretAccessKey": "lpeIbLumlVwLUXDHjNS7UkDBcwcPJphNV66zu8A5",
  "Token": "IQoJb3JpZ2luX2VjEE..=",
  "Expiration": "2023-04-28T10:37:35Z"
}

# 보안그룹 ID와 보안그룹 이름(Name아님을 주의!) 확인
aws ec2 describe-security-groups --query 'SecurityGroups[*].[GroupId, GroupName]' --output text
sg-04eb6c3fdbc07ca60	eks-cluster-sg-myeks-104368993
sg-07b2f7abf09f8052f	myeks-EKSEC2SG-7RDQNNAWUWOW
sg-030816612b3cb564d	my-test
sg-02ff741d66bfe6ab7	default
sg-01666f708a89150a7	eksctl-myeks-cluster-ClusterSharedNodeSecurityGroup-A67EGJDE1Z9R
sg-0895bccf05145b817	eksctl-myeks-nodegroup-myeks-nodegroup-remoteAccess
sg-0cc6a910ce75e83b5	eksctl-myeks-cluster-ControlPlaneSecurityGroup-TOCBU851NR30
sg-0e9cabc97accb4f7f	default

# 보안그룹 확인
aws ec2 describe-security-groups --group-ids sg-04eb6c3fdbc07ca60 --output yaml | yh
aws ec2 describe-security-groups --group-ids sg-07b2f7abf09f8052f --output yaml | yh
aws ec2 describe-security-groups --group-ids sg-01666f708a89150a7--output yaml | yh
aws ec2 describe-security-groups --group-ids sg-0895bccf05145b817 --output yaml | yh

기본사용

선언형 (멱등성) 알아보기 실습

# 터미널1 (모니터링)
watch -d 'kubectl get pod'
Every 2.0s: kubectl get pod                                                                                   Fri Apr 28 14:02:12 2023

NAME                     READY   STATUS    RESTARTS   AGE
my-webs-8dd6b4db-2xzr4   1/1     Running   0          46s
my-webs-8dd6b4db-7c2rd   1/1     Running   0          46s
my-webs-8dd6b4db-tpvzd   1/1     Running   0          46s

# 터미널2
# Deployment 배포(Pod 3개)
kubectl create deployment my-webs --image=gcr.io/google-samples/kubernetes-bootcamp:v1 --replicas=3
kubectl get pod -w
NAME                     READY   STATUS              RESTARTS   AGE
my-webs-8dd6b4db-2xzr4   0/1     ContainerCreating   0          7s
my-webs-8dd6b4db-7c2rd   0/1     ContainerCreating   0          7s
my-webs-8dd6b4db-tpvzd   0/1     ContainerCreating   0          7s
my-webs-8dd6b4db-2xzr4   1/1     Running             0          9s
my-webs-8dd6b4db-7c2rd   1/1     Running             0          10s
my-webs-8dd6b4db-tpvzd   1/1     Running             0          12s

# 파드 증가 및 감소
kubectl scale deployment my-webs --replicas=6 && kubectl get pod -w
kubectl scale deployment my-webs --replicas=3
kubectl get pod

# 강제로 파드 삭제 : 바라는상태 + 선언형에 대한 대략적인 확인! ⇒ 어떤 일이 벌어지는가? 
kubectl delete pod --all && kubectl get pod -w
pod "my-webs-8dd6b4db-2xzr4" deleted
pod "my-webs-8dd6b4db-7c2rd" deleted
pod "my-webs-8dd6b4db-tpvzd" deleted

kubectl get pod
NAME                     READY   STATUS        RESTARTS   AGE
my-webs-8dd6b4db-2xzr4   1/1     Terminating   0          2m58s
my-webs-8dd6b4db-6nlrf   1/1     Running       0          21s
my-webs-8dd6b4db-7c2rd   1/1     Terminating   0          2m58s
my-webs-8dd6b4db-d27dl   1/1     Running       0          21s
my-webs-8dd6b4db-tpvzd   1/1     Terminating   0          2m58s
my-webs-8dd6b4db-z9qdg   1/1     Running       0          21s

# 실습 완료 후 Deployment 삭제
kubectl delete deploy my-webs

*--replicas=3 옵션을 넣었기때문에 delete를 실행해도 바로 3개가 생성되서 항상 3개를 유지한다.


서비스/파드(mario 게임) 배포 테스트 with CLB

# 터미널1 (모니터링)
watch -d 'kubectl get pod,svc'

# 수퍼마리오 디플로이먼트 배포
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/1/mario.yaml
kubectl apply -f mario.yaml
cat mario.yaml | yh
apiVersion: apps/v1
kind: Deployment
metadata: 
  name: mario
  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
spec: 
  selector: 
    app: mario
  ports: 
  - port: 80
    protocol: TCP
    targetPort: 8080
  type: LoadBalancer

# 배포 확인 : CLB 배포 확인
kubectl get deploy,svc,ep mario

# 마리오 게임 접속 : CLB 주소로 웹 접속
kubectl get svc mario -o jsonpath={.status.loadBalancer.ingress[0].hostname} | awk '{ print "Maria URL = http://"$1 }'
Maria URL = http://a38afb464d3cc41d5a9728a707b08f3f-307106267.ap-northeast-2.elb.amazonaws.com

  • AWS EKS 관리 콘솔에서 리소스 확인(파드, 서비스) → AWS EC2 ELB(CLB) 확인
  • 삭제 : kubectl delete -f mario.yaml

노드에 배포된 컨테이너 정보 확인 Containerd clients 3종 : ctr, nerdctl, crictl - 링크

# ctr 버전 확인
ssh -i ~/.ssh/id_rsa ec2-user@$N1 ctr --version
ctr github.com/containerd/containerd v1.6.19

# ctr help
ssh -i ~/.ssh/id_rsa ec2-user@$N1 ctr
NAME:
   ctr -
        __
  _____/ /______
 / ___/ __/ ___/
/ /__/ /_/ /
\___/\__/_/

containerd CLI
...

DESCRIPTION:
ctr is an unsupported debug and administrative client for interacting with the containerd daemon.
Because it is unsupported, the commands, options, and operations are not guaranteed to be backward compatible or stable from release to release of the containerd project.

COMMANDS:
   plugins, plugin            provides information about containerd plugins
   version                    print the client and server versions
   containers, c, container   manage containers
   content                    manage content
   events, event              display containerd events
   images, image, i           manage images
   leases                     manage leases
   namespaces, namespace, ns  manage namespaces
   pprof                      provide golang pprof outputs for containerd
   run                        run a container
   snapshots, snapshot        manage snapshots
   tasks, t, task             manage tasks
   install                    install a new package
   oci                        OCI tools
   shim                       interact with a shim directly
   help, h                    Shows a list of commands or help for one command

# 네임스페이스 확인
ssh -i ~/.ssh/id_rsa ec2-user@$N1 sudo ctr ns list
NAME   LABELS
k8s.io

# 컨테이너 리스트 확인
ssh -i ~/.ssh/id_rsa ec2-user@$N1 sudo ctr -n k8s.io container list
CONTAINER                                                           IMAGE                                                                                          RUNTIME                  
1b95bc2f8c2e7048079dc6761ff166da117398929841ba9f81e63e56c8cd0dc0    602401143452.dkr.ecr-fips.us-east-1.amazonaws.com/amazon-k8s-cni-init:v1.11.4                  io.containerd.runc.v2    
2733b5cf90b85e922d51af6d00fcbdd1e61ae4a132fb22e4f0694a516aa0c1a1    602401143452.dkr.ecr-fips.us-east-1.amazonaws.com/amazon-k8s-cni:v1.11.4                       io.containerd.runc.v2    
....

# 컨테이너 이미지 확인
ssh -i ~/.ssh/id_rsa ec2-user@$N1 sudo ctr -n k8s.io image list --quiet
...

# 태스크 리스트 확인
ssh -i ~/.ssh/id_rsa ec2-user@$N1 sudo ctr -n k8s.io task list
TASK                                                                PID     STATUS    
2733b5cf90b85e922d51af6d00fcbdd1e61ae4a132fb22e4f0694a516aa0c1a1    3333    RUNNING
2944ea5e798f9236c1c4e51354e23e45b76b3ac8f514e5ce5eea990361e217cf    3023    RUNNING
7dcad65e55644565671787601599c7a665fe09b148390b4f0f6ea85253e86e1a    3093    RUNNING
ce42aaf6a68f39c62698e2aa38306de56293564efed88476a0b3479c22fd06f3    3022    RUNNING

## 예시) 각 테스크의 PID(5923) 확인
ssh -i ~/.ssh/id_rsa ec2-user@$N1 sudo ps -c 3093
PID CLS PRI TTY      STAT   TIME COMMAND
3099 TS   19 ?       Ssl    0:01 kube-proxy --v=2 --config=/var/lib/kube-proxy-config/config --hostname-override=ip-192-168-1-229.ap-northeast-2.compute.internal

ECR 퍼블릭 Repository 사용 : 퍼블릭 Repo 는 설정 시 us-east-1 를 사용 - 링크

# 퍼블릭 ECR 인증
aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws
cat /root/.docker/config.json | jq
{
  "auths": {
    "public.ecr.aws": {
      "auth": "QVdTOmV5Sn.....=="
    }
  }
}

# 퍼블릭 Repo 기본 정보 확인
aws ecr-public describe-registries --region us-east-1 | jq

# 퍼블릭 Repo 생성
NICKNAME=<각자자신의닉네임>
NICKNAME=pjh
aws ecr-public create-repository --repository-name $NICKNAME/nginx --region us-east-1

# 생성된 퍼블릭 Repo 확인
aws ecr-public describe-repositories --region us-east-1 | jq
REPOURI=$(aws ecr-public describe-repositories --region us-east-1 | jq -r .repositories[].repositoryUri)
echo $REPOURI
public.ecr.aws/d6o3g6v4/pjh/nginx

# 이미지 태그
docker pull nginx:alpine
docker images
docker tag nginx:alpine $REPOURI:latest
docker images
REPOSITORY                          TAG       IMAGE ID       CREATED       SIZE
nginx                               alpine    8e75cbc5b25c   4 weeks ago   41MB
public.ecr.aws/d6o3g6v4/pjh/nginx   latest    8e75cbc5b25c   4 weeks ago   41MB

# 이미지 업로드
docker push $REPOURI:latest

# 파드 실행
kubectl run mynginx --image $REPOURI
kubectl get pod
NAME      READY   STATUS    RESTARTS   AGE
mynginx   1/1     Running   0          16s

kubectl delete pod mynginx

# 퍼블릭 이미지 삭제
aws ecr-public batch-delete-image \
      --repository-name $NICKNAME/nginx \
      --image-ids imageTag=latest \
      --region us-east-1

# 퍼블릭 Repo 삭제
aws ecr-public delete-repository --repository-name $NICKNAME/nginx --force --region us-east-1

관리형노드에 노드 추가 및 삭제 Scale - 링크

# 옵션 [터미널1] EC2 생성 모니터링
#aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,PrivateIPAdd:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output table
while true; do aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,PrivateIPAdd:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output text ; echo "------------------------------" ; sleep 1; done

# eks 노드 그룹 정보 확인
eksctl get nodegroup --cluster $CLUSTER_NAME --name $CLUSTER_NAME-nodegroup

# 노드 2개 → 3개 증가
eksctl scale nodegroup --cluster $CLUSTER_NAME --name $CLUSTER_NAME-nodegroup --nodes 3 --nodes-min 3 --nodes-max 6

myeks-myeks-nodegroup-Node	192.168.2.58	13.125.132.120	running
myeks-host	192.168.1.100	3.38.168.8	running
myeks-myeks-nodegroup-Node	192.168.1.67	52.78.137.53	running
------------------------------
myeks-myeks-nodegroup-Node	192.168.2.58	13.125.132.120	running
myeks-myeks-nodegroup-Node	192.168.2.183	43.200.175.60	running
myeks-host	192.168.1.100	3.38.168.8	running
myeks-myeks-nodegroup-Node	192.168.1.67	52.78.137.53	running

# 노드 확인
kubectl get nodes -o wide
NAME                                               STATUS   ROLES    AGE    VERSION                INTERNAL-IP     EXTERNAL-IP      OS-IMAGE         KERNEL-VERSION                  CONTAINER-RUNTIME
ip-192-168-1-67.ap-northeast-2.compute.internal    Ready    <none>   101m   v1.24.11-eks-a59e1f0   192.168.1.67    52.78.137.53     Amazon Linux 2   5.10.176-157.645.amzn2.x86_64   containerd://1.6.19
ip-192-168-2-183.ap-northeast-2.compute.internal   Ready    <none>   28s    v1.24.11-eks-a59e1f0   192.168.2.183   43.200.175.60    Amazon Linux 2   5.10.176-157.645.amzn2.x86_64   containerd://1.6.19
ip-192-168-2-58.ap-northeast-2.compute.internal    Ready    <none>   101m   v1.24.11-eks-a59e1f0   192.168.2.58    13.125.132.120   Amazon Linux 2   5.10.176-157.645.amzn2.x86_64   containerd://1.6.19

kubectl get nodes -l eks.amazonaws.com/nodegroup=$CLUSTER_NAME-nodegroup
NAME                                               STATUS   ROLES    AGE    VERSION
ip-192-168-1-67.ap-northeast-2.compute.internal    Ready    <none>   101m   v1.24.11-eks-a59e1f0
ip-192-168-2-183.ap-northeast-2.compute.internal   Ready    <none>   35s    v1.24.11-eks-a59e1f0
ip-192-168-2-58.ap-northeast-2.compute.internal    Ready    <none>   101m   v1.24.11-eks-a59e1f0

# 노드 3개 → 2개 감소 : 적용까지 시간이 소요됨
aws eks update-nodegroup-config --cluster-name $CLUSTER_NAME --nodegroup-name $CLUSTER_NAME-nodegroup --scaling-config minSize=2,maxSize=2,desiredSize=2
myeks-myeks-nodegroup-Node	192.168.2.58	13.125.132.120	running
myeks-myeks-nodegroup-Node	192.168.2.183	43.200.175.60	running
myeks-host	192.168.1.100	3.38.168.8	running
myeks-myeks-nodegroup-Node	192.168.1.67	52.78.137.53	running
------------------------------
myeks-myeks-nodegroup-Node	192.168.2.183	43.200.175.60	running
myeks-host	192.168.1.100	3.38.168.8	running
myeks-myeks-nodegroup-Node	192.168.1.67	52.78.137.53	running

kubectl get nodes -o wide
NAME                                               STATUS   ROLES    AGE     VERSION                INTERNAL-IP     EXTERNAL-IP     OS-IMAGE         KERNEL-VERSION                  CONTAINER-RUNTIME
ip-192-168-1-67.ap-northeast-2.compute.internal    Ready    <none>   104m    v1.24.11-eks-a59e1f0   192.168.1.67    52.78.137.53    Amazon Linux 2   5.10.176-157.645.amzn2.x86_64   containerd://1.6.19
ip-192-168-2-183.ap-northeast-2.compute.internal   Ready    <none>   3m42s   v1.24.11-eks-a59e1f0   192.168.2.183   43.200.175.60   Amazon Linux 2   5.10.176-157.645.amzn2.x86_64   containerd://1.6.19

kubectl get nodes -l eks.amazonaws.com/nodegroup=$CLUSTER_NAME-nodegroup
NAME                                               STATUS   ROLES    AGE     VERSION
ip-192-168-1-67.ap-northeast-2.compute.internal    Ready    <none>   104m    v1.24.11-eks-a59e1f0
ip-192-168-2-183.ap-northeast-2.compute.internal   Ready    <none>   3m23s   v1.24.11-eks-a59e1f0

(심화) Managing etcd database size on Amazon EKS clusters - 링크

# monitor the metric etcd_db_total_size_in_bytes to track the etcd database size
kubectl get --raw /metrics | grep "etcd_db_total_size_in_bytes"
# HELP etcd_db_total_size_in_bytes [ALPHA] Total size of the etcd database file physically allocated in bytes.
# TYPE etcd_db_total_size_in_bytes gauge
etcd_db_total_size_in_bytes{endpoint="http://10.0.160.16:2379"} 2.613248e+06
etcd_db_total_size_in_bytes{endpoint="http://10.0.32.16:2379"} 2.646016e+06
etcd_db_total_size_in_bytes{endpoint="http://10.0.96.16:2379"} 2.650112e+06

# How do I identify what is consuming etcd database space?
kubectl get --raw=/metrics | grep apiserver_storage_objects |awk '$2>10' |sort -g -k 2
# HELP apiserver_storage_objects [STABLE] Number of stored objects at the time of last check split by kind.
# TYPE apiserver_storage_objects gauge
apiserver_storage_objects{resource="flowschemas.flowcontrol.apiserver.k8s.io"} 13
apiserver_storage_objects{resource="roles.rbac.authorization.k8s.io"} 15
apiserver_storage_objects{resource="rolebindings.rbac.authorization.k8s.io"} 16
apiserver_storage_objects{resource="apiservices.apiregistration.k8s.io"} 31
apiserver_storage_objects{resource="serviceaccounts"} 40
apiserver_storage_objects{resource="clusterrolebindings.rbac.authorization.k8s.io"} 67
apiserver_storage_objects{resource="clusterroles.rbac.authorization.k8s.io"} 81
apiserver_storage_objects{resource="events"} 108

(실습 완료 후) 자원 삭제

 🚨 실습 완료 후 반드시 실습 리소스를 삭제해주시기 바랍니다. 인스턴스 비용 발생을 최소화하기 위함입니다.
  • Amazon EKS 클러스터 삭제(10분 정도 소요): eksctl delete cluster --name $CLUSTER_NAME
  • (클러스터 삭제 완료 확인 후) AWS CloudFormation 스택 삭제 : aws cloudformation delete-stack --stack-name myeks
728x90
반응형

'EKS' 카테고리의 다른 글

EKS CloudFormation  (0) 2024.03.03
5주차 - EKS Autoscaling  (0) 2023.05.30
EKS 4주차 - EKS Observability  (0) 2023.05.16
EKS 3주차 - EKS Storage & Node 관리  (0) 2023.05.12
EKS 2주차 - EKS Networking  (0) 2023.05.09
Comments