카이도스의 Tech Blog
EKS 1주차 - Amzaon EKS 설치 및 기본 사용 본문
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을 이용하여 Pod 별 VM 할당 - 링크
[심화 내용] 카타 컨테이너 (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 배포해보기
AWS EKS Workshop에서 배포에 사용하는 테라폼 코드를 사용하지 않는 이유?
⇒ 모든 기능이 전부 활성화되서 배포되어 비용과 시간이 필요하고 오히려 복잡해서 이해에 어려움
AWS EKS Workshop에서 사용하는 Cloud9 IDE를 사용하지 않는 이유?
⇒ 최대한의 비용 절감과 SSH로 접속 후 사용해도 실습에 문제 없음
EKS 배치 시 보통 PrivateSubnet에 NAT GW를 사용하는데, 스터디 실습에서 사용하지 않는 이유?
⇒ 역시 최대한의 비용 절감을 위함
EKS 배치 시 보통 3개의 Subnet을 사용하는데, 스터디 실습에서는 2개의 Subnet을 사용하는 이유?
⇒ 복잡하지 않게 최대한 간결한 환경에서 실습 진행을 위해
EKS 버전을 v1.24 선정한 이유?
⇒ EKS 지원 add-on 및 호환되고 검증된 애플리케이션이 가장 많은 버전
- Amazon EKS now supports Kubernetes version 1.24 - 링크
- 기본 인프라 배포 - 링크 ← AWS CloudFormation 페이지로 연결되며, 파라미터 입력 후 스택 실행
파라미터 : 아래 빨간색 부분은 설정해주는어야 할 것, 그외 부분은 기본값 사용을 권장
- <<<<< EKSCTL MY EC2 >>>>>
- ClusterBaseName: EKS 클러스터의 기본 이름 (생성되는 리소스들의 주석에 접두어로 활용), EKS 클러스터 이름에 '_(밑줄)' 사용 불가!
- KeyName: EC2 접속에 사용하는 SSH 키페어 지정
- SgIngressSshCidr: eksctl 작업을 수행할 EC2 인스턴스를 접속할 수 있는 IP 주소 입력 (집 공인IP/32 입력)
- MyInstanceType: eksctl 작업을 수행할 EC2 인스턴스의 타입 (기본 t3.medium)
- <<<<< Region AZ >>>>> : 리전과 가용영역을 지정
- <<<<< 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
'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 |