본문 바로가기
🪲 bugs

🐛 Error: MacOS에서 Kind로 구축한 k8s 클러스터의 Deployment external IP에 접근을 하지 못합니다

by iirin 2024. 4. 6.

발생 상황

```
☁  _Lecture_k8s_starter.kit [main] ⚡  kubectl get services
NAME           TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)        AGE
chk-hn         LoadBalancer   10.96.253.167   192.168.1.11   80:30941/TCP   12m
```
  • 쿠버네티스 실습 중에 LoadBalancer service를 만들고 클러스터 내부와 외부에서 External IP로 각각 접근을 실행하였습니다.
  • 클러스터 내부에서는 문제없이 접근할 수 있었으나, 클러스터 외부에서는 timeout이 발생하였습니다.
  • 외부에서 ping을 날려봤지만, timeout이 됩니다.
curl 192.168.247.5:30623
// 응답없음...



발생 원인

추측했던 원인은 두 가지였습니다.

  • Network 설정 중 누락된 것이 있는가?
    • 클러스터를 띄울 때, 실습 가이드를 따라한 것이 아니라 yml 파일을 작성하여 클러스터를 띄웠기 때문에 default 값이 없거나 적절하게 설정되어 있지 않을 수도 있다는 추측이었습니다.
# 클러스터 설정 yml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
  ipFamily: ipv6
  apiServerAddress: 127.0.0.1
nodes:
  - role: control-plane
  - role: worker
  - role: worker
  - role: worker

 

  • Kind의 특징인가?
    • MacOS에서 쿠버네티스를 연습할 수 있어서 
    • Minikube는 명령어가 조금 다를 수 있는 반면, 명령어가 같아서 Kind를 사용했는데요.
    • 아무래도 VM을 Docker container 위에 띄우는 Kind 특성상 네트워크 설정에 달라지는 부분이 있을까 싶었습니다.

 

그래서 좀 찾아보니 해당 이슈는 알려진 문제점으로 공식 문서에도 이렇게 적혀있었습니다.

 

On macOS and Windows, docker does not expose the docker network to the host. Because of this limitation, containers (including kind nodes) are only reachable from the host via port-forwards, however other containers/pods can reach other things running in docker including loadbalancers. You may want to check out the Ingress Guide as a cross-platform workaround. You can also expose pods and services using extra port mappings as shown in the extra port mappings section of the Configuration Guide.

 

Docker 가 Linux VM에서 컨테이너를 실행하고 있지만, Docker Network가 호스트에 노출되지 않았기 때문에 발생하는 오류입니다.

 

출처 : https://medium.com/groupon-eng/loadbalancer-services-using-kubernetes-in-docker-kind-694b4207575d

 

LoadBalancer 타입 특성상 external IP로 접근 가능해야하지만, Docker container에서 노출하지 않으므로 이 external IP로는 접근이 불가능한 것입니다.

서비스 노출 방식을 NordPort로 한다면 별 문제 없이 접근 가능합니다.

 

대처

  • 일단 실습과정이기 때문에 `{NodeIP}:{Service Port}`로 요청을 보내 우회하는 전략으로 해결하였습니다.
# 노드 정보
kubectl get pods -o wide
NAME                            READY   STATUS    RESTARTS   AGE     IP           NODE                 NOMINATED NODE   READINESS GATES
deploy-nginx-7f979874cf-4kqjx   1/1     Running   0          24s     10.244.3.3   del-deploy-worker    <none>           <none>
deploy-nginx-7f979874cf-hn22v   1/1     Running   0          24s     10.244.2.3   del-deploy-worker2   <none>           <none>
deploy-nginx-7f979874cf-t48jt   1/1     Running   0          4m58s   10.244.1.2   del-deploy-worker3   <none>           <none>
nginx                           1/1     Running   0          7h26m   10.244.2.2   del-deploy-worker2   <none>           <none>

# 서비스 정보
NAME           TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)        AGE
chk-hn         LoadBalancer   10.96.253.167   192.168.1.11   80:30941/TCP   12m

# 요청결과
curl 192.168.247.5:30623
chk-hn-6cb6cdf8f8-68xsn

 

  • 다른 해결방법으로는 NGINX 수신 컨트롤러를 설정하는 방법이 있습니다. [참고링크]
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
  - http:
      paths:
      - pathType: Prefix
        path: "/test(/|$)(.*)"
        backend:
          service:
            name: test-service
            port:
              number: 80

 

 


Refs.