쿠버네티스

컨테이너화 된 애플리케이션을 자동으로 배포, 스케일링 및 관리해주는 오픈소스 시스템




쿠버네티스는 ‘원하는 상태’를 유지하는 것이 핵심이다.

Desired State

  1. 상태체크(Observe)
    Current State == Desired State

  2. 차이점 발견(Diff)
    Current State != Desired State

  3. 조치(Act)
    Current State => Desired State

Master

etcd

모든 상태와 데이터를 저장
Key(directory)-Value 형태로 데이터 저장

API server

상태를 바꾸거나 조회
etcd와 유일하게 통신하는 모듈
REST API 형태로 제공
권한을 체크하여 적절한 권한이 없을 경우 요청을 차단
관리자 요청 뿐 아니라 다양한 내부 모듈과 통신
요청이 많으므로 수평으로 확장하도록 디자인 되어있음

Scheduler

새로 생성된 Pod를 감지하고 실행할 노드를 선택
노드의 현재 상태와 Pod의 요구사항 체크

Controller

논리적으로 다양한 컨트롤러가 존재
끊임없이 상태를 체크하고 원하는 상태를 유지
복잡성을 낮추기 위해 하나의 프로세스로 실행


Node

kubelet

직접 pod과 통신
각 노드마다 존재
Pod을 실행/중지하고 상태를 체크

proxy

네트워크 프록시와 부하 분산 역할



API 호출하기

원하는 상태(desired state)를 다양한 오브젝트(object)로 정의(spec)하고 API 서버에 yaml 형식으로 전달한다.




yml 필수 요소

apiVersion: v1
kind: Pod
metadata:
  name: echo
  labels:
    app: echo
spec:
  containers:
    - name: app
      image: ghcr.io/subicura/echo:v1


정의 설명
version 오브젝트 버전 v1, app/v1, networking.k8s.io/v1
kind 종류 Pod, ReplicaSet, Deployment, Service
metadata 메타데이터 name과 label, annotation(주석)으로 구성
spec 상세명세 리소스 종류마다 다름



kubectl command

기본 명령어

명령어 설명
create 원하는 상태 적용. 보통 -f 옵션으로 파일과 함께 사용
delete 리소스를 제거
get 리소스 목록
describe 리소스의 상태를 자세하게 보여준다.
logs 컨테이너의 로그
exec 컨테이너에 접근할 때 사용. 컨테이너에 명령어를 전달.
config kubectl 설정을 관리


[root@platform-group-k8s-1 test1]# kubectl create -f nginx-deployment.yml -n hb-test
deployment.apps/nginx created

[root@platform-group-k8s-1 test1]# kubectl delete -f wp-mysql.yml -n hb-test
deployment.apps "wordpress-mysql" deleted
service "wordpress-mysql" deleted
deployment.apps "wordpress" deleted
service "wordpress" deleted

[root@platform-group-k8s-1 test1]# kubectl get svc -n hb-test
NAME          TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
my-nodeport   NodePort   10.1.228.120   <none>        9000:31000/TCP   3d4h

kubectl exec [POD] -- [COMMAND]
[root@platform-group-k8s-1 test1]# kubectl exec -it myapp-pod -n hb-test -- /bin/sh
/workspace/test #

Endpoint : 서비스의 접속정보

$ kubectl describe ep/[서비스이름] 



Object

Pod

Pod은 쿠버네티스에서 관리하는 가장 작은 배포 단위.
쿠버네티스와 도커의 차이점은 도커는 컨테이너를 만들지만, 쿠버네티스는 컨테이너 대신 Pod을 만든다. Pod은 한 개 또는 여러 개의 컨테이너를 포함할 수 있다.

격리된 논리공간 namespace 생성

$ kubectl create namespace hb-test

yaml 파일로 pod 생성

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  namespace: hb-test
  labels:
    app: myapp
spec:
  containers:
    - name: myapp-container
      image: repo.iris.tools/hb/hb-image:v1.0

실행/확인

$ kubectl create -f sample-pod.yml -n hb-test
$ kubectl get pod -n hb-test
NAME        READY   STATUS    RESTARTS   AGE
myapp-pod   1/1     Running   0          26s
$ kubectl exec -it myapp-pod -n hb-test -- /bin/sh
/workspace/test # ls
Dockerfile        go.mod            go.sum            run_my_docker.sh  test1             test1.go




ReplicaSet

