kubernetes manifest file

chris·2022년 12월 24일
0

kubernetes

목록 보기
1/1
post-thumbnail

매니페스트 파일(manifest file)은 컴퓨팅에서 집합의 일부 또는 논리정연한 단위인 파일들의 그룹을 위한 메타데이터를 포함하는 파일이다. 예를 들어, 컴퓨터 프로그램의 파일들은 이름, 버전 번호, 라이선스, 프로그램의 구성 파일들을 가질 수 있다.
이 용어는 화물 목록(ship manifest)이 선원 및 화물을 나열하는 화물 수송 절차로부터 가져온 것이다.[link]

Docker에서는 docker run ... 명령어로, docker swarm에서는 docker service create ... 명령어로 container를 생성할 수 있는 것 같이 kubernetes에서도 kubectl 명령어로 대 부분의 작업을 할 수 있다.
하지만 매번 직접 kubectl 명령어로 모든 object를 배포하고 업데이트 한다면 Human error[link]의 발생 확율이 높고 또 여러 환경에 배포시 일관성이 저하 될 수 있다.
그렇기 때문에 kubernetes를 잘 사용하려면 YAML파일을 작 작성하는 것이라고 해도 과언이 아니다.

Kubernetes는 아주 많은 수의 Component가 존재한다. 그중에서 Application을 구동하기 위해 반드시 알아야 할 몇 가지 Object가 있다.

  • Pod
  • Replica Set
  • Service
  • Deployment

Pod

Kubernetes에서는 Container Application의 기본 단위를 Pod라고 한다. Pod는 1개 이상의 Container로 구성된 Container의 집합이다.
다음은 nginx pod이다.

apiVersion: v1
kind: Pod
metadata:
  name: my-nginx
spec:
  containers:
  - name: my-nginx
    image: nginx:latest
    ports:
    - containerPort: 80
      protocol: TCP

Kubernetes의 YAML 파일은 일반적으로 apiVersion, kind, metadata, spec 네 가지 항목으로 구성된다.

  • apiVersion: YAML 파일에서 정의한 object의 API 버전을 나타낸다. kubernetes version별로 지원하는 object 버전이 다를 수 있다.
  • kind: 리소스의 종류를 나타낸다. Kind 항목에서 사용할 수 있는 리소스 object 종류는 kubectl api-resources 명령어의 KIND 항목에서 확인 할 수 있다.
  • metadata: label, annotation, name 등과 같은 리소스의 부가 정보들을 입력한다.
  • spec: 리소스를 생성하기 위한 자세한 정보를 입력한다.

Replica Set

Kubernetes의 기본 단위인 Pod는 여러 개의 Container를 추상화해 하나의 Application으로 동작하도록 만드는 Container 묶음이다. 그러나 YAML에 Pod만 정의해 생성하면 이 Pod의 Lifecyle은 어떻게 될까?
예를 들어 kubectl delete ... 명령어로 Pod를 삭제하면 그 Pod의 Container 또한 삭제된 뒤 Kubernetes에서 영원히 사라지게 된다. 이처럼 YAML 파일에 Pod만 정의하면 해당 Pod는 오직 Kubernetes 사용자에 의해 관리된다.
또 여러개의 동일한 Pod를 생성해야 할 경우는 해당 YAML파일이 다음과 같을 것이다.

apiVersion: v1
kind: Pod
metadata:
  name: my-nginx-a
spec:
  containers:
  - name: my-nginx
    image: nginx:latest
    ports:
    - containerPort: 80
      protocol: TCP
---
apiVersion: v1
kind: Pod
metadata:
  name: my-nginx-b
spec:
  containers:
  - name: my-nginx
    image: nginx:latest
    ports:
    - containerPort: 80
      protocol: TCP

이와 같이 정의할 경우 Pod가 어떠한 이유로 삭제되거나, Pod이 위치한 Node에 장애가 발생해 더 이상 Pod에 접근하지 못하게 될 경우, 관리자가 직접 Pod를 삭제하고 다시 생성하지 않는 한 해당 Pod는 다시 복구되지 않는다.
이러한 한계점을 해결해주는 것이 바로 Replica Set이라는 Kubernetes object이다.
Replica Set의 역할은 다음과 같다.

  • 정해진 수의 동일한 Pod가 항상 실행되도록 관리한다.
  • 노드 장애 등의 이유로 Pod를 사용할 수 없다면 다른 노드에서 Pod를 다시 생성한다.

Replica Set을 사용하여 위 YAML 파일을 다시 정의해보겠다.

  • spec.replicas: 동일한 Pod를 몇 개 유지시킬 것인지 설정한다.
  • spec.template: 어떠한 Pod를 어떻게 생성할 것인지 설정한다.

Label은 Kubernetes Resource의 부가적인 정보를 표현할 수 있을 뿐만 아니라, 서로 다른 Object가 서로를 찾아야 할 때 사용하기도 한다. Replica Set은 spec.selector.matcheLabel에 정의된 Label을 통해 생성해야 하는 Pod를 찾는다.

Deployment

Replica Set만 사용해도 충분히 Microservice 구조의 Container를 구성할 수 있을 것 같지만, 실제 Kubernetes 운영 환경에서 Replica Set을 YAML 파일에서 사용하는 경우는 거의 없다.
대부분은 Replicaset과 Pod의 정보를 정의하는 Deployment라는 이름의 Object를 YAML 파일에 정의해 사용한다.
Deployment는 Replica Set의 상위 Object이기 때문에 Deployment를 생성하면 해당 Deployment에 대응하는 Replica Set도 함께 생성된다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-nginx
  strategy: 
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
  	metadata:
      name: my-nginx-pod
      labels:
        app: my-nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.10
        ports:
        - containerPort: 80


