1
2
Production Kubernetes Online Study (=PKOS)는 쿠버네티스 실무 실습 스터디입니다.
CloudNet@ Gasida(가시다)님이 진행하시며, 책 "24단계 실습으로 정복하는 쿠버네티스"을 기반으로 진행하고 있습니다. 

PKOS 1주차 스터디 내용과 느낌점을 정리하고자 한다. 스터디하면서 매번 느끼는 거지만 정말 괴수분들 너무 많고, 배울 점이 정말 많다… 특히 모임장님이신 가시다님의 스터디 내용은 볼 때마다 감탄만 나온다. 쿠버네티스에 대한 원리와 세부 컴포넌트에 대한 명령어까지 배운 점이 많다. 본 글에서는 필자가 배운 내용을 정리함과 동시에 개념에 대해 몰랐던 부분이나, 트러블슈팅에 대한 내용을 중점적으로 정리하였다.

추가로, 몰랐던 부분은 ChatGPT를 활용하여 작성하였다. ChatGPT가 주는 답변은 대체로 만족하지만, 공식 문서에 대한 내용과 비교하여 다른 내용이 일부 존재한다. ChatGPT 활용시, 공식 문서와 이중 검증이 필요하다고 본다. 본 글에서도 답변 내용을 일부 수정하여 작성한다.



kops?

kops는 쿠버네티스 클러스터를 생성, 업그레이드, 관리하는 데 사용되는 오픈 소스 도구이다. 명령어 툴로 쉽게 쿠버네티스 클러스터를 구성하고 관리할 수 있는 툴이라고 이해하면 되겠다. 쿠버네티스 클러스터의 인프라를 코드로 정의하고 관리하는데 사용할 수 있어 IaC 이며, 같은 IaC 툴인 Terraform(테라폼)과의 특징을 비교하면 다음과 같다.

kops과 Terraform 특징 비교 표

특징 kops Terraform
지원하는 클라우드 플랫폼(Provider) AWS, GCP, OpenStack, DigitalOcean 등 AWS, GCP, Azure, Oracle Cloud, Alibaba Cloud, VMware, OpenStack 등
관리 대상 Kubernetes 클러스터 인프라스트럭처 (서버, 네트워크, 데이터베이스 등)
코드 작성 방식 YAML 파일 HCL (HashiCorp Configuration Language)
상태 관리 상태를 지정된 저장소(state)에 저장 상태를 지정된 저장소(backend)에 저장
장점 간단하고 직관적인 클러스터 구성 AWS뿐만 아니라 다른 클라우드 프로바이더도 지원
단점 Kubernetes 클러스터만 지원 Kops에 비해 배우기가 어려움


그렇다면 kops는 언제 써야 할까?

모임장님 의견과 동일하게 교육용이 적합하다고 본다. 쿠버네티스 클러스터 구축이 간단하고 배우기 쉽다. 또한, 배포 속도도 빠르다. 쿠버네티스 관리형 서비스인 EKS 와 비교했을 때, 마스터 노드들을 세부적으로 알 수 있어 세부 원리 이해에 좋고, 비용도 저렴하다. kops 공식문서도 정리가 잘 되어 있다. 눈여겨 볼 점은 공식문서의 addon과 Operation 부분이다. 클러스터 관리를 및 addon 배포를 간단하게 테스트할 수 있고 배포 yaml를 확인할 수 있기 때문이다.




실습

스터디 내용으로 kops를 통해 AWS에 쿠버네티스 클러스터를 구축하고, 게임 마리오를 예제로 배포하였다. 과정은 크게 3가지로 진행하였다.

arch.png

  1. 베스천 서버(kops-ec2) 구성
  2. kops 를 통한 클러스터 구축 및 확인
  3. External DNS 와 게임, 슈퍼마리오 배포