Pod를 단독으로 만들면 Pod에 어떤 문제(서버가 죽어서 Pod이 사라졌다던가)가 생겼을 때 자동으로 복구되지 않는다.
이러한 Pod을 정해진 수만큼 복제하고 관리하는 것이 ReplicaSet이다.

ReplicaSet 예시
replicas opbejct에 app=nginx인 pod 3개를 정의하고 생성해준다.

apiVersion: apps/v1
kind: ReplicaSet
metadata: 
  name: nginx
  namespace: hb-test
  labels:
    app: nginx
spec:
  replicas: 3
  selector: 
    matchLabels: 
      app: nginx
  template:
    metadata: 
      labels: 
        app: nginx
        tier: app
    spec:
      containers:  
        - name: nginx
          image: nginx:latest


[root@platform-group-k8s-1 test1]# kubectl get pod --show-labels -n hb-test
NAME                     READY   STATUS    RESTARTS   AGE     LABELS
nginx-57796d7dff-c6z4r   1/1     Running   0          2m     app=nginx,pod-template-hash=57796d7dff
nginx-57796d7dff-kr2rh   1/1     Running   0          2m     app=nginx,pod-template-hash=57796d7dff
nginx-57796d7dff-zjjhf   1/1     Running   0          2m     app=nginx,pod-template-hash=57796d7dff

app- 옵션으로 하나의 pod의 app라벨을 제거해준다.

[root@platform-group-k8s-1 test1]# kubectl label pod/nginx-57796d7dff-c6z4r app- -n hb-test
pod/nginx-57796d7dff-c6z4r labeled

해당 pod에 대해 기존에 생성된 app 라벨이 사라지면서 selector에 정의한 app=nginx조건을 만족하는 pod의 개수가 2가 되어 이를 만족하는 pod이 하나 더 생성되었다.

[root@platform-group-k8s-1 test1]# kubectl get pod --show-labels -n hb-test
NAME                     READY   STATUS    RESTARTS   AGE     LABELS
nginx-57796d7dff-6qfzj   1/1     Running   0          10s     app=nginx,pod-template-hash=57796d7dff
nginx-57796d7dff-c6z4r   1/1     Running   0          3m      pod-template-hash=57796d7dff
nginx-57796d7dff-kr2rh   1/1     Running   0          3m      app=nginx,pod-template-hash=57796d7dff
nginx-57796d7dff-zjjhf   1/1     Running   0          3m      app=nginx,pod-template-hash=57796d7dff



Deployment

Deployment는 쿠버네티스에서 가장 널리 사용되는 오브젝트이다.
ReplicaSet을 이용하여 Pod를 업데이트하고 이력을 관리하여 Rollback하거나 특정버전으로 돌아갈 수 있다.

ReplicaSet에서 사용했던 파일에 kind만 바꿔주고 실행해준다.

apiVersion: apps/v1
kind: Deployment
metadata: 
  name: nginx
  namespace: hb-test
  labels:
    app: nginx
spec:
  replicas: 3
  selector: 
    matchLabels: 
      app: nginx
  template:
    metadata: 
      labels: 
        app: nginx
        tier: app
    spec:
      containers:  
        - name: nginx
          image: nginx:1.14.2


[root@platform-group-k8s-1 test1]# kubectl create -f nginx-deployment.yml -n hb-test
deployment.apps/nginx created
[root@platform-group-k8s-1 test1]# kubectl get po,rs,deploy -n hb-test
NAME                         READY   STATUS    RESTARTS   AGE
pod/nginx-5f6587f7f8-2fchs   1/1     Running   0          14s
pod/nginx-5f6587f7f8-cmwq6   1/1     Running   0          15s
pod/nginx-5f6587f7f8-xnm6d   1/1     Running   0          14s

NAME                               DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-5f6587f7f8   3         3         3       15s

NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx   3/3     3            3           15s

이제 기존 설정에서 이미지 태그만 바꿔주고 다시 적용해준다.

[root@platform-group-k8s-1 test1]# kubectl set image deployment/nginx nginx=nginx:1.16.1 --record  -n hb-test
deployment.apps/nginx image updated

기존 3개의 pod이 terminating 되고 3개가 새로 생긴다.

[root@platform-group-k8s-1 test1]# kubectl get po,rs,deploy -n hb-test
NAME                         READY   STATUS    RESTARTS   AGE
pod/nginx-757bd75865-7fcq8   1/1     Running   0          19s
pod/nginx-757bd75865-8xznf   1/1     Running   0          16s
pod/nginx-757bd75865-gjbl9   1/1     Running   0          39s

