Kubernetes 네트워킹과 SDN 개념을 활용해 Kubernetes 클러스터 환경에서 Spring Boot 애플리케이션을 Docker 이미지로 만들어 배포하고, NodePort로 외부에서 접근할 수 있도록 설정하는 과정에 대해 다루었습니다.
1. CNI와 데이터 공유
1) 컨테이너 네트워크 인터페이스(CNI)
CNI는 쿠버네티스 파드들이 클러스터 내에서 서로 통신할 수 있도록 해주는 네트워크 플러그인입니다. 이를 통해 파드 간 통신은 물론 클러스터 외부와의 네트워크 연결도 가능해집니다. 쿠버네티스 파드 간의 일관성 있는 네트워크 연결을 보장하고 파드는 네트워크 내부에서 생성과 삭제가 반복되며, CNI는 파드가 쉽게 접근 가능하도록 IP를 동적으로 관리합니다.
2) 볼륨을 통한 데이터 공유
Kubernetes의 hostPath 볼륨을 사용하면 클러스터의 파드들이 동일한 호스트 파일 시스템을 공유하여 데이터를 저장하고 접근할 수 있습니다.
2. SDN (Software-Defined Networking)
SDN이란?
SDN은 네트워크를 가상화하고 네트워크 리소스를 효율적으로 관리하는 기술로, 네트워크 제어와 데이터 전송을 분리하여 클러스터 내의 파드들이 자유롭게 이동할 수 있도록 합니다. 네트워크 자원을 소프트웨어로 제어하여 트래픽 흐름을 최적화합니다. 쿠버네티스에서는 SDN이 네트워크 제어 평면과 데이터 평면을 분리하여, 서비스 IP에 대한 로드 밸런싱 및 고정된 IP 주소에 대한 네임스페이스 격리를 제공합니다.
Kubernetes에서 SDN이 필요한 이유
• 쿠버네티스는 수백 개의 파드가 클러스터 내에서 동적으로 생성되며 이동할 수 있어야 합니다.
• 클러스터에 들어오고 나가는 트래픽을 파드의 이동에 따라 올바른 위치로 라우팅할 수 있어야 합니다.
3. Kubernetes 네트워크 서비스 설정
ClusterIP와 NodePort
• ClusterIP: 클러스터 내부에서만 접근 가능한 기본 서비스 유형으로, 파드가 클러스터 내부에서 서로 통신할 수 있게 합니다.
• NodePort: 클러스터 외부에서 접근할 수 있는 서비스 유형으로, 각 노드의 고정된 포트로 연결됩니다.
NodePort 서비스 생성하기
my-nodeport.yml 작성
apiVersion: v1
kind: Service
metadata:
name: kube-dns-2
namespace: kube-system
labels:
k8s-app: kube-dns
kubernetes.io/name: CoreDNS
spec:
ports:
- name: dns
port: 53
protocol: UDP
targetPort: 53
- name: dns-tcp
port: 53
protocol: TCP
targetPort: 53
selector:
k8s-app: kube-dns
type: NodePort
'
서비스 생성 및 확인
4. Spring Boot 애플리케이션 개발 및 Docker 이미지 생성
이제 Spring Boot 애플리케이션을 생성하고 Docker로 컨테이너화하여 Kubernetes에서 배포 가능한 이미지를 생성합니다.
1) Spring Boot 애플리케이션 생성
• Intellij에서 새로운 Spring Boot 프로젝트를 생성하여 Lombok과 Web 의존성을 추가합니다.
FrontController
간단한 요청을 처리하는 FrontController 클래스를 추가합니다.
@RestController
public class FrontController {
@GetMapping("/")
public Map<String, Object> index(){
Map<String, Object> data = new HashMap<>();
data.put("result", "success");
List<Map> list = new ArrayList<>();
Map<String, String> map1 = new HashMap<>();
map1.put("id", "itstudy");
map1.put("name", "아현");
list.add(map1);
data.put("list", list);
return data;
}
}
2) Dockerfile 작성 및 이미지 생성
프로젝트 루트에 Dockerfile을 생성하고 작성합니다.
FROM amazoncorretto:17
CMD ["./mvnw", "clean", "package"]
ARG JAR_FILE=target/*.jar
COPY ./build/libs/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
이미지 빌드
./gradlew clean build
docker build -t apiserver:0.0.1 .
이미지 확인 및 실행
docker images
docker run -d --name apiserver -p 80:8080 apiserver:0.0.1
5. DockerHub에 애플리케이션 배포
1) GitHub와 DockerHub 연동
• GitHub에서 새로운 저장소를 생성하고 코드를 푸시합니다.
• DockerHub에 프로젝트를 업로드하기 위해 CI/CD를 설정합니다.
apiserver라는 이름으로 GitHub에서 새 저장소를 생성하고 GitHub에 커밋 푸시합니다.
git add .
git commit -m "Add GitHub Actions workflow for DockerHub deployment"
git push origin main
DockerHub에 Repository 생성
GitHub Actions가 빌드한 이미지를 DockerHub에 푸시할 Repository를 DockerHub에서 생성합니다.
Create Repository 클릭 > Create 버튼을 클릭하여 Repository를 생성
Repository 생성이 완료되면 GitHub Actions 워크플로우에서 빌드한 이미지를 DockerHub의 해당 Repository로 푸시할 수 있습니다.
DockerHub에서 토큰 발급하기
DockerHub에서 액세스 토큰을 발급받아 사용합니다.
Account Settings > Security > Personal Access Tokens > New Access Token > Generate
1. DockerHub 로그인: DockerHub 계정에 로그인합니다.
2. Account Settings 이동: 오른쪽 상단의 사용자 아이콘을 클릭하고 Account Settings를 선택합니다.
3. Security 선택: Account Settings에서 Security 탭으로 이동합니다.
4. New Access Token 클릭: Personal Access Tokens 섹션에서 New Access Token 버튼을 클릭합니다.
5. 토큰 이름 설정: 토큰 이름을 github-actions와 같이 구체적으로 입력합니다.
6. Read, Write 권한 설정 후 발급: 권한을 설정하고 Generate를 클릭하여 토큰을 생성합니다.
7. 토큰 복사: 발급된 토큰을 복사하여 GitHub Secrets에 DOCKERHUB_TOKEN으로 등록합니다.
⚠️ 주의: 토큰은 발급 시에만 표시되기 때문에 이 토큰을 GitHub Secrets에 바로 저장해야 합니다.
2) GitHub Actions 설정
프로젝트 루트에 .github/workflows/upload.yml 파일을 작성하여 DockerHub에 자동으로 이미지를 배포합니다.
upload.yml
name: Java CI with Gradle
on:
push:
branches: ["main"]
jobs:
build-docker-image:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
#JDK 17버전 설치
- name: Set Up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
#빌드
- name: Build and Gradle
uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1
with:
arguments: clean bootJar
#도커 허브 로그인
- name: Login To DockerHub
uses: docker/login-action@v1
with:
username: ${{secrets.DOCKERHUB_USERNAME}}
password: ${{secrets.DOCKERHUB_TOKEN}}
#이미지 빌드 및 업로드
- name: Image Build and Release to DockerHub
env:
NAME: ${{secrets.DOCKERHUB_USERNAME}}
REPO: ${{secrets.DOCKERHUB_REPOSITORY}}
run: |
docker build -t $REPO .
docker tag $REPO:latest $NAME/$REPO:latest
docker push $NAME/$REPO:latest
GitHub에 DockerHub 배포용 변수 등록
DockerHub와 GitHub 간의 연동을 위해 DockerHub 로그인 정보를 GitHub Secrets에 저장합니다. 이를 통해 GitHub Actions 워크플로우가 DockerHub에 안전하게 접근하여 이미지를 푸시할 수 있습니다.
GitHub Repository > Settings > Secrets and variables > Actions > New repository secret
1. GitHub 저장소 열기: Docker 이미지 배포를 원하는 GitHub Repository로 이동합니다.
2. Settings로 이동: 저장소 페이지 상단에서 Settings 탭을 클릭합니다.
3. Secrets and variables 선택: 왼쪽 메뉴에서 Secrets and variables > Actions을 선택합니다.
4. New repository secret 클릭: 오른쪽 상단의 New repository secret 버튼을 클릭합니다.
다음 세 가지 변수를 각각 아래 내용으로 등록합니다.
• DOCKERHUB_USERNAME: DockerHub 사용자 이름
• DOCKERHUB_TOKEN: DockerHub에서 발급받은 액세스 토큰
• DOCKERHUB_REPOSITORY: DockerHub의 Repository 이름 (예: apiserver)
Actions secrets에 DOCKERHUB_USERNAME, DOCKERHUB_TOKEN, DOCKERHUB_REPOSITORY가 각각 저장된 것을 확인할 수 있습니다. 이 정보는 GitHub Actions에서 자동으로 참조하여 DockerHub에 로그인하고 이미지를 푸시하는 데 사용됩니다.
DockerHub에서 이미지 확인
GitHub Actions가 정상적으로 완료되면 DockerHub Repository에 latest 태그가 붙은 새로운 Docker 이미지가 푸시됩니다.
6. Kubernetes 배포 및 NodePort 서비스 설정
1) 쿠버네티스 Deployment 이용해서 pod 생성
Kubernetes 클러스터에 Spring Boot 애플리케이션을 배포할 수 있도록 Deployment 파일을 생성합니다.
springbootdeployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: devops-spring-deployment
spec:
replicas: 2
selector:
matchLabels:
app: devops-spring-app
template:
metadata:
labels:
app: devops-spring-app
spec:
containers:
- name: core
image: ahyeonlim/apiserver
ports:
- containerPort: 8080
protocol: TCP
Deployment 실행
kubectl apply -f springbootdeployment.yml
2) 쿠버네티스 Service 이용해서 NodePort 설정
외부에서 접근할 수 있는 NodePort 서비스를 설정합니다. 이를 통해 로컬 시스템 외부에서도 Spring Boot 애플리케이션에 접근할 수 있습니다.
service.yml 파일
apiVersion: v1
kind: Service
metadata:
name: devops-spring-service
spec:
type: NodePort
ports:
- port: 80
protocol: TCP
targetPort: 8080
selector:
app: devops-spring-app
Service 생성
kubectl apply -f service.yml
Service 확인
kubectl get svc
kubectl get svc -o wide
endpoint 확인
kubectl get ep
'BackEnd > DEVOPS' 카테고리의 다른 글
[AWS] AWS ECS와 ECR을 활용한 CI/CD 구현 (1) | 2024.11.18 |
---|---|
[ArgoCD] ArgoCD 설치 (1) | 2024.11.15 |
[Kubernetes] Master Node, Worker Node 연결 (0) | 2024.11.15 |
[Kubernetes] 쿠버네티스 클러스터 구성 및 관리 (0) | 2024.10.29 |
[Docker] Dockerfile 작성 및 이미지 빌드 (5) | 2024.10.16 |