13년차의 서버실

서버, 인프라, 홈랩 기술 블로그

[태그:] 컨테이너

  • [k8s] k3s로 경량 쿠버네티스 클러스터 구축: 홈랩과 엣지 완벽 가이드

    [k8s] k3s로 경량 쿠버네티스 클러스터 구축: 홈랩과 엣지 완벽 가이드

    k3s로 경량 쿠버네티스 클러스터 구축하기: 13년차 엔지니어의 삽질 완전 정복

    안녕하세요, 13년차의 서버실 주인장입니다. 오늘은 제가 최근 홈랩에서 직접 구축해보고, 엣지 컴퓨팅 환경에서도 정말 유용하겠다 싶었던 기술, k3s(케이쓰리 에스)에 대해 이야기해보려고 해요. 기존 쿠버네티스(Kubernetes)는 아무래도 무겁고 복잡해서 홈랩이나 리소스가 제한적인 엣지 환경에 도입하기가 쉽지 않았거든요. 근데 k3s를 만나고 나서 생각이 확 바뀌었습니다. 가볍고 빠르면서도 쿠버네티스의 강력한 기능을 고스란히 쓸 수 있다는 게 정말 매력적이더라고요!

    저도 처음엔 이게 뭔가 싶었는데, 실제로 써보니까 ‘아, 이거 진짜 물건이다!’ 싶었습니다. 제 경험을 바탕으로 k3s 경량 쿠버네티스를 활용해서 클러스터를 어떻게 구축하는지, 그리고 어떤 삽질을 겪었고 어떻게 해결했는지 솔직하게 공유해볼게요. 특히 엣지 컴퓨팅(Edge Computing)이나 저처럼 홈랩(Home Lab)을 운영하는 분들께 큰 도움이 될 거라 생각합니다.

    💡 k3s, 왜 선택했을까? 경량 쿠버네티스의 진짜 매력

    혹시 이런 경험 있으신가요? 작은 라즈베리 파이(Raspberry Pi)나 오래된 미니 PC에 k3s를 포함한 쿠버네티스를 올려보고 싶었는데, 리소스 문제나 복잡한 설치 과정 때문에 포기했던 경험 말이죠. 저도 그랬거든요. 일반적인 쿠버네티스 배포판은 마스터 노드(Master Node) 하나만 해도 꽤 많은 메모리와 CPU를 요구합니다. 그런데 k3s는 이런 제약을 확 낮춰줍니다. 말 그대로 ‘경량(Lightweight)’ 쿠버네티스죠.

    k3s는 Rancher Labs에서 개발한 CNCF(Cloud Native Computing Foundation) 샌드박스 프로젝트로, 리소스가 제한적인 환경, 예를 들면 IoT 디바이스, 엣지 서버, 그리고 저의 사랑스러운 홈랩 같은 곳에 최적화되어 있습니다. 바이너리 파일 하나로 설치가 끝나고, 필요 없는 기능들을 쳐내서 메모리 사용량도 훨씬 적어요. 제가 직접 해보니, 512MB RAM 이상이면 마스터 노드를 구동할 수 있더라고요! 정말 놀랍지 않습니까? 🎉

    k3s 경량 쿠버네티스 클러스터의 간소화된 아키텍처 다이어그램: 마스터 노드와 여러 워커 노드가 연결되어 엣지 및 홈랩 환경에서 효율적으로 동작하는 모습을 보여줍니다.

    k3s 기본 이해: 경량 쿠버네티스의 핵심 개념

    쉽게 말해 k3s는 쿠버네티스(Kubernetes)의 모든 핵심 기능을 제공하면서도, 배포판을 경량화한 버전입니다. k3s는 기존 쿠버네티스가 제공하는 API Server, Controller Manager, Scheduler, etcd 같은 핵심 컴포넌트들을 모두 포함하고 있어요. 하지만 몇 가지 차이점이 있습니다.

    • 단일 바이너리(Single Binary): 설치 파일이 하나로 되어 있어 배포가 정말 간편합니다.
    • SQLite3 내장(Embedded SQLite3): 기본적으로 외부 etcd 대신 SQLite3를 데이터 저장소로 사용합니다. 물론 PostgreSQL, MySQL, etcd 등 외부 DB도 연결할 수 있어요.
    • 불필요한 기능 제거: 레거시(Legacy) 코드나 클라우드 제공업체(Cloud Provider) 관련 기능을 제거하여 경량화했습니다.
    • 컨테이너 런타임(Container Runtime) 변경: 도커(Docker) 대신 containerd(컨테이너디)를 기본 컨테이너 런타임으로 사용합니다.

    이런 특징들 덕분에 k3s는 일반적인 쿠버네티스에 비해 설치도 빠르고 리소스 소모도 적어서, 소규모 프로젝트나 학습용, 그리고 저처럼 홈랩에서 다양한 실험을 해보고 싶을 때 최적의 선택이 됩니다. 컨테이너 오케스트레이션(Container Orchestration)이라는 쿠버네티스의 핵심 개념은 그대로 가져가면서도, 훨씬 쉽게 접근할 수 있게 해주는 거죠.

    실전! k3s 경량 쿠버네티스 클러스터 구축 스텝별 가이드

    자, 이제 직접 k3s 클러스터를 구축해볼 시간입니다. 저는 라즈베리 파이 4B 두 대와 오래된 미니 PC 한 대를 이용해서 클러스터를 만들어봤어요. OS는 모두 Ubuntu Server 22.04 LTS를 사용했습니다. 여러분도 리눅스(Linux) 기반의 어떤 장비든 준비하시면 됩니다.

    1. k3s 마스터 노드(Server) 설치

    가장 먼저 클러스터의 ‘뇌’ 역할을 할 마스터 노드를 설치합니다. k3s는 정말 설치가 간단해서 명령어 한 줄이면 끝나버려요. 💡 팁: 실제 운영 환경에서는 스크립트 내용을 확인하고 사용하는 것이 좋습니다.

    
    curl -sfL https://get.k3s.io | sh -
    

    이 명령어를 실행하면 k3s가 자동으로 설치되고 서비스로 등록되어 실행됩니다. 설치가 끝나면 제대로 작동하는지 확인해볼까요?

    
    sudo k3s kubectl get nodes
    

    기본적으로 k3s는 자체적으로 제공하는 k3s kubectl 명령어를 사용하도록 설정되어 있어요. 처음엔 조금 어색하지만 익숙해지니 괜찮더라고요. k3s가 정상적으로 설치되었다면 마스터 노드가 Ready 상태로 보일 겁니다. 예를 들면 이런 식이죠:

    
    NAME         STATUS   ROLES                  AGE   VERSION
    master-node   Ready    control-plane,master   2m    v1.28.3+k3s1
    

    2. k3s 워커 노드(Agent) 추가

    이제 마스터 노드에 연결할 워커 노드(Agent Node)를 추가해봅시다. 워커 노드 역시 명령어 한 줄로 설치되는데, 다만 마스터 노드와 연결하기 위한 토큰(Token)이 필요해요. 이 토큰은 마스터 노드에서 확인할 수 있습니다.

    
    sudo cat /var/lib/rancher/k3s/server/node-token
    

    이 명령어를 실행하면 긴 문자열이 나올 텐데, 이게 바로 워커 노드를 연결할 때 필요한 토큰입니다. 이 토큰과 마스터 노드의 IP 주소를 알고 있다면, 워커 노드에서 다음 명령어를 실행해주세요. <master-ip> 부분은 마스터 노드의 실제 IP 주소로, <token> 부분은 위에서 확인한 토큰으로 바꿔주셔야 합니다.

    
    curl -sfL https://get.k3s.io | K3S_URL=https://<master-ip>:6443 K3S_TOKEN=<token> sh -
    

    워커 노드 설치 후, 다시 마스터 노드에서 sudo k3s kubectl get nodes 명령어를 실행해보세요. 몇 분 뒤에 워커 노드가 Ready 상태로 보인다면 성공입니다! 🎉

    k3s 마스터 및 워커 노드 구성과 kubectl 환경 설정이 완료된 명령줄 인터페이스 스크린샷입니다.

    3. kubectl 환경 설정으로 편하게 사용하기

    매번 sudo k3s kubectl이라고 치는 게 귀찮으시죠? 저도 그랬거든요. 일반적인 kubectl 명령어를 사용할 수 있도록 환경 설정을 해봅시다. 마스터 노드에서 다음 명령어를 실행하여 kubeconfig 파일을 홈 디렉토리로 복사하고 환경 변수를 설정합니다.

    
    mkdir -p ~/.kube
    sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
    sudo chown $(id -u):$(id -g) ~/.kube/config
    chmod 600 ~/.kube/config
    export KUBECONFIG=~/.kube/config
    

    마지막 export 명령어는 현재 세션에만 적용되므로, 로그인할 때마다 자동으로 적용되게 하려면 .bashrc나 .zshrc 파일에 추가하는 것이 좋습니다. 이제 kubectl get nodes 명령어를 실행해보세요. 잘 동작할 겁니다!

    ⚠️ k3s 설치 중 만난 난관들 & 해결법

    제가 13년차 엔지니어라고 해도 삽질은 피할 수 없죠! k3s 설치 중 저를 괴롭혔던 몇 가지 문제와 해결법을 공유합니다. 혹시 여러분도 비슷한 문제를 겪는다면 참고가 되셨으면 좋겠어요.

    1. 워커 노드가 연결되지 않는 문제 (방화벽!)

      처음엔 마스터 노드와 워커 노드 간 통신이 안 되는 거예요. kubectl get nodes를 하면 워커 노드가 NotReady 상태로 계속 머물러 있었죠. 알고 보니 방화벽(Firewall) 문제였습니다. Ubuntu Server는 기본적으로 ufw(Uncomplicated Firewall)가 활성화되어 있는 경우가 많거든요. k3s는 기본적으로 6443/tcp 포트를 사용하는데, 이 포트가 막혀있었던 겁니다. 🤯

      해결법: 마스터 노드와 워커 노드 모두에서 필요한 포트를 열어줬습니다.

      
      sudo ufw allow 6443/tcp  # k3s API Server
      sudo ufw allow 10250/tcp # Kubelet (필수)
      sudo ufw reload
      

      특히 마스터 노드는 워커 노드의 Kubelet과 통신해야 하므로 10250 포트도 열어주는 것이 좋습니다. 이 문제를 해결하고 나니 워커 노드가 바로 Ready 상태로 바뀌더라고요. 역시 네트워크 문제는 언제나 기본부터 체크해야 합니다.

    2. 토큰(Token) 불일치로 인한 연결 실패

      간혹 워커 노드를 추가할 때 K3S_TOKEN 값을 잘못 입력하는 경우가 있어요. 아니면 복사 붙여넣기 할 때 공백이 들어간다거나요. 그럼 당연히 워커 노드가 마스터에 연결되지 않습니다.

      해결법: 워커 노드에서 k3s 서비스를 중지하고 삭제한 후, 정확한 토큰 값으로 다시 설치했습니다.

      
      sudo systemctl stop k3s-agent
      sudo systemctl disable k3s-agent
      sudo k3s-uninstall.sh # 워커 노드에 설치된 k3s 삭제 스크립트
      # 정확한 토큰으로 다시 설치
      curl -sfL https://get.k3s.io | K3S_URL=https://<master-ip>:6443 K3S_TOKEN=<correct-token> sh -
      
    3. 로그 확인의 중요성

      어떤 문제가 발생하든, 가장 먼저 해야 할 일은 로그를 확인하는 것입니다. k3s 서비스의 로그는 journalctl 명령어를 통해 볼 수 있어요.

      
      sudo journalctl -u k3s --since "10 minutes ago" -f
      # 워커 노드는
      sudo journalctl -u k3s-agent --since "10 minutes ago" -f
      

      로그를 보면 에러 메시지나 경고 메시지를 통해 문제의 원인을 파악할 수 있는 경우가 많습니다. 저는 방화벽 문제도 로그에서 connection refused 같은 메시지를 보고 눈치챘거든요.

    🎉 완성! k3s 클러스터에 애플리케이션 배포하기

    클러스터가 성공적으로 구축되었다면, 이제 간단한 애플리케이션을 배포해서 잘 동작하는지 확인해봐야죠. 저는 웹 서버로 유명한 Nginx(엔진엑스)를 배포해볼게요. 다음 YAML 파일을 nginx-deployment.yaml로 저장합니다.

    
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment
      labels:
        app: nginx
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: nginx:latest
            ports:
            - containerPort: 80
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx-service
    spec:
      selector:
        app: nginx
      ports:
        - protocol: TCP
          port: 80
          targetPort: 80
      type: NodePort
    

    저장한 파일을 클러스터에 배포합니다.

    
    kubectl apply -f nginx-deployment.yaml
    

    배포가 성공적으로 완료되었다면, 파드(Pod)와 서비스(Service)가 잘 생성되었는지 확인해봅시다.

    
    kubectl get pods -o wide
    kubectl get svc
    

    kubectl get svc 결과에서 nginx-service의 NodePort를 확인해보세요. 예를 들어 30000번대 포트가 할당될 겁니다. 이제 워커 노드의 IP 주소와 할당된 NodePort를 이용하여 웹 브라우저에서 Nginx 웹 페이지에 접속할 수 있습니다. 예를 들어, http://<워커-노드-IP>:<NodePort> 이런 식으로요. 드디어 제 홈랩 k3s 클러스터에서 Nginx가 동작하는 걸 보니 정말 뿌듯하더라고요! 🎉

    k3s 클러스터에 Nginx 애플리케이션 배포 후 웹 브라우저 접속 화면 및 kubectl 명령 결과를 보여주는 스크린샷입니다.

    🚀 13년차 엔지니어의 제언: k3s 경량 쿠버네티스 활용처

    k3s를 직접 구축하고 사용해보니, 이 경량 쿠버네티스가 얼마나 유용한지 다시 한번 깨달았습니다. 제가 생각하는 k3s의 주요 활용처는 다음과 같습니다.

    활용 분야 k3s의 장점 예시
    홈랩 (Home Lab) 저렴한 비용으로 쿠버네티스 학습 및 개인 서비스 운영 라즈베리 파이 클러스터, 개인 웹서버, 미디어 서버
    엣지 컴퓨팅 (Edge Computing) 제한된 리소스 환경에서 컨테이너 애플리케이션 배포 및 관리 스마트 팩토리, 스마트 시티 IoT 게이트웨이, 지점 서버
    개발/테스트 환경 로컬 머신이나 가상 머신에 빠르고 가볍게 k3s 클러스터 구축 CI/CD 파이프라인 테스트, 개발자 개인 환경
    IoT (사물 인터넷) 수많은 IoT 디바이스의 애플리케이션 배포 및 업데이트 관리 자율주행 차량, 스마트 농장 센서 데이터 처리

    k3s는 쿠버네티스의 복잡성을 줄여주면서도 강력한 기능을 제공하기 때문에, 위와 같은 환경에서 컨테이너 기반 애플리케이션을 효율적으로 배포하고 관리하는 데 탁월한 선택이 될 수 있습니다. 저처럼 인프라를 직접 만져보고 실험하는 걸 좋아하는 분들에게는 정말 최고의 장난감이 될 거예요. 💡

    물론 k3s가 모든 상황에 완벽한 만능 해결책은 아니에요. 대규모 엔터프라이즈 환경에서는 여전히 표준 쿠버네티스 배포판이 더 적합할 수 있습니다. 하지만 소규모, 리소스 제한 환경에서는 k3s가 제공하는 가치는 엄청나다고 생각합니다. 저도 처음엔 ‘이 작은 걸로 뭘 할 수 있을까?’ 싶었는데, 지금은 제 홈랩의 핵심 인프라가 되었습니다. 다음 글에서는 k3s 위에 Helm(헬름)으로 애플리케이션을 배포하거나 Persistent Storage(영구 스토리지)를 구성하는 방법에 대해서도 다뤄볼 예정이니 기대해주세요!

    k3s의 주요 장점과 활용 사례를 간결하게 요약한 인포그래픽입니다.

    오늘 제가 공유한 삽질 경험과 해결 과정이 여러분의 k3s 경량 쿠버네티스 클러스터 구축에 조금이나마 도움이 되었기를 바랍니다. 혹시 궁금한 점이나 또 다른 삽질 경험이 있다면 언제든지 댓글로 남겨주세요! 13년차의 서버실은 언제나 열려있습니다. 다음 글에서 또 만나요! 👋

  • [Proxmox] LXC 컨테이너 심화 활용: Docker 연동 및 성능 최적화 (Proxmox VE 9.1)

    [Proxmox] LXC 컨테이너 심화 활용: Docker 연동 및 성능 최적화 (Proxmox VE 9.1)

    LXC 컨테이너 심화 활용: Docker 연동 및 성능 최적화 (Proxmox VE 9.1)

    안녕하세요, 13년차 인프라 엔지니어 ’13년차의 서버실’ 블로그 주인장입니다. 오늘도 홈랩에서 밤샘 삽질 끝에 얻어낸 귀한 경험 하나를 공유해드리려고 해요. 💡

    홈랩을 운영하거나 소규모 서버를 돌리시는 분들이라면 Proxmox VE (Virtual Environment)의 매력에 빠져 계실 텐데요. 특히 LXC (Linux Containers)는 가벼운 오버헤드로 높은 성능을 내주기 때문에 저도 애용하고 있습니다. 여기에 Docker까지 연동하면 어떨까요? 효율은 물론이고 관리 유연성까지 챙길 수 있거든요.

    오늘은 Proxmox VE 9.1 환경에서 LXC 컨테이너 안에 Docker를 설치하고, 실제 서비스를 운영하면서 겪었던 삽질과 함께 성능 최적화 팁까지 아낌없이 풀어보겠습니다. LXC와 Docker 연동에 어려움을 겪으셨다면, 이 글이 든든한 가이드가 될 거예요!

    Proxmox VE 호스트에서 LXC 컨테이너와 Docker가 연동되는 아키텍처 다이어그램

    LXC와 Docker, 그리고 그들의 시너지

    먼저 LXC와 Docker가 뭔지 간단하게 짚고 넘어갈게요. 이미 잘 아시는 분들도 계시겠지만, 핵심만 콕 짚어드리겠습니다.

    • LXC (Linux Containers, 리눅스 컨테이너): 리눅스 커널의 컨테이너 기술을 활용한 OS 수준의 가상화예요. 쉽게 말해, 별도의 커널 없이 호스트의 커널을 공유하면서도 독립적인 운영체제 환경을 만들어주는 거죠. 가상 머신(VM)보다 훨씬 가볍고 빠르고, 부팅 시간도 거의 없어서 자원 소모가 정말 적어요.
    • Docker (도커): 애플리케이션 수준의 컨테이너 기술입니다. 특정 애플리케이션과 그에 필요한 모든 종속성(라이브러리, 설정 파일 등)을 하나의 이미지(Image)로 묶어서 어디서든 동일하게 실행되도록 해줘요. 개발 환경과 운영 환경의 불일치 문제를 한 번에 해결하는 거죠.

    그럼 이 둘을 왜 같이 쓸까요? 직접 써본 결과 이런 장점들이 정말 크더라고요.

    특징 LXC + Docker 연동의 장점 기존 방식 대비
    자원 효율성 LXC는 VM보다 오버헤드가 적어서, 그 위에 Docker를 올리면 VM 내 Docker보다 훨씬 적은 자원으로 많은 서비스를 돌릴 수 있어요. VM 내 Docker: 커널 이중화로 자원 낭비
    베어메탈 Docker: 호스트 OS 오염 우려
    격리성 LXC 컨테이너가 OS 수준의 격리를 제공하고, 그 안에 Docker가 또 한 번 애플리케이션 격리를 제공하니 보안성과 안정성이 정말 높아져요. 베어메탈 Docker: 호스트 OS와 Docker 컨테이너 간 완전한 격리가 어려움
    관리 용이성 Proxmox VE의 강력한 LXC 관리 기능(스냅샷, 마이그레이션 등)과 Docker의 애플리케이션 배포/관리 기능을 동시에 누릴 수 있어요. 각각의 장점을 한 번에!

    Proxmox VE 9.1 버전에서는 LXC 컨테이너 기능이 더욱 안정화되고 사용성이 개선되었기 때문에, Docker 연동할 때 시너지가 정말 커져요.

    Proxmox VE 9.1 환경에서 LXC 컨테이너 생성 및 Docker 연동 실전 가이드

    자, 이제 직접 해볼 시간입니다. 제가 홈랩에서 실제로 진행했던 과정을 그대로 따라하시면 돼요. 😎

    1. LXC 컨테이너 기본 생성

    먼저 Proxmox VE 웹 UI에 접속해서 LXC 컨테이너를 생성합니다. OS 템플릿은 Ubuntu 22.04 LTS (Jammy Jellyfish)를 추천할게요. 가장 안정적이고 Docker 지원도 정말 잘 되거든요.

    1. Proxmox VE 웹 UI (https://<Proxmox_IP>:8006) 에 접속합니다.
    2. Datacenter -> pve -> Local (pve) -> CT Templates -> Templates에서 원하는 Ubuntu 템플릿을 다운로드해요.
    3. pve 노드에서 CT 생성 버튼을 클릭합니다.
    4. 일반 설정: Hostname, Password 등을 설정하세요.
    5. 템플릿 설정: 다운로드한 Ubuntu 22.04 LTS 템플릿을 선택해요.
    6. 디스크 설정: 최소 8GB 이상으로 설정해주세요. Docker 이미지를 많이 올릴 계획이라면 더 크게 잡는 게 좋습니다.
    7. CPU 설정: 코어는 1개 이상, CPU units (CPU 유닛)은 기본값(1024)으로 둬도 되지만, 고성능이 필요하면 더 높게 설정할 수 있어요.
    8. 메모리 설정: 최소 512MB 이상을 권장합니다. Docker 앱에 따라 달라지니 유연하게 설정하세요.
    9. 네트워크 설정: Bridge (브리지) 모드로 설정하여 호스트와 동일한 네트워크 대역을 사용하도록 하세요.
    10. 마지막으로 확인을 눌러 LXC 컨테이너를 생성합니다.

    ⚠️ 중요 포인트: 비특권 컨테이너(Unprivileged Container) 설정!

    Docker를 LXC 컨테이너 안에서 안전하게 사용하려면 비특권 컨테이너로 만드는 게 좋아요. 보안상 훨씬 유리하거든요. 하지만 비특권 컨테이너에서 Docker가 제대로 동작하려면 몇 가지 추가 설정이 필요해요.

    1. 컨테이너 생성 후, Proxmox VE 웹 UI에서 해당 LXC 컨테이너를 선택하세요.
    2. 옵션 탭으로 이동합니다.
    3. Features (기능) 항목을 찾아서 편집을 클릭하세요.
    4. 여기서 Nesting (중첩)과 FUSE (파일 시스템 인 유저스페이스)를 활성화하고 확인을 눌러요.

    이 두 가지 옵션이 Docker의 스토리지 드라이버(특히 overlay2)가 LXC 내부에서 정상적으로 작동하도록 하는 핵심이에요. 제가 이걸 몰라서 며칠 밤낮을 삽질했던 기억이 생생하네요… 😅

    Proxmox VE 웹 UI에서 LXC 컨테이너 생성 시 Nesting 및 FUSE 기능을 활성화하는 화면

    2. Docker 설치 및 설정

    LXC 컨테이너가 준비되었다면, 이제 컨테이너에 접속해서 Docker를 설치해봅시다. Proxmox 웹 UI에서 해당 LXC 컨테이너를 선택하고 콘솔 탭으로 이동하면 바로 접속돼요.

    \n# LXC 컨테이너 내부에서 실행
    
    # 패키지 목록 업데이트 및 필요한 도구 설치
    sudo apt update
    sudo apt install -y apt-transport-https ca-certificates curl gnupg lsb-release
    
    # Docker 공식 GPG 키 추가
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
    
    # Docker Stable 저장소 추가
    echo \
      "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
      $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    
    # Docker 엔진 설치
    sudo apt update
    sudo apt install -y docker-ce docker-ce-cli containerd.io
    
    # Docker 서비스 시작 및 부팅 시 자동 시작 설정
    sudo systemctl start docker
    sudo systemctl enable docker
    
    # 현재 사용자에게 Docker 그룹 권한 추가 (선택 사항, sudo 없이 docker 명령어 사용 가능)
    sudo usermod -aG docker $USER
    
    # 변경 사항 적용을 위해 재로그인 또는 새 쉘 시작
    # exit 후 다시 접속하거나, su - $USER 명령으로 적용
    
    # Docker 설치 확인
    docker run hello-world
    

    docker run hello-world 명령을 실행했을 때 성공 메시지가 나온다면 🎉 Docker 설치가 완벽하게 된 거예요!

    3. 비특권(Unprivileged) 컨테이너의 Docker 이슈 해결 (추가 팁)

    위에서 Nesting과 FUSE를 활성화했지만, 간혹 비특권 컨테이너에서 Docker를 사용할 때 권한 문제나 스토리지 관련 이슈가 발생할 수 있어요. 특히 subuid, subgid 매핑이 제대로 안 되어있을 때 그렇습니다. 제가 겪었던 문제 중 하나였죠.

    만약 Docker 컨테이너 실행 시 권한 관련 오류가 발생한다면, Proxmox 호스트에서 다음 설정을 확인해보세요.

    1. Proxmox 호스트에 SSH로 접속합니다.
    2. /etc/subuid와 /etc/subgid 파일에 LXC 컨테이너의 UID/GID 범위가 매핑되어 있는지 확인하세요. 보통 LXC 생성 시 자동으로 추가돼요.
    3. 만약 특정 Docker 컨테이너가 호스트의 특정 디렉토리에 접근해야 하는데 권한 문제가 있다면, /etc/pve/lxc/<VMID>.conf 파일에 다음 라인을 추가하세요. (예시: 100은 컨테이너 ID)
      echo 'lxc.apparmor.profile: unconfined'
      echo 'lxc.mount.auto: cgroup:rw'
      

      이 설정은 컨테이너의 보안 프로파일을 완화하고 cgroup 마운트를 허용하여 Docker가 더 자유롭게 동작하도록 해요. 하지만 보안상 약간 취약해질 수 있으니 신중하게 사용하세요.

    4. 또 다른 방법으로는 Docker root directory를 변경하여 /var/lib/docker 대신 /mnt/data/docker처럼 별도의 마운트 경로를 사용하는 거예요. /etc/docker/daemon.json 파일을 생성(또는 편집)하고 다음 내용을 추가하세요.
      {
        "data-root": "/mnt/data/docker",
        "storage-driver": "overlay2"
      }
      

      그 후 Docker 서비스를 재시작해요: sudo systemctl restart docker. 이 방법은 특히 ZFS 같은 파일 시스템을 사용하는 Proxmox 호스트에서 LXC에 더 안정적인 Docker 스토리지 환경을 제공할 때 정말 유용해요.

    성능 최적화를 위한 팁과 트러블슈팅 ⚠️

    LXC 컨테이너에 Docker를 올리면 기본적으로 성능이 좋지만, 몇 가지 설정을 통해 더 극대화할 수 있어요.

    1. 컨테이너 자원 관리 (CPU, RAM)

    • CPU Core (CPU 코어) 할당: Proxmox VE 웹 UI에서 LXC 컨테이너의 CPU 코어를 필요한 만큼 할당하세요. 너무 많이 할당하면 다른 컨테이너나 VM의 자원을 잠식할 수 있으니, 실제 워크로드에 맞춰 조절하는 게 중요해요.
    • CPU Units (CPU 유닛) 조절: 여러 컨테이너가 CPU를 경쟁할 때, 특정 컨테이너에 더 높은 우선순위를 주고 싶다면 CPU units 값을 높게 설정해요. 기본값 1024가 공평한 분배라면, 2048은 두 배의 우선순위를 갖는 식이죠.
    • Memory (메모리) 및 Swap (스왑): Docker 컨테이너가 사용할 메모리를 충분히 할당해주세요. 스왑은 꼭 필요한 경우가 아니라면 비활성화하거나 최소한으로 설정하는 게 성능에 좋아요. 스왑이 너무 많이 발생하면 I/O 병목 현상이 생기거든요.

    2. I/O 성능 개선 (Storage)

    • SSD 사용: Proxmox VE 호스트의 OS 및 LXC 컨테이너 스토리지는 반드시 SSD (Solid State Drive)를 사용하는 게 좋아요. 특히 Docker는 이미지 다운로드, 레이어 관리 등으로 I/O 작업이 빈번하니 SSD의 이점이 극대화돼요. NVMe SSD라면 더할 나위 없겠죠.
    • LVM-Thin or ZFS: Proxmox에서 LXC 컨테이너를 생성할 때 LVM-Thin이나 ZFS 같은 스토리지를 사용하는 게 좋아요. 스냅샷 기능도 유용하고, 성능도 괜찮거든요. 개인적으로는 ZFS를 선호해요.
    • Bind Mount (바인드 마운트) 활용: Docker 컨테이너가 영구 데이터를 저장해야 한다면, LXC 컨테이너 내부의 디렉토리를 호스트의 물리 디스크에 바인드 마운트하는 게 좋아요. 예를 들어, 호스트에 별도의 데이터 디스크를 마운트하고, 이를 LXC 컨테이너에 다시 마운트한 뒤 Docker 볼륨으로 사용하는 방식이죠.
    \n# Proxmox 호스트에서 LXC 컨테이너 설정 파일 편집
    # /etc/pve/lxc/VMID.conf 에 다음 라인 추가
    lxc.mount.entry: /path/on/host /path/on/lxc none bind,create=dir 0 0
    

    3. 네트워크 설정 최적화

    • Bridge (브리지) 모드: LXC 컨테이너의 네트워크는 기본적으로 브리지 모드를 사용하는 게 가장 일반적이고 성능 저하가 적어요. 호스트의 브리지(vmbr0)에 직접 연결돼서 별도의 NAT 변환 없이 호스트와 동일한 네트워크에서 통신하거든요.
    • MacVLAN (맥브이랜): 특정 Docker 컨테이너에 별도의 물리적 MAC 주소를 할당하여 호스트 네트워크와 동등하게 통신하고 싶다면 MacVLAN을 고려할 수 있어요. 하지만 설정이 조금 복잡하고, 네트워크 장비가 이를 지원해야 해요. 저도 이 부분은 아직 삽질 중이지만, 특정 시나리오에서는 정말 유용할 수 있습니다.

    성능 검증 및 결과 확인 ✅

    모든 설정이 끝났다면, 이제 실제로 Docker 컨테이너를 띄워서 성능을 확인해볼 차례예요. docker stats 명령어로 각 Docker 컨테이너의 자원 사용량을 실시간으로 모니터링할 수 있거든요.

    \n# LXC 컨테이너 내부에서 실행
    docker stats
    

    이 명령어를 실행하면 CPU 사용량, 메모리 사용량, 네트워크 I/O, 블록 I/O 등을 한눈에 볼 수 있어요. 이 외에도 htop이나 glances 같은 도구를 LXC 컨테이너에 설치하여 전체적인 자원 사용량을 확인하는 것도 정말 좋습니다.

    제가 직접 여러 Docker 컨테이너(Nginx, MariaDB, Portainer 등)를 LXC에 올려서 테스트해보니, 확실히 VM에 올렸을 때보다 CPU와 메모리 사용량이 눈에 띄게 줄어드는 거더라고요. 특히 아이들(idle) 상태에서는 거의 자원을 사용하지 않아서 매우 만족스러웠어요. 🎉

    Proxmox LXC 내 Docker 컨테이너의 CPU, 메모리, I/O 성능 모니터링 대시보드

    마무리하며: 13년차 엔지니어의 한마디

    오늘은 Proxmox VE 9.1 환경에서 LXC 컨테이너와 Docker를 연동하고 성능을 최적화하는 방법을 심도 있게 다뤄봤어요. 제가 직접 겪었던 Nesting, FUSE 같은 핵심 삽질 포인트를 해결하는 방법을 공유하면서, 독자분들의 시간을 절약해드리고 싶었거든요. 😅

    이 조합은 가벼운 홈랩부터 소규모 프로덕션 환경까지, 자원을 효율적으로 사용하면서도 높은 유연성을 제공하는 정말 강력한 솔루션이에요. Proxmox의 안정적인 가상화 기반 위에 Docker의 강력한 애플리케이션 관리 능력을 더하는 거죠.

    물론 모든 기술이 그렇듯, 완벽한 솔루션은 없어요. 하지만 LXC와 Docker의 장점을 잘 이해하고 활용한다면, 여러분의 서버실도 더욱 스마트하고 효율적으로 운영될 수 있을 거예요. 다음에는 이 LXC + Docker 환경 위에 Docker Compose (도커 컴포즈)를 활용해서 여러 서비스를 한 번에 배포하는 방법을 다뤄볼까 하는데, 기대해주세요!

    궁금한 점이나 추가로 알고 싶은 내용이 있다면 언제든지 댓글로 남겨주세요. 여러분의 서버실 운영에 조금이나마 도움이 되었으면 좋겠고, 다음 글에서 또 만나요! 👋

    Proxmox LXC와 가상 머신(VM)에서 Docker를 실행할 때의 성능 및 자원 활용 비교 인포그래픽

  • [k8s] ArgoCD 프로덕션 환경 GitOps 베스트 프랙티스: 안정적인 배포와 보안 강화

    [k8s] ArgoCD 프로덕션 환경 GitOps 베스트 프랙티스: 안정적인 배포와 보안 강화

    ArgoCD 프로덕션 환경 GitOps 베스트 프랙티스: 안정적인 배포와 보안 강화

    안녕하세요, 13년차 인프라 엔지니어입니다. 오늘은 쿠버네티스(Kubernetes) 배포의 핵심 툴 중 하나인 ArgoCD와 GitOps에 대해 이야기해보려고 해요. 사실 제가 처음 인프라 엔지니어를 시작했을 때는 배포라고 하면 SSH로 서버에 접속해서 스크립트 돌리고, 수동으로 설정을 변경하고, 문제가 터지면 눈으로 찾아 헤매는 게 일상이었거든요. 그러다 쿠버네티스 세상이 열리고 CI/CD 파이프라인이 중요해지면서, 더 안정적이고 효율적인 배포 방식에 대한 갈증이 커졌습니다.

    수많은 삽질 끝에 제가 정착한 방법이 바로 GitOps였습니다. 그리고 그 중심에는 ArgoCD가 있었죠. 처음엔 이게 뭔가 싶었는데, 막상 써보니까 ‘아, 이거 진짜 편하고 안전하네!’ 싶더라고요. 프로덕션 환경에서 ArgoCD를 안정적으로 운영하고 GitOps 보안을 강화하기 위한 저만의 경험과 베스트 프랙티스를 공유해볼까 합니다. 혹시 쿠버네티스 배포 때문에 밤잠 설치고 계신 분들이 있다면, 이 글이 조금이나마 도움이 되었으면 좋겠네요. 💡

    ArgoCD와 GitOps의 전체 아키텍처는 위 그림처럼 구성됩니다. Git을 중심으로 모든 것이 돌아가는 모습을 보실 수 있어요.

    왜 ArgoCD와 GitOps인가요? – 삽질 끝에 찾은 안정성

    저도 처음에는 Jenkins 같은 전통적인 CI/CD 툴로 쿠버네티스 배포를 시도했어요. 하지만 배포 스크립트 관리도 어렵고, 배포 이력 추적도 쉽지 않더라고요. 특히 긴급 롤백(Rollback) 상황에서는 정말 아찔한 경험도 많았습니다. 😱

    GitOps는 쉽게 말해, Git을 인프라의 ‘단 하나의 진실된 소스(Single Source of Truth)’로 삼는 운영 방식입니다. 모든 인프라와 애플리케이션의 상태를 Git 리포지토리(Repository)에 코드(Code)로 저장하고, Git에 변경사항이 푸시(Push)되면 자동으로 인프라에 반영하는 방식이죠. ArgoCD는 이 GitOps 철학을 쿠버네티스 환경에서 구현해주는 강력한 선언적(Declarative) GitOps 지속적 배포(Continuous Delivery) 툴입니다.

    ArgoCD는 쿠버네티스 클러스터(Cluster) 내부에서 동작하면서, Git 리포지토리의 상태와 실제 클러스터의 상태를 계속 비교합니다. 만약 두 상태가 다르면, Git 리포지토리의 상태(원하는 상태)로 클러스터의 상태를 동기화(Sync)하려고 시도하죠. 이걸 풀 기반(Pull-based) 배포라고 하는데, 기존의 푸시 기반(Push-based) CI/CD 방식보다 훨씬 안정적이고 보안에도 유리합니다. 직접 써보니, 이 방식이 정말 믿음직하더라고요. ✅

    ArgoCD와 GitOps, 쉽게 이해하기

    복잡하게 생각할 것 없이, GitOps는 우리가 늘 쓰던 Git으로 인프라도 관리하자는 이야기입니다. 애플리케이션 코드를 Git으로 관리하듯이, 쿠버네티스 매니페스트(Manifest) 파일들도 Git에 넣고 관리하는 거죠. 이렇게 하면 다음과 같은 장점들이 생깁니다.

    • 버전 관리(Version Control): 모든 변경 이력이 Git에 남으니, 누가 언제 무엇을 바꿨는지 명확하게 알 수 있습니다.
    • 롤백(Rollback) 용이: 문제가 생기면 Git 커밋(Commit)을 되돌리는 것만으로 이전 상태로 쉽게 돌아갈 수 있습니다.
    • 감사(Auditing) 및 보안 강화: 모든 변경이 Git을 통해 이루어지므로, 승인된 변경만 반영될 수 있도록 워크플로우(Workflow)를 구축하기 좋습니다.
    • 단일 진실 공급원(Single Source of Truth): 개발, 운영팀 모두 Git만 보면 현재 인프라 상태를 파악할 수 있습니다.

    ArgoCD는 이 GitOps를 쿠버네티스에서 실현시켜주는 컨트롤러(Controller)입니다. 주요 특징은 다음과 같아요.

    • 선언적(Declarative) 관리: 원하는 상태를 YAML 파일로 선언해두면, ArgoCD가 알아서 그 상태를 유지합니다.
    • 자동 동기화(Automatic Synchronization): Git 리포지토리의 변경을 감지하고 자동으로 클러스터에 반영할 수 있습니다.
    • 시각적인 UI: 웹 UI를 통해 애플리케이션의 배포 상태, 리소스(Resource) 현황, 동기화 이력 등을 한눈에 확인할 수 있습니다. 저처럼 눈으로 확인해야 직성이 풀리는 사람에겐 정말 최고더라고요.
    • 다양한 배포 전략 지원: 롤링 업데이트(Rolling Update), 카나리 배포(Canary Deployment), 블루/그린 배포(Blue/Green Deployment) 등 다양한 배포 전략을 연동하여 구현할 수 있습니다.

    프로덕션 환경을 위한 ArgoCD 설정 팁

    이제 본격적으로 프로덕션 환경에서 ArgoCD를 효과적으로 사용하는 베스트 프랙티스를 공유해볼게요. 제가 직접 겪으면서 터득한 노하우들이니, 꼭 참고하시면 좋겠습니다.

    1. Git Repository 구조화: Monorepo vs. Multirepo

    Git 리포지토리를 어떻게 구성할지는 GitOps 전략의 첫 단추입니다. 크게 모노레포(Monorepo)와 멀티레포(Multirepo) 두 가지 방식이 있어요.

    • 모노레포(Monorepo): 모든 애플리케이션과 인프라 설정 파일을 하나의 Git 리포지토리에 저장하는 방식입니다. 초기 설정이 간단하고, 모든 것을 한곳에서 관리할 수 있다는 장점이 있습니다.
    • 멀티레포(Multirepo): 각 애플리케이션이나 환경별로 별도의 Git 리포지토리를 사용하는 방식입니다. 팀별 권한 분리나 대규모 서비스 운영에 유리할 수 있습니다.

    저 같은 경우, 초기에는 모노레포로 시작했다가 규모가 커지면서 멀티레포 형태로 전환했어요. 하지만 ArgoCD를 통해 여러 애플리케이션을 관리할 때는 애플리케이션별 Git 리포지토리 + 인프라 설정용 Git 리포지토리를 분리하는 방식이 가장 효율적이라고 느꼈습니다. 프로덕션 환경에서는 GitOps 보안과 관리의 용이성을 위해 인프라 설정과 애플리케이션 코드를 분리하는 것을 추천합니다.

    예시: 인프라 설정 Git 리포지토리 구조

    ├── applications # ArgoCD Application 정의
    │   ├── app1.yaml
    │   ├── app2.yaml
    │   └── ...
    ├── environments
    │   ├── dev
    │   │   ├── kustomization.yaml
    │   │   ├── namespace.yaml
    │   │   └── ...
    │   ├── stage
    │   │   ├── kustomization.yaml
    │   │   └── ...
    │   └── prod
    │       ├── kustomization.yaml
    │       └── ...
    └── base # 공통 설정
        ├── deployment.yaml
        ├── service.yaml
        └── ...
    

    위 다이어그램은 제가 주로 사용하는 Git Repository 구조를 시각적으로 보여줍니다. 환경별로 설정을 분리하고, 공통 설정은 base에 두는 방식이에요.

    2. 환경별 분리 및 Kustomize/Helm 활용

    개발(dev), 스테이징(stage), 프로덕션(prod) 환경은 각각 다른 설정(리소스 요구 사항, 환경 변수 등)을 가집니다. 이를 효과적으로 관리하려면 Kustomize나 Helm을 적극적으로 활용해야 합니다.

    • Kustomize: 기존 YAML 파일을 수정하지 않고 덮어쓰기(Overlay) 방식으로 환경별 설정을 관리하는 데 매우 유용합니다. base 디렉터리에 공통 설정 파일을 두고, 각 환경별 overlays 디렉터리에서 필요한 부분만 변경하는 방식은 정말 깔끔하죠.
    • Helm: 재사용 가능한 쿠버네티스 애플리케이션 패키징(Packaging) 도구입니다. 데이터베이스(Database)나 메시지 큐(Message Queue)처럼 공통적으로 사용되는 미들웨어(Middleware)를 배포할 때 매우 편리합니다. 저도 처음엔 Helm이 좀 어렵게 느껴졌는데, 익숙해지니 없으면 안 되는 존재가 되더라고요.

    ArgoCD 애플리케이션 정의에서 Kustomize나 Helm을 소스(Source)로 지정하면, ArgoCD가 알아서 해당 툴을 사용해서 매니페스트를 렌더링(Rendering)하고 배포해줍니다. 🚀

    apiVersion: argoproj.io/v1alpha1
    kind: Application
    metadata:
      name: my-app-prod
      namespace: argocd
    spec:
      project: default
      source:
        repoURL: https://github.com/my-org/my-infra-gitops.git
        targetRevision: HEAD
        path: environments/prod/my-app # Kustomize overlay 경로
      destination:
        server: https://kubernetes.default.svc
        namespace: my-app-prod
      syncPolicy:
        automated:
          prune: true
          selfHeal: true
        syncOptions:
          - CreateNamespace=true
    

    3. Sync Options와 Health Checks

    ArgoCD의 syncPolicy는 배포의 안정성을 결정하는 중요한 부분입니다. 프로덕션 환경에서는 다음 옵션들을 신중하게 설정해야 합니다.

    • automated.prune: true: Git 리포지토리에서 삭제된 리소스를 클러스터에서도 자동으로 삭제합니다. 클러스터의 불필요한 리소스 잔여물을 방지해줍니다.
    • automated.selfHeal: true: 클러스터의 상태가 Git 리포지토리의 상태와 다를 경우, ArgoCD가 자동으로 Git의 상태로 되돌립니다. 누군가 수동으로 클러스터 설정을 변경했을 때 원래대로 복구해주는 강력한 기능이죠. GitOps의 핵심 정신과 일치하는 부분입니다.
    • syncOptions: - CreateNamespace=true: 해당 네임스페이스(Namespace)가 없으면 ArgoCD가 자동으로 생성하도록 합니다.
    • 커스텀 헬스 체크(Custom Health Checks): 애플리케이션이 단순히 배포되었다고 끝이 아닙니다. 실제로 정상 작동하는지 확인하는 헬스 체크가 중요하죠. ArgoCD는 기본적으로 Pod의 Readiness/Liveness Probe를 활용하지만, 경우에 따라 ConfigMap에 커스텀 헬스 체크를 정의하여 더 정교한 상태 감지를 할 수 있습니다.

    4. Rollback 전략

    아무리 잘 준비해도 문제는 발생하기 마련이죠. 이때 빠르고 안전하게 롤백하는 것이 중요합니다. ArgoCD 환경에서의 롤백은 크게 두 가지 방식이 있어요.

    1. Git Revert: 가장 권장되는 방식입니다. 문제가 발생한 커밋을 Git에서 되돌리면(Revert) ArgoCD가 이를 감지하고 자동으로 이전 상태로 클러스터를 동기화합니다. 이 방식은 Git의 변경 이력이 그대로 남으므로 감사 추적에도 유리합니다.
    2. ArgoCD UI 롤백: ArgoCD 웹 UI에서 특정 애플리케이션의 History and Rollback 탭을 통해 이전 동기화 지점(Sync Point)으로 롤백할 수 있습니다. 긴급 상황에서 빠르게 대처할 수 있는 방법이지만, Git의 변경 이력에는 남지 않으므로 나중에 Git Revert로 맞춰주는 게 좋습니다.

    저도 예전에 새벽에 긴급 롤백을 해야 했던 적이 있었는데, Git Revert 하나로 모든 상황이 깔끔하게 정리되었을 때의 안도감이란… 정말 겪어봐야 알 수 있습니다. 👍

    GitOps 보안 강화: ArgoCD 프로덕션 환경 보안 설정

    프로덕션 환경에서는 GitOps 보안이 최우선 고려사항입니다. ArgoCD를 통해 모든 것이 배포되므로, ArgoCD 자체의 보안 설정은 물론 주변 환경과의 연동도 중요합니다.

    1. RBAC (Role-Based Access Control)

    ArgoCD는 자체적인 RBAC(Role-Based Access Control)를 지원합니다. 이를 통해 누가 어떤 애플리케이션을 조회, 동기화, 삭제할 수 있는지 세밀하게 권한을 제어할 수 있어요. argocd-cm ConfigMap이나 argocd-rbac-cm ConfigMap을 수정하여 정책을 정의합니다.

    또한, ArgoCD 프로젝트(Project)를 활용하여 애플리케이션들을 논리적으로 묶고, 프로젝트별로 RBAC 정책을 적용하면 관리 효율성과 보안을 동시에 잡을 수 있습니다. 예를 들어, 개발팀은 dev-project에만 접근 가능하고, 운영팀은 prod-project에만 접근 가능하도록 설정하는 식이죠.

    # argocd-rbac-cm ConfigMap 예시
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: argocd-rbac-cm
      namespace: argocd
    data:
      policy.csv: |
        p, role:admin, applications, *, */*, allow
        p, role:dev, applications, get, dev-project/*, allow
        g, myuser, role:dev
      policy.default: role:readonly
    

    2. Secret Management (외부 Secret 연동)

    민감한 정보인 시크릿(Secret)을 Git 리포지토리에 평문으로 저장하는 것은 절대 금물입니다. 🙅‍♂️ GitOps 보안을 위해 외부 시크릿 관리 솔루션과 연동하는 것이 필수입니다.

    • Sealed Secrets: 클러스터에 배포된 컨트롤러가 시크릿을 암호화하고, Git에 암호화된 시크릿을 저장합니다. 암호화된 시크릿은 해당 클러스터에서만 복호화(Decrypt)될 수 있어 안전합니다. 제가 홈랩에서도 가장 즐겨 쓰는 방식이에요.
    • External Secrets Operator: AWS Secrets Manager, Azure Key Vault, Google Secret Manager, HashiCorp Vault 등 클라우드(Cloud) 기반 시크릿 관리 서비스와 연동하여 시크릿을 쿠버네티스 시크릿으로 동기화합니다. 프로덕션 환경에서는 이 방식이 가장 일반적입니다.

    어떤 방법을 선택하든, 절대 시크릿을 Git에 직접 올리는 일은 없어야 합니다! 이건 제가 정말 피땀 흘려 배운 교훈입니다. ⚠️

    3. Private Repository 접근

    대부분의 프로덕션 환경에서는 프라이빗 Git 리포지토리(Private Git Repository)를 사용합니다. ArgoCD가 이 리포지토리에 접근하려면 인증 정보가 필요하겠죠. 다음 방법들을 사용할 수 있습니다.

    • SSH 키(SSH Key): 가장 일반적이고 강력한 방법입니다. ArgoCD에 SSH 키를 등록하고, 해당 키를 사용하여 리포지토리에 접근합니다.
    • HTTPS with Username/Password 또는 Personal Access Token (PAT): Git 서비스에서 발급받은 PAT를 ArgoCD에 등록하여 사용할 수 있습니다. 보안상 일반적인 비밀번호보다는 PAT를 사용하는 게 좋습니다.

    인증 정보를 ArgoCD에 등록할 때는 쿠버네티스 시크릿으로 안전하게 관리해야 합니다. 당연한 이야기지만, 이걸 놓쳐서 문제가 되는 경우를 꽤 많이 봤거든요. 😅

    ArgoCD 트러블슈팅: 제가 겪었던 문제들 (그리고 해결책)

    13년차 엔지니어라고 해도 삽질은 피할 수 없는 운명이죠. ArgoCD를 쓰면서도 여러 번 머리를 쥐어뜯었습니다. 몇 가지 흔한 문제와 해결책을 공유해볼게요.

    • 문제: ImagePullBackOff 에러 (프라이빗 레지스트리)
      상황: 배포된 Pod에서 프라이빗 컨테이너 이미지 레지스트리(Private Container Image Registry)의 이미지를 당겨오지 못하고 ImagePullBackOff 에러가 발생하는 경우.
      해결: 해당 네임스페이스에 ImagePullSecrets를 제대로 설정했는지 확인해야 합니다. ArgoCD 애플리케이션이 배포될 때 이 시크릿이 같이 생성되도록 매니페스트에 포함하거나, 수동으로 시크릿을 생성하고 Pod Spec에 추가해야 합니다. 저는 주로 ArgoCD가 CreateNamespace=true와 함께 시크릿도 함께 배포하도록 설정합니다.

    • 문제: Resource is not available 또는 Failed to install CRD
      상황: 애플리케이션 배포 시 커스텀 리소스 정의(CRD: Custom Resource Definition)가 먼저 설치되어야 하는데, 순서가 맞지 않아 발생하는 에러.
      해결: ArgoCD의 Sync Waves 기능을 활용하면 배포 순서를 제어할 수 있습니다. CRD를 먼저 배포하고, 그 이후에 CRD를 사용하는 애플리케이션 리소스를 배포하도록 설정하는 거죠. 예를 들어, CRD는 sync-wave: "-1", 일반 리소스는 sync-wave: "0"으로 설정하면 됩니다. 이 기능을 알게 된 후로 정말 속이 시원했습니다. 🎉

    • 문제: 롤백 후에도 문제가 지속됨
      상황: Git Revert나 ArgoCD UI 롤백을 했는데도 애플리케이션이 정상 상태로 돌아오지 않는 경우.
      해결: 롤백 대상이 되는 커밋이 정말 이전의 ‘정상’ 상태를 가리키는지 확인해야 합니다. 때로는 환경 변수나 외부 의존성(예: 데이터베이스 스키마 변경) 때문에 롤백만으로는 해결되지 않을 수 있거든요. 이럴 때는 문제 발생 시점을 정확히 파악하고, 관련된 모든 변경사항(Git, DB 스키마, 외부 서비스 설정 등)을 함께 되돌려야 합니다. 그리고 롤백 후 ArgoCD UI에서 애플리케이션의 Health 상태와 Events 탭을 꼼꼼히 확인하는 습관을 들이는 게 좋습니다.

    결과 및 검증: 안정적인 배포, 이제 Git만 바라봅니다.

    ArgoCD와 GitOps 베스트 프랙티스를 적용하고 나니, 정말 배포 과정이 안정적이고 예측 가능해졌습니다. 더 이상 불안에 떨며 배포 버튼을 누를 필요가 없어졌죠. ✅

    배포가 완료되면 ArgoCD 웹 UI에서 각 애플리케이션의 상태를 한눈에 확인할 수 있습니다. 모든 리소스가 Healthy 상태이고, Synced 상태인지 확인하는 것이 중요해요. 혹시 OutOfSync 상태라면, 어떤 리소스가 Git과 다른지 명확하게 보여주므로 문제 파악이 매우 쉽습니다. 이 시각적인 피드백(Feedback) 덕분에 트러블슈팅 시간도 대폭 줄었습니다.

    ArgoCD UI에서 모든 애플리케이션이 건강하고(Healthy) 동기화(Synced)된 상태를 보여주는 화면입니다. 이 화면을 볼 때마다 뿌듯하더라고요!

    실제로 저는 홈랩에서 여러 서비스를 ArgoCD로 관리하고 있는데, Git에 커밋만 하면 알아서 배포가 되고, 문제가 생겨도 Git Revert 한 번으로 해결되는 경험은 정말 혁신적이었습니다. CI/CD 파이프라인의 완성도를 높이는 데 ArgoCD가 결정적인 역할을 했다고 생각합니다.

    ArgoCD GitOps를 프로덕션 환경에 적용하기 위한 핵심 베스트 프랙티스를 요약한 인포그래픽입니다.

    마무리: GitOps 여정, 계속됩니다

    오늘은 ArgoCD 프로덕션 환경 GitOps 베스트 프랙티스에 대해 저의 경험을 바탕으로 이야기해봤습니다. 안정적인 배포와 GitOps 보안 강화를 위해 Git 리포지토리 구조화, 환경별 설정 관리, Sync Policy, 롤백 전략, RBAC, 시크릿 관리 등 다양한 측면을 다루었네요.

    처음에는 복잡하게 느껴질 수도 있지만, 한 번 제대로 구축해두면 개발팀과 운영팀 모두에게 엄청난 효율성과 안정성을 가져다줄 겁니다. 저도 아직 배워야 할 것이 많고, 계속해서 새로운 기술을 실험하고 있습니다. 이 글이 여러분의 쿠버네티스 배포 여정에 작은 등불이 되기를 바랍니다. 궁금한 점이나 공유하고 싶은 삽질 경험이 있다면 언제든지 댓글로 남겨주세요! 다음에는 ArgoCD와 함께 CI/CD 파이프라인을 더욱 자동화하는 방법에 대해 다뤄보겠습니다. 그때까지 모두 즐거운 서버실 라이프 즐기시길 바랍니다! 😊