Kind Kubernetes 클러스터 설치 가이드

이 문서는 ARM64 Linux 환경에서 Kind(Kubernetes in Docker)를 사용하여 로컬 Kubernetes 클러스터를 빠르게 설치하고 설정하는 단계를 설명합니다.

1. 전제 조건

1.1 Kind 및 kubectl 설치

Kind(Kubernetes in Docker)를 설치하여 로컬 테스트 및 개발용 Kubernetes 클러스터를 생성합니다.

curl -Lo ./kind https://github.com/kubernetes-sigs/kind/releases/download/v0.27.0/kind-linux-arm64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind

다음으로, Kubernetes 클러스터와 상호작용하기 위한 명령줄 도구인 kubectl을 설치합니다.

KUBECTL_VERSION="v1.30.0"
curl -sLO "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/arm64/kubectl"
sudo mv kubectl /usr/local/bin/
sudo chmod +x /usr/local/bin/kubectl

1.2 시스템 요구사항

  • Docker가 설치되고 실행 중이어야 합니다.
  • Raspberry Pi 5를 사용하는 경우, /boot/firmware/cmdline.txt 파일 끝에 다음을 추가하고 재부팅하세요:
    cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory systemd.unified_cgroup_hierarchy=0
    

2. Kind 클러스터 생성

2.1 클러스터 구성 파일

이 폴더에는 kind-4nodes.yaml 파일이 포함되어 있으며, 다음과 같은 구성을 제공합니다:

  • 1개의 control-plane 노드: Ingress 준비 레이블 및 포트 매핑 (80, 443)
  • 3개의 worker 노드: insecure registry 설정을 위한 certs.d 마운트
  • 네트워킹: API 서버 주소 및 포트 설정
  • Containerd 설정: Registry 구성 패치

2.2 클러스터 생성

제공된 구성 파일을 사용하여 Kubernetes 클러스터를 생성합니다.

kind create cluster --name kind --config ./kind-4nodes.yaml --image kindest/node:v1.34.0

2.3 자동 재시작 설정

Kind 노드 컨테이너가 시스템 재부팅 시 자동으로 시작되도록 설정합니다.

docker ps -a --filter "name=^kind-" --format "{{.Names}}" \
| xargs -r -n1 docker update --restart unless-stopped

2.4 Insecure Registry 설정

Kind에서 보안되지 않은 컨테이너 레지스트리를 사용하려면 certs.d/<domain>/hosts.toml 파일을 수정해야 합니다.``

이 폴더에는 certs.d/harbor.cnapcloud.com/hosts.toml 파일이 포함되어 있으며, Harbor 레지스트리를 위한 설정 예시입니다:

server = "https://harbor.cnapcloud.com"

[host."https://harbor.cnapcloud.com"]
  capabilities = ["pull", "resolve"]
  skip_verify = true

또한 DNS 서버를 kind worker가 접근하지 못하는 경우, 각 kind-worker의 /etc/hosts 파일에 Harbor Registry를 등록하세요.

$ docker exec -it kind-worker[,2,3,4] bash
root@kind-worker:/#  sh -c 'echo "<DOCKER_HOST_IP> harbor.cnapcloud.com" >> /etc/hosts'

3. 추가 구성

3.1 Ingress Controller 설정

Nginx Ingress Controller를 배포하여 클러스터 외부에서 서비스에 접근할 수 있도록 합니다.

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/refs/tags/helm-chart-4.9.0/deploy/static/provider/kind/deploy.yaml

선택적으로, Ingress Controller ConfigMap에서 snippet annotations를 활성화합니다:

kubectl -n ingress-nginx edit cm ingress-nginx-controller
apiVersion: v1
kind: ConfigMap
metadata:
  name: ingress-nginx-controller
  namespace: ingress-nginx
data:
  allow-snippet-annotations: "true"
  annotations-risk-level: "Critical"
kubectl -n ingress-nginx rollout restart deploy ingress-nginx-controller

참고: GitOps의 ingress-nginx 모듈을 사용할 경우 Ingress Controller 배포 전 아래 선행 작업이 필요합니다.

  1. GPG 암호화 구성 (Cloudflare DNS Issuer API 토큰 등)
  2. reflector 설치 (Certificate가 생성한 Secret 복제)
  3. cert-manager 설치

이후, helm values 설정에서 하단의 주석을 제거하면 Control Plane 노드에 Ingress Controller가 정상적으로 배포됩니다.

