Ansible 로 Kubernetes 세팅하며 생긴 오류 잡아가기

쿠버네티스 환경 구성시 발생하는 문제들과 해결방법 🚀

안녕하세요, 여러분! 오늘은 제가 물뮤(MoolMeow) 프로젝트를 위한 쿠버네티스 환경을 구성하면서 마주친 다양한 이슈들과 해결 방법에 대해 공유하려고 해요. 🐱 + 💧 = 물뮤!

프로젝트 소개 🌟

물뮤(MoolMeow)는 수영(Mool, 물)과 고양이(Meow, 야옹)를 주제로 하는 통합 온라인 커뮤니티 서비스입니다. 하나의 도메인(moolmeow.com) 아래 두 가지 컨셉의 커뮤니티를 운영하는 재미있는 프로젝트예요!

저는 이를 위해 온프레미스 환경에서 쿠버네티스 클러스터를 구축했는데, 그 과정에서 몇 가지 도전적인 상황들이 있었어요. 지금부터 이 여정을 함께 살펴볼까요? 💪

인프라 구성 환경 🖥️

  • 하드웨어: Mac Mini Pro (M2, 16GB RAM, 512GB SSD)
  • 가상화: Vagrant + VMware Fusion을 사용한 VM 구성
  • 쿠버네티스: kubeadm으로 설치 (마스터 노드 1개, 워커 노드 1개)
  • 자동화: Ansible을 사용한 설치 자동화
  • 스토리지: Rook-Ceph을 사용한 분산 스토리지

발생한 이슈들과 해결 방법 🔧

1. 아키텍처 불일치 문제 (Architecture Mismatch) 😵

이슈: Helm 설치 과정에서 Exec format error 발생

/bin/sh: 1: helm: Exec format error

원인: 다운로드한 Helm 바이너리가 VM 아키텍처와 맞지 않았습니다.

해결방법: 타겟 시스템의 아키텍처를 확인하고 그에 맞는 바이너리를 다운로드하도록 수정했습니다.

# 적절한 아키텍처의 Helm 다운로드
- name: Download Helm for the appropriate architecture
  get_url:
    url: "https://get.helm.sh/helm-v3.12.3-linux-{{ 'arm64' if 'aarch64' in vm_arch.stdout else 'amd64' }}.tar.gz"
    dest: /tmp/helm.tar.gz

2. 네트워크 플러그인 설치 실패 🌐

이슈: Calico 네트워크 플러그인 설치 URL이 유효하지 않음

error: error validating "calico.yaml": error validating data: invalid object to validate

해결방법: 로컬에 저장된 매니페스트 파일을 사용하도록 변경했습니다.

- name: Copy local Calico manifest to master node
  copy:
    src: ./calico.yml
    dest: /home/vagrant/calico.yml

- name: Apply Calico network plugin
  shell: |
    kubectl apply -f /home/vagrant/calico.yml

3. 중복 설치 문제 (Idempotency Issues) 🔄

이슈: Helm 차트가 이미 설치되어 있을 때 발생하는 오류

Error: INSTALLATION FAILED: cannot re-use a name that is still in use

해결방법: 설치 전에 먼저 확인하고, 이미 설치된 경우 업그레이드하도록 로직 추가

- name: Check if Rook-Ceph is already installed
  shell: helm list -n rook-ceph | grep rook-ceph
  register: rook_ceph_check
  failed_when: false

- name: Install Rook-Ceph Operator
  shell: helm install --create-namespace --namespace rook-ceph rook-ceph rook-release/rook-ceph
  when: rook_ceph_check.rc != 0  # 설치되지 않은 경우에만 실행

- name: Upgrade Rook-Ceph if already installed
  shell: helm upgrade rook-ceph rook-release/rook-ceph --namespace rook-ceph
  when: rook_ceph_check.rc == 0  # 이미 설치된 경우에만 실행

4. 파드 준비 대기 시간 초과 (Pod Readiness Timeout) ⏱️

