[PKOS STUDY #1] - 쿠버네티스 기본 설치 (AWS kOps)
이정훈님의 ‘24단계 실습으로 정복하는 쿠버네티스’ 기반으로 작성된 포스팅 입니다. 도서 링크 : 여기
kOps란?
-
kOps는 서버 인스턴스와 네트워크 리소스 등을 클라우드에서 자동으로 생성해 k8s 를 설치 할 수 있는 도구 중 하나입니다. kOps를 사용하면 클라우드 플랫폼(aws, gcp, azure 등)에서 쉽게 k8s 를 설치할 수 있습니다.
-
kOps 특징 자세히 보기: https://kops.sigs.k8s.io/#features
Overall
- k8s 를 배포할 수 있는 kops 가 설치된 ec2 를 cloudformation 에 의해서 생성됨
- kops 로 k8s 클러스터를 생성 : 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 키 설치 등 확인
[root@kops-ec2 ~]# kubectl version --client=true -o yaml | yh
clientVersion:
buildDate: "2023-02-22T13:39:03Z"
compiler: gc
gitCommit: fc04e732bb3e7198d2fa44efa5457c7c6f8c0f5b
gitTreeState: clean
gitVersion: v1.26.2
goVersion: go1.19.6
major: "1"
minor: "26"
platform: linux/amd64
kustomizeVersion: v4.5.7
[root@kops-ec2 ~]# kops version
Client version: 1.25.3 (git-v1.25.3)
[root@kops-ec2 ~]# aws --version
aws-cli/2.11.0 Python/3.11.2 Linux/4.14.305-227.531.amzn2.x86_64 exe/x86_64.amzn.2 prompt/off
[root@kops-ec2 ~]# ls /root/.ssh/id_rsa*
/root/.ssh/id_rsa /root/.ssh/id_rsa.pub
IAM User 자격 구성 : 실습 편리를 위해 administrator 권한을 가진 IAM User 의 자격 증명 입력
[root@kops-ec2 ~]# aws ec2 describe-instances
-
만약 IAM User가 생성 되지 않았다면, 여기 에서 admin 권한 갖은 IAM 생성 후 csv 파일 다운 받은 후 진행
-
자격증명 입력
[root@kops-ec2 ~]# 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 생성 모니터링
[root@kops-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
완료시 이렇게 마스터 노드 1대(t3.medium), 워커 노드 2대(t3.medium) 생성됨
NODE STATUS
NAME ROLE READY
i-0bda4b6485eeac1a4 node True
i-0de11644f4168ad2a node True
i-0f0b4d32ec78557b0 master True
Your cluster yuran.link is ready
AWS Route53 도메인 정보 확인
# 자신의 도메인 변수 지정 : 소유하고 있는 자신의 도메인을 입력하시면 됩니다
MyDomain=<자신의 도메인>
MyDomain=yuran.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 클러스터 정보 확인
[root@kops-ec2 ~]# kops get cluster
NAME CLOUD ZONES
yuran.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.yuran.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.yuran.link | jq
- kOps 설치 중간에 실패 시 삭제 방법
- EC2 Auto Scaling 그룹 : 3개 삭제
- EC2 시작 템플릿 Launch Templates : 3개 삭제
- S3 버킷 비우기
- Route53에 추가된 A 레코드 3개 삭제
- CloudFormation 삭제
ExternalDNS : 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:
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
```
- mario 서비스에 도메인 연결 실습 - 도메인체크
CLB에 ExternanDNS 로 도메인 연결
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/1/mario.yaml
kubectl apply -f mario
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"
Maria Game URL = http://mario.yuran.link
[root@kops-ec2 ~]# kubectl describe svc mario
Name: mario
Namespace: default
Labels: <none>
Annotations: external-dns.alpha.kubernetes.io/hostname: mario.yuran.link
Selector: app=mario
Type: LoadBalancer
IP Family Policy: SingleStack
IP Families: IPv4
IP: 100.71.52.109
IPs: 100.71.52.109
LoadBalancer Ingress: a7ac657470af04c109d2048f0ccb7dc2-75386274.ap-northeast-2.elb.amazonaws.com
Port: <unset> 80/TCP
TargetPort: 8080/TCP
NodePort: <unset> 31321/TCP
Endpoints: 172.30.86.217:8080
Session Affinity: None
- AWS Route53 A 레코드 확인
- 실습 완료 후 mario 게임 삭제
댓글남기기