cni設(shè)計(jì)簡析

cni設(shè)計(jì)

參考: https://github.com/containernetworking/cni/blob/main/SPEC.md

1. 插件式使用的cni

術(shù)語理解:

container: 在cni這里對應(yīng)linux network ns
network: 指一組endpoint,可以用于獲取到唯一的地址
runtime: 一個(gè)負(fù)責(zé)執(zhí)行CNI plugin的程序
plugin: 負(fù)責(zé)配置網(wǎng)絡(luò)

這個(gè)文檔會僅對runtime 和 plugin進(jìn)行說明

第一部分: 網(wǎng)絡(luò)配置格式

cniVersion: 版本,版本號越大支持的特性越豐富
name: 網(wǎng)絡(luò)名
disableCheck: 對應(yīng)cni的check (Add|Del|check)
plugins: cni list

plugin 配置對象

type: 對應(yīng)cni二進(jìn)制的名字,比如macvlan,ipvlan
capabilities: 稍后補(bǔ)充
ipMasq: 通過host上的一個(gè)ip來偽裝整個(gè)網(wǎng)絡(luò),所有pod用的該網(wǎng)段的pod ip都會使用該host ip進(jìn)行地址偽裝(nat)
ipam: 地址管理字典,其內(nèi)的type字段即是ipam plugin
dns: 一個(gè)字典缨历,包括,nameservers糙麦,domain戈二,search,options


{
  "cniVersion": "1.0.0",
  "name": "dbnet",
  "plugins": [
    {
      "type": "bridge",
      // plugin specific parameters
      "bridge": "cni0",
      "keyA": ["some more", "plugin specific", "configuration"],
      
      "ipam": {
        "type": "host-local",
        // ipam specific
        "subnet": "10.1.0.0/16",
        "gateway": "10.1.0.1",
        "routes": [
            {"dst": "0.0.0.0/0"}
        ]
      },
      "dns": {
        "nameservers": [ "10.1.0.1" ]
      }
    },
    {
      "type": "tuning",
      "capabilities": {
        "mac": true
      },
      "sysctl": {
        "net.core.somaxconn": "500"
      }
    },
    {
        "type": "portmap",
        "capabilities": {"portMappings": true}
    }
  ]
}

第二部分喳资, 執(zhí)行協(xié)議

cni protocol協(xié)議基于容器運(yùn)行時(shí)調(diào)用cni(二進(jìn)制)觉吭,cni定義了cni二進(jìn)制腳本和容器運(yùn)行時(shí)交互的協(xié)議。
plugin分兩種仆邓。

