[DevOps]

ehekaanldk·2025년 6월 18일

[DevOps]

목록 보기
3/4

label

label 은 쿠버네티스 리소스에 붙이는 key-value형태의 태그

kubernetes의 객체라면 모두 label을 붙일 수 있다.

  • Pod
  • Service
  • Deployment
  • ReplicaSet
  • Node

label을 붙이는 목적

  • 요구사항에 맞춰 객체의 하위 집합을 구성하고 선택하기 위해 사용한다.
  • env=dev 라벨이 붙은 pod만 모아서 보기, 관리하기 등

label selector

label이 붙은 객체들을 조건에 맞춰서 필터링하는 방법

label selector는 객체들의 집합을 선택한다.

  • 라벨이 app=nginx인 것만 골라줘!"
    → 이걸 Label Selector라고 한다.

selector의 결과는 주로 Pod의 묶음 단위가 된다.

  • Service가 label selector를 통해서 app=web인 pod를 골랐다면,
  • 이 서비스는 그 pod들에만 트래픽을 전달한다.

Replication Controller(RC)

지정한 Pod의 개수를 유지하고,
Pod가 죽으면 새로 만들어주고,
많으면 줄여주는 역할을 한다.

master node의 controller manager 중의 하나이다.

[추가]controller manager??

쿠버네티스 내부에서 각종 컨트롤러들을 실행하고 관리하는 프로그램

  • ReplicaSet Controller
  • Node Controller
  • Job Controller
  • Endpoint Controller
    이 모든 컨트롤러들이 돌아가는 실행 엔진이 controller manager이다.

기존에 Deployment → ReplicaSet → Pod → Container 라고 이해했는데
ReplicaSet도 동일하게 지정된 Pod의 개수를 유지해주는 것이다.

RC는 단순히 pod의 수를 유지하는 역할
deployment는 replicaset을 감싸서 버전 업데이트, 배포, 롤백 등을 하기 위해서 Deployment + ReplicaSet 구조를 사용한다.

[추가] Deployment

쿠버네티스에서 배포하겠다는 설명서!
Pods와 ReplicaSets 에 대한 선언적 업데이트를 제공한다.

"nginx 컨테이너를 3개 돌리고 싶어요.
pod가 죽으면 다시 만들고, 버전 바꾸고 싶을 땐 자연스럽게 바꿔줘요."
=> yaml 파일로 작성해서 kubectl apply -f xxx.yaml로 배포한다.
=> 쿠버네티스가 해석해서 실제로 배포해주는 대상 => !!

ReplicaSet : Pod의 생명 관리자

ReplicaSet은 지정한 수만큼 Pod를 유지시키러는 controller

"Pod가 3개 있어야 해!" 하면
→ 실제로 그 pod 수를 유지시켜주는 게 ReplicaSet이다.

pod들의 복제본을 관리하는 부분이다.
deployment없이 pod를 실습이나 학습 목적으로 유지할 때 사용한다.
거의 replicaset이 독립적으로 사용되는 경우는 없으며 deployment가 대신한다.

/replicaset.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx-replicaset  # ReplicaSet의 이름
spec:
  replicas: 3              # Pod 몇 개 만들지
  selector:                # 어떤 Pod를 관리할지 라벨 조건
    matchLabels:
      app: nginx
  template:                # ↓ 실제 Pod의 설계도
    metadata:
      labels:
        app: nginx         # ↑ 이 라벨이 selector와 일치해야 함
    spec:
      containers:          # ↓ 이 안이 실제 컨테이너 정의
        - name: nginx
          image: nginx:1.21
          ports:
            - containerPort: 80
  • replicaset.yaml 안에는 replicaset 의 메타정보가 들어있다.
  • 또한 pod 템플릿으로 Pod 안에 들어갈 컨테이너 정의가 적혀있다.

Deployment와 ReplicaSet

/kubernetes/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.21

Deployment를 만들면

  • 쿠버네티스가 Deployment 내용을 바탕으로 ReplicaSet을 생성한다.
  • ReplicaSet이 Pod 3개를 생성한다.
  • Pod 안에서 nginx:1.21 컨테이너가 실행된다.

Deployment rollout
업데이트가 발생해 nginx:1.21 -> nginx:1.22가 되면(pod template이 바뀌면)

  • Deployment가 알아서 새 ReplicaSet을 생성하고,
  • 새 ReplicaSet은 새로운 Pod를 생성하고,
  • 예전 ReplicaSet의 Pod는 점점 삭제됨
    => scaling 작업에서는 replicaset을 새로 생성하지 않는다.
    => rollback 으로 문제 발생시 되돌릴 수 있다.

결론적으로
deployment사용자가 직접 만들고
Pod 개수 유지하는 replicasetDeployment가 자동 생성하고,
실제 컨테이너가 돌아가는 최소 단위인 PodReplicaSet이 생성한다.

Pod에 접속

컨테이너 안에 들어가서 확인하는 방법

kubectl exec -it [pod이름] -- /bin/bash

실행하면
root@[pod이름]:/# 으로 변경되어 리눅스로 명령어 입력이 가능하다.

