개요
준비 사항
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
복사