Search

Kubernetes in Docker (Single / Multi) 설치 및 구성

Tags
k8s
docker
install
kind
dind
dood
Created
2024/09/06 08:52
Created time
2024/09/05 23:52
category
kubernetes

개요

DinD 방식으로 Kubernetes 클러스터를 구축하는 방법 (a.k.a. KinD)을 기술

준비 사항

1.
Docker Desktop 설치
Settings > Kubernetes > Enable Kubernetes를 체크 후, Apply & Restart 해줍니다.
2.
vCPU 4, Memory 8GB 정도의 리소스 할당
3.
kind 설치
# kind 설치 brew install kind # 버전 확인 kind --version
Shell
복사
4.
kubectl 설치
# kubectl 설치 brew install kubernetes-cli # 버전 확인 kubectl version
Shell
복사
5.
helm 설치
# helm 설치 brew install helm # 버전 확인 helm version
Shell
복사
6.
wireshark 설치
# wireshark 설치 brew install --cask wireshark
Shell
복사
7.
krew 설치
# kubectl 플러그인 관리 도구 설치 brew install krew # krew 경로 설정 echo 'export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"' >> ~/.zshrc # 플러그인 탐색 kubectl krew search # 플러그인 설치 kubectl krew install <plugin-name> # 설치 플러그인 목록 kubectl krew list # get -o yaml로 리소스 추출 시 아래의 불필요한 데이터도 함께 표출되는데, neat 이용 시 정리된 yaml을 얻을 수 있음 # - timestamp # - id metadata # - omitted default value # - system property like service account token # - status kubectl krew install neat
Shell
복사
8.
kube-ps1 설치
# 프롬프트에 컨텍스트와 네임스페이스 표기하는 스크립트 # PS1 프롬프트 적용은 아래 링크 참고 # https://github.com/jonmosco/kube-ps1 brew install kube-ps1 # k8s 프롬프트 끄기 kubeoff # k8s 프롬프트 켜기 kubeon # 디폴트 끄기 kubeoff -g # 디폴트 켜기 kubeon -g
Shell
복사
9.
kubectx 설치
# 컨텍스트 전환 및 네임스페이스 선택을 돕는 도구 # kubectx로 클러스터, kubens로 네임스페이스 선택 가능 brew install kubectx
Shell
복사
클러스터 선택
네임스페이스 선택
10.
kubecolor 설치
# kubectl highlighting 설치 brew install kubecolor # kubectl 자동 완성 설정을 kubecolor에 재정의 echo "compdef kubecolor=kubectl" >> ~/.zshrc # kubecolor를 kubectl로 별칭 등록 echo "alias kubectl=kubecolor" >> ~/.zshrc
Shell
복사

KUBECONFIG 설정

이미 디폴트 경로로 ~/.kube로 kubeconfig를 이용하고 있고, 해당 디렉토리가 오염되지 않길 바란다면 별도 설정이 필요
# kind에서 사용할 kubeconfig 경로 생성 mkdir -p ~/.kubekind # kubeconfig 파일 생성 touch ~/.kubekind/config # kubeconfig 경로 지정 # 해제 시 unset KUBECONFIG export KUBECONFIG=~/.kubekind/config
Shell
복사
kubectl 명령어 이용 시 --kubeconfig 경로를 지정 방식도 가능

Single Node 클러스터 구축

# 클러스터 생성 # 이미지는 아래 링크 참고하여 기재 # https://hub.docker.com/r/kindest/node/tags # kind create cluster --name <cluster-name> --image <image:tag> kind create cluster --name default-cluster --image kindest/node:v1.31.0
Shell
복사
kind로 클러스터 생성에 실패한다면, Docker Desktop의 Kubernetes 활성화 여부를 확인하고 리소스가 부족하지 않은지 확인
k8s 버전은 이미지로 명시하는 방법 외에도, 클러스터 리소스 manifest에 직접 이미지를 명시한 후 해당 manifest를 kind 명령어의 —-config인자로 이용하는 방법도 존재
# 생성한 클러스터 사용 # kubectl cluster-info --context kind-<cluster-name> kubectl cluster-info --context kind-default-cluster
Shell
복사
# 생성된 클러스터의 kubeconfig 파일 확인 ls -l ~/.kubekind/config # kubeconfig 파일 내용 확인 cat ~/.kubekind/config
Shell
복사
# 클러스터 목록 확인 kind get clusters # 지정한 클러스터의 노드 확인 # kind get nodes --name <cluster-name> kind get nodes --name default-cluster # 현재 컨텍스트의 클러스터 정보 확인 kubectl cluster-info # node 확인 kubectl get no -o wide # pod 확인 kubectl get po -A # k8s 컴포넌트 상태 확인 kubectl get componentstatuses
Shell
복사
# nginx 배포 시도 kubectl run nginx --image=nginx:alpine # 배포된 pod 조회 kubectl get po -o wide # control-plane의 Taints 확인 시 None이어서 control-plane에 스케줄링 가능 kubectl describe no | grep Taints
Shell
복사
# 클러스터 삭제 # kind delete cluster <cluster-name> kind delete cluster default-cluster
Shell
복사
# 생성된 클러스터의 kubeconfig 파일 확인 ls -l ~/.kubekind/config # kubeconfig 파일 내용 확인 cat ~/.kubekind/config
Shell
복사

