연재 시리즈

pkos 스터디 1주차 - aws에 kops클러스터 생성

악분 2023. 3. 8. 22:55
반응형

1주차 주제

1주차에서는 kops를 사용하여 AWS에 쿠버네티스를 설치하는 실습을 진행했습니다. 2주차부터는 쿠버네티스가 설치된 전제로 스터디를 진행합니다. 그래서 1주차는 쿠버네티스 설치를 목표로 한 것 같습니다.

 

kops를 사용한 이유는, 스터디장이 언급하신 것처럼 학습 목적에 적합했습니다. 쿠버네티스 클러스터 생성 도구를 다루면서 애드온(예: AWS 로드 밸런서 컨트롤러 등)이 지원이 필요했습니다. kops가 이 요구조건에 만족하여 스터디에 kops가 선택된 것 같습니다.

 

kops의 또 다른 장점은 쿠버네티스 클러스터 설치 이후에도 kops를 이용하여 클러스터 설정을 수정할 수 있습니다.

 

실습에 필요한 것

kops를 사용할 리눅스 쉘과 IAM 사용자 또는 역할, (구매한)도메인이 필요합니다.

 

  • 리눅스 쉘

kops명령어를 사용할 리눅스 쉘이 필요합니다. kops가 설치되어 있어야 하며, IAM 사용자 또는 역할을 가지고 있어야 합니다. kops는 AWS 리소스를 관리하기 때문에 AWS IAM 사용자 또는 역할은 적절한 권한이 필요합니다. 권한 설정은 공식 문서를 참고해 주세요.

# 공식문서 링크: https://kops.sigs.k8s.io/getting_started/aws/#setup-iam-user
AmazonEC2FullAccess
AmazonRoute53FullAccess
AmazonS3FullAccess
IAMFullAccess
AmazonVPCFullAccess
AmazonSQSFullAccess
AmazonEventBridgeFullAccess

 

  • (구매한) 도메인

kops는 쿠버네티스를 생성하고 DNS 레코드를 사용해서 API Server 도메인을 생성합니다. 따라서 도메인을 준비해야합니다. AWS Route53에서 직접 도메인을 구매할 수 있지만, 가격이 비쌉니다. 가격이 저렴한 곳에서 도메인을 구매하고 AWS Route53에 등록하는 것을 추천합니다.

 

인프라 구조

kops도구를 사용할 EC2 instance(kops-ec2)와 S3, route53이 기본 구조입이다. kops도구는 쿠버네티스 클러스터를 생성하면 EC2 Instance와 여러 aws리소스를 생성합니다.

 

 

kops 사용 준비

kops 설치된 EC2 Instance 생성

EC2 인스턴스를 생성하고 kops를 설치했습니다. 스터디장님이 이 복잡한 과정을 cloudformation으로 자동화해주셨습니다. cloudformation을 사용하기 위해 EC2 pair key가 필요합니다.

cloudformation메뉴에서 create stack페이지로 이동합니다. 그리고 템플릿 url을 입력하고 다음 단계로 넘어갑니다.

템플릿 링크: https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/K8S/kops-new-ec2.yaml

 

미리 준비한 EC2 key pair를 입력하고 다음 단계로 넘어갑니다.

 

Next 버튼을 계속 눌러 CloudFormation 템플릿을 제출하고 스택을 생성합니다.

 

cloudformation 스택이 성공적으로 생성되면 상태는 "CREATE_COMPLETE"가 됩니다.

 

EC2 대시보드에 접속하고 EC2 Instance가 생성되었는지 확인합니다.

 

 

cloudformation에서 설정한 인증서를 사용하여 kops가 설치된 EC2 Instance에 원격 접속할 수 있습니다.

ssh -i <인증서 위치> ec2-user@<your-public-ec2-instance-ip>

 

kops명령어 확인

cloudformation으로 생성된 EC2 instance는 kops가 설치되어 있습니다. kops명령어가 잘 실행되는지 확인해보세요.

kops --help

 

AWS IAM 설정

kops는 AWS 리소스를 생성, 수정, 삭제하는 작업을 수행하므로 적절한 permission이 필요합니다. 그리고 permission이 연결된 AWS IAM 사용자 또는 역할이 필요합니다.

 

저는 AWS IAM 사용자를 사용했습니다. EC2 Instance에서 aws configure명령어로 AWS IAM 사용자를 설정했습니다.

aws configure

 

S3 버킷 생성

kops가 생성한 쿠버네티스 클러스터 상태를 저장할 s3 버킷을 생성합니다. 저는 aws CLI를 사용하여 s3를 만들었습니다.

aws s3 mb s3://{your-bucket} --region ap-northeast-2

 

kops로 쿠버네티스 클러스터 생성

