[PKOS STUDY #1] - 쿠버네티스 기본 설치 (AWS kOps) & ExternalDNS

유유·2023년 3월 11일
0

이정훈님의 ‘24단계 실습으로 정복하는 쿠버네티스’ 기반으로 작성된 포스팅 입니다.
도서 링크 : http://www.yes24.com/Product/Goods/115187666

kOps란?

  • kOps는 서버 인스턴스와 네트워크 리소스 등을 클라우드에서 자동으로 생성해 k8s 를 설치 할 수 있는 도구 중 하나입니다. kOps를 사용하면 클라우드 플랫폼(aws, gcp, azure 등)에서 쉽게 k8s 를 설치할 수 있습니다.

  • kOps 특징 자세히 보기: https://kops.sigs.k8s.io/#features

Overall

  • k8s 를 배포할 수 있는 kops 가 설치된 ec2cloudformation 에 의해서 생성됨
  • kopsk8s 클러스터를 생성 : k8s 설정 파일을 s3 에 저장
  • 버전 : k8s v1.24.10, OS Ubuntu 20.04 LTS
  • kops-ec2 역할 : kOps 배포 수행, kubectl 명령 실행 등
  • 마스터 노드와 워커 노드는 EC2 Auto Scaling Group(=ASG) 설정으로 구성됨
  • 도메인은 퍼블릭 도메인을 사용함
  • 퍼블릭 호스팅 메인 주소는 여기 에서 구입할 수 있다. 등록 까지 시간이 조금 걸리니 미리 진행하는 것을 추천한다

AWS kOps 설치

기본 인프라 배포 (방법 1)

  • 링크 ← AWS CloudFormation 페이지로 연결되며, 파라미터 입력 후 스택 실행

  • 인스턴스 접근 시 사용할 keypair 선택
  • SgIngressSshCidr: 접속할 PC IP

기본 인프라 배포 (방법 2)

  • 같은 내용 CLI로 진행하려면
# yaml 파일 다운로드
curl -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/K8S/kops-new-ec2.yaml

# 배포
# aws cloudformation deploy --template-file ~/Downloads/kops-new-ec2.yaml --stack-name mykops --parameter-overrides KeyName=<My SSH Keyname> SgIngressSshCidr=<My Home Public IP Address>/32 --region <리전>

예시) aws cloudformation deploy --template-file ~/Downloads/kops-new-ec2.yaml --stack-name mykops --parameter-overrides KeyName=yuran SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32 --region ap-northeast-2

kOps-ec2 접속

# CloudFormation 스택 배포 완료 후 EC2 IP 출력
aws cloudformation describe-stacks --stack-name mykops --query 'Stacks[*].Outputs[*].OutputValue' --output text
예시) 3.35.137.31

# kOps-ec2 에 SSH 접속
예시) ssh -i <My SSH Keyfile> ec2-user@3.35.137.31
ssh -i ~/.ssh/kp-gasida.pem ec2-user@$(aws cloudformation describe-stacks --stack-name mykops --query 'Stacks[*].Outputs[0].OutputValue' --output text)

kOps 클러스터 배포 및 확인

kOps-ec2 에 SSH 로그인 후 아래 실행

기본 툴 및 SSH 키 설치 등 확인

kubectl version --client=true -o yaml | yh

... gitVersion: v1.26.2 ...

kops version

Client version: 1.25.3 (git-v1.25.3)

aws --version

aws-cli/2.10.3 Python/3.9.11 Linux/4.14.304-226.531.amzn2.x86_64 exe/x86_64.amzn.2 prompt/off

ls /root/.ssh/id_rsa*

IAM User 자격 구성 : 실습 편리를 위해 administrator 권한을 가진 IAM User 의 자격 증명 입력

aws ec2 describe-instances
  • 만약 IAM User가 생성 되지 않았다면, 여기 에서 admin 권한 갖은 IAM 생성 후 csv 파일 다운 받은 후 진행

  • 자격증명 입력

aws configure

AWS Access Key ID [None]: AKIA5...
AWS Secret Access Key [None]: CVNa2...
Default region name [None]: ap-northeast-2
Default output format [None]: json
# 자격 구성 적용 확인 : 노드 IP 확인
aws ec2 describe-instances

# aws cli 페이지 출력 옵션
export AWS_PAGER=""

# 리소스를 배치할 리전이름을 변수 지정
REGION=ap-northeast-2  # 서울 리전 사용

