brunch

EKS 4탄-1. EKS 클러스터 생성-1/17

2025 업데이트, EKS 생성 잘됨

by Master Seo

목표

# cf로 ec2 1대 생성, 해당 ec2에서 eksctl 사용해 쿠버네티스 생성해보자.

# 내용은 주말 CloudNet EKS 스터디 하며 , 해당 내용을 참고하여 작성 되었습니다.



# 서울리전으로 변경, 디폴트 vpc 삭제후 실습.

# ec2 key 사전 생성 - windows는 .ppk로 만든다. aws-agame-com1

# admin 권한 가진 iam-role 사전 생성 - ec2에 적용



실습


1. cloudfomation으로 EC2 1대 생성 = eksctl , kubectl , aws cli 자동설치

pubsubnet 3개 생성


2. EKSCTL로 쿠버네티스 생성 = vpc,subnet 등 변수 값으로 받아와 설치함.

사용자 네트워크에 맞는 쿠버네티스 구성이 가능해짐.

클러스터 name : first-eks




<1> EKS 클러스터 알아보자 (이론)

<2> EKS 아키텍처 이해 (이론)

<3> EKS 클러스터 생성 방법 4가지 (이론)

<4> 실습1 - Cloudformation으로 명령용 EC2생성 (실습) - eks-work-base , 1분

<5> EC2에 role 적용하기, 로그인 하기 (실습) (필수,콘솔작업)

<6> CLI로 EKS 클러스터 생성을 위해 변수 4개 지정하기 (실습,필수)

<7> 실습2 - EKS 클러스터 생성 (실습)

<8> 실습3 - 모니터링 툴인 kube-ops-view를 설치해보자 (실습)

<9> 실습4 - 시범 서비스 구성 예제

<10> 실습5 - Cloudformation으로 Private Subnet 3개와 DB 구축 (실습)

<11> EKS 클러스터 동작 확인 (실습)

<12> 실습6 - Pod생성과 접속 (실습)

<13> 실습7 - 디플로이먼트와 서비스 알아보기 (실습)

<14> 사용하지 않으면 EKS 클러스터 삭제 (실습)







<1> EKS 클러스터 알아보자 (이론)


EKS 클러스터 구축은 명령서버 생성과 EKS 클러스터 생성으로 나누어 진다.


EKS클러스터는 컨트롤 플래인(마스터 노드) + 워커노드로 구성 된다.


0 k8s.jpg




1

명령서버 생성 ?

EC2 키페어 만든다.


CloudFormation 돌려 EC2 만든다.

eks-work-host 라고 EC2가 만들어진다.

EC2에 seo-admin-role 부여한다.

여기서, 사용의 편의를 위해 VPC안에 생성 해보자.



2

EKSCTL로 쿠버네티스 생성

서비스를 하기 위한 EKS 클러스터 생성하는것이다.

클러스터가 만들어지면, Pod 생성해보자

서비스(로드밸런서)를 만들어 외부에서 접속해보자




<2> EKS 아키텍처 이해 (이론)


1

쿠버네티스는 마스터 노드(컨트롤 플래인) + 워커노드로 구성된다.

Amazon EKS는 마스터 노드는 AWS에서 운영해 준다.

EKS는 워커 노드만 사용자가 관리하면 된다.



2

개발자 사용 흐름?

EC2에 kubectl 설치 상태

EC2에서 kubectl 명령어 날림 - API Server로 명령을 날림

API Server는 Work node의 Kubelet에게 명령을 날림 , Pod등 리소스가 생성됨

개발자 PC가 직접 Work node의 Pod IP로는 연결하지는 못한다.



3

서비스 사용하는 사용자의 트래픽 흐름?

서비스 사용자 -> Work node의 kube-proxy - > Container 접속해서 서비스(Pod안에 Container 생성)



4

EKS는 기존 쿠버네티스 플러그인과 툴 모두 사용 가능하다.

온프라미스의 기존 쿠버네티스와 호환이 된다.



5

2개 VPC가 사용된다.


1) EKS Managed VPC ?

AWS에 관리하는 Control Plane이 위치한다.


2) 사용자 VPC ?

Work node와 Pod(컨테이너)가 위치한다.



6

EKS네트워크는 VPC 통합 네트워크이다.

Pod도 VPC 내부 주소대역을 같이 사용한다.

VPC 자체로 통신이 가능하다.



7

EKS VPC와 Work node가 있는 사용자 VPC와는 ENI로 연결된다.

EKS 컨트롤 플래인에서 node 접속을 할때는 ENI를 통해 접속한다.

ENI는 work node 사용자 VPC안에 위치한다.

ENI 소유는 AWS이다.


EKS Control Plane에서 실행,Logs,Proxy는 ENI를 통해 node로 연결한다.


100 node.png



8

AWS EKS는 ELB, Route53 와 연동한다.

EBS ,EFS 등 저장 스토지리와 연동한다.

IAM등 AWS 보안서비스와 연동해서 사용한다.




<3> EKS 클러스터 생성 방법 4가지 (이론)


1. EC2 나 명령PC에서 eksctl로 생성

2. 콘솔로 클릭클릭해 EKS 생성

3. AWS CloudFormation과 CDK로 생성

4. 테라폼 으로 생성



1

방법 1

EC2 나 명령PC에서 eksctl로 생성

EC2에 쿠버네티스를 설치할 eksctl 툴을 설치한다.

아마존 리눅스에 설치하는 유틸입니다.

EC2 생성시 userdata에 넣거나, EC2 설치후 실행한다.

여기 실습에서는 Cloudformation으로 만들거라 참고만 하기 바란다.


명령 pc 이름

eks-work-host




방법2

콘솔로 클릭클릭해 EKS 생성



방법 3

AWS CloudFormation과 CDK로 생성



방법 4

테라폼 으로 생성