kops create cluster명령어로 쿠버네티스 클러스터를 생성할 수 있습니다. Auto Scaling Group을 생성하고 control plane, worker node를 역할을 나눠 쿠버네티스 클러스터를 생성합니다. 그리고 현재 클러스터 설정을 s3버킷에 저장합니다.

kops create cluster --인자

 

kops create cluster에 인자를 사용하지 않으면 default 설정이 사용되므로 인자를 적절히 설정해주는 것이 좋습니다. 저는 쿠버네티스 클러스터 이름과 도메인, 버킷경로를 설정했습니다. 인자는 환경 변수로 설정했습니다.

export AWS_PAGER=""
export REGION=ap-northeast-2
export KOPS_CLUSTER_NAME={구매한 도메인 이름}
export KOPS_STATE_STORE=s3://{your-bucket}

echo 'export AWS_PAGER=""' >>~/.bashrc
echo 'export REGION=ap-northeast-2' >>~/.bashrc
echo 'export KOPS_CLUSTER_NAME={구매한 도메인 이름}' >>~/.bashrc
echo 'export KOPS_STATE_STORE=s3://{your-bucket}' >>~/.bashrc

 

환경변수로 설정한 인자를 사용하여 쿠버네티스 클러스터를 생성합니다.

kops create cluster --zones="$REGION"a,"$REGION"c --networking amazonvpc --cloud aws \
--master-size t3.medium --node-size t3.medium --node-count=2 --network-cidr 172.30.0.0/16 \
--ssh-public-key ~/.ssh/id_rsa.pub --name=$KOPS_CLUSTER_NAME --kubernetes-version "1.24.10" -y

 

kops create cluster 명령어가 성공적으로 실행되면 아래 그림과 같이 성공 메시지가 표시됩니다. 이 작업은 약 10분 정도 소요됩니다.

 

클러스터가 생성될 때까지 kops validate 명령어를 사용하여 대기할 수 있습니다.

kops validate cluster --wait 10m

 

클러스터가 생성되면 “reday”라는 메세지가 출력됩니다.

 

kops 설치확인

이 챕터에서는 kops 클러스터를 설치하면서 생성된 주요 aws 리소스와 설정을 살펴봅니다.

 

EC2 Instance

kops create cluster명령어는 쿠버네티스 클러스터 node를 EC2 Instance로 사용하므로 EC2 Instance를 생성합니다. worker node 개수를 2개를 설정했으므로 worker역할을 하는 EC2 Instance가 2대 생성됩니다.

kops create cluster ... --node-count=2 ...

 

kubectl get node에서 보이는 노드 목록이 EC2 Instance목록과 동일합니다.

Kubectl get no

 

EC2 Instance tag

클라우드 환경에서 쿠버네티스를 사용하려면 tag설정이 중요합니다. 약속된 tag를 사용하지 않으면 클러스터 생성, 네트워크 통신 등 제약을 받게 됩니다. kops는 Auto Scaling Group에 tag를 적절하게 설정하여 올바르게 쿠버네티스 클러스터가 생성되도록 합니다.

 

예를 들어 "kubernetes.io/cluster tag" tag는 쿠버네티스 클러스터에 join될 수 있도록 설정해야하는 tag입니다.

참고자료: https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/troubleshooting.html

 

Auto Scaling Group

EC2 인스턴스는 Auto Scaling Group으로 생성됩니다. 따라서 kops 클러스터를 삭제할 때 주의해야 합니다. EC2 Instance를 삭제하더라도 Auto Scaling Group 때문에 새로운 EC2 Instance가 생성됩니다. 이로 인해 EC2 인스턴스가 계속 실행되어 요금이 부과됩니다.

 

S3

kops 클러스터를 생성할 때 지정한 S3 버킷을 확인해보세요. kops 클러스터 현재 설정이 버킷에 있습니다.

 

Route 53

Route 53에서 record를 확인하면 외부에서 접속할 수 있는 도메인이 생성되어 있습니다.

kops create cluster ... --name=$KOPS_CLUSTER_NAME ...

 

생성된 도메인은 쿠버네티스 context에 설정됩니다.

kubectl config get-contexts

 

StorageClass

aws volume타입을 사용할 수 있도록 storeageclass가 있습니다.

 

예제 -  마리오게임 배포

예제로 쿠버네티스에 마리오 게임 depoyment, svc를 배포해보겠습니다.

kubectl apply -f https://raw.githubusercontent.com/gasida/PKOS/main/1/mario.yaml

 

Loadbalancer타입 서비스는 aws CLB를 사용합니다. 약 5분 정도 기다려야 CLB가 생성됩니다.

kubectl get svc

 

CLB주소로 접속하면 마리오게임이 보입니다. CLB주소는 aws 대시보드 또는 kubectl get svc로 조회할 수 있습니다.