Multi Node 클러스터 구축

생성

# 클러스터 설정 파일 생성 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 # 설정 파일 생성확인 ls -l kind-2node.yaml # 클러스터 생성 kind create clustre --name custom-cluster --config kind-2node.yaml # 클러스터 전환 kubectl cluster-info --context kind-custom-cluster
Shell
복사

k8s 클러스터 조회

# 클러스터 목록 확인 kind get clusters # 지정한 클러스터 노드 확인 시, control-plane 및 worker 노드 확인 가능 kind get nodes --name custom-cluster # 클러스터 내 노드 상세 정보 확인 kubectl get no -o wide # control-plane 노드 Taints 조회 kubectl describe no/custom-cluster-control-plane | grep Taints # worker 노드 Taints 조회 kubectl describe no/custom-cluster-worker | grep Taints
Shell
복사

Docker 컨테이너 조회

# 컨테이너 목록 조회 docker ps --format '{{.ID}}\t{{.Names}}'
Shell
복사
# 컨테이너가 점유 중인 포트 조회 # kind-2node.yaml에 기재한 설정대로 로컬호스트의 31000 포트 접속이 곧 컨테이너의 31000 포트 접속 # 컨테이너가 곧 노드를 지칭하므로, 워커 노드가 NodePort로 31000 포트를 열었다면 로컬 호스트에서 워커 노드 접속 가능 # docker port <container-name> docker port custom-cluster-worker
Shell
복사
# 컨테이너 내부에 접속하여 노드가 사용하는 IP 주소 조회 docker exec -it custom-cluster-control-plane ip -br -c -4 addr docker exec -it custom-cluster-worker ip -br -c -4 addr
Shell
복사

NodePort 서비스 배포 및 조회

# Replica 2짜리 Nginx와 NodePort 서비스를 배포 cat <<EOF | kubectl create -f - apiVersion: apps/v1 kind: Deployment metadata: name: deploy-websrv spec: replicas: 2 selector: matchLabels: app: deploy-websrv template: metadata: labels: app: deploy-websrv spec: terminationGracePeriodSeconds: 0 containers: - name: deploy-websrv image: nginx:alpine ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: deploy-websrv spec: ports: - name: svc-webport port: 80 targetPort: 80 nodePort: 31001 selector: app: deploy-websrv type: NodePort EOF # 리소스 (Deployment, Service, Enpoint) 조회 kubectl get deploy,svc,ep deploy-websrv # 로컬호스트의 포트로 접속 시 worker 노드의 NodePort로 접속 됨을 확인 open http://localhost:31001 curl -s localhost:31001 | egrep "<title>.*</title>" # 리소스 삭제 (Endpoint는 자동 삭제) kubectl delete deploy,svc deploy-websrv
Shell
복사

클러스터로 이미지 주입

