가시다님이 진행하시는 AEWS(AWS EKS Workshop Study) 내용 정리입니다. On-Premise Kubernetes 환경이 아닌 EKS(Managed Kubernetes)는 접해보지 못하였는데, 이번 기회에 학습할 수 있는 기회를 주신 가시다님에게 다시 한번 감사드립니다.
EKS 설치
개요
실습 과정은 다음과 같습니다.
- CloudFomation을 통해 작업용 EC2(Bastion) 서버와 VPC, 보안그룹 등을 생성합니다.
- 1번 과정은 생략하겠습니다.
- 작업용EC2(Bastion) 서버에서 eksctl 명령어를 이용하여 EKS를 구축합니다.
eksctl로 EKS 배포하기
- 커맨드 편의성 위해서 필요한 매개 변수들을 변수에 저장합니다.
- eksctl create cluster 명령어를 통해서 eks 클러스터를 손쉽게 생성할 수 있습니다.
- dry-run 옵션을 이용해서 실제로 클러스터를 생성하지 않고 설정을 파일로 추출하여 생성합니다.
- --name myeks : 생성할 EKS 클러스터의 이름을 지정합니다/
- --region=ap-northeast-2 : 클러스터를 생성할 AWS 리전을 지정합니다.
- --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: 클러스터에서 사용할 VPC의 CIDR 블록을 지정합니다.
- --ssh-access: SSH 접근을 허용할지 여부를 지정합니다.
- --node-ami-family Ubuntu2004: 노드 AMI 패밀리를 지정합니다.
주의!
--dry-run 옵션 없이, eksctl create cluster 명령어 입력 시, 클러스터가 생성될 수 있으므로 주의해야 사용합니다.
# IAM 인증
aws configure
AWS Access Key ID [None]: ...
AWS Secret Access Key [None]: ...
Default region name [None]: ap-northeast-2
Default output format [None]: json
# 클러스터 생성 시, 사용할 AWS 리소스들을 정보를 변수에 저장합니다.
# AWS_DEFAULT_REGION : 리전
export AWS_DEFAULT_REGION=ap-northeast-2
# CLUSTER_NAME : 배포할 EKS 클러스터명
export CLUSTER_NAME=myeks
# $VPCID : EKS 배포할 VPC 정보 확인
export VPCID=$(aws ec2 describe-vpcs --filters "Name=tag:Name,Values=$CLUSTER_NAME-VPC" | jq -r .Vpcs[].VpcId)
echo "export VPCID=$VPCID" >> /etc/profile
# PubSubnet : 퍼블릭 서브넷 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 $AWS_DEFAULT_REGION
echo $CLUSTER_NAME
echo $VPCID
echo $PubSubnet1,$PubSubnet2
eksctl create cluster --help
# 클러스터 생성파일 생성
eksctl create cluster --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.28 --ssh-access --external-dns-access --verbose 4 --dry-run > create-eks.yaml
# 클러스터 생성
eksctl create cluster -f create-eks.yaml
2024-03-08 14:41:21 [ℹ] eksctl version 0.173.0
2024-03-08 14:41:21 [ℹ] using region ap-northeast-2
2024-03-08 14:41:21 [ℹ] subnets for ap-northeast-2a - public:172.20.0.0/19 private:172.20.64.0/19
2024-03-08 14:41:21 [ℹ] subnets for ap-northeast-2c - public:172.20.32.0/19 private:172.20.96.0/19
2024-03-08 14:41:21 [ℹ] nodegroup "mynodegroup" will use "ami-008a930070f96449c" [Ubuntu2004/1.29]
2024-03-08 14:41:21 [ℹ] using SSH public key "/root/.ssh/id_rsa.pub" as "eksctl-myeks-nodegroup-mynodegroup-b1:b4:f9:bb:01:f3:63:97:f1:88:78:10:06:25:c4:39"
create-eks.yaml
추출한 eks 설정파일의 전체 내용입니다.
accessConfig:
authenticationMode: API_AND_CONFIG_MAP
apiVersion: eksctl.io/v1alpha5
cloudWatch:
clusterLogging: {}
iam:
vpcResourceControllerPolicy: true
withOIDC: false
kind: ClusterConfig
kubernetesNetworkConfig:
ipFamily: IPv4
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: true
fsx: false
imageBuilder: false
xRay: false
instanceSelector: {}
instanceType: t3.medium
labels:
alpha.eksctl.io/cluster-name: myeks
alpha.eksctl.io/nodegroup-name: myeks-nodegroup
maxSize: 2
minSize: 2
name: myeks-nodegroup
privateNetworking: false
releaseVersion: ""
securityGroups:
withLocal: null
withShared: null
ssh:
allow: true
publicKeyPath: ~/.ssh/id_rsa.pub
tags:
alpha.eksctl.io/nodegroup-name: myeks-nodegroup
alpha.eksctl.io/nodegroup-type: managed
volumeIOPS: 3000
volumeSize: 30
volumeThroughput: 125
volumeType: gp3
metadata:
name: myeks
region: ap-northeast-2
version: "1.28"
privateCluster:
enabled: false
skipEndpointCreation: false
vpc:
autoAllocateIPv6: false
cidr: 192.168.0.0/16
clusterEndpoints:
privateAccess: false
publicAccess: true
id: vpc-06c40b21abdfae5c0
manageSharedNodeSecurityGroupRules: true
nat:
gateway: Disable
subnets:
public:
ap-northeast-2a:
az: ap-northeast-2a
cidr: 192.168.1.0/24
id: subnet-07a72974368a6d569
ap-northeast-2c:
az: ap-northeast-2c
cidr: 192.168.2.0/24
id: subnet-018287d8444b8cb1d
EKS 배포 확인하기
생성된 EKS가 잘 배포되었는지, AWS Console과 Kubernetes에서 EKS와 관련된 리소스들을 확인합니다.
[ AWS Console ]
AWS CloudFormation
eksctl은 클러스터를 프로비저닝 할 때, CloudFormation을 이용한다고 합니다. EKS에서 사용하는 AWS 리소스들을 확인할 수 있습니다.
AWS EKS
버전, 네트워크, 상태 등 클러스터 정보를 조회할 수 있습니다.
AWS EC2
추가한 Node Group들이 지정한 스펙의 EC2 인스턴스로 실행 중인 것을 확인할 수 있습니다.
AWS Autoscaling Group
[ Kubernetes ]
EKS 클러스터에서 eks 관련 리소스를 확인해 보고, 데모 서비스를(슈퍼마리오 게임) 배포합니다.
클러스터 정보확인
# kubectl로 클러스터 엔드포인트 확인
kubectl cluster-info
Kubernetes control plane is running at https://16D67F92DCF2FE68B2F271366B21278B.yl4.ap-northeast-2.eks.amazonaws.com
CoreDNS is running at https://16D67F92DCF2FE68B2F271366B21278B.yl4.ap-northeast-2.eks.amazonaws.com/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
# eksctl로 클러스터 엔드포인트 확인
aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint
https://16D67F92DCF2FE68B2F271366B21278B.yl4.ap-northeast-2.eks.amazonaws.com
APIDNS=$(aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint | cut -d '/' -f 3)
# eks API 접속 시도 -> 퍼블릭 엔드포인트 엑세스이기 때문에 외부에서 접속가능!
curl -k -s $(aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint)/version | jq
{
"major": "1",
"minor": "29+",
"gitVersion": "v1.29.1-eks-508b6b3",
"gitCommit": "91af9bf4f80caa30ef9c0ad9250d2053d084968b",
"gitTreeState": "clean",
"buildDate": "2024-01-29T20:58:44Z",
"goVersion": "go1.21.6",
"compiler": "gc",
# 노드의 capacityType 확인
kubectl get node --label-columns=eks.amazonaws.com/capacityType
NAME STATUS ROLES AGE VERSION CAPACITYTYPE
ip-172-20-1-221.ap-northeast-2.compute.internal Ready 6m55s v1.29.0 ON_DEMAND
ip-172-20-46-144.ap-northeast-2.compute.internal Ready 6m55s v1.29.0 ON_DEMAND
"platform": "linux/amd64"
}
# 모든 파드의 이미지 확인 -> eks addon 이미지 확인
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/aws-network-policy-agent:v1.0.7-eksbuild.1
2 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/amazon-k8s-cni:v1.16.0-eksbuild.1
2 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/eks/coredns:v1.11.1-eksbuild.4
2 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/eks/kube-proxy:v1.29.0-minimal-eksbuild.1
데모 서비스 배포(슈퍼마리오 게임)
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/1/mario.yaml
kubectl apply -f mario.yaml
cat mario.yaml | yh
# 배포 확인 : CLB 배포 확인
kubectl get deploy,svc,ep mario
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/mario 1/1 1 1 3m27s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEservice/mario LoadBalancer 10.100.63.145 aa667b8bf6e984b2fab501fc2138f090-1168198092.ap-northeast-2.elb.amazonaws.com 80:32065/TCP 3m27s
NAME ENDPOINTS AGE
endpoints/mario 192.168.1.167:8080 3m27s
# 마리오 게임 접속 : CLB 주소로 웹 접속
kubectl get svc mario -o jsonpath={.status.loadBalancer.ingress[0].hostname} | awk '{ print "Maria URL = http://"$1 }'
Maria URL = http://aa667b8bf6e984b2fab501fc2138f090-1168198092.ap-northeast-2.elb.amazonaws.com
EKS 클러스터 삭제
과도한 요금이 발생할 수 있으니, 실습 완료 후에는, 리소스를 삭제합니다.
eksctl delete cluster --name $CLUSTER_NAME
클러스터 엔드포인트 액세스(Cluster Endpoint Access)
- 클러스터 생성 시, EKS에서는 관리형 Kuberenetes API 서버에 대한 엔드 포인트를 생성합니다.
- 클러스터 앤드포인트 액세스의 방식은 다음과 같습니다.
- 퍼블릭
- 퍼블릭 + 프라이빗
- 프라이빗
EKS owned ENI
먼저, EKS의 클러스터 엔드포인트 액세스의 네트워크 구성을 이해하기 위해서는 EKS Owned ENI라는 개념을 알 필요가 있습니다.
- EKS owned ENI는 AWS 소유의 네트워크 인터페이스입니다.
- ENI는 EKS의 각 노드에 생성되며 관리노드(AWS)와 워커노드(사용자) 간 통신을 하는 인터페이스 역할을 합니다.
- AWS가 이러한 ENI를 소유하고 관리함으로써 보안이 강화되고, 클러스터의 네트워크 관리를 단순화하고 운영을 간소화할 수 있습니다.
1. 퍼블릭(Public)
통신흐름
- 컨트롤 플레인 -> EKS owned ENI -> 워커노드
- 워커노드 -> 퍼블릭 도메인 -> 컨트롤플레인
- 클라이언트 -> 퍼블릭 도메인 -> 컨트롤플레인
2. 퍼블릭 + 프라이빗(Public + Private)
통신흐름
- 컨트롤플레인 -> EKS onwed ENI -> 워커노드
- 워커노드 -> Private Domain , EKS Owned ENI -> 컨트롤플레인
- 클라이언트 -> 퍼블릭도메인 -> 컨트롤플레인
3. 프라이빗(Private)
통신흐름
- 컨트롤플레인 -> EKS onwed ENI -> 워커노드
- 워커노드 -> Private Domain ,EKS Owned ENI -> 컨트롤플레인
- 클라이언트 -> Private Domain ,EKS Owned ENI -> 컨트롤플레인
퍼블릭 + 프라이빗(Public + Private) 적용해보기
public + private 액세스로 변경하고 설정 정보를 확인합니다.
# public
(admin-eks@myeks:N/A) [root@myeks-host ~]# APIDNS=$(aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint | cut -d '/' -f 3) AME | jq -r .cluster.endpoint
(admin-eks@myeks:N/A) [root@myeks-host ~]# dig +short $APIDNS
13.124.40.60
3.35.254.237
# Public(IP제한)+Private 로 변경 : 설정 후 8분 정도 후 반영
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
{
"update": {
"id": "a1dc0051-2aac-428d-9e5b-22d272a82402",
"status": "InProgress",
"type": "EndpointAccessUpdate",
"params": [
{
"type": "EndpointPublicAccess",
"value": "true"
},
{
"type": "EndpointPrivateAccess",
"value": "true"
},
{
"type": "PublicAccessCidrs",
"value": "[\"13.209.80.108/32\"]"
}
],
"createdAt": "2024-03-08T16:50:29.252000+09:00",
"errors": []
}
}
Public + Private 액세스로 변경 시, api-server와 통신하기 위해서는 추가적으로 기존 작업 인스턴스의 IP대역을 추가해주어야 합니다.
# kubectl 사용 확인
kubectl get node -v=6
kubectl cluster-info
# 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
# kubectl 사용 확인
kubectl get node -v=6
kubectl cluster-info
"Public + Private 액세스 방식을 통해 Public API 사용하는 사용자의 IP 대역 통제하여 사용하는 것을 적극 권장드립니다 "
'AWS > EKS' 카테고리의 다른 글
EKS 오토스케일링(Autoscaling) - AEWS 5주차 (0) | 2024.04.07 |
---|---|
EKS 옵저버빌리티(Obsivability) - AEWS 4주차 (0) | 2024.03.31 |
EKS 노드그룹(Nodegroup) - AEWS 3주차 2 (0) | 2024.03.23 |
EKS 스토리지(Storage) - AEWS 3주차 1 (0) | 2024.03.23 |
EKS 네트워킹(Networking) - AEWS 2주차 (4) | 2024.03.16 |