home..

EKS 프로비저닝하기

Kubernetes EKS AEWS Gasida Cloudnet

EKS Provisiong

이번 AEWS 스터디 에서는 Cloud Fromation을 이용해

Bastion 역할과 비슷한 EC2 Console을 생성하여 EKS를 프로비저닝 합니다.

Untitled

예전 스터디 자료처럼 다음과 같은 아키텍처로 구성됩니다.

Link

에서 그릴 수 있습니다.

CloudFormation 링크는 다음과 같습니다.

CloudFormation

해당 Cloud Formation 링크에 접속하여 필요한 IAM 역할과 작업용 EC2에 접속하기 위한 IP를 /32로 할당 해준 후 생성 진행을 합니다.

aws configure

우선 EKS 생성을 위한 자격 증명을 진행합니다.

Access Key ID, Secret Access Key를 넣고 Region을 설정해줍니다.

이후에 생성할 클러스터의 변수들을 조회 및 설정합니다.

## 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
echo $VPCID

## 퍼블릭 서브넷 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

이제 프로비저닝에 필요한 변수 값들을 다시 한번 확인해봅니다.

# 변수 확인
echo $AWS_DEFAULT_REGION
echo $CLUSTER_NAME
echo $VPCID
echo $PubSubnet1,$PubSubnet2

Untitled

해당 작업용 EC2에서는 EKSCTL을 이용해 클러스터를 생성하기로 했습니다.

EKSCTL로 클러스터를 생성하기에 앞서, dry-run 옵션을 이용해 생성하려 하는 클러스터의 정보를 얻어보는 것이 가능합니다.

eksctl create cluster -h | grep version

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 --dry-run | yh

생성하려는 클러스터의 정보를 dry-run으로 실행하면 다음과 같은 결과가 나옵니다

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-05c8bab796b9ffcda
  manageSharedNodeSecurityGroupRules: true
  nat:
    gateway: Disable
  subnets:
    public:
      ap-northeast-2a:
        az: ap-northeast-2a
        cidr: 192.168.1.0/24
        id: subnet-002518082823e72ba
      ap-northeast-2c:
        az: ap-northeast-2c
        cidr: 192.168.2.0/24
        id: subnet-08c8e0a876668b973

이제 클러스터 구성에 이상이 없음을 확인했으므로

클러스터 생성을 시작합니다.

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

위의 변수확인 과정이 선행 되어있어야 클러스터 프로비저닝이 진행이 가능합니다.

프로비저닝에는 약 15분가량의 시간이 소요됩니다.

프로비저닝이 완료되면 다음과 같은 명령어로 생성된 인스턴스들의 정보를 볼 수 있습니다.

 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

Untitled

EKS는 노드의 확장을 노드 그룹으로 진행하는데, eksctl로 생성하면서 만들어진 nodegroup은

AWS Console의 EC2 Autoscaling Group에서도 확인이 가능합니다.

Untitled

여기서 AZ별, 최소 최대 사용량등에 대한 값을 조회할수도 있습니다.

환경에따라 AWS Console에서 작업하지 않아도 되는 값들이라면 AWS CLI등 외부 환경에서도 확인 및 설정이 가능합니다.

EKS 에서의 ENI는 좀 특이한점이 있습니다.

Untitled

출처

그림에서 볼 수 있듯이, AWS Managed VPC에서의 ENI는 EKS owned ENI로 현재 프로비저닝 된 EKS Node의 ENI는 EKS owned ENI로 설정이 되어있습니다.

Untitled

계정정보는 소유자인 값이지만, 해당 ENI의 요청자 ID는 AWS측의 ID로 되어있음을 확인 할 수 있습니다. 인스턴스 소유자 또한 AWS측의 ID로 확인이 되네요

관리 편의성

Console 인스턴스 에서는 각종 Krew 패키지등 쿠버네티스를 원활하게 사용 할 수 있는 패키지들이 설치되어있습니다.

가시다님이 스터디를 진행하면서 편리성에 신경을 많이 쓴 부분들입니다.

# 자동 완성 및 alias 축약 설정
source <(kubectl completion bash)
alias k=kubectl
complete -F __start_kubectl k'

# 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

# ctx 설치
kubectl krew install ctx

# 컨텍스트 확인
kubectl ctx

# ns 설치
kubectl krew install ns

# 네임스페이스 확인
kubectl ns

