用bash实现一个kubernets CNI

Network plugin(Org/CN)

Kubernetes Networking: How to Write Your Own CNI Plug-in with Bash 

github)

很多人想更深入的了解kubernets的网络

  • 部署到不同物理节点的Pod如何使用从单个子网分配的IP地址直接相互通信
  • Kubernetes服务如何工作
  • 如何实现负载平衡
  • 如何实施网络策略
  • Kubernetes覆盖网络增加了多少开销

本文计划:

  • 首先讨论Kubernetes网络模型以及CNI插件如何适配他。
  • 然后,尝试编写一个简单的CNI插件,该插件负责实现Kubernetes覆盖网络,以及在Pod中分配和配置网络接口。
  • 部署Kubernetes集群并将其配置为使用CNI插件。
  • 此过程中,将讨论所有相关网络概念来理解插件如何工作的。

涉及到的基本知识

Kubernetes网络的模型

三个基本要求:

  • 所有容器都可以直接相互通信而无需NAT。
  • 所有节点都可以在没有NAT的情况下与所有容器通信(反之亦然)。
  • 容器所看到的IP与其他人所看到的IP是相同的。

 

 

CNI插件  

Kubernetes网络模型的另一个问题是它没有单一的标准实现。取而代之的是,首选的实现很大程度上取决于群集的部署环境。因此,Kubernetes团队决定将这种方法外部化,并将将网络模型的实现任务交给CNI插件。

CNI插件负责将网络接口分配给新创建的容器。 Kubernetes首先创建一个没有网络接口的容器,然后调用CNI插件。该插件配置容器网络并返回有关分配的网络接口,IP地址等的信息。Kubernetes发送给CNI插件的参数以及响应的结构必须满足CNI规范,但是插件本身可能会做任何需要做的事情。

配置CNI插件

几个基本设计原则:

Plugins是可执行文件

  • 提供基本的命令: ADD, DEL, CHECK and VERSION
  • runtime在需要网络操作的时候启动插件
  • 通过stdin传入JSON 格式的配置
  • 通过stdin传入container-specific的数据
  • 通过stdout返回数据。

现在,我们准备开始配置插件。 您应该做的第一件事是创建插件配置。 将以下文件另存为/etc/cni/net.d/10-bash-cni-plugin.conf。

{
        "cniVersion": "0.3.1",
        "name": "mynet",
        "type": "bash-cni",
        "network": "10.244.0.0/16",
        "subnet": "<node-cidr-range>"
}

这必须在主节点和辅助节点上都进行。 别忘了将<node-cidr-range>替换为master的10.244.0.0/24和worker的10.244.1.0./24。 将文件放入/etc/cni/net.d/文件夹也很重要。 kubelet使用此文件夹发现CNI插件。

现在,让我们自己创建插件。 插件的可执行文件必须放在/ opt / cni / bin /文件夹中,其名称必须与插件配置(bash-cni)中的type参数完全相同,并且其内容在 这个GiHub。 (将插件放置在正确的文件夹中后,请不要忘记通过运行sudo chmod + x bash-cni使其可执行。)在主虚拟机和辅助虚拟机上均应执行此操作。

Golang example

package skel provides skeleton code for a CNI plugin, In particular, it implements argument parsing and validation.  提供解析环境变量函数getCmdArgsFromEnv, 并提供了一个调用plugin的主入口函数PluginMain, 该函数要求提供ADD,DEL,CHECK和VERSION的回调函数。比如intel的multus plugin提供了cmdAdd来处理ADD操作。

Kubelet 调用plugin

network cni  提供了各种库如(skel/libcin等)用来编写插件以配置Linux容器中的网络接口, 并定了相应的规范。 CNI仅涉及容器的网络连接以及删除容器时删除分配的资源。 由于这种关注,CNI具有广泛的支持,并且该规范易于实现。

kubelet的network package 提供了InitNetworkPlugin  来调用这些plugin。

