Kubernetes

[PKOS] 2주차 - AWS VPC CNI

라온클 2023. 3. 19. 05:27

 

PKOS 스터디 소개

본 포스팅은 가시다님의 PKOS(Production Kubernetes Online Study)스터디 내용을 정리한 것이다.

이번 PKOS 스터디는 스터디, 스터디 노션 자료, 과제(본 포스팅) 모두  <24단계 실습으로 정복하는 쿠버네티스> 내용을 기반으로 진행한다.

 

AWS VPC CNI 소개

쿠버네티스 CNI란?

Container Network Interface. 쿠버네티스의 네트워크 환경을 구성하는 역할을 맡는다.

CNCF 프로젝트인 CNI는 Linux 컨테이너에서 네트워크 인터페이스를 구성하기 위한 플러그인을 작성하기 위한 사양 및 라이브러리와 지원되는 여러 플러그인으로 구성됩니다. 
CNI는 '컨테이너의 네트워크 연결성'과 '컨테이너 삭제 시 할당된 리소스 제거'에만 관심이 있습니다.

출처: https://github.com/containernetworking/cni#what-is-cni 

Calico, Flannel, Cilium, Weave 등 다양한 CNI 플러그인들이 존재한다.
https://kubernetes.io/docs/concepts/cluster-administration/addons/ 
https://github.com/containernetworking/cni#3rd-party-plugins 

 

 

AWS VPC CNI란?

AWS에서 Elastic Network Interfaces 를 사용하는 쿠버네티스의 Pod 네트워킹을 위한 네트워킹 플러그인.

출처: https://github.com/aws/amazon-vpc-cni-k8s#amazon-vpc-cni-k8s 
한마디로 AWS에서 만든 CNI 플러그인이라고 생각하면 편하다.


AWS VPC CNI의 특징

  • 파드의 IP를 할당해준다
  • 파드의 IP 네트워크 대역과 노드(워커)의 IP 대역이 같아서 직접 통신이 가능하다

 

본 스터디의 기본 환경인 Kops에서도 AWS VPC CNI를 정식으로 지원한다.

https://kops.sigs.k8s.io/networking/#supported-networking-options 

https://kops.sigs.k8s.io/networking/aws-vpc/

쿠버네티스 CNI(Calico) 와 AWS VPC CNI 의 차이점은?

AWS VPC CNI의 특징은 노드와 Pod의 네트워크 대역이 동일하다는 것이다.

 

노드와 Pod의 네트워크 대역이 동일하면 무엇이 좋을까?

오버레이(VXLAN, IP-IP 등) 통신 기술 없이, VPC Native하게(클라우드 위엄) Pod간 직접 통신이 가능하다.

Pod간 직접 통신이 가능하면, 네트워크 통신의 최적화(성능, 지연)면에서 더 나은 결과를 얻을 수 있다.

 

 

쿠버네티스 네트워크

Service

Cluster IP

Cluster IP는 클러스터 내부에 한해서 Pod끼리 통신하기 위한 서비스다.
서비스를 만들 때 type을 별도로 지정하지 않으면 기본값으로 Cluster IP가 생성된다.
Cluster IP는 클러스터 외부에서 Pod로 접근할 수 없다.

apiVersion: v1
kind: Service
metadata:
  name: svc-clusterip
spec:
  selector:
    app: pod
  ports:
  - port: 9000
    targetPort: 8080
  type: ClusterIP

 

 

 

NodePort

NodePort는 클러스터 외부로부터 모든 워커노드들의 특정 포트(=NodePort)를 통해서 Pod에 접근할 수 있도록 설정하는 서비스다.
노드포트 번호 대역은 30000~32767다.

apiVersion: v1
kind: Service
metadata:
  name: svc-nodeport
spec:
  selector:
    app: pod
  ports:
  - port: 9000
    targetPort: 8080
    nodePort: 30000
  type: NodePort


Load Balancer

클러스터 외부에서 올바른 포트로 트래픽을 전송할 수 있도록 접근 가능한 IP 주소를 제공하는 서비스다.
보통 CSP에서 제공하는 LB플러그인으로 설정한다.

apiVersion: v1
kind: Service
metadata:
  name: svc-lb
spec:
  selector:
    app: example
  ports:
    - port: 8765
      targetPort: 9376
  type: LoadBalancer



 

Ingress

Ingress는 HTTP, HTTPS 등 네트워크 Layer 7에 대한 설정을 담당하는 리소스다.

https://lifeoncloud.kr/entry/Ingress

 

