thumbnail

멋쟁이사자처럼 클라우드 엔지니어링 부트캠프 수강 후기

멋쟁이사자처럼 클라우드 엔지니어링 부트캠프 3기 수강후기

멋쟁이사자처럼 오늘 공부 후기 챌린지 - 클라우드 엔지니어링 편

이런 고민을 하고 있다면, 지금 이 순간에도 멋쟁이사자처럼에서 클라우드 엔지니어링 부트캠프를 수강하며 자신만의 속도로 성장 중인 수강생들을 주목해보세요.


배우고 잊어버리는 건 누구나 겪는 일이에요. 하지만 멋쟁이사자처럼 부트캠프는 단순히 배우는 것에 그치지 않고, 배운 내용을 내 것으로 만드는 방법까지 고민하고 있어요. 그렇다면, 배운 것을 가장 효과적으로 습득하는 방법은 무엇일까요? 바로 기록하고 정리하는 것이죠. 배운 내용을 정리하고 기록하면, 기억은 오래 남고 실전에서도 활용할 수 있으니까요!

멋쟁이사자처럼 부트캠프는 수강생들이 배운 내용을 정리하고 공유할 수 있도록 TIL (Today I Learned) 블로그 챌린지를 진행하고 있어요. 그래서 오늘, 강사님과 멘토님에게 배운 내용을 체계적으로 기록하며 성장하고 있는 수강생의 이야기를 가져왔어요. 작고 사소해 보일지라도 배운 내용을 정리하고, 기록하면서 성장한 이들의 소중한 경험을 지금 확인해 보세요.


1. Spring Boot + NodePort

 

목표

  • Spring Boot 애플리케이션을 Docker 이미지로 빌드하고, Kubernetes의 Deployment & NodePort Service로 배포

 

sample-app.jar

  • sts maven build로 .jar 파일 생성

 

 Dockerfile

Plaintext
FROM openjdk:17
COPY *.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]

 

Docker Image 빌드 및 푸시

Plaintext
# 멀티 아키텍처 이미지 빌드
docker buildx build --platform linux/amd64,linux/arm64 -t app-k8s-basic .

# 태깅 및 Docker Hub 푸시
docker tag app-k8s-basic <username>/<repo-name>
docker push <username>/<repo-name>

 

Deployment

Plaintext
# app-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app.kubernetes.io/name: myapp
  template:
    metadata:
      labels:
        app.kubernetes.io/name: myapp
    spec:
      containers:
        - name: myapp-container
          image: <username>/<repo-name>
          ports:
            - containerPort: 8080

 

 NodePort Service

Plaintext
# app-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app.kubernetes.io/name: myapp
  template:
    metadata:
      labels:
        app.kubernetes.io/name: myapp
    spec:
      containers:
        - name: myapp-container
          image: <username>/<repo-name>
          ports:
            - containerPort: 8080

 

  

2. MySQL 연결 실습

 

PersistentVolume

Plaintext
# db-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: db-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: /mnt/data # 로컬 노드에 실제 파일 저장

 

PersistentVolumeClaim

Plaintext
# db-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: db-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

 MySQL Service

Plaintext
# db-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: mysql-service
spec:
  selector:
    app: mysql
  type: NodePort
  ports:
    - port: 3306
      targetPort: 3306
      nodePort: 31306
  • ClusterIP로 설정하면 클러스터 내부에서 mysql-service 이름으로 접근 가능함

 

MySQL Deployment

Plaintext
# db-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql-container
          image: mysql:8
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: k8s12345
          ports:
            - containerPort: 3306
          volumeMounts:
            - mountPath: /var/lib/mysql
              name: mysql-volume
      volumes:
        - name: mysql-volume
          persistentVolumeClaim:
            claimName: db-pvc

 Spring Boot 설정 파일

  • src/main/resources/application.properties

Plaintext
# 서버 기본 설정
server.port=8080
spring.application.name=k8s-basic-app

# MySQL 연결 정보 (mysql-service는 K8S의 서비스 이름)
spring.datasource.url=jdbc:mysql://mysql-service:3306/k8sdb?serverTimezone=Asia/Seoul
spring.datasource.username=appuser
spring.datasource.password=apppass123
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# JPA 설정
spring.jpa.hibernate.ddl-auto=update   # 또는 create (초기 생성용)
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

 

요약 포인트

구성 요소

설명

Dockerfile

Spring Boot jar을 이미지로 만듦

Deployment

애플리케이션 또는 DB Pod 복제 관리

Service

외부 트래픽 연결 (NodePort로 포트 개방)

PV/PVC

DB 데이터 영속 저장소 구성

MySQL 연동