2

# EKS는 AWS에서 쿠버네티스를 관리하는 툴이다.


Master 와 워커 노드 생성


슬라이드1.JPG



3

디플로이먼트?


배포를 관리하는 오브젝트이다.

파드를 동작시킬때 디플로이먼트 단위로 관리한다.

디플로이먼트 - 리플리카셋 - 파드 로 구성된다.

리플리카세트를 관리하고 다루기 위한 리소스이다.

프론트 앤드 서비스 적합



4

리플리카셋 컨트롤러 ?

Pod를 복제하도록 관리하는 컨트롤러

리플리카 = 복제

Pod를 몇개 운영할지 관리하는 오브젝트이다.

리플리카세트를 증가시키면 그만큼 Pod수가 증가한다.

똑같은 Pod수를 관리 및 제어한다.



5

Pod ?

파드는 IP를 가지는 서버이다.

Pod내 컨테이너들은 서로 IP를 공유한다.

파드안에 컨테이너가 여러개 운영 될 수 있다.

파드에 어플리케이션이 올라가 서비스를 한다.

nginx 컨테이너를 올리면 웹서버가 된다.



6

스테이트풀셋(StatefulSet) 컨트롤러 ?

상태를 저장해야 하는 데이터 베이스에 적합한 컨트롤러

Redis,Zookeeper,Cassandra,MongoDB 등 Master-Slave 구조 시스템

백엔드 서비스 적합

Pod와 퍼시스턴트 볼륨 조합으로 데이터의 보관에 중점을 둔 컨트롤러.

Pod와 퍼시스턴트 볼륨에 번호를 매겨 관리.



7

잡(Job) 컨트롤러 ?

배치 서비스에 적합

배치 처리하는 컨테이너를 정상 처리되도록 반복하는 컨트롤러



8

크론잡(CronJob) 컨트롤러 ?

배치 서비스에 적합

지정한 시작에 정기작업 실행.



9

데몬셋(DaemonSet) 컨트롤러 ?

시스템 운영에 적합한 컨트롤러

모든 노드에 같은 파드를 실행하기 위해 존재함.

노드가 추가 되면 dns pod가 추가되거나 모니터링 pod가 추가되도록 한다.



10

서비스?

로드밸런서 L4 , L7이라고 생각하면 된다.

Pod를 외부에 노출 시키기 위한 서비스이다.



11

구성 ?


사용자------- 서비스(L4)------디플로이먼트-리플리카세트-파드 (컨테이너)


쿠버네티스 클러스터 기반에서 운영된다.

디플로이먼트 (Deployment) = 배포 역할

리플리카세트(ReplicaSet) = 복제 역할

파드(Pod) = 컨테이너 실행 역할


10 eks.png



12

# 쿠버네티스 생성후 모니터링


watch -d kubectl get deploy,rs,pod,svc



13

# 디플로이먼트로 Pod생성법 ?

디플로이먼트 dpy-nginx


kubectl create deployment dpy-nginx --image=nginx




14

# 디플로이 먼트로 생성한 pod는 scale 가능


kubectl scale deployment dpy-nginx --replicas=3


NAME READY STATUS RESTARTS AGE

pod/dpy-nginx-858d475df8-s8jfp 1/1 Running 0 10m

pod/dpy-nginx-858d475df8-w749m 1/1 Running 0 2m54s

pod/dpy-nginx-858d475df8-x7mhx 1/1 Running 0 2m54s


NAME READY UP-TO-DATE AVAILABLE AGE

deployment.apps/dpy-nginx 3/3 3 3 10m





<4> 실습1 - Cloudformation으로 명령용 EC2생성 (실습) - eks-work-base , 1분


요약

CloudFormation 돌려 Public Subnet 3개 만든다.

CloudFormation 돌려 EC2 만든다.

EC2에 seo-admin-role 부여한다.



1

실습 구성

1 단계 Cloudformaion 사용시는 worker subnet 3개와 EC 2 1개가 만들어진다.


1 구성.png



2

AWS 개인 계정에 로그온 한다.

서울 리전에서 한다

또는

도쿄 리전에서 한다.



3

EC2에 admin role 을 주어 사용하거나, Access-key를 만들어 사용한다.

여기서는 EC2에 admin role 을 주어 사용하여, access-key는 생성하지 않는다.

admin role 만들어 ec2에 적용하여 사용한다.


iam > Roles > Create role > EC2 >

seo-admin-role



4

계정 생성 (선택)


access-key는 생성법 ?

IAM > user > eks-topasvga6-key

프로 그램 방식 Access-key 생성 > attach existing policies directly > admin 권한 부여




5

EC2 서버 접속을 위한 키 페어 생성


EC2 > 키 페어 >

aws-com4-ec2-2024-12-22



6

별도 VPC 로 명령 실행용 EC2 생성

서울 리전으로 변경


AWS CloudFormation 실행

툴까지 설치된 EC2도 자동 생성된다.




7

Cloudformation 사용


서울 리전용 EC2 생성



# 2가지 선행 조건

1) EC2 접속이 필요하므로 EC2 > Key-pair 미리 생성한다.

2) EC2에서 사용할 admin-role 을 미리 생성한다. (EC2에 권한을 주어 aws리소스를 사용할수 있도록한다.)



Stack name (필수)

eks-work-base 로 이름을 동일하게 하자 (필수)

eks-work-base

Cloudformation이용시 CLI로 클러스터 생성시 해당 Stack name사용함.



ClusterBaseName = eks-work

VPC = eks-work-vpc

EC2 = eks-work-host4



8

# 클라우드 포메이션 설정 보기

# 서울리전 상세



AWSTemplateFormatVersion: '2010-09-09'

Parameters:

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.

SgIngressCidr:

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.

EksCtlHostInstanceType:

Description: Enter t2.micro, t2.small, t2.medium, t3.micro, t3.small, t3.medium. Default is t3.small.

Type: String

Default: t3.small

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

ClusterBaseName:

Type: String

Default: eks-work

TargetRegion:

Type: String

Default: ap-northeast-2

AvailabilityZone1:

Type: String

Default: ap-northeast-2a

AvailabilityZone2:

Type: String

Default: ap-northeast-2b

AvailabilityZone3:

Type: String

Default: ap-northeast-2c

VpcBlock:

Type: String

Default: 192.168.0.0/16

WorkerSubnet1Block:

Type: String

Default: 192.168.0.0/24

WorkerSubnet2Block:

Type: String

Default: 192.168.1.0/24

WorkerSubnet3Block:

Type: String

Default: 192.168.2.0/24

Resources:

# VPC

EksWorkVPC:

Type: AWS::EC2::VPC

Properties:

CidrBlock: !Ref VpcBlock

EnableDnsSupport: true

EnableDnsHostnames: true

Tags:

- Key: Name

Value: !Sub ${ClusterBaseName}-VPC

WorkerSubnet1:

Type: AWS::EC2::Subnet

Properties:

AvailabilityZone: !Ref AvailabilityZone1

CidrBlock: !Ref WorkerSubnet1Block

VpcId: !Ref EksWorkVPC

MapPublicIpOnLaunch: true

Tags:

- Key: Name

Value: !Sub ${ClusterBaseName}-WorkerSubnet1

WorkerSubnet2:

Type: AWS::EC2::Subnet

Properties:

AvailabilityZone: !Ref AvailabilityZone2

CidrBlock: !Ref WorkerSubnet2Block

VpcId: !Ref EksWorkVPC

MapPublicIpOnLaunch: true

Tags:

- Key: Name

Value: !Sub ${ClusterBaseName}-WorkerSubnet2

WorkerSubnet3:

Type: AWS::EC2::Subnet

Properties:

AvailabilityZone: !Ref AvailabilityZone3

CidrBlock: !Ref WorkerSubnet3Block

VpcId: !Ref EksWorkVPC

MapPublicIpOnLaunch: true

Tags:

- Key: Name

Value: !Sub ${ClusterBaseName}-WorkerSubnet3

InternetGateway:

Type: AWS::EC2::InternetGateway

VPCGatewayAttachment:

Type: AWS::EC2::VPCGatewayAttachment

Properties:

InternetGatewayId: !Ref InternetGateway

VpcId: !Ref EksWorkVPC

WorkerSubnetRouteTable:

Type: AWS::EC2::RouteTable

Properties:

VpcId: !Ref EksWorkVPC

Tags:

- Key: Name

Value: !Sub ${ClusterBaseName}-WorkerSubnetRouteTable

WorkerSubnetRoute:

Type: AWS::EC2::Route

Properties:

RouteTableId: !Ref WorkerSubnetRouteTable

DestinationCidrBlock: 0.0.0.0/0

GatewayId: !Ref InternetGateway

WorkerSubnet1RouteTableAssociation:

Type: AWS::EC2::SubnetRouteTableAssociation

Properties:

SubnetId: !Ref WorkerSubnet1

RouteTableId: !Ref WorkerSubnetRouteTable

WorkerSubnet2RouteTableAssociation:

Type: AWS::EC2::SubnetRouteTableAssociation

Properties:

SubnetId: !Ref WorkerSubnet2

RouteTableId: !Ref WorkerSubnetRouteTable

WorkerSubnet3RouteTableAssociation:

Type: AWS::EC2::SubnetRouteTableAssociation

Properties:

SubnetId: !Ref WorkerSubnet3

RouteTableId: !Ref WorkerSubnetRouteTable

# EKSCTL-Host

EKSEC2SG:

Type: AWS::EC2::SecurityGroup

Properties:

GroupDescription: eksctl-host Security Group

VpcId: !Ref EksWorkVPC

Tags:

- Key: Name

Value: !Sub ${ClusterBaseName}-HOST-SG

SecurityGroupIngress:

- IpProtocol: '-1'

#FromPort: '22'

#ToPort: '22'

CidrIp: !Ref SgIngressCidr

EKSEC2:

Type: AWS::EC2::Instance

Properties:

InstanceType: !Ref EksCtlHostInstanceType

ImageId: !Ref LatestAmiId

KeyName: !Ref KeyName

Tags:

- Key: Name

Value: !Sub ${ClusterBaseName}-host

NetworkInterfaces:

- DeviceIndex: 0

SubnetId: !Ref WorkerSubnet1

GroupSet:

- !Ref EKSEC2SG

AssociatePublicIpAddress: true

PrivateIpAddress: 192.168.0.100

BlockDeviceMappings:

- DeviceName: /dev/xvda

Ebs:

VolumeType: gp2

VolumeSize: 20

DeleteOnTermination: true

UserData:

Fn::Base64:

!Sub |

#!/bin/bash

hostnamectl --static set-hostname eksctl-host4

# Install tools

yum -y install git tree tmux jq lynx htop

# Install aws cli v2

curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"

unzip awscliv2.zip

sudo ./aws/install

export PATH=/usr/local/bin:$PATH

source ~/.bash_profile

complete -C '/usr/local/bin/aws_completer' aws

# Install eksctl

curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp

mv /tmp/eksctl /usr/local/bin

# Install kubectl v1.21.2

curl -LO https://dl.k8s.io/release/v1.21.2/bin/linux/amd64/kubectl

install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl

# Install postgresql11

amazon-linux-extras install -y postgresql11

# Install the full Amazon Corretto 11

yum install java-11-amazon-corretto -y

# Install Docker

amazon-linux-extras install docker -y

systemctl start docker && systemctl enable docker

# Install nodejs

yum install -y gcc-c++ make

