,

[OKE 인프라 학습 시리즈] 관리비 $0로 쿠버네티스 띄우기 — OCI Always Free로 OKE 클러스터 구축

이 글의 위치: 기술 블로그 → Infra · OKE 인프라 학습 시리즈의 실습 1편. 왜 다시 상시 가동 쿠버네티스로 옮겼는지를 정리한 도입부에 이어, 이번 편부터는 직접 손을 움직인다. 목표는 하나 — 관리비·노드비 $0로 OKE를 띄우는 것.

이번 편은 실제로 성공한 절차만 남겼다. 중간에 며칠씩 헤맨 지점은 "⚠️ 함정" 으로 따로 표시해 뒀다.

무료의 조건은 딱 3가지

OCI의 setup-oke.sh 같은 스크립트 기본값은 대부분 유료 구성이다. 무료로 가려면 아래 3개를 반드시 지켜야 한다. 하나라도 어기면 과금되거나 프로비저닝이 실패한다.

항목 무료 조건 어기면
클러스터 타입 Basic (BASIC_CLUSTER) Enhanced는 시간당 $0.10 관리비
노드 shape VM.Standard.A1.Flex (Ampere A1 = arm64) E4.Flex 등은 유료
노드 총합 ≤ 4 OCPU / 24GB (예: 2 OCPU × 2노드) Always Free 한도 초과 → 과금

리전은 춘천(ap-chuncheon-1) 을 권장한다. 서울(ap-seoul-1)은 A1 무료 용량 부족(Out of host capacity)이 잦다. 그리고 A1은 arm64 이므로, 그 위에 올릴 서비스 컨테이너 이미지는 반드시 linux/arm64로 빌드해야 한다. 이 arm64 제약은 뒤에 나오는 채팅 백엔드 배포 편에서 다시 발목을 잡는다.

인증 — 세션 토큰 말고 API 키를 쓰자

제일 크게 헤맨 곳이다. 처음엔 oci session authenticate(브라우저 세션 토큰)로 시도했는데 세 가지 이유로 계속 막혔다.

  • MFA: 로그인마다 휴대폰 승인이 필요하다.
  • 60분 만료: 프로비저닝 도중 토큰이 죽는다.
  • 유저당 API 키 3개 한도: 세션 인증은 매번 임시 공개키를 업로드하는데, 재시도가 쌓이면 You can not create ApiKey as maximum quota limit of 3 has been reached로 실패한다.

결론: API 키 방식이 훨씬 안정적이다. 만료도, MFA 반복도 없다.

mkdir -p ~/.oci
openssl genrsa -out ~/.oci/oke_deploy_key.pem 2048
chmod 600 ~/.oci/oke_deploy_key.pem
openssl rsa -pubout -in ~/.oci/oke_deploy_key.pem -out ~/.oci/oke_deploy_key_public.pem
# 콘솔 등록 확인용 fingerprint
openssl rsa -pubout -outform DER -in ~/.oci/oke_deploy_key.pem | openssl md5 -c

공개키는 콘솔 → 우측 상단 프로필 → My profile → API keys → Add API key 에 붙여넣는다. 그다음 ~/.oci/config[DEFAULT] 프로필(user·fingerprint·tenancy·region·key_file)을 쓰고 확인한다.

oci iam region list --query 'data[0].name' --raw-output   # 값이 나오면 인증 성공

⚠️ 함정 — API 키는 "로그인 열쇠"일 뿐이다. 이미 API 키가 3개면 하나 지워야 추가된다. 그런데 안 쓰는 키를 지워도 클러스터·컴파트먼트엔 아무 영향이 없다. API 키는 리소스가 아니라 인증 수단이기 때문이다. 또 방금 등록한 키로 첫 호출 시 NotAuthenticated(401)가 날 수 있는데, 수십 초 전파 지연이니 잠깐 뒤 재시도하면 된다.

네트워크가 클러스터보다 먼저다