NAME                               DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-5f6587f7f8   0         0         0       2m16s
replicaset.apps/nginx-757bd75865   3         3         3       39s

NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx   3/3     3            3           2m16s



Service

Pod는 자체 IP를 가지고 다른 Pod와 통신할 수 있지만, 쉽게 사라지고 생성되는 특징 때문에 직접 통신하는 것을 권장하지 않는다. 대신 별도의 고정된 IP를 가진 Service를 만들고 그 서비스를 통해 Pod에 접근하는 방식을 사용한다.
이때 이 Service는 노출범위에 따라 ClusterIP, NodePort, LoadBalancer로 나뉘어진다.

ClusterIP

ClusterIP는 클러스터 내부에 새로운 서비스의 고유 IP를 할당하고 여러개의 Pod를 바라보는 로드밸런서 기능을 제공한다. 따라서 이 IP는 k8s 클러스터 내에서만 접근이 가능하다. 또한 Pod를 여러개 연결 할 수 있고 트래픽을 분산해서 Pod에 전달해준다.


NodePort

NodePort는 k8s 클러스터에 연결되어 있는 모든 Node에게 똑같은 Port가 할당이 되어서 외부로부터 어느 Node던간에 그 IP의 포트로 접속을 하면 해당 Service에 연결이 되고, 이 Servcie는 자신에 연결되어 있는 Pod에 트래픽을 전달해준다.
(NodePort는 CluterIP의 기능을 기본으로 포함.)


Load Balancer

NodePort는 노드가 사라졌을때 자동으로 다른 노드를 통해 접근이 불가능하다. 자동으로 살아있는 노드에 접근하기 위해서는 모든 노드를 바라보는 Load Balancer가 필요하다.
(LoadBalancer는 NodePort의 기능을 기본으로 포함.)



Service 실습 - Pod을 외부에 노출시키기

NodePort를 이용해서 외부에서 접속할 수 있도록 해보자.

sample-pod.yml

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  namespace: hb-test
  labels:
    app: helloApp
spec:
  containers:
     - name: myapp-container
       image: repo.iris.tools/hb/hb-image:v1.0
       ports:
          - containerPort: 1322
            protocol: TCP

이전에 작성한 pingpong 서버의 포트번호가 1322였으므로 여기서도 pod의 포트번호를 1322로 맞춰준다.

my-nodeport.yml

apiVersion: v1
kind: Service
metadata:
  name: my-nodeport
spec:
  type: NodePort
  ports:
    - port: 9000
      targetPort: 1322
      nodePort: 31000
  selector:
    app: helloApp

targetPort는 nodeport service가 찾아갈 pod의 포트번호 1322로 지정해준다.

실행

$ kubectl create -f sample-pod.yml
$ kubectl create -f my-nodeport.yml

$ kubectl get all -n hb-test
NAME               READY   STATUS    RESTARTS   AGE
pod/myapp-pod   1/1     Running   0          52m

NAME                  TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
service/my-nodeport   NodePort   10.1.158.241   <none>        9000:31000/TCP   48m

노드의 공용 ip를 확인해서(ifconfig)
node의 ip:nodeport 로 GET 요청 날리기

$ curl 192.168.102.114:31000/ping
pong!



헷갈리는 개념 정리해보기

apiVersion: apps/v1
kind: Deployment
metadata: #1
  name: nginx
  labels:
    app: nginx
    tier: backend
spec:
  selector: #2
    matchLabels:
      app: nginx
  template: #3
    metadata:
      labels:
        app: nginx
        tier: backend
...

metadata와 selector와 template에 관하여

먼저, 맨 위의 metadata(#1)는 deployment그 자체에 대한 설명이다. 따라서 이 deployment를 지우고 싶으면 아래 명령어로 지울 수 있다.

kubectl delete -l app=nginx,tier=backend 


selector(#2)는 해당 Pods을 deployment와 연결(link)해 준다.
template(#3)은 podTemplate 이다. 이 부분에서는 실행되는 pod에 대해 기술한다. 따라서 이 부분에 쓰여지는 label은 해당 deployment가 아니라 실행되는 pod에 대한 label이다.
따라서 #2와 #3은 같아야한다.




그림출처

https://www.youtube.com/watch?v=Ia8IfowgU7s
https://dev-youngjun.tistory.com/20