home..

KIND 클러스터링

mont-kim Docker Container Kubernetes KIND

KIND 클러스터링

Kubernetes

Cluster Architecture

  • Master Node
    • ETCD CLUSTER
    • kube apiserver
    • kube controller manager
    • kube scheduler
  • Worker Nodes
    • kubelet
    • kube proxy
    • Container Runtime Engine

쿠버네티스는 마스터노드라는 컨트롤 플레인과 컨테이너를 담는 워커노드들로 이루어진 컨테이너 오케스트레이션입니다.

워커 노드는 기본적으로 컨테이너들의 호스트 어플리케이션이고 컨테이너들을 관리합니다.

컨테이너들을 어떻게 관리 해야할지에 대한 전체적인 관리 프로세스를 가지며, 관리 프로세스들의 집합을 마스터 노드가 가지고있습니다.

마스터 노드에서는 워커노드들을 관리하고, 스케줄링하고, 노드들(컨테이너)의 상태를 모니터링합니다.

많은 참조를 한 블로그입니다.

https://insujang.github.io/2019-10-31/container-runtime/

image.png

우리가 컨테이너를 실행할때는 다음과 같은 동작이 일어납니다.

image.png

반대로 쿠버네티스에서 컨테이너를 실행할때는 조금 더 복잡한 순서대로 컨테이너를 만들게 되죠.

사실 노드의 kubelet이 crio - runc 를 거쳐 컨테이너를 생성하게되는건 위에 봤던거랑 크게 차이나지않습니다.

누가 하는가 의 차이정도겠네요.

대신에 kubelet은 헬스체크도하면서 만들기도하면서 재시작을 트리거링하기도하고 더 많은걸 해줄뿐이죠.

물론 cri와 oci 규격은… 뭔가 많이 복잡해집니다

image.png

docker가 표준런타임에서 분리된것도 같은맥락인데

kubelet은 Pod Lifecycle Event Generator가 있습니다.

파드 라이프사이클 관리를 당당하는데, 파드 스펙에 대한 변경 관리 , 컨테이너 상태 관리

  • Pod 내에 실행되는 컨테이너들은 반드시 동일한 노드에 할당되며 동일한 생명 주기를 갖습니다 → Pod 삭제 시, Pod 내 모든 컨테이너가 삭제됩니다. → 하지만 컨테이너들의 종료를 Triggering 하는것은 별개입니다. pod의 lifecycle과 container의 lifecycle 은 별개입니다.

image.png

PLEG

kubelet에서 이런 관리들을 하며 다시 주기를 맞추기도 합니다.

Kind

image.png

KIND

현재 구동된 kind 구조입니다.

호스트 Docker 위에서 각 docker container들이 논리적인 노드의 역할을 하고,

각 컨테이너 안에서 containerd 소켓을 이용해 pod / container들을 생성하는 구조입니다.

MAC 기준으로 작성된 KIND 클러스터 구축입니다

# Install Kind
brew install kind
kind --version

# Install kubectl
brew install kubernetes-cli
kubectl version --client=true

# Install Helm
brew install helm
helm version

# Utility
brew install krew
brew install kube-ps1
brew install kubecolor
brew install kubectx

단일 노드 클러스터 구성


kind create cluster

2 노드 클러스터 구성

cat << EOT > kind-2node.yaml 
# two node (one workers) cluster config
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
EOT
kind create cluster --config kind-2node.yaml --name myk8s

단일노드 클러스터 구성을해도, Controlplane에 Taint 가 들어가지않아 파드들을 생성 할 수 있습니다.


  taints:
  - effect: NoSchedule
    key: node-role.kubernetes.io/control-plane

클러스터링에 Control Plane을 다음과 같은 taint를 부여할경우, 해당 toleration 키가 없는 파드는 프로비저닝이 될 수 없습니다.

그래도 만약에 꼭 파드를 배치해보고싶다면

Schduling_Pod_On_CordonNode

이런 방법들이 있기도 합니다.

image.png

간단하게는 다음과 같은 컨테이너들이 “노드” 역할을 해주는 docker container로 생성이 됩니다.

그중에서도 kubernetes api 통신을 처리해주는 네트워크는 49831로

image.png

실제 내 kubeconfig을 봐도 다음과 같은 엔드포인트를 바라보고있다는것을 알 수 있습니다.

이제 해당 노드(도커 컨테이너) 안에 들어와봅니다.

image.png

일반 노드에서 구성된 containerd 기반의 파드들과 “동일” 합니다.

containerd는 crictl 기반의 명령어들로 컨테이너들을 조회합니다.

고유 식별번호인 container id는 프로세스로 조회가 가능합니다!

가끔… kubelet이 제대로 정리안해주면 직접 정리해줘야하거든요…

kind 포트 외부노출하기!

cat <<EOT> kind-2node.yaml
# two node (one workers) cluster config
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
  extraPortMappings:
  - containerPort: 31000
    hostPort: 31000
    listenAddress: "0.0.0.0" # Optional, defaults to "0.0.0.0"
    protocol: tcp # Optional, defaults to tcp
  - containerPort: 31001
    hostPort: 31001
EOT

노드를 실행하는 docker container에 대한 외부노출 (클러스터 관점에서의 외부노출) 할 포트를 명시적으로 해줍니다.

