cilium 을 공부하면서 테스트 클러스터는 vagrant 와 kind를 사용하면 대부분 테스트가 큰 무리 없이 가능했고, bgp 구성 관련해서도 쉽지는 않지만 containerlab을 사용하면 되어서 만족하고 있었다.
테스트를 하면서도 결국 올려야하는 앱이 제대로 없어서 테스트 할 때 쓸데없는 시간을 더 많이 쓰기도 했다.
그래서 frontend-backend-database 구조의 3tier 샘플 앱을 만들어봤다.
https://github.com/ryusstory/k8s-3tier-sample-clickcounter/tree/cni/kindnet
GitHub - ryusstory/k8s-3tier-sample-clickcounter
Contribute to ryusstory/k8s-3tier-sample-clickcounter development by creating an account on GitHub.
github.com
frontend와 backend 코드는 Grok의 도움을 받았고, frontend의 index.html은 Genspark의 도움을 받았다.
일단 cilium hubble에서 보면 이렇게 구성된다.
처음에 cilium을 가지고 구성했지만, 범용으로 쓸 수 있을 것 같아서 cilium를 사용하지 않고 kind의 기본 kindnet으로 작성했다.

테스트 클러스터이다 보니 control plane과 worker 노드 두 개로 구성되어 있으며, 호스트 머신에서 bridge 네트워크를 통해 연결된다. 이는 Kind를 사용하여 로컬 환경에서 간단히 Kubernetes 클러스터를 생성하고 테스트할 수 있도록 설계된 구조이다.

이 샘플 앱은 3-tier 아키텍처를 따르며, 다음과 같은 컴포넌트로 구성된다


Node.js 기반의 웹 애플리케이션으로, 사용자 인터페이스를 제공한다. 포트 3000(TCP/HTTP)을 통해 접근 가능하며, 백엔드로 요청을 전달한다. 구성도에서 보듯이, HTTP와 gRPC 백엔드로 분기되어 연결된다.
configmap을 통해 backend 주소를 얻어와서 배포된다.

웹에도 HTTP와 gRPC 클릭 버튼을 별도로 구성했다., (데이터베이스 쓰기 동작)

history를 보여주는 것도 http와 grpc 를 별도로 구성했다. (데이터베이스 읽기 동작)
default는 click 후 바로 데이터베이스로부터 데이터를 읽어와서 보여주는데, 이 동작을 http로 할지 grpc로 할지 선택하는 버튼이다.

start로 시작하면 nodejs에서 1초 정도 간격으로 랜덤하게 http와 grpc도 랜덤으로 선택해서 요청하게 된다.
두 가지 버전으로 구현되어 있다.
backend-http: HTTP 프로토콜을 사용하며, 포트 5000(TCP)으로 frontend로부터 요청을 받는다.
backend-grpc: gRPC 프로토콜을 사용하며, 포트 50051(TCP)으로 frontend로부터 요청을 받는다.
둘 다 데이터베이스(MySQL)와 연결되어 데이터를 처리한다.
데이터베이스 정보는 configmap을 통해서 전달되며, password는 secret을 적용할까 했지만 그냥 configmap으로 통일했다.
kubernetes.io에서 제공하는 스테이트풀셋 mysql을 사용할까 했지만 이게 들어가면 어떻게 해도 간단하게 보이지가 않을 것 같아 단순하게 1대로 구성했다.
데이터베이스는 클릭 카운터 등의 데이터를 저장하고, 스토리지는 Rancher local-path-provisioner를 사용해서 간단하게 배포했다.
.
├── app
│ ├── be
│ │ ├── Dockerfile
│ │ ├── app.py
│ │ ├── click.proto
│ │ ├── click_pb2.py
│ │ ├── click_pb2_grpc.py
│ │ └── venv (생략)
│ ├── fe
│ │ ├── Dockerfile
│ │ ├── app.js
│ │ ├── click.proto
│ │ └── public
│ │ └── index.html
│ ├── k8s-be.yaml
│ ├── k8s-db.yaml
│ └── k8s-fe.yaml
├── build.sh
├── deploy.sh
└── recreate.sh
recreate.sh 실행시 아래 절차 진행
build.sh 실행시
app/fe 의 docker image buildapp/be 의 docker image buildkind는 load 명령어를 통해서 kind 클러스터에 이미지를 업로드 할 수 있어서, 빌드된 이미지를 각 클러스터의 노드에 넣어준다.
docker exec kind-control-plane crictl image ls 명령어로 올라간 이미지를 확인할 수 있다.
그리고, 테스트 시에 계속 앱을 다시 만들고 배포 했어서, id=3tier-app 이라는 태그를 각각 frontend와 backend 에 적용해놨다. 그래서 마지막에 kubectl delete pod -l id=3tier-app --now=true 를 실행해서 앱을 재시작 해준다.
deploy.sh 실행시
배포시 프론트페이지는 먼저 뜨지만 mysql이 올라오기까지 시간이 걸려 클릭하더라도 에러가 나지만 기다리면 정상적으로 동작한다. init container를 넣을까 했지만 패스했다.
backend의 경우 app.py에서는 http와 grpc를 둘다 구현하고, SERVER_MODE 환경변수를 통해 http와 grpc를 전달하면 각각 프로토콜에 맞는 형태로 동작한다.
빨리 정리하고 cilium 테스트를 진행해보면서 업데이트 해야겠다.
| Cilium:Securing gRPC 테스트 (0) | 2025.09.05 |
|---|---|
| kube-burner measurement 테스트 (1) | 2025.08.30 |
| kube-burner 툴 소개 (0) | 2025.08.28 |