[1주차] Amzaon EKS 설치 및 기본 사용
CloudNet@ 가시다님이 진행하는 AWS EKS Hands-on Study 내용 참고.
K8S 소개
기초 이론
☞ Kubernetes Components : K8S 클러스터는 Controle Plane(마스터)와 Node(노드)로 구성 - 링크
- Control Plane(마스터 노드) 핵심 컴포넌트 : 마스터는 단일 서버 혹은 고가용성을 위한 클러스터 마스터로 구축
- kube-apiserver : 마스터로 전달되는 모든 요청을 받아 드리는 API 서버 - (심화) 링크1 링크2 링크3
- etcd : 클러스터내 모든 메타 정보를 저장하는 서비스
- kube-scheduler : 사용자의 요청에 따라 적절하게 컨테이너를 워커 노드에 배치하는 스케줄러
- kube-controller-manager : 현재 상태와 바라는 상태를 지속적으로 확인하며 특정 이벤트에 따라 특정 동작을 수행하는 컨트롤러 - 링크
- cloud-controller-manager : 클라우드 플랫폼(AWS, GCP, Azure 등)에 특화된 리소스를 제어하는 클라우드 컨트롤러 - 링크
- 워커 노드 - 링크
- kubelet : 마스터의 명령에 따라 컨테이너의 라이프 사이클을 관리하는 노드 관리자
- kube-proxy : 컨테이너의 네트워킹을 책임지는 프록시, 네트워크 규칙을 유지 관리
- Container Runtime : 실제 컨테이너를 실행하는 컨테이너 실행 환경, (
Docker& containerD & CRI-O)
- Add on
☞ K8S 아키텍처 소개 : 김태민 기술 블로그 - 링크 아키텍처
Amazon EKS 소개
Amazon EKS 기초 소개 필독 영상
https://www.youtube.com/watch?v=E49Q3y9wsUo
그림출처: T14S4_Amazon EKS 마이그레이션 요점 정리.pdf
- K8S : cloud-controller-manager…
- Amazon Elastic Kubernetes Service는 자체 Kubernetes 컨트롤 플레인 또는 노드를 설치, 운영 및 유지 관리할 필요 없이 Kubernetes 실행에 사용할 수 있는 관리형 서비스
- 여러 AWS 가용 영역에 걸쳐 Kubernetes 컨트롤 플레인을 실행하고 크기를 조정하여 높은 가용성을 보장
- 컨트롤 플레인은 제어 영역 인스턴스의 크기를 자동으로 조정하고, 비정상 제어 영역 인스턴스를 감지하고 교체하며, 자동화된 버전 업데이트 및 패치를 제공
- 여러 AWS 서비스와 통합 : 컨테이너 이미지 저장소 Amazon ECR, 로드 분산을 위한 ELB, 인증 IAM, 격리를 위한 Amazon VPC
- 오픈 소스 Kubernetes 소프트웨어의 최신 버전을 실행하므로 Kubernetes 커뮤니티에서 모든 기존 플러그 인과 도구를 사용할 수 있습니다. 필요한 코드를 수정하지 않고 표준 Kubernetes 애플리케이션을 Amazon EKS로 쉽게 마이그레이션할 수 있습니다.
- 지원 버전 : 보통 4개의 마이너 버전 지원(현재 1.32~1.29), 평균 3개월마다 새 버전 제공, 처음 14개월 지원, 추가(1.28~1.24) 12개월 연장 지원(비용 추가) - 링크
- v1.25.Y → Major.Minor.Patch ⇒ Major(Breaking Changes) . Minor(New Features) . Patch(Bug fixes Security)
☞ EKS 아키텍처 - Docs*
- EKS 컨트롤 플레인 : 분산 구성 요소, 복원성, 가동 시간(SLA), AWS Managed VPC(3개 AZ, API NLB, ETCD ELB - 링크)
- EKS 데이터 플레인 : Customer VPC - EKS owned ENI?, 노드 유형(Managed node groups, Self-managed nodes, AWS Auto Mode, AWS Fargate, Karpenter, AWS Hybrid Nodes) - 링크
- Managed node groups (관리형 노드 그룹) : 최신 EKS Optimized AMI를 사용 - 링크, AWS에서 AMI 관리, Capacity(On-Demand, Spot) - 링크
- Bottlerocket, A Year in the Life - 링크
- Self-managed nodes : Custom AMI를 사용, ASG 직접 관리, OS 기본구성/패치를 고객이 직접 관리 - 링크
- Karpenter : 유연한 고성능 Kubernetes 클러스터 자동 규모 조정기로 애플리케이션 가용성과 클러스터 효율성 개선에 도움이 됩니다.Karpenter는 변화하는 애플리케이션 로드에 대응하여 적절한 크기의 컴퓨팅 리소스를 시작합니다. 이 옵션은 워크로드의 요구 사항을 충족하는 적시 컴퓨팅 리소스를 프로비저닝.
- EKS Auto Mode : 컨트롤 플레인을 넘어 데이터 영역을 포함하도록 AWS 관리를 확장하여 클러스터 인프라 관리를 자동화합니다. 컴퓨팅 오토 스케일링, 네트워킹, 로드 밸런싱, DNS, 스토리지, GPU 지원을 포함하여 핵심 Kubernetes 기능을 기본 구성 요소로 통합합니다. EKS Auto Mode는 향상된 보안 기능과 함께 변경할 수 없는 AMI를 사용하여 워크로드 수요에 따라 노드를 동적으로 관리.
- EKS Hybrid Nodes : 온프레미스 및 엣지 인프라를 Amazon EKS 클러스터의 노드로 사용할 수 있습니다. Amazon EKS Hybrid Nodes는 환경 전반의 Kubernetes 관리를 통합하고 온프레미스 및 엣지 애플리케이션을 위해 Kubernetes 컨트롤 플레인 관리를 AWS로 오프로드.
- AWS Fargate (서버리스) : 고객은 별도의 EC2관리할 필요 없이, AWS Fargate 환경에서 제공하는 Micro VM을 이용하여 Pod 별 VM 할당 - 링크
- 서버리스 가상화 오픈소스 Firecracker 톺아보기 - 신재현, 무신사
- 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 배포 방식 : (1) 웹 관리 콘솔 - 링크, (2) eksctl, (3) IaC - CDK, CloudFormation, Terraform 등
- eksctl : EKS 클러스터 구축 및 관리를 하기 위한 오프소스 명령줄 도구 - 링크
- eksctl 을 통해 배포 및 업데이트 시 AWS CloudFormation 서비스를 통해서 스택을 생성하거나 업데이트를 수행합니다 - 코드링크
// NewStackCollection creates a stack manager for a single cluster
func NewStackCollection(provider api.ClusterProvider, spec *api.ClusterConfig) StackManager {
tags := []types.Tag{
newTag(api.ClusterNameTag, spec.Metadata.Name),
newTag(api.OldClusterNameTag, spec.Metadata.Name),
newTag(api.EksctlVersionTag, version.GetVersion()),
}
for key, value := range spec.Metadata.Tags {
tags = append(tags, newTag(key, value))
}
return &StackCollection{
spec: spec,
sharedTags: tags,
cloudformationAPI: provider.CloudFormation(),
ec2API: provider.EC2(),
eksAPI: provider.EKS(),
iamAPI: provider.IAM(),
cloudTrailAPI: provider.CloudTrail(),
asgAPI: provider.ASG(),
disableRollback: provider.CloudFormationDisableRollback(),
roleARN: provider.CloudFormationRoleARN(),
region: provider.Region(),
waitTimeout: provider.WaitTimeout(),
}
}
// DoCreateStackRequest requests the creation of a CloudFormation stack
func (c *StackCollection) DoCreateStackRequest(ctx context.Context, i *Stack, templateData TemplateData, tags, parameters map[string]string, withIAM bool, withNamedIAM bool) error {
input := &cloudformation.CreateStackInput{
StackName: i.StackName,
DisableRollback: aws.Bool(c.disableRollback),
}
input.Tags = append(input.Tags, c.sharedTags...)
for k, v := range tags {
input.Tags = append(input.Tags, newTag(k, v))
}
switch data := templateData.(type) {
case TemplateBody:
input.TemplateBody = aws.String(string(data))
case TemplateURL:
input.TemplateURL = aws.String(string(data))
default:
return fmt.Errorf("unknown template data type: %T", templateData)
}
if withIAM {
input.Capabilities = stackCapabilitiesIAM
}
if withNamedIAM {
input.Capabilities = stackCapabilitiesNamedIAM
}
if cfnRole := c.roleARN; cfnRole != "" {
input.RoleARN = aws.String(cfnRole)
}
for k, v := range parameters {
input.Parameters = append(input.Parameters, types.Parameter{
ParameterKey: aws.String(k),
ParameterValue: aws.String(v),
})
}
logger.Debug("CreateStackInput = %#v", input)
s, err := c.cloudformationAPI.CreateStack(ctx, input)
if err != nil {
return errors.Wrapf(err, "creating CloudFormation stack %q", *i.StackName)
}
i.StackId = s.StackId
return nil
}
Terraform 배포
https://learnk8s.io/terraform-eks
Provisioning Kubernetes clusters on AWS with Terraform and EKS
Learn how you can leverage Terraform and EKS to provision identical clusters for development, staging and production environments with a single click.
learnk8s.io
직접 처음부터 EKS 배포해보기
- 악분일상 님 : eksctl로 EKS생성 - Blog
☞ 기본 인프라 배포 - 링크 ← 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, 서브넷 정보 지정
# yaml 파일 다운로드
curl -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/K8S/myeks-1week.yaml
# 배포
# aws cloudformation deploy --template-file ~/Downloads/myeks-1week.yaml --stack-name mykops --parameter-overrides KeyName=<My SSH Keyname> SgIngressSshCidr=<My Home Public IP Address>/32 --region <리전>
예시) aws cloudformation deploy --template-file ~/Downloads/myeks-1week.yaml \
--stack-name myeks --parameter-overrides KeyName=kp-gasida SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32 --region ap-northeast-2
# CloudFormation 스택 배포 완료 후 EC2 IP 출력
aws cloudformation describe-stacks --stack-name myeks --query 'Stacks[*].Outputs[*].OutputValue' --output text
예시) 54.180.245.88
# ec2 에 SSH 접속 : root / qwe123
예시) ssh root@54.180.245.88
ssh root@$(aws cloudformation describe-stacks --stack-name myeks --query 'Stacks[*].Outputs[0].OutputValue' --output text)
root@@X.Y.Z.A's password: qwe123
- myeks-1week.yaml : VPC, Subnet4개, EC2 1대 + 보안그룹(자신의 집 IP만 허용)
AWSTemplateFormatVersion: '2010-09-09'
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: "<<<<< EKSCTL MY EC2 >>>>>"
Parameters:
- ClusterBaseName
- KeyName
- SgIngressSshCidr
- MyInstanceType
- LatestAmiId
- Label:
default: "<<<<< Region AZ >>>>>"
Parameters:
- TargetRegion
- AvailabilityZone1
- AvailabilityZone2
- Label:
default: "<<<<< VPC Subnet >>>>>"
Parameters:
- VpcBlock
- PublicSubnet1Block
- PublicSubnet2Block
- PrivateSubnet1Block
- PrivateSubnet2Block
Parameters:
ClusterBaseName:
Type: String
Default: myeks
AllowedPattern: "[a-zA-Z][-a-zA-Z0-9]*"
Description: must be a valid Allowed Pattern '[a-zA-Z][-a-zA-Z0-9]*'
ConstraintDescription: ClusterBaseName - must be a valid Allowed Pattern
KeyName:
Description: Name of an existing EC2 KeyPair to enable SSH access to the instances. Linked to AWS Parameter
Type: AWS::EC2::KeyPair::KeyName
ConstraintDescription: must be the name of an existing EC2 KeyPair.
SgIngressSshCidr:
Description: The IP address range that can be used to communicate to the EC2 instances
Type: String
MinLength: '9'
MaxLength: '18'
Default: 0.0.0.0/0
AllowedPattern: (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})
ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.
MyInstanceType:
Description: Enter t2.micro, t2.small, t2.medium, t3.micro, t3.small, t3.medium. Default is t2.micro.
Type: String
Default: t3.medium
AllowedValues:
- t2.micro
- t2.small
- t2.medium
- t3.micro
- t3.small
- t3.medium
LatestAmiId:
Description: (DO NOT CHANGE)
Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2'
AllowedValues:
- /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
TargetRegion:
Type: String
Default: ap-northeast-2
AvailabilityZone1:
Type: String
Default: ap-northeast-2a
AvailabilityZone2:
Type: String
Default: ap-northeast-2c
VpcBlock:
Type: String
Default: 192.168.0.0/16
PublicSubnet1Block:
Type: String
Default: 192.168.1.0/24
PublicSubnet2Block:
Type: String
Default: 192.168.2.0/24
PrivateSubnet1Block:
Type: String
Default: 192.168.3.0/24
PrivateSubnet2Block:
Type: String
Default: 192.168.4.0/24
Resources:
# VPC
EksVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VpcBlock
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: !Sub ${ClusterBaseName}-VPC
# PublicSubnets
PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Ref AvailabilityZone1
CidrBlock: !Ref PublicSubnet1Block
VpcId: !Ref EksVPC
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub ${ClusterBaseName}-PublicSubnet1
- Key: kubernetes.io/role/elb
Value: 1
PublicSubnet2:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Ref AvailabilityZone2
CidrBlock: !Ref PublicSubnet2Block
VpcId: !Ref EksVPC
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub ${ClusterBaseName}-PublicSubnet2
- Key: kubernetes.io/role/elb
Value: 1
InternetGateway:
Type: AWS::EC2::InternetGateway
VPCGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId: !Ref InternetGateway
VpcId: !Ref EksVPC
PublicSubnetRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref EksVPC
Tags:
- Key: Name
Value: !Sub ${ClusterBaseName}-PublicSubnetRouteTable
PublicSubnetRoute:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PublicSubnetRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PublicSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet1
RouteTableId: !Ref PublicSubnetRouteTable
PublicSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet2
RouteTableId: !Ref PublicSubnetRouteTable
# PrivateSubnets
PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Ref AvailabilityZone1
CidrBlock: !Ref PrivateSubnet1Block
VpcId: !Ref EksVPC
Tags:
- Key: Name
Value: !Sub ${ClusterBaseName}-PrivateSubnet1
- Key: kubernetes.io/role/internal-elb
Value: 1
PrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Ref AvailabilityZone2
CidrBlock: !Ref PrivateSubnet2Block
VpcId: !Ref EksVPC
Tags:
- Key: Name
Value: !Sub ${ClusterBaseName}-PrivateSubnet2
- Key: kubernetes.io/role/internal-elb
Value: 1
PrivateSubnetRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref EksVPC
Tags:
- Key: Name
Value: !Sub ${ClusterBaseName}-PrivateSubnetRouteTable
PrivateSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet1
RouteTableId: !Ref PrivateSubnetRouteTable
PrivateSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet2
RouteTableId: !Ref PrivateSubnetRouteTable
# EKSCTL-Host
EKSEC2SG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: eksctl-host Security Group
VpcId: !Ref EksVPC
Tags:
- Key: Name
Value: !Sub ${ClusterBaseName}-HOST-SG
SecurityGroupIngress:
- IpProtocol: '-1'
CidrIp: !Ref SgIngressSshCidr
EKSEC2:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref MyInstanceType
ImageId: !Ref LatestAmiId
KeyName: !Ref KeyName
Tags:
- Key: Name
Value: !Sub ${ClusterBaseName}-host
NetworkInterfaces:
- DeviceIndex: 0
SubnetId: !Ref PublicSubnet1
GroupSet:
- !Ref EKSEC2SG
AssociatePublicIpAddress: true
PrivateIpAddress: 192.168.1.100
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
VolumeType: gp3
VolumeSize: 30
DeleteOnTermination: true
UserData:
Fn::Base64:
!Sub |
#!/bin/bash
hostnamectl --static set-hostname "${ClusterBaseName}-host"
# Config Root account
echo 'root:qwe123' | chpasswd
sed -i "s/^#PermitRootLogin yes/PermitRootLogin yes/g" /etc/ssh/sshd_config
sed -i "s/^PasswordAuthentication no/PasswordAuthentication yes/g" /etc/ssh/sshd_config
rm -rf /root/.ssh/authorized_keys
systemctl restart sshd
# Config convenience
echo 'alias vi=vim' >> /etc/profile
echo "sudo su -" >> /home/ec2-user/.bashrc
sed -i "s/UTC/Asia\/Seoul/g" /etc/sysconfig/clock
ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime
# Install Packages
yum -y install tree jq git htop
# Install YAML Highlighter
wget https://github.com/andreazorzetto/yh/releases/download/v0.4.0/yh-linux-amd64.zip
unzip yh-linux-amd64.zip
mv yh /usr/local/bin/
# Install kubectl & helm
cd /root
curl -O https://s3.us-west-2.amazonaws.com/amazon-eks/1.31.2/2024-11-15/bin/linux/amd64/kubectl
install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
curl -s https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
# Install eksctl
curl -sL "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_Linux_amd64.tar.gz" | tar xz -C /tmp
mv /tmp/eksctl /usr/local/bin
# 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/
Outputs:
eksctlhost:
Value: !GetAtt EKSEC2.PublicIp
- 기본 정보 확인
# (옵션) cloud-init 실행 과정 로그 확인
tail -f /var/log/cloud-init-output.log
# 사용자 확인
whoami
# 기본 툴 및 SSH 키 설치 등 확인
kubectl version --client=true -o yaml
eksctl version
aws --version
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]: AKIA5...
AWS Secret Access Key [None]: CVNa2...
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
# 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
## 퍼블릭 서브넷 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
echo $PubSubnet2
- EKS Add-on 정보 확인
# EKS Addon 정보 확인
aws eks describe-addon-versions --kubernetes-version 1.32 --query 'addons[].{MarketplaceProductUrl: marketplaceInformation.productUrl, Name: addonName, Owner: owner Publisher: publisher, Type: type}' --output table
aws eks describe-addon-versions --kubernetes-version 1.31 --query 'addons[].{MarketplaceProductUrl: marketplaceInformation.productUrl, Name: addonName, Owner: owner Publisher: publisher, Type: type}' --output table
aws eks describe-addon-versions --kubernetes-version 1.30 --query 'addons[].{MarketplaceProductUrl: marketplaceInformation.productUrl, Name: addonName, Owner: owner Publisher: publisher, Type: type}' --output table
aws eks describe-addon-versions --kubernetes-version 1.29 --query 'addons[].{MarketplaceProductUrl: marketplaceInformation.productUrl, Name: addonName, Owner: owner Publisher: publisher, Type: type}' --output table
## wc -l 로 갯수 비교
aws eks describe-addon-versions --kubernetes-version 1.32 --query 'addons[].{MarketplaceProductUrl: marketplaceInformation.productUrl, Name: addonName, Owner: owner Publisher: publisher, Type: type}' --output text | wc -l
aws eks describe-addon-versions --kubernetes-version 1.31 --query 'addons[].{MarketplaceProductUrl: marketplaceInformation.productUrl, Name: addonName, Owner: owner Publisher: publisher, Type: type}' --output text | wc -l
aws eks describe-addon-versions --kubernetes-version 1.30 --query 'addons[].{MarketplaceProductUrl: marketplaceInformation.productUrl, Name: addonName, Owner: owner Publisher: publisher, Type: type}' --output text | wc -l
aws eks describe-addon-versions --kubernetes-version 1.29 --query 'addons[].{MarketplaceProductUrl: marketplaceInformation.productUrl, Name: addonName, Owner: owner Publisher: publisher, Type: type}' --output text | wc -l
aws eks describe-addon-versions --kubernetes-version 1.28 --query 'addons[].{MarketplaceProductUrl: marketplaceInformation.productUrl, Name: addonName, Owner: owner Publisher: publisher, Type: type}' --output text | wc -l
aws eks describe-addon-versions --kubernetes-version 1.27 --query 'addons[].{MarketplaceProductUrl: marketplaceInformation.productUrl, Name: addonName, Owner: owner Publisher: publisher, Type: type}' --output text | wc -l
# EKS Add-on 별 전체 버전 정보 확인
ADDON=<add-on 이름>
ADDON=vpc-cni
# 아래는 vpc-cni 전체 버전 정보와 기본 설치 버전(True) 정보 확인
aws eks describe-addon-versions \
--addon-name $ADDON \
--kubernetes-version 1.31 \
--query "addons[].addonVersions[].[addonVersion, compatibilities[].defaultVersion]" \
--output text
# EKS 애드온의 버전별로 호환되는 EKS 버전을 확인하는 스크립트 https://malwareanalysis.tistory.com/760
ADDON_NAME=aws-ebs-csi-driver
aws eks describe-addon-versions --addon-name $ADDON_NAME | jq -r '
.addons[] |
.addonVersions[] |
select(.architecture[] | index("amd64")) |
[.addonVersion, (.compatibilities[] | .clusterVersion), (.compatibilities[] | .defaultVersion)] |
@tsv'
# eksctl help
eksctl
eksctl create
eksctl create cluster --help
eksctl create nodegroup --help
eksctl utils schema | jq
# 현재 지원 버전 정보 확인
eksctl create cluster -h | grep version
# eks 클러스터 생성 + 노드그룹없이
eksctl create cluster --name myeks --region=ap-northeast-2 --without-nodegroup --dry-run | yh
apiVersion: eksctl.io/v1alpha5
availabilityZones:
- ap-northeast-2c
- ap-northeast-2d
- ap-northeast-2a
...
# eks 클러스터 생성 + 노드그룹없이 & 사용 가용영역(2a,2c)
eksctl create cluster --name myeks --region=ap-northeast-2 --without-nodegroup --zones=ap-northeast-2a,ap-northeast-2c --dry-run | yh
apiVersion: eksctl.io/v1alpha5
availabilityZones:
- ap-northeast-2a
- ap-northeast-2c
...
# eks 클러스터 생성 + 관리형노드그룹생성(이름, 인스턴스 타입, EBS볼륨사이즈) & 사용 가용영역(2a,2c) + VPC 대역 지정
eksctl create cluster --name myeks --region=ap-northeast-2 --nodegroup-name=mynodegroup --node-type=t3.medium --node-volume-size=30 \
--zones=ap-northeast-2a,ap-northeast-2c --vpc-cidr=172.20.0.0/16 --dry-run | yh
...
managedNodeGroups:
- amiFamily: AmazonLinux2
desiredCapacity: 2
disableIMDSv1: true
disablePodIMDS: false
iam:
withAddonPolicies:
albIngress: false
appMesh: false
appMeshPreview: false
autoScaler: false
awsLoadBalancerController: false
certManager: false
cloudWatch: false
ebs: false
efs: false
externalDNS: false
fsx: false
imageBuilder: false
xRay: false
instanceSelector: {}
instanceType: t3.medium
labels:
alpha.eksctl.io/cluster-name: myeks
alpha.eksctl.io/nodegroup-name: mynodegroup
maxSize: 2
minSize: 2
name: mynodegroup
privateNetworking: false
releaseVersion: ""
securityGroups:
withLocal: null
withShared: null
ssh:
allow: false
publicKeyPath: ""
tags:
alpha.eksctl.io/nodegroup-name: mynodegroup
alpha.eksctl.io/nodegroup-type: managed
volumeIOPS: 3000
volumeSize: 30
volumeThroughput: 125
volumeType: gp3
metadata:
name: myeks
region: ap-northeast-2
version: "1.30"
privateCluster:
enabled: false
skipEndpointCreation: false
vpc:
autoAllocateIPv6: false
cidr: 172.20.0.0/16
clusterEndpoints:
privateAccess: false
publicAccess: true
manageSharedNodeSecurityGroupRules: true
nat:
gateway: Single
# eks 클러스터 생성 + 관리형노드그룹생성(AMI:Ubuntu 20.04, 이름, 인스턴스 타입, EBS볼륨사이즈, SSH접속허용) & 사용 가용영역(2a,2c) + VPC 대역 지정
eksctl create cluster --name myeks --region=ap-northeast-2 --nodegroup-name=mynodegroup --node-type=t3.medium --node-volume-size=30 \
--zones=ap-northeast-2a,ap-northeast-2c --vpc-cidr=172.20.0.0/16 --ssh-access --node-ami-family Ubuntu2004 --dry-run | yh
...
managedNodeGroups:
- amiFamily: Ubuntu2004
...
ssh:
allow: true
publicKeyPath: ~/.ssh/id_rsa.pub
- [컨트롤 플레인] amazon EKS 배포 실습!
# 변수 확인***
echo $AWS_DEFAULT_REGION
echo $CLUSTER_NAME
echo $VPCID
echo $PubSubnet1,$PubSubnet2
# 옵션 [터미널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.31 --ssh-access --external-dns-access --dry-run | yh
...
vpc:
autoAllocateIPv6: false
cidr: 192.168.0.0/16
clusterEndpoints:
privateAccess: false
publicAccess: true
id: vpc-0505d154771a3dfdf
manageSharedNodeSecurityGroupRules: true
nat:
gateway: Disable
subnets:
public:
ap-northeast-2a:
az: ap-northeast-2a
cidr: 192.168.1.0/24
id: subnet-0d98bee5a7c0dfcc6
ap-northeast-2c:
az: ap-northeast-2c
cidr: 192.168.2.0/24
id: subnet-09dc49de8d899aeb7
# eks 클러스터 & 관리형노드그룹 배포: 총 15분 소요
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
...
023-04-23 01:32:22 [▶] setting current-context to admin@myeks.ap-northeast-2.eksctl.io
2023-04-23 01:32:22 [✔] saved kubeconfig as "/root/.kube/config"
...
- AWS CloudFormation 확인해보기 → AWS EKS 확인해보기 → AWS EC2 확인해보기 → AWS EC2 ASG 확인해보기
- eks 정보 확인
# krew 플러그인 확인
kubectl krew list
kubectl ctx
kubectl ns
kubectl ns default
kubectl get-all # 모든 네임스페이스에서 모든 리소스 확인
# eks 클러스터 정보 확인
kubectl cluster-info
Kubernetes control plane is running at https://50E14FE698DE0E5CA2055F72AB086163.gr7.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://50E14FE698DE0E5CA2055F72AB086163.gr7.ap-northeast-2.eks.amazonaws.com
## dig 조회 : 해당 IP 소유 리소스는 어떤것일까요? : 자신의 PC에서도 해당 도메인 질의 조회 해보자
APIDNS=$(aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint | cut -d '/' -f 3)
dig +short $APIDNS
# eks API 접속 시도 : 도메인 or 출력되는 ip 주소로 https://<IP>/version 외부에서도 접속 가능!
curl -k -s $(aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint)
curl -k -s $(aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint)/version | jq
# 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
# 노드 정보 확인 : OS와 컨테이너런타임 확인
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
# 노드의 capacityType 확인
kubectl get node --label-columns=eks.amazonaws.com/capacityType
NAME STATUS ROLES AGE VERSION CAPACITYTYPE
ip-192-168-1-76.ap-northeast-2.compute.internal Ready <none> 19m v1.24.11-eks-a59e1f0 ON_DEMAND
ip-192-168-2-21.ap-northeast-2.compute.internal Ready <none> 19m v1.24.11-eks-a59e1f0 ON_DEMAND
# 인증 정보 확인 : 자세한 정보는 보안에서 다룸
kubectl get node -v=6
I0423 02:00:38.691443 5535 loader.go:374] Config loaded from file: /root/.kube/config
I0423 02:00:39.519097 5535 round_trippers.go:553] GET https://C813D20E6263FBDC356E60D2971FCBA7.gr7.ap-northeast-2.eks.amazonaws.com/api/v1/nodes?limit=500 200 OK in 818 milliseconds
...
cat /root/.kube/config
kubectl config view
kubectl ctx
## Get a token for authentication with an Amazon EKS cluster
aws eks get-token help
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
kubectl top node
kubectl top pod -A
# kube-system 네임스페이스에 모든 리소스 확인
kubectl get-all -n kube-system
# 현재 네임스페이스에서 모든 리소스 확인
kubectl get-all
# 모든 파드의 컨테이너 이미지 정보 확인
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.19.0-eksbuild.1
2 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/amazon/aws-network-policy-agent:v1.1.5-eksbuild.1
2 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/eks/coredns:v1.11.3-eksbuild.1
2 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/eks/kube-proxy:v1.31.2-minimal-eksbuild.3
2 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/eks/metrics-server:v0.7.2-eksbuild.1
# AWS ECR에서 컨테이너 이미지 가져오기 시도
docker pull 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/eks/coredns:v1.11.3-eksbuild.1
☞ cluster endpoint 방식에 대한 상세 설명 참고 링크
Control network access to cluster API server endpoint - Amazon EKS
Before October 2024, IPv6 clusters used this endpoint format also. For those clusters, both the public endpoint and the private endpoint have only IPv4 addresses resolve from this endpoint.
docs.aws.amazon.com
☞ [데이터 플레인] 노드 정보 상세 확인
- 노드 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
kubectl get node --label-columns=topology.kubernetes.io/zone
kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2a
kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2c
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 $N1, $N2
echo "export N1=$N1" >> /etc/profile
echo "export N2=$N2" >> /etc/profile
# eksctl-host 에서 노드의IP나 coredns 파드IP로 ping 테스트
ping <IP>
ping -c 1 $N1
ping -c 1 $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
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 -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
exit
ssh 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
kubecolor describe pod -n kube-system -l k8s-app=aws-node
# 파드 IP 확인
kubectl get pod -n kube-system -o wide
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
- Node cgroup version : v1(tmpfs), v2(cgroup2fs) - Link
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i stat -fc %T /sys/fs/cgroup/; 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 확인
# kubelet, kube-proxy 통신 Peer Address는 어딘인가요?
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo ss -tnp; echo; done
# 참고
APIDNS=$(aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint | cut -d '/' -f 3)
dig +short $APIDNS
# [터미널] 파드 1곳에 shell 실행해두기
## kubectl 명령으로 특정 파드에 접근 (경로) : 작업PC -> API Server -> kubelet -> pod
kubectl run -it --rm netdebug --image=nicolaka/netshoot --restart=Never -- zsh
$ ip -c a
$ watch uptime
# kubectl exec daemonsets/aws-node -it -n kube-system -c aws-eks-nodeagent -- bash
# exec 실행으로 추가된 연결 정보의 Peer Address는 어딘인가요? + AWS 네트워크 인터페이스 ENI에서 해당 IP 정보 확인
# 192.168.1.197 node에서 확인됨
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo ss -tnp; echo; done
...
ESTAB 0 0 [::ffff:192.168.1.197]:10250 [::ffff:192.168.1.37]:54610 users:(("kubelet",pid=2892,fd=21))
...
- EKS owned ENI : 관리형 노드 그룹의 워커 노드는 내 소유지만, 연결된 ENI(NIC는 내꺼)의 인스턴스(관리형 노드?)는 AWS 소유이다
- EC2 메타데이터 확인(IAM Role) : 상세한 내용은 보안에서 다룸 - 링크
# 노드1 접속
ssh ec2-user@$N1
----------------
# IMDSv2 메타데이터 정보 확인
TOKEN=`curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/ ;echo
eksctl-myeks-nodegroup-myeks-nodeg-NodeInstanceRole-LvouwOLQqtoG
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/eksctl-myeks-nodegroup-myeks-nodeg-NodeInstanceRole-LvouwOLQqtoG | jq
- [조력자 최영락] kubectl 버전 중요성 및 바이너리 커스텀 빌드를 통한 버전 문자열 커스터마이징 - Blog
관리 편리성
- kubectl 자동 완성 기능과 alias 사용하기 : 설치 확인에서 이미 설정함
# 자동 완성 및 alias 축약 설정
source <(kubectl completion bash)
alias k=kubectl
complete -F __start_kubectl k'
- kubectl cli 플러그인 매니저 쿠버네티스 크루(krew) 설치 : 이미 설치 되어 있음 - 링크
# 설치
curl -fsSLO https://github.com/kubernetes-sigs/krew/releases/download/v0.4.4/krew-linux_amd64.tar.gz
tar zxvf krew-linux_amd64.tar.gz
./krew-linux_amd64 install krew
tree -L 3 /root/.krew/bin
# krew 확인
kubectl krew
kubectl krew update
kubectl krew search
kubectl krew list
- krew 로 kube-ctx, kube-ns 설치 및 사용 : 이미 설치 되어 있음
- kube-ctx : 쿠버네티스 컨텍스트 사용
# 설치
kubectl krew install ctx
# 컨텍스트 확인
kubectl ctx
# 컨텍스트 사용
kubectl ctx <각자 자신의 컨텍스트 이름>
- kube-ns : 네임스페이스(단일 클러스터 내에서 가상 클러스터) 사용
# 설치
kubectl krew install ns
# 네임스페이스 확인
kubectl ns
# 터미널1
watch kubectl get pod
# kube-system 네임스페이스 선택 사용
kubectl ns kube-system
# default 네임스페이스 선택 사용
kubectl ns -
혹은
kubectl ns default
- krew list 확인
kubectl krew list
- krew 로 기타 플러그인 설치 및 사용 : df-pv get-all ktop neat oomd view-secret ← 플러그인 추천 부탁드립니다
# 설치
kubectl krew install df-pv get-all ktop neat oomd view-secret # mtail tree
# get-all 사용
kubectl get-all
kubectl get-all -n kube-system
# ktop 사용
kubectl ktop
# oomd 사용
kubectl oomd
# df-pv 사용
kubectl df-pv
# view-secret 사용 : 시크릿 복호화
kubectl view-secret
- kube-ps1 설치 및 사용 : 이미 설치 되어 있음
# 설치 및 설정
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=true
function get_cluster_short() {
echo "$1" | cut -d . -f1
}
KUBE_PS1_CLUSTER_FUNCTION=get_cluster_short
KUBE_PS1_SUFFIX=') '
PS1='$(kube_ps1)'$PS1
EOT
# 적용
exit
exit
# default 네임스페이스 선택
kubectl ns default
기본 사용
☞ 선언형 (멱등성) 알아보기 실습
# 터미널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
# 실습 완료 후 Deployment 삭제
kubectl delete deploy my-webs
- 서비스/디플로이먼트(mario 게임) 배포 테스트 with AWS CLB
# 터미널1 (모니터링)
watch -d 'kubectl get pod,svc'
# 수퍼마리오 디플로이먼트 배포
cat <<EOT > mario.yaml
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
EOT
kubectl apply -f mario.yaml
# 배포 확인 : 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 }'
- [Q] AWS CLB는 어떻게 배포가 되었을 까요? : Cloud Controller Manager 동작(아래 예시) - Docs → 하지만 부족한점? (동적 파드 IP 등)
- 노드 컨트롤러: 클라우드 공급자가 응답을 멈춘 후 클라우드에서 노드가 삭제되었는지 확인하기 위해 클라우드 공급자를 확인합니다.
- 경로 컨트롤러: 기본 클라우드 인프라에서 경로를 설정하기 위한 것입니다.
- 서비스 컨트롤러: 클라우드 공급자 로드 밸런서를 생성, 업데이트 및 삭제합니다 - Docs
- 서비스 컨트롤러는 서비스 오브젝트 생성, 업데이트 그리고 삭제 이벤트를 수신한 다음 해당 서비스에 대한 엔드포인트를 적절하게 구성한다(엔드포인트슬라이스(EndpointSlice)의 경우, kube-controller-manager가 필요에 따라 이들을 관리한다).
- v1/Service : List , Get, Watch, Patch, Update
- AWS EKS 관리 콘솔에서 리소스 확인(파드, 서비스) → AWS EC2 ELB(CLB) 확인
- 삭제 : kubectl delete -f mario.yaml
☞ 노드에 배포된 컨테이너 정보 확인 Containerd clients 3종 : ctr, nerdctl, crictl - 링크
# ctr 버전 확인
ssh ec2-user@$N1 ctr --version
# ctr help
ssh 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 ec2-user@$N1 sudo ctr ns list
NAME LABELS
k8s.io
# 컨테이너 리스트 확인
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo ctr -n k8s.io container list; echo; done
CONTAINER IMAGE RUNTIME
1bced59d140560853a5a6e0640878f0f2764f30698d658602fd66bd3da018d6c 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/eks/eks-node-monitoring-agent:v1.0.2-eksbuild.2 io.containerd.runc.v2
2a01593d6c5c5e15358a2e5ad7a7a42225fbf61fbc17335c027e6361f2e7e947 066635153087.dkr.ecr.il-central-1.amazonaws.com/amazon-k8s-cni-init:v1.19.0 io.containerd.runc.v2
4a2cea1ad7cbc2be9e692166bf16a8a04c76f862878e38919f0b2bef9a1c04a4 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/amazon/aws-network-policy-agent:v1.1.5-eksbuild.1 io.containerd.runc.v2
67aeeb8d654dd2a8b375958c86475cd92853e9cd6bd4fce79a75986e86f313a0 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/eks/pause:3.5 io.containerd.runc.v2
6e19530fe859a7ac1ac3a985b16518dbfecdb23876e0c0a88d821b810b2c23c9 066635153087.dkr.ecr.il-central-1.amazonaws.com/amazon-k8s-cni:v1.19.0 io.containerd.runc.v2
...
# 컨테이너 이미지 확인
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo ctr -n k8s.io image list --quiet; echo; done
...
# 태스크 리스트 확인
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo ctr -n k8s.io task list; echo; done
...
## 예시) 각 테스크의 PID(3706) 확인
ssh ec2-user@$N1 sudo ps -c 3108
PID CLS PRI TTY STAT TIME COMMAND
3108 TS 19 ? Ssl 0:00 kube-proxy --v=2 --config=/var/lib/kube-proxy-config/config --hostname-override=ip-192-168-1-163.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
# 퍼블릭 Repo 기본 정보 확인
aws ecr-public describe-registries --region us-east-1 | jq
# 퍼블릭 Repo 생성
NICKNAME=<각자자신의닉네임>
NICKNAME=gasida
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
# 이미지 태그
docker pull nginx:alpine
docker images
docker tag nginx:alpine $REPOURI:latest
docker images
# 이미지 업로드
docker push $REPOURI:latest
# 파드 실행
kubectl run mynginx --image $REPOURI
kubectl get pod
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
☞ [Add-on] eks-node-monitoring-agent EKS 노드 상태 - Docs
- eks-node-monitoring-agent addon 설치 : 웹 관리 콘솔에서 직접 선택 후 설치 - Docs
웹 관리 콘솔에서 직접 선택 후 설치
# 기본 정보 확인
eksctl utils describe-addon-versions --kubernetes-version 1.31 | grep AddonName
eksctl utils describe-addon-versions --kubernetes-version 1.31 | grep AddonName | grep -i node
eksctl utils describe-addon-versions --kubernetes-version 1.31 --name eks-node-monitoring-agent | grep AddonVersion
"AddonVersion": "v1.0.2-eksbuild.2",
"AddonVersion": "v1.0.1-eksbuild.2",
"AddonVersion": "v1.0.0-eksbuild.1",
# 설치 확인
watch -d kubectl get pod -n kube-system
kube-system eks-node-monitoring-agent-4gjsv 1/1 Running 0 17m
kube-system eks-node-monitoring-agent-6ddjb 1/1 Running 0 17m
# 노드 상태 정보 관찰 추가 : ContainerRuntimeReady,StorageReady,NetworkingReady,KernelReady
kubectl get nodes -o 'custom-columns=NAME:.metadata.name,CONDITIONS:.status.conditions[*].type,STATUS:.status.conditions[*].status'
kubecolor describe node
Conditions:
Type Status LastHeartbeatTime LastTransitionTime Reason Message
---- ------ ----------------- ------------------ ------ -------
MemoryPressure False Sat, 08 Feb 2025 21:53:38 +0900 Sat, 08 Feb 2025 20:24:22 +0900 KubeletHasSufficientMemory kubelet has sufficient memory available
DiskPressure False Sat, 08 Feb 2025 21:53:38 +0900 Sat, 08 Feb 2025 20:24:22 +0900 KubeletHasNoDiskPressure kubelet has no disk pressure
PIDPressure False Sat, 08 Feb 2025 21:53:38 +0900 Sat, 08 Feb 2025 20:24:22 +0900 KubeletHasSufficientPID kubelet has sufficient PID available
Ready True Sat, 08 Feb 2025 21:53:38 +0900 Sat, 08 Feb 2025 20:24:34 +0900 KubeletReady kubelet is posting ready status
ContainerRuntimeReady True Sat, 08 Feb 2025 21:52:59 +0900 Sat, 08 Feb 2025 21:42:59 +0900 ContainerRuntimeIsReady Monitoring for the ContainerRuntime system is active
StorageReady True Sat, 08 Feb 2025 21:52:59 +0900 Sat, 08 Feb 2025 21:42:59 +0900 DiskIsReady Monitoring for the Disk system is active
NetworkingReady True Sat, 08 Feb 2025 21:52:59 +0900 Sat, 08 Feb 2025 21:42:59 +0900 NetworkingIsReady Monitoring for the Networking system is active
KernelReady True Sat, 08 Feb 2025 21:52:59 +0900 Sat, 08 Feb 2025 21:42:59 +0900 KernelIsReady Monitoring for the Kernel system is active
# 노드 상태 정보 확인
kubectl get nodes -o 'custom-columns=NAME:.metadata.name,CONDITIONS:.status.conditions[*].type,STATUS:.status.conditions[*].status'
NAME CONDITIONS STATUS
ip-192-168-1-163.ap-northeast-2.compute.internal MemoryPressure,DiskPressure,PIDPressure,Ready,ContainerRuntimeReady,StorageReady,NetworkingReady,KernelReady False,False,False,True,True,True,True,True
ip-192-168-2-222.ap-northeast-2.compute.internal MemoryPressure,DiskPressure,PIDPressure,Ready,NetworkingReady,KernelReady,ContainerRuntimeReady,StorageReady False,False,False,True,True,True,True,True
...>> 아래는 eks-node-monitoring-agent 미설치시 출력 정보
ip-192-168-1-163.ap-northeast-2.compute.internal MemoryPressure,DiskPressure,PIDPressure,Ready False,False,False,True
ip-192-168-2-222.ap-northeast-2.compute.internal MemoryPressure,DiskPressure,PIDPressure,Ready False,False,False,True
# 특정 노드 세부 정보
kubectl describe node <node-name>
kubecolor describe node <node-name>
# 노드 이벤트 정보
kubectl get events --field-selector involvedObject.kind=Node
kubectl get events -w --field-selector involvedObject.kind=Node
# 파드 로그 확인
kubectl krew install stern
kubectl stern -l app.kubernetes.io/instance=eks-node-monitoring-agent -n kube-system # EC2 재부팅 해두고 로그 확인
- eks-node-monitoring-agent-4gjsv › eks-node-monitoring-agent
failed to tail: Get "https://192.168.1.163:10250/containerLogs/kube-system/eks-node-monitoring-agent-4gjsv/eks-node-monitoring-agent?follow=true&sinceSeconds=172800×tamps=true": dial tcp 192.168.1.163:10250: connect: connection refused, will retry
+ eks-node-monitoring-agent-4gjsv › eks-node-monitoring-agent
- eks-node-monitoring-agent-4gjsv › eks-node-monitoring-agent
failed to tail: Get "https://192.168.1.163:10250/containerLogs/kube-system/eks-node-monitoring-agent-4gjsv/eks-node-monitoring-agent?follow=true&sinceSeconds=172800×tamps=true": dial tcp 192.168.1.163:10250: connect: connection refused, will retry
+ eks-node-monitoring-agent-4gjsv › eks-node-monitoring-agent
eks-node-monitoring-agent-4gjsv eks-node-monitoring-agent {"level":"info","ts":"2025-02-08T13:50:37Z","msg":"fetched runtime context","value":{"RuntimeOSDistro":"linux","AcceleratedHardware":"none","Tags":["amzn"]}}
eks-node-monitoring-agent-4gjsv eks-node-monitoring-agent {"level":"info","ts":"2025-02-08T13:50:37Z","msg":"initializing controller manager"}
eks-node-monitoring-agent-4gjsv eks-node-monitoring-agent {"level":"info","ts":"2025-02-08T13:50:37Z","msg":"initializing monitoring manager"}
eks-node-monitoring-agent-4gjsv eks-node-monitoring-agent {"level":"info","ts":"2025-02-08T13:50:37Z","msg":"registered monitor","name":"container-runtime"}
# 이벤트 확인 https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/node-health.html#node-health-issues
kubectl get events --field-selector=reportingComponent=eks-node-monitoring-agent # EC2 재부팅 해두고 로그 확인
LAST SEEN TYPE REASON OBJECT MESSAGE
60s Warning StorageReady node/ip-192-168-1-164.ap-northeast-2.compute.internal IODelays: Process (kworker/u4:1-xfs-cil/nvme0n1p1) (PID 22) incurred 14.6 seconds of I/O delay
- Node auto repair : 문제 발생 시 자동으로 노드 교체 기능 - Docs
- 노드 자동 복구(Node Auto Repair)는 기본적으로 kubelet의 Ready 상태 및 수동으로 삭제된 노드 객체에 반응할 수 있습니다.하지만 노드 모니터링 에이전트(Node Monitoring Agent)와 함께 사용하면, 기본적으로 감지할 수 없는 추가적인 상태 변화에도 반응할 수 있습니다.이러한 추가적인 상태에는 KernelReady, NetworkingReady, StorageReady가 포함됩니다.
- 노드 자동 복구는 DiskPressure, MemoryPressure, PIDPressure와 같은 문제를 처리할 수 없습니다.
- Amazon EKS는 AcceleratedHardwareReady와 관련된 노드 조건(NodeConditions)에 대해 10분 동안 대기한 후 조치를 취하며,그 외의 모든 조건에 대해서는 30분 동안 대기한 후 조치를 취합니다.
- 설정
- AWS CLI, add the --node-repair-config enabled=true
- eksctl ClusterConfig
# An example ClusterConfig that uses a managed node group with auto repair.
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: cluster-44
region: us-west-2
managedNodeGroups:
- name: ng-1
nodeRepairConfig:
enabled: true
- 관리형노드에 노드 추가 및 삭제 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
# 노드 확인
kubectl get nodes -o wide
kubectl get nodes -l eks.amazonaws.com/nodegroup=$CLUSTER_NAME-nodegroup
# 노드 3개 → 2개 감소 : 적용까지 시간이 소요됨
aws eks update-nodegroup-config --cluster-name $CLUSTER_NAME --nodegroup-name $CLUSTER_NAME-nodegroup --scaling-config minSize=2,maxSize=2,desiredSize=2
☞ 악분일상님 : 쿠버네티스 노드 헬스체크 원리(lease API) - Lease(리스) , Blog
- 노드 체크(하트비트) 방식 2가지 : (1) .state 노드 업데이트 , (2) lease
- kubelet은 노드의 .status 정보를 업데이트할 때, 상태 변경이 발생했을 경우 또는 설정된 주기 동안 업데이트가 없을 경우에 갱신합니다. 노드의 .status 업데이트 기본 주기는 5분이며, 이는 연결이 끊긴 노드에 대한 기본 타임아웃(40초)보다 훨씬 깁니다.
- kubelet은 Lease 객체를 생성한 후 기본적으로 10초마다 업데이트합니다. Lease 업데이트는 노드의 .status 업데이트와는 독립적으로 수행됩니다.만약 Lease 업데이트가 실패하면, kubelet은 200밀리초에서 시작하여 최대 7초까지 증가하는 지수 백오프(exponential backoff)를 사용하여 재시도합니다.
- 헬스체크 알고리즘 lease : 자원 대여 → 자원 반납 or 대여 주기적인 업데이트 (노드 헬스체크 사용) - K8S_Docs , Lease(리스)
- Lease 객체는 kube-node-lease 네임스페이스에 저장되며, 각 노드당 하나의 Lease 객체
# lease 자원 확인
kubectl get leases -n kube-node-lease
NAME HOLDER AGE
ip-192-168-1-170.ap-northeast-2.compute.internal ip-192-168-1-170.ap-northeast-2.compute.internal 8m28s
ip-192-168-2-222.ap-northeast-2.compute.internal ip-192-168-2-222.ap-northeast-2.compute.internal 172m
# 상세 정보 확인
kubecolor describe leases -n kube-node-lease
Spec:
Holder Identity: ip-192-168-2-20.ap-northeast-2.compute.internal
Lease Duration Seconds: 40 # 컨트롤러가 노드를 NotReady로 간주하기 전에 기다리는 시간 (기본 40초)
⇒ pod-eviction-timeout : 노드가 NotReady 상태일 때, Pod를 강제 퇴출(evict)하는 시간 - EKS 기본값 5분(300초)
- Kubernetes Controller Manager의 pod-eviction-timeout 파라미터는 기본적으로 5분으로 설정되어 있으며, Kubernetes 컨트롤 플레인을 통해 변경할 수 있습니다.
- 그러나 Amazon EKS는 관리형 Kubernetes 서비스이므로, pod-eviction-timeout 값을 수정할 수 없습니다.
Configure pod eviction time - AWS Prescriptive Guidance
Configure pod eviction time Pod eviction time is useful when designing for resiliency in a control plane or Availability Zone failure scenario. During the Availability Zone failure testing, where the subnets lose network connectivity, all the impacted Amaz
docs.aws.amazon.com
- How Does Alibaba Ensure the Performance of System Components in a 10,000-node Kubernetes Cluster?
How Does Alibaba Ensure the Performance of System Components in a 10,000-node Kubernetes Cluster?
This article looks the problems and challenges that Alibaba Cloud overcame for Kubernetes to function at an ultra-large scale and the specific solutions proposed.
www.alibabacloud.com
- 효율적인 노드 하트비트
- 쿠버네티스 클러스터의 확장성은 노드 하트비트의 효과적인 처리에 달려 있습니다. 일반적인 프로덕션 환경에서 kubelet은 10초마다 하트비트를 보고합니다. 각 하트비트 요청과 연결된 콘텐츠는 노드의 수십 개의 이미지와 일정량의 볼륨 정보를 포함하여 15KB에 이릅니다. 그러나 이 모든 것에는 두 가지 문제가 있습니다.
- 하트비트 요청은 etcd에서 노드 객체의 업데이트를 트리거하는데, 이는 10,000개의 노드가 있는 쿠버네티스 클러스터에서 분당 약 1GB의 트랜잭션 로그를 생성할 수 있습니다. 변경 내역은 etcd에 기록됩니다.
- API 서버의 CPU 사용량이 높고 직렬화 및 역직렬화의 오버헤드가 큰 노드로 구성된 Kubernetes 클러스터에서 하트비트 요청을 처리하는 CPU 오버헤드는 API 서버의 CPU 시간 사용량의 80%를 초과합니다.
☞ Node-pressure Eviction 문서 정리* - Docs , KrDocs , 추천Blog
☞ EKS Cluster Endpoint 를 Public(IP제한)+Private 로 변경 및 확인 : 설정 먼저 해두자!(6분 소요) - Docs 참고링크
- api-server → kubelet [private 통신]
- (외부 인터넷망) kubectl-host → (IP 접속 통제 설정 가능) api-server [public 통신]
- kubelet / kube-proxy → api-server [private 통신]
- [Q] 동일한 API (도메인) 주소에 대해서 VPC 내부와 외부(인터넷)에서 각기 다른 IP 정보를 응답을 가능한 기술 방법은?
- 현재 정보 확인
# [모니터링1] 설정 후 변경 확인 >> 추가로 자신의 집 PC에서도 아래 dig 조회 모니터링 걸어보자!
APIDNS=$(aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint | cut -d '/' -f 3)
dig +short $APIDNS
while true; do dig +short $APIDNS ; echo "------------------------------" ; date; sleep 1; done
# [모니터링2] 노드에서 ControlPlane과 통신 연결 확인 : IPv4 kube-proxy, kubelet 확인
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})
while true; do ssh ec2-user@$N1 sudo ss -tnp | egrep 'kubelet|kube-proxy' ; echo ; ssh ec2-user@$N2 sudo ss -tnp | egrep 'kubelet|kube-proxy' ; echo "------------------------------" ; date; sleep 1; done
# Public(IP제한)+Private 로 변경 : 설정 후 6분 정도 후 반영 >> IP를 자신의 집 공인 IP를 직접 넣어보자!
aws eks update-cluster-config --region $AWS_DEFAULT_REGION --name $CLUSTER_NAME --resources-vpc-config endpointPublicAccess=true,publicAccessCidrs="$(curl -s ipinfo.io/ip)/32",endpointPrivateAccess=true
- kubectl 확인
# kubectl 사용 확인
kubectl get node -v=6
kubectl cluster-info
ss -tnp | grep kubectl # 신규 터미널에서 확인 해보자 >> EKS 동작 VPC 내부에서는 Cluster Endpoint 도메인 질의 시 Private IP 정보를 리턴해준다
# EKS ControlPlane 보안그룹 ID 확인
aws ec2 describe-security-groups --filters Name=group-name,Values=*ControlPlaneSecurityGroup* --query "SecurityGroups[*].[GroupId]" --output text
CPSGID=$(aws ec2 describe-security-groups --filters Name=group-name,Values=*ControlPlaneSecurityGroup* --query "SecurityGroups[*].[GroupId]" --output text)
echo $CPSGID
# 노드 보안그룹에 eksctl-host 에서 노드(파드)에 접속 가능하게 룰(Rule) 추가 설정
aws ec2 authorize-security-group-ingress --group-id $CPSGID --protocol '-1' --cidr 192.168.1.100/32
# (최소 6분 이후 확인) 아래 dig 조회
dig +short $APIDNS
# kubectl 사용 확인
kubectl get node -v=6
kubectl cluster-info
- 노드에서 확인
# 모니터링 : tcp peer 정보 변화 확인
while true; do ssh ec2-user@$N1 sudo ss -tnp | egrep 'kubelet|kube-proxy' ; echo ; ssh ec2-user@$N2 sudo ss -tnp | egrep 'kubelet|kube-proxy' ; echo "------------------------------" ; date; sleep 1; done
# kube-proxy rollout : ss에 kube-proxy peer IP 변경 확인
kubectl rollout restart ds/kube-proxy -n kube-system
# kubelet 은 노드에서 systemctl restart kubelet으로 적용해보자 : ss에 kubelet peer IP 변경 확인
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo systemctl restart kubelet; echo; done
- 자신의 개인 PC에서 EKS API 정보 확인
# 외부이기 때문에 Cluster Endpoint 도메인 질의 시 Public IP 정보를 리턴해준다
dig +short $APIDNS
(실습 완료 후) 자원 삭제
실습 완료 후 반드시 실습 리소스를 삭제 필요. 인스턴스 비용 발생을 최소화하기 위함.
- Amazon EKS 클러스터 삭제(10분 정도 소요): eksctl delete cluster --name $CLUSTER_NAME
- (클러스터 삭제 완료 확인 후) AWS CloudFormation 스택 삭제 : aws cloudformation delete-stack --stack-name myeks