본문 바로가기

Cloud/GCP

[Kubernetes] 쿠버네티스의 주요 개념

쿠버네티스 용어 정의

노드

컨테이너가 배치되는 서버

네임스페이스

쿠버네티스 클러스터 안의 가상 클러스터

파드

컨테이너의 집합 중 가장 작은 단위로, 컨테이너의 실행 방법을 정의

레플리카세트

같은 스펙을 갖는 파드를 여러 개 생성하고 관리하는 역할

디플로이먼트

레플리카 세트의 리비전 관리

서비스

파드의 집합에 접근하기 위한 경로 정의

인그레스

서비스를 쿠버네티스 클러스터 외부로 노출

컨피그맵

설정 정보를 정의하고 파드에 전달

퍼시스턴트볼륨

파드가 사용할 스토리지의 크기 및 종류의 정의

퍼시스턴트볼륨클레임

퍼시스턴트 볼륨을 동적으로 확보

스토리지클래스

퍼시스턴트 볼륨이 확보하는 스토리지의 종류를 정의

스테이트풀세트

같은 스펙으로 모두 동일한 파드를 여러 개 생성하고 관리

상주 실행을 목적으로 하지 않는 파드를 여러 개 생성하고 정상적인 종료 보장

크론잡

크론 문법으로 스케줄링 되는 잡

시크릿

인증 정보 같은 기밀 데이터를 정의

네임스페이스 안에서 조작 가능한 쿠버네티스 리소스의 규칙을 정의

롤바인딩

쿠버네티스 리소스 사용자와 롤을 연결

클러스터롤

클러스터 전체적으로 조작 가능한 쿠버네티스 리소스의 규칙을 정의

클러스터롤바인딩

쿠버네티스 리소스 사용자와 클러스터롤을 연결

서비스 계정

파드가 쿠버네티스 리소스를 조작할 때 사용하는 계정

마스터를 구성하는 관리 컴포넌트

* GKE, AKS, EKS는 매니지드 서비스이므로 마스터를 신경 쓸 필요가 없다.

* 논매니지드 환경에서는 마스터 서버가 SPOF가 되지 않도록 마스터를 3대 두는 것이 일반적이다.

컴포넌트 명

역할

kube-apiserver

쿠버네티스 API를 노출하는 컴포넌트 kubectl로부터 리소스를 조작하라는 지시를 받는다.

etcd

고가용성을 갖춘 분산 키-값 스토어. 쿠버네티스 클러스터의 백킹 스토어로 쓰인다.

kube-scheduler

노드를 모니터링하고 컨테이너를 배치할 적절한 노드를 선택한다.

kube-controller-manager

리소스를 제어하는 컨트롤러를 실행한다.

네임스페이스(Namespace)

- 쿠버네티스는 클러스터 안에 가상 클러스를 또 만들 수 있음

- 가상 클러스터를 네임스페이스라고 함

- 네임스페이스는 개발팀이 일정 규모 이상일 때 유용

- 네임스페이스 마다 권한 설정 가능

- 네임스페이스 목록 조회

$ kubectl get namespace

 

파드(Pod) 

- 컨테이너 모임의 집합체, 적어도 하나 이상의 컨테이너로 구성

- 서로 강한 결합을 유지하는 쪽이 나는 경우 파드로 묶어 일괄 배포하는 것이 유리함  (웹서버(WAS), 웹애플리케이션)

- 파드는 노드에 배치한다. 같은 파드를 여러 노드에 배치할 수도 있고 한 노드에 여러개 배치 할 수 있다.

- 파드 하나가 여러 노드에 걸쳐 배포 될 수는 없다.

 

- 파드 생성 및 배포하기

* 파드 생성은 kubectl만 사용해도 가능 하지만, 버전 관리 관점에서도 yaml 파일로 정의 하는 것이 좋다.

* 쿠버네티스의 여러 가지 리소스를 정희하는 파일을 매니페스트 파일이라고 함.

* 매니페스트 파일 소개

 

 
#simple-echo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: simple-echo
spec:
  containers:
  - name: nginx 
    image: gihyodocker/nginx:latest 
    env: 
    - name: BACKEND_HOST
      value: localhost:8080
    ports:
    - containerPort: 80 
  - name: echo
    image: gihyodocker/echo:latest
    ports:
    - containerPort: 8080

 

- kind : 쿠버네티스 리소스의 유형 정의

- metadata : 리소스에 부여 되는 메타데이터

- spec : 리소스를 정의 하기 위한 속성, 파드의 경우 containers 아래에 정의 한다.