이슈: MetalLB 파드가 준비되는 데 시간이 너무 오래 걸려 타임아웃 발생

timed out waiting for the condition on pods/controller-5f56cd6f78-fghps

해결방법: 더 긴 타임아웃과 주기적인 상태 확인 로직 추가

- name: Wait for MetalLB pods with extended timeout
  shell: |
    # 최대 10분 동안 1분 간격으로 확인
    timeout=600
    elapsed=0
    interval=60

    while [ $elapsed -lt $timeout ]; do
      echo "Checking MetalLB pods status (elapsed time: ${elapsed}s / ${timeout}s)"
      kubectl get pods -n metallb-system
      
      if kubectl get pods -n metallb-system -o jsonpath='{.items[*].status.conditions[?(@.type=="Ready")].status}' | grep -v False; then
        echo "All MetalLB pods are ready!"
        break
      fi
      
      sleep $interval
      elapsed=$((elapsed + interval))
    done

배운 점 & 교훈 📚

  1. 아키텍처 차이를 항상 고려하세요: 특히 Apple Silicon 같은 ARM 기반 시스템에서 작업할 때 VM의 아키텍처를 확인하는 습관을 들이세요!

  2. 멱등성(Idempotency)이 중요합니다: Ansible 플레이북은 여러 번 실행해도 문제가 없어야 해요. 항상 상태를 확인하고 그에 맞게 행동하도록 설계하세요.

  3. 충분한 대기 시간을 제공하세요: 쿠버네티스 컴포넌트, 특히 로드밸런서나 스토리지 솔루션은 초기화에 생각보다 많은 시간이 필요할 수 있어요.

  4. 오류 처리를 세심하게 구현하세요: 플레이북이 중간에 멈추지 않도록 예상 가능한 모든 오류 상황에 대처 방법을 마련해두세요.

  5. 디버깅 정보를 충분히 수집하세요: 문제 해결에 필요한 정보(파드 상태, 로그 등)를 자동으로 수집하도록 플레이북을 구성하면 트러블슈팅이 훨씬 쉬워집니다.

결론 🎯

온프레미스 환경에서 쿠버네티스 클러스터를 구축하는 것은 결코 쉬운 일이 아니지만, 위와 같은 문제들을 하나씩 해결해나가면서 많은 것을 배울 수 있었어요. 특히 Ansible을 활용한 자동화는 반복적인 작업을 크게 줄여주고, 일관된 환경을 유지하는 데 큰 도움이 됩니다.

물뮤 프로젝트를 위한 이 인프라는 앞으로도 계속 개선해 나갈 예정이에요. 여러분도 비슷한 프로젝트를 진행하고 계시다면, 이 글이 조금이나마 도움이 되었으면 좋겠습니다! 💖

해피 쿠버네팅! Happy Kuberneting! 🎉

#쿠버네티스 #Ansible #DevOps #Vagrant #RookCeph #MetalLB #물뮤 #MoolMeow

Troubleshooting Kubernetes Environment Setup: Challenges and Solutions 🚀

Hello everyone! Today I’d like to share the various issues I encountered while setting up a Kubernetes environment for my MoolMeow project, along with the solutions I found. 🐱 + 💧 = MoolMeow!

Project Introduction 🌟

MoolMeow is an integrated online community service centered around swimming (Mool, 물) and cats (Meow, 야옹). It’s an exciting project that operates two concept-based communities under a single domain (moolmeow.com)!

I built a Kubernetes cluster in an on-premises environment for this project, and along the way, I faced several challenging situations. Let’s explore this journey together! 💪

Infrastructure Setup 🖥️

  • Hardware: Mac Mini Pro (M2, 16GB RAM, 512GB SSD)
  • Virtualization: VM configuration using Vagrant + VMware Fusion
  • Kubernetes: Installed with kubeadm (1 master node, 1 worker node)
  • Automation: Installation automated with Ansible
  • Storage: Distributed storage using Rook-Ceph

Issues Encountered and Solutions 🔧

1. Architecture Mismatch Problem 😵

