카이도스의 Tech Blog

PKOS(쿠버네티스) 1주차 - AWS kOps 설치 및 기본 사용 본문

KOPS

PKOS(쿠버네티스) 1주차 - AWS kOps 설치 및 기본 사용

카이도스 2023. 1. 11. 17:48
728x90
반응형

쿠버네티스 기초

*발음

- master(control-plane, leader) : 마스터, 컨트롤 플레인, 리더

- node(worker node) : 노드, 워커노드 (구 minion 미니언)

- k8s(kubernetes, k~s 사이에 8글자 == k8s) : 쿠버네티스, 케이에잇츠, 케이팔에스

- De facto(라틴어) : 데 팍토, 사실상의 의미 - Kubernetes has become a de facto standard.

- kubectl : 큐브 컨트롤(control), 큐버 컨트롤, 큐브 시티엘, 큐버 시티엘

- etcd : 엣시디, 이티시디

- flannel : 플라넬

- calico : 칼리코, 캘리코

- istio : 이스티오

- helm : 헬름, 핾, 햄

- pod : 파드, 포드

- label : 레이블, 라벨

 

* 쿠버네티스 아키텍처

- Kubernetes Components : K8S 클러스터는 Controle Plane(마스터)와 Node(노드)로 구성 

- Control Plane(마스터 노드) 핵심 컴포넌트 : 마스터는 단일 서버 혹은 고가용성을 위한 클러스터 마스터로 구축

kube-apiserver : 마스터로 전달되는 모든 요청을 받아 드리는 API 서버

etcd : 클러스터내 모든 메타 정보를 저장하는 서비스

kube-scheduler : 사용자의 요청에 따라 적절하게 컨테이너를 워커 노드에 배치하는 스케줄러

kube-controller-manager : 현재 상태와 바라는 상태를 지속적으로 확인하며 특정 이벤트에 따라 특정 동작을 수행하는 컨트롤러 cloud-controller-manager : 클라우드 플랫폼(AWS, GCP, Azure 등)에 특화된 리소스를 제어하는 클라우드 컨트롤러

 

- 워커 노드

kubelet : 마스터의 명령에 따라 컨테이너의 라이프 사이클을 관리하는 노드 관리자

kube-proxy : 컨테이너의 네트워킹을 책임지는 프록시, 네트워크 규칙을 유지 관리

Container Runtime : 실제 컨테이너를 실행하는 컨테이너 실행 환경, (Docker & containerD & CRI-O)

 

- Add on

CNI : Container Network Interface 는 k8s 네트워크 환경을 구성해준다, 다양한 플러그인이 존재

DNS : 쿠버네티스 서비스를 위해 DNS 레코드를 제공해주며, Service Discovery 기능을 제공을 한다. 대표적으로 CoreDNS 가 있다

CSI : Container Storage Interface

그외 대시보드, 모니터링, 로깅 등등이 있다.

 

* 쿠버네티스는 멱등성의 특징을 가진다.

-멱등성 : 연산을 여러 번 적용하더라도 결과가 달라지지 않는 성질


AWS Kops  소개

* Kubernetes Operations(kOps) - Production Grade k8s Installation, Upgrades and Management

kOps 는 클라우드 플랫폼(aws, gcp, azure 등)에서 쉽게 k8s 를 설치할 수 있도록 도와주는 도구

kOps 는 서버 인스턴스와 네트워크 리소스 등을 클라우드에서 자동으로 생성해 k8s 를 설치

kOpsAWS 의 다양한 서비스와 유연하게 연동되어 사용 가능

지원 버전 : Github 에 보면 현재 kOps v1.25 이 최신버전

실습구성도

  • k8s 를 배포할 수 있는 kops 가 설치된 ec2cloudformation 에 의해서 생성됨
  • kopsk8s 클러스터를 생성 : k8s 설정 파일을 s3 에 저장
  • 버전 : k8s v1.24.9, OS Ubuntu 20.04 LTS
  • kops-ec2 역할 : kOps 배포 수행, kubectl 명령 실행 등
  • 마스터 노드와 워커 노드는 EC2 Auto Scaling Group(=ASG) 설정으로 구성됨
  • 도메인은 퍼블릭 도메인 혹은 프라이빗 도메인을 사용, Gossip 도 가능 → 현재 실습 내용은 퍼블릭 도메인을 사용함

실습 환경에서 오른쪽 AWS kOps가 배포되는 VPC의 CIDR는 10.1.0.0/16 이 아니라 172.30.0.0/16


실습 시작

제공된 yaml 파일 다운로드하여 진행했다.(나중에 yaml 파일을 직접 생성하여 하는날이 오길...)

 