- containers

* name : 컨테이너 이름

* image : 도커 허브에 저장된 이미지 태그값

* ports : 컨테이너가 노출시킬 포트를 지정

* env : 환경 변수 열거

 

- 파드 배포 : kubectl -f 옵션으로매니페스트 파일 경로 지정하고 apply 명령 사용

 
$ kubectl apply -f simple-pod.yaml

 

- 파드 목록 및 상태 확인

 
$ kubectl get pod

 

- 컨테이너 내부 접근 : exec -> 컨테이너 안의 프로그램 실행, 파드안의 컨테이너 여러개인 경우 -c 옵션에 컨테이너 명을 지정

 
$ kubectl exec -it simple-echo sh -c nginx

 

- 컨테이너 표준 출력 

 
$ kubectl logs -f simple-echo -c echo

 

- 파드 삭제하기

 
$ kubectl delete pod simple-echo
$ kubectl delete -f simple-pod.yaml

레플리카세트 

- 똑같은 정의를 갖는 파드를 여러 개 생성하고 관리하기 위한 리소스

- 매니페스트 파일로는 파드를 하나밖에 생성 할 수 없음

- 파드의 정의 자체를 포함하고 있어 별도의 설정 파일 필요 없음

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: echo 
  labels:
    app: echo 
spec:
  replicas: 2
  selector:
    matchLabels:
      app: echo 
  template: # template 아래는 파드 리소스 정의와 같음
    metadata:
      labels:
        app: echo
    spec:
      containers:
      - name: nginx 
        image: gihyodocker/nginx:latest 
        env: 
        - name: BACKEND_HOST
          value: localhost:8080
        ports:
        - containerPort: 80 
      - name: echo
        image: gihyodocker/echo:latest
        ports:
        - containerPort: 8080

- replicas : 파드의 복제본 수

- template : 파드의 정의와 동일

- 레프릴카 세트는 파드를 replicas에서 지정한 수만큼 만들어 파드 정의 및 파드복제를 모두 수행

디플로이먼트

- 레플리카세트보다 상위 리소스

- 애프리케이션 배포의 기본 단위

- 레플리카세트를 관리하고 다루기 위한 리소스

- 레플리카세트의 리비전 관리

- 파드 개수만 변경해서는 레플리카세트가 새로 생성 되지 않음

 

 
apiVersion: apps/v1
kind: Deployment 
metadata:
  name: echo 
  labels:
    app: echo 
spec:
  replicas: 2
  selector:
    matchLabels:
      app: echo 
  template: # template 아래는 파드 리소스 정의와 같음
    metadata:
      labels:
        app: echo
    spec:
      containers:
      - name: nginx 
        image: gihyodocker/nginx:latest 
        env: 
        - name: BACKEND_HOST
          value: localhost:8080
        ports:
        - containerPort: 80 
      - name: echo
        image: gihyodocker/echo
        env: 
        - name: HOGE 
          value: fuga 
        ports:
        - containerPort: 8080

 

배포시 명령 실행 기록 남기기 옵션 - 이렇게 해야 리비전 명령어가 제대로 표시 됨

$ kubectl apply -f simple-deployment.yaml --record

 

모든 리소스 목록 조회

$ kubectl get pod,replicaset,deployment --selector app=echo

 

디플로이먼트 리비전 조회

$ kubectl rollout history deployment echo

 

디플로이먼트 특정 리비전 내용 확인

$ kubectl rollout history deployment echo --revision=1

 

디플로이먼트 롤백 실행 - undo를 실행하면 바로 직전 리비전으로 롤백된다.

$ kubectl rollout undo deployment echo

 

서비스

- 파드의 집합(레플리카세트)에 대한 경로나 서비스디스커버리를 제공하는 리소스

- 서비스는 기본적으로 쿠버네티스 클러스터 안에서만 접근 할 수 있음

* 서비스디스커버리 : API 주소가 동적으로 바뀌는 경우에도 클라이언트가 접속 대상을 바꾸지 않고 하나의 이름으로 접근할 수 있는 기능

 

- 서비스 네임 레졸루션

쿠버네티스 클러스터의 DNS는 서비스를 서비스명.[네임스페이스명.svc.local]로 연결 함. [] : 생략가능

 

 
 apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: echo-spring
  labels:
    app: echo 
    release: spring