k8s 설정 파일이 저장될 버킷 생성 (있으면 있는거 써도됨)

aws s3 mb s3://버킷<유일한 이름> --region <S3 배포될 AWS 리전>
aws s3 mb s3://버킷<유일한 이름> --region $REGION
aws s3 ls
## 예시)
aws s3 mb s3://gasida-k8s-s3 --region ap-northeast-2

배포 시 참고할 정보를 환경 변수에 저장

퍼블릭 호스팅 메인 주소는 여기 에서 구입할 수 있다. 등록 까지 시간이 조금 걸리니 미리 진행하는 것을 추천한다

## export NAME=<자신의 퍼블릭 호스팅 메인 주소>
## export KOPS_STATE_STORE=s3://(위에서 생성한 자신의 버킷 이름)
export KOPS_CLUSTER_NAME=<자신의 퍼블릭 호스팅 메인 주소>
export KOPS_STATE_STORE=<s3://(위에서 생성한 자신의 버킷 이름)>
export AWS_PAGER=""
export REGION=ap-northeast-2

## 예시)
export AWS_PAGER=""
export REGION=ap-northeast-2
export KOPS_CLUSTER_NAME=**gasida.link**
export KOPS_STATE_STORE=s3://gasida-k8s-s3
echo 'export AWS_PAGER=""' >>~/.bashrc
echo 'export REGION=ap-northeast-2' >>~/.bashrc
echo 'export KOPS_CLUSTER_NAME=gasida.link' >>~/.bashrc
echo 'export KOPS_STATE_STORE=s3://gasida-k8s-s3' >>~/.bashrc

옵션 [터미널1] EC2 생성 모니터링

while true; do aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output text ; echo "------------------------------" ; sleep 1; done

kops 설정 파일 생성(s3) 및 k8s 클러스터 배포 : 6분 정도 소요

  • CNI는 aws vpc cni 사용, 마스터 노드 1대(t3.medium), 워커 노드 2대(t3.medium), 파드 사용 네트워크 대역 지정(172.30.0.0/16)

  • container-runtime containerd --kubernetes-version: 1.24.0 ~ 1.25.6

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" --dry-run -o yaml > mykops.yaml

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

# validate
kops validate cluster --wait 10m

AWS Route53 도메인 정보 확인

# 자신의 도메인 변수 지정 : 소유하고 있는 자신의 도메인을 입력하시면 됩니다
MyDomain=<자신의 도메인>
MyDomain=gasida.link

# 자신의 Route 53 도메인 ID 조회 및 변수 지정
aws route53 list-hosted-zones-by-name --dns-name "${MyDomain}." | jq
aws route53 list-hosted-zones-by-name --dns-name "${MyDomain}." --query "HostedZones[0].Name"
aws route53 list-hosted-zones-by-name --dns-name "${MyDomain}." --query "HostedZones[0].Id" --output text
MyDnzHostedZoneId=`aws route53 list-hosted-zones-by-name --dns-name "${MyDomain}." --query "HostedZones[0].Id" --output text`
echo $MyDnzHostedZoneId

# A 레코드 타입 조회
aws route53 list-resource-record-sets --hosted-zone-id "${MyDnzHostedZoneId}" --query "ResourceRecordSets[?Type == 'A']" | jq
aws route53 list-resource-record-sets --hosted-zone-id "${MyDnzHostedZoneId}" --query "ResourceRecordSets[?Type == 'A'].Name" | jq
aws route53 list-resource-record-sets --hosted-zone-id "${MyDnzHostedZoneId}" --query "ResourceRecordSets[?Type == 'A'].Name" --output text

# A 레코드 값 반복 조회
while true; do aws route53 list-resource-record-sets --hosted-zone-id "${MyDnzHostedZoneId}" --query "ResourceRecordSets[?Type == 'A']" | jq ; date ; echo ; sleep 1; done

설치 확인

노드 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

파드 IP 확인

kubectl get pod -n kube-system -o=custom-columns=NAME:.metadata.name,IP:.status.podIP,STATUS:.status.phase

kops 클러스터 정보 확인

kops get cluster
NAME CLOUD ZONES
k8s.gasida.link aws ap-northeast-2a,ap-northeast-2c

kops get cluster -o yaml
kops get cluster -o yaml | yh
...

인스턴스그룹 정보 확인

kops get ig

kops get ig -o yaml
kops get ig -o yaml | yh
...

인스턴스 정보 확인

kops get instances
kops get instances -o yaml | yh
...

