[{"data":1,"prerenderedAt":1683},["ShallowReactive",2],{"post-document:\u002Fbackend\u002Fkubernetes\u002F2026\u002F09\u002F06\u002Fkubernetes-introduction\u002F":3},{"id":4,"title":5,"body":6,"categories":1668,"date":1671,"description":1672,"extension":1673,"image":1674,"key_concepts":1674,"last_modified_at":1674,"legacyPath":1675,"meta":1676,"navigation":376,"part":1674,"path":1678,"published":376,"robots":1674,"seo":1679,"series":1674,"stem":1680,"strengths":1674,"summary":1674,"tags":1681,"tradeoffs":1674,"__hash__":1682},"posts\u002Fposts\u002FBackend\u002FKubernetes\u002F2026-09-06-kubernetes-introduction.md","쿠버네티스 입문",{"type":7,"value":8,"toc":1639},"minimark",[9,13,20,23,27,32,121,124,135,140,145,148,151,155,227,243,245,251,254,258,262,265,282,285,288,293,295,319,322,325,328,332,335,341,344,347,418,421,425,428,431,461,465,468,471,477,481,550,554,604,609,612,615,618,622,625,630,634,754,759,763,767,1032,1036,1166,1170,1175,1178,1183,1186,1189,1192,1198,1201,1206,1209,1213,1219,1223,1241,1245,1266,1270,1284,1287,1293,1303,1307,1313,1318,1322,1325,1343,1346,1354,1359,1365,1368,1372,1375,1471,1481,1484,1487,1493,1496,1500,1556,1559,1563,1567,1570,1613,1620,1624,1627,1630,1635],[10,11,5],"h1",{"id":12},"쿠버네티스-입문",[14,15,16],"blockquote",{},[17,18,19],"p",{},"쿠버네티스는 “이 애플리케이션을 몇 개, 어떤 상태로 실행할지” 선언하면, 실제 실행 상태를 그 선언에 맞게 유지하는 시스템",[17,21,22],{},"\"웹 서버를 3개 유지해\"라고 설정하면, 처음에는 3개를 실행하는 것을 넘어서, 실행 단위가 계속 유지될 수 있도록 상태를 계속 조정해 주는 컨테이너 오케스트레이션 툴",[10,24,26],{"id":25},"_1-핵심-단어-정의","1. 핵심 단어 정의",[28,29,31],"h2",{"id":30},"_1-1-무엇을-실행하고-어디에서-실행할까","1-1. 무엇을 실행하고, 어디에서 실행할까?",[33,34,35,51],"table",{},[36,37,38],"thead",{},[39,40,41,45,48],"tr",{},[42,43,44],"th",{},"용어",[42,46,47],{},"쉬운 정의",[42,49,50],{},"예시",[52,53,54,69,82,95,108],"tbody",{},[39,55,56,63,66],{},[57,58,59],"td",{},[60,61,62],"strong",{},"Image",[57,64,65],{},"프로그램과 실행에 필요한 파일을 담은 패키지",[57,67,68],{},"Nginx 이미지",[39,70,71,76,79],{},[57,72,73],{},[60,74,75],{},"Container",[57,77,78],{},"이미지를 바탕으로 실행한 격리된 프로그램 환경",[57,80,81],{},"실행 중인 Nginx",[39,83,84,89,92],{},[57,85,86],{},[60,87,88],{},"Pod",[57,90,91],{},"쿠버네티스가 배포하고 관리하는 가장 작은 실행 단위. 하나 이상의 컨테이너를 묶음",[57,93,94],{},"Nginx 컨테이너 하나가 들어 있는 Pod",[39,96,97,102,105],{},[57,98,99],{},[60,100,101],{},"Node",[57,103,104],{},"Pod를 실행하는 컴퓨터. 물리 서버나 가상 머신일 수 있음",[57,106,107],{},"서버 A",[39,109,110,115,118],{},[57,111,112],{},[60,113,114],{},"Cluster",[57,116,117],{},"노드들과 이를 관리하는 구성 요소를 묶은 전체 시스템",[57,119,120],{},"우리 서비스의 쿠버네티스 운영 환경",[17,122,123],{},"용어 관계는 아래와 같다.",[125,126,132],"pre",{"className":127,"code":129,"language":130,"meta":131},[128],"language-text","Cluster\n├── Node A\n│   ├── Pod 1\n│   │   └── Nginx 컨테이너\n│   └── Pod 2\n│       └── Nginx 컨테이너\n│\n└── Node B\n    └── Pod 3\n        └── Nginx 컨테이너\n","text","",[133,134,129],"code",{"__ignoreMap":131},[14,136,137],{},[17,138,139],{},"Pod 3개가 반드시 서버 3대를 의미하지는 않아. 한 노드에서 여러 Pod를 실행할 수 있다.",[141,142,144],"h3",{"id":143},"근데-왜-컨테이너가-아니라-pod를-관리할까","근데 왜 컨테이너가 아니라 Pod를 관리할까?",[17,146,147],{},"함께 실행해야 하는 컨테이너들이 있기 때문.",[17,149,150],{},"예를 들어 애플리케이션 컨테이너와 그 애플리케이션을 보조하는 컨테이너를 하나의 Pod로 넣으면 같은 노드에 함께 배치되고 네트워크를 공유할 수 있다.",[28,152,154],{"id":153},"_1-2-실행-상태는-무엇으로-관리할까","1-2. 실행 상태는 무엇으로 관리할까?",[33,156,157,165],{},[36,158,159],{},[39,160,161,163],{},[42,162,44],{},[42,164,47],{},[52,166,167,177,187,197,207,217],{},[39,168,169,174],{},[57,170,171],{},[60,172,173],{},"Deployment",[57,175,176],{},"사용할 이미지, Pod 개수, 업데이트 방식 등을 선언하는 배포 관리 객체",[39,178,179,184],{},[57,180,181],{},[60,182,183],{},"ReplicaSet",[57,185,186],{},"같은 형태의 Pod가 지정한 개수만큼 존재하도록 관리하는 객체",[39,188,189,194],{},[57,190,191],{},[60,192,193],{},"Service",[57,195,196],{},"Pod가 바뀌어도 일정한 이름과 접속 지점으로 접근하게 해 주는 네트워크 객체",[39,198,199,204],{},[57,200,201],{},[60,202,203],{},"Label \u002F Selector",[57,205,206],{},"Label은 객체에 붙이는 명찰, Selector는 그 명찰로 대상을 고르는 조건",[39,208,209,214],{},[57,210,211],{},[60,212,213],{},"Manifest",[57,215,216],{},"어떤 객체를 어떤 설정으로 만들지 적은 명세. 보통 YAML 파일로 작성",[39,218,219,224],{},[57,220,221],{},[60,222,223],{},"kubectl",[57,225,226],{},"쿠버네티스에 요청을 보내고 상태를 조회하는 명령줄 도구",[228,229,230,234,237,240],"ul",{},[231,232,233],"li",{},"Deployment와 ReplicaSet은 Pod 운영을 담당",[231,235,236],{},"Service는 Pod에 접근하는 방법을 제공",[231,238,239],{},"Manifest는 이 객체들을 제공",[231,241,242],{},"kubectl로 적용",[17,244,50],{},[125,246,249],{"className":247,"code":248,"language":130,"meta":131},[128],"Deployment: “이 웹 서버를 이런 설정으로 운영해.”\nReplicaSet: “그 설정의 Pod 개수를 유지해.”\nPod:        “실제 애플리케이션이 실행되는 단위야.”\nService:    “실행 중인 Pod에 이 이름으로 접속해.”\n",[133,250,248],{"__ignoreMap":131},[17,252,253],{},"Deployment는 사용자가 작성하고, ReplicaSet, Pod는 쿠버네티스가 만들도록 맡긴다.",[10,255,257],{"id":256},"_2-아키텍처-철학-왜-이렇게-설계했을까","2. 아키텍처 철학 : 왜 이렇게 설계했을까?",[28,259,261],{"id":260},"_2-1-무엇을-할지보다-어떤-상태여야-하는지를-선언","2-1 \"무엇을 할지\"보다 \"어떤 상태여야 하는지\"를 선언",[17,263,264],{},"우리가 자주 쓰는 명령형 방식을 살펴보자.\n명령형 방식의 경우는 사용자가 직접 작업 순서를 지시한다.",[266,267,268,271,274,277,279],"ol",{},[231,269,270],{},"서버 A에 접속한다.",[231,272,273],{},"컨테이너를 실행한다.",[231,275,276],{},"서버 B에 접속한다.",[231,278,273],{},[231,280,281],{},"하나가 사라지면 사람이 다시 실행한다.",[17,283,284],{},"그러나!",[17,286,287],{},"쿠버네티스의 경우에는 이와 다른 \"선언형 방식\"을 사용한다.",[14,289,290],{},[17,291,292],{},"선언형 방식이란, 최종적으로 원하는 상태를 적는 것",[17,294,50],{},[125,296,300],{"className":297,"code":298,"language":299,"meta":131,"style":131},"language-yaml shiki shiki-themes github-light github-dark","replicas: 3\n","yaml",[133,301,302],{"__ignoreMap":131},[303,304,307,311,315],"span",{"class":305,"line":306},"line",1,[303,308,310],{"class":309},"s9eBZ","replicas",[303,312,314],{"class":313},"sVt8B",": ",[303,316,318],{"class":317},"sj4cs","3\n",[17,320,321],{},"이 설정의 의미는 \"Pod를 3개 만들어\"가 아닌, \"이 애플리케이션의 원하는 Pod 개수는 3개야\"라고 말하는 것.",[17,323,324],{},"쿠버네티스는 이 원하는 상태를 실제 상태와 비교하면서 조정한다.",[17,326,327],{},"참고로 우리가 앞서서 썼던 Docker Compose도 선언형 설정을 사용한다. 다만 쿠버네티스와 Docker Compose의 결정적 차이는, 쿠버네티스가 클러스터 수준에서 여러 관리 구성 요소가 상태를 지속적으로 조정한다는 점이다. (규모가 더 큰 것에 집중하면 될 것 같다.)",[28,329,331],{"id":330},"_2-2-원하는-상태와-실제-상태의-차이를-줄인다","2-2. 원하는 상태와 실제 상태의 차이를 줄인다.",[17,333,334],{},"Reconciliation : 조정",[125,336,339],{"className":337,"code":338,"language":130,"meta":131},[128],"원하는 상태: Pod 3개\n실제 상태:   Pod 2개\n\n차이 발견\n    ↓\n부족한 Pod 1개 생성 요청\n    ↓\n실행 상태를 다시 확인\n",[133,340,338],{"__ignoreMap":131},[17,342,343],{},"쿠버네티스에서는 Controller라는 프로그램을 통해서 원하는 상태와 실제 상태가 일치하도록 조정한다.",[17,345,346],{},"Pseudo Code",[125,348,352],{"className":349,"code":350,"language":351,"meta":131,"style":131},"language-python shiki shiki-themes github-light github-dark","while True:\n    desired = read_desired_pod_count()   # 원하는 개수\n    current = count_managed_pods()      # 현재 관리 중인 개수\n\n    if current \u003C desired:\n        request_new_pods(desired - current)\n\n    elif current > desired:\n        request_pod_deletions(current - desired)\n\n    wait_for_next_check()\n","python",[133,353,354,359,365,371,378,384,390,395,401,407,412],{"__ignoreMap":131},[303,355,356],{"class":305,"line":306},[303,357,358],{},"while True:\n",[303,360,362],{"class":305,"line":361},2,[303,363,364],{},"    desired = read_desired_pod_count()   # 원하는 개수\n",[303,366,368],{"class":305,"line":367},3,[303,369,370],{},"    current = count_managed_pods()      # 현재 관리 중인 개수\n",[303,372,374],{"class":305,"line":373},4,[303,375,377],{"emptyLinePlaceholder":376},true,"\n",[303,379,381],{"class":305,"line":380},5,[303,382,383],{},"    if current \u003C desired:\n",[303,385,387],{"class":305,"line":386},6,[303,388,389],{},"        request_new_pods(desired - current)\n",[303,391,393],{"class":305,"line":392},7,[303,394,377],{"emptyLinePlaceholder":376},[303,396,398],{"class":305,"line":397},8,[303,399,400],{},"    elif current > desired:\n",[303,402,404],{"class":305,"line":403},9,[303,405,406],{},"        request_pod_deletions(current - desired)\n",[303,408,410],{"class":305,"line":409},10,[303,411,377],{"emptyLinePlaceholder":376},[303,413,415],{"class":305,"line":414},11,[303,416,417],{},"    wait_for_next_check()\n",[17,419,420],{},"핵심은 한 번 실행하고 끝나는 스크립트가 아니라, 계속 상태를 확인하는 관리 구조임에 집중하면 될 것 같다.",[28,422,424],{"id":423},"_2-3-개별-실행-인스턴스가-영원히-살아-있다고-가정하지-않는다","2-3. 개별 실행 인스턴스가 영원히 살아 있다고 가정하지 않는다.",[17,426,427],{},"쿠버네티스에서는 Pod를 영구적으로 유지해야 하는 존재로 생각하지 않는다. 다만 필요하면 삭제하고 새로운 Pod로 만들 뿐이다.",[17,429,430],{},"근데 컨테이너와 Pod 재생성은 다르니까 인지하자.",[33,432,433,443],{},[36,434,435],{},[39,436,437,440],{},[42,438,439],{},"상황",[42,441,442],{},"대표적인 대응",[52,444,445,453],{},[39,446,447,450],{},[57,448,449],{},"Pod 안의 컨테이너가 종료됨",[57,451,452],{},"kubelet이 재시작 정책에 따라 컨테이너를 다시 시작",[39,454,455,458],{},[57,456,457],{},"Deployment가 관리하는 Pod 자체가 삭제됨",[57,459,460],{},"ReplicaSet 컨트롤러가 대체할 새 Pod 생성",[10,462,464],{"id":463},"_3-시스템-아키텍처-누가-무엇을-담당하나","3. 시스템 아키텍처 : 누가 무엇을 담당하나?",[17,466,467],{},"쿠버네티스 구조는 크게 두 부분으로 나눠 보면 쉽다.",[17,469,470],{},"Control Plane은 전체 상태를 관리하고, Worker Node는 애플리케이션을 실행",[125,472,475],{"className":473,"code":474,"language":130,"meta":131},[128],"사용자\n  │\n  │ kubectl로 요청\n  ▼\nControl Plane: 전체 관리\n  ├── API Server\n  ├── etcd\n  ├── Scheduler\n  └── Controller Manager\n          │\n          │ API를 통한 상태 공유와 조정\n          ▼\nWorker Node: 실제 실행\n  ├── kubelet\n  ├── Container Runtime\n  ├── 네트워크 관련 구성 요소\n  └── Pod\n       └── 애플리케이션 컨테이너\n",[133,476,474],{"__ignoreMap":131},[28,478,480],{"id":479},"_3-1-control-plane-전체-관리-담당","3-1. Control Plane : 전체 관리 담당",[33,482,483,496],{},[36,484,485],{},[39,486,487,490,493],{},[42,488,489],{},"구성 요소",[42,491,492],{},"역할",[42,494,495],{},"쉽게 생각하면",[52,497,498,511,524,537],{},[39,499,500,505,508],{},[57,501,502],{},[60,503,504],{},"API Server",[57,506,507],{},"쿠버네티스 관리 API를 제공하는 중심 창구",[57,509,510],{},"요청 접수처",[39,512,513,518,521],{},[57,514,515],{},[60,516,517],{},"etcd",[57,519,520],{},"쿠버네티스 객체와 상태 정보를 저장하는 저장소",[57,522,523],{},"관리 장부",[39,525,526,531,534],{},[57,527,528],{},[60,529,530],{},"Scheduler",[57,532,533],{},"아직 노드가 정해지지 않은 Pod를 적절한 노드에 배정",[57,535,536],{},"배치 담당자",[39,538,539,544,547],{},[57,540,541],{},[60,542,543],{},"Controller Manager",[57,545,546],{},"여러 컨트롤러를 실행하여 원하는 상태와 실제 상태를 조정",[57,548,549],{},"운영 관리자 집합",[28,551,553],{"id":552},"_3-2-worker-node-실제-실행-담당","3-2. Worker Node : 실제 실행 담당",[33,555,556,564],{},[36,557,558],{},[39,559,560,562],{},[42,561,489],{},[42,563,492],{},[52,565,566,576,594],{},[39,567,568,573],{},[57,569,570],{},[60,571,572],{},"kubelet: 큐블릿",[57,574,575],{},"자기 노드에 배정된 Pod가 실행되도록 관리하고 상태를 보고",[39,577,578,583],{},[57,579,580],{},[60,581,582],{},"Container Runtime",[57,584,585,586,589,590,593],{},"이미지를 준비하고 컨테이너를 실제로 실행. ",[133,587,588],{},"containerd",", ",[133,591,592],{},"CRI-O"," 등이 있음",[39,595,596,601],{},[57,597,598],{},[60,599,600],{},"kube-proxy 또는 대체 구현",[57,602,603],{},"Service로 들어오는 통신이 대상 Pod에 전달되도록 네트워크 규칙 등을 구성",[14,605,606],{},[17,607,608],{},"쿠버네티스는 반드시 Docker Engine을 통해 컨테이너를 실행하는 것은 아님. containerd 같은 런타임을 사용할 수 있다.",[17,610,611],{},"다시 한번 정리해 보자면",[17,613,614],{},"Deployment는 “운영 계획을 담은 객체”이고, Deployment Controller는 “그 계획을 읽고 실행 상태를 조정하는 프로그램”",[17,616,617],{},"매니페스트에 Deployment를 작성하는 것은 새로운 관리 프로그램을 코딩하는 일이 아니라, 이미 실행 중인 관리 프로그램에 원하는 상태를 전달하는 일",[10,619,621],{"id":620},"_4-코드로-따라가는-작동-과정","4. 코드로 따라가는 작동 과정",[17,623,624],{},"예시 상황",[14,626,627],{},[17,628,629],{},"Nginx 웹 서버 Pod를 3개 실행하고, 접속한 뒤, Pod를 하나 지워서 다시 생성되는지 확인",[28,631,633],{"id":632},"_4-1-연습용-쿠버네티스-준비","4-1. 연습용 쿠버네티스 준비",[125,635,639],{"className":636,"code":637,"language":638,"meta":131,"style":131},"language-bash shiki shiki-themes github-light github-dark","# 필요한 도구 설치\nbrew install minikube kubectl\n\n# 연습용 클러스터 생성\nminikube start -p k8s-intro --driver=docker --container-runtime=containerd\n\n# 이후 명령을 보낼 클러스터 선택\nkubectl config use-context k8s-intro\n\n# 현재 선택된 클러스터 확인\nkubectl config current-context\n\n# 노드 상태 확인\nkubectl get nodes\n","bash",[133,640,641,647,663,667,672,692,696,701,714,718,723,732,737,743],{"__ignoreMap":131},[303,642,643],{"class":305,"line":306},[303,644,646],{"class":645},"sJ8bj","# 필요한 도구 설치\n",[303,648,649,653,657,660],{"class":305,"line":361},[303,650,652],{"class":651},"sScJk","brew",[303,654,656],{"class":655},"sZZnC"," install",[303,658,659],{"class":655}," minikube",[303,661,662],{"class":655}," kubectl\n",[303,664,665],{"class":305,"line":367},[303,666,377],{"emptyLinePlaceholder":376},[303,668,669],{"class":305,"line":373},[303,670,671],{"class":645},"# 연습용 클러스터 생성\n",[303,673,674,677,680,683,686,689],{"class":305,"line":380},[303,675,676],{"class":651},"minikube",[303,678,679],{"class":655}," start",[303,681,682],{"class":317}," -p",[303,684,685],{"class":655}," k8s-intro",[303,687,688],{"class":317}," --driver=docker",[303,690,691],{"class":317}," --container-runtime=containerd\n",[303,693,694],{"class":305,"line":386},[303,695,377],{"emptyLinePlaceholder":376},[303,697,698],{"class":305,"line":392},[303,699,700],{"class":645},"# 이후 명령을 보낼 클러스터 선택\n",[303,702,703,705,708,711],{"class":305,"line":397},[303,704,223],{"class":651},[303,706,707],{"class":655}," config",[303,709,710],{"class":655}," use-context",[303,712,713],{"class":655}," k8s-intro\n",[303,715,716],{"class":305,"line":403},[303,717,377],{"emptyLinePlaceholder":376},[303,719,720],{"class":305,"line":409},[303,721,722],{"class":645},"# 현재 선택된 클러스터 확인\n",[303,724,725,727,729],{"class":305,"line":414},[303,726,223],{"class":651},[303,728,707],{"class":655},[303,730,731],{"class":655}," current-context\n",[303,733,735],{"class":305,"line":734},12,[303,736,377],{"emptyLinePlaceholder":376},[303,738,740],{"class":305,"line":739},13,[303,741,742],{"class":645},"# 노드 상태 확인\n",[303,744,746,748,751],{"class":305,"line":745},14,[303,747,223],{"class":651},[303,749,750],{"class":655}," get",[303,752,753],{"class":655}," nodes\n",[14,755,756],{},[17,757,758],{},"Context는 kubectl이 어느 클러스터에 접속할지 정하는 연결 설정",[28,760,762],{"id":761},"_4-2-원하는-상태를-yaml로-작성","4-2. 원하는 상태를 YAML로 작성",[141,764,766],{"id":765},"_1-웹-서버-pod의-운영-설정","1. 웹 서버 Pod의 운영 설정",[125,768,770],{"className":297,"code":769,"language":299,"meta":131,"style":131},"apiVersion: apps\u002Fv1\nkind: Deployment\n\nmetadata:\n  name: web\n\nspec:\n  replicas: 3                  # 원하는 Pod 개수\n\n  selector:\n    matchLabels:\n      app: web                 # 관리할 Pod를 찾는 조건\n\n  template:                    # 앞으로 만들 Pod의 설계도\n    metadata:\n      labels:\n        app: web               # Pod에 붙일 명찰\n\n    spec:\n      containers:\n        - name: nginx\n          image: nginx:stable-alpine\n\n          ports:\n            - containerPort: 80\n\n          readinessProbe:      # 요청을 받을 준비가 됐는지 검사\n            httpGet:\n              path: \u002F\n              port: 80\n",[133,771,772,782,792,796,804,814,818,825,838,842,849,856,869,873,884,892,900,913,918,926,934,948,959,964,972,986,991,1003,1011,1022],{"__ignoreMap":131},[303,773,774,777,779],{"class":305,"line":306},[303,775,776],{"class":309},"apiVersion",[303,778,314],{"class":313},[303,780,781],{"class":655},"apps\u002Fv1\n",[303,783,784,787,789],{"class":305,"line":361},[303,785,786],{"class":309},"kind",[303,788,314],{"class":313},[303,790,791],{"class":655},"Deployment\n",[303,793,794],{"class":305,"line":367},[303,795,377],{"emptyLinePlaceholder":376},[303,797,798,801],{"class":305,"line":373},[303,799,800],{"class":309},"metadata",[303,802,803],{"class":313},":\n",[303,805,806,809,811],{"class":305,"line":380},[303,807,808],{"class":309},"  name",[303,810,314],{"class":313},[303,812,813],{"class":655},"web\n",[303,815,816],{"class":305,"line":386},[303,817,377],{"emptyLinePlaceholder":376},[303,819,820,823],{"class":305,"line":392},[303,821,822],{"class":309},"spec",[303,824,803],{"class":313},[303,826,827,830,832,835],{"class":305,"line":397},[303,828,829],{"class":309},"  replicas",[303,831,314],{"class":313},[303,833,834],{"class":317},"3",[303,836,837],{"class":645},"                  # 원하는 Pod 개수\n",[303,839,840],{"class":305,"line":403},[303,841,377],{"emptyLinePlaceholder":376},[303,843,844,847],{"class":305,"line":409},[303,845,846],{"class":309},"  selector",[303,848,803],{"class":313},[303,850,851,854],{"class":305,"line":414},[303,852,853],{"class":309},"    matchLabels",[303,855,803],{"class":313},[303,857,858,861,863,866],{"class":305,"line":734},[303,859,860],{"class":309},"      app",[303,862,314],{"class":313},[303,864,865],{"class":655},"web",[303,867,868],{"class":645},"                 # 관리할 Pod를 찾는 조건\n",[303,870,871],{"class":305,"line":739},[303,872,377],{"emptyLinePlaceholder":376},[303,874,875,878,881],{"class":305,"line":745},[303,876,877],{"class":309},"  template",[303,879,880],{"class":313},":                    ",[303,882,883],{"class":645},"# 앞으로 만들 Pod의 설계도\n",[303,885,887,890],{"class":305,"line":886},15,[303,888,889],{"class":309},"    metadata",[303,891,803],{"class":313},[303,893,895,898],{"class":305,"line":894},16,[303,896,897],{"class":309},"      labels",[303,899,803],{"class":313},[303,901,903,906,908,910],{"class":305,"line":902},17,[303,904,905],{"class":309},"        app",[303,907,314],{"class":313},[303,909,865],{"class":655},[303,911,912],{"class":645},"               # Pod에 붙일 명찰\n",[303,914,916],{"class":305,"line":915},18,[303,917,377],{"emptyLinePlaceholder":376},[303,919,921,924],{"class":305,"line":920},19,[303,922,923],{"class":309},"    spec",[303,925,803],{"class":313},[303,927,929,932],{"class":305,"line":928},20,[303,930,931],{"class":309},"      containers",[303,933,803],{"class":313},[303,935,937,940,943,945],{"class":305,"line":936},21,[303,938,939],{"class":313},"        - ",[303,941,942],{"class":309},"name",[303,944,314],{"class":313},[303,946,947],{"class":655},"nginx\n",[303,949,951,954,956],{"class":305,"line":950},22,[303,952,953],{"class":309},"          image",[303,955,314],{"class":313},[303,957,958],{"class":655},"nginx:stable-alpine\n",[303,960,962],{"class":305,"line":961},23,[303,963,377],{"emptyLinePlaceholder":376},[303,965,967,970],{"class":305,"line":966},24,[303,968,969],{"class":309},"          ports",[303,971,803],{"class":313},[303,973,975,978,981,983],{"class":305,"line":974},25,[303,976,977],{"class":313},"            - ",[303,979,980],{"class":309},"containerPort",[303,982,314],{"class":313},[303,984,985],{"class":317},"80\n",[303,987,989],{"class":305,"line":988},26,[303,990,377],{"emptyLinePlaceholder":376},[303,992,994,997,1000],{"class":305,"line":993},27,[303,995,996],{"class":309},"          readinessProbe",[303,998,999],{"class":313},":      ",[303,1001,1002],{"class":645},"# 요청을 받을 준비가 됐는지 검사\n",[303,1004,1006,1009],{"class":305,"line":1005},28,[303,1007,1008],{"class":309},"            httpGet",[303,1010,803],{"class":313},[303,1012,1014,1017,1019],{"class":305,"line":1013},29,[303,1015,1016],{"class":309},"              path",[303,1018,314],{"class":313},[303,1020,1021],{"class":655},"\u002F\n",[303,1023,1025,1028,1030],{"class":305,"line":1024},30,[303,1026,1027],{"class":309},"              port",[303,1029,314],{"class":313},[303,1031,985],{"class":317},[141,1033,1035],{"id":1034},"_2-웹-서버-pod들에-접근할-접속-지점","2. 웹 서버 Pod들에 접근할 접속 지점",[125,1037,1039],{"className":297,"code":1038,"language":299,"meta":131,"style":131},"---\napiVersion: v1\nkind: Service\n\nmetadata:\n  name: web\n\nspec:\n  type: ClusterIP              # 클러스터 내부용 접속 지점\n\n  selector:\n    app: web                   # 이 명찰이 있는 Pod에 연결\n\n  ports:\n    - port: 80                 # Service가 제공하는 포트\n      targetPort: 80           # 대상 Pod의 애플리케이션 포트\n",[133,1040,1041,1046,1055,1064,1068,1074,1082,1086,1092,1105,1109,1115,1127,1131,1138,1154],{"__ignoreMap":131},[303,1042,1043],{"class":305,"line":306},[303,1044,1045],{"class":651},"---\n",[303,1047,1048,1050,1052],{"class":305,"line":361},[303,1049,776],{"class":309},[303,1051,314],{"class":313},[303,1053,1054],{"class":655},"v1\n",[303,1056,1057,1059,1061],{"class":305,"line":367},[303,1058,786],{"class":309},[303,1060,314],{"class":313},[303,1062,1063],{"class":655},"Service\n",[303,1065,1066],{"class":305,"line":373},[303,1067,377],{"emptyLinePlaceholder":376},[303,1069,1070,1072],{"class":305,"line":380},[303,1071,800],{"class":309},[303,1073,803],{"class":313},[303,1075,1076,1078,1080],{"class":305,"line":386},[303,1077,808],{"class":309},[303,1079,314],{"class":313},[303,1081,813],{"class":655},[303,1083,1084],{"class":305,"line":392},[303,1085,377],{"emptyLinePlaceholder":376},[303,1087,1088,1090],{"class":305,"line":397},[303,1089,822],{"class":309},[303,1091,803],{"class":313},[303,1093,1094,1097,1099,1102],{"class":305,"line":403},[303,1095,1096],{"class":309},"  type",[303,1098,314],{"class":313},[303,1100,1101],{"class":655},"ClusterIP",[303,1103,1104],{"class":645},"              # 클러스터 내부용 접속 지점\n",[303,1106,1107],{"class":305,"line":409},[303,1108,377],{"emptyLinePlaceholder":376},[303,1110,1111,1113],{"class":305,"line":414},[303,1112,846],{"class":309},[303,1114,803],{"class":313},[303,1116,1117,1120,1122,1124],{"class":305,"line":734},[303,1118,1119],{"class":309},"    app",[303,1121,314],{"class":313},[303,1123,865],{"class":655},[303,1125,1126],{"class":645},"                   # 이 명찰이 있는 Pod에 연결\n",[303,1128,1129],{"class":305,"line":739},[303,1130,377],{"emptyLinePlaceholder":376},[303,1132,1133,1136],{"class":305,"line":745},[303,1134,1135],{"class":309},"  ports",[303,1137,803],{"class":313},[303,1139,1140,1143,1146,1148,1151],{"class":305,"line":886},[303,1141,1142],{"class":313},"    - ",[303,1144,1145],{"class":309},"port",[303,1147,314],{"class":313},[303,1149,1150],{"class":317},"80",[303,1152,1153],{"class":645},"                 # Service가 제공하는 포트\n",[303,1155,1156,1159,1161,1163],{"class":305,"line":894},[303,1157,1158],{"class":309},"      targetPort",[303,1160,314],{"class":313},[303,1162,1150],{"class":317},[303,1164,1165],{"class":645},"           # 대상 Pod의 애플리케이션 포트\n",[141,1167,1169],{"id":1168},"가장-중요한-부분-해석","가장 중요한 부분 해석",[17,1171,1172],{},[133,1173,1174],{},"replicas: 3",[17,1176,1177],{},"이 설계도를 사용하는 Pod의 개수를 3개로 설정",[17,1179,1180],{},[133,1181,1182],{},"template",[17,1184,1185],{},"새 Pod를 사용할 때 사용할 설계도, 어떤 이미지와 설정으로 실행할지 들어 있음",[17,1187,1188],{},"Label과 Selector",[17,1190,1191],{},"둘을 연결해서 읽어야 함.",[125,1193,1196],{"className":1194,"code":1195,"language":130,"meta":131},[128],"Pod에 붙인 명찰:          app=web\nDeployment의 선택 조건:  app=web\nService의 선택 조건:     app=web\n",[133,1197,1195],{"__ignoreMap":131},[17,1199,1200],{},"즉, 이름이 같아서 자동으로 연결되는 것이 아니라, 명찰과 선택 조건이 맞기 때문에 연결되는 것.",[17,1202,1203],{},[133,1204,1205],{},"readinessProbe",[17,1207,1208],{},"“이 컨테이너가 요청을 받을 준비가 됐는가?”를 검사",[28,1210,1212],{"id":1211},"_4-3-쿠버네티스에-적용","4-3. 쿠버네티스에 적용",[17,1214,1215,1218],{},[133,1216,1217],{},"web.yaml","이 있는 폴더에서 실행",[141,1220,1222],{"id":1221},"파일에-정의한-원하는-상태-적용","파일에 정의한 원하는 상태 적용",[125,1224,1226],{"className":636,"code":1225,"language":638,"meta":131,"style":131},"kubectl apply -f web.yaml\n",[133,1227,1228],{"__ignoreMap":131},[303,1229,1230,1232,1235,1238],{"class":305,"line":306},[303,1231,223],{"class":651},[303,1233,1234],{"class":655}," apply",[303,1236,1237],{"class":317}," -f",[303,1239,1240],{"class":655}," web.yaml\n",[141,1242,1244],{"id":1243},"배포가-준비되는지-확인","배포가 준비되는지 확인",[125,1246,1248],{"className":636,"code":1247,"language":638,"meta":131,"style":131},"kubectl rollout status deployment\u002Fweb --timeout=180s\n",[133,1249,1250],{"__ignoreMap":131},[303,1251,1252,1254,1257,1260,1263],{"class":305,"line":306},[303,1253,223],{"class":651},[303,1255,1256],{"class":655}," rollout",[303,1258,1259],{"class":655}," status",[303,1261,1262],{"class":655}," deployment\u002Fweb",[303,1264,1265],{"class":317}," --timeout=180s\n",[141,1267,1269],{"id":1268},"생성된-pod-확인","생성된 Pod 확인",[125,1271,1273],{"className":636,"code":1272,"language":638,"meta":131,"style":131},"kubectl get pods\n",[133,1274,1275],{"__ignoreMap":131},[303,1276,1277,1279,1281],{"class":305,"line":306},[303,1278,223],{"class":651},[303,1280,750],{"class":655},[303,1282,1283],{"class":655}," pods\n",[17,1285,1286],{},"정상 실행되었을 때 출력 예시는 다음과 같다.",[125,1288,1291],{"className":1289,"code":1290,"language":130,"meta":131},[128],"NAME                  READY   STATUS    RESTARTS   AGE\nweb-xxxxxx-aaaaa       1\u002F1     Running   0          30s\nweb-xxxxxx-bbbbb       1\u002F1     Running   0          30s\nweb-xxxxxx-ccccc       1\u002F1     Running   0          30s\n",[133,1292,1290],{"__ignoreMap":131},[17,1294,1295,1298,1299,1302],{},[133,1296,1297],{},"apply","는 객체 설정을 적용하는 명령. ",[133,1300,1301],{},"rollout status","는 배포 진행 상태를 확인하는 명령.\n설정이 접수되는 것과 모든 Pod의 실행 준비가 끝나는 것은 같은 순간이 아니므로 구분해서 확인",[141,1304,1306],{"id":1305},"apply-이후-내부에서는-무슨-일이-일어날까","apply 이후 내부에서는 무슨 일이 일어날까?",[125,1308,1311],{"className":1309,"code":1310,"language":130,"meta":131},[128],"kubectl이 YAML 내용을 API Server에 전달\n    ↓\nAPI Server가 검증한 객체 정보를 저장\n    ↓\nDeployment Controller가 ReplicaSet을 생성하도록 요청\n    ↓\nReplicaSet Controller가 Pod 3개를 생성하도록 요청\n    ↓\nScheduler가 각 Pod를 실행할 노드 결정\n    ↓\n해당 노드의 kubelet이 런타임을 통해 컨테이너 실행\n    ↓\n실행 상태와 준비 상태가 보고됨\n",[133,1312,1310],{"__ignoreMap":131},[14,1314,1315],{},[17,1316,1317],{},"각 구성 요소가 API를 통해 상태를 확인하고, 자기 역할에 해당하는 작업을 수행한 결과가 이어지는 구조",[28,1319,1321],{"id":1320},"_4-4-웹-서버에-접속","4-4. 웹 서버에 접속",[17,1323,1324],{},"이번 Service는 ClusterIP이므로 기본적으로 클러스터 내부에서 사용하는 접속 지점임. 따라서 내 브라우저에서 확인하기 위해서는 개발용 포트 포워딩을 임시로 사용한다.",[125,1326,1328],{"className":636,"code":1327,"language":638,"meta":131,"style":131},"kubectl port-forward service\u002Fweb 8080:80\n",[133,1329,1330],{"__ignoreMap":131},[303,1331,1332,1334,1337,1340],{"class":305,"line":306},[303,1333,223],{"class":651},[303,1335,1336],{"class":655}," port-forward",[303,1338,1339],{"class":655}," service\u002Fweb",[303,1341,1342],{"class":655}," 8080:80\n",[17,1344,1345],{},"터미널을 실행 상태로 두고, 브라우저에서 다음 주소에 접속",[17,1347,1348],{},[1349,1350,1351],"a",{"href":1351,"rel":1352},"http:\u002F\u002Flocalhost:8080",[1353],"nofollow",[14,1355,1356],{},[17,1357,1358],{},"“내 컴퓨터의 8080번 포트를 Service가 선택하는 Pod의 대상 포트에 연결”",[125,1360,1363],{"className":1361,"code":1362,"language":130,"meta":131},[128],"요청을 보내는 애플리케이션\n    ↓\nService의 이름 또는 IP로 접속\n    ↓\nService 전달 규칙\n    ↓\n대상 Pod 중 하나\n    ↓\n그 Pod 안의 웹 서버\n",[133,1364,1362],{"__ignoreMap":131},[17,1366,1367],{},"Deployment는 배포를 관리하고, Service는 접속 지점을 제공해\n일반적인 웹 요청이 Deployment나 Scheduler를 거쳐 처리되는 것은 아니다.",[28,1369,1371],{"id":1370},"_4-5-pod를-하나-삭제해서-자동-복구-확인","4-5. Pod를 하나 삭제해서 자동 복구 확인",[17,1373,1374],{},"Pod 하나를 강제로 삭제해 보자!",[125,1376,1378],{"className":636,"code":1377,"language":638,"meta":131,"style":131},"# app=web인 Pod 중 하나의 이름을 변수에 저장\nPOD=$(kubectl get pods -l app=web -o jsonpath='{.items[0].metadata.name}')\n\n# 선택한 Pod 삭제\nkubectl delete pod \"$POD\"\n\n# Pod 상태를 계속 관찰\nkubectl get pods -l app=web -w\n",[133,1379,1380,1385,1419,1423,1428,1447,1451,1456],{"__ignoreMap":131},[303,1381,1382],{"class":305,"line":306},[303,1383,1384],{"class":645},"# app=web인 Pod 중 하나의 이름을 변수에 저장\n",[303,1386,1387,1390,1394,1397,1399,1401,1404,1407,1410,1413,1416],{"class":305,"line":361},[303,1388,1389],{"class":313},"POD",[303,1391,1393],{"class":1392},"szBVR","=",[303,1395,1396],{"class":313},"$(",[303,1398,223],{"class":651},[303,1400,750],{"class":655},[303,1402,1403],{"class":655}," pods",[303,1405,1406],{"class":317}," -l",[303,1408,1409],{"class":655}," app=web",[303,1411,1412],{"class":317}," -o",[303,1414,1415],{"class":655}," jsonpath='{.items[0].metadata.name}'",[303,1417,1418],{"class":313},")\n",[303,1420,1421],{"class":305,"line":367},[303,1422,377],{"emptyLinePlaceholder":376},[303,1424,1425],{"class":305,"line":373},[303,1426,1427],{"class":645},"# 선택한 Pod 삭제\n",[303,1429,1430,1432,1435,1438,1441,1444],{"class":305,"line":380},[303,1431,223],{"class":651},[303,1433,1434],{"class":655}," delete",[303,1436,1437],{"class":655}," pod",[303,1439,1440],{"class":655}," \"",[303,1442,1443],{"class":313},"$POD",[303,1445,1446],{"class":655},"\"\n",[303,1448,1449],{"class":305,"line":386},[303,1450,377],{"emptyLinePlaceholder":376},[303,1452,1453],{"class":305,"line":392},[303,1454,1455],{"class":645},"# Pod 상태를 계속 관찰\n",[303,1457,1458,1460,1462,1464,1466,1468],{"class":305,"line":397},[303,1459,223],{"class":651},[303,1461,750],{"class":655},[303,1463,1403],{"class":655},[303,1465,1406],{"class":317},[303,1467,1409],{"class":655},[303,1469,1470],{"class":317}," -w\n",[17,1472,1473,1476,1477,1480],{},[133,1474,1475],{},"-l app=web","은 해당 명찰이 붙은 Pod만 선택하고, ",[133,1478,1479],{},"-w","는 변경되는 상태를 계속 보여 달라는 의미",[17,1482,1483],{},"삭제하고 나면, 잠시 후 다른 이름의 새 Pod가 나타나고, 다시 3개가 준비되는 것을 확인할 수 있다.",[17,1485,1486],{},"개수가 계속 유지되는 것은 ReplicaSet이 우리가 선언한 개수를 유지하도록 동작하기 때문이다.",[125,1488,1491],{"className":1489,"code":1490,"language":130,"meta":131},[128],"내가 한 행동:\nPod 하나 삭제\n\n남아 있는 운영 설정:\nPod 3개 유지\n\n쿠버네티스의 대응:\n부족한 자리를 채울 새 Pod 생성\n",[133,1492,1490],{"__ignoreMap":131},[17,1494,1495],{},"삭제된 Pod가 부활한 것이 아니라, 대체할 새 Pod가 만들어진 것",[28,1497,1499],{"id":1498},"_4-6-pod를-3개에서-5개로-늘리기","4-6. Pod를 3개에서 5개로 늘리기",[125,1501,1503],{"className":636,"code":1502,"language":638,"meta":131,"style":131},"# 원하는 개수를 5개로 변경\nkubectl scale deployment\u002Fweb --replicas=5\n\n# 변경 결과 확인\nkubectl rollout status deployment\u002Fweb --timeout=180s\nkubectl get pods -l app=web\n",[133,1504,1505,1510,1522,1526,1531,1543],{"__ignoreMap":131},[303,1506,1507],{"class":305,"line":306},[303,1508,1509],{"class":645},"# 원하는 개수를 5개로 변경\n",[303,1511,1512,1514,1517,1519],{"class":305,"line":361},[303,1513,223],{"class":651},[303,1515,1516],{"class":655}," scale",[303,1518,1262],{"class":655},[303,1520,1521],{"class":317}," --replicas=5\n",[303,1523,1524],{"class":305,"line":367},[303,1525,377],{"emptyLinePlaceholder":376},[303,1527,1528],{"class":305,"line":373},[303,1529,1530],{"class":645},"# 변경 결과 확인\n",[303,1532,1533,1535,1537,1539,1541],{"class":305,"line":380},[303,1534,223],{"class":651},[303,1536,1256],{"class":655},[303,1538,1259],{"class":655},[303,1540,1262],{"class":655},[303,1542,1265],{"class":317},[303,1544,1545,1547,1549,1551,1553],{"class":305,"line":386},[303,1546,223],{"class":651},[303,1548,750],{"class":655},[303,1550,1403],{"class":655},[303,1552,1406],{"class":317},[303,1554,1555],{"class":655}," app=web\n",[17,1557,1558],{},"이 명령은 Deployment의 원하는 개수를 변경하고, 관련 컨트롤러들이 실제 개수를 맞춘다.",[28,1560,1562],{"id":1561},"_4-7-pod를-순차적으로-교체하기","4-7. Pod를 순차적으로 교체하기",[141,1564,1566],{"id":1565},"rolling-update","Rolling Update",[17,1568,1569],{},"Deployment는 Pod를 한꺼번에 모두 없애는 대신, 설정된 전략에 따라 새 Pod로 교체할 수 있어. 이를 Rolling Update: 롤링 업데이트라 한다.",[125,1571,1573],{"className":636,"code":1572,"language":638,"meta":131,"style":131},"# Pod들을 새 Pod로 교체하는 재시작 요청\nkubectl rollout restart deployment\u002Fweb\n\n# 교체 진행 상태 확인\nkubectl rollout status deployment\u002Fweb --timeout=180s\n",[133,1574,1575,1580,1592,1596,1601],{"__ignoreMap":131},[303,1576,1577],{"class":305,"line":306},[303,1578,1579],{"class":645},"# Pod들을 새 Pod로 교체하는 재시작 요청\n",[303,1581,1582,1584,1586,1589],{"class":305,"line":361},[303,1583,223],{"class":651},[303,1585,1256],{"class":655},[303,1587,1588],{"class":655}," restart",[303,1590,1591],{"class":655}," deployment\u002Fweb\n",[303,1593,1594],{"class":305,"line":367},[303,1595,377],{"emptyLinePlaceholder":376},[303,1597,1598],{"class":305,"line":373},[303,1599,1600],{"class":645},"# 교체 진행 상태 확인\n",[303,1602,1603,1605,1607,1609,1611],{"class":305,"line":380},[303,1604,223],{"class":651},[303,1606,1256],{"class":655},[303,1608,1259],{"class":655},[303,1610,1262],{"class":655},[303,1612,1265],{"class":317},[17,1614,1615,1616,1619],{},"새 이미지 버전을 배포할 때는 매니페스트의 ",[133,1617,1618],{},"image"," 값을 변경하고 적용하는 방식으로 진행할 수 있어. 다만 롤링 업데이트를 사용한다는 사실만으로 모든 요청의 무중단 처리가 보장되는 것은 아니고, 준비 상태 검사와 애플리케이션의 종료 처리도 중요",[10,1621,1623],{"id":1622},"_5-마지막으로-구분해야-할-것","5. 마지막으로 구분해야 할 것",[17,1625,1626],{},"자동 복구는 애플리케이션의 버그를 고치는 기능이 아니다. 재시작해도 같은 버그가 발생하면 계속 실패할 수 있다. 단지 쿠버네티스가 할 수 있는 것은 설정된 정책에 따라 실행 상태를 조정하는 일",[17,1628,1629],{},"한 줄 요약",[14,1631,1632],{},[17,1633,1634],{},"Deployment에 원하는 실행 상태를 적으면, 컨트롤러는 필요한 Pod를 만들도록 조정하고, Scheduler는 실행할 노드를 정하며, kubelet과 런타임은 컨테이너를 실행한다. Service는 그렇게 실행되는 Pod에 접근할 접속 지점을 제공한다.",[1636,1637,1638],"style",{},"html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}",{"title":131,"searchDepth":361,"depth":361,"links":1640},[1641,1644,1645,1646,1647,1648,1649,1650,1651,1656,1662,1663,1664,1665],{"id":30,"depth":361,"text":31,"children":1642},[1643],{"id":143,"depth":367,"text":144},{"id":153,"depth":361,"text":154},{"id":260,"depth":361,"text":261},{"id":330,"depth":361,"text":331},{"id":423,"depth":361,"text":424},{"id":479,"depth":361,"text":480},{"id":552,"depth":361,"text":553},{"id":632,"depth":361,"text":633},{"id":761,"depth":361,"text":762,"children":1652},[1653,1654,1655],{"id":765,"depth":367,"text":766},{"id":1034,"depth":367,"text":1035},{"id":1168,"depth":367,"text":1169},{"id":1211,"depth":361,"text":1212,"children":1657},[1658,1659,1660,1661],{"id":1221,"depth":367,"text":1222},{"id":1243,"depth":367,"text":1244},{"id":1268,"depth":367,"text":1269},{"id":1305,"depth":367,"text":1306},{"id":1320,"depth":361,"text":1321},{"id":1370,"depth":361,"text":1371},{"id":1498,"depth":361,"text":1499},{"id":1561,"depth":361,"text":1562,"children":1666},[1667],{"id":1565,"depth":367,"text":1566},[1669,1670],"Backend","Kubernetes","2026-09-06 09:00:00 +0900","쿠버네티스의 핵심 용어와 아키텍처를 살펴보고, Nginx 배포 실습으로 원하는 상태를 유지하는 작동 과정을 정리한다.","md",null,"\u002Fbackend\u002Fkubernetes\u002F2026\u002F09\u002F06\u002Fkubernetes-introduction\u002F",{"layout":1677},"post","\u002Fposts\u002Fbackend\u002Fkubernetes\u002F2026-09-06-kubernetes-introduction",{"title":5,"description":1672},"posts\u002FBackend\u002FKubernetes\u002F2026-09-06-kubernetes-introduction",[1670,88,173,183,193,223,676],"aDzWp7RALAcIywj6rgwSQvSRGR6hl-SbZCdLd_-iGdw",1788744785328]