"Interface" plugins: 常見的cni macvlan ipvlan等
"Chained" plugins: 基于cni配置好的接口鲜滩,做qos,安全組等配置节值,比如terway 的ipvlan和之后的cilium鏈?zhǔn)秸{(diào)用

容器運(yùn)行時(shí)徙硅,通過將配置和環(huán)境變量以stdin的形式傳遞給cni插件。cni插件配置完容器接口以及網(wǎng)絡(luò)之后搞疗,基于stdout 反饋成功嗓蘑。 如果有錯誤,基于strerr反饋匿乃。
stdin的配置和stdout的結(jié)果都是JSON格式桩皿。

成功是狀態(tài)碼 必須是0
失敗時(shí) 非0

容器運(yùn)行時(shí)是在root network ns中執(zhí)行cni plugin的。

傳遞給cni的json包括:

CNI_COMMAND: ADD, DEL, CHECK, or VERSION
CNI_CONTAINERID: 容器id
CNI_NETNS: 容器所在網(wǎng)絡(luò)命名空間 /run/netns/[nsname]
CNI_IFNAME: 容器內(nèi)部的網(wǎng)卡
CNI_ARGS: 額外的參數(shù)幢炸,格式為 "FOO=BAR;ABC=123"
CNI_PATH: CNI插件所在路徑

cni 的操作

ADD 將容器連接到網(wǎng)絡(luò)泄隔,或者執(zhí)行變更

  1. 在CNI_NETNS內(nèi)部, 基于CNI_IFNAME 創(chuàng)建網(wǎng)卡
  2. 或者在CNI_NETNS內(nèi)部, 基于CNI_IFNAME 調(diào)整接口的配置

如果ADD成功,那么返回的json 也就是 prevResult 對象會包括這些內(nèi)容: https://github.com/containernetworking/cni/blob/main/SPEC.md#Success

cniVersion:
容器網(wǎng)卡: name, mac, samdbox(CNI_NETNS)
ips: ipcidr 192.168.1.3/24, gw, 網(wǎng)卡index
路由: dst cidr, gw
dns: nameservers domain search options

如果容器內(nèi)有同樣的接口宛徊,肯定會報(bào)錯佛嬉,而且,容器運(yùn)行時(shí)不會連續(xù)執(zhí)行ADD兩次(中間沒有刪除動作)闸天,僅執(zhí)行一次暖呕。

輸入:

容器運(yùn)行時(shí)會提供一個(gè)json 對象作為cni的標(biāo)輸入:

必須包含的字段:

  1. CNI_COMMAND
  2. CNI_CONTAINERID
  3. CNI_NETNS
  4. CNI_IFNAME

可選字段:
CNI_ARGS
CNI_PATH

DEL是add的反操作,暫不寫
CHECK 用于檢查和確認(rèn)苞氮,暫不寫

ipam 代理插件

Delegated plugins (IPAM)

ipam 插件必須反饋一個(gè)縮略的的成功對象的結(jié)構(gòu)體湾揽。 比如沒有接口數(shù)組以及接口ip等。

ipam插件式cni設(shè)計(jì)的一部分,ipam和cni二級制協(xié)調(diào)工作钝腺,才能完成網(wǎng)絡(luò)配置

第三部分抛姑, 網(wǎng)絡(luò)配置的執(zhí)行

容器運(yùn)行時(shí)會在容器內(nèi)部執(zhí)行 add, del, check 等網(wǎng)絡(luò)操作赞厕。

  1. 網(wǎng)絡(luò)配置如何轉(zhuǎn)化
  1. 轉(zhuǎn)化后的網(wǎng)絡(luò)配置如何提供給插件

網(wǎng)絡(luò)配置的操作統(tǒng)一叫做 attachment艳狐, 容器id 和 接口id, 是attachment的唯一標(biāo)識

(操作)周期 和 順序

  1. 在調(diào)用任何插件(cni ipam)之前皿桑,容器運(yùn)行時(shí)必須已經(jīng)創(chuàng)建了一個(gè)新的網(wǎng)絡(luò)命名空間毫目。
  2. 對于同一個(gè)容器,容器運(yùn)行時(shí)不能調(diào)用多個(gè)并行的操作诲侮。 多個(gè)容器的操作可以并行镀虐。
  3. 不同的容器,插件可以并行執(zhí)行沟绪,必要的話刮便,需要實(shí)現(xiàn)一定的鎖機(jī)制,必須ipam 的地址分配绽慈。
  4. 容器運(yùn)行時(shí)必須保證恨旱,add 和 delete的先后順序, add 結(jié)束坝疼,delete才能執(zhí)行搜贤,即使add失敗,del必須成功執(zhí)行钝凶。
  5. delete保證冪等仪芒,無論delete多少次,結(jié)果一致耕陷。
  6. add 和 delete 之間的時(shí)間段掂名, 網(wǎng)絡(luò)配置不能發(fā)生變化。
  7. 在不同的attachments之間哟沫,網(wǎng)絡(luò)配置不能發(fā)生變化铆隘。
  8. 容器運(yùn)行時(shí)負(fù)責(zé)ns的清理。

Attachment的參數(shù):

  1. 容器id
  2. ns
  3. 容器網(wǎng)卡名
  4. 原生參數(shù)南用, 額外參數(shù)膀钠,鍵值對格式,在CNI_ARGS 里面
  5. Capability Arguments裹虫, 鍵值對肿嘲,json 格式: https://github.com/containernetworking/cni/blob/main/CONVENTIONS.md

 "capabilities": {"portMappings": true}
  "runtimeConfig": {
    "portMappings": [
      {"hostPort": 8080, "containerPort": 80, "protocol": "tcp"}
    ]
  }

添加一個(gè)attachment

#  cat /etc/cni/net.d/00-multus.conf | jq
{
  "cniVersion": "0.4.0",
  "name": "multus-cni-network",
  "type": "multus",
  "capabilities": {
    "portMappings": true
  },
  "kubeconfig": "/etc/cni/net.d/multus.d/multus.kubeconfig",
  "delegates": [
    {
      "name": "kube-ovn",
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "kube-ovn",
          "server_socket": "/run/openvswitch/kube-ovn-daemon.sock"
        },
        {
          "type": "portmap",
          "capabilities": {
            "portMappings": true
          }
        }
      ]
    }
  ]
}

