개발강의정리/DevOps

[데브옵스를 위한 쿠버네티스 마스터] 쿠버네티스 핵심개념-Network

nineDeveloper 2021. 1. 3.
728x90

Network

쿠버네티스 네트워크 모델

  • 한 포드에 있는 다수의 컨테이너끼리 통신
  • 포드끼리 통신
  • 포드와 서비스 사이의 통신
  • 외부 클라이언트와 서비스 사이의 통신
  • 실습 전 설치:
    • sudo apt install net-tools

한 포드에 있는 다수의 컨테이너끼리 통신

  • pause 명령을 실행해 아무 동작을 하지 않는 빈 컨테이너를 생성
  • 인터페이스를 공유
  • 포트를 겹치게 구성하지 못하는 것이 특징

  • Docker의 기능을 사용해 쿠버네티스 컨테이너를 관찰
  • 각 포드마다 하나의 pause 이미지 실행
$ sudo docker ps | grep pause
78c434040e28   k8s.gcr.io/pause:3.2   "/pause"                 2 hours ago   Up 2 hours             k8s_POD_weave-net-qq5bk_kube-system_850c730e-932f-4a4b-8ff3-2af47daa2b1f_4
1d1e1f608a5d   k8s.gcr.io/pause:3.2   "/pause"                 2 hours ago   Up 2 hours             k8s_POD_kube-proxy-4frsb_kube-system_9ea055c0-3566-4c36-8139-eb24564aadf2_4
d37a2925e6d9   k8s.gcr.io/pause:3.2   "/pause"                 2 hours ago   Up 2 hours             k8s_POD_kube-scheduler-master_kube-system_9be8cb4627e7e5ad4c3f8acabd4b49b3_4
9fd2da446669   k8s.gcr.io/pause:3.2   "/pause"                 2 hours ago   Up 2 hours             k8s_POD_etcd-master_kube-system_527dd0bdddb333977f0320f4dd615fe8_4
d3dc1f8376ff   k8s.gcr.io/pause:3.2   "/pause"                 2 hours ago   Up 2 hours             k8s_POD_kube-controller-manager-master_kube-system_c61f75a63a6b7c302751a6cc76c53045_4
b3ad0d87b6a7   k8s.gcr.io/pause:3.2   "/pause"                 2 hours ago   Up 2 hours             k8s_POD_kube-apiserver-master_kube-system_794b8900b469322060832f0a803ff984_4

실습

master 서버에 있는 쿠버네티스를 통해서 커버된 도커 이미지를 볼 수 있음

$ kubectl get pod --all-namespaces -o wide | grep master
kube-system   etcd-master                      1/1     Running   4          6d14h   10.0.2.15   master   <none>           <none>
kube-system   kube-apiserver-master            1/1     Running   4          6d14h   10.0.2.15   master   <none>           <none>
kube-system   kube-controller-manager-master   1/1     Running   4          6d14h   10.0.2.15   master   <none>           <none>
kube-system   kube-proxy-4frsb                 1/1     Running   4          6d14h   10.0.2.15   master   <none>           <none>
kube-system   kube-scheduler-master            1/1     Running   4          6d14h   10.0.2.15   master   <none>           <none>
kube-system   weave-net-qq5bk                  2/2     Running   12         6d14h   10.0.2.15   master   <none>           <none>

도커 명령어로 도커 컨테이너를 확인해볼 수 있음

$ docker ps -a

apiserver 도커 컨테이너 /pause 역할만 하는 pot 이미지 확인

$ docker ps | grep apiserver
7f29101039d2   75c7f7112080           "kube-apiserver --ad…"   About an hour ago   Up About an hour                         k8s_kube-apiserver_kube-apiserver-master_kube-system_794b8900b469322060832f0a803ff984_4
b3ad0d87b6a7   k8s.gcr.io/pause:3.2   "/pause"                 About an hour ago   Up About an hour                         k8s_POD_kube-apiserver-master_kube-system_794b8900b469322060832f0a803ff984_4

