Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
languagebash
# kubectl exec -n test -it busybox-9ff887cc8-f5m46 -- sh
/ # ping 10.244.2.14
PING 10.244.2.14 (10.244.2.14): 56 data bytes
64 bytes from 10.244.2.14: seq=0 ttl=62 time=1.243 ms
64 bytes from 10.244.2.14: seq=1 ttl=62 time=0.887 ms
^C
--- 10.244.2.14 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.887/1.065/1.243 ms
--- 10.244.2.15 ping statistics ---
7 packets transmitted, 0 packets received, 100% packet loss
/ #
/ # ping 10.244.1.15
PING 10.244.1.15 (10.244.1.15): 56 data bytes
64 bytes from 10.244.1.15: seq=0 ttl=64 time=0.322 ms
^C
--- 10.244.1.15 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.322/0.322/0.322 ms

그러나, IP는 언제든 바뀔 수 있으므로, 이번에는 미리 만들어둔 Service를 통해 접근해보도록 하자.

당연한 말이지만, Service는 Pod가 아니라 pod의 특정 포트를 cluster ip와 포트로 연결해주는 일종의 정책이므로, 위의 ping은 도달하지 않는다.

아래와 같이 telnet을 통해 서비스 포트로 접근이 가능하다는 것을 확인할 수 있다.

Code Block
languagebash
/ # telnet nginx-svc 80
Connected to nginx-svc

/ # telnet nginx-svc-lb 8080
Connected to nginx-svc-lb

 # telnet nginx-svc-np 8081
Connected to nginx-svc-np

그럼 어떻게 pod에서 서비스 포트로 접근이 가능할까?

...

Info

CRI-O runtime의 경우 보안 상 pod 내부에서 ping이 나가는 것이 막혀있다.
각 K8s 클러스터 노드들에 /etc/crio/crio.conf.d/default_capabilities.conf를 생성하여,
아래 옵션(“NET_RAW")을 넣어준다.
[crio.runtime] default_capabilities = [ "CHOWN", "DAC_OVERRIDE", "FSETID", "FOWNER", "SETGID", "SETUID", "SETPCAP", "NET_BIND_SERVICE", "KILL", "NET_RAW", ]

이후, systemctl restart crio를 통해 crio를 재시작하고,
ping을 사용하려는 pod(“busybox”)도 재생성해야 한다.

자세한 내용은 https://flavono123.github.io/posts/crio-capabilities-bug/ 을 참고 하기 바란다.

그러나, IP는 언제든 바뀔 수 있으므로, 이번에는 미리 만들어둔 Service를 통해 접근해보도록 하자.

당연한 말이지만, Service는 Pod가 아니라 pod의 특정 포트를 cluster ip와 포트로 연결해주는 일종의 정책이므로, 위의 ping은 도달하지 않는다.

아래와 같이 telnet을 통해 서비스 포트로 접근이 가능하다는 것을 확인할 수 있다.

Code Block
languagebash
/ # telnet nginx-svc 80
Connected to nginx-svc

/ # telnet nginx-svc-lb 8080
Connected to nginx-svc-lb

 # telnet nginx-svc-np 8081
Connected to nginx-svc-np

그럼 어떻게 pod에서 서비스 포트로 접근이 가능할까?

nslookup을 통해 도메인 찾기를 해보자.

Code Block
languagebash
/ # nslookup nginx-svc
Server:         10.96.0.10
Address:        10.96.0.10:53

** server can't find nginx-svc.svc.cluster.local: NXDOMAIN


Name:   nginx-svc.test.svc.cluster.local
Address: 10.105.132.127

위의 10.96.0.10:53kube-dns 서비스의 CLUSTER-IP이다.(kubectl get svc -n kube-system 명령으로 확인할 수 있다.)

10.105.132.127nginx-svc서비스의 CLUSTER-IP이다.

즉, CLUSTER-IP: 10.105.132.127에 대하여 nginx-svc.test.svc.cluster.local으로 도메인이 등록되어 있음을 알 수 있으며, nginx-svc는 label selector로 각 pod와 연결된다는 것을 추정할 수 있을 것이다.

참고로, 다른 domain의 pod에 접근하기 위해서는 서비스명.도메인명으로 사용하면 된다.

Code Block
languagebash
/ # nslookup nginx-svc
Server:         10.96.0.10
Address:        10.96.0.10:53

** server can't find nginx-svc.svc.cluster.local: NXDOMAIN


Name:   nginx-svc.test.svc.cluster.local
Address: 10.105.132.127

위의 10.96.0.10:53kube-dns 서비스의 CLUSTER-IP이다.(kubectl get svc -n kube-system 명령으로 확인할 수 있다.)

10.105.132.127nginx-svc서비스의 CLUSTER-IP이다.

즉, CLUSTER-IP: 10.105.132.127에 대하여 nginx-svc.test.svc.cluster.local으로 도메인이 등록되어 있음을 알 수 있으며, nginx-svc는 label selector로 각 pod와 연결된다는 것을 추정할 수 있을 것이다.

참고로, 다른 domain의 pod에 접근하기 위해서는 서비스명.도메인명으로 사용하면 된다.

Code Block
languagebash
/ # telnet kube-dns.kube-system 53
Connected to kube-dns.kube-system
Connection closed by foreign host # telnet kube-dns.kube-system 53
Connected to kube-dns.kube-system
Connection closed by foreign host

Headless Service

위 Service 예제에서는 편의상 externalIPs를 모두 할당하였다.
하지만,

  1. Pod 간 통신 즉 클러스터 내 통신만을 하기 때문에 굳이 externalIPs를 할당할 필요가 없다.

  2. 클러스터된 Pod가 2개 이상이고, 이들 pod들에 load balancing 하여 request할 필요가 없다.

등의 경우, Headless 서비스를 생성하면 되는데, 클러스터 내에서 DNS 쿼리를 하면, 앞 장에서 살펴본 CLUSTER-IP가 할당되지 않기 때문에 해당 Pod의 IP를 직접 제공해준다.

만약 2개 이상의 Pod가 seletor로 연결되어 있다면, 랜덤한 순서로 이 서비스에 연결된 모든 IP 리스트를 리턴하게 된다. 말그대로, DNS 서버 역할만 수행한다.

자세한 내용은 구글 검색 등을 통해 살펴보기를 바라며, 아래와 같이 clusterIP: None을 명시적으로 붙여주면 된다.

Code Block
languageyaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
  namespace: test
spec:
  selector:
    app: nginx # 위 matchLabels에 지정되었던 label 지정.
  type: ClusterIP
  clusterIP: None
  ports:
    - name: http
      port: 80 # targetPort를 지정하지 않을 경우, targetPort=port 설정 값.

생성 후, 앞 장의 내용대로 nslookup 테스트를 해보면 이해가 될 것이다.

정리

이 실습들을 통해 모던 어플리케이션 시스템을 어떻게 K8s 상에 구축할 것 인가에 대한 통상의 개념을 알아보았다.

...