실습 과정 전 사전 작업으로 퍼블릭 도메인 구입, 키 페어 생성, S3 버킷 생성, AWS IAM 자격 증명을 진행하였다. 사전 작업 내용은 공식 문서에서 참고가 가능하다.

  • Q. 퍼블릭 도메인 구입 이유 ?

    퍼블릭 도메인은 쿠버네티스 클러스터 이름으로 사용하기 위하여 구입하였다. 클러스터 이름을 도메인으로 설정하면 외부에서 서비스 디스커버리 및 클러스터 액세스가 쉽게 가능해지기 때문이다. 스터디에서는 해당 도메인을 통해 클러스터 구성 확인과 게임 배포 후 접근을 위해 사용하였다.



1. 베스천 서버(kops-ec2) 구성

베스천 서버 구성은 모임장님이 공유해주신 CloudFormation 템플릿을 통해 구성하였다. 템플릿 구성은 VPC 와 igw 구성같은 AWS 네트워크 구성과 EC2 서버 설정으로 되어있다. 그 중 EC2 서버 설정 스크립트를 확인할 필요가 있는데 kops와 필요 패키지를 같이 설치해주기 때문이다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#!/bin/bash

# 호스트 이름 변경 
hostnamectl --static set-hostname kops-ec2

# EC2 서버 시간을 서울로 변경 
ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime

# Install Packages
cd /root
yum -y install tree jq git htop
## kubectl 설치 
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
## kops 설치
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
## awscli 설치
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
## aws cli 자동 완성 설정
complete -C '/usr/local/bin/aws_completer' aws
## SSH 설정 
ssh-keygen -t rsa -N "" -f /root/.ssh/id_rsa
## vi -> vim 으로 설정 
echo 'alias vi=vim' >> /etc/profile
## root 계정 변환
echo 'sudo su -' >> /home/ec2-user/.bashrc
## helm 설치
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/

베스천 서버 구성 과정 중 에러 발생 시, AWS Cloudformation에서 로그를 확인할 수 있다. 필자는 VPC가 최대여서 베스천 서버 구성이 안되었다. 해결을 위해 필요없는 VPC를 삭제하고, 템플릿으로 생성한 Cloudformtation 스택을 삭제하고 재실행하였다.

study1.png



2. kops를 통한 클러스터 구축 및 확인

쿠버네티스 클러스터 구축은 kops 명령어로 구축하였다. 클러스터 생성에 대한 옵션은 공식 문서에서 참고할 수 있었다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# 클러스터 생성 bash

## export KOPS_STATE_STORE=s3://( 클러스터 관리 저장소로 활용할 버킷 이름)
## export KOPS_CLUSTER_NAME=<도메인 메인 주소>
## export REGION=ap-northeast-2 지역

kops create cluster \
--cloud aws \
--name $KOPS_CLUSTER_NAME \
--state s3://$KOPS_STATE_STORE \
--zones "$REGION"a,"$REGION"c \
--networking amazonvpc \
--network-cidr 172.30.0.0/16 \
--kubernetes-version "1.24.10" \
--node-count 2 \
--node-size t3.medium \
--master-size t3.medium \
--ssh-public-key ~/.ssh/id_rsa.pub \
-y
  • --state : 클러스터 관련 설정 파일들이 저장된다. 이렇게 저장된 설정 파일들은 나중에 클러스터를 업데이트하거나 삭제할 때 사용된다. 실습에서는 외부 스토리지인 S3를 이용하였다.
  • —state 플래그를 사용하지 않으면 로컬 저장소인 ~/.kops 에 클러스터 설정 파일이 저장된다. 하지만 로컬 시스템에 대한 의존성이 높아지고 협업시에 대한 공유성이 떨어져 외부 스토리지를 사용하는 것을 권장한다.

필자는 클러스터 생성시 VPC 개수 이유(error creating VPC: VpcLimitExceeded) 로 클러스터 생성이 되지 않았다.

kops cluster-error.png

재설치를 위해서는 기존 클러스터 삭제가 필요하다. 실습 내용의 구성 단계에 따라 삭제하면 된다.

