클러스터 관리
쿠버네티스 클러스터 생성 또는 관리에 관련된 로우-레벨(lower-level)의 세부 정보를 설명한다.
클러스터 관리 개요는 쿠버네티스 클러스터를 생성하거나 관리하는 모든 사람들을 위한 것이다.
핵심 쿠버네티스 개념에 어느 정도 익숙하다고 가정한다.
클러스터 계획
쿠버네티스 클러스터를 계획, 설정 및 구성하는 방법에 대한 예는 시작하기에 있는 가이드를 참고한다. 이 문서에 나열된 솔루션을 배포판 이라고 한다.
참고: 모든 배포판이 활발하게 유지되는 것은 아니다. 최신 버전의 쿠버네티스에서 테스트된 배포판을 선택한다.
가이드를 선택하기 전에 고려해야 할 사항은 다음과 같다.
- 컴퓨터에서 쿠버네티스를 한번 사용해보고 싶은가? 아니면, 고가용 멀티 노드 클러스터를 만들고 싶은가? 사용자의 필요에 따라 가장 적합한 배포판을 선택한다.
- 구글 쿠버네티스 엔진(Google Kubernetes Engine)과 같은 클라우드 제공자의 쿠버네티스 클러스터 호스팅 을 사용할 것인가? 아니면, 자체 클러스터를 호스팅 할 것인가?
- 클러스터가 온-프레미스 환경 에 있나? 아니면, 클라우드(IaaS) 에 있나? 쿠버네티스는 하이브리드 클러스터를 직접 지원하지는 않는다. 대신 여러 클러스터를 설정할 수 있다.
- 온-프레미스 환경에 쿠버네티스 를 구성하는 경우, 어떤 네트워킹 모델이 가장 적합한 지 고려한다.
- 쿠버네티스를 "베어 메탈" 하드웨어 에서 실행할 것인가? 아니면, 가상 머신(VM) 에서 실행할 것인가?
- 클러스터만 실행할 것인가? 아니면, 쿠버네티스 프로젝트 코드를 적극적으로 개발 하는 것을 기대하는가? 만약
후자라면, 활발하게 개발이 진행되고 있는 배포판을 선택한다. 일부 배포판은 바이너리 릴리스만 사용하지만,
더 다양한 선택을 제공한다.
- 클러스터를 실행하는 데 필요한 컴포넌트에 익숙해지자.
클러스터 관리
클러스터 보안
kubelet 보안
선택적 클러스터 서비스
1 - 인증서
클러스터를 위한 인증서를 생성하기 위해서는, 인증서를 참고한다.
2 - 리소스 관리
애플리케이션을 배포하고 서비스를 통해 노출했다. 이제 무엇을 해야 할까? 쿠버네티스는 확장과 업데이트를 포함하여, 애플리케이션 배포를 관리하는 데 도움이 되는 여러 도구를 제공한다. 더 자세히 설명할 기능 중에는 구성 파일과 레이블이 있다.
리소스 구성 구성하기
많은 애플리케이션들은 디플로이먼트 및 서비스와 같은 여러 리소스를 필요로 한다. 여러 리소스의 관리는 동일한 파일에 그룹화하여 단순화할 수 있다(YAML에서 ---
로 구분). 예를 들면 다음과 같다.
apiVersion: v1
kind: Service
metadata:
name: my-nginx-svc
labels:
app: nginx
spec:
type: LoadBalancer
ports:
- port: 80
selector:
app: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
단일 리소스와 동일한 방식으로 여러 리소스를 생성할 수 있다.
kubectl apply -f https://k8s.io/examples/application/nginx-app.yaml
service/my-nginx-svc created
deployment.apps/my-nginx created
리소스는 파일에 표시된 순서대로 생성된다. 따라서, 스케줄러가 디플로이먼트와 같은 컨트롤러에서 생성한 서비스와 관련된 파드를 분산시킬 수 있으므로, 서비스를 먼저 지정하는 것이 가장 좋다.
kubectl apply
는 여러 개의 -f
인수도 허용한다.
kubectl apply -f https://k8s.io/examples/application/nginx/nginx-svc.yaml -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml
그리고 개별 파일 대신 또는 추가로 디렉터리를 지정할 수 있다.
kubectl apply -f https://k8s.io/examples/application/nginx/
kubectl
은 접미사가 .yaml
, .yml
또는 .json
인 파일을 읽는다.
동일한 마이크로서비스 또는 애플리케이션 티어(tier)와 관련된 리소스를 동일한 파일에 배치하고, 애플리케이션과 연관된 모든 파일을 동일한 디렉터리에 그룹화하는 것이 좋다. 애플리케이션의 티어가 DNS를 사용하여 서로 바인딩되면, 스택의 모든 컴포넌트를 함께 배포할 수 있다.
URL을 구성 소스로 지정할 수도 있다. 이는 GitHub에 체크인된 구성 파일에서 직접 배포하는 데 편리하다.
kubectl apply -f https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/application/nginx/nginx-deployment.yaml
deployment.apps/my-nginx created
kubectl에서의 대량 작업
kubectl
이 대량으로 수행할 수 있는 작업은 리소스 생성만이 아니다. 또한 다른 작업을 수행하기 위해, 특히 작성한 동일한 리소스를 삭제하기 위해 구성 파일에서 리소스 이름을 추출할 수도 있다.
kubectl delete -f https://k8s.io/examples/application/nginx-app.yaml
deployment.apps "my-nginx" deleted
service "my-nginx-svc" deleted
두 개의 리소스가 있는 경우, 리소스/이름 구문을 사용하여 커맨드 라인에서 둘다 모두 지정할 수도 있다.
kubectl delete deployments/my-nginx services/my-nginx-svc
리소스가 많을 경우, -l
또는 --selector
를 사용하여 지정된 셀렉터(레이블 쿼리)를 지정하여 레이블별로 리소스를 필터링하는 것이 더 쉽다.
kubectl delete deployment,services -l app=nginx
deployment.apps "my-nginx" deleted
service "my-nginx-svc" deleted
kubectl
은 입력을 받아들이는 것과 동일한 구문으로 리소스 이름을 출력하므로, $()
또는 xargs
를 사용하여 작업을 연결할 수 있다.
kubectl get $(kubectl create -f docs/concepts/cluster-administration/nginx/ -o name | grep service)
kubectl create -f docs/concepts/cluster-administration/nginx/ -o name | grep service | xargs -i kubectl get {}
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-nginx-svc LoadBalancer 10.0.0.208 <pending> 80/TCP 0s
위의 명령을 사용하여, 먼저 examples/application/nginx/
에 리소스를 생성하고 -o name
출력 형식으로 생성한 리소스를 출력한다(각 리소스를 resource/name으로 출력).
그런 다음 "service"만 grep
한 다음 kubectl get
으로 출력한다.
특정 디렉터리 내의 여러 서브 디렉터리에서 리소스를 구성하는 경우, --filename,-f
플래그와 함께 --recursive
또는 -R
을 지정하여, 서브 디렉터리에 대한 작업을 재귀적으로 수행할 수도 있다.
예를 들어, 리소스 유형별로 구성된 개발 환경에 필요한 모든 매니페스트를 보유하는 project/k8s/development
디렉터리가 있다고 가정하자.
project/k8s/development
├── configmap
│ └── my-configmap.yaml
├── deployment
│ └── my-deployment.yaml
└── pvc
└── my-pvc.yaml
기본적으로, project/k8s/development
에서 대량 작업을 수행하면, 서브 디렉터리를 처리하지 않고, 디렉터리의 첫 번째 레벨에서 중지된다. 다음 명령을 사용하여 이 디렉터리에 리소스를 생성하려고 하면, 오류가 발생할 것이다.
kubectl apply -f project/k8s/development
error: you must provide one or more resources by argument or filename (.json|.yaml|.yml|stdin)
대신, 다음과 같이 --filename,-f
플래그와 함께 --recursive
또는 -R
플래그를 지정한다.
kubectl apply -f project/k8s/development --recursive
configmap/my-config created
deployment.apps/my-deployment created
persistentvolumeclaim/my-pvc created
--recursive
플래그는 kubectl {create,get,delete,describe,rollout}
등과 같이 --filename,-f
플래그를 허용하는 모든 작업에서 작동한다.
--recursive
플래그는 여러 개의 -f
인수가 제공될 때도 작동한다.
kubectl apply -f project/k8s/namespaces -f project/k8s/development --recursive
namespace/development created
namespace/staging created
configmap/my-config created
deployment.apps/my-deployment created
persistentvolumeclaim/my-pvc created
kubectl
에 대해 더 자세히 알고 싶다면, kubectl 개요를 참조한다.
효과적인 레이블 사용
지금까지 사용한 예는 모든 리소스에 최대 한 개의 레이블만 적용하는 것이었다. 세트를 서로 구별하기 위해 여러 레이블을 사용해야 하는 많은 시나리오가 있다.
예를 들어, 애플리케이션마다 app
레이블에 다른 값을 사용하지만, 방명록 예제와 같은 멀티-티어 애플리케이션은 각 티어를 추가로 구별해야 한다. 프론트엔드는 다음의 레이블을 가질 수 있다.
labels:
app: guestbook
tier: frontend
Redis 마스터와 슬레이브는 프론트엔드와 다른 tier
레이블을 가지지만, 아마도 추가로 role
레이블을 가질 것이다.
labels:
app: guestbook
tier: backend
role: master
그리고
labels:
app: guestbook
tier: backend
role: slave
레이블은 레이블로 지정된 차원에 따라 리소스를 분할하고 사용할 수 있게 한다.
kubectl apply -f examples/guestbook/all-in-one/guestbook-all-in-one.yaml
kubectl get pods -Lapp -Ltier -Lrole
NAME READY STATUS RESTARTS AGE APP TIER ROLE
guestbook-fe-4nlpb 1/1 Running 0 1m guestbook frontend <none>
guestbook-fe-ght6d 1/1 Running 0 1m guestbook frontend <none>
guestbook-fe-jpy62 1/1 Running 0 1m guestbook frontend <none>
guestbook-redis-master-5pg3b 1/1 Running 0 1m guestbook backend master
guestbook-redis-slave-2q2yf 1/1 Running 0 1m guestbook backend slave
guestbook-redis-slave-qgazl 1/1 Running 0 1m guestbook backend slave
my-nginx-divi2 1/1 Running 0 29m nginx <none> <none>
my-nginx-o0ef1 1/1 Running 0 29m nginx <none> <none>
kubectl get pods -lapp=guestbook,role=slave
NAME READY STATUS RESTARTS AGE
guestbook-redis-slave-2q2yf 1/1 Running 0 3m
guestbook-redis-slave-qgazl 1/1 Running 0 3m
카나리(canary) 디플로이먼트
여러 레이블이 필요한 또 다른 시나리오는 동일한 컴포넌트의 다른 릴리스 또는 구성의 디플로이먼트를 구별하는 것이다. 새 릴리스가 완전히 롤아웃되기 전에 실제 운영 트래픽을 수신할 수 있도록 새로운 애플리케이션 릴리스(파드 템플리트의 이미지 태그를 통해 지정됨)의 카나리 를 이전 릴리스와 나란히 배포하는 것이 일반적이다.
예를 들어, track
레이블을 사용하여 다른 릴리스를 구별할 수 있다.
기본(primary), 안정(stable) 릴리스에는 값이 stable
인 track
레이블이 있다.
name: frontend
replicas: 3
...
labels:
app: guestbook
tier: frontend
track: stable
...
image: gb-frontend:v3
그런 다음 서로 다른 값(예: canary
)으로 track
레이블을 전달하는 방명록 프론트엔드의 새 릴리스를 생성하여, 두 세트의 파드가 겹치지 않도록 할 수 있다.
name: frontend-canary
replicas: 1
...
labels:
app: guestbook
tier: frontend
track: canary
...
image: gb-frontend:v4
프론트엔드 서비스는 레이블의 공통 서브셋을 선택하여(즉, track
레이블 생략) 두 레플리카 세트에 걸쳐 있으므로, 트래픽이 두 애플리케이션으로 리디렉션된다.
selector:
app: guestbook
tier: frontend
안정 및 카나리 릴리스의 레플리카 수를 조정하여 실제 운영 트래픽을 수신할 각 릴리스의 비율을 결정한다(이 경우, 3:1).
확신이 들면, 안정 릴리스의 track을 새로운 애플리케이션 릴리스로 업데이트하고 카나리를 제거할 수 있다.
보다 구체적인 예시는, Ghost 배포에 대한 튜토리얼을 확인한다.
레이블 업데이트
새로운 리소스를 만들기 전에 기존 파드 및 기타 리소스의 레이블을 다시 지정해야 하는 경우가 있다. 이것은 kubectl label
로 수행할 수 있다.
예를 들어, 모든 nginx 파드에 프론트엔드 티어로 레이블을 지정하려면, 다음과 같이 실행한다.
kubectl label pods -l app=nginx tier=fe
pod/my-nginx-2035384211-j5fhi labeled
pod/my-nginx-2035384211-u2c7e labeled
pod/my-nginx-2035384211-u3t6x labeled
먼저 "app=nginx" 레이블이 있는 모든 파드를 필터링한 다음, "tier=fe" 레이블을 지정한다.
레이블을 지정한 파드를 보려면, 다음을 실행한다.
kubectl get pods -l app=nginx -L tier
NAME READY STATUS RESTARTS AGE TIER
my-nginx-2035384211-j5fhi 1/1 Running 0 23m fe
my-nginx-2035384211-u2c7e 1/1 Running 0 23m fe
my-nginx-2035384211-u3t6x 1/1 Running 0 23m fe
그러면 파드 티어의 추가 레이블 열(-L
또는 --label-columns
로 지정)과 함께, 모든 "app=nginx" 파드가 출력된다.
더 자세한 내용은, 레이블 및 kubectl label을 참고하길 바란다.
어노테이션 업데이트
때로는 어노테이션을 리소스에 첨부하려고 할 수도 있다. 어노테이션은 도구, 라이브러리 등과 같은 API 클라이언트가 검색할 수 있는 임의의 비-식별 메타데이터이다. 이는 kubectl annotate
으로 수행할 수 있다. 예를 들면 다음과 같다.
kubectl annotate pods my-nginx-v4-9gw19 description='my frontend running nginx'
kubectl get pods my-nginx-v4-9gw19 -o yaml
apiVersion: v1
kind: pod
metadata:
annotations:
description: my frontend running nginx
...
더 자세한 내용은, 어노테이션 및 kubectl annotate 문서를 참고하길 바란다.
애플리케이션 스케일링
애플리케이션의 로드가 증가하거나 축소되면, kubectl
을 사용하여 애플리케이션을 스케일링한다. 예를 들어, nginx 레플리카 수를 3에서 1로 줄이려면, 다음을 수행한다.
kubectl scale deployment/my-nginx --replicas=1
deployment.apps/my-nginx scaled
이제 디플로이먼트가 관리하는 파드가 하나만 있다.
kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
my-nginx-2035384211-j5fhi 1/1 Running 0 30m
시스템이 필요에 따라 1에서 3까지의 범위에서 nginx 레플리카 수를 자동으로 선택하게 하려면, 다음을 수행한다.
kubectl autoscale deployment/my-nginx --min=1 --max=3
horizontalpodautoscaler.autoscaling/my-nginx autoscaled
이제 nginx 레플리카가 필요에 따라 자동으로 확장되거나 축소된다.
더 자세한 내용은, kubectl scale, kubectl autoscale 및 horizontal pod autoscaler 문서를 참고하길 바란다.
리소스 인플레이스(in-place) 업데이트
때로는 자신이 만든 리소스를 필요한 부분만, 중단없이 업데이트해야 할 때가 있다.
kubectl apply
구성 파일 셋을 소스 제어에서 유지하는 것이 좋으며
(코드로서의 구성 참조),
그렇게 하면 구성하는 리소스에 대한 코드와 함께 버전을 지정하고 유지할 수 있다.
그런 다음, kubectl apply
를 사용하여 구성 변경 사항을 클러스터로 푸시할 수 있다.
이 명령은 푸시하려는 구성의 버전을 이전 버전과 비교하고 지정하지 않은 속성에 대한 자동 변경 사항을 덮어쓰지 않은 채 수정한 변경 사항을 적용한다.
kubectl apply -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml
deployment.apps/my-nginx configured
참고로 kubectl apply
는 이전의 호출 이후 구성의 변경 사항을 판별하기 위해 리소스에 어노테이션을 첨부한다. 호출되면, kubectl apply
는 리소스를 수정하는 방법을 결정하기 위해, 이전 구성과 제공된 입력 및 리소스의 현재 구성 간에 3-way diff를 수행한다.
현재, 이 어노테이션 없이 리소스가 생성되므로, kubectl apply
의 첫 번째 호출은 제공된 입력과 리소스의 현재 구성 사이의 2-way diff로 대체된다. 이 첫 번째 호출 중에는, 리소스를 생성할 때 설정된 특성의 삭제를 감지할 수 없다. 이러한 이유로, 그 특성들을 삭제하지 않는다.
kubectl apply
에 대한 모든 후속 호출, 그리고 kubectl replace
및 kubectl edit
와 같이 구성을 수정하는 다른 명령은, 어노테이션을 업데이트하여, kubectl apply
에 대한 후속 호출이 3-way diff를 사용하여 삭제를 감지하고 수행할 수 있도록 한다.
kubectl edit
또는, kubectl edit
로 리소스를 업데이트할 수도 있다.
kubectl edit deployment/my-nginx
이것은 먼저 리소스를 get
하여, 텍스트 편집기에서 편집한 다음, 업데이트된 버전으로 리소스를 apply
하는 것과 같다.
kubectl get deployment my-nginx -o yaml > /tmp/nginx.yaml
vi /tmp/nginx.yaml
# 편집한 다음, 파일을 저장한다.
kubectl apply -f /tmp/nginx.yaml
deployment.apps/my-nginx configured
rm /tmp/nginx.yaml
이를 통해 보다 중요한 변경을 더 쉽게 수행할 수 있다. 참고로 EDITOR
또는 KUBE_EDITOR
환경 변수를 사용하여 편집기를 지정할 수 있다.
더 자세한 내용은, kubectl edit 문서를 참고하길 바란다.
kubectl patch
kubectl patch
를 사용하여 API 오브젝트를 인플레이스 업데이트할 수 있다. 이 명령은 JSON 패치,
JSON 병합 패치 그리고 전략적 병합 패치를 지원한다.
kubectl patch를 사용한 인플레이스 API 오브젝트 업데이트와
kubectl patch를
참조한다.
파괴적(disruptive) 업데이트
경우에 따라, 한 번 초기화하면 업데이트할 수 없는 리소스 필드를 업데이트해야 하거나, 디플로이먼트에서 생성된 손상된 파드를 고치는 등의 재귀적 변경을 즉시 원할 수도 있다. 이러한 필드를 변경하려면, replace --force
를 사용하여 리소스를 삭제하고 다시 만든다. 이 경우, 원래 구성 파일을 수정할 수 있다.
kubectl replace -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml --force
deployment.apps/my-nginx deleted
deployment.apps/my-nginx replaced
서비스 중단없이 애플리케이션 업데이트
언젠가는, 위의 카나리 디플로이먼트 시나리오에서와 같이, 일반적으로 새 이미지 또는 이미지 태그를 지정하여, 배포된 애플리케이션을 업데이트해야 한다. kubectl
은 여러 가지 업데이트 작업을 지원하며, 각 업데이트 작업은 서로 다른 시나리오에 적용할 수 있다.
디플로이먼트를 사용하여 애플리케이션을 생성하고 업데이트하는 방법을 안내한다.
nginx 1.14.2 버전을 실행한다고 가정해 보겠다.
kubectl create deployment my-nginx --image=nginx:1.14.2
deployment.apps/my-nginx created
3개의 레플리카를 포함한다(이전과 새 개정판이 공존할 수 있음).
kubectl scale deployment my-nginx --current-replicas=1 --replicas=3
deployment.apps/my-nginx scaled
1.16.1 버전으로 업데이트하려면, 위에서 배운 kubectl 명령을 사용하여 .spec.template.spec.containers[0].image
를 nginx:1.14.2
에서 nginx:1.16.1
로 변경한다.
kubectl edit deployment/my-nginx
이것으로 끝이다! 디플로이먼트는 배포된 nginx 애플리케이션을 배후에서 점차적으로 업데이트한다. 업데이트되는 동안 특정 수의 이전 레플리카만 중단될 수 있으며, 원하는 수의 파드 위에 특정 수의 새 레플리카만 생성될 수 있다. 이에 대한 더 자세한 내용을 보려면, 디플로이먼트 페이지를 방문한다.
다음 내용
3 - 클러스터 네트워킹
네트워킹은 쿠버네티스의 중심적인 부분이지만, 어떻게 작동하는지 정확하게
이해하기가 어려울 수 있다. 쿠버네티스에는 4가지 대응해야 할 네트워킹
문제가 있다.
- 고도로 결합된 컨테이너 간의 통신: 이 문제는
파드와
localhost
통신으로 해결된다.
- 파드 간 통신: 이 문제가 이 문서의 주요 초점이다.
- 파드와 서비스 간 통신: 이 문제는 서비스에서 다룬다.
- 외부와 서비스 간 통신: 이 문제는 서비스에서 다룬다.
쿠버네티스는 애플리케이션 간에 머신을 공유하는 것이다. 일반적으로,
머신을 공유하려면 두 애플리케이션이 동일한 포트를 사용하지 않도록
해야 한다. 여러 개발자 간에 포트를 조정하는 것은 대규모로 실시하기가 매우 어렵고,
사용자가 통제할 수 없는 클러스터 수준의 문제에 노출된다.
동적 포트 할당은 시스템에 많은 복잡성을 야기한다. 모든
애플리케이션은 포트를 플래그로 가져와야 하며, API 서버는 동적 포트 번호를
구성 블록에 삽입하는 방법을 알아야 하고, 서비스는 서로를
찾는 방법 등을 알아야 한다. 쿠버네티스는 이런 것들을 다루는 대신
다른 접근법을 취한다.
쿠버네티스 네트워크 모델
모든 Pod
에는 고유의 IP 주소가 있다. 즉, Pod
간에 링크를 명시적으로
생성할 필요가 없으며 컨테이너 포트를 호스트 포트에 매핑할
필요가 거의 없다. 이렇게 하면 포트 할당, 이름 지정, 서비스 검색, 로드 밸런싱,
애플리케이션 구성 및 마이그레이션 관점에서 Pod
를 VM 또는
물리적 호스트처럼 취급할 수 있는 깔끔하고, 하위 호환성
있는 모델이 생성된다.
쿠버네티스는 모든 네트워크 구현에 다음과 같은
기본 요구 사항을 적용한다(의도적 네트워크 세분화 정책 제외).
- 노드의 파드는 NAT 없이 모든 노드의 모든 파드와 통신할 수 있다.
- 노드의 에이전트(예: 시스템 데몬, kubelet)는 해당 노드의 모든
파드와 통신할 수 있다.
참고: 호스트 네트워크에서 실행되는 Pod
를 지원하는 리눅스와 같은 플랫폼의 경우, 다음의 요구 사항을
적용한다.
- 노드의 호스트 네트워크에 있는 파드는 NAT 없이 모든 노드에 있는 모든
파드와 통신할 수 있다.
이 모델은 전체적으로 덜 복잡할 뿐만 아니라, 쿠버네티스를 위해 VM에서
컨테이너로 애플리케이션을 포팅할 때 충돌이 적게 구현하려는 요구와
주로 호환된다. 잡이 이전에 VM에서 실행된 경우, VM에 IP가 있고
프로젝트의 다른 VM과 통신할 수 있다. 이것은 동일한 기본 모델이다.
쿠버네티스의 IP 주소는 그것의 IP 주소와 MAC 주소를 포함하여 Pod
범위에 존재한다(Pod
내
컨테이너는 네트워크 네임스페이스를 공유함). 이것은 Pod
내 컨테이너가 모두
localhost
에서 서로의 포트에 도달할 수 있다는 것을 의미한다. 또한
Pod
내부의 컨테이너 포트의 사용을 조정해야하는 것을 의미하지만, 이것도
VM 내의 프로세스와 동일하다. 이것을 "IP-per-pod(파드별 IP)" 모델이라고
한다.
이것이 어떻게 구현되는 지는 사용 중인 특정 컨테이너 런타임의 세부 사항이다.
Pod
로 전달하는 Node
자체의 포트(호스트 포트라고 함)를
요청할 수 있지만, 이는 매우 틈새 작업이다. 전달이 구현되는 방법은
컨테이너 런타임의 세부 사항이기도 하다. Pod
자체는
호스트 포트의 존재 여부에 대해 인식하지 못한다.
쿠버네티스 네트워크 모델의 구현 방법
이 네트워크 모델을 구현할 수 있는 방법에는 여러 가지가 있다. 이
문서는 다양한 방법에 대한 철저한 연구는 아니지만, 다양한 기술에 대한
소개로 활용되며 도약하는 포인트로 사용되기를 바란다.
이 목록은 알파벳 순으로 정렬되어 있으며, 정렬된 순서가
우선 상태를 의미하는 것은 아니다.
참고:
이 섹션은 쿠버네티스에 필요한 기능을 제공하는 써드파티 프로젝트와 관련이 있다. 쿠버네티스 프로젝트 작성자는 써드파티 프로젝트에 책임이 없다. 이 페이지는
CNCF 웹사이트 가이드라인에 따라 프로젝트를 알파벳 순으로 나열한다. 이 목록에 프로젝트를 추가하려면 변경사항을 제출하기 전에
콘텐츠 가이드를 읽어본다.
ACI
Cisco 애플리케이션 센트릭 인프라스트럭처(Application Centric Infrastructure)는 컨테이너, 가상 머신 및 베어메탈 서버를 지원하는 통합 오버레이 및 언더레이 SDN 솔루션을 제공한다. ACI는 ACI를 위한 컨테이너 네트워킹 통합을 제공한다. 통합의 개요는 여기에서 제공된다.
Antrea
프로젝트 Antrea는 쿠버네티스 고유의 오픈소스 쿠버네티스 네트워킹 솔루션이다. 네트워킹 데이터 플레인으로 Open vSwitch를 활용한다. Open vSwitch는 리눅스와 윈도우를 모두 지원하는 고성능의 프로그래밍이 가능한 가상 스위치이다. Antrea는 Open vSwitch를 통해 쿠버네티스 네트워크 정책을 고성능의 효율적인 방식으로 구현할 수 있다.
Antrea는 Open vSwitch의 "프로그래밍이 가능한" 특성으로 인해 Open vSwitch 위에 광범위한 네트워킹 및 보안 기능과 서비스를 구현할 수 있다.
쿠버네티스용 AWS VPC CNI
AWS VPC CNI는 쿠버네티스 클러스터를 위한 통합된 AWS 버추얼 프라이빗 클라우드(Virtual Private Cloud, VPC) 네트워킹을 제공한다. 이 CNI 플러그인은 높은 처리량과 가용성, 낮은 레이턴시(latency) 그리고 최소 네트워크 지터(jitter)를 제공한다. 또한, 사용자는 쿠버네티스 클러스터를 구축하기 위한 기존의 AWS VPC 네트워킹 및 보안 모범 사례를 적용할 수 있다. 여기에는 VPC 플로우 로그, VPC 라우팅 정책과 네트워크 트래픽 격리를 위한 보안 그룹을 사용하는 기능이 포함되어 있다.
이 CNI 플러그인을 사용하면 쿠버네티스 파드는 VPC 네트워크와 동일한 IP 주소를 파드 내부에 가질 수 있다. CNI는 각 쿠버네티스 노드에 AWS 엘라스틱 네트워킹 인터페이스(Elastic Networking Interfaces, ENI)를 할당하고 노드의 파드에 대해 각 ENI의 보조 IP 범위를 사용한다. CNI에는 파드를 빠르게 시작하기 위해 ENI와 IP 주소의 사전 할당 제어 기능이 포함되어 있으며 최대 2,000개의 노드로 구성된 대규모 클러스터가 가능하다.
또한, CNI는 네트워크 폴리시 적용을 위해 캘리코(Calico)와 함께 실행할 수 있다. AWS VPC CNI 프로젝트는 GitHub의 문서와 함께 오픈소스로 공개되어 있다.
쿠버네티스용 Azure CNI
Azure CNI는 VM과 동등한 네트워크 성능을 제공하는 Azure 버추얼 네트워크(VNet이라고도 알려진)와 쿠버네티스 파드를 통합하는 오픈소스 플러그인이다. 파드는 피어링된 VNet과 Express Route 또는 사이트 간 VPN을 통해 온-프레미스에 연결할 수 있으며 이러한 네트워크에서 직접 연결할 수도 있다. 파드는 서비스 엔드포인트 또는 프라이빗 링크로 보호되는 스토리지와 SQL과 같은 Azure 서비스에 접근할 수 있다. VNet 보안 정책과 라우팅을 사용하여 파드 트래픽을 필터링할 수 있다. 플러그인은 쿠버네티스 노드의 네트워크 인터페이스에 사전 구성된 보조 IP 풀을 활용하여 VNet IP를 파드에 할당한다.
Azure CNI는 Azure 쿠버네티스 서비스(Azure Kubernetes Service, AKS)에서 기본적으로 사용할 수 있다.
캘리코
캘리코는 컨테이너, 가상 시스템 및 기본 호스트 기반 워크로드를 위한 오픈소스 네트워킹 및 네트워크 보안 솔루션이다. 캘리코는 순수 리눅스 eBPF 데이터플레인, 표준 리눅스 네트워킹 데이터플레인, 윈도우 HNS 데이터플레인을 포함한 여러 데이터플레인을 지원한다. 캘리코는 완전한 네트워킹 스택을 제공하지만, 클라우드 제공자 CNI와 함께 사용하여 네트워크 정책 시행을 제공할 수도 있다.
실리움(Cilium)
실리움은 애플리케이션 컨테이너 간에
네트워크 연결을 제공하고 투명하게 보호하기 위한 오픈소스 소프트웨어이다.
실리움은 L7/HTTP를 인식하며 네트워크 주소 지정에서 분리된 ID 기반 보안 모델을 사용하여 L3-L7에서
네트워크 정책을 적용할 수 있으며,
다른 CNI 플러그인과 함께 사용할 수 있다.
화웨이의 CNI-Genie
CNI-Genie는 쿠버네티스가 런타임 시 쿠버네티스 네트워크 모델의 서로 다른 구현에 동시에 접근할 수 있는 CNI 플러그인이다. 여기에는 플라넬(Flannel), 캘리코, 로마나(Romana), 위브넷(Weave-net)과 같은 CNI 플러그인으로 실행되는 모든 구현이 포함된다.
CNI-Genie는 각각 다른 CNI 플러그인에서 하나의 파드에 여러 IP 주소를 할당하는 것도 지원한다.
cni-ipvlan-vpc-k8s
cni-ipvlan-vpc-k8s는
L2 모드에서 리눅스 커널의 IPvlan 드라이버를 사용하여 Amazon 엘라스틱 네트워크 인터페이스(ENI)를
사용하고 AWS 매니지드 IP를 파드에 바인딩하는
Amazon 버추얼 프라이빗 클라우드(VPC) 환경 내에서 쿠버네티스를 위한
간단하고, 호스트 로컬, 낮은 레이턴시, 높은 처리량 및 호환 네트워킹 스택을 제공하는
CNI와 IPAM 플러그인 셋을 포함한다.
플러그인은 VPC 내에서 구성하고 배포할 수 있도록 간단하게 설계되었다.
Kubelets는 오버레이 네트워크 관리, BGP 관리, 소스/대상 확인 비활성화 또는
VPC 라우팅 테이블을 조정하여 각 호스트에 인스턴스별 서브넷을
제공(VPC별 50-100개 항목으로 제한)하는 등의 자주 권장되는 복잡성을 요구하지 않고
부팅한 다음 필요에 따라 IP 사용량을 자체 구성하고 확장할
수 있다. 즉, cni-ipvlan-vpc-k8s는 AWS 내에서 쿠버네티스를
대규모로 배포하는 데 필요한 네트워크 복잡성을 크게 줄인다.
Coil
Coil은 통합이 용이하도록 설계된 CNI 플러그인으로 유연한 이그레스(egress) 네트워킹을 제공한다.
Coil은 베어메탈에 비해 낮은 오버헤드로 작동하며, 외부 네트워크에 대해 임의의 이그레스 NAT 게이트웨이를 정의할 수 있다.
콘티브(Contiv)
콘티브는 다양한 적용 사례에서 구성 가능한 네트워킹(BGP를 사용하는 네이티브 L3, vxlan을 사용하는 오버레이, 클래식 L2 또는 Cisco-SDN/ACI)을 제공한다.
콘트레일(Contrail) / 텅스텐 패브릭(Tungsten Fabric)
텅스텐 패브릭을 기반으로 하는 콘트레일은 진정한 개방형 멀티 클라우드 네트워크 가상화 및 정책 관리 플랫폼이다. 콘트레일 및 텅스텐 패브릭은 쿠버네티스, OpenShift, OpenStack 및 Mesos와 같은 다양한 오케스트레이션 시스템과 통합되어 있으며, 가상 머신, 컨테이너/파드 및 베어메탈 워크로드에 대해 서로 다른 격리 모드를 제공한다.
DANM
DANM은 쿠버네티스 클러스터에서 실행되는 통신사 워크로드를 위한 네트워킹 솔루션이다. 다음의 컴포넌트로 구성된다.
- 고급 기능들로 IPVLAN 인터페이스를 프로비저닝할 수 있는 CNI 플러그인
- 여러 클러스터 전체의 불연속 L3 네트워크를 관리하고 요청 시 동적, 정적 또는 IP를 할당하지 않는 방식을 제공하는 내장 IPAM 모듈
- 자체 CNI를 통해서, 또는 SRI-OV나 플라넬과 같은 널리 사용되는 CNI 솔루션에 잡을 동시에 위임하여 여러 네트워크 인터페이스를 컨테이너에 연결할 수 있는 CNI 메타플러그인
- 모든 쿠버네티스 호스트의 VxLAN 및 VLAN 인터페이스를 중앙에서 관리할 수 있는 쿠버네티스 컨트롤러
- 쿠버네티스의 서비스 기반의 서비스 검색 개념을 확장하여 파드의 모든 네트워크 인터페이스에서 작동하는 다른 쿠버네티스 컨트롤러
이 도구 셋을 통해 DANM은 여러 개의 분리된 네트워크 인터페이스를 제공할 수 있으며, 파드에 다른 네트워킹 백엔드 및 고급 IPAM 기능을 사용할 수 있다.
플라넬
플라넬은 쿠버네티스 요구 사항을
충족하는 매우 간단한 오버레이 네트워크이다. 많은
경우에 쿠버네티스와 플라넬은 성공적으로 적용이 가능하다.
Google 컴퓨트 엔진(GCE)
Google 컴퓨트 엔진 클러스터 구성 스크립트의 경우, 고급
라우팅을 사용하여
각 VM에 서브넷을 할당한다(기본값은 /24
- 254개 IP). 해당 서브넷에 바인딩된
모든 트래픽은 GCE 네트워크 패브릭에 의해 VM으로 직접 라우팅된다. 이는
아웃 바운드 인터넷 접근을 위해 NAT로 구성된 VM에 할당된 "기본"
IP 주소에 추가된다. 리눅스 브릿지(cbr0
)는 해당 서브넷에 존재하도록
구성되며, 도커의 --bridge
플래그로 전달된다.
도커는 다음의 설정으로 시작한다.
DOCKER_OPTS="--bridge=cbr0 --iptables=false --ip-masq=false"
이 브릿지는 노드의 .spec.podCIDR
에 따라 Kubelet(--network-plugin=kubenet
플래그로 제어되는)에 의해 생성된다.
도커는 이제 cbr-cidr
블록에서 IP를 할당한다. 컨테이너는 cbr0
브릿지를
통해 서로 Node
에 도달할 수 있다. 이러한 IP는 모두 GCE 프로젝트 네트워크
내에서 라우팅할 수 있다.
그러나, GCE 자체는 이러한 IP에 대해 전혀 알지 못하므로, 아웃 바운드 인터넷 트래픽을 위해
IP를 NAT하지 않는다. 그것을 달성하기 위해 iptables 규칙을 사용하여
GCE 프로젝트 네트워크(10.0.0.0/8) 외부의 IP에 바인딩된 트래픽을
마스커레이드(일명 SNAT - 마치 패킷이 Node
자체에서 온 것처럼
보이게 함)한다.
iptables -t nat -A POSTROUTING ! -d 10.0.0.0/8 -o eth0 -j MASQUERADE
마지막으로 커널에서 IP 포워딩이 활성화되어 있으므로, 커널은 브릿지된 컨테이너에
대한 패킷을 처리한다.
sysctl net.ipv4.ip_forward=1
이 모든 것의 결과는 모든 Pod
가 서로에게 도달할 수 있고 인터넷으로 트래픽을
송신할 수 있다는 것이다.
재규어(Jaguar)
재규어는 OpenDaylight 기반의 쿠버네티스 네트워크를 위한 오픈소스 솔루션이다. 재규어는 vxlan을 사용하여 오버레이 네트워크를 제공하고 재규어 CNI 플러그인은 파드별로 하나의 IP 주소를 제공한다.
k-vswitch
k-vswitch는 Open vSwitch 기반의 간단한 쿠버네티스 네트워킹 플러그인이다. Open vSwitch의 기존 기능을 활용하여 운영하기 쉽고, 성능이 뛰어나고 안전한 강력한 네트워킹 플러그인을 제공한다.
Knitter
Knitter는 쿠버네티스에서 여러 네트워킹을 지원하는 네트워크 솔루션이다. 테넌트 관리 및 네트워크 관리 기능을 제공한다. Knitter에는 애플리케이션의 IP 주소 유지, IP 주소 마이그레이션 등과 같은 여러 네트워크 플레인 외에 엔드-투-엔드 NFV 컨테이너 네트워킹 솔루션 셋이 포함되어 있다.
Kube-OVN
Kube-OVN은 기업을 위한 OVN 기반 쿠버네티스 네트워크 패브릭이다. OVN/OVS의 도움으로, 서브넷, QoS, 고정 IP 할당, 트래픽 미러링, 게이트웨이, 오픈플로우 기반 네트워크 정책 및 서비스 프록시와 같은 고급 오버레이 네트워크 기능을 제공한다.
Kube-router
kube-router는 쿠버네티스를 위한 특수 목적의 네트워킹 솔루션으로 고성능 및 운영 단순성을 제공한다. 큐브 라우터는 리눅스 LVS/IPVS 기반 서비스 프록시, 오버레이가 없는 리눅스 커널 포워딩 기반의 파드 간 네트워킹 솔루션 그리고 iptables/ipset 기반 네트워크 정책 집행도구를 제공한다.
L2 네트워크 및 리눅스 브릿지
"베어메탈" 환경의 간단한 스위치와 같은 "더미(dumb)" L2 네트워크가 있는 경우,
위의 GCE 설정과 비슷한 작업을 수행할 수 있어야 한다.
이 방법은 매우 우연히 시도되었고 작동하는 것으로 보이지만
철저히 테스트되지 않았다. 이 기술을 사용하여
프로세스를 완료한 경우, 알려주길 바란다.
Lars Kellogg-Stedman이 제공하는
이 훌륭한 튜토리얼의
"With Linux Bridge devices" 섹션을 참고한다.
Multus(멀티 네트워크 플러그인)
Multus는 쿠버네티스의 CRD 기반 네트워크 오브젝트를 사용하여 쿠버네티스에서 멀티 네트워킹 기능을 지원하는 멀티 CNI 플러그인이다.
Multus는 CNI 명세를 구현하는 모든 레퍼런스 플러그인(예: 플라넬, DHCP, Macvlan) 및 써드파티 플러그인(예: 캘리코, 위브(Weave), 실리움, 콘티브)을 지원한다. 또한, Multus는 쿠버네티스의 클라우드 네이티브 애플리케이션과 NFV 기반 애플리케이션을 통해 쿠버네티스의 SRIOV, DPDK, OVS-DPDK 및 VPP 워크로드를 지원한다.
OVN4NFV-K8s-Plugin (OVN 기반의 CNI 컨트롤러 & 플러그인)
OVN4NFV-K8S-Plugin은 OVN 기반의 CNI 컨트롤러 플러그인으로 클라우드 네이티브 기반 서비스 기능 체인(Service function chaining(SFC)), 다중 OVN 오버레이 네트워킹, 동적 서브넷 생성, 동적 가상 네트워크 생성, VLAN 공급자 네트워크, 직접 공급자 네트워크와 멀티 클러스터 네트워킹의 엣지 기반 클라우드 등 네이티브 워크로드에 이상적인 멀티 네티워크 플러그인이다.
NSX-T
VMware NSX-T는 네트워크 가상화 및 보안 플랫폼이다. NSX-T는 멀티 클라우드 및 멀티 하이퍼바이저 환경에 네트워크 가상화를 제공할 수 있으며 이기종 엔드포인트와 기술 스택이 있는 새로운 애플리케이션 프레임워크 및 아키텍처에 중점을 둔다. vSphere 하이퍼바이저 외에도, 이러한 환경에는 KVM, 컨테이너 및 베어메탈과 같은 다른 하이퍼바이저가 포함된다.
NSX-T 컨테이너 플러그인(NCP)은 NSX-T와 쿠버네티스와 같은 컨테이너 오케스트레이터 사이의 통합은 물론, NSX-T와 Pivotal 컨테이너 서비스(PKS) 및 OpenShift와 같은 컨테이너 기반 CaaS/PaaS 플랫폼 간의 통합을 제공한다.
OpenVSwitch
OpenVSwitch는 다소 성숙하지만
오버레이 네트워크를 구축하는 복잡한 방법이다. 이것은 네트워킹 분야의 몇몇
"대형 벤더"에 의해 승인되었다.
OVN(오픈 버추얼 네트워킹)
OVN은 Open vSwitch 커뮤니티에서 개발한 오픈소스 네트워크
가상화 솔루션이다. 논리적 스위치, 논리적 라우터, 스테이트풀 ACL, 로드 밸런서 등을 생성하여
서로 다른 가상 네트워킹 토폴로지를 구축할 수 있다. 이 프로젝트에는
ovn-kubernetes에
특정 쿠버네티스 플러그인 및 문서가 있다.
로마나
로마나는 오버레이 네트워크 없이 쿠버네티스를 배포할 수 있는 오픈소스 네트워크 및 보안 자동화 솔루션이다. 로마나는 쿠버네티스 네트워크 폴리시를 지원하여 네트워크 네임스페이스에서 격리를 제공한다.
Weaveworks의 위브넷
위브넷은
쿠버네티스 및 호스팅된 애플리케이션을 위한 탄력적이고 사용하기 쉬운 네트워크이다.
위브넷은 CNI 플러그인 또는
독립형으로 실행된다. 두 버전에서, 실행하기 위해 구성이나 추가 코드가 필요하지 않으며,
두 경우 모두, 쿠버네티스의 표준과 같이 네트워크에서 파드별로 하나의 IP 주소를 제공한다.
다음 내용
네트워크 모델의 초기 설계와 그 근거 및 미래의 계획은
네트워킹 디자인 문서에
자세히 설명되어 있다.
4 - 로깅 아키텍처
애플리케이션 로그는 애플리케이션 내부에서 발생하는 상황을 이해하는 데 도움이 된다. 로그는 문제를 디버깅하고 클러스터 활동을 모니터링하는 데 특히 유용하다. 대부분의 최신 애플리케이션에는 일종의 로깅 메커니즘이 있다. 마찬가지로, 컨테이너 엔진들도 로깅을 지원하도록 설계되었다. 컨테이너화된 애플리케이션에 가장 쉽고 가장 널리 사용되는 로깅 방법은 표준 출력과 표준 에러 스트림에 작성하는 것이다.
그러나, 일반적으로 컨테이너 엔진이나 런타임에서 제공하는 기본 기능은 완전한 로깅 솔루션으로 충분하지 않다.
예를 들어, 컨테이너가 크래시되거나, 파드가 축출되거나, 노드가 종료된 경우에도 애플리케이션의 로그에 접근하고 싶을 것이다.
클러스터에서 로그는 노드, 파드 또는 컨테이너와는 독립적으로 별도의 스토리지와 라이프사이클을 가져야 한다. 이 개념을 클러스터-레벨-로깅 이라고 한다.
클러스터-레벨 로깅은 로그를 저장, 분석, 쿼리하기 위해서는 별도의 백엔드가 필요하다. 쿠버네티스가
로그 데이터를 위한 네이티브 스토리지 솔루션을 제공하지는 않지만,
쿠버네티스에 통합될 수 있는 기존의 로깅 솔루션이 많이 있다.
쿠버네티스의 기본 로깅
이 예시는 텍스트를 초당 한 번씩 표준 출력에 쓰는
컨테이너에 대한 Pod
명세를 사용한다.
apiVersion: v1
kind: Pod
metadata:
name: counter
spec:
containers:
- name: count
image: busybox
args: [/bin/sh, -c,
'i=0; while true; do echo "$i: $(date)"; i=$((i+1)); sleep 1; done']
이 파드를 실행하려면, 다음의 명령을 사용한다.
kubectl apply -f https://k8s.io/examples/debug/counter-pod.yaml
출력은 다음과 같다.
로그를 가져오려면, 다음과 같이 kubectl logs
명령을 사용한다.
출력은 다음과 같다.
0: Mon Jan 1 00:00:00 UTC 2001
1: Mon Jan 1 00:00:01 UTC 2001
2: Mon Jan 1 00:00:02 UTC 2001
...
kubectl logs --previous
를 사용해서 컨테이너의 이전 인스턴스에 대한 로그를 검색할 수 있다. 파드에 여러 컨테이너가 있는 경우, 명령에 컨테이너 이름을 추가하여 접근하려는 컨테이너 로그를 지정해야 한다. 자세한 내용은 kubectl logs
문서를 참조한다.
노드 레벨에서의 로깅
컨테이너화된 애플리케이션의 stdout(표준 출력)
및 stderr(표준 에러)
스트림에 의해 생성된 모든 출력은 컨테이너 엔진이 처리 및 리디렉션 한다.
예를 들어, 도커 컨테이너 엔진은 이 두 스트림을 로깅 드라이버로 리디렉션 한다. 이 드라이버는 쿠버네티스에서 JSON 형식의 파일에 작성하도록 구성된다.
참고: 도커 JSON 로깅 드라이버는 각 라인을 별도의 메시지로 취급한다. 도커 로깅 드라이버를 사용하는 경우, 멀티-라인 메시지를 직접 지원하지 않는다. 로깅 에이전트 레벨 이상에서 멀티-라인 메시지를 처리해야 한다.
기본적으로, 컨테이너가 다시 시작되면, kubelet은 종료된 컨테이너 하나를 로그와 함께 유지한다. 파드가 노드에서 축출되면, 해당하는 모든 컨테이너도 로그와 함께 축출된다.
노드-레벨 로깅에서 중요한 고려 사항은 로그 로테이션을 구현하여,
로그가 노드에서 사용 가능한 모든 스토리지를 사용하지 않도록 하는 것이다. 쿠버네티스는
로그 로테이션에 대한 의무는 없지만, 디플로이먼트 도구로
이를 해결하기 위한 솔루션을 설정해야 한다.
예를 들어, kube-up.sh
스크립트에 의해 배포된 쿠버네티스 클러스터에는,
매시간 실행되도록 구성된 logrotate
도구가 있다. 애플리케이션의 로그를 자동으로
로테이션하도록 컨테이너 런타임을 설정할 수도 있다.
예를 들어, kube-up.sh
가 GCP의 COS 이미지 로깅을 설정하는 방법은
configure-helper
스크립트를 통해
자세히 알 수 있다.
CRI 컨테이너 런타임 을 사용할 때, kubelet은 로그를 로테이션하고 로깅 디렉터리 구조를 관리한다.
kubelet은 이 정보를 CRI 컨테이너 런타임에 전송하고 런타임은 컨테이너 로그를 지정된 위치에 기록한다.
kubelet config file에 있는
두 개의 kubelet 파라미터 containerLogMaxSize
및 containerLogMaxFiles
를
사용하여 각 로그 파일의 최대 크기와 각 컨테이너에 허용되는 최대 파일 수를 각각 구성할 수 있다.
기본 로깅 예제에서와 같이 kubectl logs
를
실행하면, 노드의 kubelet이 요청을 처리하고
로그 파일에서 직접 읽는다. kubelet은 로그 파일의 내용을 반환한다.
참고: 만약, 일부 외부 시스템이 로테이션을 수행했거나 CRI 컨테이너 런타임이 사용된 경우,
kubectl logs
를 통해 최신 로그 파일의 내용만
사용할 수 있다. 예를 들어, 10MB 파일이 있으면, logrotate
가
로테이션을 수행하고 두 개의 파일이 생긴다. (크기가 10MB인 파일 하나와 비어있는 파일)
kubectl logs
는 이 예시에서는 빈 응답에 해당하는 최신 로그 파일을 반환한다.
시스템 컴포넌트 로그
시스템 컴포넌트에는 컨테이너에서 실행되는 것과 컨테이너에서 실행되지 않는 두 가지 유형이 있다.
예를 들면 다음과 같다.
- 쿠버네티스 스케줄러와 kube-proxy는 컨테이너에서 실행된다.
- Kubelet과 컨테이너 런타임은 컨테이너에서 실행되지 않는다.
systemd를 사용하는 시스템에서는, kubelet과 컨테이너 런타임은 journald에 작성한다.
systemd를 사용하지 않으면, kubelet과 컨테이너 런타임은 /var/log
디렉터리의
.log
파일에 작성한다. 컨테이너 내부의 시스템 컴포넌트는 기본 로깅 메커니즘을 무시하고,
항상 /var/log
디렉터리에 기록한다.
시스템 컴포넌트는 klog
로깅 라이브러리를 사용한다. 로깅에 대한 개발 문서에서
해당 컴포넌트의 로깅 심각도(severity)에 대한 규칙을 찾을 수 있다.
컨테이너 로그와 마찬가지로, /var/log
디렉터리의 시스템 컴포넌트 로그를
로테이트해야 한다. kube-up.sh
스크립트로 구축한 쿠버네티스 클러스터에서
로그는 매일 또는 크기가 100MB를 초과하면
logrotate
도구에 의해 로테이트가 되도록 구성된다.
클러스터 레벨 로깅 아키텍처
쿠버네티스는 클러스터-레벨 로깅을 위한 네이티브 솔루션을 제공하지 않지만, 고려해야 할 몇 가지 일반적인 접근 방법을 고려할 수 있다. 여기 몇 가지 옵션이 있다.
- 모든 노드에서 실행되는 노드-레벨 로깅 에이전트를 사용한다.
- 애플리케이션 파드에 로깅을 위한 전용 사이드카 컨테이너를 포함한다.
- 애플리케이션 내에서 로그를 백엔드로 직접 푸시한다.
노드 로깅 에이전트 사용
각 노드에 노드-레벨 로깅 에이전트 를 포함시켜 클러스터-레벨 로깅을 구현할 수 있다. 로깅 에이전트는 로그를 노출하거나 로그를 백엔드로 푸시하는 전용 도구이다. 일반적으로, 로깅 에이전트는 해당 노드의 모든 애플리케이션 컨테이너에서 로그 파일이 있는 디렉터리에 접근할 수 있는 컨테이너이다.
로깅 에이전트는 모든 노드에서 실행되어야 하므로, 에이전트를
DaemonSet
으로 동작시키는 것을 추천한다.
노드-레벨 로깅은 노드별 하나의 에이전트만 생성하며, 노드에서 실행되는 애플리케이션에 대한 변경은 필요로 하지 않는다.
컨테이너는 stdout과 stderr를 동의되지 않은 포맷으로 작성한다. 노드-레벨 에이전트는 이러한 로그를 수집하고 취합을 위해 전달한다.
로깅 에이전트와 함께 사이드카 컨테이너 사용
다음 중 한 가지 방법으로 사이드카 컨테이너를 사용할 수 있다.
- 사이드카 컨테이너는 애플리케이션 로그를 자체
stdout
으로 스트리밍한다.
- 사이드카 컨테이너는 로깅 에이전트를 실행하며, 애플리케이션 컨테이너에서 로그를 가져오도록 구성된다.
사이드카 컨테이너 스트리밍
사이드카 컨테이너가 자체 stdout
및 stderr
스트림으로
쓰도록 하면, 각 노드에서 이미 실행 중인 kubelet과 로깅 에이전트를
활용할 수 있다. 사이드카 컨테이너는 파일, 소켓 또는 journald에서 로그를 읽는다.
각 사이드카 컨테이너는 자체 stdout
또는 stderr
스트림에 로그를 출력한다.
이 방법을 사용하면 애플리케이션의 다른 부분에서 여러 로그 스트림을
분리할 수 있고, 이 중 일부는 stdout
또는 stderr
에
작성하기 위한 지원이 부족할 수 있다. 로그를 리디렉션하는 로직은
최소화되어 있기 때문에, 심각한 오버헤드가 아니다. 또한,
stdout
및 stderr
가 kubelet에서 처리되므로, kubectl logs
와 같은
빌트인 도구를 사용할 수 있다.
예를 들어, 파드는 단일 컨테이너를 실행하고, 컨테이너는
서로 다른 두 가지 형식을 사용하여 서로 다른 두 개의 로그 파일에 기록한다. 파드에 대한
구성 파일은 다음과 같다.
apiVersion: v1
kind: Pod
metadata:
name: counter
spec:
containers:
- name: count
image: busybox
args:
- /bin/sh
- -c
- >
i=0;
while true;
do
echo "$i: $(date)" >> /var/log/1.log;
echo "$(date) INFO $i" >> /var/log/2.log;
i=$((i+1));
sleep 1;
done
volumeMounts:
- name: varlog
mountPath: /var/log
volumes:
- name: varlog
emptyDir: {}
두 컴포넌트를 컨테이너의 stdout
스트림으로 리디렉션한 경우에도, 동일한 로그
스트림에 서로 다른 형식의 로그 항목을 작성하는 것은
추천하지 않는다. 대신, 두 개의 사이드카 컨테이너를 생성할 수 있다. 각 사이드카
컨테이너는 공유 볼륨에서 특정 로그 파일을 테일(tail)한 다음 로그를
자체 stdout
스트림으로 리디렉션할 수 있다.
다음은 사이드카 컨테이너가 두 개인 파드에 대한 구성 파일이다.
apiVersion: v1
kind: Pod
metadata:
name: counter
spec:
containers:
- name: count
image: busybox
args:
- /bin/sh
- -c
- >
i=0;
while true;
do
echo "$i: $(date)" >> /var/log/1.log;
echo "$(date) INFO $i" >> /var/log/2.log;
i=$((i+1));
sleep 1;
done
volumeMounts:
- name: varlog
mountPath: /var/log
- name: count-log-1
image: busybox
args: [/bin/sh, -c, 'tail -n+1 -f /var/log/1.log']
volumeMounts:
- name: varlog
mountPath: /var/log
- name: count-log-2
image: busybox
args: [/bin/sh, -c, 'tail -n+1 -f /var/log/2.log']
volumeMounts:
- name: varlog
mountPath: /var/log
volumes:
- name: varlog
emptyDir: {}
이제 이 파드를 실행하면, 다음의 명령을 실행하여 각 로그 스트림에
개별적으로 접근할 수 있다.
kubectl logs counter count-log-1
출력은 다음과 같다.
0: Mon Jan 1 00:00:00 UTC 2001
1: Mon Jan 1 00:00:01 UTC 2001
2: Mon Jan 1 00:00:02 UTC 2001
...
kubectl logs counter count-log-2
출력은 다음과 같다.
Mon Jan 1 00:00:00 UTC 2001 INFO 0
Mon Jan 1 00:00:01 UTC 2001 INFO 1
Mon Jan 1 00:00:02 UTC 2001 INFO 2
...
클러스터에 설치된 노드-레벨 에이전트는 추가 구성없이
자동으로 해당 로그 스트림을 선택한다. 원한다면, 소스 컨테이너에
따라 로그 라인을 파싱(parse)하도록 에이전트를 구성할 수 있다.
참고로, CPU 및 메모리 사용량이 낮음에도 불구하고(cpu에 대한 몇 밀리코어의
요구와 메모리에 대한 몇 메가바이트의 요구), 로그를 파일에 기록한 다음
stdout
으로 스트리밍하면 디스크 사용량은 두 배가 될 수 있다. 단일 파일에
쓰는 애플리케이션이 있는 경우, 일반적으로 스트리밍
사이드카 컨테이너 방식을 구현하는 대신 /dev/stdout
을 대상으로
설정하는 것을 추천한다.
사이드카 컨테이너를 사용하여 애플리케이션 자체에서 로테이션할 수 없는
로그 파일을 로테이션할 수도 있다. 이 방법의 예시는 정기적으로 logrotate
를 실행하는 작은 컨테이너를 두는 것이다.
그러나, stdout
및 stderr
을 직접 사용하고 로테이션과
유지 정책을 kubelet에 두는 것이 권장된다.
로깅 에이전트가 있는 사이드카 컨테이너
노드-레벨 로깅 에이전트가 상황에 맞게 충분히 유연하지 않은 경우,
애플리케이션과 함께 실행하도록 특별히 구성된 별도의 로깅 에이전트를 사용하여
사이드카 컨테이너를 생성할 수 있다.
참고: 사이드카 컨테이너에서 로깅 에이전트를 사용하면
상당한 리소스 소비로 이어질 수 있다. 게다가, kubelet에 의해
제어되지 않기 때문에, kubectl logs
를 사용하여 해당 로그에
접근할 수 없다.
여기에 로깅 에이전트가 포함된 사이드카 컨테이너를 구현하는 데 사용할 수 있는 두 가지 구성 파일이 있다. 첫 번째 파일에는
fluentd를 구성하기 위한 ConfigMap
이 포함되어 있다.
apiVersion: v1
kind: ConfigMap
metadata:
name: fluentd-config
data:
fluentd.conf: |
<source>
type tail
format none
path /var/log/1.log
pos_file /var/log/1.log.pos
tag count.format1
</source>
<source>
type tail
format none
path /var/log/2.log
pos_file /var/log/2.log.pos
tag count.format2
</source>
<match **>
type google_cloud
</match>
참고: fluentd를 구성하는 것에 대한 자세한 내용은,
fluentd 문서를 참고한다.
두 번째 파일은 fluentd가 실행되는 사이드카 컨테이너가 있는 파드를 설명한다.
파드는 fluentd가 구성 데이터를 가져올 수 있는 볼륨을 마운트한다.
apiVersion: v1
kind: Pod
metadata:
name: counter
spec:
containers:
- name: count
image: busybox
args:
- /bin/sh
- -c
- >
i=0;
while true;
do
echo "$i: $(date)" >> /var/log/1.log;
echo "$(date) INFO $i" >> /var/log/2.log;
i=$((i+1));
sleep 1;
done
volumeMounts:
- name: varlog
mountPath: /var/log
- name: count-agent
image: k8s.gcr.io/fluentd-gcp:1.30
env:
- name: FLUENTD_ARGS
value: -c /etc/fluentd-config/fluentd.conf
volumeMounts:
- name: varlog
mountPath: /var/log
- name: config-volume
mountPath: /etc/fluentd-config
volumes:
- name: varlog
emptyDir: {}
- name: config-volume
configMap:
name: fluentd-config
이 예시 구성에서, 사용자는 애플리케이션 컨테이너 내의 모든 소스을 읽는 fluentd를 다른 로깅 에이전트로 대체할 수 있다.
애플리케이션에서 직접 로그 노출
애플리케이션에서 직접 로그를 노출하거나 푸시하는 클러스터-로깅은 쿠버네티스의 범위를 벗어난다.
5 - 시스템 로그
시스템 컴포넌트 로그는 클러스터에서 발생하는 이벤트를 기록하며, 이는 디버깅에 아주 유용하다.
더 많거나 적은 세부 정보를 표시하도록 다양하게 로그를 설정할 수 있다.
로그는 컴포넌트 내에서 오류를 표시하는 것 처럼 간단하거나, 이벤트의 단계적 추적(예: HTTP 엑세스 로그, 파드의 상태 변경, 컨트롤러 작업 또는 스케줄러의 결정)을 표시하는 것처럼 세밀할 수 있다.
Klog
klog는 쿠버네티스의 로깅 라이브러리다. klog
는 쿠버네티스 시스템 컴포넌트의 로그 메시지를 생성한다.
klog 설정에 대한 더 많은 정보는, 커맨드라인 툴을 참고한다.
klog 네이티브 형식 예 :
I1025 00:15:15.525108 1 httplog.go:79] GET /api/v1/namespaces/kube-system/pods/metrics-server-v0.3.1-57c75779f-9p8wg: (1.512ms) 200 [pod_nanny/v0.0.0 (linux/amd64) kubernetes/$Format 10.56.1.19:51756]
구조화된 로깅
FEATURE STATE: Kubernetes v1.19 [alpha]
경고: 구조화된 로그메시지로 마이그레이션은 진행중인 작업이다. 이 버전에서는 모든 로그 메시지가 구조화되지 않는다. 로그 파일을
파싱할 때, 구조화되지 않은 로그 메시지도 처리해야 한다.
로그 형식 및 값 직렬화는 변경될 수 있다.
구조화된 로깅은 로그 메시지에 통일된 구조를 적용하여 정보를 쉽게 추출하고,
로그를 보다 쉽고 저렴하게 저장하고 처리하는 작업이다.
새로운 메시지 형식은 이전 버전과 호환되며 기본적으로 활성화 된다.
구조화된 로그 형식:
<klog header> "<message>" <key1>="<value1>" <key2>="<value2>" ...
예시:
I1025 00:15:15.525108 1 controller_utils.go:116] "Pod status updated" pod="kube-system/kubedns" status="ready"
JSON 로그 형식
FEATURE STATE: Kubernetes v1.19 [alpha]
경고: JSON 출력은 많은 표준 klog 플래그를 지원하지 않는다. 지원하지 않는 klog 플래그 목록은, 커맨드라인 툴을 참고한다.
모든 로그가 JSON 형식으로 작성되는 것은 아니다(예: 프로세스 시작 중). 로그를 파싱하려는 경우
JSON 형식이 아닌 로그 행을 처리할 수 있는지 확인해야 한다.
필드 이름과 JSON 직렬화는 변경될 수 있다.
--logging-format=json
플래그는 로그 형식을 klog 기본 형식에서 JSON 형식으로 변경한다.
JSON 로그 형식 예시(보기좋게 출력된 형태):
{
"ts": 1580306777.04728,
"v": 4,
"msg": "Pod status updated",
"pod":{
"name": "nginx-1",
"namespace": "default"
},
"status": "ready"
}
특별한 의미가 있는 키:
ts
- Unix 시간의 타임스탬프 (필수, 부동 소수점)
v
- 자세한 정도 (필수, 정수, 기본 값 0)
err
- 오류 문자열 (선택 사항, 문자열)
msg
- 메시지 (필수, 문자열)
현재 JSON 형식을 지원하는 컴포넌트 목록:
로그 정리(sanitization)
FEATURE STATE: Kubernetes v1.20 [alpha]
경고: 로그 정리(sanitization)는 상당한 오버 헤드를 발생시킬 수 있으므로 프로덕션 환경에서는 사용하지 않아야한다.
--experimental-logging-sanitization
플래그는 klog 정리(sanitization) 필터를 활성화 한다.
활성화된 경우 모든 로그 인자에서 민감한 데이터(예: 비밀번호, 키, 토큰)가 표시된 필드를 검사하고
이러한 필드의 로깅이 방지된다.
현재 로그 정리(sanitization)를 지원하는 컴포넌트 목록:
- kube-controller-manager
- kube-apiserver
- kube-scheduler
- kubelet
참고: 로그 정리(sanitization) 필터는 사용자 작업 로그로부터 민감한 데이터가 유출되는 것을 방지할 수 없다.
로그 상세 레벨(verbosity)
-v
플래그로 로그 상세 레벨(verbosity)을 제어한다. 값을 늘리면 기록된 이벤트 수가 증가한다. 값을 줄이면
기록된 이벤트 수가 줄어든다.
로그 상세 레벨(verbosity)를 높이면 점점 덜 심각한 이벤트가 기록된다. 로그 상세 레벨(verbosity)을 0으로 설정하면 중요한 이벤트만 기록된다.
로그 위치
시스템 컴포넌트에는 컨테이너에서 실행되는 것과 컨테이너에서 실행되지 않는 두 가지 유형이 있다. 예를 들면 다음과 같다.
- 쿠버네티스 스케줄러와 kube-proxy는 컨테이너에서 실행된다.
- kubelet과 컨테이너 런타임(예: 도커)은 컨테이너에서 실행되지 않는다.
systemd를 사용하는 시스템에서는, kubelet과 컨테이너 런타임은 jounald에 기록한다.
그 외 시스템에서는, /var/log
디렉터리의 .log
파일에 기록한다.
컨테이너 내부의 시스템 컴포넌트들은 기본 로깅 메커니즘을 무시하고,
항상 /var/log
디렉터리의 .log
파일에 기록한다.
컨테이너 로그와 마찬가지로, /var/log
디렉터리의 시스템 컴포넌트 로그들은 로테이트해야 한다.
kube-up.sh
스크립트로 생성된 쿠버네티스 클러스터에서는, logrotate
도구로 로그가 로테이트되도록 설정된다.
logrotate
도구는 로그가 매일 또는 크기가 100MB 보다 클 때 로테이트된다.
다음 내용
6 - 쿠버네티스 시스템 컴포넌트에 대한 메트릭
시스템 컴포넌트 메트릭으로 내부에서 발생하는 상황을 더 잘 파악할 수 있다. 메트릭은 대시보드와 경고를 만드는 데 특히 유용하다.
쿠버네티스 컴포넌트의 메트릭은 프로메테우스 형식으로 출력된다.
이 형식은 구조화된 평문으로 디자인되어 있으므로 사람과 기계 모두가 쉽게 읽을 수 있다.
쿠버네티스의 메트릭
대부분의 경우 메트릭은 HTTP 서버의 /metrics
엔드포인트에서 사용할 수 있다. 기본적으로 엔드포인트를 노출하지 않는 컴포넌트의 경우 --bind-address
플래그를 사용하여 활성화할 수 있다.
해당 컴포넌트의 예는 다음과 같다.
프로덕션 환경에서는 이러한 메트릭을 주기적으로 수집하고 시계열 데이터베이스에서 사용할 수 있도록
프로메테우스 서버 또는 다른 메트릭 수집기(scraper)를 구성할 수 있다.
참고로 kubelet도 /metrics/cadvisor
, /metrics/resource
그리고 /metrics/probes
엔드포인트에서 메트릭을 노출한다. 이러한 메트릭은 동일한 라이프사이클을 가지지 않는다.
클러스터가 RBAC을 사용하는 경우, 메트릭을 읽으려면 /metrics
에 접근을 허용하는 클러스터롤(ClusterRole)을 가지는 사용자, 그룹 또는 서비스어카운트(ServiceAccount)를 통한 권한이 필요하다.
예를 들면, 다음과 같다.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: prometheus
rules:
- nonResourceURLs:
- "/metrics"
verbs:
- get
메트릭 라이프사이클
알파(Alpha) 메트릭 → 안정적인(Stable) 메트릭 → 사용 중단된(Deprecated) 메트릭 → 히든(Hidden) 메트릭 → 삭제된(Deleted) 메트릭
알파 메트릭은 안정성을 보장하지 않는다. 따라서 언제든지 수정되거나 삭제될 수 있다.
안정적인 메트릭은 변경되지 않는다는 것을 보장한다. 이것은 다음을 의미한다.
- 사용 중단 표기가 없는 안정적인 메트릭은, 이름이 변경되거나 삭제되지 않는다.
- 안정적인 메트릭의 유형(type)은 수정되지 않는다.
사용 중단된 메트릭은 해당 메트릭이 결국 삭제된다는 것을 나타내지만, 아직은 사용 가능하다는 뜻이다.
이 메트릭은 어느 버전에서부터 사용 중단된 것인지를 표시하는 어노테이션을 포함한다.
예를 들면,
# HELP some_counter this counts things
# TYPE some_counter counter
some_counter 0
# HELP some_counter (Deprecated since 1.15.0) this counts things
# TYPE some_counter counter
some_counter 0
히든 메트릭은 깔끔함(scraping)을 위해 더 이상 게시되지는 않지만, 여전히 사용은 가능하다. 히든 메트릭을 사용하려면, 히든 메트릭 표시 섹션을 참고한다.
삭제된 메트릭은 더 이상 게시되거나 사용할 수 없다.
히든 메트릭 표시
위에서 설명한 것처럼, 관리자는 특정 바이너리의 커맨드 라인 플래그를 통해 히든 메트릭을 활성화할 수 있다. 관리자가 지난 릴리스에서 사용 중단된 메트릭의 마이그레이션을 놓친 경우 관리자를 위한 임시방편으로 사용된다.
show-hidden-metrics-for-version
플래그는 해당 릴리스에서 사용 중단된 메트릭을 보여주려는 버전을 사용한다. 버전은 xy로 표시되며, 여기서 x는 메이저(major) 버전이고, y는 마이너(minor) 버전이다. 패치 릴리스에서 메트릭이 사용 중단될 수 있지만, 패치 버전은 필요하지 않다. 그 이유는 메트릭 사용 중단 정책이 마이너 릴리스에 대해 실행되기 때문이다.
플래그는 그 값으로 이전의 마이너 버전만 사용할 수 있다. 관리자가 이전 버전을 show-hidden-metrics-for-version
에 설정하면 이전 버전의 모든 히든 메트릭이 생성된다. 사용 중단 메트릭 정책을 위반하기 때문에 너무 오래된 버전은 허용되지 않는다.
1.n 버전에서 사용 중단되었다고 가정한 메트릭 A
를 예로 들어보겠다. 메트릭 사용 중단 정책에 따르면, 다음과 같은 결론에 도달할 수 있다.
1.n
릴리스에서는 메트릭이 사용 중단되었으며, 기본적으로 생성될 수 있다.
1.n+1
릴리스에서는 기본적으로 메트릭이 숨겨져 있으며, show-hidden-metrics-for-version=1.n
커맨드 라인에 의해서 생성될 수 있다.
1.n+2
릴리스에서는 코드베이스에서 메트릭이 제거되어야 한다. 더이상 임시방편은 존재하지 않는다.
릴리스 1.12
에서 1.13
으로 업그레이드 중이지만, 1.12
에서 사용 중단된 메트릭 A
를 사용하고 있다면, 커맨드 라인에서 --show-hidden-metrics=1.12
플래그로 히든 메트릭을 설정해야 하고, 1.14
로 업그레이드하기 전에 이 메트릭을 사용하지 않도록 의존성을 제거하는 것을 기억해야 한다.
액셀러레이터 메트릭 비활성화
kubelet은 cAdvisor를 통해 액셀러레이터 메트릭을 수집한다. NVIDIA GPU와 같은 액셀러레이터의 경우, 이러한 메트릭을 수집하기 위해 kubelet은 드라이버에 열린 핸들을 가진다. 이는 인프라 변경(예: 드라이버 업데이트)을 수행하기 위해 클러스터 관리자가 kubelet 에이전트를 중지해야 함을 의미한다.
액셀러레이터 메트릭을 수집하는 책임은 이제 kubelet이 아닌 공급 업체에 있다. 공급 업체는 메트릭을 수집하여 메트릭 서비스(예: 프로메테우스)에 노출할 컨테이너를 제공해야 한다.
[DisableAcceleratorUsageMetrics
기능 게이트](/ko/docs/reference/command-line-tools-reference/feature-gates/#알파-또는-베타-기능을-위한-기능-게이트:~:text= DisableAcceleratorUsageMetrics,-false)는 이 기능을 기본적으로 사용하도록 설정하는 타임라인를 사용하여 kubelet에서 수집한 메트릭을 비활성화한다.
컴포넌트 메트릭
kube-controller-manager 메트릭
컨트롤러 관리자 메트릭은 컨트롤러 관리자의 성능과 상태에 대한 중요한 인사이트를 제공한다.
이러한 메트릭에는 go_routine 수와 같은 일반적인 Go 언어 런타임 메트릭과
etcd 요청 대기 시간 또는 Cloudprovider(AWS, GCE, OpenStack) API 대기 시간과 같은 컨트롤러 특정 메트릭이 포함되어
클러스터의 상태를 측정하는 데 사용할 수 있다.
쿠버네티스 1.7부터 GCE, AWS, Vsphere 및 OpenStack의 스토리지 운영에 대한 상세한 Cloudprovider 메트릭을 사용할 수 있다.
이 메트릭은 퍼시스턴트 볼륨 동작의 상태를 모니터링하는 데 사용할 수 있다.
예를 들어, GCE의 경우 이러한 메트릭을 다음과 같이 호출한다.
cloudprovider_gce_api_request_duration_seconds { request = "instance_list"}
cloudprovider_gce_api_request_duration_seconds { request = "disk_insert"}
cloudprovider_gce_api_request_duration_seconds { request = "disk_delete"}
cloudprovider_gce_api_request_duration_seconds { request = "attach_disk"}
cloudprovider_gce_api_request_duration_seconds { request = "detach_disk"}
cloudprovider_gce_api_request_duration_seconds { request = "list_disk"}
kube-scheduler 메트릭
FEATURE STATE: Kubernetes v1.21 [beta]
스케줄러는 실행 중인 모든 파드의 요청(request)된 리소스와 요구되는 제한(limit)을 보고하는 선택적 메트릭을 노출한다. 이러한 메트릭은 용량 계획(capacity planning) 대시보드를 구축하고, 현재 또는 과거 스케줄링 제한을 평가하고, 리소스 부족으로 스케줄할 수 없는 워크로드를 빠르게 식별하고, 실제 사용량을 파드의 요청과 비교하는 데 사용할 수 있다.
kube-scheduler는 각 파드에 대해 구성된 리소스 요청과 제한을 식별한다. 요청 또는 제한이 0이 아닌 경우 kube-scheduler는 메트릭 시계열을 보고한다. 시계열에는 다음과 같은 레이블이 지정된다.
- 네임스페이스
- 파드 이름
- 파드가 스케줄된 노드 또는 아직 스케줄되지 않은 경우 빈 문자열
- 우선순위
- 해당 파드에 할당된 스케줄러
- 리소스 이름 (예:
cpu
)
- 알려진 경우 리소스 단위 (예:
cores
)
파드가 완료되면 (Never
또는 OnFailure
의 restartPolicy
가 있고 Succeeded
또는 Failed
파드 단계에 있거나, 삭제되고 모든 컨테이너가 종료된 상태에 있음) 스케줄러가 이제 다른 파드를 실행하도록 스케줄할 수 있으므로 시리즈가 더 이상 보고되지 않는다. 두 메트릭을 kube_pod_resource_request
및 kube_pod_resource_limit
라고 한다.
메트릭은 HTTP 엔드포인트 /metrics/resources
에 노출되며 스케줄러의 /metrics
엔드포인트
와 동일한 인증이 필요하다. 이러한 알파 수준의 메트릭을 노출시키려면 --show-hidden-metrics-for-version=1.20
플래그를 사용해야 한다.
메트릭 비활성화
커맨드 라인 플래그 --disabled-metrics
를 통해 메트릭을 명시적으로 끌 수 있다. 이 방법이 필요한 이유는 메트릭이 성능 문제를 일으키는 경우을 예로 들 수 있다. 입력값은 비활성화되는 메트릭 목록이다(예: --disabled-metrics=metric1,metric2
).
메트릭 카디널리티(cardinality) 적용
제한되지 않은 차원의 메트릭은 계측하는 컴포넌트에서 메모리 문제를 일으킬 수 있다. 리소스 사용을 제한하려면, --allow-label-value
커맨드 라인 옵션을 사용하여 메트릭 항목에 대한 레이블 값의 허용 목록(allow-list)을 동적으로 구성한다.
알파 단계에서, 플래그는 메트릭 레이블 허용 목록으로 일련의 매핑만 가져올 수 있다.
각 매핑은 <metric_name>,<label_name>=<allowed_labels>
형식이다. 여기서
<allowed_labels>
는 허용되는 레이블 이름의 쉼표로 구분된 목록이다.
전체 형식은 다음과 같다.
--allow-label-value <metric_name>,<label_name>='<allow_value1>, <allow_value2>...', <metric_name2>,<label_name>='<allow_value1>, <allow_value2>...', ...
.
예시는 다음과 같다.
--allow-label-value number_count_metric,odd_number='1,3,5', number_count_metric,even_number='2,4,6', date_gauge_metric,weekend='Saturday,Sunday'
다음 내용
7 - kubelet 가비지(Garbage) 수집 설정하기
가비지 수집은 사용되지 않는
이미지들과
컨테이너들을 정리하는 kubelet의 유용한 기능이다. Kubelet은
1분마다 컨테이너들에 대하여 가비지 수집을 수행하며, 5분마다 이미지들에 대하여 가비지 수집을 수행한다.
별도의 가비지 수집 도구들을 사용하는 것은, 이러한 도구들이 존재할 수도 있는 컨테이너들을 제거함으로써
kubelet을 중단시킬 수도 있으므로 권장하지 않는다.
이미지 수집
쿠버네티스는 cadvisor와 imageManager를 통하여 모든 이미지들의
라이프사이클을 관리한다.
이미지들에 대한 가비지 수집 정책은 다음의 2가지 요소를 고려한다.
HighThresholdPercent
와 LowThresholdPercent
. 임계값을 초과하는
디스크 사용량은 가비지 수집을 트리거 한다. 가비지 수집은 낮은 입계값에 도달 할 때까지 최근에 가장 적게 사용한
이미지들을 삭제한다.
컨테이너 수집
컨테이너에 대한 가비지 수집 정책은 세 가지 사용자 정의 변수들을 고려한다.
MinAge
는 컨테이너를 가비지 수집할 수 있는 최소 연령이다.
MaxPerPodContainer
는 모든 단일 파드(UID, 컨테이너 이름)
쌍이 가질 수 있는 최대 비활성 컨테이너의 수량이다.
MaxContainers
는 죽은 컨테이너의 최대 수량이다.
이러한 변수는 MinAge
를 0으로 설정하고,
MaxPerPodContainer
와 MaxContainers
를 각각 0 보다 작게 설정해서 비활성화할 수 있다.
Kubelet은 미확인, 삭제 또는 앞에서 언급한
플래그가 설정한 경계를 벗어나거나, 확인되지 않은 컨테이너에 대해 조치를 취한다.
일반적으로 가장 오래된 컨테이너가 먼저 제거된다. MaxPerPodContainer
와 MaxContainer
는
파드 당 최대
컨테이너 수(MaxPerPodContainer
)가 허용 가능한 범위의
전체 죽은 컨테이너의 수(MaxContainers
)를 벗어나는 상황에서 잠재적으로 서로 충돌할 수 있다.
다음의 상황에서 MaxPerPodContainer
가 조정된다.
최악의 시나리오는 MaxPerPodContainer
를 1로 다운그레이드하고
가장 오래된 컨테이너를 제거하는 것이다. 추가로, 삭제된 파드가 소유한 컨테이너는
MinAge
보다 오래되면 제거된다.
kubelet이 관리하지 않는 컨테이너는 컨테이너 가비지 수집 대상이 아니다.
사용자 설정
여러분은 후술될 kubelet 플래그들을 통하여 이미지 가비지 수집을 조정하기 위하여 다음의 임계값을 조정할 수 있다.
image-gc-high-threshold
, 이미지 가비지 수집을 발생시키는 디스크 사용량의 비율로
기본값은 85% 이다.
image-gc-low-threshold
, 이미지 가비지 수집을 더 이상 시도하지 않는 디스크 사용량의 비율로
기본값은 80% 이다.
다음의 kubelet 플래그를 통해 가비지 수집 정책을 사용자 정의할 수 있다.
minimum-container-ttl-duration
, 종료된 컨테이너가 가비지 수집
되기 전의 최소 시간. 기본 값은 0 분이며, 이 경우 모든 종료된 컨테이너는 바로 가비지 수집의 대상이 된다.
maximum-dead-containers-per-container
, 컨테이너가 보유할 수 있는 오래된
인스턴스의 최대 수. 기본 값은 1 이다.
maximum-dead-containers
, 글로벌하게 보유 할 컨테이너의 최대 오래된 인스턴스의 최대 수.
기본 값은 -1이며, 이 경우 인스턴스 수의 제한은 없다.
컨테이너들은 유용성이 만료되기 이전에도 가비지 수집이 될 수 있다. 이러한 컨테이너들은
문제 해결에 도움이 될 수 있는 로그나 다른 데이터를 포함하고 있을 수 있다. 컨테이너 당 적어도
1개의 죽은 컨테이너가 허용될 수 있도록 maximum-dead-containers-per-container
값을 충분히 큰 값으로 지정하는 것을 권장한다. 동일한 이유로 maximum-dead-containers
의 값도 상대적으로 더 큰 값을 권장한다.
자세한 내용은 해당 이슈를 참고한다.
사용 중단(Deprecation)
문서에 있는 몇 가지 kubelet의 가비지 수집 특징은 향후에 kubelet 축출(eviction) 기능으로 대체될 예정이다.
포함:
기존 Flag |
신규 Flag |
근거 |
--image-gc-high-threshold |
--eviction-hard or --eviction-soft |
기존의 축출 신호로 인하여 이미지 가비지 수집이 트리거 될 수 있음 |
--image-gc-low-threshold |
--eviction-minimum-reclaim |
축출 리클레임 기능이 동일한 행동을 수행 |
--maximum-dead-containers |
|
컨테이너의 외부 영역에 오래된 로그가 저장되어 사용중단(deprecated)됨 |
--maximum-dead-containers-per-container |
|
컨테이너의 외부 영역에 오래된 로그가 저장되어 사용중단(deprecated)됨 |
--minimum-container-ttl-duration |
|
컨테이너의 외부 영역에 오래된 로그가 저장되어 사용중단(deprecated)됨 |
--low-diskspace-threshold-mb |
--eviction-hard or eviction-soft |
축출이 다른 리소스에 대한 디스크 임계값을 일반화 함 |
--outofdisk-transition-frequency |
--eviction-pressure-transition-period |
축출이 다른 리소스로의 디스크 압력전환을 일반화 함 |
다음 내용
자세한 내용은 리소스 부족 처리 구성를
본다.
8 - 쿠버네티스에서 프락시(Proxy)
이 페이지는 쿠버네티스에서 함께 사용되는 프락시(Proxy)를 설명한다.
프락시
쿠버네티스를 이용할 때에 사용할 수 있는 여러 프락시가 있다.
-
kubectl proxy:
- 사용자의 데스크탑이나 파드 안에서 실행한다.
- 로컬 호스트 주소에서 쿠버네티스의 API 서버로 프락시한다.
- 클라이언트로 프락시는 HTTP를 사용한다.
- API 서버로 프락시는 HTTPS를 사용한다.
- API 서버를 찾는다.
- 인증 헤더를 추가한다.
-
apiserver proxy:
- API 서버에 내장된 요새(bastion)이다.
- 클러스터 외부의 사용자가 도달할 수 없는 클러스터 IP 주소로 연결한다.
- API 서버 프로세스에서 실행한다.
- 클라이언트로 프락시는 HTTPS(또는 API서버에서 HTTP로 구성된 경우는 HTTP)를 사용한다.
- 사용 가능한 정보를 이용하여 프락시에 의해 선택한 HTTP나 HTTPS를 사용할 수 있는 대상이다.
- 노드, 파드, 서비스에 도달하는데 사용할 수 있다.
- 서비스에 도달할 때에는 로드 밸런싱을 수행한다.
-
kube proxy:
- 각 노드에서 실행한다.
- UDP, TCP, SCTP를 이용하여 프락시 한다.
- HTTP는 이해하지 못한다.
- 로드 밸런싱을 제공한다.
- 서비스에 도달하는데만 사용한다.
-
API 서버 앞단의 프락시/로드밸런서
- 존재 및 구현은 클러스터 마다 다르다. (예: nginx)
- 모든 클라이언트와 하나 이상의 API 서버에 위치한다.
- 여러 API 서버가 있는 경우 로드 밸런서로서 작동한다.
-
외부 서비스의 클라우드 로드 밸런서
- 일부 클라우드 제공자는 제공한다. (예: AWS ELB, 구글 클라우드 로드 밸런서)
- 쿠버네티스 서비스로
LoadBalancer
유형이 있으면 자동으로 생성된다.
- 일반적으로 UDP/TCP만 지원한다.
- SCTP 지원은 클라우드 제공자의 구현에 달려 있다.
- 구현은 클라우드 제공자에 따라 다양하다.
쿠버네티스 사용자는 보통 처음 두 가지 유형 외의 것은 걱정할 필요없다.
클러스터 관리자는 일반적으로 후자의 유형이 올바르게 구성되었는지 확인한다.
요청을 리다이렉트하기
프락시는 리다이렉트 기능을 대체했다. 리다이렉트는 더 이상 사용하지 않는다.
9 - 애드온 설치
참고:
이 섹션은 쿠버네티스에 필요한 기능을 제공하는 써드파티 프로젝트와 관련이 있다. 쿠버네티스 프로젝트 작성자는 써드파티 프로젝트에 책임이 없다. 이 페이지는
CNCF 웹사이트 가이드라인에 따라 프로젝트를 알파벳 순으로 나열한다. 이 목록에 프로젝트를 추가하려면 변경사항을 제출하기 전에
콘텐츠 가이드를 읽어본다.
애드온은 쿠버네티스의 기능을 확장한다.
이 페이지는 사용 가능한 일부 애드온과 관련 설치 지침 링크를 나열한다.
네트워킹과 네트워크 폴리시
- ACI는 Cisco ACI로 통합 컨테이너 네트워킹 및 네트워크 보안을 제공한다.
- Antrea는 레이어 3/4에서 작동하여 쿠버네티스를 위한 네트워킹 및 보안 서비스를 제공하며, Open vSwitch를 네트워킹 데이터 플레인으로 활용한다.
- Calico는 네트워킹 및 네트워크 폴리시 제공자이다. Calico는 유연한 네트워킹 옵션을 지원하므로 BGP 유무에 관계없이 비-오버레이 및 오버레이 네트워크를 포함하여 가장 상황에 맞는 옵션을 선택할 수 있다. Calico는 동일한 엔진을 사용하여 서비스 메시 계층(service mesh layer)에서 호스트, 파드 및 (이스티오(istio)와 Envoy를 사용하는 경우) 애플리케이션에 대한 네트워크 폴리시를 적용한다.
- Canal은 Flannel과 Calico를 통합하여 네트워킹 및 네트워크 폴리시를 제공한다.
- Cilium은 L3 네트워크 및 네트워크 폴리시 플러그인으로 HTTP/API/L7 폴리시를 투명하게 시행할 수 있다. 라우팅 및 오버레이/캡슐화 모드를 모두 지원하며, 다른 CNI 플러그인 위에서 작동할 수 있다.
- CNI-Genie를 사용하면 쿠버네티스는 Calico, Canal, Flannel, Romana 또는 Weave와 같은 CNI 플러그인을 완벽하게 연결할 수 있다.
- Contiv는 다양한 유스케이스와 풍부한 폴리시 프레임워크를 위해 구성 가능한 네트워킹(BGP를 사용하는 네이티브 L3, vxlan을 사용하는 오버레이, 클래식 L2 그리고 Cisco-SDN/ACI)을 제공한다. Contiv 프로젝트는 완전히 오픈소스이다. 인스톨러는 kubeadm을 이용하거나, 그렇지 않은 경우에 대해서도 설치 옵션을 모두 제공한다.
- Contrail은 Tungsten Fabric을 기반으로 하며, 오픈소스이고, 멀티 클라우드 네트워크 가상화 및 폴리시 관리 플랫폼이다. Contrail과 Tungsten Fabric은 쿠버네티스, OpenShift, OpenStack 및 Mesos와 같은 오케스트레이션 시스템과 통합되어 있으며, 가상 머신, 컨테이너/파드 및 베어 메탈 워크로드에 대한 격리 모드를 제공한다.
- Flannel은 쿠버네티스와 함께 사용할 수 있는 오버레이 네트워크 제공자이다.
- Knitter는 쿠버네티스 파드에서 여러 네트워크 인터페이스를 지원하는 플러그인이다.
- Multus는 쿠버네티스에서 SRIOV, DPDK, OVS-DPDK 및 VPP 기반 워크로드 외에 모든 CNI 플러그인(예: Calico, Cilium, Contiv, Flannel)을 지원하기 위해 쿠버네티스에서 다중 네트워크 지원을 위한 멀티 플러그인이다.
- OVN-Kubernetes는 Open vSwitch(OVS) 프로젝트에서 나온 가상 네트워킹 구현인 OVN(Open Virtual Network)을 기반으로 하는 쿠버네티스용 네트워킹 제공자이다. OVN-Kubernetes는 OVS 기반 로드 밸런싱과 네트워크 폴리시 구현을 포함하여 쿠버네티스용 오버레이 기반 네트워킹 구현을 제공한다.
- OVN4NFV-K8S-Plugin은 OVN 기반의 CNI 컨트롤러 플러그인으로 클라우드 네이티브 기반 서비스 기능 체인(Service function chaining(SFC)), 다중 OVN 오버레이 네트워킹, 동적 서브넷 생성, 동적 가상 네트워크 생성, VLAN 공급자 네트워크, 직접 공급자 네트워크와 멀티 클러스터 네트워킹의 엣지 기반 클라우드 등 네이티브 워크로드에 이상적인 멀티 네티워크 플러그인이다.
- NSX-T 컨테이너 플러그인(NCP)은 VMware NSX-T와 쿠버네티스와 같은 컨테이너 오케스트레이터 간의 통합은 물론 NSX-T와 PKS(Pivotal 컨테이너 서비스) 및 OpenShift와 같은 컨테이너 기반 CaaS/PaaS 플랫폼 간의 통합을 제공한다.
- Nuage는 가시성과 보안 모니터링 기능을 통해 쿠버네티스 파드와 비-쿠버네티스 환경 간에 폴리시 기반 네트워킹을 제공하는 SDN 플랫폼이다.
- Romana는 네트워크폴리시 API도 지원하는 파드 네트워크용 Layer 3 네트워킹 솔루션이다. Kubeadm 애드온 설치에 대한 세부 정보는 여기에 있다.
- Weave Net은 네트워킹 및 네트워크 폴리시를 제공하고, 네트워크 파티션의 양면에서 작업을 수행하며, 외부 데이터베이스는 필요하지 않다.
서비스 검색
- CoreDNS는 유연하고 확장 가능한 DNS 서버로, 파드를 위한 클러스터 내 DNS로 설치할 수 있다.
시각화 & 제어
인프라스트럭처
- KubeVirt는 쿠버네티스에서 가상 머신을 실행하기 위한 애드온이다. 일반적으로 베어 메탈 클러스터에서 실행한다.
레거시 애드온
더 이상 사용되지 않는 cluster/addons 디렉터리에 다른 여러 애드온이 문서화되어 있다.
잘 관리된 것들이 여기에 연결되어 있어야 한다. PR을 환영한다!