Ingress

Ingress는 HTTP, HTTPS 등 네트워크 Layer 7에 대한 설정을 담당하는 리소스다. Ingress의 가장 기본적인 역할은 외부 HTTP 호출에 대한 트래픽을 처리하는 것이다. (예시 : 부하 분산, TLS 종료, 도메인 기반

lifeoncloud.kr

 

Ingress + ALB + ExternalDNS

# 변수 지정 - 자신의 full 도메인
WEBDOMAIN=<각자편한웹서버도메인>
WEBDOMAIN=albweb.$KOPS_CLUSTER_NAME

 

ingress2.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: game-2048
---
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: game-2048
  name: deployment-2048
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: app-2048
  replicas: 2
  template:
    metadata:
      labels:
        app.kubernetes.io/name: app-2048
    spec:
      containers:
      - image: public.ecr.aws/l6m2t8p7/docker-2048:latest
        imagePullPolicy: Always
        name: app-2048
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  namespace: game-2048
  name: service-2048
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  type: NodePort
  selector:
    app.kubernetes.io/name: app-2048
---
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:
    - host: ${WEBDOMAIN}
      http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: service-2048
              port:

 

 

배포한다

# 게임 Pod와 Service, Ingress 배포
cat ~/pkos/3/ingress2.yaml | yh
WEBDOMAIN=$WEBDOMAIN envsubst < ~/pkos/3/ingress2.yaml | kubectl apply -f -

# 확인
kubectl get ingress,svc,ep,pod -n game-2048

# AWS R53 적용 확인
dig +short $WEBDOMAIN
dig +short $WEBDOMAIN @8.8.8.8

# 외부단말(집PC 등)에서 접속 확인 : curl or 웹브라우저

# 로그 확인
kubectl logs -n kube-system -f $(kubectl get po -n kube-system | egrep -o 'external-dns[A-Za-z0-9-]+')

# 삭제
kubectl delete ingress ingress-2048 -n game-2048
kubectl delete svc service-2048 -n game-2048 && kubectl delete deploy deployment-2048 -n game-2048 && kubectl delete ns game-2048

 

 

이걸 그림으로 표현하면 다음과 같다.

 

 

 

<과제> 하위 path별 애플리케이션 연결하기

네임스페이스

apiVersion: v1
kind: Namespace
metadata:
  name: game

 

 

mario 애플리케이션과 서비스

apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: game
  name: mario
  labels:
    app: mario
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mario
  template:
    metadata:
      labels:
        app: mario
    spec:
      containers:
      - name: mario
        image: pengbai/docker-supermario
---
apiVersion: v1
kind: Service
metadata:
  namespace: game
  name: mario
  annotations:
    alb.ingress.kubernetes.io/healthcheck-path: /mario/index.html
spec:
  selector:
    app: mario
  ports:
  - port: 80
    protocol: TCP
    targetPort: 8080
  type: NodePort
  externalTrafficPolicy: Local

 

 

tetris 애플리케이션과 서비스

apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: game
  name: tetris
  labels:
    app: tetris
spec:
  replicas: 1
  selector:
    matchLabels:
      app: tetris
  template:
    metadata:
      labels:
        app: tetris
    spec:
      containers:
      - name: tetris
        image: bsord/tetris
---
apiVersion: v1
kind: Service
metadata:
  namespace: game
  name: tetris
  annotations:
     alb.ingress.kubernetes.io/healthcheck-path: /tetris/index.html
spec:
  selector:
    app: tetris
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  type: NodePort

 

Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  namespace: game
  name: ingress-game-soojin
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/certificate-arn: {Certificate Manager에서 발급받은 정보}
    alb.ingress.kubernetes.io/healthcheck-port: traffic-port
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]'
    alb.ingress.kubernetes.io/ssl-redirect: '443'
spec:
  ingressClassName: alb
  rules:
    - host: {내 도메인}
      http:
        paths:
        - path: /tetris
          pathType: Prefix
          backend:
            service:
              name: tetris
              port:
                number: 80
        - path: /mario
          pathType: Prefix
          backend:
            service:
              name: mario
              port:
                number: 80

 

 

 

웹브라우저로 접속해보자

 

 

 

 

 

리소스 삭제

꺼진 불.. 아니 꺼진 리소스도 다시 보자.

 

 

위부터 아래로 순서대로 삭제하자

# kops 삭제
kops delete cluster --yes

# Cloud Formation 스택 삭제
aws cloudformation delete-stack --stack-name mykops