kube-proxy 도 확인
쿠버네티스 상에서 보면 하나만 떠있는 것 같지만 실제로는 /pause 포함 두개의 컨테이너가 떠있음

$ docker ps | grep kube-proxy
858572a27382   e3f6fcd87756           "/usr/local/bin/kube…"   2 hours ago         Up 2 hours                   k8s_kube-proxy_kube-proxy-4frsb_kube-system_9ea055c0-3566-4c36-8139-eb24564aadf2_4
1d1e1f608a5d   k8s.gcr.io/pause:3.2   "/pause"                 2 hours ago         Up 2 hours                   k8s_POD_kube-proxy-4frsb_kube-system_9ea055c0-3566-4c36-8139-eb24564aadf2_4

ifconfig 명령어로 쿠버네티스 네트워크 인터페이스들을 확인할 수 있다

가상의 인터페이스를 하나 만들어서 서로 통신을 하고 있는 구조
veth 하나의 pot에는 하나의 인터페이스가 구현이 되어있어서 서로 간의 IP를 공유할 수 있도록 만들어진 시스템

포드끼리 통신

  • 포드끼리의 통신을 위해서는 CNI 플러그인이 필요
  • ACI, AOS, AWS VPN CNI, CNI-Genie, GCE, flannel, Weave Net, Calico 등

  • CNI 플러그인 지원 기능 설명
기능 설명
Network Model VXLAN: 캡슐화된 네트워킹으로 이론적으로 속도가 느림
레이어2 네트워킹: 캡슐화되지 않았기 때문에 오버 헤드의 영향이 없음
Route Distribution BGP 프로토콜 사용
네트워크 세그먼트에 분할 된 클러스터를 구축하려는 경우 사용
인터넷에서 라우팅 및 연결 가능성 정보를 교환하도록 설계된 외부 게이트웨이 프로토콜
Network Policies 네트워크 정책을 사용하여 포드가 서로 통신 할 수있는 규칙을 적용
Mesh Networking 쿠버네티스 클러스터 간 "Pod to Pod"네트워킹이 가능
Kubernetes 페레이션이 아니라 포드 간의 순수한 네트워킹입니다
Encyption 네트워크 컨트롤 플레인을 암호화하여 모든 TCP 및 UDP 트래픽을 암호화
Ingress / Egress Policies 들어오거나 나가는 패킷에 대한 통신 제어
  • 프로세스 및 포트 확인
$ sudo netstat -antp | grep weave
tcp        0      0 127.0.0.1:6784          0.0.0.0:*               LISTEN      3903/weaver
tcp        0      0 10.0.2.15:57428         10.96.0.1:443           ESTABLISHED 3352/weave-npc
tcp6       0      0 :::6781                 :::*                    LISTEN      3352/weave-npc
tcp6       0      0 :::6782                 :::*                    LISTEN      3903/weaver
tcp6       0      0 :::6783                 :::*                    LISTEN      3903/weaver
tcp6       0      0 10.0.2.15:6783          10.0.2.7:49735          ESTABLISHED 3903/weaver
tcp6       0      0 10.0.2.15:6783          10.0.2.6:52249          ESTABLISHED 3903/weaver

$ ps -eaf | grep 3903
root        3903    3811  0 10:46 ?        00:00:05 /home/weave/weaver --port=6783 --datapath=datapath --name=56:00:8d:3a:55:29 --host-root=/host --http-addr=127.0.0.1:6784 --metrics-addr=0.0.0.0:6782 --docker-api= --no-dns --db-prefix=/weavedb/weave-net --ipalloc-range=10.32.0.0/12 --nickname=master --ipalloc-init consensus=2 --conn-limit=200 --expect-npc --no-masq-local 10.0.2.6 10.0.2.7
server1    47834   45771  0 12:53 pts/1    00:00:00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn --exclude-dir=.idea --exclude-dir=.tox 3903