1
2
3
4
5
1. EC2 Auto Scaling 그룹 삭제
2. EC2 시작 템플릿 Launch Templates 삭제
3. S3 버킷 비우기
4. Route53에 추가된 A 레코드 3개 삭제 
5. CloudFormation 삭제

VPC 문제는 S3 버킷만 지우면 됐었다. Cloudformtation 스택 생성시 에러가 발생하여 AWS 리소스들은 생성되지 않았기 때문이다. 아래는 kops 를 통한 클러스터 구성 과정을 정리하였다

1
2
3
4
5
6
7
8
1. kops create cluster 명령어 실행
2. 클러스터 구성 정보를 S3에 저장
3. 클러스터 구성 정보를 기반으로 CloudFormation 스택 생성
4. VPC 및 관련 리소스 생성
5. 마스터 노드 EC2 인스턴스 생성
6. 노드 그룹 EC2 인스턴스 생성
7. 노드 그룹 EC2 인스턴스가 마스터 노드를 참조하여 클러스터에 가입
8. 클러스터가 실행되고 kubectl을 통해 액세스 가능해짐

클러스터 구성 확인 확인

스터디 실습 내용으로 클러스터 구성 확인에 대한 것도 시간을 할당하여 확인하였다. 쿠버네티스 클러스터가 복잡한 만큼 확인할 것이 많았는데, 실습 내용을 참고로 하여 명령어를 정리해보았다.

  • 클러스터 도메인 확인

    클러스터 구성시 클러스터 이름을 퍼블릭 도메인으로 입력하였다. 필자는 퍼블릭 도메인을 AWS Route53 에서 구매하였는데, 이 같은 경우 route53에서 A레코드도메인이 추가된 것을 확인할 수 있다.

    create-cluster-check1.png

  • 클러스터 구성 정보 확인

    클러스터 구성 정보는 kubectl 와 kops 툴로 확인이 가능하다. kops 툴을 통해 클러스터 정보 뿐만 아니라 이미지 확인(assets), 보안 정보 확인이 가능하다. 공식문서를 링크한다.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    
    # 클러스터 확인 
    kops get cluster 
    
    # 클러스터 인스턴스 그룹 확인 
    kops get ig 
    
    # 클러스터 인스턴스 확인
    kops get instances
    
    # 클러스터 접근 정보 확인 
    kubectl get nodes -v6
    
    # 클러스터 배포 파드 확인 
    kubectl get pods -A 
    
    # 클러스터 정보 확인
    k**ubectl cluster-info dump**
    

    kops-craete-cluster.png

    kops-create-cluster3.png

  • 클러스터 세부 구성 확인

    클러스터 세부 구성 확인으로 스토리지, 네트워크, 파드, 마스터 노드 컴포넌트들의 구성 정보를 확인하였다. 추후 참고용을 위해 정리해둔다. 퍼블릭 도메인을 이용하여 구성 정보를 확인할 수 있다.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    # storage class 확인 
    kubectl get sc
    
    # 노드별 스토리지 확인 
    lsblk 
    df -hT
    
    # 네트워크 확인 
    sudo iptables -t nat -S
    
    # 마스터 노드 컴포넌트 확인 
    **tree /etc/kubernetes/manifests/
    
    # kubelet 작동 확인
    systemctl status kubelet
    
    # 컨테이너 접근 방법 확인
    ps axf | grep /usr/bin/containerd
    
    # 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/latest/meta-data/iam/security-credentials/<도메인> | jq
    
    • kubectl get sc : kops로 클러스터 구성시 스토리지 CSI 가 기본 제공된다. 스토리지 CSI 는 클러스터 스토리지 관리 기능 플러그인이다. kops-csikops-ssd 가 존재하는데 kops-csi 는 AWS EBS(gp3), EFS, GCP 등의 스토리지를 사용할 수 있는 플러그인이고, kops-ssd 는 NVMe SSD 기반 인스턴스 스토리지를 사용할 수 있는 플러그인이다.

    • sudo iptables -t nat -S : Kubernetes에서 사용하는 iptables rule 을 확인할 수 있다. 이번 장에서 구성한 네트워크 CNI는 VPC로 노드 IP와 서비스 IP의 할당별 iptables rule을 확인할 수 있다.

      • 파드 IP 설정 iptables rule

        파드체인확인.png

        • 임의의 애플리케이션 파드 IP를 확인했다. 체인을 따라가보면 들어오는 패킷 중 목적지 IP 주소가 100.64.59.121/32이고, 프로토콜이 TCP이며, 목적지 포트가 80인 패킷이 172.30.41.131:8080(파드 할당 IP) 으로 가는 것을 확인 할 수 있다.
      • 노드 IP 설정 iptables rule

        노드IP체인확인.png

        • 임의의 노트 IP를 확인했다. 노드 IP에 대해NAT 규칙을 적용하는 것을 확인할 수 있었다.
    • tree /etc/kubernetes/manifests/ : 마스터 노드에서 작동하는 컴포넌트 mainfest 정보들이다. kubelet에 의해 Static Pod로 배포되어 있으며 API 서버의 명령어(kubectl apply, delete) 등으로 관리가 불가능하다. kubelet을 통해 아래 컴포넌트의 manifest 를 모니터링하고 있으며 manifest 수정시 자동으로 업데이트된다.

      1
      2
      3
      4
      5
      6
      7
      
      /etc/kubernetes/manifests/
      ├── etcd-events-master-ap-northeast-2a.manifest
      ├── etcd-main-master-ap-northeast-2a.manifest
      ├── kube-apiserver.manifest
      ├── kube-controller-manager.manifest
      ├── kube-proxy.manifest
      └── kube-scheduler.manifest
      



