프로비저닝
Mont Kim / January 2023 (1307 Words, 8 Minutes)
1주차 KOPS로 노드 프로비저닝
이번 스터디에서는 KOPS를 이용한 프로비저닝을 진행한다.
시작에 앞서
작업환경에따라 KOPS 프로비저닝 환경이 다를 수 있기때문에
KOPS EC2를 별도로 생성하여 이 작업환경에서 작업을 시작한다.
- KOPS로 프로비저닝 하는 이유
- 온프레미스 제외 각 PC에서 가상화를 통한 프로비저닝 (Kubespray 등)의 경우 각 PC의 사양 또는 호환성 (윈도우, 유닉스 등)에 따라 다르기때문에 동일한 환경을 제공 할 수 없다.
- EKS 프로비저닝 테라폼을 이용한 EKS 프로비저닝이 훨씬 보편적이지만, 클러스터 프로비저닝에 시간이 KOPS보다 오래걸리기때문에 제외
KOPS EC2는 클라우드 포메이션을 이용해 생성을 하는데
클라우드 포메이션은 작성된 파일이 있다면 링크를 통해 AWS 콘솔에서도 생성이 가능하고
작업환경에서 명령어를 통해서도 생성이 가능하다.
윈도우 환경에서는 CMD 명령어가 익숙하지않아 직접 테스트해보지 못했지만
맥의경우 shell 명령어가 어렵지 않기때문에 훨씬 쉽게 사용 할 수 있다
KOPS 프로비저닝 클러스터 아키텍쳐
draw.io에서 구조를 그리는것이 보편적이지만
https://www.cloudcraft.co/ 라는 플랫폼에서도 조금 입체적인 그림을 그릴 수 있다고해서 그려봤다.
정확한 스펙을 기입하면 예상비용도 산정이 가능하다.
클라우드 포메이션을 이용한 KOPS EC2 생성
해당 yaml파일이 첨부되어있는 링크를클릭하면
Template 파일이 첨부되어있는 상태로 바로 진행이 가능하다.
링크로 바로 접속하지않아도, AWS 콘솔창의 CloudFormation 생성에 해당 템플릿을 넣고 진행해도 무방하다
-
kops-new-ec2.yaml
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 curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl curl -Lo kops https://github.com/kubernetes/kops/releases/download/$(curl -s https://api.github.com/repos/kubernetes/kops/releases/latest | grep tag_name | cut -d '"' -f 4)/kops-linux-amd64 chmod +x kops mv kops /usr/local/bin/kops curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" 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 curl -s https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash wget https://github.com/andreazorzetto/yh/releases/download/v0.4.0/yh-linux-amd64.zip unzip yh-linux-amd64.zip mv yh /usr/local/bin/ Outputs: KopsEC2IP: Value: !GetAtt KOPSEC2.PublicIp
다음과 같은 화면을 볼 수 있다.
보안을 위해 본인의 작업환경에서만 접근을 허용해주기 위해
SgIngressCidr 를 본인의 IP / 32 로 선언을 한다
만약 본인의 IP를 모른다면
curl -s ipinfo.io/ip
명령어로 본인의 IP를 확인 할 수 있다.
AWS 콘솔창에서 CloudFormation Apply를 하면 다음과 같은 진행 프로세스를 볼 수 있다.
생성이 종료되었으면 인스턴스 콘솔창에 들어가 생성된 KOPS-EC2 정보를 확인한다.
해당인스턴스에 개방주소(public IP)와 pem(ppk) 키로 로그인을 해 KOPS-EC2에 접속을 한다
프로비저닝 된 이미지에서 기본적인 명령어들을 이용해 이미지 확인을 진행한다
# 기본 툴 및 SSH 키 설치 등 확인
kubectl version --client=true -o yaml
kops version
Client version: 1.25.3 (git-v1.25.3)
aws --version
KOPS EC2는 Amazon Linux로 프로비저닝되어 AWS 통합에 필요한 간단한 서비스, 유틸리티 및 도구들이 설치되어있어 KOPS 프로비저닝을 바로 진행 할 수 있습니다.
KOPS 프로비저닝
위의 이미지 확인이 모두 완료된후
이후 기본적인 명령어를 위한 configure를 진행한다.
aws configure
이때 IAM User 생성에서 진행했던 “엑세스 키”를 입력한다.
생성한 KOPS-EC2에서 AWS 명령어를 쓰기위한 기본적인 조건은 충족했지만
프로비저닝 할 클러스터의 정보를 입력해야하기때문에, 다른 변수들을 입력해준다.
export AWS_PAGER=""
export REGION=ap-northeast-2
export KOPS_CLUSTER_NAME=@@@@@@.com
export KOPS_STATE_STORE=s3://@@@@@@@@
변수를 입력하는 제일 확실한 방법은 bashrc에 입력해 bash 접속을 할때마다
변수를 지정해주는것이 제일 명확하다.
echo 'export AWS_PAGER=""' >>~/.bashrc
echo 'export REGION=ap-northeast-2' >>~/.bashrc
echo 'export KOPS_CLUSTER_NAME=@@@@@@.com' >>~/.bashrc
echo 'export KOPS_STATE_STORE=s3://@@@@@@@@@' >>~/.bashrc
기본 config 설정을 진행후 AWS 커맨드로 프로비저닝을 진행한다.
KOPS_CLUSTER_NAME 은 route53에서 구매, 등록되어있는 도메인을 입력할경우
자동으로 api 서버등이 등록이된다.
KOPS_STATE_STORE 는 쿠버네티스 기본자원들이 S3 버킷에 저장되는데, 이 버킷명을 지정해주면 된다.
KOPS 클러스터 생성
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
이때 위에 첨부했던 구조도와 같이 쿠버네티스 클러스터가 배포된다.
생성에는 약 6분정도 소요된다고 하는데, 10분정도 뒤에 AWS콘솔창에서도 정상적으로 생성된 모습들을 볼 수 있다.
시간이 조금 지난후, AWS 콘솔의 인스턴스 정보를 보면 t3.medium으로 프로비저닝 된것을 확인할 수 있다.
KOPS-EC2에서
kops validate cluster --wait 10m
kubectl get nodes
명령어등으로 프로비저닝 된 쿠버네티스 클러스터의 상태를 확인 할 수 있다.
발생했던 오류
-
DNS 오류
인스턴스의 상태는 모두 정상인데, kubectl 명령어 또는 kops validate cluster가 정상적으로 되지 않을경우
Route 53의 DNS 등록정보가 잘못 등록되어있는 경우가 있다.
해당 파일에서 route53에서 구매했던 도메인을입력하면
자동으로 route 53 서브도메인이 등록된다.
(다른 호스팅 사이트에서 구매한 도메인도 route 53에 등록하고, 권한을 부여하면 정상적으로 사용이 가능할것 같다)
알수 없는 이유로 route53의 api 서브도메인이 다른 IP로 등록되어있었다…
과정을 따라하다 몇번 삭제, 재생성하다 생긴 오류인거같다
프로비저닝 클러스터 확인하기
kops get cluster
kops get instances
정상적인 kops 클러스터임을 확인 할 수 있다.
WordPress 배포하기
이제 클러스터에 Wordpress 를 배포하여 정상적으로 동작하는것을 확인한다.
배포는 HELM을 이용해 진행되는데, HELM에 대해서는 따로 정리해서 올려두겠습니다.
간단하게 요약하면 하나의 템플릿을 이용해 소스를 설치하기 쉽게 만들어져있는 도구입니다.
이번 helm 배포에서는 별도로 repo를 pull하고, values.yaml파일에 필요한 변수들을 명세하여 실행하지않지만 모듈에 필요한 변수들만 정의하여 배포하는 방법도 가능합니다.
helm prerequsite
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo list
사용하고자 하는 helm repo를 로컬에 등록하고 확인하는 과정입니다.
kubectl create ns wordpress
HELM으로 배포할 wordpress는 별도의 namespace : wordpress에서 시작한다.
helm 배포하기
helm install myblog \
--set wordpressUsername=admin \
--set wordpressPassword=password \
--set wordpressBlogName="PKOS BLOG" \
--namespace wordpress bitnami/wordpress --version 15.2.22
마주했던 또다른 문제
hlelm을 통해 wordpress 자원을 생성을 했는데 IAM에서 권한 오류가 발생해 loadbalancer type의 service를 생성하는데 pending이 되고있다.
해당 Service를 Describe 했을때 나오는 에러멘트인데, IAM 권한문제라고 알려주고있어 IAM 설정을 다시 보기로 한다.
IAM 수정
https://us-east-1.console.aws.amazon.com/iamv2/home#/roles
Elastic Load Balancing 관련 IAM Role을 추가한다.
역할생성이 완료되면 권한을 받아 LoadBalancer를 사용 할 수 있다.
이제 정상적으로 service에서 loadbalancer가 생성된것을 확인 할 수 있다.
이제 생성된 loadbalancer의 external-ip로 접속을 하면 wordpress 사이트에 접속 할 수있다.
/admin 페이지에 접속해서 publish를 하면 main페이지의 내용을 publish 가능하다.
AutoScaling 값 조절
쿠버네티스의 핵심은 컨테이너 단위의 자원을 가변적으로 관리한다는 장점이 있다.
이에따라 사용량 또는 다른 전략들에 의해 (쿠버네티스) 시스템 자체의 최대 자원량이 늘어야하는 경우가있는데, AutoScaling 설정에 따라 최대 자원량을 정해둘 수 있다.
온프레미스 쿠버네티스 클러스터에서는 오토스케일링이 꽤나 제한적이지만, 클라우드에서는 오토스케일링이 어렵지않게 가능하다.
오토스케일링 옵션 조절은 KOPS를 이용해 node 오토스케일링 정보를 변경 할 수 있다.
kops edit ig nodes-ap-northeast-2a
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: kops.k8s.io/v1alpha2
kind: InstanceGroup
metadata:
creationTimestamp: "2023-01-10T03:24:39Z"
labels:
kops.k8s.io/cluster: mont-kim.com
name: nodes-ap-northeast-2a
spec:
image: 099720109477/ubuntu/images/PKOS/hvm-ssd/ubuntu-focal-20.04-amd64-server-20221206
instanceMetadata:
httpPutResponseHopLimit: 1
httpTokens: required
machineType: t3.medium
maxSize: 1
minSize: 1
role: Node
subnets:
- ap-northeast-2a
KOPS 명령어는 각 AZ 노드별로 (2a, 2c) 설정을 진행하기때문에 각각 값을 수정하면 된다.
(max 1→3, min 1→2로 조절을 진행했다)
maxSize, minSize를 수정후 적용을 진행한다.
kops update cluster --yes
kops rolling-update cluster
해당 명령어들을 입력하면
AWS 콘솔창에서 EC2의 AutoScaling Group 값이 변경된것을 확인 할 수 있다.
kops 명령어로 클러스터 정보를 확인해도 오토스케일링 된 노드의 정보를 확인 할 수 있다.
kubectl get nodes 의 정보로도 증가된 노드를 확인 할 수 있다.
kops 명령어로 클러스터 정보를 확인해도 오토스케일링 된 노드의 정보를 확인 할 수 있다.
kubectl get nodes 의 정보로도 증가된 노드를 확인 할 수 있다.