실습 : label과 annotation 으로 객체 관리

  • pod 인스턴스에 label을 추가한다.
    kubectl edit po [pod이름]

kubectl get pods -l env=test
kubectl get pods --selector env=test

  • replicaset을 확인할 수 있다.
    kubectl get rs
    kubectl describe rs

  • repliacset을 삭제할 수 있다.
    kubectl delete rs

  • deployment를 파일기반으로 배포한다.
    kubectl create -f deployment.yaml
    kubectl apply -f deployment.yaml (해당 배포가 있으면 업데이트, 없으면 새배포)
    kubectl describe deployment deployment.yaml (생성 확인)

  • deployment의 replicaset의 개수확인한다.
    kubectl get pods

  • deployment의 scale 수를 수동 조정한다.
    kubectl scale deployments [deployments 이름] --replicas=3

rolling update
kubectl apply -f deployment.yaml

  • 기존 Deployment에 정의된 컨테이너의 이미지를 새 버전으로 변경 (롤링 업데이트의 트리거 역할)
    kubectl set image [리소스종류]/[이름][컨테이너이름]=[새로운 이미지]

  • 롤링 업데이트의 진행 상태를 보여준다.
    kubectl rollout status deployment/nginx-deployment

rollback

  • 객체를 image 버전도 나오게 자세히 확인
    kubectl get deployments -o wide

  • 객체를 롤백 처리한다.
    kubectl rollout undo deployment/nginx-deployment


Namespaces : 리소스의 논리적 부분

AKS 클러스터를 가상으로 여러개 나누어 이 나누어진 가상의 클러스터를 namespace라고 한다.

하나의 클러스터는 노드로 구성되어 있다.
노드는 pod들이 올라가는 컴퓨터의 모음이다.

물리적으로는 하나이지만,
논리적으로 공간을 나눠둬야 여러팀과 환경이 완전히 분리된 공간처럼 사용할 수 있다.

AKS 클러스터
├── Namespace: dev
│   └── Pod, Service, ConfigMap (개발팀)
├── Namespace: prod
│   └── Pod, Service, ConfigMap (운영팀)
├── Namespace: data-team
│   └── 분석 관련 리소스

kubernetes는 생성 시에 4개의 namespace를 제공한다.

  • default
  • kube-node-lease
  • kube-public
  • kube-system

Service

Service가 필요한 이유

  • Pod 안에 들어 있는 컨테이너가 실제 어플리케이션이다.
    pod는 컨테이너를 실행하기 위한 포장지/껍데기라고 생각한다.

  • 어플리케이션에 접근하기 위해서 사용자가 pod에 직접 접근할 수 없다.

  • pod에 고정 IP로 사용자가 접근을 하게 되면,
    pod가 죽거나 새로 생기면 그때마다 조치를 해줘야 한다.

Service

추상화된 객체인 Service를 통해서
pod들의 논리적인 집단을 만들어서 규칙을 설정하고
사용자는 service를 통해서 접속하도록 한다.

  • selector로 pod들을 논리적인 그룹으로 나누고 service ip를 연결해서,
  • 사용자service ip에 접속하면 selector로 묶인 pod들에 접근한다.
  • service는 각 pod들에 대해서 load balancing(트래픽 균등)을 자동 수행한다.
/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx               # 이 라벨을 가진 Pod에 연결
  ports:
    - protocol: TCP
      port: 80              # 서비스 포트
      targetPort: 80        # 실제 Pod(컨테이너)의 포트
  type: ClusterIP           # 서비스 타입 (내부 접근만 허용)
  • 사용자는 service ip 주소를 통해서 pod에 접속한다.
  • 각 service 에 부여된 IPcluster IP라고 한다.

kube-proxy 데몬

Service는 가상의 객체로 사용자에게
고정 cluster IP를 제공하는 트래픽 라우터 역할을 한다.

Service 자체에서는 트래픽을 처리하지 않고, 실제 트래픽을 전달하는 것이 kube-porxy이다.
Service의 ClusterIP로 들어오는 트래픽을 해당 pod로 전달한다.

kube-proxy의 역할

  • 각 node(서버)에 설치되어 있는 데몬(백그라운드 프로세스)
  • API Server로부터 다음 리소스를 감시(watch):
    - Service 정보
    • Endpoints 정보 (어떤 Pod들이 연결되어 있는지)
  • service가 제거되면 iptable이 사라져서 해당 clusterip로 접근할 수 없다.

Service Discovery

service가 동적으로 생기고 사라질 때 이를 자동으로 찾고 연결해주는 시스템 자체를 의미한다.

Pod나 Service의 IP/주소가 계속 바뀌어도
애플리케이션이 자동으로 상대 서비스의 위치를 찾아낼 수 있게 하는 메커니즘

쿠버네티스에서의 service discovery 방법

1. DNS 기반 Service Discovery (🔄 내부에서 내부로)

AKS 안에서 Pod 간 통신이나 Service 간 통신을 할 때,
Service IP를 기억할 필요없이, Service 이름만으로 자동 연결된다.