Spring Boot에서 내부 DB 접근 설정 완료

 

 

기본 개념

  • Kubernetes에서 API 리소스(Pod, Deployment, Service 등)를 논리적으로 그룹핑하여 관리할 수 있도록 제공되는 리소스

  • 네임스페이스를 활용하면 여러 팀/환경/서비스를 서로 격리하여 관리할 수 있음

주로 사용하는 Namespace 구분 기준

  • 팀 단위: team-a, team-b …

  • 환경 단위: dev, stage, prod …

  • 서비스 단위: auth, payment, frontend …

클러스터 내 리소스 범위 확인

명령어

설명

kubectl api-resources

전체 리소스 종류 확인

kubectl api-resources --namespaced=true

네임스페이스 단위 리소스만 확인

kubectl api-resources --namespaced=false

클러스터 범위 리소스만 확인

1) 네임스페이스 종류 및 역할

Namespace

설명

default

명시하지 않으면 기본으로 사용되는 공간

kube-system

Kubernetes 시스템 컴포넌트(Pod 등) 관리

kube-public

클러스터 내 모든 사용자가 접근 가능한 공용 정보

kube-node-lease

노드의 상태(헬스체크 등)를 주기적으로 Lease 리소스로 관리

2) Namespace 기반 리소스 분리 - 실습

 

디렉터리 이동

Plaintext
cd ~/manifest

 

 네임스페이스 생성

Plaintext
kubectl create namespace alpha
kubectl create namespace beta

 Deployment 예시

Plaintext
# deploy-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-svc
  template:
    metadata:
      labels:
        app: nginx-svc
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
        ports:
        - containerPort: 80

 

 Service 예시

Plaintext
# service-nginx.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  type: ClusterIP
  selector:
    app: nginx-svc
  ports:
    - port: 8080
      targetPort: 80

 

리소스 적용

Plaintext
kubectl apply -f deploy-nginx.yaml -n alpha
kubectl apply -f service-nginx.yaml -n alpha

kubectl apply -f deploy-nginx.yaml -n beta
kubectl apply -f service-nginx.yaml -n beta

 

확인 명령어

 

 

ResourceQuota & LimitRange

리소스

설명

ResourceQuota

네임스페이스 단위로 사용 가능한 전체 리소스 총량 제한

LimitRange

Pod/Container 단위로 기본/최대/최소 자원 제한

실습

 

 네임스페이스 생성

Plaintext
# ns-gamma.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: ns-gamma
Plaintext
kubectl apply -f ns-gamma.yaml

 

 

 LimitRange 예시

Plaintext
# limitrange-gamma.yaml
apiVersion: v1
kind: LimitRange
metadata:
  name: lr-gamma
  namespace: ns-gamma
spec:
  limits:
    - type: Container
      default:
        cpu: 200m
        memory: 256Mi
      defaultRequest:
        cpu: 100m
        memory: 128Mi
      max:
        cpu: 1
        memory: 512Mi
      min:
        cpu: 50m
        memory: 64Mi
    - type: PersistentVolumeClaim
      max:
        storage: 2Gi
      min:
        storage: 200Mi

 

 

ResourceQuota 예시

Plaintext
# quota-gamma.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: quota-gamma
  namespace: ns-gamma
spec:
  hard:
    limits.cpu: "4"
    limits.memory: "6Gi"
    requests.storage: "10Gi"
    count/pods: 15
    count/services: 5
    count/secrets: 10
    count/configmaps: 10

 

 

 테스트용 Pod

Plaintext
# pod-gamma1.yaml
apiVersion: v1
kind: Pod
metadata:
  name: gamma-pod-default
  namespace: ns-gamma
spec:
  containers:
    - name: web
      image: nginx
      ports:
        - containerPort: 80
Plaintext
# pod-gamma2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: gamma-pod-limit
  namespace: ns-gamma
spec:
  containers:
    - name: web
      image: nginx
      ports:
        - containerPort: 80
      resources:
        limits:
          cpu: 1
          memory: 512Mi

 

 

개요

  • key:value 형태로 데이터를 저장하는 리소스

  • 환경 설정을 Pod 외부에서 분리하여 관리할 수 있도록 지원

  • 민감하지 않은 설정 정보 저장용 (예: DB 이름, 이메일 등)

ConfigMap 생성방법

 

1) 리터럴 방식

Plaintext
kubectl create configmap user-config \
  --from-literal=APP_NAME=myapp \
  --from-literal=ADMIN_EMAIL=admin@k8s.io
kubectl get configmap user-config -o yaml

 

2) 파일 또는 디렉토리로 생성

Plaintext
APP_NAME=myapp
ADMIN_EMAIL=admin@k8s.io
Plaintext
kubectl create configmap file-config --from-file=./app.config
kubectl get configmap file-config -o yaml

 