$ docker ps | grep weave
3f653c9f0fd5   a8ef3e215aac           "/home/weave/launch.…"   2 hours ago   Up 2 hours             k8s_weave_weave-net-qq5bk_kube-system_850c730e-932f-4a4b-8ff3-2af47daa2b1f_8
1bc1d89facf8   db66692318fc           "/usr/bin/launch.sh"     2 hours ago   Up 2 hours             k8s_weave-npc_weave-net-qq5bk_kube-system_850c730e-932f-4a4b-8ff3-2af47daa2b1f_4
78c434040e28   k8s.gcr.io/pause:3.2   "/pause"                 2 hours ago   Up 2 hours             k8s_POD_weave-net-qq5bk_kube-system_850c730e-932f-4a4b-8ff3-2af47daa2b1f_4

weave-net 에 관련된 설정파일 확인
demonset 이라는 것을 통해서 node 마다 정확히 하나씩 포드를 배치하는 방식으로 배치하고 있음
포드를 몇개씩 설치하라고 설정하지 않아도 각각의 node 마다 하나씩 설치함

$ kubectl get ds weave-net -n kube-system -o yaml

포드와 서비스 사이의 통신

  • ClusterIP를 생성하면 iptables의 설정 적용

그림 출처: https://kubernetes.io/docs/concepts/services-networking/service/#proxy-mode-iptables

  • Kube-proxy라는 컴포넌트로 서비스 트래픽을 제어
  • Iptables는 리눅스 커널 기능인 netfilter를 사용하여 트래픽을 제어

그림 출처: https://ko.wikipedia.org/wiki/Iptables

  • 다음 그림은 서비스 IP를 통해 10.3.241.152을 요청하는 흐름을 나타냄

그림 출처: https://medium.com/google-cloud/understanding-kubernetes-networking-services-f0cb48e4cc82

  • ClusterIP를 생성하면 iptables의 설정 적용이 됨
  • Iptable에서 목록을 확인하는 실습
$ kubectl get svc --all-namespaces
NAMESPACE     NAME          TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)                  AGE
default       kubernetes    ClusterIP   10.96.0.1      <none>        443/TCP                  6d15h
kube-system   kube-dns      ClusterIP   10.96.0.10     <none>        53/UDP,53/TCP,9153/TCP   6d15h

$ sudo iptables -S -t nat | grep 10.96
-A KUBE-SERVICES -d 10.96.0.1/32 -p tcp -m comment --comment "default/kubernetes:https cluster IP" -m tcp --dport 443 -j KUBE-SVC-NPX46M4PTMTKRN6Y
-A KUBE-SERVICES -d 10.96.0.10/32 -p udp -m comment --comment "kube-system/kube-dns:dns cluster IP" -m udp --dport 53 -j KUBE-SVC-TCOU7JCQXEZGVUNU
-A KUBE-SERVICES -d 10.96.0.10/32 -p tcp -m comment --comment "kube-system/kube-dns:dns-tcp cluster IP" -m tcp --dport 53 -j KUBE-SVC-ERIFXISQEP7F7OF4
-A KUBE-SERVICES -d 10.96.0.10/32 -p tcp -m comment --comment "kube-system/kube-dns:metrics cluster IP" -m tcp --dport 9153 -j KUBE-SVC-JD5MR3NA4I4DYORP

외부 클라이언트와 서비스 사이의 통신

  • 앞서 학습한대로 netfilter와 kube-proxy 기능을 사용해 원하는 서비스 및 포드로 연결

그림 출처: https://medium.com/google-cloud/understanding-kubernetes-networking-ingress-1bc341c84078

DNS 서비스를 이용한 서비스 검색

  • 서비스를 생성하면, 대응되는 DNS 엔트리가 생성
  • 이 엔트리는 <서비스-이름>.<네임스페이스-이름>.svc.cluster.local의 형식을 가짐
$ kubectl exec -it http-go-rs-4l52m bash

root@http-go-rs-4l52m:/# curl http-go-svc.default.svc.cluster.local
Welcome! http-go-rs-5pspr

root@http-go-rs-4l52m:/# curl http-go-svc.default
Welcome! http-go-rs-5pspr

root@http-go-rs-4l52m:/# curl http-go-svc