# 比如當(dāng)前的k8s集群環(huán)境
# plugins包含兩部分 cni是multus,ipam是kube-ovn-daemon

  1. 查看type 字段筑公,不存在雳窟,則失敗,報(bào)錯
  2. 基于plugin 配置,去請求配置封救,包括如下參數(shù)

如果這個(gè)plugin在list中的第一位拇涤, 不需要提供之前的結(jié)果,應(yīng)該指的是默認(rèn)cni誉结。
其他的plugins鹅士, 之前的結(jié)果就是上一個(gè)plugin處理過的輸出。

這里說明惩坑,主plugin和其他plugin是有一定的順序鏈?zhǔn)秸{(diào)用關(guān)系的掉盅。

  1. 執(zhí)行plugin 二進(jìn)制(比如macvlan cni), 基于CNI_COMMAND=ADD 參數(shù)以舒,二進(jìn)制可以通過環(huán)境變量讀入?yún)?shù)趾痘,stdin也有包含一些配置項(xiàng)(ip mac dns 網(wǎng)關(guān) svc localdns等)。

  2. 一旦plugin 執(zhí)行出錯蔓钟,會立刻停止并失敗永票,返回錯誤。

容器運(yùn)行時(shí)滥沫,必須存儲最后一個(gè)plugin返回的結(jié)果侣集,并持久化存儲(pod的狀態(tài)),用于做pod狀態(tài)檢查以及是否刪除佣谐。

Deleting an attachment: 是add的反向操作肚吏,暫不寫

從 plugin 配置中,獲取(待)執(zhí)行配置項(xiàng)

網(wǎng)絡(luò)配置的格式: 就是一個(gè)list狭魂,包含所有需要執(zhí)行的plugin配置內(nèi)容罚攀。

必須被轉(zhuǎn)化為單個(gè)plugin能夠理解的格式,因?yàn)榧词故嵌嗑W(wǎng)卡場景雌澄,也要一個(gè)一個(gè)的執(zhí)行斋泄。

單個(gè)plugin調(diào)用時(shí)需要的配置也是一個(gè)json。

容器運(yùn)行時(shí)必須將以下配置項(xiàng)傳遞給cni二進(jìn)制

  1. cniVersion: cni 版本
  2. name: 取自網(wǎng)絡(luò)配置中的name字段
  3. runtimeConfig: json 對象镐牺, plugin中的capabilities 字段
  4. prevResult: 一個(gè)json對象炫掐,上一個(gè)運(yùn)行過的plugin(add/delete/check)返回的結(jié)果

plugin 中定義的 capabilities會被容器運(yùn)行時(shí)移除。 其他field都毫無更改的直接傳遞睬涧。

runtimeConfig

然而 當(dāng)CNI_ARGS 被傳遞給所有plugins后募胃,沒有任何指示表示這些信息會被消費(fèi)。
所以畦浓,Capability需要在plugins字段中明確定義痹束。 那么 容器運(yùn)行時(shí),就可以基于此來確定是否一個(gè)給定的網(wǎng)絡(luò)配置支持某些特定的capability(能力)讶请。


