컨테이너를 쉽고 빠르게 배포/확장하고 관리를 자동화해주는 오픈소스 플랫폼
Deployment
: 새로운 버전의 앱을 다양한 전략으로 무중단 배포
StatefulSets
: 실행 순서를 보장, 호스트 이름과 볼륨을 일정하게 사용
DaemonSet
: 로그나 모니터링 등 모든 노드에 설치가 필요한 경우 사용
Job
, CronJob
: 배치성 작업
웹 애플리케이션을 배포하는 과정을 보면 외부에서 직접 접근할 수 없도록 애플리케이션을 내부망에 설치하고 외부에서 접근이 가능한 ALB나 Nginx, Apache를 프록시 서버로 활용
프록시 서버는 도메인과 path 조건에 따라 등록된 서버로 요청을 전달하는데 서버가 바뀌거나 IP가 변경되면 매번 설정을 수정해줘야함
쿠버네티스의 Ingress는 이를 자동화하면서 기존 프록시 서버에서 사용하는 설정을 거의 그대로 사용
하나의 클러스터에 여러 개의 Ingress 설정을 할 수 있어 관리자 접속용 Ingress와 일반 접속용 Ingress를 따로 관리 가능
클라우드 별로 적절한 API를 사용하는 모듈 필요
Cloud Controller를 이용하여 클라우드 연동을 손쉽게 확장
다양한 클라우드 업체(AWS, Google Cloud, Azure...)에서 모듈을 제공하여 관리자는 동일한 설정 파일을 서로 다른 클라우드에서 사용가능
쿠버네티스가 제공하지 않는 기능을 기본 기능과 동일한 방식으로 적용하고 사용
Ex) 쿠버네티스는 기본적으로 SSL 인증서 관리 기능을 제공하지 않지만,
cert-manager
를 설치하고 Certificate 리소스를 이용하면 익숙한 쿠버네티스 명령어로 인증서를 관리가능
CPU, memory 사용량에 따른 확장은 기본이고 현재 접속자 수와 같은 값을 사용가능
Horizontal Pod Autoscaler(HPA)
: 컨테이너 개수 조정 방식
Vertical Pod Autoscaler(VPA)
: 컨테이너의 리소스 할당량 조정 방식
Cluster Autosclaer(CA)
: 서버 개수 조정 방식
클라우드에 설치한 쿠버네티스 클러스터와 자체 서버에 설치한 쿠버네티스를 묶어서 하나로 사용가능
쿠버네티스가 하는 일은 결국 현재 상태를 모니터링하면서 관리자가 설정한 원하는 상태를 유지하는 작업
apiVersion: v1
kind: Pod
metadata:
name: echo
labels:
app: echo
spec:
containers:
- name: app
image: ghcr.io/subicura/echo:v1
version
: 오프젝트 버전 ex) v1, networking.k8s.io/v1, ...
kind
: 종류 ex) Pod, ReplicaSet, Deployment, Service, ...
metadata
: 메타데이터 ex) name과 label, annotation(주석)으로 구성
spec
: 상세명세 ex) 리소스 종류 별로 다름
livenessProbe
컨테이너가 정상적으로 동작하는지 체크하고 정상적으로 동작하지 않는다면 컨테이너를 재시작하여 문제를 해결
apiVersion: v1
kind: Pod
metadata:
name: echo-lp
labels:
app: echo
spec:
containers:
- name: app
image: ghcr.io/subicura/echo:v1
livenessProbe:
httpGet: << 정상적으로 동작하는지 체크하는 방식 중 하나 (tcpSocket, exec)
path: /not/exist << 존재하지 않는 path(/not/exist)와 port(8080)를 입력
port: 8080
initialDelaySeconds: 5
timeoutSeconds: 2 # Default 1
periodSeconds: 5 # Defaults 10
failureThreshold: 1 # Defaults 3
정상적으로 응답하지 않았기 때문에 pod가 여러번 재시작되고 CrashLoopBackOff상태로 변경됨
readinessProbe
컨테이너가 준비되었는지 체크하고 정상적으로 준비되지 않았다면 Pod으로 들어오는 요청을 제외
livenessProbe와 차이점은 문제가 있어도 Pod을 재시작하지 않고 요청만 제외
...
containers:
- name: app
image: ghcr.io/subicura/echo:v1
readinessProbe: <<
httpGet:
path: /not/exist
port: 8080
...
보통 livenessProbe
와 readinessProbe
를 같이 적용
다중 컨테이너
apiVersion: v1
kind: Pod
metadata:
name: counter
labels:
app: counter
spec:
containers:
- name: app <<
image: ghcr.io/subicura/counter:latest
env:
- name: REDIS_HOST
value: "localhost"
- name: db <<
image: redis
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: echo-rs
spec:
replicas: 1 <<
selector: <<
matchLabels:
app: echo
tier: app
template: <<
metadata:
labels:
app: echo
tier: app
spec:
containers:
- name: echo
image: ghcr.io/subicura/echo:v1
spec.selector
: label 체크 조건
spec.replicas
: 원하는 pod 수
spec.template
: 생성할 pod의 명세
apiVersion: apps/v1
kind: Deployment <<
metadata:
name: echo-deploy
spec:
replicas: 4
selector:
matchLabels:
app: echo
tier: app
template: <<
metadata:
labels:
app: echo
tier: app
spec:
containers:
- name: echo
image: ghcr.io/subicura/echo:v1
apiVersion: apps/v1
kind: Deployment <<
metadata:
name: echo-deploy
spec:
replicas: 4
selector:
matchLabels:
app: echo
tier: app
template: <<
metadata:
labels:
app: echo
tier: app
spec:
containers:
- name: echo
image: ghcr.io/subicura/echo:v2 <<
새로운 버전의 Pod을 생성하고 기존 Pod을 제거됨
# 히스토리 확인
kubectl rollout history deploy/echo-deploy
# revision 1 히스토리 상세 확인
kubectl rollout history deploy/echo-deploy --revision=1
# 바로 전으로 롤백
kubectl rollout undo deploy/echo-deploy
# 특정 버전으로 롤백
kubectl rollout undo deploy/echo-deploy --to-revision=2
동시에 업데이트하는 pod의 개수 조정 (default=25%)
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo-deploy-st
spec:
replicas: 4
selector:
matchLabels:
app: echo
tier: app
minReadySeconds: 5
strategy: <<
type: RollingUpdate
rollingUpdate:
maxSurge: 3
maxUnavailable: 3
template:
metadata:
labels:
app: echo
tier: app
spec:
containers:
- name: echo
image: ghcr.io/subicura/echo:v1
livenessProbe:
httpGet:
path: /
port: 3000
ClusterIp
, NodePort
, LoadBalancer
타입으로 나뉨 ClusterIp
여러 개의 pod를 바라보는 내부 로드 밸런서
서비스 이름을 내부 도메인 서버에 등록하여 Pod 간에 서비스 이름으로 통신할 수 있음
counter 앱 중 redis
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
spec:
selector:
matchLabels:
app: counter
tier: db
template:
metadata:
labels:
app: counter
tier: db
spec:
containers:
- name: redis
image: redis
ports:
- containerPort: 6379
protocol: TCP
---
apiVersion: v1
kind: Service <<
metadata:
name: redis <<
spec:
ports:
- port: 6379
protocol: TCP
selector:
app: counter
tier: db
spec.ports.port
: 서비스가 생성할 Port
spec.ports.targetPort
: 서비스가 접근할 Pod의 Port (기본: port랑 동일)
spec.selector
: 서비스가 접근할 Pod의 label 조건
redis에 접근할 counter 앱
apiVersion: apps/v1
kind: Deployment
metadata:
name: counter
spec:
selector:
matchLabels:
app: counter
tier: app
template:
metadata:
labels:
app: counter
tier: app
spec:
containers:
- name: counter
image: ghcr.io/subicura/counter:latest
env:
- name: REDIS_HOST <<
value: "redis"
- name: REDIS_PORT
value: "6379"
counter app pod 에서 redis Pod로 접근이 가능
ubectl apply -f counter-app.yml
# counter app에 접근
kubectl get po
kubectl exec -it counter-<xxxxx> -- sh
# curl localhost:3000
>> 1
# curl localhost:3000
>> 2
# telnet redis 6379
dbsize
KEYS *
GET count
>> 2
quit
NodePort
apiVersion: v1
kind: Service
metadata:
name: counter-np
spec:
type: NodePort
ports:
- port: 3000
protocol: TCP
nodePort: 31000
selector:
app: counter
tier: app
spec.ports.nodePort
: 노드에 오픈할 Port (미지정시 30000-32768 중에 자동 할당)
LoadBalancer
Load Balancer는 AWS, Google Cloud, Azure 같은 클라우드 환경이 아니면 사용이 제한적임
특정 서버(노드)를 가리키는 무언가(Load Balancer)가 필요한데 이런 무언가가 가상머신이나 로컬 서버에는 존재 X
앱을 배포하기 위해 원하는 상태(desired state)를 다양한 오브젝트에 라벨을 붙여 정의(yaml)하고 API서버에 전달하는 방식
ex) 컨테이너를 2개 배포하고 80 포트로 오픈 ⬇️
master에 API서버와 상태 저장소를 두고 각 node의 kubelet과 통신하는 구조
특정 node의 컨테이너에 명령하거나 로그를 조회할 떄도 node에 직접 명령하는게 아니라 master에 명령을 내리고 master가 node에 접속해서 대신 결과 응답
kube-apiserver
: API 서버
etcd
: 분산 데이터 저장소
kube-scheduler
할당되지 않은 pod를 여러 조건에 따라 적절한 노드 서버에 할당
kube-controller-manager
cloud-controller-manager
kubelet
kube-proxy
API서버는 json또는 protobuf형식을 이용한 http 통신을 지원하지만 kubectl이라는 명령행 도구를 사용
관리자가 ReplicaSet을 생성하면 아래와 같은 과정을 거쳐 Pod 생성
각 모듈은 서로 통신하지 않고 오직 API서버를 통해 etcd에 저장된 상태를 체크하고 현재 상태와 원하는 상태가 다르면 필요한 작업을 수행하는 방식
위 과정은 ReplicaSet이 pod를 생성하는 과정이지만 모든 노드에 pod를 배포하는 DaemonSet도 동일한 방식으로 동작
https://subicura.com/2019/05/19/kubernetes-basic-1.html
https://subicura.com/k8s/guide/