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를 사용하지 않고 네임스페이스와 서비스만 있다면 이 요청을 가지고 얼마든지 응답을 받아낼 수 있음
'개발강의정리 > DevOps' 카테고리의 다른 글
[데브옵스를 위한 쿠버네티스 마스터] 쿠버네티스 핵심개념-Statefulset (0) | 2021.01.03 |
---|---|
[데브옵스를 위한 쿠버네티스 마스터] 쿠버네티스 핵심개념-Storage (0) | 2021.01.03 |
[데브옵스를 위한 쿠버네티스 마스터] 쿠버네티스 핵심 개념-Services (0) | 2020.12.27 |
[데브옵스를 위한 쿠버네티스 마스터] 쿠버네티스 핵심 개념-Namespaces (0) | 2020.12.27 |
[데브옵스를 위한 쿠버네티스 마스터] 쿠버네티스 핵심 개념-애플리케이션 롤링 업데이트와 롤백 (0) | 2020.12.04 |
댓글