{
  "type": "myPlugin",
  "capabilities": {
    "portMappings": true  // 表示支持端口映射的能力
  }
}

// 將 capabilities 格式化為 runtimeConfig

{
  "type": "myPlugin",
  "runtimeConfig": {
    "portMappings": [ { "hostPort": 8080, "containerPort": 80, "protocol": "tcp" } ]
  }
  ...
}

runtimeConfig 的內(nèi)容來自于 網(wǎng)絡(luò)配置中的capabilities域

第四部分 插件代理(Plugin Delegation)

有一些操作祷嘶,無論出于何種原因,都不能合理地實(shí)現(xiàn)為一個(gè)離散的鏈?zhǔn)讲寮?br> 更確切的說,一個(gè)CNI plugin 希望能代理別的插件執(zhí)行一些功能论巍。 一個(gè)最常用的例子就是代理執(zhí)行ip 地址分配(ipam)

作為網(wǎng)絡(luò)配置的一部分烛谊,CNI 插件需要能夠分配并維護(hù)容器內(nèi)網(wǎng)卡的ip地址,也包括配置必要的路由嘉汰。

這讓CNI插件具有極大的靈活性丹禀,但也變得更重(ipam 路由 dns 這些東西的維護(hù))。

很多CNI插件需要的ipam的代碼幾乎都是類似的郑现,比如dhcp host-local湃崩。

所以荧降, 一個(gè)CNI 插件需要設(shè)計(jì)為可以用來作為其他plugin的ipam代理接箫。

為了讓CNI更輕便,而且讓IPAM 和 cni (二進(jìn)制)保持正交關(guān)系(低耦合)朵诫。

正交設(shè)計(jì)原則

消除重復(fù)
分離關(guān)注點(diǎn)
縮小依賴范圍
向穩(wěn)定的方向依賴

ipam 被設(shè)計(jì)為一個(gè)第三方的插件辛友,為了保證ipam被代理調(diào)用,同時(shí)設(shè)計(jì)了一個(gè)協(xié)議剪返,用于指導(dǎo)代理(ipam)功能的實(shí)現(xiàn)废累。
然而這不是容器運(yùn)行時(shí)的職責(zé),而是CNI plugin的職責(zé): 在執(zhí)行的過程中脱盲,適當(dāng)?shù)臅r(shí)間點(diǎn)邑滨,調(diào)用IPAM插件。
ipam 插件必須定義了ip钱反,子網(wǎng)掖看,網(wǎng)關(guān),路由面哥。 并且返回這些信息給“主” 插件去應(yīng)用(把這些參數(shù)在調(diào)用cni二進(jìn)制的時(shí)候給過去)哎壳。
ipam插件也有可能通過協(xié)議(dhcp)來獲取這些信息。 或者數(shù)據(jù)存儲在本地文件系統(tǒng)中尚卫。 或者網(wǎng)絡(luò)配置的ipam部分归榕。

被代理的插件協(xié)議(Delegated Plugin protocol)

和cni 插件一樣,被代理的(ipam)插件也是通過調(diào)用一個(gè)可執(zhí)行的(二進(jìn)制)吱涉。 這些插件也在預(yù)先指定好的目錄下刹泄,