3. External DNS, 게임 마리오 배포

실습 예제로는 게임 마리오를 배포하였다. External DNS은 쿠버네티스 addon으로, 내부에서 동작하는 마리오 서비스의 IP 주소를 외부의 DNS 서버에 자동으로 등록시켜주기 위해 배포하였다. 인상 깊은 점은 addon인 ExternalDNS 배포였는데, kops를 통해 클러스터 정보를 수정하니 자동으로 배포되었다.

공식 문서1, 공식 문서2 에는 클러스터 스펙 수정시의 옵션이 잘 정리되어 있다. 추후 기능 테스트시 접근을 위해 남겨둔다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 클러스터 수정 
kops edit cluster

# 아래 spec 에 ExternalDNS 정보 추가**
--------------------------
spec:
  externalDns:
    provider: external-dns
--------------------------

# 클러스터 업데이트 후, 롤링 업데이트 진행
kops update cluster --yes && echo && sleep 3 && kops rolling-update cluster

mario.png



트러블슈팅

API 서버 접근시, 아래의 에러 메세지(couldn’t get current server API group list: ~ dial tcp connect refused )가 확인되었다.

configerror.png

원인은 클러스터 접근 토큰 만료였다. kops 명령어를 통해 자격 증명을 재발급(kops export kubeconfig) 받을 수 있다하여 시도해보았지만, 쿠버네티스 유저가 없어서 그런지 접근 토큰이 null 로 발급되었다. kops 클러스터 관리 저장소인 s3에도 접근 토큰 정보가 없었다. 필자는 마스터 노드에 접근(~/.kube/config)하여 토큰을 복사하니 해결하였다.



마치며

kops 간단하다! 특히 마스터 노드를 직접 접근하여 컨트롤할 수 있어 클러스터 동작 이해에 좋은 툴이였다. 공식문서도 참고할 것이 많다. 공식 문서 kops operation 에 재밌는 주제들(카펜터)이 많던데 얼른 테스트해보고 싶은 마음이다. 시간나는대로 정리해서 올려보겠다.