curl -sL https://rpm.nodesource.com/setup_14.x | sudo -E bash -

yum install -y nodejs

# Source bash-completion for kubectl

source <(kubectl completion bash)

echo 'source <(kubectl completion bash)' >>~/.bashrc

echo 'alias k=kubectl' >> ~/.bashrc

echo 'complete -F __start_kubectl k' >>~/.bashrc

# Install kubens kubectx

git clone https://github.com/ahmetb/kubectx /opt/kubectx

ln -s /opt/kubectx/kubens /usr/local/bin/kubens

ln -s /opt/kubectx/kubectx /usr/local/bin/kubectx

# Config convenience

echo 'alias vi=vim' >> /etc/profile

echo "sudo su -" >> /home/ec2-user/.bashrc

# Change localtime

sed -i "s/UTC/Asia\/Seoul/g" /etc/sysconfig/clock

ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime

Outputs:

VPC:

Value: !Ref EksWorkVPC

WorkerSubnets:

Value: !Join

- ","

- [!Ref WorkerSubnet1, !Ref WorkerSubnet2, !Ref WorkerSubnet3]

RouteTable:

Value: !Ref WorkerSubnetRouteTable

eksctlhost:

Value: !GetAtt EKSEC2.PublicIp




9

# 싱가포르 리전용 EC2 생성



# 도쿄 리전용 - EC2 생성 CloudFormation-mini




10

# 별도 VPC가 생성 된다. = eks-work-vpc 생성 됨


Public Subnet 안에 EC2가 생성된다.


# 로그온 하여 호스트 네임 변경볍.


hostnamectl --static set-hostname aws-com4

sudo su -



11

# Public 3개만 생성됨 = 192.168.x.x


eks-work-WorkerSubnet1

eks-work-WorkerSubnet2

eks-work-WorkerSubnet3


eks-work-host 생성



12

# vpc와 ec2 1개 배포 된다.

keypair는 기본적으로 만들어져 있어야 한다.

웹 콘솔로 만들어도 되고, 아래처럼 cli로 만들어도 된다.





# CLI 사용법 (참고만하세요)


1

# cli로 SSH 키페어 생성

기존에 생성되어 있는것이 있다. 생성법 참고만 하자.


aws ec2 create-key-pair --key-name eks-ssh --query 'KeyMaterial' --output text > eks-ssh.pem




2

# SSH 키페어 확인

# 콘솔에서 EC2에 role 권한을 부여 한다. 이후 아래 실행.


3

aws ec2 describe-key-pairs

aws ec2 describe-key-pairs --query 'KeyPairs[*].KeyName' --output text


MySSHKeypair=<자신의 SSH 키페어 이름>

export MySSHKeypair=$(aws ec2 describe-key-pairs --query 'KeyPairs[*].KeyName' --output text)

echo $MySSHKeypair



4

내 공인 IP 확인 (선택)

curl ifconfig.me

curl ipinfo.io

curl ipinfo.io/ip



5

# VPC , EC2를 CLI로 생성하는 법 ?


eks-work-base (필수)


# 키네임 수정 seo-key 대신 수정필요.

# SgIngressCidr=1.2.3.4/32 는 내 PC의 IP의 공인 IP 입력 = 작업용 EC2의 보안그룹에 내 IP를 허용.



aws cloudformation deploy --template-file k8s-aws-book/eks-env/01_base_resources_cfn.yaml --stack-name eks-work-base --parameter-overrides KeyName=seo-key SgIngressCidr=1.2.3.4/32



# Stack name


eks-work-base (필수)

(중요) eks-work-base으로 스택 이름을 한다 // 이 부분 아래 내용에 나오니 동일하게 하자.


KeyName

만들어진 키페어 선택


SgIngressCidr에 집 ip로 사용 (선택)- EC2 접속 소스 IP 지정

아니면 그냥 0.0.0.0/0 유지해도 된다.


CloudFormation 완료되면



6

만들어진 로그 확인


more /var/log/cloud-init-output.log




7

# 참고

# 일반 EC2 만들고 툴까지 한번에 설치하는법 (선택)


https://brunch.co.kr/@topasvga/1898





<5> EC2에 role 적용하기, 로그인 하기 (실습) (필수,콘솔작업)


1

만들어진 ec2 eks-work-host 에 admin-role을 부여한다.


EC2 > instance > eks-work-host > 오른 마우스 > 보안 > IAM 역할 수정 > seo-admin 연결한다.



2

EC2 접속


자격 권한이 잘 들어갔는지 확인

aws s3 ls

aws ec2 describe-vpcs



3

내 ip 확인 ?

aws cloudformation describe-stacks --stack-name eks-work-base --query 'Stacks[*].Outputs[3].OutputValue' --output text


// eks-work-base 이 cloudformation 이름이다.


or

curl ipconfig.io



4

라우팅 테이블, vpc , workersubnet , eksctl host 확인?


aws cloudformation describe-stacks --stack-name eks-work-base --query 'Stacks[*].Outputs' --output table








<6> CLI로 EKS 클러스터 생성을 위해 변수 4개 지정하기 (실습,필수)


CloudFormation 기반으로 변수 저장 등 추가 작업한다.


Public Subnet을 변수에 넣는다. (필수)


VpcBlock:

Default: 192.168.0.0/16


WorkerSubnet1Block: (public Subnet)

Default: 192.168.0.0/24

Default: 192.168.1.0/24

Default: 192.168.2.0/24



1

서브넷을 변수에 넣기

eks-work-base

(stack name이다)



WKSubnets=`aws cloudformation describe-stacks --stack-name eks-work-base --query 'Stacks[*].Outputs[2].OutputValue' --output text`


echo $WKSubnets


서브넷 3개 확인

subnet-70c8c8271b1,subnet-c64f7777b,subnet-0b3a183eff



2

