게시글
스터디
모집완료
📢 [스터디 모집] GraphRAG 강좌 함께 공부하실 분 모집
- 1
- 0
- 167
스터디
모집완료
완) [사당 오프모임, 일요일] 'LangChain 한국어 튜토리얼' 스터디
- 0
- 1
- 270
스터디
모집중
[사당,주말] 자바 퍼시스턴스 프로그래밍 도서 스터디 모집
- 1
- 0
- 533
스터디
모집완료
완) 퀀트 전략을 위한 인공지능 트레이딩
- 1
- 0
- 561
스터디
모집완료
퀀트 프로그래밍 스터디 모집
- 0
- 0
- 728
질문&답변
수업자료
맥에서 압축 파일 만들면 저렇게 되던데 윈도우즈 기본 압축유틸이 못 풀어주더라구요. 전 7zip깔아서 풀었습니다.
- 0
- 3
- 255
질문&답변
useForm 관련 질문입니다.
자문자답입니다. reValidateMode 가 onChange라 그런건가 보네요. https://react-hook-form.com/api
- 0
- 2
- 353
블로그
전체 72025. 06. 15.
1
일프로 3주차 발자취
* 손쉽게 데브옵스 환경을 구축하는 방법- Vagrant랑 스크립트로 Jenkins, K8s, Docker 환경을 한 번에 구성함- Jenkins 대시보드랑 K8s 대시보드까지 바로 접속 가능하게 되어 있음- kubectl 인증서 복사해서 사용하는 구조 실습- VM 네트워크 구성이랑 Jenkins가 이미 설치된 상태라 실습 위주로 진행 가능함- 기본적으로 DevOps 환경에 필요한 구성요소를 다 갖춘 느낌→ 직접 설치 안 해도 되는 게 편했고, 환경 구조 자체를 이해하기엔 괜찮았음* 배포를 시작하기 전에 반드시 알아야 할 것들- CI/CD 전반 흐름 설명 (개발 → 테스트 → 빌드 → 배포 → 운영)- 배포 전략 종류 비교: Rolling Update / Blue-Green / Canary→ 단순히 yaml만 만지는 게 아니라, 전체 흐름이 머릿속에 좀 정리되는 느낌* Jenkins Pipeline 기초부터 Blue-Green까지- Jenkinsfile로 파이프라인 구성: 소스 빌드 → 컨테이너 빌드 → 쿠버네티스 배포- Blue/Green 배포 실습: 두 버전 배포하고 selector 바꿔서 트래픽 전환- 수동 전환도 해보고, 자동화 스크립트도 따로 구성해봄- 버전 관리, 라벨/셀렉터 활용하는 구조 이해하는 데 도움이 됨→ 직접 파이프라인 돌아가게 해보니까 전체 흐름이 눈에 보임. 생각보다 할만했음* Helm과 Kustomize 비교하며 사용하기- Helm: 패키지처럼 앱 배포, 템플릿 구조. values.yaml로 설정 주입- Kustomize: base + overlay 방식. 간단한 환경 오버레이 구성에 유리- Helm은 재사용성 좋고, Kustomize는 직관적인 구성에 강점→ 헬름 구조 익숙해지면 생각보다 어렵진 않음. 실무에선 둘 다 써야 할 듯
2025. 06. 10.
0
일프로 미션4 PVC/PV, Deployment, Service, HPA
1. PVC/PV1-1 로컬 동작 확인curl http://192.168.56.30:31231/create-file-pod # /usr/src/myapp/tmp에 랜덤한 파일 생성 curl http://192.168.56.30:31231/create-file-pv # /usr/src/myapp/files/dev에 랜덤한 파일 생성1-2 생성 결과1-3 pod 삭제kubectl delete -n anotherclass-123 pod api-tester-1231-5ddb74d6c4-6zzlv1-4 API - 파일 조회curl http://192.168.56.30:31231/list-file-pod # nothing curl http://192.168.56.30:31231/list-file-pv # 파일 유지 1-5 hostPath 동작 확인apiVersion: apps/v1 kind: Deployment metadata: namespace: anotherclass-123 name: api-tester-1231 spec: template: spec: nodeSelector: kubernetes.io/hostname: k8s-master containers: - name: api-tester-1231 volumeMounts: - name: files mountPath: /usr/src/myapp/files/dev - name: secret-datasource mountPath: /usr/src/myapp/datasource volumes: - name: files persistentVolumeClaim: // 삭제 claimName: api-tester-1231-files // 삭제 // 아래 hostPath 추가 hostPath: path: /root/k8s-local-volume/1231 - name: secret-datasource secret: secretName: api-tester-1231-postgresql1-6 로컬 동작 확인curl http://192.168.56.30:31231/create-file-pod # /usr/src/myapp/tmp에 랜덤한 파일 생성 curl http://192.168.56.30:31231/create-file-pv # /usr/src/myapp/files/dev에 랜덤한 파일 생성1-7 생성 결과1-8 pod 삭제 kubectl delete -n anotherclass-123 pod api-tester-1231-df8fd468c-wm2gq1-9 API - 파일 조회curl http://192.168.56.30:31231/list-file-pod # nothing curl http://192.168.56.30:31231/list-file-pv # 파일 유지 2. Deployment2-1 RollingUpdate 하기// 1) HPA minReplica 2로 바꾸기 (이전 강의에서 minReplicas를 1로 바꿔놨었음) kubectl patch -n anotherclass-123 hpa api-tester-1231-default -p '{"spec":{"minReplicas":2}}' // 1) 그외 Deployment scale 명령 kubectl scale -n anotherclass-123 deployment api-tester-1231 --replicas=2 // 1) edit로 모드로 직접 수정 kubectl edit -n anotherclass-123 deployment api-tester-1231 // 2) 지속적으로 Version호출 하기 (업데이트 동안 리턴값 관찰) while true; do curl http://192.168.56.30:31231/version; sleep 2; echo ''; done; // 3) 별도의 원격 콘솔창을 열어서 업데이트 실행 kubectl set image -n anotherclass-123 deployment/api-tester-1231 api-tester-1231=1pro/api-tester:v2.0.0 kubectl set image -n anotherclass-123 deployment/api-tester-1231 // update 실행 포맷 // kubectl set image -n deployment/ =:2-1-1 결과2-2 RollingUpdate (maxUnavailable: 0%, maxSurge: 100%) 하기apiVersion: apps/v1 kind: Deployment metadata: namespace: anotherclass-123 name: api-tester-1231 spec: replicas: 2 strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 25% -> 0% # 수정 maxSurge: 25% -> 100% # 수정2-2-1 업그레이드kubectl set image -n anotherclass-123 deployment/api-tester-1231 api-tester-1231=1pro/api-tester:v1.0.02-2-2 결과2-3 Recreate 하기apiVersion: apps/v1 kind: Deployment metadata: namespace: anotherclass-123 name: api-tester-1231 spec: replicas: 2 strategy: type: RollingUpdate -> Recreate # 수정 rollingUpdate: # 삭제 maxUnavailable: 0% # 삭제 maxSurge: 100% # 삭제2-3-1 업그레이드kubectl set image -n anotherclass-123 deployment/api-tester-1231 api-tester-1231=1pro/api-tester:v2.0.02-3-2 결과2-4 롤백// 이전 버전으로 롤백 kubectl rollout undo -n anotherclass-123 deployment/api-tester-12313. Service3-1 Pod 내부에서 Service 명으로 API 호출 [서비스 디스커버리]// Version API 호출 curl http://api-tester-1231:80/version # 에러3-2 Deployment에서 Pod의 ports 전체 삭제, Service targetPort를 http -> 8080으로 수정apiVersion: apps/v1 kind: Deployment metadata: namespace: anotherclass-123 name: api-tester-1231 spec: template: spec: nodeSelector: kubernetes.io/hostname: k8s-master containers: - name: api-tester-1231 ports: // 삭제 - name: http // 삭제 containerPort: 8080 // 삭제 --- apiVersion: v1 kind: Service metadata: namespace: anotherclass-123 name: api-tester-1231 spec: ports: - port: 80 targetPort: http -> 8080 // 변경 nodePort: 31231 type: NodePort3-3 다시 Pod 내부에서 Service 명으로 API 호출curl http://api-tester-1231:80/version HPA4.1 부하 발생http://192.168.56.30:31231/cpu-load?min=3 // 3분 동안 부하 발생 // 개인 PC 사양(core 수)에 따라 부하가 너무 오르거나/오르지 않을 경우 queryparam으로 수치 조정 http://192.168.56.30:31231/cpu-load?min=3&thread=5 // 3분 동안 5개의 쓰레드로 80% 부하 발생 // default : min=2, thread=104-1-1 부하 확인// 실시간 업데이트는 명령어로 확인하는 게 빨라요 kubectl top -n anotherclass-123 pods kubectl get hpa -n anotherclass-123 // Grafana는 Prometheus를 거쳐 오기 때문에 좀 늦습니다 Grafana > Home > Dashboards > [Default] Kubernetes / Compute Resources / Pod4-1-2 에러시 원복 방법// 1. hpa 삭제 kubectl delete -n anotherclass-123 hpa api-tester-1231-default // 2. deployment replicas 2로 변경 kubectl scale -n anotherclass-123 deployment api-tester-1231 --replicas=2 // 3. hpa 다시 생성 kubectl apply -f - 4-2 [behavior] 미사용으로 적용kubectl edit -n anotherclass-123 hpa api-tester-1231-default --- apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: namespace: anotherclass-123 name: api-tester-1231-default spec: behavior: # 삭제 scaleUp: # 삭제 stabilizationWindowSeconds: 120 # 삭제4-2-1 부하 확인// 실시간 업데이트는 명령어로 확인하는 게 빨라요 kubectl top -n anotherclass-123 pods kubectl get hpa -n anotherclass-123
2025. 06. 10.
1
일프로 미션3 ConfigMap & Secret
▶ 응용1 : Configmap의 환경변수들을 Secret을 사용해서 작성하고, App에서는 같은 결과가 나오도록 확인해 보세요.☞ Secret을 이렇게 사용하는 경우는 별로 보지 못했습니다. 여러가지 방법으로 Secret을 만들어본다는데 의의를 두시면 됩니다. Step1. Secret 생성 (1) - dashboardapiVersion: v1 kind: Secret metadata: namespace: anotherclass-123 name: api-tester-1231-properties labels: part-of: k8s-anotherclass component: backend-server name: api-tester instance: api-tester-1231 version: 1.0.0 managed-by: dashboard stringData: spring_profiles_active: "dev" application_role: "ALL" postgresql_filepath: "/usr/src/myapp/datasource/dev/postgresql-info.yaml"Step1 - Secret 생성 (2) - kubectl #1kubectl apply -f - Step1 - Secret 생성 (2) - kubectl #2 (이렇게 쓰는건 label 넣기도 불편하고, 명령어 관리가 불편하긴 해요)kubectl create secret -n anotherclass-123 generic api-tester-1231-properties2 --from-literal=spring_profiles_active=dev --from-literal=application_role=ALL --from-literal=postgresql_filepath="/usr/src/myapp/datasource/dev/postgresql-info.yaml"결과 확인Step2. Deployment의 envFrom.secretRef 부분 업데이트(1) - 대시보드apiVersion: apps/v1 kind: Deployment metadata: namespace: anotherclass-123 name: api-tester-1231 spec: template: spec: nodeSelector: kubernetes.io/hostname: k8s-master containers: - name: api-tester-1231 image: 1pro/api-tester:v1.0.0 envFrom: - secretRef: name: api-tester-1231-propertiesStep2. Deployment의 envFrom.secretRef 부분 업데이트(2) - kubectlkubectl edit -n anotherclass-123 deployments.apps api-tester-1231 ▶ 응용2 : 반대로 Secret의 DB정보를 Configmap으로 만들어보고 App을 동작시켜 보세요☞ Configmap을 Volume에 연결해서 쓰는 케이스는 매우 많습니다.Step1 - ConfigMap 생성apiVersion: v1 kind: ConfigMap metadata: namespace: anotherclass-123 name: api-tester-1231-postgresql labels: part-of: k8s-anotherclass component: backend-server name: api-tester instance: api-tester-1231 version: 1.0.0 managed-by: dashboard data: postgresql-info.yaml: | driver-class-name: "org.postgresql.Driver" url: "jdbc:postgresql://postgresql:5431" username: "dev" password: "dev123"결과Step2. Deployment의 envFrom.secretRef 부분 업데이트(1) - 대시보드apiVersion: apps/v1 kind: Deployment metadata: namespace: anotherclass-123 name: api-tester-1231 spec: template: spec: nodeSelector: kubernetes.io/hostname: k8s-master containers: - name: api-tester-1231 image: 1pro/api-tester:v1.0.0 volumeMounts: - name: configmap-datasource mountPath: /usr/src/myapp/datasource/dev volumes: - name: configmap-datasource configMap: name: api-tester-1231-postgresqlStep2. Deployment의 envFrom.secretRef 부분 업데이트(2) - kubectlkubectl edit -n anotherclass-123 deployments.apps api-tester-1231
ConfigMap
・
Secret
2025. 06. 10.
0
일프로 미션2 Probe
▶ 응용1 : startupProbe가 실패 되도록 설정해서 Pod가 무한 재기동 상태가 되도록 설정해 보세요.startupProbe의 failureThreshold를 '1'로 설정하면 "/startup"이 가동전 호출로 실패라 인지하고Pod를 재가동하게 됩니다.startupProbe: httpGet: path: "/startup" port: 8080 periodSeconds: 5 failureThreshold: 1재가동 스샷 ▶ 응용2 : 일시적 장애 상황(App 내부 부하 증가)가 시작 된 후, 30초 뒤에 트래픽이 중단되고, 3분 뒤에는 App이 재기동 되도록 설정해 보세요.startupProbe 는 정상적인 설정으로 변경startupProbe: httpGet: path: "/startup" port: 8080 periodSeconds: 5 failureThreshold: 30readinessProbe 실패시 서비스 재연결을 함readinessProbe: httpGet: path: "/readiness" port: 8080 periodSeconds: 10 failureThreshold: 3 # 30slivenessProbe 실패시 Pod를 재기동함livenessProbe: httpGet: path: "/liveness" port: 8080 periodSeconds: 60 failureThreshold: 3 # 3mterminal에서 아래 명령어 실행// 부하 증가 API - (App 내부 isAppReady와 isAppLive를 False로 바꿈) curl http://192.168.56.30:31231/server-load-onPod 재시작 모습▶ 응용3 : Secret 파일(/usr/src/myapp/datasource/postgresql-info.yaml)이 존재하는지 체크하는 readinessProbe를 만들어 보세요.readinessProbe에 없는 파일로 설정하여 에러 발생readinessProbe: exec: command: ["cat", "/usr/src/myapp/datasource/postgresql-infoa.yaml"] periodSeconds: 10 failureThreshold: 3이벤트 확인
probe
2025. 06. 08.
1
Kubernetes 2주차 발자취
* Probe목적: 컨테이너가 잘 작동하고 있는지 확인.종류:Liveness Probe: 컨테이너가 살아있는지 확인. 실패 시 재시작.Readiness Probe: 요청을 받을 준비가 되었는지 확인. 실패 시 Service에서 제외됨.Startup Probe: 애플리케이션이 시작되었는지 확인. 느린 앱에 유용.* ConfigMap목적: 환경설정 데이터를 코드와 분리해서 관리.특징:일반적인 설정 정보(환경변수, 설정파일 경로 등)를 저장.Pod에 환경변수, 볼륨 형태로 주입 가능.* Secret목적: 비밀번호, 인증 토큰 등 민감 정보 저장.특징:Base64로 인코딩되어 저장됨 (보안 강화를 위해 추가 조치 필요).ConfigMap과 유사하게 환경변수나 볼륨으로 주입 가능.주의: Secret은 인코딩일 뿐 암호화가 아님 * PV / PVC (Persistent Volume / Persistent Volume Claim)PV: 클러스터에 의해 제공되는 실제 스토리지.PVC: 사용자가 원하는 스토리지 요청.사용 목적: Pod가 재시작되거나 사라져도 데이터 유지 가능. * Deployment목적: 애플리케이션을 선언적으로 배포하고 관리.기능:원하는 Replica 수 유지.롤링 업데이트, 롤백 지원.Pod 자동 재생성 및 관리.* Service목적: Pod에 안정적인 네트워크 접근 제공.종류:ClusterIP: 클러스터 내부 통신용.NodePort: 외부에서 노드 IP + 포트로 접근 가능.LoadBalancer: 클라우드에서 외부 로드밸런서와 연동.* HPA (Horizontal Pod Autoscaler)목적: 리소스 사용량(CPU, 메모리 등)에 따라 Pod 수 자동 조절.
쿠버네티스
2025. 06. 03.
2
일프로 미션1 설치 점검하기
쿠버네티스 무게감 있게 설치하는 방법 1/2[1-1] 내 PC 네트워크 확인▶ 윈도우 > 실행 > cmd 입력 > 확인c:\사용자>ipconfig[1-2] 내 PC 자원 확인▶ 윈도우 하단 상태바 우클릭 > 작업관리자 > 성능 탭[1-3] VirtualBox 설치 버전 확인▶ Virtualbox 실행 > 도움말 > Virtualbox 정보[FAQ] : https://cafe.naver.com/kubeops/25[1-4] Vagrant 설치 버전 확인▶ 윈도우 > 실행 > cmd 입력 > 확인c:\사용자>vagrant --version[FAQ] : https://cafe.naver.com/kubeops/26[1-5] 원격접속(MobaXterm) 설치 버전 확인▶ MobaXterm 실행 > Help > About MobaXterm[2-1] VirtualBox VM 확인▶ Virtualbox 실행 > VM Name 확인▶ 네이밍 : __[2-2] 내 VM에 적용된 NAT 확인▶ Virtualbox 실행 > k8s_master-node 마우스 우클릭 > 설정 > 네트워크 > 어댑터 1[2-3] 내 VM에 적용된 Host-Only Network 확인▶ Virtualbox 실행 > k8s_master-node 마우스 우클릭 > 설정 > 네트워크 > 어댑터 2[2-4] VirtualBox Host-Only cidr 확인▶파일 > 도구 > Network Manager[FAQ] : https://cafe.naver.com/kubeops/27[3-1] Rocky Linux 버전 확인▶ k8s-master 원격접속 후 명령어 실행[root@k8s-master ~]# cat /etc/*-release▶ 실행 결과[3-2] Hostname 확인▶ k8s-master 원격접속 후 명령어 실행[root@k8s-master ~]# hostname▶ 실행 결과[3-3], [3-4] Network 확인▶ k8s-master 원격접속 후 명령어 실행[root@k8s-master ~]# ip addr▶ 실행 결과[3-5] 자원(cpu, memory) 확인▶ k8s-master 원격접속 후 명령어 실행[root@k8s-master ~]# lscpu [root@k8s-master ~]# free -h▶ 실행 결과[4] Rocky Linux 기본 설정▶ 패키지 업데이트 진행[update 25.01.02] 강의와 동일한 실습 환경을 유지하기 위해 Linux Update는 하지 않습니다.▶ 타임존 설정 확인(스크립트로 적용된 명령: timedatectl set-timezone Asia/Seoul) - 중복 실행할 필요는 없습니다.[root@k8s-master ~]# timedatectl▶ 실행 결과[5] kubeadm 설치 전 사전작업▶ 방화벽 해제 확인(스크립트로 적용된 명령: systemctl stop firewalld && systemctl disable firewalld) - 중복 실행할 필요는 없습니다.[root@k8s-master ~]# systemctl status firewalld▶ 실행 결과▶ 스왑(swap) 비활성화 확인(스크립트로 적용된 명령: swapoff -a && sed -i '/ swap / s/^/#/' /etc/fstab) - 중복 실행할 필요는 없습니다.[root@k8s-master ~]# free [root@k8s-master ~]# cat /etc/fstab | grep swap▶ 실행 결과Swap에 할당된 자원이 없어야함# [Kubernetes Docs] : https://kubernetes.io/ko/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-%EC%A0%84%EC%97%90[6] 컨테이너 런타임 설치[6-1] 컨테이너 런타임 설치 전 사전작업▶ iptables 세팅# 설정 세팅 확인[root@k8s-master ~]# cat /etc/modules-load.d/k8s.conf[root@k8s-master ~]# cat /etc/sysctl.d/k8s.conf # 모듈 적제 확인[root@k8s-master ~]# lsmod | grep overlay[root@k8s-master ~]# lsmod | grep br_netfilter▶ 실행 결과[Kubernetes Docs] : https://kubernetes.io/ko/docs/setup/production-environment/container-runtimes/#ipv4%EB%A5%BC-%ED%8F%AC%EC%9B%8C%EB%94%A9%ED%95%98%EC%97%AC-iptables%EA%B0%80-%EB%B8%8C%EB%A6%AC%EC%A7%80%EB%90%9C-%ED%8A%B8%EB%9E%98%ED%94%BD%EC%9D%84-%EB%B3%B4%EA%B2%8C-%ED%95%98%EA%B8%B0[6-2] 컨테이너 런타임 (containerd 설치)[Kubernetes Docs] : https://kubernetes.io/ko/docs/setup/production-environment/container-runtimes/#containerd[Containerd Release] : https://github.com/containerd/containerd/blob/main/RELEASES.md#kubernetes-support[6-2-1] containerd 패키지 설치 (option2)[Containerd Docs] : https://github.com/containerd/containerd/blob/main/docs/getting-started.md#option-2-from-apt-get-or-dnf[6-2-1-1] docker engine (containerd.io)만 설치▶ docker repo 설정 확인(스크립트로 적용된 명령: yum install -y yum-utils, yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo)[root@k8s-master ~]# yum repolist enabled▶ 실행 결과[Docker Docs] : https://docs.docker.com/engine/install/centos/#install-using-the-repository▶containerd 설치 확인(스크립트로 이미 적용된 명령: yum install -y containerd.io-1.6.21-3.1.el8) - 중복실행은 하지마세요![root@k8s-master ~]# systemctl status containerd▶ 실행 결과-> 확인 후 [ctrl + c]로 빠져나오기[Docker Docs] : https://docs.docker.com/engine/install/centos/#install-using-the-repository▶설치 가능한 버전의 containerd.io 리스트 확인[root@k8s-master ~]# yum list containerd.io--showduplicates | sort -r▶ 실행 결과[6-3] 컨테이너 런타임 (CRI활성화)* 쿠버네티스 문서에 Kubelet의 Cgroup의 Default가 cgroupfs라고 말씀 드렸는데, 레드햇 계열 리눅스의 경우 systemd를 메인으로 프로세스를 실행시키는 시스템이기 때문에, 쿠버네티스 설치시Default로 systemd가 세팅됩니다. 이 경우 containerd도 systemd로 변경하여 모두 systemd를 쓰는게 Core 사용에 부담이 없습니다.▶ cri 활성화 설정 확인(스크립트로 이미 적용된 명령: containerd config default > /etc/containerd/config.toml; sed -i 's/ SystemdCgroup = false/ SystemdCgroup = true/' /etc/containerd/config.toml) - 중복실행은 하지마세요![root@k8s-master ~]# cat /etc/containerd/config.toml▶ 실행 결과 :* false 일 경우 cgroupfs▶ kubelet cgroup 확인 (configmap)[root@k8s-master ~]# kubectl get -n kube-system cm kubelet-config -o yaml▶ 실행 결과 :▶ kubelet cgroup 확인 (kubelet)[root@k8s-master ~]# cat /var/lib/kubelet/config.yaml▶ 실행 결과 :* kubelet에서 cgroup 수정 필요시 적용 방법// 아래 두 군데에서 cgroupDriver를 systemd 혹은 cgroupfs로 변경[root@k8s-master ~]# vi /var/lib/kubelet/config.yaml[root@k8s-master ~]# kubectl edit -n kube-system cm kubelet-config[root@k8s-master ~]# systemctl restart kubelet[Kubernetes Docs] : https://kubernetes.io/ko/docs/setup/production-environment/container-runtimes/#containerd[7] kubeadm 설치▶ repo 설정 확인[root@k8s-master ~]# yum repolist enabled▶ 실행 결과[Kubernetes Docs] : https://kubernetes.io/ko/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#kubeadm-kubelet-%EB%B0%8F-kubectl-%EC%84%A4%EC%B9%98▶ SELinux 설정 확인[root@k8s-master ~]# cat /etc/selinux/config[root@k8s-master ~]# sestatus▶ 실행 결과▶ kubelet, kubeadm, kubectl 패키지 설치(스크립트로 이미 적용된 명령: yum install -y kubelet-1.27.2-150500.1.1.x86_64 kubeadm-1.27.2-150500.1.1.x86_64 kubectl-1.27.2-150500.1.1.x86_64 --disableexcludes=kubernetes) - 중복실행은 하지 마세요!#버전 보기[root@k8s-master ~]# kubeadm version[root@k8s-master ~]# kubectl version#상태 보기[root@k8s-master ~]# systemctl status kubelet#설정 파일 위치[root@k8s-master ~]# cat /var/lib/kubelet/config.yaml#로그 조회[root@k8s-master ~]# journalctl -u kubelet | tail -10▶ 실행 결과-> 확인 후 [ctrl + c]로 빠져나오기* stop 상태일 때는 아래 명령으로 올리기[root@k8s-master ~]# systemctl restart kubelet▶ 설치 가능한 버전의 kubeadm 리스트 확인[root@k8s-master ~]# yum list --showduplicates kubeadm --disableexcludes=kubernetes▶ 실행 결과[8] kubeadm으로 클러스터 생성[Kubernetes Docs] : https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/[8-1] 클러스터 초기화 (Pod Network 세팅)▶ 클러스터 상태 확인(스크립트로 이미 적용된 명령: kubeadm init --pod-network-cidr=20.96.0.0/12 --apiserver-advertise-address 192.168.56.30) - 중복실행은 하지 마세요!# master node 상태확인[root@k8s-master ~]# kubectl get node# pod network cidr 설정 확인[root@k8s-master ~]# kubectl cluster-info dump | grep -m 1 cluster-cidr# apiserver advertise address 적용 확인[root@k8s-master ~]# kubectl cluster-info# kubernetes component pod 확인[root@k8s-master ~]# kubectl get pods -n kube-system▶ 실행 결과 :[Kubernetes Docs] : https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#initializing-your-control-plane-node* Cluster가 정상이 아닐 때는 아래 명령으로 reset후 다시 init 해주기.* reset 실행 후 1분 정도 시간이 지난 후에 init을 해주세요.[root@k8s-master ~]# kubeadm reset [root@k8s-master ~]# kubeadm init --pod-network-cidr=20.96.0.0/12--apiserver-advertise-address 192.168.56.30[8-2] kubectl 사용 설정▶ 인증서 설정 확인[root@k8s-master ~]# cat ~/.kube/config▶ 실행 결과 :[Kubernetes Docs] : https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#more-information[8-3] CNI Plugin 설치 (calico)▶ calico pod 설치 및 pod network cidr 적용 확인# Calico Pod 상태 확인 [root@k8s-master ~]# kubectl get -n calico-system pod [root@k8s-master ~]# kubectl get -n calico-apiserver pod # Calico에 pod network cidr 적용 확인 [root@k8s-master ~]# kubectl get installations.operator.tigera.io default -o yaml | grep cidr▶ 실행 결과 :[Calico Docs] : https://docs.tigera.io/calico/latest/getting-started/kubernetes/self-managed-onprem/onpremises#install-calico* Calico 설치가 정상이 아닐 때 (Calico가 CrashLoopBackOff 상태고, coredns가 가 Pending 상태)#Calico 삭제 [root@k8s-master ~]# kubectl delete-f https://raw.githubusercontent.com/k8s-1pro/install/main/ground/k8s-1.27/calico-3.26.4/calico.yaml[root@k8s-master ~]# kubectl delete-f https://raw.githubusercontent.com/k8s-1pro/install/main/ground/k8s-1.27/calico-3.26.4/calico-custom.yaml#Calico 재설치 [root@k8s-master ~]# kubectl create -f https://raw.githubusercontent.com/k8s-1pro/install/main/ground/k8s-1.27/calico-3.26.4/calico.yaml[root@k8s-master ~]# kubectl create -f https://raw.githubusercontent.com/k8s-1pro/install/main/ground/k8s-1.27/calico-3.26.4/calico-custom.yaml[8-4] Master에 pod를 생성 할 수 있도록 설정▶ Master Node에 Taint 해제 확인(스크립트로 이미 적용된 명령: kubectl taint nodes k8s-master node-role.kubernetes.io/control-plane- )[root@k8s-master ~]# kubectl describe nodes | grep Taints▶ 실행 결과 :[Kubernetes Docs] : https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#control-plane-node-isolation[9] 쿠버네티스 편의 기능 설치[9-1] kubectl 자동완성 기능▶ kubectl 기능 설정 확인[root@k8s-master ~]# cat ~/.bashrc▶ 실행 결과 :[kubectl Cheat Sheet] : https://kubernetes.io/docs/reference/kubectl/cheatsheet/[9-2] Dashboard 설치▶ dashboard 설치 확인[root@k8s-master ~]# kubectl get pod -n kubernetes-dashboard▶ 실행 결과 :[kubernetes dashboard] : https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/※ 문제시 관련 FAQ : https://cafe.naver.com/kubeops/22[9-3] Metrics Server 설치▶ metrics server 설치 확인[root@k8s-master ~]# kubectl get pod -n kube-system | grep metrics [root@k8s-master ~]# kubectl top pod -A▶ 실행 결과 :[kubernetes Metrics Server : https://github.com/kubernetes-sigs/metrics-server* 설치 후 kubectl top pod -A 명령시 error: Metrics API not available 메세지가 나올때최초 설치시 / VM 재기동시 매트릭 정보가 수집되는데 시간이 좀 걸릴 수 있습니다.
2025. 06. 01.
2
🚀 Kubernetes 발전사: 문제 해결 중심
컨테이너 기술과 Kubernetes의 발전을 문제 해결 관점에서 살펴보면, 각 기술이 어떤 필요에 의해 등장했는지 자연스럽게 이해할 수 있습니다. 실제 발생한 문제들과 그 해결 과정을 중심으로 정리해보겠습니다. 1단계: 서버 자원 활용의 딜레마 (2000년대 초반)🔴 문제상황가상 머신의 한계각 VM마다 전체 운영체제 필요 → 메모리, CPU 낭비 심각하나의 물리 서버에 몇 개 안 되는 VM만 실행 가능부팅 시간도 오래 걸리고 관리 복잡물리 서버 직접 사용의 문제여러 애플리케이션이 같은 서버에서 실행되면 서로 간섭라이브러리 버전 충돌, 포트 충돌 등 문제 빈발장애 발생 시 다른 애플리케이션까지 영향🟢 해결책: 리눅스 커널 격리 기술 발전핵심 기술들의 등장chroot (1982년): 파일 시스템 격리 - "애플리케이션별로 보이는 파일 시스템 분리"namespace (2002년): 프로세스, 네트워크, 사용자 등 시스템 리소스 격리cgroup (2006년): CPU, 메모리, 디스크 I/O 등 하드웨어 자원 제어 및 모니터링이 기술들이 현대 컨테이너의 토대가 되었지만, 직접 사용하기엔 너무 복잡했습니다.2단계: 커널 기술의 복잡성 문제 (2008년)🔴 문제상황개발자에게는 너무 어려운 기술chroot, namespace, cgroup을 조합해서 사용하려면 리눅스 커널 전문 지식 필요매번 복잡한 설정 과정 반복같은 환경을 다른 서버에 재현하기 어려움실수로 잘못 설정하면 보안 취약점 발생 가능🟢 해결책: LXC (Linux Containers) 등장"쉬운 컨테이너"의 시작복잡한 커널 기술들을 묶어서 간단한 명령어로 제공설정 파일을 통한 일관된 환경 구성가상 머신보다 가볍고, 물리 서버보다 안전한 중간 지점 제공하지만 여전히 시스템 관리자 수준의 기술 지식이 필요했습니다.3단계: 개발자 친화성 부족 (2013년)🔴 문제상황LXC의 한계여전히 시스템 관리자 중심의 도구 → 개발자가 사용하기 복잡컨테이너 이미지 관리 기능 없음 → "내가 만든 환경을 어떻게 공유하지?"네트워킹, 로깅, 스토리지 관리 등 실제 서비스 운영에 필요한 기능 부족각 배포판마다 다른 설정 방식🟢 해결책: Docker의 혁신적 등장개발자 경험(DX) 혁신초기(2013년): LXC를 백엔드로 사용하되 사용자 친화적 인터페이스 제공2014년 Docker 0.9: libcontainer 도입으로 LXC 의존성 제거통합 관리 플랫폼:직관적인 CLI (docker run, docker build)Docker Hub를 통한 이미지 공유자동 로그 관리, 네트워크 설정Dockerfile을 통한 재현 가능한 환경 구성Docker의 성공 비결은 복잡한 기술을 개발자가 쉽게 사용할 수 있게 만든 것이었습니다.4단계: 컨테이너 관리의 복잡성 (2014년)🔴 문제상황운영 환경의 현실수십, 수백 개의 컨테이너를 어떻게 관리할 것인가?컨테이너가 죽으면 누가 다시 실행시켜 주나?트래픽 증가 시 컨테이너를 자동으로 늘리려면?여러 컨테이너 간 네트워크 통신은 어떻게?로드밸런싱, 서비스 디스커버리는?🟢 해결책: Kubernetes 등장컨테이너 오케스트레이션의 시작Google의 내부 시스템 Borg 경험을 바탕으로 개발초기 아키텍처 (단순함):kube-apiserver: 사용자 요청 처리kubelet: 각 노드에서 컨테이너 관리직접 통합: kubelet → Docker API 직접 호출당시에는 Docker가 거의 유일한 컨테이너 런타임이었기 때문에 이런 단순한 구조로도 충분했습니다.5단계: 런타임 생태계의 다양화 (2016년)🔴 문제상황단일 런타임 의존의 위험성Docker에만 의존하는 구조의 리스크CoreOS rkt, Intel Clear Containers 등 대안 런타임 등장각 런타임마다 장단점이 다름 (보안, 성능, 기능 등)하지만 Kubernetes는 Docker에만 연결 가능 → 새로운 런타임 추가할 때마다 kubelet 코드 수정 필요🟢 해결책 1: Docker 내부 구조 개선containerd 프로젝트 시작2016년 4월 Docker 1.11: 내부적으로 containerd 사용 시작2016년 12월: containerd를 독립 오픈소스 프로젝트로 공개구조 변경: Docker Engine = dockerd → containerd → runccontainerd가 실제 컨테이너 라이프사이클 관리 담당🟢 해결책 2: CRI(Container Runtime Interface) 도입Kubernetes 1.5 (2016년 12월)표준 인터페이스 정의: kubelet과 런타임 간의 통신 규약 표준화플러그인 아키텍처: 새로운 런타임 추가 시 kubelet 코드 수정 불필요확장성 확보: 런타임 벤더가 CRI 구현체만 제공하면 됨하지만 문제 발생: Docker는 CRI를 직접 지원하지 않음 → Kubernetes가 dockershim 임시 어댑터 개발6단계: 표준화의 필요성 (2015-2017년)🔴 문제상황런타임 간 호환성 부재Docker, rkt, containerd 등 각각 다른 방식으로 동작컨테이너 이미지 포맷이 런타임마다 다름A 런타임에서 만든 이미지가 B 런타임에서 실행 안 되는 경우 발생벤더 락인(vendor lock-in) 위험성🟢 해결책: OCI(Open Container Initiative) 표준 제정2015년 6월 OCI 설립Docker와 CoreOS(rkt 개발사)가 주도목표: 컨테이너 런타임과 이미지 포맷 표준화결과: 런타임 간 상호 호환성 보장runc 개발 (2015년)OCI 표준을 구현한 로우레벨 런타임Docker의 libcontainer를 OCI 표준에 맞게 재작성containerd가 libcontainer 대신 runc 사용으로 변경7단계: dockershim의 관리 부담 (2018-2020년)🔴 문제상황임시방편의 한계dockershim은 원래 "임시" 해결책이었는데 계속 사용됨Docker가 CRI를 직접 지원하지 않아서 Kubernetes 팀이 어쩔 수 없이 유지보수복잡한 호출 체인: kubelet → dockershim → Docker API → containerd → runcKubernetes 팀에게 Docker 관련 버그까지 떠안기는 부담성능 오버헤드와 아키텍처 복잡성🟢 해결책: Docker 지원 중단 결정2020년 12월 Kubernetes 1.20에서 dockershim deprecated 선언"Kubernetes 1.24에서 dockershim 제거 예정"2년간의 마이그레이션 기간 제공containerd, CRI-O 등 대안 런타임 권장하지만 사용자 커뮤니티에서 큰 우려 표출 - 많은 기업이 Docker 기반으로 시스템 구축했기 때문8단계: 커뮤니티의 대안 제시 (2021-2022년)🔴 문제상황현실적인 마이그레이션 어려움수많은 기업들이 Docker 기반으로 운영 중containerd로 전환하는 데 시간과 비용 필요개발자들의 Docker 도구 친숙도기존 CI/CD 파이프라인의 Docker 의존성🟢 해결책: cri-dockerd 프로젝트Mirantis와 커뮤니티 협력dockershim을 Kubernetes에서 분리하여 독립 프로젝트로 개발cri-dockerd: Docker를 CRI 호환으로 만들어주는 어댑터오픈소스로 제공하여 Docker 사용 지속 가능결과: 사용자들이 자신의 일정에 맞춰 점진적으로 전환할 수 있게 됨9단계: 최적화된 구조로의 진화 (2019-현재)🔴 문제상황여전히 비효율적인 구조Docker 사용 시: kubelet → cri-dockerd → Docker → containerd → runc불필요한 중간 계층들로 인한 성능 오버헤드복잡한 의존성 체인실제로는 containerd만 있으면 충분한 상황🟢 해결책: 직접 연결 아키텍처containerd의 CRI 플러그인 개발containerd에서 CRI 인터페이스 직접 지원단순화된 구조: kubelet → containerd → runc중간 계층 제거로 성능 향상 및 안정성 개선현재 권장 아키텍처Kubernetes 1.24부터 dockershim 완전 제거containerd가 가장 널리 사용되는 런타임CRI-O, Firecracker 등 다양한 선택지 제공🎯 현재 상황 정리 (2025년)📊 런타임 선택지런타임특징주 사용처containerd가장 일반적, 안정적대부분의 Kubernetes 클러스터CRI-ORed Hat 주도, OCI 호환OpenShift, 엔터프라이즈 환경Docker + cri-dockerd레거시 지원기존 Docker 기반 시스템🏗 현재 아키텍처 계층Kubernetes (kubelet) ↓ CRI High-level Runtime (containerd, CRI-O) ↓ OCI Low-level Runtime (runc, firecracker) ↓ Linux Kernel (cgroup, namespace, chroot)🔄 발전 과정의 패턴전체 발전 과정을 보면 다음과 같은 패턴을 발견할 수 있습니다:복잡함 → 단순함: 어려운 기술을 쉽게 사용할 수 있게 개선단일 선택 → 다양한 선택: 한 가지 솔루션에서 여러 대안으로 확장표준화: 혼재된 기술들을 통일된 규약으로 정리최적화: 불필요한 복잡성 제거하고 성능 개선각 단계의 변화는 모두 실제 사용자들이 겪은 구체적인 문제를 해결하기 위한 필연적 진화였습니다. 기술적 완벽함보다는 실용성과 사용자 경험을 우선시한 결과가 현재의 성숙한 컨테이너 생태계를 만들어냈습니다.현재의 아키텍처는 이러한 시행착오를 통해 완성된 안정적인 구조로, 앞으로도 컨테이너 기술 발전의 견고한 기반이 될 것입니다.
쿠버네티스
・
발전사