자동 완성 및 alias 축약 설정

source <(kubectl completion bash)
echo 'source <(kubectl completion bash)' >> ~/.bashrc
echo 'alias k=kubectl' >> ~/.bashrc
echo 'complete -F __start_kubectl k' >> ~/.bashrc
exit
exit

클러스터 정보 확인

kubectl cluster-info
kubectl cluster-info dump

배포 완료 후 정보 확인

tree -L 1 ~/.kube
cat .kube/config
cat .kube/config | yh

  • master node에 SSH 접속 후 확인
# [master node] SSH 접속
**ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME**

# [master node] EC2 메타데이터 확인 : IAM Role - [링크](https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html)
TOKEN=`curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
echo $TOKEN

curl -s -H "X-aws-ec2-metadata-token: $TOKEN" –v http://169.254.169.254/
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" –v http://169.254.169.254/latest/
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" –v http://169.254.169.254/latest/meta-data/iam/security-credentials/
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" –v http://169.254.169.254/latest/meta-data/iam/security-credentials/**masters.gasida.link** | jq
  • 워커 노드에 SSH 접속 후 확인 : 워커 노드의 public ip 로 SSH 접속
# 워커 노드 Public IP 확인
**aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value}" --filters Name=instance-state-name,Values=running --output table**

# 워커 노드 Public IP 변수 지정
W1PIP=<워커 노드 1 Public IP>
W2PIP=<워커 노드 2 Public IP>
W1PIP=3.35.50.183
W2PIP=54.180.118.11

# 워커 노드 SSH 접속
**ssh -i ~/.ssh/id_rsa ubuntu@$**W1PIP
exit
**ssh -i ~/.ssh/id_rsa ubuntu@$**W2PIP
exit



# 워커 노드 SSH 접속 후 node EC2 메타데이터 확인 : IAM Role - [링크](https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html)
**ssh -i ~/.ssh/id_rsa ubuntu@$**W1PIP
**ssh -i ~/.ssh/id_rsa ubuntu@$**W2PIP

TOKEN=`curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
echo $TOKEN
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" –v http://169.254.169.254/latest/meta-data/iam/security-credentials/
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" –v http://169.254.169.254/latest/meta-data/iam/security-credentials/**nodes.gasida.link** | jq

  • kOps 설치 중간에 실패 시 삭제 방법
    1. EC2 Auto Scaling 그룹 : 3개 삭제
    2. EC2 시작 템플릿 Launch Templates : 3개 삭제
    3. S3 버킷 비우기
    4. Route53에 추가된 A 레코드 3개 삭제
    5. CloudFormation 삭제

    소개 : K8S 서비스/인그레스 생성 시 도메인을 설정하면, AWS(Route 53), Azure(DNS), GCP(Cloud DNS) 에 A 레코드(TXT 레코드)로 자동 생성/삭제

  • ExternalDNS Addon 설치 - 링크
    # 모니터링
    watch -d kubectl get pod -A
    
    # 정책 생성 -> 마스터/워커노드에 정책 연결
    **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
    
    # ACCOUNT_ID 변수 지정
    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 edit cluster**
    --------------------------
    spec:
      ~~certManager:    # 없어도됨!
        enabled: true # 없어도됨!~~
      externalDns:
        provider: external-dns
    --------------------------
    
    # 업데이트 적용
    kops update cluster --yes && echo && sleep 3 && kops rolling-update cluster
    
    # externalDns 컨트롤러 파드 확인
    **kubectl get pod -n kube-system -l k8s-app=external-dns**
    NAME                            READY   STATUS    RESTARTS   AGE
    external-dns-66969c4497-wbs5p   1/1     Running   0          8m53s
    ```
    

# CLB에 ExternanDNS 로 도메인 연결
kubectl annotate service mario "external-dns.alpha.kubernetes.io/hostname=mario.$KOPS_CLUSTER_NAME"

# 확인
 dig +short mario.$KOPS_CLUSTER_NAME
        kubectl logs -n kube-system -l k8s-app=external-dns

        # 웹 접속 주소 확인 및 접속
        echo -e "Maria Game URL = http://mario.$KOPS_CLUSTER_NAME"

        # 도메인 체크
        echo -e "My Domain Checker = https://www.whatsmydns.net/#A/mario.$KOPS_CLUSTER_NAME"
    ```
    
    
 - AWS Route53 A 레코드 확인
 - 실습 완료 후 mario 게임 삭제
    
profile
하이

0개의 댓글