클러스터 이름을 변수 저장 ?


export CLUSTER_NAME=first-eks

echo 'export CLUSTER_NAME=first-eks' >> ~/.bashrc

echo $CLUSTER_NAME

first-eks



3

# 리전을 변수 저장 ?


방법1

export AWS_REGION=ap-northeast-2

echo "export AWS_REGION=${AWS_REGION}" | tee -a ~/.bash_profile

aws configure set default.region ${AWS_REGION}

aws configure get default.region

echo ${AWS_REGION}




방법2


aws configure

[root@eksctl-host ~]# aws configure

AWS Access Key ID [None]:

AWS Secret Access Key [None]:

Default region name [None]: ap-northeast-2

Default output format [None]:


export AWS_REGION=$(aws configure get default.region)

echo "export AWS_REGION=$AWS_REGION" >> ~/.bashrc

echo $AWS_REGION




4

키 페어 변수 저장 (필수) ?


방법1

MySSHKeypair=master-seo-seoul-personal

echo $MySSHKeypair



방법2

MySSHKeypair=`aws ec2 describe-key-pairs --query 'KeyPairs[*].KeyName' --output text`

echo $MySSHKeypair



방법3

export MySSHKeypair=$(aws ec2 describe-key-pairs --query 'KeyPairs[*].KeyName' --output text)

echo $MySSHKeypair



SSH 키페어 확인

aws ec2 describe-key-pairs

aws ec2 describe-key-pairs --query 'KeyPairs[*].KeyName' --output text


MySSHKeypair=aws-10-30-2

echo $MySSHKeypair



5

vpc 변수 지정 ?


WKVPC=`aws cloudformation describe-stacks --stack-name eks-work-base --query 'Stacks[*].Outputs[1].OutputValue' --output text`

echo $WKVPC



6

stack에서 정보 보기

aws cloudformation describe-stacks --stack-name eks-work-base

aws cloudformation describe-stacks --stack-name eks-work-base --query 'Stacks[*]'

aws cloudformation describe-stacks --stack-name eks-work-base --query 'Stacks[*].Outputs'

aws cloudformation describe-stacks --stack-name eks-work-base --query 'Stacks[*].Outputs' --output table

aws cloudformation describe-stacks --stack-name eks-work-base --query 'Stacks[*].Outputs' --output text

aws cloudformation describe-stacks --stack-name eks-work-base --query 'Stacks[*].Outputs[2]'

aws cloudformation describe-stacks --stack-name eks-work-base --query 'Stacks[*].Outputs[2].OutputValue'

aws cloudformation describe-stacks --stack-name eks-work-base --query 'Stacks[*].Outputs[2].OutputValue' --output text



7

aws 임시 자격증명 확인 ?

aws sts get-caller-identity






<6> 실습2 - EKS 클러스터 생성 (2단계) (필수,실습)



1

# 변수 지정 확인 = 아래4개 값이 다 나와야 한다.


echo $CLUSTER_NAME

echo $WKSubnets

echo $AWS_REGION

echo $MySSHKeypair




2

생성 사전 테스트


# 생성은 하지 않고 설정 정보 출력

# 콘솔에서 새버전확인하여 새버전으로 지정한다. 1.33 버전

# node를 2개로 만든다.



eksctl create cluster --vpc-public-subnets $WKSubnets --name $CLUSTER_NAME --region $AWS_REGION --version 1.33 --nodegroup-name $CLUSTER_NAME-nodegroup --node-type t3.medium --nodes 2 --nodes-min 2 --nodes-max 6 --with-oidc --node-volume-size=20 --ssh-access --ssh-public-key $MySSHKeypair --dry-run



3

생성


eksctl create cluster --vpc-public-subnets $WKSubnets --name $CLUSTER_NAME --region $AWS_REGION --version 1.33 --nodegroup-name $CLUSTER_NAME-nodegroup --node-type t3.medium --nodes 2 --nodes-min 2 --nodes-max 6 --with-oidc --node-volume-size=20 --ssh-access --ssh-public-key $MySSHKeypair


(15분 걸림)




# 주의

공란이나 변수가 지정되지 않았을때 아래와 오류 메시지가 뜬다.

2021-08-22 21:54:23 [✖] only one argument is allowed to be used as a name


#

Node groups 명 =

$CLUSTER_NAME-nodegroup

first-eks-nodegroup



https://vclock.kr/timer/#countdown=00:10:00&enabled=0&seconds=0&sound=xylophone&loop=1

30 create-eks.png






4

# 생성 결과 확인


kubectl get nodes


[ec2-user@eksctl-host ~]$ kubectl get nodes

NAME STATUS ROLES AGE VERSION

ip-192-168-0-50.ap-northeast-2.compute.internal Ready <none> 2m6s v1.33.5-eks-113cf36

ip-192-168-1-219.ap-northeast-2.compute.internal Ready <none> 2m3s v1.33.5-eks-113cf3




Cluster

first-eks


Node groups 명 = $CLUSTER_NAME-nodegroup

first-eks-nodegroup



instance

first-eks-first-eks-nodegroup-Node

first-eks-first-eks-nodegroup-Node


t3.medium





5

# 생성 옵션들 확인 (참고)




6

JSON파일로도 만들수 있다.(참고)


https://aws-eks-web-application.workshop.aws/ko/50-eks-cluster/100-launch-cluster.html



7

참고

eksctl로 EKS 클러스터 생성시 yaml 파일로 생성도 가능하다.


https://aws-eks-web-application.workshop.aws/ko/50-eks-cluster/100-launch-cluster.html



8

# 유틸리티 설치하기


# 프롬프트 변경하기 = kube-ps1 설치 (선택)

# Install kube-ps1


sudo su -

git clone https://github.com/jonmosco/kube-ps1.git /root/kube-ps1