3) 선언 방식(YAML)

Plaintext
apiVersion: v1
kind: ConfigMap
metadata:
  name: declared-config
data:
  APP_NAME: myapp
  ADMIN_EMAIL: admin@k8s.io

 

Pod에서 ConfigMap 활용 방법

 

1) 직접 환경 변수 지정

Plaintext
apiVersion: v1
kind: Pod
metadata:
  name: pod-v1
spec:
  containers:
    - name: web
      image: nginx
      env:
        - name: APP_NAME
          value: myapp
        - name: ADMIN_EMAIL
          value: admin@k8s.io

 

 

2) ConfigMap 전체를 환경 변수로 가져오기

Plaintext
apiVersion: v1
kind: Pod
metadata:
  name: pod-v2
spec:
  containers:
    - name: web
      image: nginx
      envFrom:
        - configMapRef:
            name: declared-config

 

3) ConfigMap의 특정 key만 참조

Plaintext
apiVersion: v1
kind: Pod
metadata:
  name: pod-v3
spec:
  containers:
    - name: web
      image: nginx
      env:
        - name: CONTACT_EMAIL
          valueFrom:
            configMapKeyRef:
              name: declared-config
              key: ADMIN_EMAIL

 

4)  Volume으로 마운트

Plaintext
apiVersion: apps/v1
kind: Deployment
metadata:
  name: configmap-vol
spec:
  selector:
    matchLabels:
      app: cm-volume
  template:
    metadata:
      labels:
        app: cm-volume
    spec:
      containers:
        - name: web
          image: nginx
          volumeMounts:
            - mountPath: /etc/config
              name: config-volume
      volumes:
        - name: config-volume
          configMap:
            name: declared-config

 

개요

  • ConfigMap과 유사하지만 민감한 정보 저장을 위한 리소스

  • 모든 값은 base64로 인코딩되어 저장됨

  • 내부적으로 etcd에 저장되며, TLS 미적용 시 노출 위험 있음

  • 민감한 정보 예시: PASSWORD, TOKEN, SSH_KEY, API_KEY 등

Secret 타입

타입

설명

Opaque

기본 타입, 일반 키-값 저장

kubernetes.io/dockerconfigjson

Docker 이미지 레지스트리 인증 정보

kubernetes.io/tls

TLS 인증서 (cert/key) 저장

kubernetes.io/service-account-token

ServiceAccount 토큰 저장용

 

Secret 생성 방법

 

1. 리터럴

Plaintext
kubectl create secret generic user-secret \
  --from-literal=DB_USER=admin \
  --from-literal=DB_PASS=secret123

 

2. YAML 선언 (base64 인코딩 필요)

Plaintext
apiVersion: v1
kind: Secret
metadata:
  name: encoded-secret
type: Opaque
data:
  DB_USER: YWRtaW4=         # admin
  DB_PASS: c2VjcmV0MTIz     # secret123
  • 인코딩: echo -n 'admin' | base64

 

 

 

Pod에서 Secret 활용 방법

 

1. envFrom 전체 가져오기

Plaintext
apiVersion: v1
kind: Pod
metadata:
  name: secret-pod-v1
spec:
  containers:
    - name: app
      image: nginx
      envFrom:
        - secretRef:
            name: encoded-secret

 

2. 특정 Key 참조

Plaintext
apiVersion: v1
kind: Pod
metadata:
  name: secret-pod-v2
spec:
  containers:
    - name: app
      image: nginx
      env:
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: encoded-secret
              key: DB_PASS

 

3. 볼륨으로 마운트

Plaintext
apiVersion: v1
kind: Pod
metadata:
  name: secret-pod-v3
spec:
  containers:
    - name: app
      image: nginx
      volumeMounts:
        - name: secret-vol
          mountPath: /etc/secret
  volumes:
    - name: secret-vol
      secret:
        secretName: encoded-secret

 

 

Private Docker Registry에서 이미지 Pull

 

 Secret 생성

Plaintext
kubectl create secret docker-registry regcred \
  --docker-username=<username> \
  --docker-password=<token> \
  --docker-email=<email>

 

 Deployment에 imagePullSecrets 적용

Plaintext
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-private
spec:
  replicas: 1
  selector:
    matchLabels:
      app: private-app
  template:
    metadata:
      labels:
        app: private-app
    spec:
      containers:
        - name: nginx
          image: <username>/<repo>:latest
      imagePullSecrets:
        - name: regcred

 

홈 : 멋사 부트캠프

멋쟁이사자처럼의 13년 교육 노하우로 IT 취업의 꿈을 현실로!