1) Taint & Toleration?
- Taint 얼룩이라는 뜻으로 Node에 설정한다.
- Node에 Taint를 설정하여 임의의 Pod가 할당되는 것을 방지한다.
- Toleration은 용인이라는 뜻으로 Pod에 설정한다.
- 특정 Taint를 용인할 수 있는 Toleration 설정을 가진 Pod는 해당 Node에 할당 가능하다.
=> 즉, 이 2가지 전략은 함께 이해하고 사용할 수밖에 없는 개념이다.
- 위 그림을 토대로 해석을 해보자.
- 앞에 2개의 Nodedp taint로 무언가 설정 값을 준 것을 알 수 있다.
- 이러면 일반적인 Pod 생성시에는 해당 앞의 2개의 Node에는 얼룩이 있어서 배치될 수가 없다.
- 허나 만약 Pod 생성 조건으로 Node에 준 얼룩(taint) 값(position=low)과 동일한 용인(toleration) 값을 주면, 앞의 2개의 Node에도 배치가 가능하게 된다.
2) Node Taint를 관리하는 방법
- Node를 새로 구성할 때 kubelet 옵션을 통해서 기본 Taint 설정도 가능하다.
- 이미 실행 중인 Node에 대해서 kubectl을 통해 노드의 Taint 관리가 가능하다.
- Taint는 Label 및 Annotation과 비슷하게 Key=Value형식을 가지지만, 추가적으로 Effect라는 파라미터를 가질 수 있다.
- ex) Key=Value:Effect
- Effect
- Taint가 노드에 설정될 때 어떤 효과를 가지게 될지 설정하는 것이다. (적용될 효과를 정의!)
- 3가지 종류가 있다.
- NoSchedule
- 그 Tainit Node에 Pod의 스케줄링을 허용하지 않음
- 기존 실행 중인 Pod는 어쩔수 없고, 앞으로 실행될 Pod에 대해서만 스케쥴링 제한
- NoExecute
- 그 Tainit Node에 Pod의 실행을 허용하지 않음
- 앞으로 생성 될 Pod에 대한 스케쥴링을 제한함은 물론, 기존에 해당 Node에 배치된 Pod 모두 방출
- PreferNoSchedule
- 그 Tainit Node에 Pod 스케줄링을 선호하지 않음
- Soft룰이라 할수 있다.
- 기존 실행 중인 Pod는 허용하고, 앞으로 생성될 Pod도 스케쥴링되는 것을 선호하진 않지만, 해당 Node 밖에 스케쥴링 될 곳이 없다면 허용해줌!
- 예시
1. $ kubectl taint node minikube-m02 role=system:NoSchedule
2. $ kubectl taint node minikube-m02 role:NoSchedule-
3. $ kubectl taint node minikube-m02 role-
- minikube-m02 노드에 role=system:NoSchedule Taint 추가
- minikube-m02 노드에 role:NoSchedule Taint 제거
- minikube-m02 노드에 role 키를 가진 모든 Taint 제거
3) 다양한 Toleration 설정 방법
- tolerations 아래애 key, value, operator, effect를 줌으로써 설정한다. (operator 설정값은 Equal, Exists가 있다.)
- 바로 예시로 보면서 이해하자
tolerations:
- operator: Exists
tolerations:
- key: role
operator: Exists
tolerations:
- key: role
operator: Exists
effect: NoExecute
- 키가 role이고 effect가 NoExecute인 모든 Taint를 용인한다.
tolerations:
- key: role
operator: Equal
value: system
effect: NoSchedule
- role=system:NoSchedule Taint를 용인한다.
4) Taint & Toleration 실습
- toleration 디렉토리를 만들고 진입한다.
- sh 및 yml 파일들을 준비한다. (몇몇 yml은 filebeat 폴더를 만들고 그 안에 만든다.)
set-node-taints.sh
kubectl taint node minikube-m03 --overwrite role=system:NoSchedule
- minikube-m03 노드에 대해서만 role=system:NoSchedule이라는 Taint를 주겠다는 sh 파일이다.
normal.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: normal
spec:
replicas: 3
selector:
matchLabels:
app: hello
template:
metadata:
name: hello
labels:
app: hello
spec:
containers:
- name: nginx
image: nginxdemos/hello:plain-text
ports:
- name: http
containerPort: 80
protocol: TCP
- 어떤 배치전략도 적용되지 않은 노멀한 Deployment를 준비했다.
tolerated.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: tolerated
spec:
replicas: 3
selector:
matchLabels:
app: hello
template:
metadata:
name: hello
labels:
app: hello
spec:
containers:
- name: nginx
image: nginxdemos/hello:plain-text
ports:
- name: http
containerPort: 80
protocol: TCP
tolerations:
- key: role
operator: Equal
value: system
effect: NoSchedule
- tolerations을 잘 정의하면 된다.
- key가 role이고 value는 system, effect는 NoSchedule인 Node에 대해서, 이 yml이 생성할 Pod의 배치를 용인해준다.
filebeat/daemonset.yml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: filebeat
namespace: default
labels:
app.kubernetes.io/name: filebeat
spec:
selector:
matchLabels:
app.kubernetes.io/name: filebeat
template:
metadata:
labels:
app.kubernetes.io/name: filebeat
spec:
serviceAccountName: filebeat
terminationGracePeriodSeconds: 30
containers:
- name: filebeat
image: docker.elastic.co/beats/filebeat:7.15.0
args:
- "-e"
env:
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
securityContext:
runAsUser: 0
resources: {}
ports:
- name: internal-http
containerPort: 5066
livenessProbe:
httpGet:
path: /
port: internal-http
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /
port: internal-http
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 5
failureThreshold: 3
volumeMounts:
- mountPath: /usr/share/filebeat/filebeat.yml
readOnly: true
name: config
subPath: filebeat.yml
- mountPath: /usr/share/filebeat/data
name: data
- mountPath: /var/lib/docker/containers
readOnly: true
name: varlibdockercontainers
- mountPath: /var/log
readOnly: true
name: varlog
volumes:
- name: config
configMap:
name: filebeat-config
defaultMode: 0640
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
- name: varlog
hostPath:
path: /var/log
- name: data
hostPath:
path: /var/lib/filebeat-data
type: DirectoryOrCreate
tolerations:
- key: role
operator: Exists
- 맨 아래 보면 daemonset도 당연히 Pod 영역이 있기 때문에, toleration 설정이 가능하다는 걸 알 수 있다.
- daemonset은 보통 모든 노드에 띄워지는 daemon을 실행할 때 쓰이기 때문에, toleration이 daemonset 주로 설정되는 편이다.
- 즉, taint 설정이 된 몇몇 노드에 daemon이 실행안되면 안되기 때문에, 모든 노드에 적용되게 하기 위해 Exists로 operator를 줘서 전부 용인되게 한다.
filebeat/configmap.yml
apiVersion: v1
kind: ConfigMap
metadata:
name: filebeat-config
namespace: default
data:
filebeat.yml: |
filebeat.inputs:
- type: container
paths:
- /var/log/containers/*.log
processors:
- add_kubernetes_metadata:
host: ${NODE_NAME}
matchers:
- logs_path:
logs_path: "/var/log/containers/"
http:
enabled: true
host: 0.0.0.0
port: 5066
output.console:
enabled: true
- filebeat.yml이라는 파일을 configmap의 key로하고 내용을 value로 한 걸 볼 수 있다.
- filebeat는 input과 output을 하게 된다.
filebeat/rbac.yml
apiVersion: v1
kind: ServiceAccount
metadata:
name: filebeat
namespace: default
labels:
app.kubernetes.io/name: filebeat
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: filebeat
labels:
app.kubernetes.io/name: filebeat
rules:
- apiGroups: [""]
resources:
- namespaces
- nodes
- pods
- services
verbs:
- get
- watch
- list
- apiGroups: ["apps"]
resources:
- replicasets
verbs:
- get
- watch
- list
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: filebeat
labels:
app.kubernetes.io/name: filebeat
subjects:
- kind: ServiceAccount
name: filebeat
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: filebeat
- 이거는 filebeat에 필요한 권한들을 주는 설정이라고 할 수 있다.
실습을 진행해보자.
- toleration 디렉토리에서 실습을 진행한다.
- 참고로 권한 문제가 발생하면 다음 커맨드를 입력한다.
- chmod +x set-node-taints.sh
- 우선 watch 모드 실행을 위해 2개의 터미널을 새로 띄운다.
- watch kubectl get pod
- 실습 중에
1번 watch 터미널
이라고 하겠다.
- Pod의 상태를 실시간으로 볼 수 있다. 아직 아무것도 존재하지 않는다.
- watch kubectl get nodes
- 실습 중에
2번 watch 터미널
이라고 하겠다.
- Node의 상태를 실시간으로 볼 수 있다.
- 현재 node가 3종류 임을 알 수 있다. (minikube, minikube-m02, minikube-m03)
- ./set-node-taints.sh
- modified 되었다는 메시지가 나온다.
- 이미 살펴본 커맨드이지만 다시 설명하자면, minikube-m03 노드에 대해서만 role=system:NoSchedule이라는 Taint를 주게 된다.
- kubectl apply -f normal.yml
- normla.yml을 apply한다.
- minikube-m03 노드에 Taint가 있기 때문에 그 외의 노드에만 Pod의 배치가 이루어졌다.
- kubectl apply -f tolerated.yml
- 이제 toleration으로 minikube-m03 노드에 대한 용인도 이루어져 모든 Node에 고루 배치되는 결과가 나왔다.
- kubectl apply -f .
- filebeat와 관련된 모든 yml을 apply한다.
- 모든 노드에 filebeat가 띄워진 것을 확인할 수 있다.