cat <<"EOT" >> ~/.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


source ~/.bash_profile





<7> 실습3 - 모니터링 툴인 kube-ops-view를 설치해보자 (실습)


1

node 와 pod 를 잘 볼수 있다.

1 ops-view.png



2

# kube-ops-view 설정


1

# 방법 1 - git 다운로드 설치 - 80 접속

# 파드와 노드증가를 시각화 하여 확인하는 Kubeops view 설치


$

cd

git clone https://codeberg.org/hjacobs/kube-ops-view.git

cd kube-ops-view/


kubectl apply -k deploy



2

# 외부에서 kube-ops-view를 접속하기 위해서 Service Type을 LoadBalancer 로 변경한다.


kubectl edit svc kube-ops-view


apiVersion: v1

kind: Service

metadata:

annotations:

name: kube-ops-view

spec:

....

sessionAffinity: None

type: LoadBalancer

status:

(3분 걸림)

# type: ClusterIP => type: LoadBalancer 로 수정.



# kube ops view 접속 로드 밸런서 URL 확인


watch -d kubectl get pods,deploy,svc,ep,rs


kubectl get svc kube-ops-view | tail -n 1 | awk '{ print "Kube-ops-view URL = http://"$4 }'



https://brunch.co.kr/@topasvga/1653



3

https://www.eksworkshop.com/beginner/080_scaling/install_kube_ops_view/





<8> 시범 서비스 구성 예제


1

실습은 AWS 계정의 IAM 계정으로 사용하도록 한다.

ROOT 계정으로 하지 않는다.


ROOT로 사용하지 않는 이유는 ?

IAM 사용자의 권한을 가지고, 클러스터를 생성하는데

쿠버네티스 컨트롤 플래인에서 클러스터 RBAC 의 sysyem:masters 권한을 자동으로 받게 된다.



2

VPC와 명령을 실행시킬수 있는 EC2를 만드는 Cloudformation 실행한다.

(도쿄리전 Cloud Formation 제공)


Public Subnet 3개 - Public Subnet에 EC2 1개를 만든다.

EC2에 접속한다.

여기서는 EC2에 admin role 을 주어 사용하여, access-key는 생성하지 않는다.



3

EC2에 로그온해서 서브넷 등을 변수로 지정하고, eksctl로 EKS클러스터 생성한다.



4

클라우드포메이션으로 DB생성한다.

EKS와 관련 없고, DB실습을 위해 필요 (선택)



5

시범 서비스 구성도


4-2. 서비스.jpg


6

프론트?

외부 사용자가 S3 정적 홈페이지 접속하는 구성

사용자는 Cloudfront에 접속 > S3 버킷

S3는 ELB 통해 백엔드 API로 간다.

백엔드는 뒷단의 RDS에서 정보를 가져 온다.



7

백엔드?

EKS worker node의 Pod에서비스 - ECR 사용

RDS 사용

사용자 > ELB > worker node > RDS 동작하는 구조



8

배치?

S3에 데이터 추가하면 프론트에 갱신 하는것이다.

S3에 정보를 올린다.

ELK 배치 파드가 Cron job으로 S3에서 정보를 받아와 RDS 에 저장한다.

RDS데이터를 프론트 컨테이너가 업데이트 받아 보여준다.





<9> 실습5 - Cloudformation으로 Private Subnet 3개와 DB 구축 (3단계-선택) (실습)



watch -d kubectl get no,deploy,rs,pod,svc,ep



1

DB 구축하는데 시간이 걸리므로 미리 cloudformation을 실행한다.


stack-name

eks-work-rds



RDS does not support creating a DB instance with the following combination: DBInstanceClass=db.t2.micro, Engine=postgres, EngineVersion=11.22, LicenseModel=postgresql-license. For supported combinations of instance class and database engine version, see the documentation.





2

Private subnet 3개가 생긴다.

Private subnet에 db가 구축된다.

1 구성.png



3

확인

rds > eks-work-db 확인

PostgreSQL 설치됨



4

# 상세


AWSTemplateFormatVersion: "2010-09-09"

Parameters:

EksWorkVPC:

Type: AWS::EC2::VPC::Id

WorkerSubnet1Block:

Type: String

Default: 192.168.0.0/24

WorkerSubnet2Block:

Type: String

Default: 192.168.1.0/24

WorkerSubnet3Block:

Type: String

Default: 192.168.2.0/24

ClusterBaseName:

Type: String

Default: eks-work

TargetRegion:

Type: String

Default: ap-northeast-2

AvailabilityZone1:

Type: String

Default: ap-northeast-2a

AvailabilityZone2:

Type: String

Default: ap-northeast-2b

AvailabilityZone3:

Type: String

Default: ap-northeast-2c

RdsSubnet1Block:

Type: String

Default: 192.168.3.0/24

RdsSubnet2Block:

Type: String

Default: 192.168.4.0/24

RdsSubnet3Block:

Type: String

Default: 192.168.5.0/24

Resources:

RdsSubnet1:

Type: AWS::EC2::Subnet

Properties:

AvailabilityZone: !Ref AvailabilityZone1

CidrBlock: !Ref RdsSubnet1Block

VpcId: !Ref EksWorkVPC

Tags:

- Key: Name

Value: !Sub ${ClusterBaseName}-PrivateSubnet1

- Key: kubernetes.io/role/internal-elb

Value: 1

RdsSubnet2:

Type: AWS::EC2::Subnet

Properties:

AvailabilityZone: !Ref AvailabilityZone2

CidrBlock: !Ref RdsSubnet2Block

VpcId: !Ref EksWorkVPC

Tags:

- Key: Name

Value: !Sub ${ClusterBaseName}-PrivateSubnet2

- Key: kubernetes.io/role/internal-elb

Value: 1

RdsSubnet3:

Type: AWS::EC2::Subnet