항상 클러스터 관점에서의 외부노출은 nodeport로 해주지만

Docker 관점에서의 도커 네트워크 기준 외부노출은 또 이런식으로 컨테이너 포트맵핑을 선행해주어야합니다.

Kind Conguration

kind 는 다양한 자체 CLI 명령어를 통해 노드 구성 및 애드온 구성이 가능합니다.

Kind 노드 안에 이미지 주입

kind load docker-image $NICKNAME-myweb:1.0 --name $CLUSTERNAME

해당 명령어로 docker container (노드) 안에 이미지 주입이 가능합니다.

사실 kind 클러스터 구성뿐만이 아니라, docker 구성된 노드나 쿠버네티스 노드또한…

image registry 기반의 통신을 권장하기때문에 간단하게 이미지 구성 테스트를 하고싶을때 쓸수는 있을거같습니다.

KIND Kubernetes Version

kind create cluster --image kindest/node:v1.30.4

# 클러스터 배포
cat <<EOT> kind-v29-4.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  image: kindest/node:v1.29.4@sha256:3abb816a5b1061fb15c6e9e60856ec40d56b7b52bcea5f5f1350bc6e2320b6f8
EOT

kind create cluster --config kind-v29-4.yaml

Ingress Controller on Kind

ngress Nginx 설정

  • extraPortMappings allow the local host to make requests to the Ingress controller over ports 80/443
  • node-labels only allow the ingress controller to run on a specific node(s) matching the label selector
# 클러스터 배포 : 노드 라벨, 포트 맵핑
cat <<EOT> kind-ingress.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  kubeadmConfigPatches:
  - |
    kind: InitConfiguration
    nodeRegistration:
      kubeletExtraArgs:
        node-labels: "ingress-ready=true"
  extraPortMappings:
  - containerPort: 80
    hostPort: 80
    protocol: TCP
  - containerPort: 443
    hostPort: 443
    protocol: TCP
  - containerPort: 30000
    hostPort: 30000
EOT

kind create cluster --config kind-ingress.yaml --name myk8s

# NGINX ingress 배포
## The manifests contains kind specific patches to forward the hostPorts to the ingress controller, 
## set taint tolerations and schedule it to the custom labelled node.
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
-------------------------
## 호스트 포트 80,443 사용
ports:
- containerPort: 80
  hostPort: 80
  name: http
  protocol: TCP
- containerPort: 443
  hostPort: 443
  name: https
  protocol: TCP
...

## nodeSelector 로 배포 노드 지정
nodeSelector:
  ingress-ready: "true"
  kubernetes.io/os: linux

## taint 예외 tolerations 설정
tolerations:
- effect: NoSchedule
  key: node-role.kubernetes.io/master
	operator: Equal
- effect: NoSchedule
  key: node-role.kubernetes.io/control-plane
  operator: Equal
-------------------------

# ingress 배포 확인
kubectl get deploy,svc,ep ingress-nginx-controller -n ingress-nginx

# control-plane 노드(실제로는 컨테이너)에 IPTABLES에 80,443은 ingress-nginx 파드로 전달 규칙 확인 # 10.244.0.7은 ingress-nginx 파드의 IP
root@myk8s-control-plane:/# iptables -t nat -L -n -v | grep '10.244.0.7'
    0     0 DNAT       6    --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80 to:10.244.0.7:80
    0     0 DNAT       6    --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:443 to:10.244.0.7:443
...

Feature Gates 활성화하기

Feature_Gates

kind에서는 간단한 명령줄인자로 featuregates를 활성화 할 수 있습니다.

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
featureGates:
  # any feature gate can be enabled here with "Name": true
  # or disabled here with "Name": false
  # not all feature gates are tested, however
  "InPlacePodVerticalScaling": true

원래라면 kubelet configuration을 통해 활성화가 가능합니다.

이 경우를 아주 동일한 FeatureGate / InPlacePodVerticalScaling 를 활성화 한 사례가 있는데 링크에 첨부하겠습니다.

Pod_Resizing

Animation.gif

요약

FeatureGate가 Alpha 등급인데는 무척이나 버그가 많습니다.

아마 후술할 Pause 컨테이너와 연결되는 부분일수도 있는데

  1. init container가 있는경우 resource allocation 등에 문제가 발생 (정상적으로 원하는 동작 불가능)
  2. node allocatable 이상으로의 값 할당이 가능
  3. downsizing 하기전에 “이미 자원을 사용중이라면” downsizing이 이루어지지않음.

1번의 경우, 단일 컨테이너 구성과는 다른 구조가 발생하여 mutating webhook 등을 구현할 때, 원하는대로 동작하지 않는경우를 겪은적이 있습니다.

2번은… request 자체가 overcommit이 되면 cgroup의 자원할당에 문제가 발생되기때문에.. 아직은 완성도가 꽤나 부족한거같습니다.

3번의 경우엔 버그로 예상이되는데, stress test를 하다 cpu 를 downsizing할경우 cgroup 값 자체가 변경이 되지않습니다.

아마 downsizing의 경우 꽤나 제한적인 상황을 만들어야할거같은데, 나머지는 정책적인 구현을 통해서 완성을 할 수도 있을것은 같습니다.

© 2024 mont kim   •  Powered by Soopr   •  Theme  Moonwalk