# 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

자동 완성을 통해 kubectl apply -f 같은 명령어에 자동 완성으로 많은 실수를 줄일 수 있기도 하고

kubectl addon인 krew를 통해 꽤 여러가지 패키지들을 설치할 수 있습니다

위의 사례에선 ns와 ctx를 이용해 “현재 namespace” 자동완성과 “context” 고정 등의 기능을 사용하기도 합니다.

그리고 이 두 애드온은 kube-ps1을 통해 완성이 되는데,

Untitled

저런 형태로 현재 context와 namespace를 쉘 앞에서 볼 수 있어 실수를 줄일 수 있습니다.

API Endpoint 변경하기

AWS Console의 EKS 메뉴에서 확인 가능한

Untitled

control plane의 api 서버 엔드 포인트는

kubectl cluster-info에서 확인 가능한 control plane의 주소와 동일합니다.

Untitled

근데 그 API 서버는 Public으로 되어있습니다.

Untitled

API 서버 Public 주소 확인을 해보면 전부 Public으로 되어있는 것을 확인 할 수 있습니다

Untitled

Untitled

위의 AWS EKS 장표에서도 확인이 가능하지만, EKS의 Controlplane이 AWS Managed 영역에서 Public 으로 Open되어있는것을 별도로 변경 해 줄 수 있습니다.

Untitled

aws eks update-cluster-config \
--region ap-northeast-2 \
--name myeks \
--resources-vpc-config endpointPublicAccess=false,endpointPrivateAccess=true

명령어로 API Endpoint를 Private로 수정했습니다.

해당 API Endpoint 정보를 EKS내에서 업데이트하는데 시간이 소요되는데

다음과 같은 명령어로 API DNS를 조회해봅니다.

while true; do dig +short $APIDNS ; echo "------------------------------" ; date; sleep 1; done

명령어를 통해 엔드포인트를 조회했고

Untitled

public ip에서

Untitled

private ip로 변경된것을 확인할 수 있었습니다

Untitled

콘솔 에서도 프라이빗으로 변경된것을 확인할 수 있습니다.

Private ECR 만들기

AWS에서 제공하는 Public 컨테이너 이미지 레지스트리는

https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/add-ons-images.html

에서 확인이 가능하며, 서울리전의 경우

602401143452.dkr.ecr.ap-southeast-2.amazonaws.com

주소를 사용합니다.

하지만 Public ECR뿐만아니라 개인적인 Private ECR을 사용해야할경우,

aws_account_id.dkr.ecr.region.amazonaws.com 와 같은 형태로 생성해서 사용이 가능합니다.

우선 Private ECR을 생성하기 전에 Public ECR의 접근을 다뤄보겠습니다.

Public ECR Login

ecr에 로그인하기전에 docker pull 등의 작업을 할경우

Error response from daemon: Head “<이미지명>”: no basic auth credentials

에러가 발생하는데 자격증명을 한 후에 다시 시도해봅니다.

aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com

EKS Nodegroup의 IAM Role에 AmazonEC2ContainerRegistryReadOnly 의 권한이 부여되어있어 ECR에서 이미지를 가져오는 것이 가능합니다.

Untitled

하지만 Public ECR만으로는 작업을 할 수 없기에, Private ECR을 AWS CLI로 생성해줍니다.

aws ecr create-repository \
--repository-name mont-private-ecr \
--image-scanning-configuration scanOnPush=true \
--region ap-northeast-2

Private ECR을 생성한 후 데이터들을 확인해봅니다.

Untitled

# ecr 조회
aws ecr describe-repositories
aws ecr describe-images --repository-name mont-private-ecr

CLI 명령어로도 ECR에 대해서 확인이 가능하지만, 실제로 ECR에 접근하기위해선 IAM 권한을 갖고있는 상태에서 docker login을 해주어야 pull/push 가 가능합니다.

aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin <계정ID>.dkr.ecr.ap-northeast-2.amazonaws.com

Untitled

자격증명을 완료한후, 정상적으로 이미지를 pull / push 가능한것을 확인했습니다.

ECR에 Pull 과 Push 의 적절한 권한을 부여하여 최소 권한 액세스 부여 원칙을 지키는 아키텍처를 구성하는데 힘써야합니다.

© 2024 mont kim   •  Powered by Soopr   •  Theme  Moonwalk