Properties:

AvailabilityZone: !Ref AvailabilityZone3

CidrBlock: !Ref RdsSubnet3Block

VpcId: !Ref EksWorkVPC

Tags:

- Key: Name

Value: !Sub ${ClusterBaseName}-PrivateSubnet3

- Key: kubernetes.io/role/internal-elb

Value: 1

RdsSecurityGroup:

Type: AWS::EC2::SecurityGroup

Properties:

GroupDescription: Security Group for RDS

VpcId: !Ref EksWorkVPC

RdsIngressPostgreSQLWorker1:

Type: AWS::EC2::SecurityGroupIngress

Properties:

GroupId: !Ref RdsSecurityGroup

CidrIp: !Ref WorkerSubnet1Block

IpProtocol: tcp

FromPort: 5432 # mysql 3306 mariadb 3396 postgresql 5432

ToPort: 5432

RdsIngressPostgreSQLWorker2:

Type: AWS::EC2::SecurityGroupIngress

Properties:

GroupId: !Ref RdsSecurityGroup

CidrIp: !Ref WorkerSubnet2Block

IpProtocol: tcp

FromPort: 5432

ToPort: 5432

RdsIngressPostgreSQLWorker3:

Type: AWS::EC2::SecurityGroupIngress

Properties:

GroupId: !Ref RdsSecurityGroup

CidrIp: !Ref WorkerSubnet3Block

IpProtocol: tcp

FromPort: 5432

ToPort: 5432

EksWorkDB:

Type: "AWS::RDS::DBInstance"

Properties:

DBInstanceIdentifier: !Sub ${ClusterBaseName}-db

Engine: postgres # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html#aws-properties-rds-database-instance-properties

EngineVersion: 11 # https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_MySQL.html#MySQL.Concepts.VersionMgmt

DBInstanceClass: db.t3.micro

AllocatedStorage: 30

StorageType: gp2

DBName: eksworkdb

MasterUsername: !Join ['', ['{{resolve:secretsmanager:', !Ref RdsMasterSecret, ':SecretString:username}}' ]]

MasterUserPassword: !Join ['', ['{{resolve:secretsmanager:', !Ref RdsMasterSecret, ':SecretString:password}}' ]]

DBSubnetGroupName: !Ref EksWorkDBSubnetGroup

PubliclyAccessible: false

MultiAZ: false

PreferredBackupWindow: 18:00-18:30

PreferredMaintenanceWindow: sat:19:00-sat:19:30

AutoMinorVersionUpgrade: false

DBParameterGroupName: !Ref EksWorkDBParameterGroup

VPCSecurityGroups:

- !Ref RdsSecurityGroup

CopyTagsToSnapshot: true

BackupRetentionPeriod: 7

DeletionProtection: false

RdsMasterSecret:

Type: AWS::SecretsManager::Secret

Properties:

GenerateSecretString:

SecretStringTemplate: '{"username": "eksdbadmin"}'

GenerateStringKey: 'password'

PasswordLength: 16

ExcludeCharacters: '"@/\'''

Name: RdsMasterSecret

RdsUserSecret:

Type: AWS::SecretsManager::Secret

Properties:

GenerateSecretString:

SecretStringTemplate: '{"username": "mywork"}'

GenerateStringKey: 'password'

PasswordLength: 16

ExcludeCharacters: '"@/\''{}#%&*<>[]^`|'

Name: RdsUserSecret

RdsSecretAttachment:

Type: AWS::SecretsManager::SecretTargetAttachment

Properties:

SecretId: !Ref RdsMasterSecret

TargetId: !Ref EksWorkDB

TargetType: AWS::RDS::DBInstance

EksWorkDBSubnetGroup:

Type: AWS::RDS::DBSubnetGroup

Properties:

DBSubnetGroupName: subnet-group-eks-work-db

DBSubnetGroupDescription: "DB Subnet Group"

SubnetIds:

- !Ref RdsSubnet1

- !Ref RdsSubnet2

- !Ref RdsSubnet3

EksWorkDBParameterGroup:

Type: AWS::RDS::DBParameterGroup

Properties:

Family: postgres11 # aws rds describe-db-engine-versions --query "DBEngineVersions[].DBParameterGroupFamily"

Description: Parameter Group for PostgreSQL 11

Outputs:

RDSEndpoint:

Value: !GetAtt EksWorkDB.Endpoint.Address




<10> EKS 클러스터 동작 확인 (실습)


1

노드 IP 정보 확인

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 |

+-------------------------------------+----------------+-----------------+-----------+

| eks-work-host | 192.168.0.100 | 3.36.85.65 | running |

| first-eks-first-eks-nodegroup-Node | 192.168.1.191 | 3.35.7.233 | running |

| first-eks-first-eks-nodegroup-Node | 192.168.2.158 | 13.125.246.247 | running |

+-------------------------------------+----------------+-----------------+-----------+




2

터미널 하나 더 띠우기

모니터링하기


watch -d kubectl get pods,deploy,svc,ep,rs


or


watch -d 'kubectl get deploy,pods,svc,ep -o wide'

watch -d 'kubectl get all -o wide'


서비스 / 쿠버네티스 1개

엔드포인트 / 쿠버네티스 1개 보임




3

// ec2에서 node에 접속 되도록 rule 추가


# 노드 보안그룹 ID 확인

NGSGID=`aws ec2 describe-security-groups --filters Name=group-name,Values=*nodegroup* --query "SecurityGroups[*].[GroupId]" --output text`

echo $NGSGID


# 노드 보안그룹에 작업용 EC2인 eksctl-host 에서 노드(파드)에 접속 가능하게 룰(Rule) 추가 설정

작업용 EC2인 eksctl-host ip 가 192.168.0.100/32 이다.

모든 트래픽을 허용하는 룰이다.