3.2 DNS 설정

Kind의 Docker DNS(172.18.0.1)는 일반 재귀 해석은 수행하지만 SOA 조회와 같은 권한 있는 쿼리를 올바르게 처리하지 않습니다. 따라서 Cert-Manager의 DNS-01 챌린지가 요구하는 SOA 검사를 위해 CoreDNS ConfigMap을 수정하여 DNS 쿼리를 공용 리졸버로 전달해야 합니다.

kubectl -n kube-system edit cm coredns

CoreDNS ConfigMap에 다음을 추가합니다:

kubectl -n kube-system edit cm coredns
forward . 1.1.1.1 1.0.0.1 {
    max_concurrent 1000 
}

ConfigMap을 저장하면 CoreDNS가 자동으로 reload 되지만, 반영이 바로 되지 않을 경우 아래 명령어로 수동 재시작할 수 있습니다. kubectl -n kube-system rollout restart deployment coredns

4. NFS 스토리지 설정

4.1 Helm 리포지토리 추가

NFS 서버 및 프로비저너를 위한 Helm 리포지토리를 추가합니다:

helm repo add nfs-ganesha-server-and-external-provisioner https://kubernetes-sigs.github.io/nfs-ganesha-server-and-external-provisioner/
helm repo update

4.2 NFS 클라이언트 설치

모든 Kind 노드에 NFS 클라이언트를 설치합니다:

for node in $(kind get nodes); do
  echo "Installing nfs-common on $node"
  docker exec $node bash -c "apt-get update && apt-get install -y nfs-common"
done

4.3 NFS 서버 설치

NFS 서버를 Helm을 사용하여 설치합니다 (persistence 비활성화, 기본 StorageClass로 설정하지 않음):

helm install nfs-server nfs-ganesha-server-and-external-provisioner/nfs-server-provisioner \
  --namespace kube-system \
  --set persistence.enabled=true \
  --set persistence.storageClass=standard \
  --set persistence.size=35Gi \
  --set storageClass.name=nfs \
  --set storageClass.defaultClass=false \
  --set nodeSelector."node-role\.kubernetes\.io/control-plane"="" \
  --set tolerations[0].key="node-role.kubernetes.io/control-plane" \
  --set tolerations[0].operator="Exists" \
  --set tolerations[0].effect="NoSchedule"

기본 StorageClass를 ‘standard’에서 ’nfs’로 변경합니다:

kubectl patch storageclass standard -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"false"}}}'
kubectl patch storageclass nfs -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

4.5 설치 확인

NFS 서버가 정상적으로 설치되었는지 확인합니다:

kubectl -n kube-system get pods -w

StorageClass가 생성되었는지 확인합니다:

kubectl get sc

4.6 테스트 PVC 생성

NFS 스토리지를 테스트하기 위한 PVC를 생성합니다:

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-pvc
  namespace: default
spec:
  storageClassName: nfs
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
EOF

PVC 상태를 확인합니다:

kubectl -n default get pvc

5. 예제 배포

이 폴더의 examples/ 디렉토리에는 기본적인 Kubernetes 리소스 예제가 포함되어 있습니다.

5.1 간단한 Nginx 앱 배포

Nginx 배포를 생성하고 ClusterIP 서비스로 노출합니다.

kubectl create deploy nginx --image nginx
kubectl expose deploy nginx --type ClusterIP --port 80

5.2 테스트용 Curl Pod 생성

클러스터 내부에서 서비스 연결을 테스트하기 위한 curl pod를 생성합니다.

kubectl run curl --image=curlimages/curl:latest --restart=Never -- sleep infinity
kubectl exec -it curl -- curl http://nginx

5.3 PVC 및 Pod 예제

examples/pvc.yamlexamples/pod.yaml을 사용하여 PersistentVolumeClaim과 이를 사용하는 Pod를 배포할 수 있습니다.

kubectl apply -f examples/pvc.yaml
kubectl apply -f examples/pod.yaml

5.4 Ingress 예제

examples/ingress.yaml을 사용하여 외부 접근을 위한 Ingress를 생성할 수 있습니다.

kubectl apply -f examples/ingress.yaml

6. 클러스터 삭제

실험이 끝나면 시스템 리소스를 확보하기 위해 Kind 클러스터를 안전하게 제거합니다.

kind delete cluster --name kind

7. 참고 자료

💬 무료 컨설팅 신청