본 게시물은 CloudNet@에서 진행하는 AEWS (Amazon EKS Workshop Study) 스터디에 참여하며 정리한 내용입니다.

 

1. Amazon EKS 소개

Amazon EKS 사용자 가이드 공식 문서 (링크)에 따르면, Amazon Web Services (AWS)에서 제공하는 관리형 서비스로, Kubernetes (쿠버네티스) 컨트롤 플레인을 설치, 운영 및 유지 관리할 필요가 없는 "관리형 서비스"라고 설명되어 있다. 쿠버네티스 클러스터 아키텍처가 설명된 오픈 소스 쿠버네티스 문서 (링크)에 컨트롤 플레인에 대한 그림이 있다.

위 이미지에서 나온 컨트롤 플레인에 보면 cloud-controller-manager, etcd, kube-api-server, scheduler, Controller Manager 이렇게 5개 요소가 있는데, 해당 요소를 직접 설치하여 관리하는 대신 Amazon EKS라는 관리형 서비스를 생성하여 쿠버네티스 노드들을 활용하게 된다. 자세한 내용은 EKS 워크샵 설명(링크)에도 있으니 이를 참고하자.

 

쿠버네티스 오픈 소스는 https://github.com/kubernetes/kubernetes/releases 링크를 통해서도 새로 업데이트된 버전을 확인할 수가 있는데, 이 버전 번호에 대한 자세한 설명은 링크에서도 확인 가능하다.

 

x.y.z | x: 메이저 버전, y: 마이너 버전, z: 패치 버전

 

2. EKS 워크샵 실습 환경 소개 및 작업용 EC2 구성

본 스터디에서는 EKS 워크샵에 있는 "AWS 계정으로 시작"에 따라 스터디 시작 전 미리 AWS 계정을 준비하였으며, 실습 환경 구축에 보면 AWS Cloud9부터 kubectl 설치, eksctl 설치 등이 있는데 스터디장이신 가시다님께서 준비해 주신 AWS CloudFormation을 사용하여 편하게 스터디 참여를 할 수가 있었다. EKS 버전은 스터디를 진행하고 있는 2024년 3월을 기준으로 EKS 지원 add-on 및 K8s 생태계와 가장 잘 호환되고 검증된 애플리케이션이 많은 버전인 v1.28을 선택하여 진행하였다. 스터디 진행하는 AWS 환경을 이해해볼 겸 AWS 아키텍처 아이콘을 참고하여 아래와 같이 도식화해보았다.

 

아래와 같이 CloudFormation 템플릿을 다운로드 받은 다음에 AWS CLI (링크)를 사용해 실행해 보았다.

$ curl -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/K8S/myeks-1week.yaml
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 10373  100 10373    0     0   180k      0 --:--:-- --:--:-- --:--:--  180k
$ aws cloudformation deploy --template-file myeks-1week.yaml --stack-name myeks --parameter-overrides KeyName=kp-ian SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32 --region ap-northeast-2

Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - myeks

 

이후 다음 명령어를 실행하면 IP 주소를 알 수 있으며, 이 IP 주소로 SSH를 실행하여 Shell 로 접속하여 이후 작업을 진행한다. 접속할 SSH ID 및 Password는 위 CloudFormation 템플릿 파일에 있으니 참고하자.

aws cloudformation describe-stacks --stack-name myeks --query 'Stacks[*].Outputs[*].OutputValue' --output text

 

작업용 EC2에 접속하였다면 IAM 사용자 자격 구성이 필요하다. 실습 편의를 위해 administrator 권한을 가진 IAM User의 자격 증명을 입력한다.

[root@myeks-host ~]# aws ec2 describe-instances

Unable to locate credentials. You can configure credentials by running "aws configure".
[root@myeks-host ~]# aws configure
AWS Access Key ID [None]: AKI..........
AWS Secret Access Key [None]: FQ.......................
Default region name [None]: ap-northeast-2
Default output format [None]: json
[root@myeks-host ~]# aws ec2 describe-instances
{
    "Reservations": [
        {
            "Groups": [],
            "Instances": [
                {
                    "AmiLaunchIndex": 0,
                    "ImageId": "ami-025cebb6913219d99",...........

 

3. eksctl로 클러스터 생성하기

EKS 워크샵 내용 (링크)에서는 yaml 파일을 작성하여 eksctl 명령어로 클러스터를 생성하는데, 기본적인 옵션을 직접 eksctl 명령어에 적절한 파라미터 형태로 전달하는 방식 또한 가능하여 스터디에서는 이 방법을 사용해 보았다. 필요한 옵션 값을 환경 변수로 저장하여 활용하였다.

3.1. 필요한 환경 변수 준비하기

$AWS_DEFAULT_REGION 및 $CLUSTER_NAME은 작업용 EC2에서 이미 준비가 되어 있다. 이를 확인해보고 나머지 환경 변수에 대해 설정해보았다.

[root@myeks-host ~]# echo $AWS_DEFAULT_REGION
ap-northeast-2
[root@myeks-host ~]# echo $CLUSTER_NAME
myeks
[root@myeks-host ~]# export VPCID=$(aws ec2 describe-vpcs --filters "Name=tag:Name,Values=$CLUSTER_NAME-VPC" | jq -r .Vpcs[].VpcId)
[root@myeks-host ~]# echo "export VPCID=$VPCID" >> /etc/profile
[root@myeks-host ~]# export PubSubnet1=$(aws ec2 describe-subnets --filters Name=tag:Name,Values="$CLUSTER_NAME-PublicSubnet1" --query "Subnets[0].[SubnetId]" --output text)
rt 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
[root@myeks-host ~]# export PubSubnet2=$(aws ec2 describe-subnets --filters Name=tag:Name,Values="$CLUSTER_NAME-PublicSubnet2" --query "Subnets[0].[SubnetId]" --output text)
[root@myeks-host ~]# echo "export PubSubnet1=$PubSubnet1" >> /etc/profile
[root@myeks-host ~]# echo "export PubSubnet2=$PubSubnet2" >> /etc/profile
[root@myeks-host ~]# echo $VPCID
vpc-06019251cc08c519b
[root@myeks-host ~]# echo $PubSubnet1,$PubSubnet2
subnet-09c63523c434bcaec,subnet-0244ef5fa73c2f986

3.2. 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.28 --ssh-access --external-dns-access --verbose 4​

 

총 15-20분 정도 소요되니 잠시 기다려보자. 기다리는 동안에 다른 터미널을 1개 더 열어 아래 명령어를 실행하면 클러스터가 생성되었는지 여부를 확인하는 데 도움이 된다.

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 콘솔에서도 EKS가 배포된 내용을 확인할 수 있다 (혹 콘솔에서 갱신이 안되었다면 새로고침 버튼을 클릭해보자).

 

EKS 클러스터 생성이 완료가 된 이후부터는 kubectl 명령어를 통해 EKS 클러스터에 여러 명령을 실행할 수 있게 된다. 스터디 중 여러 가지를 실행해보면서 많은 것들을 확인을 하였는데, 그 중 한 가지만 블로그에 정리해 보고자 한다.

4. 생성된 EKS 클러스터 확인 - 엔드포인트 액세스 변경 (Public -> Public and private)

EKS 클러스터 정보를 확인하기 위해서는 "kubectl cluster-info" 라는 명령어를 사용하면 된다.

(awesian@myeks:N/A) [root@myeks-host ~]# eksctl get nodegroup --cluster $CLUSTER_NAME --name $CLUSTER_NAME-nodegroup
CLUSTER NODEGROUP       STATUS  CREATED                 MIN SIZE        MAX SIZE        DESIRED CAPACITY        INSTANCE TYPE   IMAGE ID        ASG NAME              TYPE
myeks   myeks-nodegroup ACTIVE  2024-03-09T18:02:34Z    2               2               2                       t3.medium       AL2_x86_64      eks-myeks-nodegroup-eac71230-bb27-1b00-6c14-e2c96dfc5646       managed
(awesian@myeks:N/A) [root@myeks-host ~]# kubectl cluster-info
Kubernetes control plane is running at https://088CD22A78682CF5F017CFEE329E3C1A.gr7.ap-northeast-2.eks.amazonaws.com
CoreDNS is running at https://088CD22A78682CF5F017CFEE329E3C1A.gr7.ap-northeast-2.eks.amazonaws.com/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

뿐만 아니라 "eksctl get cluster" 명령어로도 확인이 가능하다. 한 가지 특이했던 점은 생성된 엔드포인트가 public이라는 것이다. Public이라는 의미는 해당 endpoint에 대한 네트워크 연결이 가능하다는 것을 의미하며, 해당 엔드포인트를 통해 Pod 생성 등을 진행하려면 추가 인증이 필요하나 간단한 version 확인은 public일 경우 별도의 인증을 거치지 않아도 위와 같이 생성한 EKS 클러스터에는 접근이 가능하였다.

콘솔에서 확인해 보더라도 API 서버 엔드포인트 액세스가 "Public"으로 나와있는 상황이다.

이를 "퍼블릭 및 프라이빗"으로 변경해보자. 변화 감지를 위해 총 3개의 터미널을 사용해보자. 2개 터미널은 모니터링 목적으로 사용한다.

# 터미널 A - 모니터링용 1
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

# 터미널 B - 모니터링용 2
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

# 터미널 C - Public(본인 접속 IP만 제한)+Private 로 변경. 설정 후 약 8-10분 정도 이후 다른 터미널에 변화 감지 가능
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

기다려보면 터미널 A에서 2개의 public IP 로 보이던 부분이 갑자기 내부 네트워크 서브넷으로 변경된 부분을 확인할 수 있었다.

그런데 오른쪽은 변화가 없었는데, 이는 Public 및 Private 모두 활성화되다보니 기존 kube-proxy 및 kubelet이 이미 연결을 맺고 있는 네트워크 연결을 굳이 종료할 필요가 없어서가 아닌가 생각된다.

 

이후 "kubectl" 명령어를 실행하면 동작하지 않는다. 다음과 같이 실행해보면 오류 메시지와 함께 보이는 IP 주소가 Public IP가 아니라는 것을 확인할 수 있다. 즉, 클러스터 설정이 변경되면서 이제는 Private IP로 Endpoint를 반환하는 것이다.

(awesian@myeks:N/A) [root@myeks-host ~]# kubectl get node -v=6
I0310 03:44:52.743735   18383 loader.go:395] Config loaded from file:  /root/.kube/config
I0310 03:45:23.611890   18383 round_trippers.go:553] GET https://088CD22A78682CF5F017CFEE329E3C1A.gr7.ap-northeast-2.eks.amazonaws.com/api/v1/nodes?limit=500  in 30861 milliseconds
I0310 03:45:23.612005   18383 helpers.go:264] Connection error: Get https://088CD22A78682CF5F017CFEE329E3C1A.gr7.ap-northeast-2.eks.amazonaws.com/api/v1/nodes?limit=500: dial tcp 192.168.1.51:443: i/o timeout
Unable to connect to the server: dial tcp 192.168.1.51:443: i/o timeout
(awesian@myeks:N/A) [root@myeks-host ~]# kubectl cluster-info

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
Unable to connect to the server: dial tcp 192.168.2.122:443: i/o timeout

 

접속이 안된다는 것은 EKS Control plane 보안 그룹에서 서브넷에 접속 가능하도록 추가 설정을 해주어야 함을 의미한다. 다음 명령어를 통해 노드 보안 그룹에 myeks-host에서 노드(파드)에 접속 가능하도록 룰을 추가 설정하였다.

# 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

# 노드 보안그룹에 myeks-host 에서 노드(파드)에 접속 가능하게 룰(Rule) 추가 설정
aws ec2 authorize-security-group-ingress --group-id $CPSGID --protocol '-1' --cidr 192.168.1.100/32

또한 kubelet과 kube-proxy도 private IP 주소로 접속하도록 설정을 변경해보자. 다음 명령어를 실행한다.

# kube-proxy rollout
kubectl rollout restart ds/kube-proxy -n kube-system

# kubelet 은 개별 노드에서 systemctl restart kubelet을 실행하는 형태로 적용. $N1과 $N2 환경 변수가 설정되어 있어야 함.
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo systemctl restart kubelet; echo; done

위 첫 번째 명령어를 실행한 다음에는 kube-proxy에 대한 연결이 private IP로 이루어지는 것을 볼 수 있으며,

두 번째 명령어가 잘 실행되면 kubelet 또한 연결이 private IP로 이루어지는 것을 볼 수 있다.

5. 리소스 정리

실습을 완료한 다음에는 반드시 리소스를 삭제하여 불필요한 비용 발생을 최소화하도록 하자.

  • Amazon EKS 클러스터 삭제하기 (약 10분 정도 소요): eksctl delete cluster --name $CLUSTER_NAME
  • 위 과정이 완료된 후 AWS CloudFormation 스택 삭제하기: aws cloudformation delete-stack --stack-name myeks

(Recovered from my old article - originally posted on 2017.03.14 10:28 KST)

 

(참고: 영문 버전은 http://sdndev.net/11에서 확인하실 수 있습니다.)

 

지난 1회 업스트림 트레이닝에 이어 2017년 2월 11일 (토), 오전 10시부터 오후 5시까지

OpenStack 두 번째 로컬 업스트림 트레이닝 행사를 개최하였다.

 

올해는 OpenStack Days Korea 2017 행사를 7월 중순에 개최 예정이기에,

이번 두 번째 업스트림 트레이닝은 지난번 보다 길게, 토요일 오전 & 오후로 진행하는 식으로 계획하였으며,

실제 모집 및 진행하였던 상세 내역은 http://openstack-kr.github.io/upstream-training/2017/ 참고.

 

아무래도 지난 첫 업스트림 트레이닝과 달리 보다 길게 진행하기에

지난 업스트림 트레이닝보다 많은 분들께서 도와주셔야 행사를 잘 치를 수 있을 것 같은 생각에

이번에는 작년 11월에 업스트림 트레이닝 진행을 위한 스터디를 커뮤니티에서 모집하였고,

많은 분들이 참여해 주셨으며, 또한 업스트림 트레이닝에 멘토로 도와주셔서 행사를 잘 마칠 수 있었다고 생각한다.

 

(스터디 내용 참고: https://github.com/openstack-kr/openstack-study/tree/master/2016-fall-upstream )

 

- 업스트림 스터디 사진 #1 -

 

- 업스트림 스터디 사진 #2 -

 

 

평소에 오픈스택 스터디를 진행하면서 토즈 공간을 많이 이용하였으나,

이번 업스트림 트레이닝 때는 참가 인원을 30명 규모로 생각하였으며, 멘토링 및 실습 등을 위해 넉넉한 공간이

있으면 좋겠다고 생각하여 어떻게 하면 좋을지 많은 고민이 있었다.

다행히 이전에 여러 실습 등을 많이 치렀던 우분투 한국 커뮤니티에서 업스트림 트레이닝에서 다루는

Launchpad (오픈 소스 버그 트래킹 및 개발을 위해 우분투에서 많이 사용함, https://launchpad.net/ )도

같이 살펴볼 겸하여 공동 개최를 하기로 결정하였다.

또한 네이버 D2에서 공간 대여 가능한 D2 Startup Factory를 흔쾌히 대여 허락해 주셔서 스터디도 많은 분들과

재미있게 같이 하면서 필요한 행사 콘텐츠 및 모집 등을 차근차근 함께 진행해 나갈 수 있었다.

 

그러나.. 행사 4일 전 마지막 스터디에서 행사 진행 준비를 논의하던 중...

두둥! D2에 멀티탭이 없을 수도 있다는 사실을 인지하기 시작했다.

수, 목에 열심히 알아보았으나 안타깝게도 D2에서 여분의 멀티탭이 없었다.

그렇다고 행사 이틀 전에 장소를 바꿀 수는 없기에.. 이곳저것 수소문한 덕택에 도움을 주신 두 곳이 있다.

 

1. 나임네트웍스 (http://www.naimnetworks.com/)

본인이 2013년 10월~2014년 8월까지 재직하였던 회사로 나임아카데미 등 교육도 진행을 같이 하기에

혹시나 싶어 회사 전 동료 및 팀장님 (지금은 본부장님이라고 하심)께 여쭈어보니 남는 여분이 있으면 가능할 것 같다고 하셨으며, 정말 다행히 그 시기에 서버 rack에서 떼놓은 14구 멀티탭이 3개인가 있어 흔쾌히 빌려주셨다.

 

- 멀티탭 14구의 위엄! (Thanks to NAIM Networks, Korea) -

 

 

2. 모두의연구소 (http://modulabs.co.kr/)

2015년 초, 인공지능 스터디를 참여하였던 적이 있는데 그 때 현재 모두의연구소 소장님이신 김승일 님을 알게 되었다. 연구소 취지가 좋다고 생각하여, 시간이 허락될 때 스터디 하나를 직접 참가하고 싶은 마음이 크지만, 현실적으로 오픈스택을 보면서 모두의 연구소에서 하는 부분까지 살펴보는 건 참으로 쉽지 않은 것 같다. 소장님께서도 외부 교육 등을 많이 진행하시기에 물어보았으며, 금요일 오전에 연락되어 소장님께선 연구소에 안 계시지만 다른 분의 도움을 받아 힘들게 멀티탭 6구를 여러 개 대여할 수 있었다.

 

이러한 준비 + 많은 분들의 도움 덕택에 이번 2회 업스트림 트레이닝은 지난 번 1회때보다 구체적인 목표를 갖고

여러 질문 & 답변과 함께 재미있는 시간을 보낼 수 있었다고 생각한다.

 

- 제2회 업스트림 트레이닝 행사 끝나고 단체 사진 -

 

- 실습 중 -

 

- Etherpad를 사용한 설명 중 -

 

- 쉬는 시간이지만 토의중 -

 

- 즐거운 토론 중 -

 

 

다음 업스트림 트레이닝 행사도 잘 진행되면 좋을 것 같은데.. D2의 도움도 계속 필요할 것 같고

무엇보다 여러 멘토 분들과 함께하였지만 사실 혼자 Full로 진행하기에는 다소 지치는 측면도 있어..

보다 많은 한국 분들께서 오픈스택 업스트림에 기여하시고, 그 경험을 바탕으로 같이 즐겁게 차후 행사를 할 수 있으면 정말 좋을 것 같다는 생각을 해본다.

 

+ Recent posts