kubectl get svc mario -o jsonpath={.status.loadBalancer.ingress[0].hostname} | awk '{ print "Maria URL = http://"$1 }'

 

External DNS

External DNS는 쿠버네티스에서 외부 DNS provider를 직접 제어하여 dns를 설정합니다. aws에서는 route53 레코르를 설정합니다.

 

EC2 Instance 권한 설정

EC2 Instance(쿠버네티스 노드)가 Route 53에 대한 권한이 필요합니다. 이 예제에서는 EC2 Instance profile을 사용하여 권한을 설정했습니다.

 

권한이 있는 정책을 만듭니다.

curl -s -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/AKOS/externaldns/externaldns-aws-r53-policy.json
aws iam create-policy --policy-name AllowExternalDNSUpdates --policy-document file://externaldns-aws-r53-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "route53:ChangeResourceRecordSets"
      ],
      "Resource": [
        "arn:aws:route53:::hostedzone/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "route53:ListHostedZones",
        "route53:ListResourceRecordSets"
      ],
      "Resource": [
        "*"
      ]
    }
  ]
}

 

kops클러스터의 EC2 Instance에 profile을 추가합니다.

export ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text)

# EC2 instance profiles 에 IAM Policy 추가(attach)
aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AllowExternalDNSUpdates --role-name masters.$KOPS_CLUSTER_NAME
aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AllowExternalDNSUpdates --role-name nodes.$KOPS_CLUSTER_NAME

 

kops 설정 수정

kops edit명령어로 클러스터 설정에 external-dns를 추가합니다.

kops edit cluster
--------------------------
spec:
  externalDns:
    provider: external-dns
--------------------------

 

업데이트 적용

수정한 kops설정을 현재 클러스터에 적용합니다. kops는 설정 적용을 위해 node재부팅이 필요하다고 판단하면 해당 node를 재부팅합니다.

kops update cluster --yes && echo && sleep 3 && kops rolling-update cluster

 

External DNS controller pod가 생성되었는지 확인합니다.

kubectl get pod -n kube-system -l k8s-app=external-dns

 

마리오 게임과 External DNS 연동

External DNS를 사용하여 예제로 배포한 마리오 게임에 도메인을 할당해보겠습니다.

 

약속된 annotations을 설정하면 route53 레코드가 추가되면서 도메인이 생성됩니다.

참고자료: https://github.com/kubernetes-sigs/external-dns/#running-locally
kubectl annotate service mario "external-dns.alpha.kubernetes.io/hostname=mario.$KOPS_CLUSTER_NAME"

 

약 1분정도 기다리면 생성한 도메인이 DNS전파가 됩니다. https://www.whatsmydns.net/에서 DNS전파 상황을 실시간 확인할 수 있습니다.

 

생성한 도메인으로 접속하면 마리오게임을 할 수 있습니다.

 

External DNS controller pod 로그

kubectl logs로 controller pod로그를 확인하면 Router53 레코드 요청과 성공로그가 보입니다.

kubectl  -n kube-system logs -l k8s-app=external-dns

 

삭제

kops 클러스터를 삭제한 후 kops명령어를 실행하는 EC2 Instance를 삭제하면 됩니다.

 

kop클러스터는 kops delete로 삭제할 수 있습니다.

kops delete cluster --yes

 

cloudformation stack을 삭제하여 EC2 Instance를 삭제합니다.

 

마치며

kops라는 도구는 많이 들어봤지만 이번 기회에 처음 다뤄봤습니다. managed 쿠버네티스를 사용하지 않을 때 규모가 큰 쿠버네티스를 구축&운영 할 때 좋은 후보도구라고 생각했습니다. (요즘은 도구로 쿠버네티스 관리하는 것보다, kuebeadm으로 직접 관리하는 것도 나쁘지 않다고 생각합니다. 도구를 쓰는 것은 좋지만 도구에서 발생한 오류를 해결하는 시간이 너무 많이 들기 때문입니다)

 

aws를 업무로 사용하지 않아 쿠버네티스 Loadbalancer타입 서비스가 바로 생성이 안되는것을 알게되었습니다. 예제에서는 마리오 게임을 접속하기 위해 aws CLB를 사용했는데 약 5분정도 소요되었습니다. 잘 생각해보니 aws에서 CLB생성요청을 처리하기 위해 시간이 필요할 것 같아 시간이 오래걸리는 상황이 납득이 갔습니다.

 

External DNS라는 개념을 처음 들어봤고, 직접 실습해보니 신기했습니다. 외부 DNS provider를 사용하여 DNS를 직접 제어하는 것은 처음이었습니다. DNS provider를 제어할 수 있다는 개념은 언젠가 유용하게 사용할 수 있을 것 같습니다.

반응형