# ls -l /opt/cni/bin/
total 177440
-rwxr-xr-x. 1 root root  4151672 Feb  5  2021 bandwidth # 帶寬限制
-rwxr-xr-x. 1 root root  4536104 Feb  5  2021 bridge
-rwxr-xr-x. 1 root root 10270090 Feb  5  2021 dhcp # ipam
-rwxr-xr-x. 1 root root  4767801 Feb  5  2021 firewall # 防火墻限制
-rwxr-xr-x. 1 root root  3357992 Feb  5  2021 flannel
-rwxr-xr-x. 1 root root  4144106 Feb  5  2021 host-device
-rwxr-xr-x. 1 root root  3565330 Feb  5  2021 host-local # ipam
-rwxr-xr-x. 1 root root  4288339 Feb  5  2021 ipvlan
-rwxr-xr-x. 1 root root 65658880 Apr 10 03:51 kube-ovn
-rwxr-xr-x. 1 root root  3566204 Apr 10 03:51 loopback
-rwxr-xr-x. 1 root root  4497003 Apr 10 03:51 macvlan
-rwxr-xr-x. 1 root root 41849770 Apr 10 03:48 multus
-rwxr-xr-x. 1 root root  3979034 Apr 10 03:51 portmap # 端口映射
-rwxr-xr-x. 1 root root  4467317 Feb  5  2021 ptp
-rwxr-xr-x. 1 root root  3701138 Feb  5  2021 sbr
-rwxr-xr-x. 1 root root  3153330 Feb  5  2021 static
-rwxr-xr-x. 1 root root  3668289 Feb  5  2021 tuning
-rwxr-xr-x. 1 root root  4287972 Feb  5  2021 vlan
-rwxr-xr-x. 1 root root  3759977 Feb  5  2021 vrf

CNI_PATH: 用于指定CNI的路徑

所有被代理的cni插件收到的環(huán)境變量都是一樣的,就像cni插件一樣怎爵,通過stdin收到網(wǎng)絡(luò)配置特石,基于stdout傳出配置。

被代理的插件(下層的)提供完整的網(wǎng)絡(luò)配置給到(上層的)插件疙咸,(插件間按照主次順序調(diào)用)

被代理的插件執(zhí)行流程

當(dāng)一個(gè)插件執(zhí)行一個(gè)被代理的插件時(shí)县匠,它應(yīng)該:

在CNI_PATH(環(huán)境變量)對應(yīng)目錄下查找二進(jìn)制對象
根據(jù)插件收到的配置和環(huán)境變量執(zhí)行找到的二進(jìn)制對象(執(zhí)行時(shí)傳給配置和環(huán)境變量)
確保 被代理的插件的stderr被傳遞給調(diào)用者的stderr對象

ADD 場景中,如果被代理的插件執(zhí)行失敗了,那么在返回錯誤前需要執(zhí)行該插件的del操作乞旦。
同樣的贼穆,DEL | check 上層插件檢測失敗,要將stderr返回給下層兰粉。

第五部分故痊,返回值類型

只有3種類型

 Success (or Abbreviated Success) 
 Error
 _Version

5.1 Success

所有插件的請求配置內(nèi)容中都會有一個(gè) prevResult, prevResult 作為插件自身的輸出玖姑。
任何插件都可能會對 prevResult 進(jìn)行修改愕秫。 如果不修改,直接反射(傳遞)即可焰络。

ADD 操作成功后戴甩,所有插件(鏈?zhǔn)綀?zhí)行后)必須返回一個(gè)json對象:
cniVersion:
interfaces: 網(wǎng)卡名, mac闪彼, ns
ips: attachment 配置好的ipcidr甜孤, 網(wǎng)關(guān), 網(wǎng)卡index
routes: 路由 dst cidr畏腕,gw
dns: nameservers domain search options

ipam (被代理的插件)

被代理的插件可以忽略 相關(guān)的配置項(xiàng)缴川。
ipam 必須返回一個(gè)縮略的 Success 成功對象,可能不會包含 interfaces 數(shù)組描馅,以及ips 對象內(nèi)部的interface把夸。

錯誤對象暫時(shí)不了解

版本

插件必須返回cniVerison, 以及 supportedVersions


{
    "cniVersion": "1.0.0",
    "supportedVersions": [ "0.1.0", "0.2.0", "0.3.0", "0.3.1", "0.4.0", "1.0.0" ]
}


示例

  1. CNI_COMMAND=ADD, 把如下參數(shù)傳遞給 bridge cni二級制 插件


{
    "cniVersion": "1.0.0", 
    "name": "dbnet", // 網(wǎng)絡(luò)名
    "type": "bridge", // cni 二進(jìn)制的名字
    "bridge": "cni0", // 參數(shù) 網(wǎng)橋名
    "keyA": ["some more", "plugin specific", "configuration"], // 額外參數(shù)
    "ipam": { // 被代理調(diào)用的ipam 插件
        "type": "host-local",
        "subnet": "10.1.0.0/16",
        "gateway": "10.1.0.1"
    },
    "dns": { // 被代理調(diào)用的 dns 插件 ?
        "nameservers": [ "10.1.0.1" ]
    }
}

