본문 바로가기
사이드 프로젝트

[CI/CD 프로젝트] K8S - Calico 내부 동작 이해

by 간장공장공차장 2024. 11. 19.
반응형

Calico란?

Calico는 Kubernetes 클러스터에서 Pod 간의 통신을 가능하게 하는 네트워킹 솔루션입니다. Calico는 기본적으로 라우팅 기반 네트워킹을 사용하며, IP 패킷을 통해 Pod 간의 통신을 처리한다.

  • 주요 특징:
    • 고성능 네트워킹: L3 라우팅을 기반으로 하여 빠르고 효율적인 통신 제공.
    • 네트워크 보안: Kubernetes 네트워크 정책을 사용하여 Pod 간의 통신을 제어.
    • 확장성: 대규모 클러스터에서도 안정적으로 작동.

CNI의 역할

  • Pod 간 통신: CNI는 각 Pod에 고유한 IP 주소를 할당하고, 이러한 IP 주소를 통해 Pod 간에 통신할 수 있도록 설정한다. CNI 플러그인은 네트워크 브리징, 라우팅, NAT(Network Address Translation) 등과 같은 네트워크 기능을 제공한다.
  • 서비스 디스커버리: Kubernetes 서비스는 여러 Pod를 하나의 서비스로 그룹화하여 외부 요청을 처리합니다. CNI는 이러한 서비스의 네트워킹을 지원하여 클러스터 내에서 서비스 간의 원활한 통신을 가능하게 한다.
  • 네트워크 정책: CNI 플러그인은 네트워크 정책을 구현하여 Pod 간의 트래픽을 제어하고 보안을 강화할 수 있도록 한다.

앞서, containerd에서는 격리된 네트워크 스페이스에서 container가 통신하는 방법에 대하여 논의하였다.

CNI 파트에서는 서로 다른 노드에 있는 pod가 통신하는 부분에 대하여 다룬다.

BGP

BGP(Border Gateway Protocol)는 인터넷의 자율 시스템(Autonomous Systems, AS) 간 경로 정보를 교환하고 라우팅하는 프로토콜이다. 인터넷의 주요 라우팅 프로토콜로 사용되며, 네트워크 트래픽이 목적지까지 도달하는 최적 경로를 선택는 역할을 한다.

서로 다른 노드의 container ↔ container

❈ 브릿지IP는 노드끼리 대역은 겹치지 않게 사용되어야한다.(충돌 방지)

먼저, 노드 사이에 네트워크가 연결되어야 Node끼리 통신이 가능해진다. Calico를 통해 어떻게 노드끼리 네트워크가 연결되는지 알아보고자 한다.

Calico 동작 방식

  • BGP 기반 라우팅 설정:
    • Calico의 컴포넌트인 Felix와 BGP 에이전트가 있다. 이 BGP 에이전트들은 각 노드의 Pod CIDR 정보를 다른 노드와 공유한다.
    • 각 노드에 BGP 피어를 형성하여, 노드 간에 경로 정보를 주고받으면서 네트워크 토폴로지를 형성합니다.
  • Pod CIDR 학습 및 경로 설정:
    • 각 노드의 BGP 에이전트는 해당 노드의 Pod들이 위치한 서브넷을 학습한다. 이 정보는 다른 노드의 BGP 피어에게 전달되어, 클러스터 내 모든 노드가 각 노드의 Pod 정보를 가지게 된다.
  • Data Plane에서의 패킷 전달:
    • BGP 라우팅을 통해 설정된 경로 정보는 각 노드의 Linux 커널 라우팅 테이블에 반영된다.
    • Pod에서 다른 노드에 위치한 Pod로 패킷을 보내면, 해당 패킷은 Linux 커널의 라우팅 테이블을 통해 최적 경로로 전송됩니다.
    • VXLAN, IPIP, Wiregard 와 같은 오버레이(calico 컴포넌트 아님)를 통해 캡슐화/디캡슐화를 진행한다.
  • 네트워크 정책 적용:
    • Calico는 네트워크 정책을 통해 특정 Pod 간 통신을 허용하거나 차단할 수 있습니다. 이러한 네트워크 정책은 Calico가 라우팅을 설정하는 데 영향을 미치지 않지만, 각 Pod 간 통신의 허용 여부를 결정하여 보안을 강화합니다.

실습

1. Calico 설치

  • 사전 작업 : Calico veth 쌍이 컨테이너에 연결되도록 앵커링된 기본 네트워크 네임스페이스의 인터페이스에 대한 라우팅 테이블을 조작합니다. 이는 Calico 에이전트가 올바르게 라우팅하는 기능을 방해할 수 있으므로, 방해하지 못하도록 아래와 같이 설정한다.
sudo mkdir /etc/NetworkManager/conf.d/

sudo tee /etc/NetworkManager/conf.d/calico.conf << EOF
[keyfile]
unmanaged-devices=interface-name:cali*;interface-name:tunl*;interface-name:vxlan.calico;interface-name:vxlan-v6.calico;interface-name:wireguard.cali;interface-name:wg-v6.cali
EOF
  • manifest로 설치 (operater 로 설치하면 계속 오류나는데 이유 모름..)
      kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
  • 수정 원할 시 curl 나 wget을 통해서 다운 받은 후 수정해서 apply 하면 된다.
  • calico가 정상적으로 실행되고 있는지 확인한다.
  • watch kubectl get pods -n kube-system
  • Pod 정상 배포 및 접속 태스트
  • calicoctl 설치
