전체 목차

 

지난 9개의 챕터에서 쿠버네티스 클러스터 환경을 구축 하고 nginx, springboot pod를 배포해 보았습니다.

이제 실무에서 많이 사용하는 React SPA 앱에서 Springboot RestFul API를 호출해서 결과를 보여주는 간단한 프로잭트를 만들어서 배포하고 작동을 테스트해 보겠습니다.

 

1. Springboot 수정

1.1. CORS 설정 추가

브라우저에서 실행되는 React 앱이 다른 포트나 IP의 API를 호출하면 CORS(Cross-Origin Resource Sharing) 보안 정책에 걸립니다. Spring Boot 소스 코드를 다음과 같이 수정해야 합니다.

 

config 패키지를 생성하고 WebConfig.java 파일을 추가 합니다.

@Configuration
public class WebConfig implements WebMvcConfigurer {

    /**
     * 브라우저에서 호출 시 CORS (Cross-Origin Resource Sharing) 보안 정책 위배를 해소하기 위한 설정
     * @param registry : CorsRegistry 객체
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOriginPatterns("*") // 모든 도메인에서 접근 허용(보안 주의)
                .allowedMethods("GET", "POST", "PUT", "DELETE")
                .allowedHeaders("*")
                .allowCredentials(true);
    }
}

실무 에서는 더 복잡하고 타이트 하게 해야 하지만 Spring Security 를 다루는 프로잭트가 아니기 때문에 간단하게 모든 URL에 대해서 요청을 허용하는 설정을 추가 합니다.

당연히 실무에서는 이렇게 간단하게 구성하지 않습니다.

 

2. React 프로잭트 생성

React 앱은 Gemini CLI 의 도움을 받아서 간단하게 작성했습니다.

더보기
더보기

Gemini CLI를 선택한 이유

익숙함의 차이 일 수도 있지만, 여러가지 AI를 이용해 보았지만 Gemini CLI가 가장 빠르게 원하는 답을 주는 것 같습니다. 

특히 VSCode에 플러그인드로 설치된 Gemini Code Assist 는 결과물이 나오는데 상당히 오랜 시간이 걸리고 자기가 만든 코드도 헷갈리는(?) 문제가 있는것 같습니다.

단점은 GUI 환경이 아니기 때문에 바이너리 파일을 채팅 창에 직접 붙혀넣지 못하고, 실행 인스턴스가 끝나면 그 채팅 내용은 모두 휘발된다는 단점이 있습니다.

바이너리 파일을 인식시키는 방법은 특정 디렉토리에 파일을 위치 시키고 그 파일을 읽어서 확인해 달라고 하면 가능합니다.

작업 내용이 휘발되는 문제는, 기본적인 사항을 GEMINI.md 파일에 기술해 두면 GEMINI가 실행하면서 현재 디렉토리의 GEMINI.md 파일의 내용을 참조 하는 방식을 사용 할 수 있습니다.

프로잭트의 내용을 파악하는 것은 필요 할 때 지시해도 되고, 기본적인 질의를 하면 알아서 디렉토리에서 파일을 찾아내서 파악하는 속도가 워낙 빠르기 때문에 큰 문제는 없습니다.

웹 프로잭트는 React, Vite 라이브러리를 사용하도록 하겠습니다.

  • Framtwork : React
  • Variant : TypeScript
  • Use rolldown-vite : N

 

PS C:\Users\user\Projects\k8sTest\HelloKubernates> npm create vite@latest hello-kubernates-web -- --template react

> npx
> create-vite hello-kubernates-web react

|
o  Select a framework:
|  React
|
o  Select a variant:
|  TypeScript
|
o  Use rolldown-vite (Experimental)?:
|  No
|
o  Install with npm and start now?
|  No
|
o  Scaffolding project in C:\Users\user\Projects\k8sTest\HelloKubernates\hello-kubernates-web...
|
—  Done. Now run:

  cd hello-kubernates-web
  npm install
  npm run dev

PS C:\Users\user\Projects\k8sTest\HelloKubernates>

 

간단한 명령 몇줄로 Vite + React 앱이 생성되었습니다.

마지막 Install with npm and start now? 에 Yes를 선택하거나 마지막 세줄을 실행

cd hello-kubernates-web
npm install
npm run dev

브라우저로 접속 하면 아래와 같은 화면이 나옵니다.

 

전체 프로잭트의 구조는 아래와 같습니다.

HelloKubernates/ (프로젝트 루트)
├── api/              
│   └── HelloKubernetesApi/  <-- Springboot 프로잭트 루트 입니다.(IntelliJ)
├── web/
│   └── hello-kubernates-web/  <-- React 프로잭트 루트 입니다. (VSCode)
└── GEMINI.md <-- GEMINI CLI 에게 전달할 전체적인 내용이 들어있는 파일입니다.

 

이제 본격적으로 GEMINI CLI의 힘을 빌려보겠습니다.

GEMINI 는 GEMINI.md 파일이 있는 디렉토리에서 실행합니다.

Springboot와 React 프로잭트 폴더보다 상위에서 GEMINI를 실행하는 이유는 웹과 API간의 전체적인 연동까지 고려해서 진행하도록 하기 위함입니다.
GEMINI.md 파일에는 각각 프로잭트의 설명, 프로잭트 루트 경로, 기술 스텍, 같은 것을 미리 정의해 두면 매번 실행할 때 마다 설명하지 않아도 됩니다.


GEMINI.md 파일의 내용입니다.(참고만 하세요)

# Project: Spring Boot Hybrid K8s Application (TS Version)

## Core Principles
- 모든 답변은 **한국어**로 작성해 주세요.
- 개발 환경: **Windows 11 (PowerShell 7, VS Code)**
- 인프라 환경: **Hybrid Kubernetes Cluster (x86_64 + ARM64)**

## 1. 프로젝트 개요
- 이종 아키텍처(AMD64 & ARM64) 쿠버네티스 클러스터 검증을 위한 테스트 프로젝트입니다.
- React(Vite) + **TypeScript** 프론트엔드가 Spring Boot API를 호출하여 클러스터 정보를 표시합니다.

## 2. 프로젝트 구조 및 경로
- **Frontend (React + Vite + TS):** `./web/hello-kubernates-web/`
  - **TypeScript 기반**, API 응답 데이터 구조를 Interface로 정의하여 관리.
  - API 호출 주소는 환경 변수(`VITE_API_URL`)로 관리.
- **Backend (Spring Boot):** `./api/HelloKubernetesApi/`
  - Java 21 기반, REST API 제공 및 CORS 설정 포함.

## 3. 쿠버네티스 클러스터 정보 (Hybrid)
- **Master (Control Plane):** Intel Xeon (AMD64) - `192.168.2.100`
- **Worker Nodes:** Raspberry Pi 5 (ARM64) - `101, 102, 103`
- **Deployment Requirement:** 모든 이미지는 `linux/amd64`와 `linux/arm64`를 모두 지원하는 **Multi-Arch Build**가 필수입니다.

## 4. CI/CD 및 형상 관리
- **SCM:** GitHub / **Registry:** Docker Hub
- **CI/CD:** GitHub Actions (Buildx 활용 멀티 아키텍처 빌드 및 푸시)


그 외에 프로잭트 내에 기술되어 있는 내용은 적지 않아도 "api 프로잭트를 분석해주세요" 하면 순식간에 분석합니다.

 

GEMINI CLI 실행 (GEMINI.md 파일이 있는 곳에서 실행합니다.)

PS C:\Users\user\Projects\k8sTest\HelloKubernates> dir

    Directory: C:\Users\user\Projects\k8sTest\HelloKubernates

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----        2026-01-16 오후 10:27                api
d----        2026-01-27  오후 9:32                web
-a---        2026-01-27  오후 9:25           1022 GEMINI.md

PS C:\Users\user\Projects\k8sTest\HelloKubernates> gemini

 ███            █████████  ██████████ ██████   ██████ █████ ██████   █████ █████
░░░███         ███░░░░░███░░███░░░░░█░░██████ ██████ ░░███ ░░██████ ░░███ ░░███
  ░░░███      ███     ░░░  ░███  █ ░  ░███░█████░███  ░███  ░███░███ ░███  ░███
    ░░░███   ░███          ░██████    ░███░░███ ░███  ░███  ░███░░███░███  ░███
     ███░    ░███    █████ ░███░░█    ░███ ░░░  ░███  ░███  ░███ ░░██████  ░███
   ███░      ░░███  ░░███  ░███ ░   █ ░███      ░███  ░███  ░███  ░░█████  ░███
 ███░         ░░█████████  ██████████ █████     █████ █████ █████  ░░█████ █████
░░░            ░░░░░░░░░  ░░░░░░░░░░ ░░░░░     ░░░░░ ░░░░░ ░░░░░    ░░░░░ ░░░░░

Tips for getting started:
1. Ask questions, edit files, or run commands.
2. Be specific for the best results.
3. /help for more information.

ℹ Code Assist login required.
  Attempting to open authentication page in your browser.
  Otherwise navigate to:
  https://accounts.google.com/o/oauth2/v2/auth?redirect_uri=http%3A%2F%2Flocalhost%3A11651%2Foauth2callback&access_type=offline&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform%20https
  3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile&state=ff292424a8e8c9a4cd689e41dd9c0b090552cc808c9ba7833a4f9f58b81e4670&response_type
  code&client_id=681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com

ℹ Waiting for authentication...

ℹ Authentication succeeded
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ You have successfully logged in with Google. Gemini CLI needs to be restarted. Press 'r' to restart, or 'escape' to choose a different auth method.                                                │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

GEMINI CLI를 처음 실행하거나 버전을 업그레이드 했다면 다시 구글계정으로 인증을 해야 할 수 있습니다.

새로 인증을 했다면 r 키를 눌르면 인스턴스가 다시 시작 됩니다.

 

GEMINI CLI 에게 시킬 작업 내용입니다.

웹 프로잭트 (hello-kubernetes-web) 에서 해야 할 내용입니다.

1. API 연동 뼈대 생성 (CORS 고려)
Spring Boot API를 호출 합니다.
로컬 환경에서는 http://localhost:8080/infos 
쿠버네티스 클러스터에 배포 됐을 때는 http://192.168.2.100:32311/infos 를 호출 하도록 구성해 주세요
Request Method : GET, Request Parameter 는 없습니다.
Response Body 는 {"message": "Hello Kubernetes! (CI/CD Success)","node_name": "node3","os_arch": "aarch64","java_version": "21.0.9"} 와 같습니다.
페이지에 접속 하면 "node 정보" 버튼이 보여지고 클릭 하면 위 API를 호출 하고 데이터 로딩 중에는 스피너를 보여주세요
데이터를 받아 오면 예쁜 카드 스타일로 보여주는 React 컴포넌트를 만들ㅇ어 주세요.
에러가 발생하면 에러 메시지를 보여주세요.

2. 환경 변수 처리
API 서버 주소를 하드코딩하지 않고 .env 파일에서 REACT_APP_API_URL로 읽어오도록 코드를 수정해 주세요 그리고 로컬 개발 환경과 운영 환경(K8s)에서 각각 다른 URL을 사용할 수 있게 설정해 주세요.

3. 최적화된 Dockerfile 생성 (멀티 스테이지 빌드)
이 React 앱을 위한 멀티 스테이지 Dockerfile을 만들어주세요.
1단계에서는 Node.js로 빌드하고, 2단계에서는 빌드된 정적 파일들을 Nginx 이미지로 복사해서 실행하는 방식이어야  합니다. 특히 **ARM64(라즈베리 파이)**와 AMD64(제온) 모두에서 동작할 수 있게 가볍게 만들어 주세요

4. 소스 형상관리
작성된 소스는 Github Actions 를 이용하여 CI/CD 를 적용할 예정입니다.
Github Tocken 및 설정은 추후에 제공하겠습니다.

 

GEMINI가 내용을 분석하면 순차대로 적용 여부를 물어봅니다.

╭───────────────────────────────────────────────────────────╮
│ ?  WriteTodos Set 4 todo(s)                             ← │
│                                                           │
│ Set 4 todo(s)                                             │
│                                                           │
│ Do you want to proceed?                                   │
│                                                           │
│ ● 1. Allow once                                           │
│   2. Allow for this session                               │
│   3. No, suggest changes (esc)                            │
│                                                           │
│                                                           │
│ ⊷  WriteFile Writing to web\...\.env.development         │
│                                                           │
│                                                           │
│ ⊷  WriteFile Writing to web\...\.env.production          │
│                                                           │
╰───────────────────────────────────────────────────────────╯

2. Allow for this session 을 선택하면 현재 세션의 모든 내용을 자동으로 적용하기 때문에 내용을 파악하고 적용하기 위해 Allow once를 선택합니다.
3. No, suggest changes 를 선택 하고 제안한 내용을 직접 적용해도 됩니다.

 

제안한 내용을 잘 확인하고 순차적으로 제안에 대해  1. Allow once  선택 합니다. (화살표키로 이동, Enter 선택)

 

제미나이가 제안한 내용을 모두 수용하고 npm run dev 명령을 실행하고  [노드 정보 가져오기] 를 클릭 하면 

 

이런 화면이 나옵니다.

호출 결과를 보여주는 카드가 약간 정렬이 맞지 않습니다. 연습용으로 가운데 정렬로 맞추도록 지시해 봅니다.

> API 호출 결과를 보여주는 카드가 약간 좌측으로 치우쳐 있습니다. 가운데 정렬해주세요

✦ API 호출 결과를 보여주는 카드를 가운데로 정렬하겠습니다. InfoCard.css 파일에서 info-card 클래스의 margin 속성을 수정하여 좌우 여백을 자동으로 설정하겠습니다.
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ?  Edit web\...\src\InfoCard.css:   margin-top: 20px; =>   margin: 20px auto;                                                                            ← │
│                                                                                                                                                            │
│ 2   background-color: #ffffff;                                                                                                                             │
│ 3   border-radius: 8px;                                                                                                                                    │
│ 4   box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);                                                                                                              │
│ 5 - margin-top: 20px;                                                                                                                                      │
│ 5 + margin: 20px auto;                                                                                                                                     │
│ 6   max-width: 400px;                                                                                                                                      │
│ 7   width: 100%;                                                                                                                                           │
│ 8   overflow: hidden;                                                                                                                                      │
│                                                                                                                                                            │
│ Apply this change?                                                                                                                                         │
│                                                                                                                                                            │
│ ● 1. Allow once                                                                                                                                            │
│   2. Allow for this session                                                                                                                                │
│   3. Modify with external editor                                                                                                                           │
│   4. No, suggest changes (esc)                                                                                                                             │
│                                                                                                                                                            │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ 네, 카드 가운데 정렬을 위한 CSS 변경을 완료했습니다. 이제 카드가 중앙에 잘 표시될 것입니다.

 

제대로 정렬이 되었는지 확인 해 봅니다.

가운데 정렬이 잘 되었고 창 크기를 변경해도 가운데에 잘 배치되고 있습니다.

 

3. 소스 커밋 & 빌드

이전 챕터에서 Springboot 프로잭트는 커밋하면 바로 빌드하고 배포 이미지까지 자동으로 생성되게 해 두었습니다.

새로 생성한 hello-kubernetes-web 프로잭트는 Github에 새로운 레포지토리를 만들고 Docker Hub와 연동을 해야 합니다.

이전 글 쿠버네티스 클러스터 #9 CI/CD 적용을 참고 해서 레포지토리를 생성하고 Docker Hub와 연동을 마칩니다.

 

Github에 소스를 커밋 하고 이전에 설치한 gh run watch 명령으로 상태를 확인합니다.

PS C:\Users\user\Projects\k8sTest\HelloKubernates\web\hello-kubernates-web> gh run watch
? Select a workflow run * Chore: Github 워크플로우 파일 수정 (인증방식 변경), Web App CI/CD Multi-Arch Build [main] 4s ago
X main Web App CI/CD Multi-Arch Build · 21400287177
Triggered via push about 1 minute ago

JOBS
X build-and-push in 17s (ID 61609191742)
  ✓ Set up job
  ✓ Checkout code
  ✓ Set up QEMU
  ✓ Set up Docker Buildx
  X Login to Docker Hub
  - Build and push Multi-Arch Image
  ✓ Post Login to Docker Hub
  ✓ Post Set up Docker Buildx
  ✓ Post Set up QEMU
  ✓ Post Checkout code
  ✓ Complete job

ANNOTATIONS
X Username and password required
build-and-push: .github#6


X Run Web App CI/CD Multi-Arch Build (21400287177) completed with 'failure'
PS C:\Users\user\Projects\k8sTest\HelloKubernates\web\hello-kubernates-web>

 

Login to Docker Hub 가 실패로 떨어졌습니다.

원인은, 기존 hello-kubernetes-api 레포지토리에 등록한 

  • DOCKERHUB_USERNAME : <도커 사용자 ID>
  • DOCKERHUB_TOKEN : <access token>

두개의 값은 hello-kubernetes-api 레포지토리에 등록한 것 일뿐, hello-kubernetes-web 레포지토리에는 등록이 안되어 있기 때문입니다.

만약 hello-kubernetes-api CI/CD 용으로 생성한 Docker Hub Access Toekn 값을 메모해 두었다면, 그 값을 hello-kubernetes-web 용으로 사용할 수 있지만, 텍스트 형태로 별도로 보관하지 않은 경우 다시 알아낼 방법이 없습니다.
보안 측면에서도 별도로 관리하는 것이 좋으므로 기존에 Docker Hub에서 생성한 토큰의 Discription을 github-actions-k8s 에서 github-actions-k8s-api로 변경하고, github-actions-k8s-web 으로 새로운 토큰을 생성하고 그것을 Github Action에 등록 했습니다.

 

gb run rerun --failed 명령으로 최근에 실패한 빌드를 재실행 합니다.

(※ gb 명령은 어떤 대상을 선택이 필요한 리스트가 나오고 그것을 선택해서 Enter를 쳐야 실행되는 경우가 있으니 참고 하세요)

PS C:\Users\user\Projects\k8sTest\HelloKubernates\web\hello-kubernates-web> gh run rerun --failed
? Select a workflow run X Chore: Github 워크플로우 파일 수정 (인증방식 변경), Web App CI/CD Multi-Arch Build [main] 30m39s ago
✓ Requested rerun (failed jobs) of run 21400287177
PS C:\Users\user\Projects\k8sTest\HelloKubernates\web\hello-kubernates-web>

 

실패한 빌드가 다시 노란색으로 바뀌고 빌드 중입니다.

 

gh run watch 명령으로 확인해 보면 

PS C:\Users\user\Projects\k8sTest\HelloKubernates\web\hello-kubernates-web> gh run watch
? Select a workflow run * Chore: Github 워크플로우 파일 수정 (인증방식 변경), Web App CI/CD Multi-Arch Build [main] 9s ago
X main Web App CI/CD Multi-Arch Build · 21400287177
Triggered via push about 2 minutes ago

JOBS
X build-and-push in 21s (ID 61613053380)
  ✓ Set up job
  ✓ Checkout code
  ✓ Set up QEMU
  ✓ Set up Docker Buildx
  ✓ Login to Docker Hub
  X Build and push Multi-Arch Image
  ✓ Post Build and push Multi-Arch Image
  ✓ Post Login to Docker Hub
  ✓ Post Set up Docker Buildx
  ✓ Post Set up QEMU
  ✓ Post Checkout code
  ✓ Complete job

ANNOTATIONS
X buildx failed with: ERROR: failed to build: unable to prepare context: path "./web/hello-kubernates-web" not found
build-and-push: .github#171


X Run Web App CI/CD Multi-Arch Build (21400287177) completed with 'failure'
PS C:\Users\user\Projects\k8sTest\HelloKubernates\web\hello-kubernates-web>

 

Build and push Multi-Arch Image 에서 실패가 발생했습니다.

Gemini CLI에게 물어봐야지요 ㅎ -> Dockerfile 경로가 잘못 되었다고 합니다. 자기가 작성하고 자기가 고치고 재미있습니다.

Github Actions CI/CD는 잘 작동해서 소스를 수정하고 github에 커밋을 하고 gh run watch 명령으로 확인을 하면 어떤 오류가 발생했는지 자세한 로그가 나옵니다.

소스 수정이 없이 재 빌드 해야 하는 경우는 마지막 실패한 빌드를 다시 실행하는 gh run rerun --failed 명령으로 하면 됩니다.

몇번의 수정 끝에 success 가 떨어졌습니다.

PS C:\Users\user\Projects\k8sTest\HelloKubernates\web\hello-kubernates-web> gh run watch
? Select a workflow run * Chore: nginx.conf 파일이 없어 발생하던 오류를 수정, Web App CI/CD Multi-Arch Build [main] 4s ago
✓ main Web App CI/CD Multi-Arch Build · 21401785790
Triggered via push less than a minute ago

JOBS
✓ build-and-push in 49s (ID 61614599686)
  ✓ Set up job
  ✓ Checkout code
  ✓ Set up QEMU
  ✓ Set up Docker Buildx
  ✓ Login to Docker Hub
  ✓ Build and push Multi-Arch Image
  ✓ Post Build and push Multi-Arch Image
  ✓ Post Login to Docker Hub
  ✓ Post Set up Docker Buildx
  ✓ Post Set up QEMU
  ✓ Post Checkout code
  ✓ Complete job

✓ Run Web App CI/CD Multi-Arch Build (21401785790) completed with 'success'
PS C:\Users\user\Projects\k8sTest\HelloKubernates\web\hello-kubernates-web>

 

 

4. 배포

4.1. API 배포

hello-kubernetes-api 는 진작에 빌드와 이미지를 생성이 완료 되었습니다.

먼저 이것을 pod에 배포 해야 합니다.

PS C:\Users\user\Projects\k8sTest\HelloKubernates\web\hello-kubernates-web> kubectl rollout restart deployment hello-kubernetes-api
deployment.apps/hello-kubernetes-api restarted
PS C:\Users\user\Projects\k8sTest\HelloKubernates\web\hello-kubernates-web>

잠시후 확인해보면 hello-kubernetes-api pod들의 graceful 이 완료 되었습니다.

PS C:\Users\user\Projects\k8sTest\HelloKubernates\web\hello-kubernates-web> kubectl get pod -o wide   
NAME                                   READY   STATUS    RESTARTS   AGE     IP            NODE    NOMINATED NODE   READINESS GATES
hello-kubernetes-api-dd6b497d6-cvfz2   1/1     Running   0          3m58s   10.244.1.66   node1   <none>           <none>
hello-kubernetes-api-dd6b497d6-wlkwc   1/1     Running   0          3m40s   10.244.3.41   node2   <none>           <none>
hello-kubernetes-api-dd6b497d6-zrsqk   1/1     Running   0          3m44s   10.244.2.72   node3   <none>           <none>
nginx-bf5d5cf98-bqcf5                  1/1     Running   0          8h      10.244.2.71   node3   <none>           <none>
nginx-bf5d5cf98-qfx46                  1/1     Running   0          8h      10.244.3.39   node2   <none>           <none>
nginx-bf5d5cf98-r28pf                  1/1     Running   0          8h      10.244.3.40   node2   <none>           <none>
PS C:\Users\user\Projects\k8sTest\HelloKubernates\web\hello-kubernates-web>

 

4.2. WEB 배포

기존에 배포되었던 테스트용 nginx pod는 삭제 하고 새로운 hello-kubernetes-web pod를 배포하겠습니다.

PS C:\Users\user\Projects\k8sTest\HelloKubernates\web\hello-kubernates-web> kubectl delete deployment nginx
deployment.apps "nginx" deleted from default namespace
PS C:\Users\user\Projects\k8sTest\HelloKubernates\web\hello-kubernates-web> kubectl delete svc nginx 
service "nginx" deleted from default namespace
PS C:\Users\user\Projects\k8sTest\HelloKubernates\web\hello-kubernates-web> kubectl get pod -o wide
NAME                                   READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
hello-kubernetes-api-dd6b497d6-cvfz2   1/1     Running   0          20m   10.244.1.66   node1   <none>           <none>
hello-kubernetes-api-dd6b497d6-wlkwc   1/1     Running   0          20m   10.244.3.41   node2   <none>           <none>
hello-kubernetes-api-dd6b497d6-zrsqk   1/1     Running   0          20m   10.244.2.72   node3   <none>           <none>
PS C:\Users\user\Projects\k8sTest\HelloKubernates\web\hello-kubernates-web>

pod와 서비스가 완전히 삭제 되었습니다.

 

웹 프로잭트를 배포하기 위해 deployment.yaml 파일을 생성합니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-kubernetes-web
  labels:
    app: hello-kubernetes-web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello-kubernetes-web
  template:
    metadata:
      labels:
        app: hello-kubernetes-web
    spec:
      containers:
      - name: hello-kubernetes-web
        # 중요: 'YOUR_DOCKERHUB_USERNAME'을 실제 Docker Hub 사용자 이름으로 변경해주세요.
        image: basscraft/hello-kubernetes-web:latest
        ports:
        - containerPort: 80

---

apiVersion: v1
kind: Service
metadata:
  name: hello-kubernetes-web-service
spec:
  type: NodePort
  selector:
    app: hello-kubernetes-web
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      # 외부에서 접속할 포트입니다. 예: http://<Node_IP>:30000
      nodePort: 30000

 

수정된 deployment.yaml 파일을 github에 커밋 하고 빌드 상태를 확인 합니다.

PS C:\Users\user\Projects\k8sTest\HelloKubernates\web\hello-kubernates-web> gh run watch
? Select a workflow run * Chore: deployment.yaml 생성, Web App CI/CD Multi-Arch Build [main] 9s ago
✓ main Web App CI/CD Multi-Arch Build · 21402870499
Triggered via push less than a minute ago

JOBS
✓ build-and-push in 42s (ID 61618560160)
  ✓ Set up job
  ✓ Checkout code
  ✓ Set up QEMU
  ✓ Set up Docker Buildx
  ✓ Login to Docker Hub
  ✓ Build and push Multi-Arch Image
  ✓ Post Build and push Multi-Arch Image
  ✓ Post Login to Docker Hub
  ✓ Post Set up Docker Buildx
  ✓ Post Set up QEMU
  ✓ Post Checkout code
  ✓ Complete job

✓ Run Web App CI/CD Multi-Arch Build (21402870499) completed with 'success'
PS C:\Users\user\Projects\k8sTest\HelloKubernates\web\hello-kubernates-web>

 

이제 배포 준비가 완료 되었습니다.

처음 배포기 때문에 kubectl apply -f deployment.yaml 명령으로 실행합니다.

PS C:\Users\user\Projects\k8sTest\HelloKubernates\web\hello-kubernates-web> kubectl apply -f ./deployment.yaml                       
deployment.apps/hello-kubernetes-web created
service/hello-kubernetes-web-service created
PS C:\Users\user\Projects\k8sTest\HelloKubernates\web\hello-kubernates-web> kubcctl get pods -o wide          
kubcctl: The term 'kubcctl' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
PS C:\Users\user\Projects\k8sTest\HelloKubernates\web\hello-kubernates-web> kubectl get pods -o wide
NAME                                   READY   STATUS              RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
hello-kubernetes-api-dd6b497d6-cvfz2   1/1     Running             0          25m   10.244.1.66   node1   <none>           <none>
hello-kubernetes-api-dd6b497d6-wlkwc   1/1     Running             0          25m   10.244.3.41   node2   <none>           <none>
hello-kubernetes-api-dd6b497d6-zrsqk   1/1     Running             0          25m   10.244.2.72   node3   <none>           <none>
hello-kubernetes-web-678557c6-ft7q4    0/1     ContainerCreating   0          27s   <none>        node1   <none>           <none>
hello-kubernetes-web-678557c6-gsw8k    0/1     ContainerCreating   0          27s   <none>        node2   <none>           <none>
hello-kubernetes-web-678557c6-hqhjg    0/1     ContainerCreating   0          27s   <none>        node3   <none>           <none>
PS C:\Users\user\Projects\k8sTest\HelloKubernates\web\hello-kubernates-web>

hello-kubernetes-web pod들이 생성되고 있습니다.

 

deployment.yaml 에 서비스 포트를 3000으로 지정 했으니 kubectl get svc 명령으로 제대로 포트를 바라보고 있는지 확인합니다.

PS C:\Users\user\Projects\k8sTest\HelloKubernates\web\hello-kubernates-web> kubectl get svc
NAME                           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
hello-kubernetes-api-service   NodePort    10.105.75.244   <none>        80:32311/TCP   8d
hello-kubernetes-web-service   NodePort    10.103.6.121    <none>        80:30000/TCP   2m49s
kubernetes                     ClusterIP   10.96.0.1       <none>        443/TCP        10d
PS C:\Users\user\Projects\k8sTest\HelloKubernates\web\hello-kubernates-web>

3000번으로 잘 떠있습니다.

 

http://192.168.2.100:30000 으로 접속해 봅니다.

정상 적으로 작동하고 데이터도 잘 받아 오고 있습니다.

 

끝.

 

+ Recent posts