Cloudnet@에서 진행하는 쿠버네티스 실무 실습 스터디를 진행하면서 작성한 글입니다.
스터디에서 사용하는 교재는 24단계 실습으로 정복하는 쿠버네티스 입니다.
Cloudnet@
24단계 실습으로 정복하는 쿠버네티스
Kubernetes Operations (kOps) - Production Grade k8s Installation, Upgrades and Management
k8s 를 배포할 수 있는 kops 가 설치된 ec2 를 cloudformation 로 생성
kops 로 k8s 클러스터를 생성 : s3 에 k8s 설정 파일 저장
버전 : k8s v1.24.10, OS Ubuntu 20.04 LTS
kops-ec2 역할 : kOps 배포 수행, kubectl 명령 실행 등
마스터 노드와 워커 노드 : EC2 Auto Scaling Group(=ASG) 설정으로 구성
도메인은 퍼블릭 도메인 사용
💡 AWS kOps 클러스터 설치 후 정보 확인하기
kops get cluster
,kops get instances
create stack
key, ami, ip 설정
스택 구성 완료
위에서 생성된 EC2 접속 후 실행
kubectl 버전 확인 : kubectl version --client=true -o yaml | yh
kops 버전 확인 : kops version
aws cli 버전 확인 : aws --version
개인 키와 공개키 확인 : ls /root/.ssh/id_rsa*
실습의 편의를 위해 administrator 권한을 가진 IAM User 생성
$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
aws ec2 describe-instances
# aws cli 페이지 출력 옵션
export AWS_PAGER=""
# 리소스를 배치할 리전이름을 변수 지정
REGION=ap-northeast-2 # 서울 리전 사용
# k8s 설정 파일이 저장될 버킷 생성
aws s3 mb s3://버킷<유일한 이름> --region $REGION
aws s3 ls
export AWS_PAGER=""
export REGION=ap-northeast-2
export KOPS_CLUSTER_NAME=<자신의 퍼블릭 호스팅 메인 주소>
export KOPS_STATE_STORE=<s3://(위에서 생성한 자신의 버킷 이름)>
echo 'export AWS_PAGER=""' >>~/.bashrc
echo 'export REGION=ap-northeast-2' >>~/.bashrc
echo 'export KOPS_CLUSTER_NAME=<자신의 퍼블릭 호스팅 메인 주소>' >>~/.bashrc
echo 'export KOPS_STATE_STORE=<s3://(위에서 생성한 자신의 버킷 이름)>' >>~/.bashrc
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 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 validate cluster --wait 10m
A 레코드 등록된 ip는 처음에 기본 203.0.113.123
이고, 배포가 완료되면 ec2 ip로 변경
dig +short api.imokapp.net
명령어로 바뀐 ip 확인
# 자신의 도메인 변수 지정 : 소유하고 있는 자신의 도메인을 입력하시면 됩니다
MyDomain=<자신의 도메인>
# 자신의 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
imokapp.net 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
...
# 클러스터 정보 확인
kubectl cluster-info
kubectl cluster-info dump
# 노드 정보 확인 : 사용자 인증 정보
kubectl get nodes -v6
...
# CRI 컨테이너 런타임
kubectl get nodes -o wide
# 배포 완료 후 정보 확인
tree -L 1 ~/.kube
cat .kube/config
cat .kube/config | yh
# volume(sc)
kubectl get sc
kubectl get sc kops-csi-1-21 -o jsonpath={.parameters} ;echo
{"encrypted":"true","type":"gp3"}
kubectl get sc kops-ssd-1-17 -o jsonpath={.parameters} ;echo
{"encrypted":"true","type":"gp2"}
# [master node] aws vpc cni log
ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME ls /var/log/aws-routed-eni
ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME cat /var/log/aws-routed-eni/plugin.log | jq
ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME cat /var/log/aws-routed-eni/ipamd.log | jq
# pod ip 확인
kubectl get pod -n kube-system
kubectl get pod -n kube-system -owide
# [master node] iptables rules
ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME sudo iptables -t nat -S
# [master node] 컨테이너 정보 확인
ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME ps axf |grep /usr/bin/containerd
ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME ps afxuwww
# [master node] tree 툴 설치
ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME sudo apt install -y tree jq
# [master node] Static 파드 정보 확인
ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME tree /etc/kubernetes/manifests/
ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME cat /etc/kubernetes/manifests/kube-apiserver.manifest
ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME cat /etc/kubernetes/manifests/kube-controller-manager.manifest
ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME cat /etc/kubernetes/manifests/kube-proxy.manifest
ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME cat /etc/kubernetes/manifests/kube-scheduler.manifest
# [master node] 볼륨/마운트 확인 : nvme1n1 과 nvme2n1 은 etcd-events, etcd-main 으로 사용
ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME lsblk
ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME df -hT --type=ext4
Filesystem Type Size Used Avail Use% Mounted on
/dev/root ext4 62G 5.6G 57G 9% /
/dev/nvme1n1 ext4 20G 126M 20G 1% /mnt/master-vol-08d1c4acf0650414b
/dev/nvme2n1 ext4 20G 123M 20G 1% /mnt/master-vol-0cc3c6878de9f5263
# [master node] nvme1n1,nvme1n2 디렉터리 확인
ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME tree /mnt/master-vol-03072035bffdd8252
ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME tree /mnt/master-vol-0db4765644c7d6ecb
# [master node] kubelet 상태 확인
ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME systemctl status kubelet
ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME
# [master node] EC2 메타데이터 확인 : IAM Role - 링크
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.imokapp.net | jq
# 워커 노드 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 -i ~/.ssh/id_rsa ubuntu@$W1PIP lsblk
ssh -i ~/.ssh/id_rsa ubuntu@$W2PIP lsblk
ssh -i ~/.ssh/id_rsa ubuntu@$W1PIP df -hT -t ext4
ssh -i ~/.ssh/id_rsa ubuntu@$W2PIP df -hT -t ext4
# 워커 노드 SSH 접속 후 node EC2 메타데이터 확인 : IAM Role - 링크
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.imokapp.net | jq
source <(kubectl completion bash)
echo 'source <(kubectl completion bash)' >> ~/.bashrc
echo 'alias k=kubectl' >> ~/.bashrc
echo 'complete -F __start_kubectl k' >> ~/.bashrc
# 설치
$curl -fsSLO https://github.com/kubernetes-sigs/krew/releases/download/v0.4.3/krew-linux_amd64.tar.gz
$tar zxvf krew-linux_amd64.tar.gz
$./krew-linux_amd64 install krew
$tree -L 3 /root/.krew/bin
# PATH 추가
export PATH="${PATH}:/root/.krew/bin"
echo 'export PATH="${PATH}:/root/.krew/bin"' >>~/.bashrc
# krew 확인
kubectl krew
kubectl krew update
kubectl krew search
kubectl krew list
kubectl krew
# 설치
kubectl krew install ctx
# 컨텍스트 확인
kubectl ctx
# 컨텍스트 사용
kubectl ctx <각자 자신의 컨텍스트 이름>
# 설치
kubectl krew install ns
# 네임스페이스 확인
kubectl ns
# 터미널1
watch kubectl get pod
# kube-system 네임스페이스 선택 사용
kubectl ns kube-system
# default 네임스페이스 선택 사용
kubectl ns -
혹은
kubectl ns default
kubectl krew list
# 설치
kubectl krew install df-pv get-all ktop neat oomd view-secret # mtail tree
# get-all 사용
kubectl get-all
kubectl get-all -n kube-system
# ktop 사용
kubectl ktop
# oomd 사용
kubectl oomd
# df-pv 사용
kubectl df-pv
# view-secret 사용 : 시크릿 복호화
kubectl view-secret
# 설치 및 설정
git clone https://github.com/jonmosco/kube-ps1.git /root/kube-ps1
cat <<"EOT" >> /root/.bash_profile
source /root/kube-ps1/kube-ps1.sh
KUBE_PS1_SYMBOL_ENABLE=true
function get_cluster_short() {
echo "$1" | cut -d . -f1
}
KUBE_PS1_CLUSTER_FUNCTION=get_cluster_short
KUBE_PS1_SUFFIX=') '
PS1='$(kube_ps1)'$PS1
EOT
# 적용
exit
exit
# default 네임스페이스 선택
kubectl ns default
# 수퍼마리오 디플로이먼트 배포
$curl -s -O https://raw.githubusercontent.com/euneun316/k8s-study/main/1/mario.yaml
$kubectl apply -f mario.yaml
cat mario.yaml | yh
# 배포 확인 : CLB 배포 확인 >> 5분 이상 소요
kubectl get deploy,svc,ep mario
watch kubectl get svc mario
# 마리오 게임 접속 : CLB 주소로 웹 접속
kubectl get svc mario -o jsonpath={.status.loadBalancer.ingress[0].hostname} | awk '{ print "Maria URL = http://"$1 }'
🚨 실습 완료 후 실습 리소스 삭제 필요
kops delete cluster --yes
aws cloudformation delete-stack --stack-name mykops
🚨 kOps 설치 중간에 실패 시 삭제 방법