PKOS Study #1 kOps에 이어 이번 #2에는 Kubernetes Network에 대해 정리할 예정이다.
사실 eks나 kOps나 배포 자체는 어렵지 않고 Docker Image을 통해 Container을 배포하는 것도 조금만 찾아보면 쉽게 따라 할 수 있다.
하지만 Network는 이해하는 영역이나 컨트롤 하는 부분이 어렵고 이 부분에 대해 자세히 학습할 수 있는 기회가 많지 않다.
이번 스터디 때는 그 부분에 대해 상세하게 설명을 들을 수 있었고 실습을 통해 이해의 영역이 조금 더 넓어진 것 같다.
0. 환경 구성
기존에 직접 kOps EC2를 배포해서 설정한 뒤에 kOps 배포를 진행했지만 이번 실습부터는 간편하게 설정 된 one-click kOps 배포 yaml을 사용하여 진행할 예정이다.
one-click yaml로 환경 배포 후 IAM 정책을 생성하고 EC2 Instance Profile에 Attach 한다.
IAM Policy은 https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.4.5/docs/install/iam_policy.json 파일을 통해 진행했다.
1. AWS VPC CNI?
CNI : Container Network Interface로 컨테이너 간의 네트워킹 제어 플러그인을 위한 표준이다. k8s에서는 Pod간의 네트워킹을 위해 CNI을 사용한다. kubenet이라는 자체 k8s CNI 플러그인이 있지만 기능이 부족하여 Calico, Weave 등을 사용하기도 한다.
Amazon VPC CNI : Node에 VPC IP Address을 할당하고 각 Node의 Pods에 대한 필수 네트워킹을 구성하는 역할을 한다.
특징으로는 Node와 Pods의 IP Range가 동일하게 Node<->Pods 통신이 가능하고 VPC Flow logs, Routing Table, Security Group 등을 지원한다.
VPC 연계되는 리소스들을 지원하기 때문에 AWS 인프라를 관리하는 것과 비슷한 방식으로 네트워크 환경을 관리할 수 있는 이점이 있다.
Node와 Pods의 IP을 확인하는 명령어를 입력하면 아래와 같이 Node와 Pods의 IP가 동일한 대역(172.30.*.*)을 사용하는 것을 확인할 수 있다.
# 노드 IP 확인
aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,PrivateIPAdd:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output table
# 파드 IP 확인
kubectl get pod -n kube-system -o=custom-columns=NAME:.metadata.name,IP:.status.podIP,STATUS:.status.phase
2. Pods 간 통신 확인
Master Node와 Worker Node의 보조 IPv4을 확인해보면 아래와 같이 확인 할 수 있다.
Worker Node #1과 #2에 각각 Pod을 생성 후 두 Pods의 통신을 확인해볼 계획이다.
우선 테스트 Pods을 생성한 뒤 생성 된 Pods의 IP을 확인한다.
# 테스트용 파드 netshoot-pod 생성
cat <<EOF | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: netshoot-pod
spec:
replicas: 2
selector:
matchLabels:
app: netshoot-pod
template:
metadata:
labels:
app: netshoot-pod
spec:
containers:
- name: netshoot-pod
image: nicolaka/netshoot
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
EOF
# 파드 이름 변수 지정
PODNAME1=$(kubectl get pod -l app=netshoot-pod -o jsonpath={.items[0].metadata.name})
PODNAME2=$(kubectl get pod -l app=netshoot-pod -o jsonpath={.items[1].metadata.name})
# 파드 확인
kubectl get pod -o wide
kubectl get pod -o=custom-columns=NAME:.metadata.name,IP:.status.podIP
Pod #1에서 Pod #2로 Ping을 시도했을 때 정상적으로 Ping이 가는 것을 확인 할 수 있다.
만약 Ping이 제대로 가지 않는다면 Routing Table 정보가 업데이트 되었는지 확인해봐야 한다. (기본적으로는 자동으로 업데이트가 된다.)
Worker Node에서 ip route 정보를 확인해보면 Pods 간 통신시에는 Overlay을 사용하지 않고 Pods간 직접 통신을 하는 것을 확인 할 수 있다. 여기서 Overlay을 사용한다는 뜻은 가상의 네트워크를 만들어서 해당 네트워크를 통해 통신하게 한다는 의미이다. Amazon VPC CNI을 사용하면 해당 기술을 사용하지 않고도 직접적으로 Pods간 통신이 가능하게 된다.
3. Pods -> 외부 통신 확인
2번에서 Pods간 통신을 확인했다면 이번에는 Pods -> 외부 통신을 확인하려 한다.
외부 통신을 할 때에는 Pods 간 통신과는 다르게 Node의 IP(eth0)로 변경되어 외부로 통신을 나가게 된다.
위 흐름에 따라 통신이 된다면 Pod에서 외부 통신을 수행할 경우 소속 된 Worker Node의 Public IP을 통해 통신을 하게 된다.
아래 켑쳐 화면을 보면 Worker Node의 Public IP인 3.36.113.87을 통해 Pod가 외부 통신을 하는 것을 확인할 수 있다.
물론 이는 기본적인 Amazon VPC CNI의 SNAT Rule에 따른 것이고 SNAT Rule을 변경하게 되면 이 부분은 변경 될 수 있다.
SNAT Rule을 확인한 화면은 아래와 같다.
Worker Node에 접속하여 확인한 화면이고 Source NAT IP을 172.30.53.166을 할당한다는 뜻이다. 해당 IP에 Attach된 Public IP는 외부 통신 확인하는 사진에서 볼 수 있듯이 172.30.53.166->3.36.113.87임을 알 수 있다. 내부에서 보기에는 Public IP을 바라보는 것이 아닌 Private IP인 172.30 대역을 바라보고 이후 Attach 된 Public IP(3.36.*.*)으로 외부 통신 됨을 확인할 수 있다.
4. 마무리
Node와 Pods 배포 및 내/외부 통신을 확인하는 과정을 진행하였다.
본 과제에는 정리하지 못하였으나 Loadbalancer와 Ingress 도 실습을 진행해보았다. 다만, 내용을 아직 이해하지 못했고 단순 따라하기 정도에 그친 부분이 있어 이 부분은 조금 더 실습을 진행하고 내가 이해한 부분을 정리할 수 있도록 해야겠다.
CNI에 대해 완벽하게 내용을 이해하지는 못하였지만 Pods간 통신과 Pods->외부 통신에 대한 원리를 이해할 수 있었던 게 이번 과정에서 제일 의미 있던 부분이라고 생각 된다.
“PKOS Study #2-1 – Kubernetes Network”에 대한 2개의 생각