接下來 主 cni (比如multus)铭污,會調(diào)用ipam(基于ipam內(nèi)的參數(shù)恋日,執(zhí)行調(diào)用host-local二進(jìn)制,將subnet gw屬性基于stdin傳遞給該二進(jìn)制)

host-local 會返回如下結(jié)果


{
    "ips": [
        {
          "address": "10.1.0.5/16",  // 分配出ip
          "gateway": "10.1.0.1"      // 返回網(wǎng)關(guān)
        }
    ],
    "routes": [
      {
        "dst": "0.0.0.0/0"
      }
    ],
    "dns": {
      "nameservers": [ "10.1.0.1" ]
    }
}

然后 bridge 二進(jìn)制cni文件况凉,基于ipam的返回結(jié)果谚鄙,配置容器的網(wǎng)絡(luò),然后返回如下結(jié)果



{
    "ips": [
        {
          "address": "10.1.0.5/16",
          "gateway": "10.1.0.1",
          "interface": 2
        }
    ],
    "routes": [
      {
        "dst": "0.0.0.0/0"
      }
    ], // 以上是ipam的返回內(nèi)容刁绒,保持不變
    "interfaces": [ //以下是cni添加的內(nèi)容
        {
            "name": "cni0", // 網(wǎng)橋名
            "mac": "00:11:22:33:44:55"  // 網(wǎng)橋的mac
        },
        {
            "name": "veth3243", // veth-pair 接在網(wǎng)橋的一段
            "mac": "55:44:33:22:11:11" // 其mac
        },
        {
            "name": "eth0",  // 容器ns 內(nèi)部的eth0 網(wǎng)卡闷营,veth-pair的另一端
            "mac": "99:88:77:66:55:44", // mac
            "sandbox": "/var/run/netns/blue" // ns 路徑
        }
    ],
    "dns": {
      "nameservers": [ "10.1.0.1" ]
    }
}



這個(gè)結(jié)果就是 bridge cni操作后的 prevResult。

第一個(gè)插件知市,一般是cni 二進(jìn)制傻盟,它的prevResult是空的,但是它的(下一個(gè)|上層)插件會基于第一個(gè)插件的result作為prevResult嫂丙。

  1. 基于 tuning (二進(jìn)制)插件娘赴, 基于CNI_COMMAND=ADD, 調(diào)用 tuning的 add函數(shù)跟啤,基于 prevResult诽表, 結(jié)合mac的capability (特性)唉锌,stdin 收到的配置請求體如下

{
  "cniVersion": "1.0.0",
  "name": "dbnet",
  "type": "tuning", // 二進(jìn)制插件
  "sysctl": {
    "net.core.somaxconn": "500"
  },
  "runtimeConfig": { // 特性, 將eth0的mac調(diào)整為該值
    "mac": "00:11:22:33:44:66"
  },
  "prevResult": { // 下層的返回
    "ips": [
        {
          "address": "10.1.0.5/16",
          "gateway": "10.1.0.1",
          "interface": 2
        }
    ],
    "routes": [
      {
        "dst": "0.0.0.0/0"
      }
    ],
    "interfaces": [
        {
            "name": "cni0",
            "mac": "00:11:22:33:44:55"
        },
        {
            "name": "veth3243",
            "mac": "55:44:33:22:11:11"
        },
        {
            "name": "eth0",
            "mac": "99:88:77:66:55:44",
            "sandbox": "/var/run/netns/blue"
        }
    ],
    "dns": {
      "nameservers": [ "10.1.0.1" ]
    }
  }
}


tuning 成功執(zhí)行后的返回結(jié)果竿奏,可以看到eth0 mac已發(fā)生變化