GKE는 기본 VPC로 대충 넘어갔지만, OKE는 VCN이 먼저 존재해야 클러스터를 만들 수 있다. 그래서 setup-oke.sh 한 스크립트가 아래 순서를 강제한다.

  1. OCIR 리포지토리 생성 → <리전키>.ocir.io/<namespace>/<repo>
  2. VCN(10.0.0.0/16) + Internet Gateway + NAT Gateway + 라우트테이블(공/사설) + Security List(6443/80/443) + 서브넷 2개(public 10.0.0.0/24, private 10.0.16.0/20)
  3. OKE Basic 클러스터 생성 (5~10분)
  4. A1.Flex 노드풀 2노드 생성
  5. IAM 배포 그룹/유저/정책 (CI에서 OCIR push용)

무료의 핵심은 아래 3개 플래그다.

bash setup-oke.sh \
  --compartment-ocid "ocid1.compartment.oc1..<SERVER_COMPARTMENT>" \
  --tenancy-ocid "ocid1.tenancy.oc1..<TENANCY>" \
  --region ap-chuncheon-1 \
  --cluster-name chat --repo-name chat \
  --cluster-type basic \
  --node-shape VM.Standard.A1.Flex --node-ocpus 2 --node-memory 12 --node-count 2 \
  --output-env ./output/.env.oci

⚠️ 함정 — OCID 캡처가 조용히 깨진다. --wait-for-state가 출력하는 "Action completed. Waiting until…" 메시지는 stderr로 나온다. 이걸 2>&1로 OCID 캡처에 섞으면, 다음 단계가 깨진 OCID를 받아 조용히 실패한다.

# ✅ 올바른 캡처 — stderr는 화면으로, stdout(OCID)만 변수로
VCN_OCID=$(oci network vcn create ... --wait-for-state AVAILABLE --query 'data.id' --raw-output)
# ❌ 이렇게 하면 대기 메시지가 OCID에 섞여 깨짐
# VCN_OCID=$(oci network vcn create ... --query 'data.id' --raw-output 2>&1)

⚠️ 함정 — Identity Domain 유저 이메일. 요즘 테넌시는 IDCS(Identity Domain) 기반이라 oci iam user create--email이 없으면 "The primary email must be specified"로 실패한다. 게다가 IDCS는 .local TLD를 거부하므로 chat-ci@oke.local 대신 chat-ci@example.com 같은 형식을 써야 한다.

kubeconfig 연결과 비용 확인

oci ce cluster create-kubeconfig \
  --cluster-id "ocid1.cluster.oc1.ap-chuncheon-1.<CLUSTER>" \
  --file "$HOME/.kube/config" --region ap-chuncheon-1 \
  --token-version 2.0.0 --kube-endpoint PUBLIC_ENDPOINT

export KUBECONFIG="$HOME/.kube/config"
kubectl get nodes -o wide
NAME          STATUS   VERSION   OS-IMAGE                  ARCH
10.0.26.149   Ready    v1.36.1   Oracle Linux Server 9.7  arm64
10.0.29.7     Ready    v1.36.1   Oracle Linux Server 9.7  arm64

두 개의 A1(arm64) 노드가 모두 Ready — 무료 쿠버네티스 완성이다. 비용은 세 줄로 요약된다.

  • 클러스터: BASIC_CLUSTER = 관리비 $0
  • 노드: A1.Flex 총 4 OCPU / 24GB = Always Free 한도 내 = $0
  • Cost Analysis에서 최근 1년 "There are no costs" 확인 (OCI 공식 Always Free 문서에서 A1 한도 기준을 확인할 수 있다)

다음 편 예고

클러스터는 떴지만 아직 바깥에서 접근할 수 없다. 다음 편 인그레스 + 도메인 + HTTPS에서 Traefik LoadBalancer(OCI 무료 10Mbps LB)와 cert-manager로 https:// 진입점을 만든다. 그리고 이 모든 반복 프로비저닝을 한 명령으로 묶은 이야기는 시리즈 마지막 Provider 계층만 교체하는 스킬 설계 편에서 다룬다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다