로컬에서 빌드한 이미지를 kind 클러스터 내부로 이미지를 로드하는 것도 가능
# index.html 생성 echo "nice to meet you, jseo" > index.html # Dockerfile 생성 cat << EOF > Dockerfile FROM nginx:alpine COPY index.html /usr/share/nginx/html/ EXPOSE 80 CMD ["nginx", "-g", "daemon off;"] EOF # 이미지 빌드 docker build -t custom-nginx:1.0 . # 빌드 이미지 조회 docker images
Shell
복사
이전 항목에서 사용했던 기본 nginx 이미지에 index.html을 변경하여 이미지 빌드
# control-plane 노드 내 이미지 목록 # docker exec -it <cluster-name>-control-plane crictl images docker exec -it custom-cluster-control-plane crictl images # worker 노드 내 이미지 목록 # docker exec -it <cluster-name>-worker crictl images docker exec -it custom-cluster-worker crictl images
Shell
복사
Multi Node 클러스터에서 사용하던 이미지들을 확인
# 이미지 주입 # kind load docker-image <image>:<tag> --name <cluster-name> kind load docker-image custom-nginx:1.0 --name custom-cluster
Shell
복사
custom-cluster에 custom-nginx 이미지를 주입
# control-plane 노드 내 이미지 목록 # docker exec -it <cluster-name>-control-plane crictl images docker exec -it custom-cluster-control-plane crictl images # worker 노드 내 이미지 목록 # docker exec -it <cluster-name>-worker crictl images docker exec -it custom-cluster-worker crictl images
Shell
복사
이전에 control-plane과 worker 노드에 없던 custom-nginx 이미지가 주입된 것을 확인 가능
cat <<EOF | kubectl create -f - apiVersion: apps/v1 kind: Deployment metadata: name: deploy-websrv spec: replicas: 2 selector: matchLabels: app: deploy-websrv template: metadata: labels: app: deploy-websrv spec: terminationGracePeriodSeconds: 0 containers: - name: deploy-websrv image: custom-nginx:1.0 ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: deploy-websrv spec: ports: - name: svc-webport port: 80 targetPort: 80 nodePort: 31001 selector: app: deploy-websrv type: NodePort EOF # 리소스 (Deployment, Service, Enpoint) 조회 kubectl get deploy,svc,ep deploy-websrv # 로컬호스트의 포트로 접속 시 worker 노드의 NodePort로 접속 됨을 확인 open http://localhost:31001 curl -s localhost:31001 | egrep "nice to meet you" # 리소스 삭제 (Endpoint는 자동 삭제) kubectl delete deploy,svc deploy-websrv
Shell
복사

삭제

# 생성했던 Multi Node 클러스터 삭제 # kind delete cluster <cluster-name> kind delete cluster --name custom-cluster
Shell
복사

인그레스

노드 구축

# 클러스터 설정 파일 생성 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 ingress-cluster
Shell
복사
extraPortMapping에 기재된 hostPort 80 / 443를 통해 인그레스 컨트롤러로 요청 가능
node-lables를 통해 인그레스 컨트롤러가 특정 노드에서 기동될 수 있도록 설정 가능
# 포트 확인 docker port ingress-cluster-control-plane # 노드 확인 kubectl get no -o wide # 라벨 확인 kubectl get nodes ingress-cluster-control-plane -o jsonpath={.metadata.labels} | jq
Shell
복사
# nginx 인그레스 노드 배포 # https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml # 배포된 리소스 확인 kubectl get deploy,svc,ep ingress-nginx-controller -n ingress-nginx
Shell
복사
control-plane에 설정했던 extraPortMapping처럼 80:80 / 443:443이 맵핑된 설정과 control-plane과 마스터에 대한 Toleration이 설정된 manifest로 배포
manifest 파일에 nodeSelector를 이용하여 ingress-ready 값이 true인 노드에 배포될 것을 지정
# control-plane의 iptables를 조회 docker exec -it ingress-cluster-control-plane iptables -t nat -L -n -v | grep '10.244.0.7'
Shell
복사
nginx 파드의 IP가 10.244.0.7이고 이에 대한 iptables 목록의 NAT를 control-plane에서 조회 시, 80:80 / 443:443인 것을 확인 가능

인그레스 리소스 배포

# 파드, 서비스, 인그레스 배포 # https://kind.sigs.k8s.io/examples/ingress/usage.yaml kubectl apply -f https://kind.sigs.k8s.io/examples/ingress/usage.yaml
Shell
복사
# 리소스 조회 kubectl get ing,po -o wide kubectl get svc,ep foo-service bar-service kubectl describe ing/example-ingress
Shell
복사

스모크 테스트

# (터미널 1) 로그 모니터링 kubectl logs -n ingress-nginx deploy/ingress-nginx-controller -f # (터미널 2) 접속 테스트 curl localhost/foo/hostname curl localhost/bar/hostname kubectl exec -it foo-app -- curl localhost:8080/foo/hostname kubectl exec -it foo-app -- curl localhost:8080/hostname kubectl exec -it bar-app -- curl localhost:8080/bar/hostname kubectl exec -it bar-app -- curl localhost:8080/hostname
Shell
복사

리소스 삭제

# 리소스 삭제 # https://kind.sigs.k8s.io/examples/ingress/usage.yaml kubectl delete -f https://kind.sigs.k8s.io/examples/ingress/usage.yaml # 작업 마무리 후 클러스터 삭제 kind delete cluster --name ingress-cluster
Shell
복사