{
    "ips": [
        {
          "address": "10.1.0.5/16",
          "gateway": "10.1.0.1",
          "interface": 2
        }
    ],
    "routes": [
      {
        "dst": "0.0.0.0/0"
      }
    ],
    "interfaces": [
        {
            "name": "cni0",
            "mac": "00:11:22:33:44:55"
        },
        {
            "name": "veth3243",
            "mac": "55:44:33:22:11:11"
        },
        {
            "name": "eth0",
            "mac": "00:11:22:33:44:66", // 已變化
            "sandbox": "/var/run/netns/blue"
        }
    ],
    "dns": {
      "nameservers": [ "10.1.0.1" ]
    }
}

tuning返回的prevResult

  1. 最后 調(diào)用 portmap 插件袄简,CNI_COMMAND=ADD 對應(yīng) portmap add函數(shù),使用的 prevResult如上泛啸,
    而 tuning 執(zhí)行完畢后绿语,如下

{
  "cniVersion": "1.0.0",
  "name": "dbnet",
  "type": "portmap", // 增加了該部分
  "runtimeConfig": {
    "portMappings" : [
      { "hostPort": 8080, "containerPort": 80, "protocol": "tcp" }
    ]
  },
  "prevResult": {// 下層的返回
    "ips": [
        {
          "address": "10.1.0.5/16",
          "gateway": "10.1.0.1",
          "interface": 2
        }
    ],
    "routes": [
      {
        "dst": "0.0.0.0/0"
      }
    ],
    "interfaces": [
        {
            "name": "cni0",
            "mac": "00:11:22:33:44:55"
        },
        {
            "name": "veth3243",
            "mac": "55:44:33:22:11:11"
        },
        {
            "name": "eth0",
            "mac": "00:11:22:33:44:66",
            "sandbox": "/var/run/netns/blue"
        }
    ],
    "dns": {
      "nameservers": [ "10.1.0.1" ]
    }
  }
}

DELETE正好是add 的逆操作,所以最上層的插件先執(zhí)行候址,執(zhí)行的參數(shù)就是上面ADD最后返回的結(jié)果吕粹。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市岗仑,隨后出現(xiàn)的幾起案子匹耕,更是在濱河造成了極大的恐慌,老刑警劉巖赔蒲,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件泌神,死亡現(xiàn)場離奇詭異良漱,居然都是意外死亡舞虱,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進(jìn)店門母市,熙熙樓的掌柜王于貴愁眉苦臉地迎上來矾兜,“玉大人,你說我怎么就攤上這事患久∫嗡拢” “怎么了?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵蒋失,是天一觀的道長返帕。 經(jīng)常有香客問我,道長篙挽,這世上最難降的妖魔是什么荆萤? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮铣卡,結(jié)果婚禮上链韭,老公的妹妹穿的比我還像新娘。我一直安慰自己煮落,他們只是感情好敞峭,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蝉仇,像睡著了一般旋讹。 火紅的嫁衣襯著肌膚如雪殖蚕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天沉迹,我揣著相機(jī)與錄音嫌褪,去河邊找鬼。 笑死胚股,一個(gè)胖子當(dāng)著我的面吹牛笼痛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播琅拌,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼缨伊,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了进宝?” 一聲冷哼從身側(cè)響起刻坊,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎党晋,沒想到半個(gè)月后谭胚,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡未玻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年灾而,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扳剿。...
    茶點(diǎn)故事閱讀 39,965評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡旁趟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出庇绽,到底是詐尸還是另有隱情锡搜,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布瞧掺,位于F島的核電站耕餐,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏辟狈。R本人自食惡果不足惜肠缔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望上陕。 院中可真熱鬧桩砰,春花似錦、人聲如沸释簿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽庶溶。三九已至煮纵,卻和暖如春懂鸵,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背行疏。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工匆光, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人酿联。 一個(gè)月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓终息,卻偏偏與公主長得像,于是被迫代替她去往敵國和親贞让。 傳聞我的和親對象是個(gè)殘疾皇子周崭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評論 2 355

推薦閱讀更多精彩內(nèi)容