운영자 입장의 kubernetes 주요 특징
뇌피셜이라 정확하지 않을 수 있으나 운영자 입장에서 제가 느낀 Kubernetes 개념과 특징을 정리해 보았습니다.
(운영자 입장) Kubernetes 핵심 개념
- 선언형 (declarative), 가장 핵심
: Application 설치 시 기존 VM처럼 순차적으로 명령어를 실행하는 것이 아니고 원하는 상태를 Code로 선언합니다. 그러면 항상 자동으로 이 상태를 유지합니다. 예를 들어 NGINX 웹서버 설치하고 웹서버를 3개로 유지하라 등을 code로 선언 할 수 있습니다. - 소스 코드 기반
: kubernetes object는 명령어가 아닌 source code로 관리합니다. 흔히 YAML 지옥이라고도 합니다. (조금 지나니 명령어 외울 필요 없고 조금씩 수정만 하면 되니 이게 편했습니다.) - immutable(변하지 않는), 죽으면 수정하지 않고 다른 멀쩡한 놈으로 교체
: Application 문제가 발생하면 기존 Application의 문제점을 찾아서 변경하는 것이 아니라 새로운 버전 혹은 문제가 없었던 기존 버전으로 교체하는 것을 의미합니다. - Application(=POD) 항상 죽을 수 있다.
: Application down 된 이유를 찾지 말고 POD Down 되어도 이중화 구성을 해서 실 서비스에는 이상 없도록 구성해야 합니다. 실 서비스 오픈 전 반드시 HA, 부하 테스트를 수행 합니다.
(편의상 POD와 application을 같은 개념으로 사용합니다.)
kube 주요 특징
선언형
: POD(= application, process) 나아가 물리 서버(node) down 되어도 자동으로 항상 선언된 상태(e.x pod 3개) 유지한다.
- POD Down
: 강제로 POD를 삭제해 보겠습니다.
[spkr@erdia22 99. ETC (spkcluster:nginx)]$ k delete pod nginx01-58cf646cdb-2q6tp
pod "nginx01-58cf646cdb-2q6tp" deleted
강제로 삭제하여도 자동으로 신규 POD가 생성됩니다.
spkr@erdia22 tmp (spkcluster:nginx)]$ k get pod -w
(-w wait, 변경 사항을 자동으로 tracking 합니다.)NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx01-58cf646cdb-2q6tp 1/1 Running 0 2m2s 10.10.100.49 dia02 <none> <none>
nginx01-58cf646cdb-vx8bs 1/1 Running 0 2m2s 10.10.100.55 dia01 <none> <none>
nginx01-58cf646cdb-x7rgt 1/1 Running 0 2m2s 10.10.100.53 dia04 <none> <none>nginx01-58cf646cdb-2q6tp 1/1 Terminating 0 2m13s 10.10.100.49 dia02 <none> <none>
nginx01-58cf646cdb-xtf92 0/1 Pending 0 0s <none> <none> <none> <none>
nginx01-58cf646cdb-xtf92 0/1 Pending 0 0s <none> dia02 <none> <none>
nginx01-58cf646cdb-xtf92 0/1 ContainerCreating 0 0s <none> dia02 <none> <none>
nginx01-58cf646cdb-2q6tp 0/1 Terminating 0 2m16s 10.10.100.49 dia02 <none> <none>
nginx01-58cf646cdb-xtf92 1/1 Running 0 8s 10.10.100.58 dia02 <none> <none>
nginx01-58cf646cdb-2q6tp 0/1 Terminating 0 2m22s 10.10.100.49 dia02 <none> <none>
nginx01-58cf646cdb-2q6tp 0/1 Terminating 0 2m22s 10.10.100.49 dia02 <none> <none>
위와 같이 기존 pod(nginx01–58cf646cdb-2q6tp) terminating 되고 신규 pod (nginx01–58cf646cdb-xtf92) 생성되어 최초 3개의 상태를 유지합니다. 이는 강제적으로 삭제하지 않고 시스템 문제 등으로 자동으로 POD가 삭제되는 경우에도 항상 3개의 상태가 자동으로 유지됩니다. (새벽에 전화받고 수동으로 올리지 않아도 됩니다.)
- 노드 Down(node drain)
POD 뿐만 아니라 물리 서버(node)가 down 되어도 항상 선언된 상태를 유지합니다.
[spkr@erdia22 99. ETC (spkcluster:nginx)]$ k drain dia04 --delete-emptydir-data --ignore-daemonsets
(drain 명령어를 사용합니다.)node/dia04 already cordoned
WARNING: ignoring DaemonSet-managed Pods: diamanti-system/collectd-v0.8-4bvcc, diamanti-system/csi-diamanti-driver-vlfml, diamanti-system/nfs-csi-diamanti-driver-7kkrv
evicting pod spektra-system/thanos-store-75cbbc5666-qrc2t
evicting pod diamanti-system/csi-external-snapshotter-6d7c748556-gcjsx
evicting pod default/nginx-test-c675f77c4-tqdth
(이하 생략)
dia04 node에서 실행중인 POD가 서버가 down되어 강제 Down 됩니다.
[spkr@erdia22 tmp (spkcluster:nginx)]$ kgpw
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx01-58cf646cdb-lngdj 1/1 Running 0 7m43s 10.10.100.50 dia04 <none> <none>
nginx01-58cf646cdb-nbljw 1/1 Running 0 7m43s 10.10.100.52 dia02 <none> <none>
nginx01-58cf646cdb-x7rgt 1/1 Running 0 7m43s 10.10.100.53 dia04 <none> <none>
nginx01-58cf646cdb-lngdj 1/1 Terminating 0 8m1s 10.10.100.50 dia04 <none> <none>
nginx01-58cf646cdb-ds6qx 0/1 Pending 0 0s <none> <none> <none> <none>
nginx01-58cf646cdb-ds6qx 0/1 Pending 0 0s <none> dia01 <none> <none>
nginx01-58cf646cdb-x7rgt 1/1 Terminating 0 8m3s 10.10.100.53 dia04 <none> <none>
nginx01-58cf646cdb-8gn2r 0/1 Pending 0 0s <none> <none> <none> <none>
nginx01-58cf646cdb-8gn2r 0/1 Pending 0 0s <none> dia02 <none> <none>
nginx01-58cf646cdb-ds6qx 0/1 ContainerCreating 0 3s <none> dia01 <none> <none>
nginx01-58cf646cdb-8gn2r 0/1 ContainerCreating 0 1s <none> dia02 <none> <none>
nginx01-58cf646cdb-lngdj 0/1 Terminating 0 8m27s 10.10.100.50 dia04 <none> <none>
nginx01-58cf646cdb-lngdj 0/1 Terminating 0 8m31s 10.10.100.50 dia04 <none> <none>
nginx01-58cf646cdb-lngdj 0/1 Terminating 0 8m31s 10.10.100.50 dia04 <none> <none>
nginx01-58cf646cdb-x7rgt 0/1 Terminating 0 8m33s 10.10.100.53 dia04 <none> <none>
nginx01-58cf646cdb-x7rgt 0/1 Terminating 0 8m34s 10.10.100.53 dia04 <none> <none>
nginx01-58cf646cdb-x7rgt 0/1 Terminating 0 8m34s 10.10.100.53 dia04 <none> <none>
nginx01-58cf646cdb-ds6qx 1/1 Running 0 41s 10.10.100.62 dia01 <none> <none>
nginx01-58cf646cdb-8gn2r 1/1 Running 0 62s 10.10.100.64 dia02 <none> <none>
위와 같이 무려(?) 서버가 죽어도 자동으로 다른 노드(dia01, dia02)에서 신규 nginx pod가 생성됩니다.
service discovery
: Application 간 서로 지정이 필요한 경우(e.x web — db 호출) 시 IP 기반이 아닌 Domain Name 기반으로 통신합니다. 신규 POD 생성되면 IP가 변경될 수 있습니다.(pod는 수시로 죽을 수 있으므로) 하지만 Domain Name은 변경되지 않으므로 일관성 유지가 가능합니다.
: Load Balancer 기능을 지원하여 복수 POD로 balancing 됩니다.
- NGINX 통신을 위한 Service 생성
: Domain 기반 통신을 위해서는 Service 라는 Kubernetes Object를 사용합니다. 용어가 Service라는 웹서비스 등에서 사용하는 서비스와 혼동될 수 있으나 다른 개념입니다.
[spkr@erdia22 06.Deployment (spkcluster:nginx)]$ k get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-svc ClusterIP 10.0.0.199 <none> 80/TCP 4m18s
- centos POD 실행(접속)
[spkr@erdia22 06.Deployment (spkcluster:nginx)]$ k exec -it cent-tools-697fc7d5fc-2nv9z -- bash
[root@cent-tools-697fc7d5fc-2nv9z /]# curl nginx-svc
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
(이하 생략)[root@cent-tools-75795cfbbb-49zjm /]# curl nginx-svc.nginx.svc.cluster.local
위와 같이 curl 실행을 IP 가 아닌 도메인(nginx-svc 또는 nginx-svc.nginx.cluster.local) 이름을 사용합니다. (nginx-svc는 Service 이름입니다.)
- Load Balancing 테스트
: POD 개수 변경(2개 -> 5개) 시 자동으로 해당 개수만큼 Load Balancing 됩니다.
[spkr@erdia22 99. ETC (spkcluster:nginx)]$ k get endpoints
NAME ENDPOINTS AGE
nginx-svc 10.10.100.52:80,10.10.100.62:80 51m
Service가 실제로 통신하는 POD는 endpoint object 으로 관리됩니다. domain name으로 호출할 때 실제 응답하는 POD가 endpoint 입니다.
[spkr@erdia22 99. ETC (spkcluster:nginx)]$ k scale deployment nginx01 --replicas=5
deployment.apps/nginx01 scaled
nginx POD 수 2개 -> 5개 증가
[spkr@erdia22 99. ETC (spkcluster:nginx)]$ k get endpoints
NAME ENDPOINTS AGE
nginx-svc 10.10.100.25:80,10.10.100.27:80,10.10.100.31:80 + 2 more... 53m
추가 설정 없이 자동으로 endpoint 개수 2개 -> 5개 증가되었습니다.
- 외부에서 접속 시 아래와 같이 10.10.100.33, 10.10.100.43 등으로 분산(Load Balancing)하여 접속됩니다.
Label 기반 Kube Object 관리
: Kube 환경에서는 서로 다른 Object 간 선택을 해야 하는 경우가 많이 있습니다. 이 선택을 label(상표) 기반으로 지정합니다. 예를 들어 Service가 POD를 선택 시 아래와 같습니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-hello
# namespace: default
labels:
app: nginx-hello
spec:
replicas: 2
selector:
matchLabels:
app: nginx-hello
template:
metadata:
labels:
app: nginx-hello # Service 등에서 참조할 Label 이름
spec:
containers:
- name: nginx
image: nginxdemos/hello
label 이름이 app: nginx-hello 입니다.
Service에서 위 POD를 선택하려면 label을 맞추어 줍니다. 아래와 같이 selector (말 그대로 선택자)— app: nginx-hello 로 지정합니다.
apiVersion: v1
kind: Service
metadata:
name: nginxhello-svc
# namespace: default
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx-hello
sessionAffinity: None
type: LoadBalancer
Apply 하시면 Service에서 POD가 선택됩니다.
[spkr@erdia22 06.Deployment (spkn02:nginx)]$ k apply -f ../11.Service/nginx-LoadBalancer-svc.yml
service/nginxhello-svc created[spkr@erdia22 06.Deployment (spkn02:nginx)]$ k describe svc nginxhello-svc
Name: nginxhello-svc
Namespace: nginx
Labels: <none>
Annotations: <none>
Selector: app=nginx-hello
Type: LoadBalancer
IP Families: <none>
IP: 10.233.9.86
IPs: 10.233.9.86
LoadBalancer Ingress: 172.17.28.160
Port: http 80/TCP
TargetPort: 80/TCP
NodePort: http 32240/TCP
Endpoints: 10.233.92.47:80,10.233.96.64:80
Session Affinity: None
External Traffic Policy: Cluster
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal IPAllocated 20s metallb-controller Assigned IP "172.17.28.160"
Normal nodeAssigned 20s metallb-speaker announcing from node "node3"
추가로 하면 아주 많이 많이 있지만 ^^ 다음 번에 하도록 하겠습니다.
컨테이너는 OS, VM 인 듯 아닌 듯
- ssh 가 아닌 exec
- curl, netstat, ping 등 안되는 명령어가 많다.
ephemeral-storage vs persistent volume
- data를 저장하려면 PV로 저장
외부에서 POD 접속 방법
- overlay vs sr-iov 환경
설정 파일 ConfigMap 관리
- NGINX nginx.conf 파일
스케쥴링
- pod 50개 생성 시 각 노드 별 균등 분배
- Node 별 cpu/memory 사용량에 따라 분배
- affinity 사용 시 특정 노드 분배
로그 파일 관리
- 로그가 사라진다