Issue: Exec format error occurred during Helm installation

/bin/sh: 1: helm: Exec format error

Cause: Helm binary didn’t match the VM architecture.

Solution: Modified the script to check the target system’s architecture and download the appropriate binary.

# Download Helm for the appropriate architecture
- name: Download Helm for the appropriate architecture
  get_url:
    url: "https://get.helm.sh/helm-v3.12.3-linux-{{ 'arm64' if 'aarch64' in vm_arch.stdout else 'amd64' }}.tar.gz"
    dest: /tmp/helm.tar.gz

2. Network Plugin Installation Failure 🌐

Issue: Invalid URL for Calico network plugin installation

error: error validating "calico.yaml": error validating data: invalid object to validate

Solution: Modified the approach to use a locally stored manifest file.

- name: Copy local Calico manifest to master node
  copy:
    src: ./calico.yml
    dest: /home/vagrant/calico.yml

- name: Apply Calico network plugin
  shell: |
    kubectl apply -f /home/vagrant/calico.yml

3. Idempotency Issues 🔄

Issue: Error when Helm chart was already installed

Error: INSTALLATION FAILED: cannot re-use a name that is still in use

Solution: Added logic to check first and then either install or upgrade based on the current state.

- name: Check if Rook-Ceph is already installed
  shell: helm list -n rook-ceph | grep rook-ceph
  register: rook_ceph_check
  failed_when: false

- name: Install Rook-Ceph Operator
  shell: helm install --create-namespace --namespace rook-ceph rook-ceph rook-release/rook-ceph
  when: rook_ceph_check.rc != 0  # Only run if not already installed

- name: Upgrade Rook-Ceph if already installed
  shell: helm upgrade rook-ceph rook-release/rook-ceph --namespace rook-ceph
  when: rook_ceph_check.rc == 0  # Only run if already installed

4. Pod Readiness Timeout ⏱️

Issue: MetalLB pods took too long to become ready, causing timeouts

timed out waiting for the condition on pods/controller-5f56cd6f78-fghps

Solution: Added longer timeout and periodic status check logic.

- name: Wait for MetalLB pods with extended timeout
  shell: |
    # Check every minute for up to 10 minutes
    timeout=600
    elapsed=0
    interval=60

    while [ $elapsed -lt $timeout ]; do
      echo "Checking MetalLB pods status (elapsed time: ${elapsed}s / ${timeout}s)"
      kubectl get pods -n metallb-system
      
      if kubectl get pods -n metallb-system -o jsonpath='{.items[*].status.conditions[?(@.type=="Ready")].status}' | grep -v False; then
        echo "All MetalLB pods are ready!"
        break
      fi
      
      sleep $interval
      elapsed=$((elapsed + interval))
    done

Lessons Learned 📚

  1. Always Consider Architecture Differences: Especially when working on ARM-based systems like Apple Silicon, make it a habit to verify your VM’s architecture!

  2. Idempotency is Critical: Ansible playbooks should run multiple times without issues. Always design them to check the current state and act accordingly.

  3. Provide Sufficient Wait Times: Kubernetes components, especially load balancers or storage solutions, may need more initialization time than expected.

  4. Implement Error Handling Carefully: Prepare handling methods for all foreseeable error situations so your playbook doesn’t stop in the middle of execution.

  5. Collect Ample Debugging Information: Configure your playbook to automatically collect information needed for troubleshooting (pod status, logs, etc.), which makes resolving issues much easier.

Conclusion 🎯

Building a Kubernetes cluster in an on-premises environment is certainly not an easy task, but I learned a lot by solving these problems one by one. In particular, automation with Ansible significantly reduces repetitive work and helps maintain a consistent environment.

I plan to continue improving this infrastructure for the MoolMeow project. If you’re working on a similar project, I hope this post helps you in some way! 💖

Happy Kuberneting! 🎉

#Kubernetes #Ansible #DevOps #Vagrant #RookCeph #MetalLB #MoolMeow

답글 남기기