위 이미지에서와 같이 Deployment를 생성함으로써 Replica Set이 생성됐고, Replica Set이 Pod를 생성한다. 따라서 Deployment를 삭제하면 Replica Set과 Pod도 삭제된다.

왜? Deployment를 사용할까?

Application의 업데이트와 배포를 편하게 만들기 위해 사용된다.

  • Application을 업데이트할 때 Replica Set의 변경 사항을 저장하는 Revision을 남겨 롤백을 가능하게 한다.
  • 무중단 서비스를 위해 Pod의 Rolling Update의 전략을 지정할 수 있다.

Service

Kubernetes에서는 Pod에 접근하도록 정의하는 방법이 Docker와 약간 다르다. docker run -p ...명령어와 달리 Kubernetes는 Deployment를 생성할 때 Pod를 외부로 노출하지 않으며, Deployment의 YAML 파일에는 단지 Pod의 Application이 사용할 내부 Port만 정의한다.
Port를 외부로 노출해 사용자들이 접근하거나, 다른 Deployment의 Pod들이 내부적으로 접근하려면 Service라고 부르는 별도의 Kubernetes Object를 생성해야 한다.

서비스의 기능

  • 여러 개의 Pod에 쉽게 접근할 수 있도록 고유한 도메인 이름을 부여한다.
  • 여러 개의 Pod에 접근할 때, 요청을 분산하는 Load Balancer 기능을 수행한다.
  • Cloud Platform의 Load Balancer, Cluster Node의 Pod 등을 통해 Pod를 외부로 노출한다.

서비스의 종류

  • ClusterIP 타입: Kubernetes 내부에서만 Pod들에 접근할 때 사용한다. 외부로 Pod를 노출하지 않기 때문에 Kubernetes Cluster 내부에서만 사용되는 Pod에 적합하다.
  • NodePort 타입: Pod에 접근할 수 있는 Port를 Cluster의 모든 Node에 동일하기 개방한다. 따라서 외부에서 Pod에 접근할 수 있는 서비스 타입이다. 접근할 수 있는 Port는 랜덤으로 정해지지만, 특정 Port로 접근하도록 설정할 수도 있다.
  • LoadBalancer 타입: Cloud Platform에서 제공하는 Load Balancer를 동적으로 Provisioning해 Pod에 연결한다. NodePort 타입과 마찬가지로 외부에서 Pod에 접근할 수 있는 서비스 타입이다.
ClusterIP 타입 서비스
apiVersion: v1
kind: Service
metadata:
  name: hostname-svc-clusterip
spec:
  ports:
  - name: web-port
    port: 8080
    targetport: 80
  selector:
    app: webserver
  type: ClusterIP
  • spec.selector: selector 항목은 이 서비스에서 어떠한 label을 가지는 pod에 접근할 수 있게 만들 것인지 결정한다.
  • spec.ports.port: 생성된 서비스는 kubernetes 내부에서만 사용할 수 있는 고유한 IP(ClusterIP)를 할당받는다. port 항목에는 서비스의 IP에 접근할 때 사용할 Port를 설정한다.
  • spec.ports.targetPort: selector 항목에서 정의한 label에 의해 접근 대상이 된 Pod들이 내부적으로 사용하고 있는 Port를 입력한다.
  • spec.type: 이 서비스가 어떤 타입인지 나타낸다. 서비스 종류에는 ClusterIP, NodePort, LoadBalancer가 있다.

NodePort 타입 서비스

apiVersion: v1
kind: Service
metadata:
  name: hostname-svc-nodeport
spec:
  ports:
  - name: web-port
    port: 8080
    targetport: 80
    nodePort: 31880 # 포트 범위는 30000~31768
  selector:
    app: webserver
  type: NodePort

실제 운영환경에서 NodePort로 서비스를 외부에 제공하는 경우는 많지 않다. NodePort에서 Port 번호를 80 또는 443으로 설정하기에는 적절하지 않으며, SSL 인증서 적용, 라우팅 등과 같은 복잡한 설정을 서비스에 적용하기가 어렵기 때문이다. 따라서 NodePort 서비스 그 자체를 통해 서비스를 외부로 제공하기보다는 Ingress라고 부르는 kubernetes의 Object에서 간접적으로 사용되는 경우가 많다.

Load Balancer 타입 서비스

apiVersion: v1
kind: Service
metadata:
  name: hostname-svc-lb
spec:
  ports:
  - name: web-port
    port: 80
    targetPort: 80
  selector:
    app: webserver
  type: LoadBalancer


1. LoadBalancer 타입의 서비스가 생성됨과 동시에 모든 Node는 Pod에 접근할 수 있는 랜덤한 Port를 개방한다.
2. Cloud Platform에서 생성된 LoadBalancer로 요청이 들어오면 이 요청은 Kubernetes의 Worker Node 중 하나로 전달되며, 이 때 사용되는 Port는 1번에서 개방된 Port이다.
3. Worker Node로 전달된 요청은 Pod 중 하나로 전달되어 처리된다.

ExternalName

apiVersion: v1
kind: Service
metadata:
  name: externalname-svc
spec:
  type: ExternalName
  externalName: my.database.com

Kuternetes를 외부 시스템과 연동해야 할 때 ExternalName 타입의 서비스를 사용할 수 있다.
ExternalName 타입을 사용해 서비스를 생성하면 서비스가 외부 Domain을 가리키도록 설정 할 수 있다.
예를 들어 Kubernetes 내부의 Pod들이 externalname-svc라는 이름으로 요청을 보낼 경우, Kubernetes의 DNS는 my.database.com으로 접근할 수 있도록 CNAME Record를 반환한다.

profile
software engineer

0개의 댓글