-기본 인프라 배포

*shell에서 진행

# yaml 파일 다운로드

curl -O yaml파일경로

(https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/K8S/kops-new-ec2.yaml)

 

# yaml파일 내용(kops-new-ec2.yaml)

kops-new-ec2.yaml
0.00MB

Parameters:
KeyName:
Description: Name of an existing EC2 KeyPair to enable SSH access to the instances. Linked to AWS Parameter
Type: AWS::EC2::KeyPair::KeyName
ConstraintDescription: must be the name of an existing EC2 KeyPair.
SgIngressSshCidr:
Description: The IP address range that can be used to communicate to the EC2 instances
Type: String
MinLength: '9'
MaxLength: '18'
Default: 0.0.0.0/0
AllowedPattern: (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})
ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.
LatestAmiId:
Description: (DO NOT CHANGE)
Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2'
AllowedValues:
- /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
 
Resources:
MyVPC:
Type: AWS::EC2::VPC
Properties:
EnableDnsSupport: true
EnableDnsHostnames: true
CidrBlock: 10.0.0.0/16
Tags:
- Key: Name
Value: My-VPC
 
MyIGW:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: My-IGW
 
MyIGWAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId: !Ref MyIGW
VpcId: !Ref MyVPC
 
MyPublicRT:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref MyVPC
Tags:
- Key: Name
Value: My-Public-RT
 
DefaultPublicRoute:
Type: AWS::EC2::Route
DependsOn: MyIGWAttachment
Properties:
RouteTableId: !Ref MyPublicRT
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref MyIGW
 
MyPublicSN:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MyVPC
AvailabilityZone: !Select [ 0, !GetAZs '' ]
CidrBlock: 10.0.0.0/24
Tags:
- Key: Name
Value: My-Public-SN
 
MyPublicSNRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref MyPublicRT
SubnetId: !Ref MyPublicSN
 
KOPSEC2SG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: kops ec2 Security Group
VpcId: !Ref MyVPC
Tags:
- Key: Name
Value: KOPS-EC2-SG
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '22'
ToPort: '22'
CidrIp: !Ref SgIngressSshCidr
 
KOPSEC2:
Type: AWS::EC2::Instance
Properties:
InstanceType: t2.micro
ImageId: !Ref LatestAmiId
KeyName: !Ref KeyName
Tags:
- Key: Name
Value: kops-ec2
NetworkInterfaces:
- DeviceIndex: 0
SubnetId: !Ref MyPublicSN
GroupSet:
- !Ref KOPSEC2SG
AssociatePublicIpAddress: true
PrivateIpAddress: 10.0.0.10
UserData:
Fn::Base64:
!Sub |
#!/bin/bash
hostnamectl --static set-hostname kops-ec2
yum -y install tree tmux jq git
install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
chmod +x kops
mv kops /usr/local/bin/kops
unzip awscliv2.zip
sudo ./aws/install
export PATH=/usr/local/bin:$PATH
source ~/.bash_profile
complete -C '/usr/local/bin/aws_completer' aws
ssh-keygen -t rsa -N "" -f /root/.ssh/id_rsa
echo 'alias vi=vim' >> /etc/profile
echo 'sudo su -' >> /home/ec2-user/.bashrc
unzip yh-linux-amd64.zip
mv yh /usr/local/bin/
 
Outputs:
KopsEC2IP:
Value: !GetAtt KOPSEC2.PublicIp

# 배포

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 PJH-aws-test.pem= SgIngressSshCidr=/32 --region ap-northeast-2

 

# CloudFormation 스택 배포 완료 후 EC2 IP 출력

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

예시)  43.201.48.178

 

# kOps-ec2 에 SSH 접속

ssh -i <My SSH Keyfile> ec2-user@IP

예시)ssh -i PJH-aws-test.pem ec2-user@43.201.48.178

접속 완료


-kOps 클러스터 배포 및 확인 : KOps-ec2 에 SSH 로그인 후 아래 실행

# 기본 툴 및 SSH 키 설치 등 확인

kubectl version --client=true -o yaml

kops version

aws --version

ls /root/.ssh/id_rsa*

# AWS 웹에서 IAM 사용자 추가하기

사용자권한은 AdministratorAccess 권한으로 생성했음.(기존 정책 직접 연결)

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

aws configure

# aws cli 페이지 출력 옵션

export AWS_PAGER=""

 

# 자격 구성 적용 확인 : 노드 IP

aws ec2 describe-instances

 

# k8s 설정 파일이 저장될 버킷 생성

aws s3 mb s3://버킷<유일한 이름> --region <S3 배포될 AWS 리전>