spec:
  replicas: 1
  selector:
    matchLabels:
      app: echo 
      release: spring
  template:
    metadata:
      labels:
        app: echo
        release: spring
    spec:
      containers:
      - name: nginx 
        image: gihyodocker/nginx:latest 
        env: 
        - name: BACKEND_HOST
          value: localhost:8080
        ports:
        - containerPort: 80 
      - name: echo
        image: gihyodocker/echo:latest
        ports:
        - containerPort: 8080

---
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: echo-summer
  labels:
    app: echo 
    release: summer 
spec:
  replicas: 2
  selector:
    matchLabels:
      app: echo 
      release: summer 
  template:
    metadata:
      labels:
        app: echo
        release: summer 
    spec:
      containers:
      - name: nginx 
        image: gihyodocker/nginx:latest 
        env: 
        - name: BACKEND_HOST
          value: localhost:8080
        ports:
        - containerPort: 80 
      - name: echo
        image: gihyodocker/echo:latest
        ports:
        - containerPort: 8080

 

실행중 파드 조회

$ kubectl get pod -l app=echo -l release=spring

 

서비스 조회

$ kubectl get svc echo

 

쿠버네티스 디버깅용 임시 테스트 컨테이너 배포 실행

$ kubectl -i --rm --tty debug --image=gihyodocker/fundamental:0.1.0 --restart=Never --bash -il

 

로그확인

$ kubectl logs -f echo-summer-asdfsdf[파드이름] -c echo

 

ClusterIP 서비스

- 내부 IP 주소에 서비스를 공개

- 다만 외부로부터 접근 불가

 

NodePort 서비스

- 클러스터 외부에서 접근할 수 있는 서비스

- 각 노드에서 서비스 포트로 접속하기 위한 글로벌 포트 개방 함

- 노드 포트를 생성했다면 80/1234/TCP라고 나오면 노드의 포트 1234를 통해 서비스에 접근 가능 함. 

- 서비스를 L4레벨에서 노출시킬 수 있으므로 TCP/UDP를 다룰 수 있음, HTTP 이외 다양한 APP계층 포트 외부 노출 가능 함.

 
apiVersion: v1
kind: Service
metadata:
  name: echo 
spec:
  type: NodePort
  selector:
    app: echo
    release: summer
  ports:
    - name: http
      port: 80

LoadBalancer 서비스

- 로컬 쿠버네티스 환경에서는 사용 불가

- 주로 클라우드 플랫폼에서 제공하는 로드 밸런서와 연동하기 위해 사용

- GCP LB, AWS ELB 지원

 

ExternalName 서비스

- 쿠버네티스 클러스터에서 외부 호스트를 네임 레졸루션하기 위한 별명 제공

- gihyo.jp를 gihyo로 참조 가능

 
 apiVersion: v1
 kind: service
 metadata:
 	name: gihyo
 spec:
 	type: ExternalName
 	externalName: gihyo.jp

인그레스

- 쿠버네티스 클러스터 외부 서비스 공개하려면 서비스 NodePort로 노출, 그러나 이방법은 L4레벨까지만 지원

- HTTP(S)처럼 경로 기반 서비스 전환하는 L7레벨 제어는 불가능

- 이를 해결 하기 위한 리소스가 인그레스

- 쿠버네티스 클러스터 외부에 대한 노출과 가상 호스트 및 경로 기반의 정교한 HTTP 라우팅을 양립 시킬 수 있음

- 로컬 쿠버네티스에서는 인그레스를 사용해 서비스 노출 불가

- 클러스터 외부에서 온 HTTP 요청을 서비스로 라우팅 하기 위해 nginx_ingress_controller를 배포

- 인그레스는 L7 라우팅이 가능하므로 가상 호스팅 기능처럼 지정된 호스트 혹은 경로와 일치하는 서비스로 요청 전달 가능

- 퍼블릭 클라우드 환경에서는 인그레스는 해당 플랫폼의 L7 로드 밸런서를 이용

 
#simple-service.yaml
#spec.type을 지정하지 않으면 ClusterIP 서비스가 생성됨. 
apiVersion: v1
kind: Service
metadata:
  name: echo 
spec:
  selector:
    app: echo
  ports:
    - name: http
      port: 80
 
#simple-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: echo
spec:
  rules:
  - host: ch05.gihyo.local
    http:
      paths:
      - path: /
        backend:
          serviceName: echo
          servicePort: 80

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.16.2/deploy/mandatory.yaml

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.16.2/deploy/provider/cloud-generic.yaml

$ kubectl apply -f simple-replicaset-with-label.yaml 

$ kubectl apply -f simple-service.yaml 

$ kubectl apply -f simple-ingress.yaml 

$ kubectl get ingress