CoreDNS

  • 내부에서 DNS 서버 역할을 하는 POD이 존재
  • 각 미들웨어를 통해 로깅, 캐시, 쿠버네티스를 질의하는 등의 기능을 가짐

  • 해당 DNS에는 configmap 저장소를 사용해 설정 파일을 컨트롤
  • Corefile을 통해 현재 클러스터의 NS를 지정
$ kubectl get configmap coredns -n kube-system -o yaml
apiVersion: v1
data:
  Corefile: |
    .:53 {
        errors
        health {
           lameduck 5s
        }
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
           pods insecure
           fallthrough in-addr.arpa ip6.arpa
           ttl 30
        }
        prometheus :9153
        forward . /etc/resolv.conf {
           max_concurrent 1000
        }
        cache 30
        loop
        reload
        loadbalance
    }
...

POD에서도 Subdomain을 사용하면 DNS 서비스를 사용 가능

  • yaml 파일의 호스트 이름은 포드의 metadata.name을 따름
  • 필요한 경우 hostname을 따로 선택 가능
  • subdomain은 서브도메인을 지정하는 데 사용
  • 서브 도메인을 설정하면 FQDN 사용 가능
  • FQDN 형식과 예

연습문제

  • 네임스페이스 blue에 jenkins 이미지를 사용하는 pod-jenkins 디플로이먼트를 생성하고 이를 위한 서비스 srv-jenkins를 생성하라

blue 네임스페이스 생성 스크립트 추가

$ kubectl create ns blue --dry-run=client -o yaml > blue-jenkins-svc-deploy.yaml

deployment 생성 스크립트 추가

$ kubectl create deploy pod-jenkins --image=jenkins --dry-run=client -o yaml -n blue >> blue-jenkins-svc-deploy.yaml

blue 네임스페이스와 deployment 생성

$ kubectl create -f blue-jenkins-svc-deploy.yaml
namespace/blue created
deployment.apps/pod-jenkins created

서비스 생성 스크립트 추가
metadata 에 namespace: blue 가 추가되어있지 않으면 추가

서비스 생성

$ kubectl expose deploy pod-jenkins --port=8080 --target-port=8080 --type=NodePort --name srv-jenkins --dry-run=client -o yaml -n blue >> blue-jenkins-svc-deploy.yaml

최종 생성된 스크립트

apiVersion: v1
kind: Namespace
metadata:
  creationTimestamp: null
  name: blue
spec: {}
status: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: pod-jenkins
  name: pod-jenkins
  namespace: blue
spec:
  replicas: 1
  selector:
    matchLabels:
      app: pod-jenkins
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: pod-jenkins
    spec:
      containers:
      - image: jenkins
        name: jenkins
        resources: {}
status: {}
---
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: pod-jenkins
  name: srv-jenkins
  namespace: blue
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    app: pod-jenkins
  type: NodePort
status:
  loadBalancer: {}

서비스 생성

$ kubectl create -f blue-jenkins-svc-deploy.yaml
service/srv-jenkins created
Error from server (AlreadyExists): error when creating "blue-jenkins-svc-deploy.yaml": namespaces "blue" already exists
Error from server (AlreadyExists): error when creating "blue-jenkins-svc-deploy.yaml": deployments.apps "pod-jenkins" already exists

http-go 컨테이너 생성 및 실행

$ kubectl create deploy http-go --image=gasbugs/http-go
deployment.apps/http-go created
  • default 네임스페이스의 http-go 이미지의 curl을 사용하여 pod-jenkis:8080을 요청하라

포드를 확인해서 Running 상태가 되면 요청

$ kubectl get pod
NAME                      READY   STATUS    RESTARTS   AGE
http-go-568f649bb-9qmct   1/1     Running   0          114s

$ kubectl exec http-go-568f649bb-9qmct -- curl srv-jenkins.blue:8080

DNS를 알게 되었으니 IP를 사용하지 않고 네임스페이스와 서비스만 있다면 이 요청을 가지고 얼마든지 응답을 받아낼 수 있음

728x90

댓글

💲 추천 글