libcni 提供了网络接口的基本的库。

type CNI interface {
	AddNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) (types.Result, error)
	CheckNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) error
	DelNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) error
	GetNetworkListCachedResult(net *NetworkConfigList, rt *RuntimeConf) (types.Result, error)
	GetNetworkListCachedConfig(net *NetworkConfigList, rt *RuntimeConf) ([]byte, *RuntimeConf, error)

	AddNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) (types.Result, error)
	CheckNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error
	DelNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error
	GetNetworkCachedResult(net *NetworkConfig, rt *RuntimeConf) (types.Result, error)
	GetNetworkCachedConfig(net *NetworkConfig, rt *RuntimeConf) ([]byte, *RuntimeConf, error)

	ValidateNetworkList(ctx context.Context, net *NetworkConfigList) ([]string, error)
	ValidateNetwork(ctx context.Context, net *NetworkConfig) ([]string, error)
}

kubelet/app/server.go 在运行的时候,run 会调用 PreInitRuntimeService -> NewDockerService -> InitNetworkPlugin

Kubenets Plugins

more example see github

Main: interface-creating

    • bridge: Creates a bridge, adds the host and the container to it.
    • ipvlan: Adds an ipvlan interface in the container.
    • loopback: Set the state of loopback interface to up.
    • macvlan: Creates a new MAC address, forwards all traffic to that to the container.
    • ptp: Creates a veth pair.
    • vlan: Allocates a vlan device.
    • host-device: Move an already-existing device into a container.

Windows: windows specific

    • win-bridge: Creates a bridge, adds the host and the container to it.
    • win-overlay: Creates an overlay interface to the container.

IPAM: IP address allocation

    • dhcp: Runs a daemon on the host to make DHCP requests on behalf of the container
    • host-local: Maintains a local database of allocated IPs
    • static: Allocate a static IPv4/IPv6 addresses to container and it's useful in debugging purpose.

Meta: other plugins

    • flannel: Generates an interface corresponding to a flannel config file
    • tuning: Tweaks sysctl parameters of an existing interface
    • portmap: An iptables-based portmapping plugin. Maps ports from the host's address space to the container.
    • bandwidth: Allows bandwidth-limiting through use of traffic control tbf (ingress/egress).
    • sbr: A plugin that configures source based routing for an interface (from which it is chained).
    • firewall: A firewall plugin which uses iptables or firewalld to add rules to allow traffic to/from the container.

Sample

The sample plugin provides an example for building your own plugin.

The CNI team also maintains some core plugins in a separate repository.

CSI

CRI

BPF/EBPF:

BPF用于很多的抓包程序,在linux中,一般内核自动编译进了af_packet这个驱动,因此只需要在用户态配置一个PACKET的socket,然后将filter配置进内核即可,使用setsockopt的SO_ATTACH_FILTER 命令,这个filter是在用户空间配制的,比如tcpdump应用程序,tcpdump和内核BPF过滤器的关系类似iptables与netfilter的关系,只是Netfilter实现了match/target的复合配合,而BPF的target则只是选择是否要与不要.

Linux BPF introduction

从Bcc到xdp原理分析

eBPF架构优势及其应用方向上的畅想

Linux内核功能eBPF入门学习(一):BPF、eBPF、BCC等基本概念  

linux 下的 包过滤器 BPF

A brief introduction to XDP and eBPF

Linux内核工程导论——网络:Filter(LSF、BPF、eBPF)  

BPF简介,以及使用kubectl trace插件为kubernetes集群运行BPF程序

Cilium: Network and Application Security with BPF and XDP (视频)

Cilium GitHub 

[译] Cilium:BPF 和 XDP 参考指南(2019) (强烈推荐)

Gilium Org Docs eBPF 

Welcome to Cilium’s documentation! (学习Cilium

github.com/cilium (github

 
 
posted @ 2020-01-30 18:28  lvmxh  阅读(672)  评论(0编辑  收藏  举报