예시) aws s3 mb s3://pjh-k8s-s3 --region ap-northeast-2

aws s3 ls

# 배포 시 참고할 정보를 환경 변수에 저장(재로그인시에도 환경변수 실행될수있게 셋팅포함)

export AWS_PAGER=""

export REGION=ap-northeast-2

export 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

 

예시)

export AWS_PAGER=""

export REGION=ap-northeast-2

export KOPS_CLUSTER_NAME=pjhtest.click

export KOPS_STATE_STORE=s3://pjh-k8s-s3

echo 'export AWS_PAGER=""' >>~/.bashrc

echo 'export REGION=ap-northeast-2' >>~/.bashrc

echo 'export KOPS_CLUSTER_NAME=pjhtest.click' >>~/.bashrc

echo 'export KOPS_STATE_STORE=s3://pjh-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 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.9" -y


kOps 설치 확인 : 설치 완료 후 진행

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

kops get cluster -o yaml

# 인스턴스그룹 정보 확인

kops get ig

kops get ig -o yaml

kops get ig -o yaml | yh (yh 설치해서 시인성 좋게보기)

# 인스턴스 정보 확인

kops get instances

# 자동 완성 및 alias 축약 설정

source <(kubectl completion bash)

echo 'source <(kubectl completion bash)' >> ~/.bashrc

echo 'alias k=kubectl' >> ~/.bashrc

echo 'complete -F __start_kubectl k' >> ~/.bashrc

# 클러스터 정보 확인

kubectl cluster-info

 

# 노드 정보 확인 : 아래 출력 정보 의미는?

kubectl get nodes -v6

# CRI 컨테이너 런타임이 무엇인가요?

kubectl get nodes -o wide

# 배포 완료 후 정보 확인

tree -L 1 ~/.kube

cat .kube/config | yh

# volume(sc)

k get sc

kubectl get sc kops-csi-1-21 -o jsonpath={.parameters} ;echo

kubectl get sc kops-csi-1-17 -o jsonpath={.parameters} ;echo

# [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 확인

k get pod -n kube-system

k 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 파드 정보 확인 : 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

 

# [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

# [master node] nvme1n1,nvme1n2 디렉터리 확인

ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME tree /mnt/master-vol-008055c4e6ab61455

ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME tree /mnt/master-vol-000def8aecbddb231

# [master node] kubelet 상태 확인

ssh -i ~/.ssh/id_rsa ubuntu@api.$KOPS_CLUSTER_NAME systemctl status kubelet | yh

master node에 SSH 접속 후 확인

# [master node] SSH 접속

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.pjhtest.click | 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.34.40.17

W2PIP=3.34.46.70 

# 워커 노드 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


AWS Route53 도메인 정보 확인

# 자신의 도메인 변수 지정

MyDomain=<자신의 도메인>

MyDomain=pjhtest.click

# 자신의 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


헬름(HELM)

레포지토리 등록

[등록] helm repo add bitnami https://charts.bitnami.com/bitnami

[조회] helm repo list

[Chart 찾기] helm search repo bitnami | grep tomcat

[업데이트] helm repo update

[삭제] # helm repo remove bitnami

워드프레스 배포

# 아티팩트 허브에서 검색

helm search hub wordpress

# repo 추가 및 확인

helm repo add bitnami https://charts.bitnami.com/bitnami

helm repo list

# wordpress 검색

helm search repo wordpress

# 네임스페이스 생성

kubectl create ns wordpress

 

# 터미널2

watch kubectl get pod,svc

 

# 기본 파라미터를 덮어쓸수 있게 --set 으로 지정

helm install myblog \ --set wordpressUsername=admin \ --set wordpressPassword=password \ --set wordpressBlogName="PKOS BLOG" \ --namespace wordpress bitnami/wordpress --version 15.2.22


과제2 (Helm 으로 워드프레스를 배포하고 관리페이지에 접속해서 글 1개 작성해주시고 스크린샷을 올려주세요)

 

과제3 워커 노드 증가(ASG = Auto Scaling Group 활용)

# 인스턴스그룹 정보 확인

kops get ig

# 편집

kops edit ig nodes-ap-northeast-2a

# 적용

kops update cluster --yes

kops rolling-update cluster

 

실습완료 후 삭제 완료(1단계 과제까지는 최대한 작성했지만 2, 3 과제부터는 스킵.......ㅠㅠ)

 

모든 실습 완료 후 삭제 작업은 꼭 진행하자!!

kOps 클러스터 삭제: kops delete cluster --yes

(클러스터 삭제 완료 확인 후) AWS CloudFormation 스택 삭제 : aws cloudformation delete-stack --stack-name mykops

 

728x90
반응형
Comments