[서비스명][네임스페이스명].svc.cluster.loacal
고정된 DNS를 통해서 서비스의 이름 => ClusterIP로 자동 변환해준다.

2. External IP 지정 방식 (🌐 외부에서 내부로)

외부 사용자, 인터넷 사용자가 쿠버네티스 내부 서비스에 접근할 수 있게 하기 위한 방법이다.

회사 내부에 쿠버네티스가 있으면,
쿠버네티스는 외부 IP를 알아서 만들어주지 않기 때문에,
spec.externalIPs 항목을 직접 명시적으로 설정해야 한다.

그렇지 않은 경우는 클라우드환경에서는,
Service 의 타입을 loadbalancer 로 설정한다.
벤터 사에서 퍼플릭IP를 자동으로 생성해서 할당한다.

ServiceType

쿠버네티스 service의 접근 범위

service를 생성할 때,
yaml파일에서 IP주소할당 방식과 서비스 연계에 따라서 4가지로 구분한다.
| 유형 | 설명 | 접근 범위 |
| -------------- | ------------------- | ----------- |
| ClusterIP | 기본값. 내부 IP만 생성 | ❗ 클러스터 내부 |
| NodePort | 외부에서 노드 IP + 포트로 접근 | ✅ 외부 접근 가능 |
| LoadBalancer | 클라우드에서 외부 IP 자동 할당 | ✅ 외부 접근 가능 |
| ExternalName | 클러스터 밖의 DNS 주소로 연결 | ✅ 외부 대상 연결용 |

클러스터 내에서만 접근이 가능 : ClusterIP

  • ClusterIP는 내부에서만 접근이 가능하다.

  • Pod → Service 통신만 할 거면 ClusterIP만으로 충분하다.

  • 외부의 인터넷 브라우저나 사용자에서는 절대 접근이 불가능하다.

클러스터 내와 외부에서 접근이 가능 : NodePort, LoadBalancer

NodePort
[노드 IP]:[포트]

  • NodePort는 각 노드의 IP에 지정된 포트로 접근한다.
  • 일종의 비상용으로 실무에서는 테스트용으로 사용한다.

Service의 일종으로 요청은 외부에서 [노드 IP]:[포트] 으로 들어오지만,
kube-proxy가 트래픽을 받아서 service의 clusterip -> 연결된 pod들로 포워딩한다.

외부 접근용 고정 포트를 열어주는 service이다.

사용자 브라우저
    ↓
[노드의 IP:NodePort 포트]      ← 외부에서 접근
    ↓
[Service: my-service]         ← type: NodePort
    ↓
[Pod A, Pod B, Pod C]         ← app=nginx 라벨 기준으로 선택됨

노드가 여러개 있어도 NodePort는 모든 Node에 동일한 포트를 열어둔다.

Node 이름외부 IP열린 포트 (NodePort)
node-1203.0.113.1030080
node-2203.0.113.1130080
node-3203.0.113.1230080

LoadBalancer

  • LoadBalancer는 퍼블릭 IP가 자동 할당된다.
  • 일반적으로 실무 외부 노출 방식이다.
  • LoadBalancer는 service의 타입이다.

사용자는 이 퍼블릭 IP만 알면 됨
→ 노드가 몇 개인지, 어디에 있는지 몰라도 접근 가능!

  • LoadBalancer는 AKS 내부에 있어서 노드들의 IP, 포트를 알고 있어서 연결이 가능하다.

LoadBalancer 타입은 실제로는 NodePort 위에 클라우드 로드밸런서를 얹은 구조이다.

[브라우저 사용자]
       ↓
[클라우드 Load Balancer (퍼블릭 IP)]  ← type: LoadBalancer
       ↓
[각 Node의 NodePort 포트 (예: 31234)] ← 자동 생성됨
       ↓
[kube-proxy]
       ↓
[ClusterIP Service]
       ↓
[Label로 선택된 Pod들] ← Pod가 어느 Node에 있어도 OK
  • nodeport와 clusterip 타입의 service는 쿠버네티스에 의해 자동생성
  • 사용자가 해당 nodeport를 알기만 하면 강제로 LB을 안거치고 접속이 가능하긴 하다.

클러스터 밖의 리소스에 대한 map을 가짐 : ExternalName

클러스터 외부에 존재하는 서비스 이름을 클러스터 내부 서비스처럼 사용이 가능한 타입이다.

[추가] Service

특정 label을 기준으로 묶인 Pod 그룹의 짝꿍이 service라고 생각한다.

네트워킹과 로드밸런싱

스케일링과 배포 전략

서비스라는 가상의 객체

실제로 동작하는 과정을 알아본다.

워커 노드들은 내부적으로 kube-proxy 라는 데몬을 실행한다.
서비스나 엔드포인트 객체의 추가/삭제를 위해서 마스터 노드의 API 서버를 모니터링한다.

워커 노드의 kube-proxy는

  • 새로운 서비스에 대한 IPtable 규칙,
  • 서비스 ClusterIP의 트래픽을 캡쳐
  • 해당 트래픽을 서비스의 백엔드 pod 중 하나로 라다이랙트한다.

0개의 댓글