curl -L https://github.com/projectcalico/calico/releases/download/v3.28.2/calicoctl-linux-amd64 -o calicoctl
chmod +x ./calicoctl
mv calicoctl /usr/local/bin
  • 이전 containerd 문서에서 본 바와 같이 caclico에 대한 네트워크 동작에 대해서 확인한다.
  • 테스트를 위해 먼저 deplyment를 수행해본다.
# cat deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80
  • caclico를 통해서 Ipam을 확인해본
calicoctl ipam show --show-block

  • Subnet에 대한 네트워크 장비 생성

여기서 if2는 가상 이터넷 장비가 생성된 것을 볼 수 있다.

  • route table 확인하기

위와 같이 생성된 pod에서 각각 가상 이더넷과 연결된 것을 볼 수 있다.

2. Calico 네트워크 정책 설정

개요에서, calico는 MSA환경에서 서비스 간의 상호작용을 제어한다고 설명하였다. 아래 실습으로 다른 Pod와의 통신을 차단하고, front ↔ backend 와의 통신만 허용하는 설정을 진행하는 실습을 진행한다.

  • Network 정책 설정
# allow-frontend-to-backend.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: backend
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: frontend
kubectl apply -f allow-frontend-to-backend.yaml

현재 네트워크 정책으로 app:backend 라벨을 가진 서비스의 ingress 정책으로 app: frontend의 라벨을 가진 서비스만 허용하도록 한다.

정상적으로 정책이 적용된 것을 볼 수 있다.

  • 정책 확인
kubectl get networkpolicy

  • frontend 배포deployment yaml을 만든 후 pod를 생성한다.
  • # frontend.yaml apiVersion: apps/v1 kind: Deployment metadata: name: frontend spec: replicas: 2 selector: matchLabels: app: frontend template: metadata: labels: app: frontend spec: containers: - name: frontend image: nginx ports: - containerPort: 80
kubectl apply -f frontend.yaml
  • backend 배포:
  • # backend.yaml apiVersion: apps/v1 kind: Deployment metadata: name: backend spec: replicas: 2 selector: matchLabels: app: backend template: metadata: labels: app: backend spec: containers: - name: backend image: nginx ports: - containerPort: 80

동일하게 deployment yaml을 만든 후 pod를 생성한다.

kubectl apply -f backend.yaml
  • unallowed 서비스 배포
# unallowed.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: unallowed
spec:
  replicas: 2
  selector:
    matchLabels:
      app: unallowed
  template:
    metadata:
      labels:
        app: unallowed
    spec:
      containers:
        - name: unallowed
          image: nginx
          ports:
            - containerPort: 80

동일하게 배포한다.

kubectl apply -f grafana.yaml

이제, default namespace에 3가지 서비스가 떠 있는 것을 볼 수 있다.

k get pod -n default -o wide

ip를 보고자 하면 위 명령어를 사용할 수 있다.

  • frontend → backend 접속 시도

이전에 ping이 설치가 되지 않았다고 나올 시 /etc/os-release를 확인한 후 os에 맞는 설치를 진행한다.

#debian
apt update
apt install iputils-ping

이 과정에서 calico가 정상 설치가 안되면 다운을 못받는다. 앞서 이론에서 보았듯이, pod에서 인터넷 구간은 calico담당이기 때문이다. 어쨌든 정상적으로 설치를 마쳐 ping을 수행해보자

kubectl exec -it <frontend-pod-name> -- /bin/bash
ping <backend-pod-ip>
  • pod의 ip 확인

  • frontend → backend ping 확인

  • unallowed → backend 접속 시도 
  • kubectl exec -it <grafana-pod-name> -- /bin/bash ping <backend-pod-ip>

이와 같이 ping이 가지 않는 것을 볼 수 있다. calico가 network policy를 정상적으로 수행하도록하는 것을 볼 수 있다.

Troubleshooting

  • calico설치 시 pod 대역을 aws ec2 vpc에 맞춘다고 수정했었는데 host랑 같은 대역 쓰면 calico 동작 못함. pod 랑 다른 대역을 사용해야함..(당연함,, 그게 네트워크 ns 개념임 ㅠㅠ..)
  • 모든 calico pod 로그 조회
kubectl logs -n kube-system -l k8s-app=calico-node
  • ping 설치 안됨 → pod에서 도메인은 reslov하지못함.
    • calico 로그 확인 결과 no /etc/calico/confd/config/bird.cfg 에러

조치 내용:

  1. cluster 다시 설치하였음.
    root로 권한이 지정되면서 파일 권한이 꼬인 가능성을 고려하여 root 권한이 있는 명령어에만 sudo 를 넣어서 진행하였다.
  2. calico를 설치할 때 operater → manifest 방식으로 변경하여 설치하였다.

딱히 저 파일(bird.cfg)이 없어서 문제는 아닌 것 같다. 정상 설치 → pod에서 정상 local nameserver(calico)와 연결하여 ping을 다운받을 수 있었다.

반응형