-
[컨테이너] 파드 네트워킹 살짝 열어보기DevOps, 클라우드/Container 2024. 11. 17. 20:47
CNI에 이어서
지난 포스팅에서는 처음으로 CNI 스펙에 관련된 내용을 보면서, 어떤 인터페이스를 구현해야 하는지 확인했다.
이번에도 파드 네트워킹이나 네트워크 인터페이스 흐름이 어떻게 되는지 얕고 난잡하게 알아보자.
파드 네트워크 구성
파드 네트워크 생성 흐름을 살짝 확인해보자.
Kubelet이 파드를 노드에 스케줄링하면, 파드에서 네트워크 설정을 요청한다.
그러면, Kubelet이 CNI를 통해서 파드의 네트워크를 설정한다.
CNI는 내부에서 네임스페이스를 생성해 네트워크를 격리하고, IP와 네트워크 인터페이스를 할당한다.
이런 과정을 통해서 파드가 Kubelet-CNI를 통해 클러스터에 등록되고 통신한다.
이런 과정을 CRI 구현체에서 확인할 수 있는데, 이는 다음과 같다.
// containerd/internal/cri/server/sandbox_run.go // setupPodNetwork setups up the network for a pod func (c *criService) setupPodNetwork(ctx context.Context, sandbox *sandboxstore.Sandbox) error { var ( id = sandbox.ID config = sandbox.Config path = sandbox.NetNSPath netPlugin = c.getNetworkPlugin(sandbox.RuntimeHandler) err error result *cni.Result ) if netPlugin == nil { return errors.New("cni config not initialized") } if c.config.UseInternalLoopback { err := c.bringUpLoopback(path) if err != nil { return fmt.Errorf("unable to set lo to up: %w", err) } } opts, err := cniNamespaceOpts(id, config) // <---------- 여기서 네트워크 네임스페이스 설정 if err != nil { return fmt.Errorf("get cni namespace options: %w", err) } log.G(ctx).WithField("podsandboxid", id).Debugf("begin cni setup") netStart := time.Now() // 여기서 네트워크 플러그인에 셋업 요청 if c.config.CniConfig.NetworkPluginSetupSerially { result, err = netPlugin.SetupSerially(ctx, id, path, opts...) } else { result, err = netPlugin.Setup(ctx, id, path, opts...) } networkPluginOperations.WithValues(networkSetUpOp).Inc() networkPluginOperationsLatency.WithValues(networkSetUpOp).UpdateSince(netStart) if err != nil { networkPluginOperationsErrors.WithValues(networkSetUpOp).Inc() return err } logDebugCNIResult(ctx, id, result) // Check if the default interface has IP config if configs, ok := result.Interfaces[defaultIfName]; ok && len(configs.IPConfigs) > 0 { sandbox.IP, sandbox.AdditionalIPs = selectPodIPs(ctx, configs.IPConfigs, c.config.IPPreference) sandbox.CNIResult = result return nil } return fmt.Errorf("failed to find network info for sandbox %q", id) }
컨테이너 런타임 중 하나인 containerd 내부 로직을 열어보면, setupPodNetwork라는 함수가 존재하는 것을 확인할 수 있다.
해당 함수에서는 컨테이너 ID, 네트워크 네임스페이스와 네트워크 플러그인을 설정하는 로직을 확인할 수 있다.
sudo crictl pods # WARN[0000] runtime connect using default endpoints: [unix:///run/containerd/containerd.sock unix:///run/crio/crio.sock unix:///var/run/cri-dockerd.sock]. As the default settings are now deprecated, you should set the endpoint instead. POD ID CREATED STATE NAME NAMESPACE ATTEMPT RUNTIME 8ca5a045204a8 10 minutes ago Ready prometheus-grafana-5c7b44cc98-8685f default 0 (default) # ...
간단하게 확인해보면, sandbox.ID는 POD ID로 설정된다.
이 값은 CNI (calico)가 설정하는 cni.projectcalico.org/containerID 와 동일한 것을 확인할 수 있다.
apiVersion: v1 kind: Pod metadata: annotations: checksum/config: 0e9cbd0ea8e24e32f7dfca5bab17a2ba05652642f0a09a4882833ae88e4cc4a3 checksum/sc-dashboard-provider-config: e70bf6a851099d385178a76de9757bb0bef8299da6d8443602590e44f05fdf24 checksum/secret: 032056e9c62bbe9d1daa41ee49cd3d9524c076f51ca4c65adadf4ef08ef28712 cni.projectcalico.org/containerID: 8ca5a045204a86919863f7f310cc80c9faca8b40249c806c01e25548585e7586 // ...
이후 동작에서, 아래 함수의 결과로 네임스페이스를 설정 값을 가져오는 것을 볼 수 있다.
opts, err := cniNamespaceOpts(id, config)
이렇게 가져온 컨테이너 정보와 네트워크 설정값을 네트워크 플러그인에 전달하고, 파드에 네트워크를 할당한다.
CNI는 많은 것을 하지만, 파드 네트워크 설정만 확인하면 대략 이런 흐름으로 동작한다.
참고
https://tetrate.io/blog/kubernetes-networking/
'DevOps, 클라우드 > Container' 카테고리의 다른 글
[Kubernetes] Cluster API 맛만 보기 (0) 2024.12.02 [컨테이너] 처음 열어보는 CNI 스펙 (0) 2024.11.09 [HomeLab] K8S 노드에 Label 추가하기 (0) 2024.07.21 [HomeLab] Tailscale 을 쿠버네티스에 배포하기 (0) 2024.07.05 [HomeLab] Calico와 Tailscale 충돌 문제 (0) 2024.06.22