aws ec2 authorize-security-group-ingress --group-id $NGSGID --protocol '-1' --cidr 192.168.0.100/32


# eksctl-host 에서 파드나 노드로 ping, curl 테스트 해보자. 잘 된다.

ping <pod IP>





<11> 실습6 - Pod생성과 접속 (실습)


슬라이드2.JPG


1

watch -d kubectl get no,deploy,rs,pod,svc,ep



# 테스트

# 공개된 nginx image로 pod를 만든다.



cat <<EOF | kubectl create -f -

apiVersion: v1

kind: Pod

metadata:

name: nginx-pod

labels:

app: nginx-app

spec:

containers:

- name: nginx-container

image: nginx

ports:

- containerPort: 80

EOF




2

서비스 / 쿠버네티스 - 1개

엔드포인트 / 쿠버네티스 - 1개

생성된 Pod/nginx-pod - 1개 보임


watch -d 'kubectl get deploy,rs,pod,svc,ep'




3

# 포트 포워딩 설정 - 터미널 1

kubectl port-forward nginx-pod 8080:80


[root@eksctl-host ~]# kubectl port-forward nginx-pod 8080:80

Forwarding from 127.0.0.1:8080 -> 80

Forwarding from [::1]:8080 -> 80

// 실행시킨 상태에서 다른 터미널에서 curl 테스트

// 호스트 8080포트를 내부 80 포트와 매칭시킴



4

# 터미널 2


# cul 접속

curl localhost:8080


혹은


lynx -dump localhost:8080


[root@eksctl-host ~]# curl localhost:8080

<!DOCTYPE html>

<html>

<head>

<title>Welcome to nginx!</title>

<style>

body {



5

kubectl get pods


[root@eksctl-host ~]# kubectl get pods

NAME READY STATUS RESTARTS AGE

nginx-pod 1/1 Running 0 3m55s



6

# 파드 삭제

kubectl delete pod nginx-pod





<12> 실습7 - 디플로이먼트와 서비스 알아보기 (실습)


디플로이먼트에 대해 알아보자


서비스 = 로드밸런서에 대해 알아보자.

외부에서 접속 하려면 서비스가 있어야 한다.

서비스는 로드밸런서 L4라고 생각하면 된다.



1

디플로이먼트와 컨테이너 구성 확인

슬라이드2.JPG


2

터미널2에서 모니터링

watch -d 'kubectl get deploy,pods,svc,ep,rs -o wide'



3

디플로이먼트 생성?

nginx 이미지로 websrv pod를 만들어보자~

kubectl create deployment websrv --image=nginx --port=80 --replicas=4



// 디플로이먼트 1개와 replicaset 1개, pos 4개가 생성된다.


디플로이먼트 1개

replicaset 1개

Pod 4개 보임

서비스 / 쿠버네티스 1개 - 기존에 있던것

엔드포인트 / 쿠버네티스 - 기존에 있던것





4

서비스 생성 ?

Pod를 외부에 노출하기 위한 부분.

L4라고 생각하면 된다.


# websrv 파드용 로드밸런서 생성


kubectl expose deployment websrv --port=80 --type=LoadBalancer

service/websrv exposed


(10분 걸림)

service/websrv LoadBalancer 1개 생긴다. CLB

endpoints/websrv 1개가 생긴다.





5

서비스 도메인에 대해 DNS 질의해 본다.


[root@eksctl-host ~]# dig ac2858703ca324ce08f7148e9b9d3199-1519822352.ap-southeast-1.elb.amazonaws.com +short

18.136.113.95

52.220.131.89

18.138.120.46



6

웹 접속 - 웹 브라우저에서 External-IP 로 접속


420 welcome to enginx.png

7

서비스 확인

kubectl get svc



8

서비스 정보 확인


kubectl describe svc websrv

Name: websrv

Namespace: default

Labels: app=websrv

Annotations: <none>

Selector: app=websrv

Type: LoadBalancer

IP Family Policy: SingleStack

IP Families: IPv4

IP: 10.100.51.215

IPs: 10.100.51.215

LoadBalancer Ingress: a89ea0383fe-331818142.ap-southeast-1.elb.amazonaws.com

Port: <unset> 80/TCP

TargetPort: 80/TCP

NodePort: <unset> 32179/TCP

Endpoints: 192.168.1.15:80,192.168.2.127:80

Session Affinity: None

External Traffic Policy: Cluster

Events: <none>



9

서버수(pod수) 조절

kubectl scale deployment websrv --replicas=2



10

접속자 IP 확인 ?


아래 명령서 실행시키로 웹브라우저로 서비스 접속해본다.

아래처럼 로그가 나온다.

kubectl logs -l app=websrv -f --max-log-requests 8


참고로 , 접속자 ip 는 192.168.x.x 로 EKS 네트워크 IP로 보인다~




11

실습 - 게임 만들기



https://brunch.co.kr/@topasvga/1868



12

삭제


kubectl delete deploy,svc websrv

deployment.apps "websrv" deleted

service "websrv" deleted



13

kubeconfig ?

eksctl은 클러스터 구축중에 kubeconfig 파일을 자동 업데이트 한다.

eksctl이 이용할 설정 파일이다.

접속 정보를 저장 한다.

컨트롤 플레인 URL , 인증정보 , 네임스페이스등 저장한다.


k config get-contexts





<13> 사용하지 않으면 EKS 클러스터 삭제 (실습)


1

자동 삭제

Cloud formation 에서 삭제



2

수동 삭제

EC2 > Auto Scaling Groups 삭제


3

EKS 가서 리소스 있으면 삭제


4

EC2 가서 리소스 있으면 삭제




참고

https://brunch.co.kr/@topasvga/1679




다음 과정 = EKS 데이터베이스,백엔드,프론트 구축


https://brunch.co.kr/@topasvga/1818

keyword