brunch

You can make anything
by writing

C.S.Lewis

by Master Seo Aug 22. 2021

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

2021년 자료- 2024년 12월 업데이트

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




실습 

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

pubsubnet 3개 생성


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

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

클러스터 name : first-eks




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

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

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

<4> 실습1 - Cloudformation으로으로 명령용 EC2  생성 (실습)

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

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

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

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

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

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

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

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

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

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






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


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

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


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 Contraol Plane에서 실행,Logs,Proxy는 ENI를 통해 node로 연결한다.




8

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

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

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




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



1

방법 1

콘솔로 클릭클릭해 EKS 생성



방법 2

EC2 나 명령PC에서 eksctl로 생성  ?

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

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

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

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




방법 3

AWS CloudFormation과 CDK로 생성 



방법 4

테라폼 으로 생성 





2

# 이론  -  쿠버네티스 기초를 알아보자~

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



Master 와 워커 노드 생성




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)------디플로이먼트-리플리카세트-Pod(컨테이너) ]

                  [ 쿠버네티스 클러스터 ]


Deployment = 배포 역할

ReplicaSet = 복제 역할

Pod = 컨테이너 실행 역할



12

# 모니터링


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



# 디플로이먼트로 Pod생성 ?  , 디플로이먼트  dpy-nginx


kubectl create deployment dpy-nginx --image=nginx



# 디플로이 먼트로 생성한 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  생성 (실습)


요약

CloudFormation 돌려 Public Subnet 3개 만든다.

CloudFormation 돌려  EC2   만든다.

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



1

실습 구성

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




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 생성


EC2이므로  EC2 > Key-pair 미리 생성한다.

EC2에서 사용할 admin-role 을 미리 생성한다.



Stack name   (필수)

eks-work-base   동일하게 필수 -  Cloudformation이용 CLI로 클러스터 생성시 해당 Stack name사용함

eks-work-base  


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 만들고 Tool 설치하는법  (선택)


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




# 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








<5> 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





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

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


echo $CLUSTER_NAME

echo $WKSubnets

echo $AWS_REGION

echo $MySSHKeypair




2

생성 사전 테스트


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

1.31 버전

node를 2개로 만든다.



eksctl create cluster --vpc-public-subnets $WKSubnets --name $CLUSTER_NAME --region $AWS_REGION --version 1.31  --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.31 --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





4

생성 결과


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

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 를 잘 볼수 있다.



2

#  kube-ops-view 설정  


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

시범 서비스 구성도



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가 구축된다.



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생성과 접속   (실습)



1

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



테스트


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

터미널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라고 생각하면 된다.


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 로 접속


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




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


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

브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari