Bastion Host 배포
현재 참여하고 있는 스터디에서 제공해 주는 CloudFormation Yaml 파일을 이용해 Bastion Host를 배포하고 Bastion Host에서 EKS 생성 실습을 진행한다.
키 페어가 없는 경우 먼저 키 페어를 생성한 후 지정해야한다.
# Bastion Host 배포 yaml 파일 다운로드
curl -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/K8S/myeks-1week.yaml
# 배포
aws cloudformation deploy --template-file ./myeks-1week.yaml --stack-name myeks --parameter-overrides KeyName={MY_KEY_PAIR} SgIngressSshCidr={MY_PUBLIC_IP}/32 --region ap-northeast-2
생성이 잘 됐다면 EC2 공인 IP가 출력된다.
# CloudFormation 스택 배포 완료 후 EC2 IP 출력
aws cloudformation describe-stacks --stack-name myeks --query 'Stacks[*].Outputs[*].OutputValue' --output text
Bastion Host 확인
# 배포된 Bastion Host 접속
ssh root@$(aws cloudformation describe-stacks --stack-name myeks --query 'Stacks[*].Outputs[0].OutputValue' --output text)
Clout-init을 통해 Bastion Host에서 EKS 실습을 바로 진행할 수 있도록 기본 툴과 SSH 키를 설치하도록 돼있다.
# Install aws cli v2
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip >/dev/null 2>&1
./aws/install
complete -C '/usr/local/bin/aws_completer' aws
echo 'export AWS_PAGER=""' >>/etc/profile
export AWS_DEFAULT_REGION=${AWS::Region}
echo "export AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION" >> /etc/profile
# Install krew
curl -L https://github.com/kubernetes-sigs/krew/releases/download/v0.4.4/krew-linux_amd64.tar.gz -o /root/krew-linux_amd64.tar.gz
tar zxvf krew-linux_amd64.tar.gz
./krew-linux_amd64 install krew
export PATH="$PATH:/root/.krew/bin"
echo 'export PATH="$PATH:/root/.krew/bin"' >> /etc/profile
# Install kube-ps1
echo 'source <(kubectl completion bash)' >> /etc/profile
echo 'alias k=kubectl' >> /etc/profile
echo 'complete -F __start_kubectl k' >> /etc/profile
git clone https://github.com/jonmosco/kube-ps1.git /root/kube-ps1
cat <<"EOT" >> /root/.bash_profile
source /root/kube-ps1/kube-ps1.sh
KUBE_PS1_SYMBOL_ENABLE=false
function get_cluster_short() {
echo "$1" | cut -d . -f1
}
KUBE_PS1_CLUSTER_FUNCTION=get_cluster_short
KUBE_PS1_SUFFIX=') '
PS1='$(kube_ps1)'$PS1
EOT
# CLUSTER_NAME
export CLUSTER_NAME=${ClusterBaseName}
echo "export CLUSTER_NAME=$CLUSTER_NAME" >> /etc/profile
# Create SSH Keypair
ssh-keygen -t rsa -N "" -f /root/.ssh/id_rsa
# Install krew plugin
kubectl krew install ctx ns get-all neat # ktop df-pv mtail tree
# Install Docker
amazon-linux-extras install docker -y
systemctl start docker && systemctl enable docker
# Install Kubecolor
wget https://github.com/kubecolor/kubecolor/releases/download/v0.5.0/kubecolor_0.5.0_linux_amd64.tar.gz
tar -zxvf kubecolor_0.5.0_linux_amd64.tar.gz
mv kubecolor /usr/local/bin/
# 기본 툴 및 SSH 키 설치 확인
kubectl version --client=true -o yaml
eksctl version
aws --version
ls /root/.ssh/id_rsa*
# 도커 엔진 설치 확인
docker info
EKS 생성을 위해서는 관련 권한을 가진 IAM User 자격 증명 설정을 해줘야 한다.
# 자격 구성 설정 전 확인
aws ec2 describe-instances
# IAM User 자격 증명 설정
aws configure
AWS Access Key ID [None]: {MY_ACCESS_KEY}
AWS Secret Access Key [None]: {MY_SECRET_ACCESS_KEY}
Default region name [None]: ap-northeast-2
Default output format [None]: json
EKS를 생성하기 위해 VPC 정보를 확인하고 환경 변수로 설정한다.
# EKS 배포할 VPC ID 확인
aws ec2 describe-vpcs --filters "Name=tag:Name,Values=$CLUSTER_NAME-VPC" | jq -r .Vpcs[].VpcId
# VPC ID 환경 변수 설정
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
# EKS 배포할 VPC 내부 Subnet 확인
aws ec2 describe-subnets --filters "Name=vpc-id,Values=$VPCID" --output json | jq
# Subnet ID 환경 변수 설정
aws ec2 describe-subnets --filters Name=tag:Name,Values="$CLUSTER_NAME-PublicSubnet1" --query "Subnets[0].[SubnetId]" --output text
aws ec2 describe-subnets --filters Name=tag:Name,Values="$CLUSTER_NAME-PublicSubnet2" --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 $PubSubnet1
echo $PubSubnet2
echo "export PubSubnet1=$PubSubnet1" >> /etc/profile
echo "export PubSubnet2=$PubSubnet2" >> /etc/profile
환경 변수가 잘 설정됐는지 최종적으로 확인해 보고 eksctl을 사용해 EKS를 생성해 보자.
# 환경 변수 확인
echo $AWS_DEFAULT_REGION
echo $CLUSTER_NAME
echo $VPCID
echo $PubSubnet1,$PubSubnet2
# EKS 클러스터, 관리형 노드 그룹 배포 전 dry-run으로 확인
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.31 --ssh-access --external-dns-access --dry-run | yh
# 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.31 --ssh-access --external-dns-access --verbose 4
*yh는 yaml-highlight의 약어
eksctl을 통해 EKS를 생성하게 되면 CloudFormation 스택을 통해 생성이 이루어진다.
EKS 클러스터가 잘 생성됐다.
EKS 노드 그룹에 의해 Auto Scaling Group, EC2 인스턴스가 생성된다.
EKS 확인
EKS Cluster 확인
EKS가 잘 생성됐으므로 설치된 플러그인과 클러스터의 정보를 살펴보자.
# krew 플러그인 확인
kubectl krew list
- ctx : k8s 컨텍스트를 쉽게 전환하는 도구. Multi Cluster나 NameSpace를 다룰 때 유용, kubectl config use-context 명령어 대신 사용
- get-all : kubectl get 명령어를 확장해 네임스페이스 내 모든 리소스 한 번에 조회
- neat : kubectl 명령어에서 불필요한 정보를 제거해서 깔끔하고 읽기 쉽게 출력하는 도구
- ns : 네임스페이스를 관리하는 도구
# eks 클러스터 정보 확인
kubectl cluster-info
eksctl get cluster
# eks 클러스터 describe
aws eks describe-cluster --name $CLUSTER_NAME | jq
# eks 클러스터 엔드포인트 확인
aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint
현재 EKS cluster API 서버 엔드포인트가 퍼블릭 액세스 설정이므로 외부에서도 접근이 가능하다.
EKS Node Group 확인
# eks 노드 그룹 정보 확인
eksctl get nodegroup --cluster $CLUSTER_NAME --name $CLUSTER_NAME-nodegroup
aws eks describe-nodegroup --cluster-name $CLUSTER_NAME --nodegroup-name $CLUSTER_NAME-nodegroup | jq
# eks 노드 OS, 컨테이너 런타임, capacity type 등 확인
kubectl get node --label-columns=node.kubernetes.io/instance-type,eks.amazonaws.com/capacityType,topology.kubernetes.io/zone
kubectl get node --label-columns=node.kubernetes.io/instance-type
kubectl get node
kubectl get node -owide
kubectl get node 옵션에 따라 OS, 컨테이너 런타임, capacity type, Node가 위치한 AZ 등 다양한 정보 확인이 가능하다.
EKS Pod 확인
# 파드 정보 확인
kubectl get pod -n kube-system
kubectl get pod -n kube-system -o wide
kubectl get pod -A
kubectl top node
kubectl top pod -A
스터디 내용 중 온프레미스 쿠버의 Pod와 EKS Pod 배치 간 차이점에 대한 질문이 있는데, 온프레미스 쿠버는 제대로 사용해본적이 없어 차이점은 모르겠지만 EKS의 Pod는 VPC 서브넷 범위에서 IP를 할당 받는 것으로 보인다.
관련 내용은 2주차에 다룰 예정이라고 하니 향후 포스팅에서 작성하겠다.
Pod 개수, Status, 실행된 시간과 CPU, Memory 점유 현황도 확인 가능하다.
CPU(cores)의 m 단위 표기법이 낯설어서 찾아보니 m은 millicore를 뜻하고 100m당 0.1 CPU와 같다고 한다.
자세한 내용은 아래 링크 참조
https://kubernetes.io/docs/tasks/configure-pod-container/assign-cpu-resource/#cpu-units
네임스페이스 모든 리소스 확인
# kube-system의 모든 리소스 확인
kubectl get-all -n kube-system
# 현재 네임스페이스에서 모든 리소스 확인
kubectl get-all
get-all 플러그인을 통해 네임스페이스를 지정해서 모든 리소스 확인이 가능하고 현재 네임스페이스의 모든 리소스도 확인이 가능하다.
파드 컨테이너 이미지 정보 확인
# 모든 파드의 컨테이너 이미지 정보 확인
kubectl get pods --all-namespaces -o jsonpath="{.items[*].spec.containers[*].image}" | tr -s '[[:space:]]' '\n' | sort | uniq -c
Data Plane 노드 상세 정보 확인
노드 SSH 접속
# 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
# VPC 내 모든 Zone의 노드 IP 확인
kubectl get node --label-columns=topology.kubernetes.io/zone
# VPC 내 AZ A 내 노드 IP 확인
kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2a
# VPC 내 AZ C 내 노드 IP 확인
kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2c
# 노드 IP 환경 변수 지정
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-2c -o jsonpath={.items[0].status.addresses[0].address})
echo "export N1=$N1" >> /etc/profile
echo "export N2=$N2" >> /etc/profile
각 노드 IP로 Ping 테스트를 진행해보자.
이 때 보안 그룹에 ICMP Allow 룰이 없으면 Ping 통신이 불가능하니 추가 후 테스트를 진행한다.
# 노드 보안그룹 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
echo "export NGSGID=$NGSGID" >> /etc/profile
# 노드 보안그룹에 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 -c 2 $N1
ping -c 2 $N2
워커 노드 SSH 접속도 진행해보자.
# 워커 노드 SSH 접속
ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no ec2-user@$N1 hostname
ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no ec2-user@$N2 hostname
ssh ec2-user@$N1
ssh ec2-user@$N2
노드 네트워크 정보
# AWS VPC CNI 사용 확인
kubectl -n kube-system get ds aws-node
# CNI 이미지 정보 확인
kubectl describe daemonset aws-node --namespace kube-system | grep Image | cut -d "/" -f 2
# kubecolor 사용해 노드 조회
kubecolor describe pod -n kube-system -l k8s-app=aws-node
#파드 IP 확인
kubectl get pod -n kube-system -owide
kubectl get pod -n kube-system -l k8s-app=kube-dns -owide
# 노드 정보 확인
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i hostname; echo; done
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo ip -c addr; echo; done
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo ip -c route; echo; done
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo iptables -t nat -S; echo; done
노드 프로세스 정보 확인
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo systemctl status kubelet; echo; done
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo pstree; echo; done
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i ps afxuwww; echo; done
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i ps axf |grep /usr/bin/containerd; echo; done
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i ls /etc/kubernetes/manifests/; echo; done # EKS static pod X
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i ls /etc/kubernetes/kubelet/; echo; done
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i cat /etc/kubernetes/kubelet/kubelet-config.json | jq; echo; done
노드 스토리지 확인
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i lsblk; echo; done
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i df -hT /; echo; done
EKS Owned ENI
관리형 노드 그룹의 워커 노드는 내 계정 소유지만, 연결된 ENI(NIC는 내꺼)의 인스턴스(관리형 노드)는 AWS 소유이다
기본 사용
기본적인 사용법을 익혀보자
# 터미널1 (모니터링)
watch -d 'kubectl get pod'
# 터미널2
# Deployment 배포(Pod 3개)
kubectl create deployment my-webs --image=gcr.io/google-samples/kubernetes-bootcamp:v1 --replicas=3
kubectl get pod -w
# 파드 증가 및 감소
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
kubectl get pod
kubectl get deploy -o yaml | kubectl neat | yh
자원 삭제
# Amazon EKS 클러스터 삭제(10분 정도 소요)
eksctl delete cluster --name $CLUSTER_NAME
#클러스터 삭제 완료 확인 후 AWS CloudFormation 스택 삭제
aws cloudformation delete-stack --stack-name myeks
'k8s > AWS EKS' 카테고리의 다른 글
[AWS] EKS AutoScaling (0) | 2025.03.08 |
---|---|
[AWS] EKS Observability (0) | 2025.03.01 |
[AWS] EKS Storage (0) | 2025.02.23 |
[AWS] EKS Networking (0) | 2025.02.16 |
[AWS]EKS Cluster Endpoint 정리 (0) | 2025.02.07 |