AEWS 스터디는 [PKOS 스터디]와 비슷한 내용으로 구성되어 있습니다. K8s 클러스터를 운영하기 위해서 알아야하는 기본적인 네트워크 지식을 한번더 스터디하며 그때는 이해하지 못하고 넘어간 부분들이 지금에 와서는 조금더 눈에 들어오기 시작했습니다.
2주차는 육용수
님과 고재성
님의 경험발표를 들을 수 있었습니다.
육용수님은 EKS 템플릿을 테라폼으로 구축하는 경험을 공유해주셨습니다.
고재성님은 AWS 신상 서비스인 VPC Latteci에 대해서 설명해주시고 핸즈온을 직접 시연해주셨습니다.
PKOS 스터디를 통해 한번 진행한 내용이므로, 간단하게 중요한 내용 위주로 정리하였습니다.
가시다님의 원클릭 실습 배포 Cloudformation Template를 이용하여 손쉽게 배포하였습니다.
배포가 완료된 아키텍처는 아래와 같습니다.
Architecture
AWS를 이용하는 경우 AWSVPC CNI를 이용할 수 있습니다.
다양한 플러그인이 존재하지만, 대표적으로 많이 사용하는 Calico CNI 등 여러 플러그인과 대조되는 차이점으로는
파드의 IP를 할당해준다, 파드의 IP 네트워크 대역과 노드(워커)의 IP 대역이 같아서 직접 통신이 가능하다
- VPC 와 통합 : VPC Flow logs , VPC 라우팅 정책, 보안 그룹(Security group) 을 사용 가능함
- This plugin assigns an IP address from your VPC to each pod.
- VPC ENI 에 미리 할당된 IP(=Local-IPAM Warm IP Pool)를 파드에서 사용할 수 있음
여러가지 장점이 있습니다.
Important !!
파드간 통신 시 일반적으로
K8S CNI
는 오버레이(VXLAN, IP-IP 등) 통신을 하고,AWS VPC CNI
는 동일 대역으로 직접 통신을 합니다이를 통해 패킷을 위한 오버헤드를 줄여 네트워크 성능을 향상할 수 있습니다.
실습
네트워크 정보를 확인합니다.
서로 다른 노드에 배포 되어있는 파드간 통신에서 AWS VPC CNI 경우 별도의 오버레이(Overlay) 통신 기술 없이, VPC Native 하게 파드간 직접 통신이 가능합니다.
Architecture
Life of a Pod to Pod Ping Packet
iptable
의 SNAT 을 통하여 노드의 eth0 IP로 변경되어서 외부와 통신하게 됩니다.
Architecture
실습
VPC CNI 의 External source network address translation (
SNAT
) 설정에 따라, 외부(인터넷) 통신 시 SNAT 하거나 혹은 SNAT 없이 통신을 할 수 있습니다.파드 shell 실행 후 외부로 ping 테스트 & 워커 노드에서 tcpdump 및 iptables 정보 확인 합니다.
Iptable의 내용을 조회하면 현재 사용중인 CIDR를 제외한 연결은 SNAT으로 향하도록 설정된 내용을 확인 할 수 있습니다.
Secondary IPv4 addresses (기본값) : 인스턴스 유형에 최대 ENI 갯수와 할당 가능 IP 수를 조합하여 선정합니다. PKOS 스터디때도 이부분이 제일 이해하기 힘들었습니다.
👉🏻 최대 파드 생성 갯수 : (Number of network interfaces for the instance type × (the number of IP addressess per network interface - 1)) + 2
실습
파드 50개 배포시 Pending 됨을 확인할 수 있습니다.
쿠버네티스에서는 서비스로 ClusterIP
NodePort
Loadbalancer
등 다양한 형태의 리소스가 존재합니다.
이중 LoadBalancer Controller
에 대해서 정리하겠습니다.
Service -
LoadBalancer Controller
다른 서비스와 차이점은 Load Balancer를 컨트롤 하기위한 파드가 생성되며, 이 파드를 통해 AWS의 NLB가 사용자의 요청에 의해 생성, 제거 됩니다.
또한, AWS NLB에서 노드의 IP를 통해 파드로 트래픽이 전달되는 것이 아닌, 파드의 IP에 직접 트래픽을 전달하는 것을 볼 수 있습니다.
AWS NLB 모드에서의 타겟그룹 설정시 주의사항 입니다.
인스턴스 유형
externalTrafficPolicy
: ClusterIP ⇒ 2번 분산 및 SNAT으로 Client IP 확인 불가능 ←LoadBalancer
타입 (기본 모드) 동작externalTrafficPolicy
: Local ⇒ 1번 분산 및 ClientIP 유지, 워커 노드의 iptables 사용함IP 유형 ⇒ 반드시 AWS LoadBalancer 컨트롤러 파드 및 정책 설정이 필요함!
Proxy Protocol v2 비활성화
⇒ NLB에서 바로 파드로 인입, 단 ClientIP가 NLB로 SNAT 되어 Client IP 확인 불가능Proxy Protocol v2 활성화
⇒ NLB에서 바로 파드로 인입 및 ClientIP 확인 가능(→ 단 PPv2 를 애플리케이션이 인지할 수 있게 설정 필요)
실습
AWS Loadbalancer 컨트롤러 파드를 Helm 차트를 이용하여 배포합니다.
요청에 따라, 적절하게 ELB를 생성, 삭제 등 컨트롤 할 수 있어야 하므로, 동작에 필요한 Policy가 부여되어 있는것을 확인 할 수 있습니다.
Deployment를 생성하여 NLB의 동작을 확인합니다.
배포 후 NLB의 주소로 요청을 보내면 아래와 같이 로드밸런싱 동작이 잘 수행되는것을 확인할 수 있습니다.
클러스터 내부의 서비스(ClusterIP, NodePort, Loadbalancer)를 외부로 노출(HTTP/HTTPS) - Web Proxy 역할을 합니다.
역시 alb를 확인하면 pod의 ip로 직접 통신하는것을 확인할 수 있습니다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
namespace: game-2048
name: ingress-2048
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
spec:
ingressClassName: alb
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: service-2048
port:
number: 80
K8S 서비스/인그레스 생성 시 도메인을 설정하면, AWS(Route 53), Azure(DNS), GCP(Cloud DNS) 에 A 레코드(TXT 레코드)로 자동 생성/삭제 합니다.
실습 - tetris ExternelDNS 사용하여 배포하기
externelDNS 기능을 이용해서, k8s 리소스의 설정만으로 도메인을 할당할 수 있는 것을 확인할 수 있습니다.
SSL 이용하여 NLB에 Https 적용
Tetris를 tetris.<자신의 도메인>으로 배포하며 NLB에서 SSL 적용하여 https 통신을 하는 실습을 추가로 진행 하였습니다.
# 도메인 및 HTTPS 적용을 위한 ACM 변수 설정
MyDomain=<도메인 이름>
MyDomain=xgro.be
CERT_ARN=`aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text`
echo $MyDomain $CERT_ARN
# 테트리스 배포
cat <<EOF | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: tetris
labels:
app: tetris
spec:
replicas: 1
selector:
matchLabels:
app: tetris
template:
metadata:
labels:
app: tetris
spec:
containers:
- name: tetris
image: bsord/tetris
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: tetris
annotations:
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip
service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "http"
# service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: "80"
service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "${CERT_ARN}"
service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "https"
external-dns.alpha.kubernetes.io/hostname: "tetris.${MyDomain}"
spec:
selector:
app: tetris
ports:
- port: 80
protocol: TCP
targetPort: 80
name: http
- port: 443
targetPort: 80
protocol: TCP
name: https
type: LoadBalancer
loadBalancerClass: service.k8s.aws/nlb
EOF
결과
도메인이 https 프로토콜을 이용하여 연결되는것을 확인할 수 있습니다.
AWS Docs - https://docs.aws.amazon.com/eks/latest/userguide/alb-ingress.html
ExternelDNS - https://edgehog.blog/a-self-hosted-external-dns-resolver-for-kubernetes-111a27d6fc2c
AWSVPC_CNI - https://github.com/aws/amazon-vpc-cni-k8s/blob/master/docs/cni-proposal.md