├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── README.zh-CN.md ├── dockin-cni ├── .gitignore ├── Makefile ├── README.md ├── cmd │ └── dockin_cni.go ├── examples │ ├── 00-dockin-cni.conf │ ├── config.md │ ├── ecn.json │ ├── mock.data │ ├── one_network.yaml │ ├── two_network.yaml │ └── webank.json ├── go.mod ├── go.sum └── internal │ ├── api │ ├── add.go │ ├── check.go │ ├── delegate.go │ └── delete.go │ ├── log │ └── logger.go │ ├── model │ ├── bridge_conf.go │ ├── delegate_net_conf.go │ ├── ipam_conf.go │ ├── k8s_args.go │ ├── net_conf.go │ └── pod.go │ ├── rm │ └── rm.go │ └── utils │ └── net.go ├── dockin-ipam ├── Makefile ├── cmd │ └── dockin-ipam.go ├── docs.go ├── go.mod ├── go.sum └── readme.md └── docs └── images └── dockin.png /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | .DS_Store 3 | local.properties 4 | /logs 5 | .idea 6 | *.iml 7 | .git/ 8 | .gradle/ 9 | .settings/ 10 | .idea/ 11 | build/ 12 | dist/ 13 | .DS_Store 14 | *.swp 15 | *.ipr 16 | *.iml 17 | *.iws 18 | *.class 19 | classes/ 20 | .classpath 21 | .project 22 | sys.pid 23 | tomcat/ 24 | out/ 25 | tmp/ 26 | vendor/ -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Dockin-CNI 2 | 3 | Welcome to Dockin-CNI! This document is a guideline about how to contribute to Dockin-CNI. 4 | If you find something incorrect or missing, please leave comments / suggestions. 5 | 6 | ## Before you get started 7 | 8 | ### Setting up your development environment 9 | 10 | You should have Golang installed in your operating system. 11 | 12 | ## Contributing 13 | 14 | We are always very happy to have contributions, whether for typo fix, bug fix or big new features. 15 | Please do not ever hesitate to ask a question or send a pull request. 16 | 17 | We strongly value documentation and integration with other projects. 18 | We are very glad to accept improvements for these aspects. 19 | 20 | ### GitHub workflow 21 | 22 | We use the `develop` branch as the development branch, which indicates that this is an unstable branch. 23 | 24 | Here are the workflow for contributors: 25 | 26 | 1. Fork to your own 27 | 2. Clone fork to local repository 28 | 3. Create a new branch and work on it 29 | 4. Keep your branch in sync 30 | 5. Commit your changes (make sure your commit message concise) 31 | 6. Push your commits to your forked repository 32 | 7. Create a pull request 33 | 34 | Please make sure the PR has a corresponding issue. [GitHub Issues](https://github.com/WeBankFinTech/Dockin-CNI/issues) 35 | 36 | After creating a PR, one or more reviewers will be assigned to the pull request. 37 | The reviewers will review the code. 38 | 39 | Before merging a PR, squash any fix review feedback, typo, merged, and rebased sorts of commits. 40 | The final commit message should be clear and concise. 41 | 42 | ### Open an issue / PR 43 | 44 | We use [GitHub Issues](https://github.com/WeBankFinTech/Dockin-CNI/issues) and [Pull Requests](https://github.com/WeBankFinTech/Dockin-CNI/pulls) for trackers. 45 | 46 | If you find a typo in a document, find a bug in code, or want new features, or want to give suggestions, 47 | you can [open an issue on GitHub](https://github.com/WeBankFinTech/Dockin-CNI/issues/new) to report it. 48 | Please follow the guideline message in the issue template. 49 | 50 | If you want to contribute, please follow the [contribution workflow](#github-workflow) and create a new pull request. 51 | If your PR contains large changes, e.g. component refactor or new components, please write detailed documents 52 | about its design and usage. 53 | 54 | Note that a single pull request should not be too large. If heavy changes are required, it's better to separate the changes 55 | to a few individual PRs. 56 | 57 | ### Code review 58 | 59 | All code should be well reviewed by one or more committers. Some principles: 60 | 61 | - Readability: Important code should be well-documented. Comply with our code style. 62 | - Elegance: New functions, classes or components should be well-designed. 63 | - Testability: Important code should be well-tested (high unit test coverage). 64 | 65 | ## Community 66 | 67 | ### Contact us -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dockin CNI - Dockin Container Network Interface 2 | [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) 3 | 4 | English | [中文](README.zh-CN.md) 5 | 6 | Dockin operation and maintenance management system is a safe operation and maintenance management service that optimizes exec execution performance and supports command authority management 7 | 8 | **For more Dockin components, please visit [https://github.com/WeBankFinTech/Dockin](https://github.com/WeBankFinTech/Dockin)** 9 | 10 | ![Architecture](docs/images/dockin.png) 11 | 12 | 13 | ## **Dockin cni** 14 | dockin cni used to manager pod network, interact with resource manager(RM), support: 15 | - create single network 16 | - create multiple network 17 | - only support dockin-ipam ipam plugin 18 | - only support bridge to manage network 19 | 20 | dockin cni must work with 21 | - dockin-cni, main plugin, used to call bridge to manage network, and communicate with rm 22 | - dockin-ipam, used to assign ip 23 | - bridge, used to manage network 24 | 25 | 26 | ## Quick Start 27 | 28 | ### 1. cni configuration 29 | You should put cni config file to `/etc/cni/net.d` (Default config path using by kubelet. If you redirect the config path, put the config to the path that your kubelet using). 30 | 31 | The name of config file name can named like `00-dockin-cni.json`. 32 | 33 | configuration sample: 34 | ``` 35 | { 36 | "cniVersion": "0.2.0", 37 | "name": "dockin-cni", 38 | "type": "dockin-cni", 39 | "confDir": "/etc/cni/dockin/net.d", 40 | "binDir": "/opt/cni/bin", 41 | "logFile": "/data/kubernetes/dockin-cni.log", 42 | "logLevel": "debug", 43 | "backend": "http://localhost:10002/rmController/getPodMultiNetwork" 44 | } 45 | ``` 46 | all the parameters a described as follows: 47 | - cniVersion, support version 48 | - name, the name about this cni plugin 49 | - type, binary execution file, always be dockin-cni 50 | - confDir, the dir about network configuration 51 | - binDir, the binary execution about bridge 52 | - logFile, file to store the dockin-cni's log 53 | - logLevel, log level, support error/info/debug 54 | - backend, the api address of webhook, here using the api of dockin-RM as the sample. 55 | 56 | 57 | ### 2. Network configuration 58 | 59 | We need to create network config file as well. 60 | 61 | #### Step1: Using webhook to get network type. 62 | Firstly, you should have a web server(webhook) to get the pod (multi)network information, and implement an API with `podName` query parameter: 63 | ``` 64 | :/?podName= 65 | ``` 66 | 67 | Here we using Dockin-RM as the sample. You can use `curl` to access RM, for example: 68 | ``` 69 | curl 127.0.0.1:10002/rmController/getPodMultiNetwork?podName= 70 | ``` 71 | If there is no error, you will get response like this. You web API must return a struct as below as well. 72 | ``` 73 | { 74 | "code": 0, 75 | "reqId": "1234", 76 | "message": "success", 77 | "data": [ 78 | { 79 | "type": "test", 80 | "podIp": "192.168.1.2", 81 | "subnetMask": "255.255.255.0", 82 | "gateway": "192.168.1.1", 83 | "ifName": "eth0", 84 | "master": true 85 | }, 86 | { 87 | "type": "dockin", 88 | "podIp": "192.168.2.2", 89 | "subnetMask": "255.255.255.0", 90 | "gateway": "192.168.1.1", 91 | "ifName": "net0", 92 | "master": false 93 | } 94 | ] 95 | } 96 | ``` 97 | in the sample: 98 | - code, indicates the response code, 0 means success, otherwise failed 99 | - message, indicates the description about this response, success or failed message 100 | - data, is the array about network information 101 | - type, network type, 102 | - podIp, the ip which will assign to this network 103 | - subnetMask, mask about this network 104 | - gateway, the gateway about this network 105 | - ifName, the network device name about this network, which will show in ifconfig or ip a 106 | - master, weather the main network, which will show in kubectl get pods, and this must be single in a pod 107 | 108 | **What we need to pay attention to is the field `type`. In the sample, there is two types: `test` and `dockin`** 109 | 110 | #### Step2: create network config file. 111 | 112 | network configuration is the bridge configuration, for more details: 113 | >https://github.com/containernetworking/plugins/tree/master/plugins/main/bridge 114 | 115 | network configuration are json files which stored in `confDir` set in the cni configuration. 116 | and will pass to kubelet create network. 117 | 118 | ``` 119 | { 120 | "cniVersion": "0.2.0", 121 | "name": "dockin", 122 | "type": "bridge", 123 | "bridge": "br1" 124 | } 125 | ``` 126 | 127 | - cniVersion, indicate the version support in this cni 128 | - name, the network name, must be same with the rm type 129 | - type, only support bridge to manage network 130 | - bridge, the bridge name about this network, multiple network can assign different bridge name 131 | 132 | **Now, let's start to create network config.** 133 | 134 | - Firstly, create config dir: 135 | 136 | You can find the path in the `00-dockin-cni.json` 137 | ```shell 138 | mkdir -p /etc/cni/dockin/net.d 139 | ``` 140 | 141 | - Secondly,create config file: 142 | 143 | In the sample as above, we need to create two network config file. 144 | 145 | 1.create config for type `test`: 146 | 147 | ``` 148 | touch /etc/cni/dockin/net.d/test.json 149 | ``` 150 | content: 151 | ```JSON 152 | { 153 | "cniVersion": "0.2.0", 154 | "name": "test", // type 155 | "type": "bridge", 156 | "bridge": "br0" 157 | } 158 | ``` 159 | 160 | 2.create config for type `dockin`: 161 | 162 | ``` 163 | touch /etc/cni/dockin/net.d/dockin.json 164 | ``` 165 | content: 166 | ```JSON 167 | { 168 | "cniVersion": "0.2.0", 169 | "name": "dockin", // type 170 | "type": "bridge", 171 | "bridge": "br0" 172 | } 173 | ``` 174 | 175 | ### 3. Put executable binary to `binDir` 176 | 177 | You can using `make` to build `dockin-cni` and `dockin-ipam`. Then put them to `binDir` in the `00-dockin-cni.json`. The binDir is `/opt/cni/bin` normally. 178 | 179 | ## **Dockin-ipam**: static IP address management plugin 180 | 181 | ### Overview 182 | 183 | static IPAM is very simple IPAM plugin that assigns IPv4 and IPv6 addresses statically to container. This will be useful in case of assign same IP address in different vlan/vxlan to containers. 184 | 185 | 186 | ### Example configuration 187 | 188 | ``` 189 | { 190 | "ipam": { 191 | "type": "static", 192 | "addresses": [ 193 | { 194 | "address": "192.168.0.1/24", 195 | "gateway": "192.168.0.254" 196 | }, 197 | { 198 | "address": "3ffe:ffff:0:01ff::1/64", 199 | "gateway": "3ffe:ffff:0::1" 200 | } 201 | ], 202 | "routes": [ 203 | { "dst": "0.0.0.0/0" }, 204 | { "dst": "192.168.0.0/16", "gw": "192.168.1.1" }, 205 | { "dst": "3ffe:ffff:0:01ff::1/64" } 206 | ], 207 | "dns": { 208 | "nameservers" : ["8.8.8.8"], 209 | "domain": "example.com", 210 | "search": [ "example.com" ] 211 | } 212 | } 213 | } 214 | ``` 215 | 216 | ### Network configuration reference 217 | 218 | * `type` (string, required): "static" 219 | * `addresses` (array, optional): an array of ip address objects: 220 | * `address` (string, required): CIDR notation IP address. 221 | * `gateway` (string, optional): IP inside of "subnet" to designate as the gateway. 222 | * `routes` (string, optional): list of routes add to the container namespace. Each route is a dictionary with "dst" and optional "gw" fields. If "gw" is omitted, value of "gateway" will be used. 223 | * `dns` (string, optional): the dictionary with "nameservers", "domain" and "search". 224 | 225 | ### Supported arguments 226 | 227 | The following [CNI_ARGS](https://github.com/containernetworking/cni/blob/master/SPEC.md#parameters) are supported: 228 | 229 | * `IP`: request a specific CIDR notation IP addresses, comma separated 230 | * `GATEWAY`: request a specific gateway address 231 | 232 | (example: CNI_ARGS="IP=192.168.1.1/24;GATEWAY=192.168.1.254") 233 | 234 | The plugin also support following [capability argument](https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md). 235 | 236 | * `ips`: Pass IP addresses for CNI interface 237 | 238 | The following [args conventions](https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md#args-in-network-config) are supported: 239 | 240 | * `ips` (array of strings): A list of custom IPs to attempt to allocate, with prefix (e.g. '192.168.1.1/24') 241 | 242 | Notice: If some of above are used at same time, only one will work according to the priorities below 243 | 244 | 1. [capability argument](https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md) 245 | 1. [args conventions](https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md#args-in-network-config) 246 | 1. [CNI_ARGS](https://github.com/containernetworking/cni/blob/master/SPEC.md#parameters) 247 | -------------------------------------------------------------------------------- /README.zh-CN.md: -------------------------------------------------------------------------------- 1 | # Dockin CNI - Dockin Container Network Interface 2 | 3 | [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) 4 | 5 | [English](README.md) | 中文 6 | 7 | Dockin运维管理系统是安全的运维管理服务,优化exec执行性能、支持命令权限管理、支持场景运维编排。 8 | 9 | **更多Dockin组件请访问 [https://github.com/WeBankFinTech/Dockin](https://github.com/WeBankFinTech/Dockin)** 10 | 11 | ![Architecture](docs/images/dockin.png) 12 | 13 | ## **Dockin cni** 14 | dockin cni 与资源管理模块(RM)进行交互,共同来管理容器网络,当前支持: 15 | - 创建单网卡网络 16 | - 创建多网卡网络 17 | - 仅支持dockin ipam插件 18 | - 仅支持桥接模式 19 | 20 | 以下为运行dockin cni的需要组件 21 | - dockin-cni,主要的插件入口,通过调用网桥来进行网络管理,并且与RM模块进行交互 22 | - dockin-ipam,用于分配ip地址 23 | - bridge, 网桥用于网络管理 24 | 25 | ## 部署说明 26 | ### 1. cni的配置 27 | cni配置文件需要放置到`/etc/cni/net.d`下(kubelet使用的默认配置路径。如果重定向了配置路径,请将配置文件放置到kubelet使用的路径。 28 | 29 | 配置文件的命名可以参考`00-dockin-cni.json`这样的命名方式 30 | 31 | 配置文件内容示例: 32 | ``` 33 | { 34 | "cniVersion": "0.2.0", 35 | "name": "dockin-cni", 36 | "type": "dockin-cni", 37 | "confDir": "/etc/cni/dockin/net.d", 38 | "binDir": "/opt/cni/bin", 39 | "logFile": "/data/kubernetes/dockin-cni.log", 40 | "logLevel": "debug", 41 | "backend": "http://localhost:10002/rmController/getPodMultiNetwork" 42 | } 43 | ``` 44 | 参数描述如下: 45 | - cniVersion, 支持的cni版本 46 | - name, 网络插件的名字 47 | - type, 类型,可执行二进制文件,这里必须使用'dockin-cni' 48 | - confDir, 网络配置文件所在的目录 49 | - binDir, 网桥(bridge)二进制文件所在目录 50 | - logFile, 日志文件路径 51 | - logLevel, 日志登记 52 | - backend, webhook的访问地址,这里使用dockin-RM的地址作为示例 53 | 54 | ### 2. 配置Network 55 | 这里同样需要创建配置network相关的配置文件。 56 | 57 | #### Step1:使用webhook获取network类型 58 | 首先,您需要有一个web服务器提供webhook,用于获取pod的网络信息(包括单/双网卡),该web服务需要实现一个带有`podName`url参数的API。比如: 59 | ``` 60 | :/?podName= 61 | ``` 62 | 这里的话,可以使用Dockin-RM作为例子。可以使用`curl`命令来访问rm的以下API: 63 | ``` 64 | curl 127.0.0.1:10002/rmController/getPodMultiNetwork?podName= 65 | ``` 66 | 如果没有出现错误的话,您将会得到如下格式的响应: 67 | ``` 68 | { 69 | "code": 0, 70 | "reqId": "1234", 71 | "message": "success", 72 | "data": [ 73 | { 74 | "type": "test", 75 | "podIp": "192.168.1.2", 76 | "subnetMask": "255.255.255.0", 77 | "gateway": "192.168.1.1", 78 | "ifName": "eth0", 79 | "master": true 80 | }, 81 | { 82 | "type": "dockin", 83 | "podIp": "192.168.2.2", 84 | "subnetMask": "255.255.255.0", 85 | "gateway": "192.168.1.1", 86 | "ifName": "net0", 87 | "master": false 88 | } 89 | ] 90 | } 91 | ``` 92 | 其中: 93 | - code, 返回码,0表示成功,其余表示失败 94 | - message, 返回的描述信息,包括成功信息和失败信息 95 | - data, 关于网络信息的数据内容 96 | - type, 网络类型 97 | - podIp, 为pod分配的ip地址 98 | - subnetMask, 子网掩码 99 | - gateway, 网管 100 | - ifName, 该网络所属的网卡名称,将能够通过ifconfig命令及ip a命令查看 101 | - master, 用于标记是否为主要网络,在使用kubectl展示信息时将会看到该网络信息,并且在一个pod中只能有一个master网卡 102 | 103 | **这里我们需要关注的是其中`type`字段. 在这个例子中,一共有两个类型: `test` 和 `dockin`** 104 | 105 | #### Step2: 创建network配置文件 106 | network 配置通过网桥进行管理,更多细节可参考以下链接: 107 | >https://github.com/containernetworking/plugins/tree/master/plugins/main/bridge 108 | 109 | 网络配置通过json文件进行存储,存放在`confDir`中(在cni配置中),并且将会传给kubelet创建网络。 110 | 111 | ``` 112 | { 113 | "cniVersion": "0.2.0", 114 | "name": "dockin", 115 | "type": "bridge", 116 | "bridge": "br1" 117 | } 118 | ``` 119 | 120 | - cniVersion, 该cni支持的版本 121 | - name, 网络名称,比如与rm中的名称保持一致 122 | - type, 类型,仅支持通过网桥进行网络管理 123 | - bridge, 网桥名称,多网卡环境下可以分配不同的网桥名称 124 | 125 | **上面对配置的内容做了简单介绍,现在来创建network配置文件.** 126 | - 首先,先创建配置文件目录: 127 | 128 | 目录的路径可以从前面的cni配置文件中的`confDir`找到 129 | ``` 130 | mkdir -p /etc/cni/dockin/net.d 131 | ``` 132 | 133 | - 然后,创建配置文件 134 | 135 | 在上面的例子中,我们需要创建两个network配置文件 136 | 1.为类型`test`创建配置文件 137 | ``` 138 | touch /etc/cni/dockin/net.d/test.json 139 | ``` 140 | 配置文件内容: 141 | ```JSON 142 | { 143 | "cniVersion": "0.2.0", 144 | "name": "test", // type 145 | "type": "bridge", 146 | "bridge": "br0" 147 | } 148 | ``` 149 | 150 | 2.为类型`dockin`创建配置文件 151 | ``` 152 | touch /etc/cni/dockin/net.d/dockin.json 153 | ``` 154 | 配置文件内容: 155 | ```JSON 156 | { 157 | "cniVersion": "0.2.0", 158 | "name": "dockin", // type 159 | "type": "bridge", 160 | "bridge": "br0" 161 | } 162 | ``` 163 | 164 | ### 3. 将可执行文件放到`binDir`中 165 | 你可以使用`make`命令完成`dockin-cni`和`dockin-ipam`的编译,然后将两个可执行文件放到cni配置文件中`binDir`指向的路径。通常情况下,cni的bin目录为`/opt/cni/bin`。 166 | 167 | --- 168 | ## **Dockin-ipam**: 静态IP地址管理插件 169 | 170 | ### 简介 171 | 172 | 静态IPAM插件用来为容器分配静态IP地址(IPv4/IPv6),使用与需要为容器分配静态IP的场景(即重启或kill之后ip地址保持不变) 173 | 174 | static IPAM is very simple IPAM plugin that assigns IPv4 and IPv6 addresses statically to container. This will be useful in debugging purpose and in case of assign same IP address in different vlan/vxlan to containers. 175 | 176 | 177 | ### 配置示例 178 | 179 | ``` 180 | { 181 | "ipam": { 182 | "type": "static", 183 | "addresses": [ 184 | { 185 | "address": "192.168.0.1/24", 186 | "gateway": "192.168.0.254" 187 | }, 188 | { 189 | "address": "3ffe:ffff:0:01ff::1/64", 190 | "gateway": "3ffe:ffff:0::1" 191 | } 192 | ], 193 | "routes": [ 194 | { "dst": "0.0.0.0/0" }, 195 | { "dst": "192.168.0.0/16", "gw": "192.168.1.1" }, 196 | { "dst": "3ffe:ffff:0:01ff::1/64" } 197 | ], 198 | "dns": { 199 | "nameservers" : ["8.8.8.8"], 200 | "domain": "example.com", 201 | "search": [ "example.com" ] 202 | } 203 | } 204 | } 205 | ``` 206 | 207 | ### 网络配置描述 208 | 209 | * `type` (string, 必须): "static" 210 | * `addresses` (array, 可选): ip地址对象数组: 211 | * `address` (string, 必须): 以CIDR表示的ip地址. 212 | * `gateway` (string, 可选): 执行子网内的ip作为网管. 213 | * `routes` (string, 可选): 需要加载到容器命名空间的路由列表。每条路由信息都是有dst及gw(可选)字段构成的字典,如果设置了gw字段,“gateway”标签对应的值将会被使用. 214 | * `dns` (string, 可选): 由"nameservers", "domain" 及 "search"构成的映射表. 215 | 216 | ### 支持的参数 217 | 218 | 支持以下CNI参数 [CNI_ARGS](https://github.com/containernetworking/cni/blob/master/SPEC.md#parameters): 219 | 220 | * `IP`: 需要指定一个以CIDR表示法表示的ip地址,用逗号进行分割 221 | * `GATEWAY`: 需要指定一个网关地址 222 | 223 | (示例: CNI_ARGS="IP=192.168.1.1/24;GATEWAY=192.168.1.254") 224 | 225 | 同时插件支持能力参数 [capability argument](https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md). 226 | 227 | * `ips`: 为CNI接口传入多个ip地址 228 | 229 | 支持以下既定参数 [args conventions](https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md#args-in-network-config) : 230 | 231 | * `ips` (字符串数组): 用于尝试分配ip的自定义ip列表 (e.g. '192.168.1.1/24') 232 | 233 | 注意: 如果以上某些参数同时使用,将会通过以下的优先级选择其中一个进行生效 234 | 235 | 1. 能力参数[capability argument](https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md) 236 | 1. 既定参数[args conventions](https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md#args-in-network-config) 237 | 1. CNI参数[CNI_ARGS](https://github.com/containernetworking/cni/blob/master/SPEC.md#parameters) 238 | -------------------------------------------------------------------------------- /dockin-cni/.gitignore: -------------------------------------------------------------------------------- 1 | # Binary output dir 2 | bin/ 3 | 4 | # GOPATH created by the build script 5 | gopath/ 6 | 7 | # Editor paths 8 | .swp* 9 | .swo* 10 | .idea* 11 | 12 | # Test outputs 13 | *.out 14 | *.test 15 | -------------------------------------------------------------------------------- /dockin-cni/Makefile: -------------------------------------------------------------------------------- 1 | BINARY="dockin-cni" 2 | VERSION=0.1.0 3 | BUILD=`date +%FT%T%z` 4 | 5 | PACKAGES=`go list ./... | grep -v /vendor/` 6 | VETPACKAGES=`go list ./... | grep -v /vendor/ | grep -v /examples/` 7 | GOFILES=`find . -name "*.go" -type f -not -path "./vendor/*"` 8 | 9 | OS=linux 10 | ARCH=amd64 11 | 12 | default: 13 | go mod tidy 14 | go mod vendor 15 | @mkdir -p build 16 | cd build && GOOS=${OS} GOARCH=${ARCH} go build -o ${BINARY} ../cmd 17 | 18 | 19 | list: 20 | echo ${PACKAGES} 21 | echo ${VETPACKAGES} 22 | echo ${GOFILES} 23 | 24 | fmt: 25 | gofmt -s -w ${GOFILES} 26 | 27 | fmt-check: 28 | diff=?(gofmt -s -d $(GOFILES)); \ 29 | if [ -n "$$diff" ]; then \ 30 | echo "Please run 'make fmt' and commit the result:"; \ 31 | echo "$${diff}"; \ 32 | exit 1; \ 33 | fi; 34 | 35 | vet: 36 | go vet $(VETPACKAGES) 37 | 38 | clean: 39 | if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi 40 | 41 | 42 | .PHONY: default fmt fmt-check install vet clean 43 | -------------------------------------------------------------------------------- /dockin-cni/README.md: -------------------------------------------------------------------------------- 1 | dockin ipam cni 2 | === 3 | 4 | dockin cni used to manager pod network, interact with resource manager(rm), support: 5 | - create single network 6 | - create multiple network 7 | - only support dockin-ipam ipam plugin 8 | - only support bridge to manage network 9 | 10 | dockin cni must work with 11 | - dockin-cni, main plugin, used to call bridge to manage network, and communicate with rm 12 | - dockin-ipam, used to assign ip 13 | - bridge, used to manage network 14 | 15 | cni configuration 16 | -- 17 | configuration sample 18 | ``` 19 | { 20 | "cniVersion": "0.2.0", 21 | "name": "dockin-cni", 22 | "type": "dockin-cni", 23 | "confDir": "/etc/cni/dockin/net.d", 24 | "binDir": "/opt/cni/bin", 25 | "logFile": "/data/kubernetes/dockin-cni.log", 26 | "logLevel": "debug", 27 | "backend": "http://localhost:8080/rm" 28 | } 29 | ``` 30 | all the parameters a described as follows: 31 | - cniVersion, support version 32 | - name, the name about this cni plugin 33 | - type, binary execution file, always be dockin-cni 34 | - confDir, the dir about network configuration 35 | - binDir, the binary execution about bridge 36 | - logFile, file to store the dockin-cni's log 37 | - logLevel, log level, support error/info/debug 38 | - backend, the rm service api address 39 | 40 | rm data sample 41 | --- 42 | ``` 43 | { 44 | "code": 0, 45 | "reqId": "1234", 46 | "message": "success", 47 | "data": [ 48 | { 49 | "type": "test", 50 | "podIp": "192.168.1.2", 51 | "subnetMask": "255.255.255.0", 52 | "gateway": "192.168.1.1", 53 | "ifName": "eth0", 54 | "master": true 55 | }, 56 | { 57 | "type": "dockin", 58 | "podIp": "192.168.2.2", 59 | "subnetMask": "255.255.255.0", 60 | "gateway": "192.168.1.1", 61 | "ifName": "net0", 62 | "master": false 63 | } 64 | ] 65 | } 66 | ``` 67 | in the sample: 68 | - code, indicates the response code, 0 means success, otherwise failed 69 | - message, indicates the description about this response, success or failed message 70 | - data, is the array about network information 71 | - type, network type, 72 | - podIp, the ip which will assign to this network 73 | - subnetMask, mask about this network 74 | - gateway, the gateway about this network 75 | - ifName, the network device name about this network, which will show in ifconfig or ip a 76 | - master, weather the main network, which will show in kubectl get pods, and this must be single in a pod 77 | 78 | network configuration 79 | --- 80 | network configuration is the bridge configuration, for more details: 81 | >https://github.com/containernetworking/plugins/tree/master/plugins/main/bridge 82 | 83 | network configuration are json files which stored in binDir set in the cni configuration. 84 | and will pass to kubelet create network. 85 | 86 | ``` 87 | { 88 | "cniVersion": "0.2.0", 89 | "name": "dockin", 90 | "type": "bridge", 91 | "bridge": "br1" 92 | } 93 | ``` 94 | 95 | - cniVersion, indicate the version support in this cni 96 | - name, the network name, must be same with the rm type 97 | - type, only support bridge to manage network 98 | - bridge, the bridge name about this network, multiple network can assign different bridge name 99 | -------------------------------------------------------------------------------- /dockin-cni/cmd/dockin_cni.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) @2021 Webank Group Holding Limited 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | *

7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | *

9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | 15 | package main 16 | 17 | import ( 18 | "flag" 19 | "fmt" 20 | "os" 21 | 22 | "github.com/webankfintech/dockin-cni/internal/api" 23 | 24 | "github.com/containernetworking/cni/pkg/skel" 25 | cniversion "github.com/containernetworking/cni/pkg/version" 26 | ) 27 | 28 | var version = "1.0.0" 29 | 30 | func printVersion() string { 31 | return fmt.Sprintf("dockin-cni used to create pod network informations, "+ 32 | "interact with resource manager, current version:%s", version) 33 | } 34 | 35 | func main() { 36 | flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError) 37 | 38 | ver := false 39 | flag.BoolVar(&ver, "v", false, "print dockin cni version") 40 | flag.Parse() 41 | if ver == true { 42 | fmt.Printf("%s\n", printVersion()) 43 | return 44 | } 45 | 46 | skel.PluginMain( 47 | func(args *skel.CmdArgs) error { 48 | result, err := api.CmdAdd(args, nil) 49 | if err != nil { 50 | return err 51 | } 52 | return result.Print() 53 | }, 54 | func(args *skel.CmdArgs) error { 55 | result, err := api.Check(args, nil) 56 | if err != nil { 57 | return err 58 | } 59 | return result.Print() 60 | }, 61 | func(args *skel.CmdArgs) error { 62 | return api.CmdDelete(args, nil) 63 | }, 64 | 65 | cniversion.All, printVersion(), 66 | ) 67 | } 68 | -------------------------------------------------------------------------------- /dockin-cni/examples/00-dockin-cni.conf: -------------------------------------------------------------------------------- 1 | { 2 | "cniVersion": "0.2.0", 3 | "name": "dockin-cni", 4 | "type": "dockin-cni", 5 | "confDir": "/etc/cni/dockin/net.d", 6 | "binDir": "/opt/cni/bin", 7 | "logFile": "/data/logs/kubernetes/dockin-cni.log", 8 | "logLevel": "debug", 9 | "backend": "http://127.0.0.1:10002/rmController/getPodMultiNetwork" 10 | } -------------------------------------------------------------------------------- /dockin-cni/examples/config.md: -------------------------------------------------------------------------------- 1 | ``` 2 | { 3 | "cniVersion": "0.3.1", 4 | "name": "mynet", 5 | "type": "bridge", 6 | "bridge": "mynet0", 7 | "isDefaultGateway": true, 8 | "forceAddress": false, 9 | "ipMasq": true, 10 | "hairpinMode": true, 11 | "route": [ 12 | { "dst": "192.168.0.0/16", "gw": "192.168.1.1" } 13 | ], 14 | "dns": { 15 | "nameservers" : ["8.8.8.8"], 16 | "domain": "example.com", 17 | "search": [ "example.com" ] 18 | } 19 | } 20 | ``` 21 | 22 | Network configuration reference 23 | - name (string, required): the name of the network. 24 | - type (string, required): "bridge". 25 | - bridge (string, optional): name of the bridge to use/create. Defaults to "cni0". 26 | - isGateway (boolean, optional): assign an IP address to the bridge. Defaults to false. 27 | - isDefaultGateway (boolean, optional): Sets isGateway to true and makes the assigned IP the default route. Defaults to false. 28 | - forceAddress (boolean, optional): Indicates if a new IP address should be set if the previous value has been changed. Defaults to false. 29 | - ipMasq (boolean, optional): set up IP Masquerade on the host for traffic originating from this network and destined outside of it. Defaults to false. 30 | - mtu (integer, optional): explicitly set MTU to the specified value. Defaults to the value chosen by the kernel. 31 | - hairpinMode (boolean, optional): set hairpin mode for interfaces on the bridge. Defaults to false. 32 | - promiscMode (boolean, optional): set promiscuous mode on the bridge. Defaults to false. 33 | - vlan (int, optional): assign VLAN tag. Defaults to none. 34 | - routes (string, optional): list of routes add to the container namespace. Each route is a dictionary with "dst" and optional "gw" fields. If "gw" is omitted, value of "gateway" will be used. 35 | - dns (string, optional): the dictionary with "nameservers", "domain" and "search". -------------------------------------------------------------------------------- /dockin-cni/examples/ecn.json: -------------------------------------------------------------------------------- 1 | { 2 | "cniVersion": "0.2.0", 3 | "name": "dockin", 4 | "type": "bridge", 5 | "bridge": "br1", 6 | "isGateway": false, 7 | "ipMasq": true, 8 | "routes": [ 9 | { "dst": "192.168.0.0/16", "gw": "192.168.1.1" } 10 | ], 11 | "dns": { 12 | "nameservers" : ["8.8.8.8"], 13 | "domain": "example.com", 14 | "search": [ "example.com" ] 15 | } 16 | } -------------------------------------------------------------------------------- /dockin-cni/examples/mock.data: -------------------------------------------------------------------------------- 1 | { 2 | "code": 0, 3 | "reqId": "1234", 4 | "message": "success", 5 | "data": [ 6 | { 7 | "type": "test", 8 | "podIp": "192.168.1.2", 9 | "subnetMask": "255.255.255.0", 10 | "gateway": "192.168.1.1", 11 | "ifName": "eth0" 12 | }, 13 | { 14 | "type": "dockin", 15 | "podIp": "192.168.2.2", 16 | "subnetMask": "255.255.255.0", 17 | "gateway": "192.168.2.1", 18 | "ifName": "net0" 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /dockin-cni/examples/one_network.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: one-network 5 | namespace: dockin 6 | labels: 7 | env: test 8 | spec: 9 | spec: 10 | containers: 11 | - args: 12 | command: 13 | - /bin/sh 14 | - -c 15 | - tail -f /dev/null 16 | image: busybox 17 | imagePullPolicy: IfNotPresent 18 | name: busybox-network 19 | nodeName: kube-node01 -------------------------------------------------------------------------------- /dockin-cni/examples/two_network.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: two-network 5 | namespace: dockin 6 | labels: 7 | env: test 8 | spec: 9 | spec: 10 | containers: 11 | - args: 12 | command: 13 | - /bin/sh 14 | - -c 15 | - tail -f /dev/null 16 | image: busybox 17 | imagePullPolicy: IfNotPresent 18 | name: two-network 19 | nodeName: kube-node01 -------------------------------------------------------------------------------- /dockin-cni/examples/webank.json: -------------------------------------------------------------------------------- 1 | { 2 | "cniVersion": "0.2.0", 3 | "name": "dockin", 4 | "type": "bridge", 5 | "bridge": "br1", 6 | "isGateway": false, 7 | "ipMasq": true, 8 | "routes": [ 9 | { "dst": "0.0.0.0/0" } 10 | ] 11 | } -------------------------------------------------------------------------------- /dockin-cni/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/webankfintech/dockin-cni 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/containernetworking/cni v0.7.1 7 | github.com/containernetworking/plugins v0.8.2 8 | github.com/golang/protobuf v1.3.2 // indirect 9 | github.com/google/uuid v1.1.1 10 | github.com/onsi/ginkgo v1.10.1 // indirect 11 | github.com/onsi/gomega v1.7.0 // indirect 12 | github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf 13 | github.com/vishvananda/netns v0.0.0-20190625233234-7109fa855b0f // indirect 14 | golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3 // indirect 15 | golang.org/x/sys v0.0.0-20190927073244-c990c680b611 // indirect 16 | golang.org/x/text v0.3.2 // indirect 17 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect 18 | gopkg.in/yaml.v2 v2.2.3 // indirect 19 | ) 20 | -------------------------------------------------------------------------------- /dockin-cni/go.sum: -------------------------------------------------------------------------------- 1 | github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= 2 | github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= 3 | github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= 4 | github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= 5 | github.com/containernetworking/cni v0.7.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= 6 | github.com/containernetworking/cni v0.7.1 h1:fE3r16wpSEyaqY4Z4oFrLMmIGfBYIKpPrHK31EJ9FzE= 7 | github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= 8 | github.com/containernetworking/plugins v0.8.2 h1:5lnwfsAYO+V7yXhysJKy3E1A2Gy9oVut031zfdOzI9w= 9 | github.com/containernetworking/plugins v0.8.2/go.mod h1:TxALKWZpWL79BC3GOYKJzzXr7U8R23PdhwaLp6F3adc= 10 | github.com/coreos/go-iptables v0.4.2/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= 11 | github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 12 | github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= 13 | github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= 14 | github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= 15 | github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= 16 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 17 | github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= 18 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 19 | github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= 20 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 21 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 22 | github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= 23 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 24 | github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= 25 | github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 26 | github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= 27 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 28 | github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= 29 | github.com/juju/errors v0.0.0-20180806074554-22422dad46e1/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= 30 | github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= 31 | github.com/juju/testing v0.0.0-20190613124551-e81189438503/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA= 32 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 33 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 34 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 35 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 36 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 37 | github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= 38 | github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 39 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 40 | github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo= 41 | github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 42 | github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= 43 | github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME= 44 | github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 45 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 46 | github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= 47 | github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= 48 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 49 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 50 | github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf h1:3J37+NPjNyGW/dbfXtj3yWuF9OEepIdGOXRaJGbORV8= 51 | github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= 52 | github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= 53 | github.com/vishvananda/netns v0.0.0-20190625233234-7109fa855b0f h1:nBX3nTcmxEtHSERBJaIo1Qa26VwRaopnZmfDQUXsF4I= 54 | github.com/vishvananda/netns v0.0.0-20190625233234-7109fa855b0f/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= 55 | golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 56 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 57 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 58 | golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 59 | golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3 h1:6KET3Sqa7fkVfD63QnAM81ZeYg5n4HwApOJkufONnHA= 60 | golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 61 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 62 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 63 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 64 | golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 65 | golang.org/x/sys v0.0.0-20190927073244-c990c680b611 h1:q9u40nxWT5zRClI/uU9dHCiYGottAg6Nzz4YUQyHxdA= 66 | golang.org/x/sys v0.0.0-20190927073244-c990c680b611/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 67 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 68 | golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= 69 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 70 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 71 | gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= 72 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 73 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 74 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= 75 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 76 | gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= 77 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 78 | gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= 79 | gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= 80 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= 81 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 82 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 83 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 84 | gopkg.in/yaml.v2 v2.2.3 h1:fvjTMHxHEw/mxHbtzPi3JCcKXQRAnQTBRo6YCJSVHKI= 85 | gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 86 | -------------------------------------------------------------------------------- /dockin-cni/internal/api/add.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) @2021 Webank Group Holding Limited 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | *

7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | *

9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | 15 | package api 16 | 17 | import ( 18 | "github.com/webankfintech/dockin-cni/internal/log" 19 | "github.com/webankfintech/dockin-cni/internal/model" 20 | "github.com/webankfintech/dockin-cni/internal/rm" 21 | 22 | "github.com/containernetworking/cni/pkg/invoke" 23 | "github.com/containernetworking/cni/pkg/skel" 24 | 25 | cnitypes "github.com/containernetworking/cni/pkg/types" 26 | ) 27 | 28 | type DockinCNIAdder struct { 29 | podName string 30 | namespace string 31 | containerID string 32 | cmdArgs *skel.CmdArgs 33 | exec invoke.Exec 34 | delegates []*Delegate 35 | } 36 | 37 | func (c *DockinCNIAdder) add() (cnitypes.Result, error) { 38 | if err := c.setPodAndNS(); err != nil { 39 | return nil, err 40 | } 41 | 42 | netconf, err := model.LoadNetConf(c.cmdArgs.StdinData) 43 | if err != nil { 44 | return nil, log.Errorf("failed to load netconf from stdin=%s, err=%s", 45 | string(c.cmdArgs.StdinData), err.Error()) 46 | } 47 | rd, err := rm.GetRMDataByPodName(c.podName, netconf.Backend) 48 | if err != nil { 49 | return nil, log.Errorf("get rm data failed, %v", err) 50 | } 51 | log.Infof("get pod network information from rm success, podName=%s, %v", c.podName, rd) 52 | 53 | for _, netinfo := range rd.Data { 54 | d := &Delegate{ 55 | netInfo: netinfo, 56 | confDir: netconf.ConfDir, 57 | binDir: netconf.BinDir, 58 | cmdArgs: c.cmdArgs, 59 | podName: c.podName, 60 | namespace: c.namespace, 61 | containerID: c.containerID, 62 | exec: c.exec, 63 | } 64 | if err := d.Initialize(); err != nil { 65 | return nil, log.Errorf("initialize delegate error %s", err.Error()) 66 | } 67 | 68 | log.Infof("success add delegate, netInfo=%v", netinfo) 69 | c.delegates = append(c.delegates, d) 70 | } 71 | 72 | var finalResult cnitypes.Result 73 | for _, delg := range c.delegates { 74 | delgResult, err := delg.add() 75 | if err != nil { 76 | return nil, log.Errorf("exec delegate add error %s", err.Error()) 77 | } 78 | if delg.netInfo.Master && delgResult != nil { 79 | finalResult = delgResult 80 | } 81 | } 82 | 83 | log.Infof("success add pod network, netInfo %v, result=%s", rd.Data, finalResult.String()) 84 | return finalResult, nil 85 | } 86 | 87 | func (c *DockinCNIAdder) setPodAndNS() error { 88 | k8sArgs := &model.K8sArgs{} 89 | log.Infof("set k8s pod and namespace, args=%s", c.cmdArgs.Args) 90 | err := cnitypes.LoadArgs(c.cmdArgs.Args, k8sArgs) 91 | if err != nil { 92 | return log.Errorf("failed to load k8s args, as err=%s", err.Error()) 93 | } 94 | 95 | c.podName = string(k8sArgs.K8S_POD_NAME) 96 | c.namespace = string(k8sArgs.K8S_POD_NAMESPACE) 97 | c.containerID = string(k8sArgs.K8S_POD_INFRA_CONTAINER_ID) 98 | 99 | log.Infof("set k8s pod info, podName=%s, namespace=%s, contaienrID=%s", 100 | c.podName, c.namespace, c.containerID) 101 | return nil 102 | } 103 | 104 | func CmdAdd(args *skel.CmdArgs, exec invoke.Exec) (cnitypes.Result, error) { 105 | log.Infof("add network, input args, ContainerID=%s, Netns=%s, ifName=%s, args=%s, path=%s, stdin=%s", 106 | args.ContainerID, args.Netns, args.IfName, args.Args, args.Path, string(args.StdinData)) 107 | 108 | adder := DockinCNIAdder{ 109 | cmdArgs: args, 110 | exec: exec, 111 | } 112 | result, err := adder.add() 113 | if err != nil { 114 | return nil, log.Errorf("execute add error %s", err.Error()) 115 | } 116 | 117 | log.Infof("success add network, input args, ContainerID=%s, Netns=%s, ifName=%s, args=%s, path=%s, stdin=%s", 118 | args.ContainerID, args.Netns, args.IfName, args.Args, args.Path, string(args.StdinData)) 119 | return result, nil 120 | } 121 | -------------------------------------------------------------------------------- /dockin-cni/internal/api/check.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) @2021 Webank Group Holding Limited 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | *

7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | *

9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | 15 | package api 16 | 17 | import ( 18 | "github.com/webankfintech/dockin-cni/internal/log" 19 | "github.com/webankfintech/dockin-cni/internal/model" 20 | 21 | "github.com/containernetworking/cni/pkg/invoke" 22 | "github.com/containernetworking/cni/pkg/skel" 23 | cnitypes "github.com/containernetworking/cni/pkg/types" 24 | ) 25 | 26 | func Check(args *skel.CmdArgs, exec invoke.Exec) (cnitypes.Result, error) { 27 | log.Infof("check cni, args=%v", args) 28 | 29 | conf, err := model.LoadNetConf(args.StdinData) 30 | if err != nil { 31 | return nil, err 32 | } 33 | 34 | return conf.PrevResult, nil 35 | } 36 | -------------------------------------------------------------------------------- /dockin-cni/internal/api/delegate.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) @2021 Webank Group Holding Limited 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | *

7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | *

9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | 15 | package api 16 | 17 | import ( 18 | "context" 19 | "os" 20 | "path/filepath" 21 | 22 | "github.com/webankfintech/dockin-cni/internal/log" 23 | "github.com/webankfintech/dockin-cni/internal/model" 24 | 25 | "github.com/containernetworking/cni/libcni" 26 | "github.com/containernetworking/cni/pkg/invoke" 27 | "github.com/containernetworking/cni/pkg/skel" 28 | "github.com/containernetworking/plugins/pkg/ns" 29 | "github.com/vishvananda/netlink" 30 | 31 | cnitypes "github.com/containernetworking/cni/pkg/types" 32 | ) 33 | 34 | type Delegate struct { 35 | delegateNetConf *model.DelegateNetConf 36 | netInfo *model.NetInfo 37 | confDir string 38 | binDir string 39 | cmdArgs *skel.CmdArgs 40 | podName string 41 | namespace string 42 | containerID string 43 | exec invoke.Exec 44 | } 45 | 46 | func (d *Delegate) Initialize() error { 47 | delegateNetConf, err := model.NewDelegateNetConf(d.netInfo, d.confDir) 48 | if err != nil { 49 | return log.Errorf(err.Error()) 50 | } 51 | d.delegateNetConf = delegateNetConf 52 | log.Infof("set delegate conf, netinfo=%v, delegate conf=%s", d, string(delegateNetConf.Bytes)) 53 | return nil 54 | } 55 | 56 | func (d *Delegate) add() (cnitypes.Result, error) { 57 | var ( 58 | result cnitypes.Result 59 | err error 60 | ) 61 | nsname := os.Getenv("CNI_NETNS") 62 | if err = d.validateIfName(nsname, d.netInfo.IfName); err != nil { 63 | return nil, log.Errorf(err.Error()) 64 | } 65 | 66 | log.Debugf("prepare to set the CNI_IFNAME=%s", d.netInfo.IfName) 67 | if os.Setenv("CNI_IFNAME", d.netInfo.IfName) != nil { 68 | return nil, log.Errorf("failed to set current ifName=%s, podName=%s", d.netInfo.IfName, d.podName) 69 | } 70 | binDirs := filepath.SplitList(os.Getenv("CNI_PATH")) 71 | binDirs = append([]string{d.binDir}, binDirs...) 72 | cniNet := libcni.NewCNIConfig(binDirs, d.exec) 73 | 74 | log.Infof("prepare to parse NetworkConfig, byte=%s", string(d.delegateNetConf.Bytes)) 75 | networkConfig, err := libcni.ConfFromBytes(d.delegateNetConf.Bytes) 76 | if err != nil { 77 | return nil, log.Errorf("error in converting the raw bytes to conf: %v", err) 78 | } 79 | 80 | log.Infof("prepare call cni api, conf = %s", string(networkConfig.Bytes)) 81 | runtimeConf := d.createDelegateCNIRuntimeConf() 82 | result, err = cniNet.AddNetwork(context.Background(), networkConfig, runtimeConf) 83 | if err != nil { 84 | return nil, log.Errorf("error in getting result from AddNetwork: %v", err) 85 | } 86 | 87 | log.Infof("success call cni api to create network, podName=%s, result=%s", d.podName, result.String()) 88 | return result, nil 89 | } 90 | 91 | func (d *Delegate) createDelegateCNIRuntimeConf() *libcni.RuntimeConf { 92 | rt := &libcni.RuntimeConf{ 93 | ContainerID: d.cmdArgs.ContainerID, 94 | NetNS: d.cmdArgs.Netns, 95 | IfName: d.netInfo.IfName, 96 | Args: [][2]string{ 97 | {"IgnoreUnknown", string("true")}, 98 | {"K8S_POD_NAMESPACE", d.namespace}, 99 | {"K8S_POD_NAME", d.podName}, 100 | {"K8S_POD_INFRA_CONTAINER_ID", d.containerID}, 101 | }, 102 | } 103 | 104 | return rt 105 | } 106 | 107 | func (d *Delegate) validateIfName(nsname string, ifname string) error { 108 | log.Infof("validate ifName, ns=%s, ifName=%s", nsname, ifname) 109 | podNs, err := ns.GetNS(nsname) 110 | if err != nil { 111 | return log.Errorf(err.Error()) 112 | } 113 | 114 | err = podNs.Do(func(_ ns.NetNS) error { 115 | _, err := netlink.LinkByName(ifname) 116 | if err != nil { 117 | if err.Error() == "Link not found" { 118 | return nil 119 | } 120 | return log.Errorf("link by name error %v", err) 121 | } 122 | return log.Errorf("interface name %s already exists", ifname) 123 | }) 124 | 125 | log.Infof("validate ifName end, nsname=%s, ifName=%s, err=%v", nsname, ifname, err) 126 | return err 127 | } 128 | 129 | func (d *Delegate) setDefaultGateway() error { 130 | return nil 131 | } 132 | 133 | func (d *Delegate) Delete() { 134 | 135 | } 136 | -------------------------------------------------------------------------------- /dockin-cni/internal/api/delete.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) @2021 Webank Group Holding Limited 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | *

7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | *

9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | 15 | package api 16 | 17 | import ( 18 | "github.com/containernetworking/cni/pkg/invoke" 19 | "github.com/containernetworking/cni/pkg/skel" 20 | ) 21 | 22 | func CmdDelete(args *skel.CmdArgs, exec invoke.Exec) error { 23 | return nil 24 | } 25 | -------------------------------------------------------------------------------- /dockin-cni/internal/log/logger.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) @2021 Webank Group Holding Limited 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | *

7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | *

9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | 15 | package log 16 | 17 | import ( 18 | "fmt" 19 | "os" 20 | "runtime" 21 | "strings" 22 | "time" 23 | 24 | "github.com/google/uuid" 25 | ) 26 | 27 | var bizSeq string 28 | 29 | func init() { 30 | loggerStderr = true 31 | loggerFp = nil 32 | loggerLevel = PanicLevel 33 | bizSeq = uuid.New().String() 34 | } 35 | 36 | type Level uint32 37 | 38 | const ( 39 | PanicLevel Level = iota 40 | ErrorLevel 41 | InfoLevel 42 | DebugLevel 43 | MaxLevel 44 | UnknownLevel 45 | ) 46 | 47 | var loggerStderr bool 48 | var loggerFp *os.File 49 | var loggerLevel Level 50 | 51 | const defaultTimestampFormat = time.RFC3339 52 | 53 | func (l Level) String() string { 54 | switch l { 55 | case PanicLevel: 56 | return "panic" 57 | case InfoLevel: 58 | return "info" 59 | case ErrorLevel: 60 | return "error" 61 | case DebugLevel: 62 | return "debug" 63 | } 64 | return "unknown" 65 | } 66 | 67 | func printf(level Level, format string, a ...interface{}) { 68 | header := "%s [%s] " 69 | t := time.Now() 70 | if level > loggerLevel { 71 | return 72 | } 73 | 74 | funcName, _, line, _ := runtime.Caller(2) 75 | nf := fmt.Sprintf("-(%s:%d) %s, bizSeq=%%s", runtime.FuncForPC(funcName).Name(), line, format) 76 | a = append(a, bizSeq) 77 | 78 | if loggerStderr { 79 | fmt.Fprintf(os.Stderr, header, t.Format(defaultTimestampFormat), level) 80 | fmt.Fprintf(os.Stderr, nf, a...) 81 | fmt.Fprintf(os.Stderr, "\n") 82 | } 83 | 84 | if loggerFp != nil { 85 | fmt.Fprintf(loggerFp, header, t.Format(defaultTimestampFormat), level) 86 | fmt.Fprintf(loggerFp, nf, a...) 87 | fmt.Fprintf(loggerFp, "\n") 88 | } 89 | } 90 | 91 | func Debugf(format string, a ...interface{}) { 92 | printf(DebugLevel, format, a...) 93 | } 94 | 95 | func Infof(format string, a ...interface{}) { 96 | printf(InfoLevel, format, a...) 97 | } 98 | 99 | func Errorf(format string, a ...interface{}) error { 100 | printf(ErrorLevel, format, a...) 101 | return fmt.Errorf(format, a...) 102 | } 103 | 104 | func getloggerLevel(levelStr string) Level { 105 | switch strings.ToLower(levelStr) { 106 | case "debug": 107 | return DebugLevel 108 | case "verbose": 109 | return InfoLevel 110 | case "error": 111 | return ErrorLevel 112 | case "panic": 113 | return PanicLevel 114 | } 115 | fmt.Fprintf(os.Stderr, "logger: cannot set logger level to %s\n", levelStr) 116 | return UnknownLevel 117 | } 118 | 119 | func SetLogLevel(levelStr string) { 120 | level := getloggerLevel(levelStr) 121 | if level < MaxLevel { 122 | loggerLevel = level 123 | } 124 | } 125 | 126 | func SetLogFile(filename string) { 127 | if filename == "" { 128 | return 129 | } 130 | 131 | fp, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644) 132 | if err != nil { 133 | loggerFp = nil 134 | fmt.Fprintf(os.Stderr, "logger: cannot open %s", filename) 135 | } 136 | loggerFp = fp 137 | } 138 | -------------------------------------------------------------------------------- /dockin-cni/internal/model/bridge_conf.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) @2021 Webank Group Holding Limited 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | *

7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | *

9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | 15 | package model 16 | 17 | import "github.com/containernetworking/cni/pkg/types" 18 | 19 | type BridgeNetConf struct { 20 | types.NetConf 21 | BrName string `json:"bridge"` 22 | IsGW bool `json:"isGateway"` 23 | IsDefaultGW bool `json:"isDefaultGateway"` 24 | ForceAddress bool `json:"forceAddress"` 25 | IPMasq bool `json:"ipMasq"` 26 | MTU int `json:"mtu"` 27 | HairpinMode bool `json:"hairpinMode"` 28 | PromiscMode bool `json:"promiscMode"` 29 | Vlan int `json:"vlan"` 30 | 31 | Routes []*types.Route `json:"routes"` 32 | DNS *types.DNS `json:"dns"` 33 | } 34 | -------------------------------------------------------------------------------- /dockin-cni/internal/model/delegate_net_conf.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) @2021 Webank Group Holding Limited 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | *

7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | *

9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | 15 | package model 16 | 17 | import ( 18 | "encoding/json" 19 | "fmt" 20 | "io/ioutil" 21 | "net" 22 | 23 | "github.com/webankfintech/dockin-cni/internal/log" 24 | "github.com/webankfintech/dockin-cni/internal/utils" 25 | 26 | "github.com/containernetworking/cni/libcni" 27 | "github.com/containernetworking/cni/pkg/types" 28 | cnitypes "github.com/containernetworking/cni/pkg/types" 29 | ) 30 | 31 | var ( 32 | _defaultIPAMType = "dockin-ipam" 33 | _defaultIPAMName = "dockin-ipam" 34 | ) 35 | 36 | type DelegateNetConf struct { 37 | Conf types.NetConf 38 | Bytes []byte 39 | } 40 | 41 | func NewDelegateNetConf(netInfo *NetInfo, confDir string) (*DelegateNetConf, error) { 42 | log.Infof("create DelegateNetConf, Type=%s, confDir=%s", netInfo.Type, confDir) 43 | 44 | files, err := libcni.ConfFiles(confDir, []string{".conf", ".json", ".conflist"}) 45 | switch { 46 | case err != nil: 47 | return nil, log.Errorf("no networks files found in %s", confDir) 48 | case len(files) == 0: 49 | return nil, log.Errorf("confDir %s dir is empty or no conf file type", confDir) 50 | } 51 | 52 | var ( 53 | bytes []byte 54 | found = false 55 | netc *libcni.NetworkConfig 56 | ) 57 | for _, confFile := range files { 58 | bytes, err = ioutil.ReadFile(confFile) 59 | if err != nil { 60 | log.Errorf("error read conf file %s: %s", confFile, err) 61 | continue 62 | } 63 | netc, err = libcni.ConfFromBytes(bytes) 64 | if err != nil { 65 | log.Errorf("error marshal to network config, conf file %s: %s", confFile, err) 66 | continue 67 | } 68 | if netc.Network.Name == netInfo.Type { 69 | found = true 70 | break 71 | } 72 | } 73 | if !found { 74 | return nil, log.Errorf("no config file exist, name=%s, confDir=%s", netInfo.Type, confDir) 75 | } 76 | log.Infof("load delegate net conf success, name=%s, content=%s", netInfo.Type, string(bytes)) 77 | 78 | confMap := make(map[string]interface{}) 79 | if err := json.Unmarshal(bytes, &confMap); err != nil { 80 | return nil, fmt.Errorf("error unmarshal delegate net conf to conf map, type=%s: err=%v", 81 | netInfo.Type, err) 82 | } 83 | bridgeNetConf := &BridgeNetConf{} 84 | if err := json.Unmarshal(bytes, bridgeNetConf); err != nil { 85 | return nil, fmt.Errorf("error unmarshal delegate net conf to BridgeNetConf, type=%s: err=%v", 86 | netInfo.Type, err) 87 | } 88 | 89 | mask := utils.ParseIPv4Mask(netInfo.SubnetMask) 90 | size, _ := mask.Size() 91 | cidrIp := fmt.Sprintf("%s/%d", netInfo.PodIP, size) 92 | 93 | if _, _, err := net.ParseCIDR(cidrIp); err != nil { 94 | return nil, log.Errorf("failed to parse CIDR %q", netInfo.PodIP) 95 | } 96 | ipam := &DockinIPAMConfig{} 97 | ipam.Type = _defaultIPAMType 98 | ipam.Name = _defaultIPAMName 99 | ipam.Addresses = []Address{{ 100 | AddressStr: cidrIp, 101 | Gateway: net.ParseIP(netInfo.Gateway), 102 | }} 103 | if bridgeNetConf.Routes == nil { 104 | ipam.Routes = []*cnitypes.Route{ 105 | { 106 | Dst: func() net.IPNet { 107 | n, _ := utils.ParseIPNet("0.0.0.0/0") 108 | return *n 109 | }(), 110 | GW: net.ParseIP(netInfo.Gateway), 111 | }, 112 | } 113 | } else { 114 | ipam.Routes = bridgeNetConf.Routes 115 | } 116 | if bridgeNetConf.DNS != nil { 117 | ipam.DNS = bridgeNetConf.DNS 118 | } 119 | 120 | confMap["ipam"] = ipam 121 | 122 | if bytes, err = json.Marshal(confMap); err != nil { 123 | return nil, log.Errorf("error marshal conf map to bytes, type %s: err=%s", netInfo.Type, err) 124 | } 125 | 126 | if err != nil || bytes == nil { 127 | return nil, log.Errorf("error convert content to NetworkConfig, %s, err=%s", string(bytes), err.Error()) 128 | } 129 | log.Infof("load conf from file return conf network Type=%s, conf bytes=%s", netInfo.Type, string(bytes)) 130 | 131 | delegateConf := &DelegateNetConf{} 132 | if err := json.Unmarshal(bytes, &delegateConf.Conf); err != nil { 133 | return nil, log.Errorf("LoadDelegateNetConf: error unmarshal delegate config: %v", err) 134 | } 135 | delegateConf.Bytes = bytes 136 | log.Infof("success create DelegateNetConf, Type=%s, delegate conf=%s", netInfo.Type, string(delegateConf.Bytes)) 137 | return delegateConf, nil 138 | } 139 | -------------------------------------------------------------------------------- /dockin-cni/internal/model/ipam_conf.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) @2021 Webank Group Holding Limited 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | *

7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | *

9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | 15 | package model 16 | 17 | import ( 18 | "net" 19 | 20 | "github.com/containernetworking/cni/pkg/types" 21 | ) 22 | 23 | type DockinIPAMConfig struct { 24 | types.IPAM 25 | Name string 26 | Routes []*types.Route `json:"routes"` 27 | Addresses []Address `json:"addresses,omitempty"` 28 | DNS *types.DNS `json:"dns"` 29 | } 30 | 31 | type Address struct { 32 | AddressStr string `json:"address"` 33 | Gateway net.IP `json:"gateway,omitempty"` 34 | Address net.IPNet 35 | Version string 36 | } 37 | -------------------------------------------------------------------------------- /dockin-cni/internal/model/k8s_args.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) @2021 Webank Group Holding Limited 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | *

7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | *

9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | 15 | package model 16 | 17 | import ( 18 | "net" 19 | 20 | "github.com/containernetworking/cni/pkg/types" 21 | ) 22 | 23 | type K8sArgs struct { 24 | types.CommonArgs 25 | IP net.IP 26 | K8S_POD_NAME types.UnmarshallableString 27 | K8S_POD_NAMESPACE types.UnmarshallableString 28 | K8S_POD_INFRA_CONTAINER_ID types.UnmarshallableString 29 | } 30 | -------------------------------------------------------------------------------- /dockin-cni/internal/model/net_conf.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) @2021 Webank Group Holding Limited 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | *

7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | *

9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | 15 | package model 16 | 17 | import ( 18 | "encoding/json" 19 | 20 | "github.com/webankfintech/dockin-cni/internal/log" 21 | 22 | "github.com/containernetworking/cni/pkg/types" 23 | "github.com/containernetworking/cni/pkg/types/current" 24 | "github.com/containernetworking/cni/pkg/version" 25 | ) 26 | 27 | const ( 28 | defaultConfDir = "/etc/cni/dockin/net.d" 29 | defaultBinDir = "/opt/cni/bin" 30 | ) 31 | 32 | type NetConf struct { 33 | types.NetConf 34 | 35 | RawPrevResult *map[string]interface{} `json:"prevResult"` 36 | PrevResult *current.Result `json:"-"` 37 | 38 | ConfDir string `json:"confDir"` 39 | BinDir string `json:"binDir"` 40 | LogFile string `json:"logFile"` 41 | LogLevel string `json:"logLevel"` 42 | 43 | Backend string `json:"backend"` 44 | RuntimeConfig *RuntimeConfig `json:"runtimeConfig,omitempty"` 45 | } 46 | 47 | func (n *NetConf) ToString() string { 48 | d, _ := json.Marshal(n) 49 | return string(d) 50 | } 51 | 52 | type RuntimeConfig struct { 53 | PortMaps []*PortMapEntry `json:"portMappings,omitempty"` 54 | Bandwidth *BandwidthEntry `json:"bandwidth,omitempty"` 55 | IPs []string `json:"ips,omitempty"` 56 | Mac string `json:"mac,omitempty"` 57 | } 58 | 59 | type PortMapEntry struct { 60 | HostPort int `json:"hostPort"` 61 | ContainerPort int `json:"containerPort"` 62 | Protocol string `json:"protocol,omitempty"` 63 | HostIP string `json:"hostIP,omitempty"` 64 | } 65 | 66 | type BandwidthEntry struct { 67 | IngressRate int `json:"ingressRate"` 68 | IngressBurst int `json:"ingressBurst"` 69 | 70 | EgressRate int `json:"egressRate"` 71 | EgressBurst int `json:"egressBurst"` 72 | } 73 | 74 | func LoadNetConf(bytes []byte) (*NetConf, error) { 75 | netconf := &NetConf{} 76 | 77 | log.Infof("load net conf, input bytes %s", string(bytes)) 78 | if err := json.Unmarshal(bytes, netconf); err != nil { 79 | return nil, log.Errorf("failed to load net conf: %v", err) 80 | } 81 | 82 | if netconf.LogFile != "" { 83 | log.SetLogFile(netconf.LogFile) 84 | } 85 | if netconf.LogLevel != "" { 86 | log.SetLogLevel(netconf.LogLevel) 87 | } 88 | 89 | if netconf.RawPrevResult != nil { 90 | resultBytes, err := json.Marshal(netconf.RawPrevResult) 91 | if err != nil { 92 | return nil, log.Errorf("could not serialize prevResult: %v", err) 93 | } 94 | res, err := version.NewResult(netconf.CNIVersion, resultBytes) 95 | if err != nil { 96 | return nil, log.Errorf("could not parse prevResult: %v", err) 97 | } 98 | netconf.RawPrevResult = nil 99 | netconf.PrevResult, err = current.NewResultFromResult(res) 100 | if err != nil { 101 | return nil, log.Errorf("could not convert result to current version: %v", err) 102 | } 103 | } 104 | 105 | if netconf.ConfDir == "" { 106 | netconf.ConfDir = defaultConfDir 107 | } 108 | 109 | if netconf.BinDir == "" { 110 | netconf.BinDir = defaultBinDir 111 | } 112 | 113 | return netconf, nil 114 | } 115 | -------------------------------------------------------------------------------- /dockin-cni/internal/model/pod.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) @2021 Webank Group Holding Limited 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | *

7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | *

9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | 15 | package model 16 | 17 | import ( 18 | "encoding/json" 19 | "errors" 20 | "fmt" 21 | ) 22 | 23 | type PodInfo struct { 24 | Name string `json:"name"` 25 | Namespace string `json:"namespace"` 26 | UID string `json:"uid"` 27 | NetInfos []*NetInfo `json:"netinfo"` 28 | } 29 | 30 | func (p *PodInfo) GetNetInfoByName(name string) (*NetInfo, error){ 31 | for _, v := range p.NetInfos { 32 | if name == v.Type { 33 | return v, nil 34 | } 35 | } 36 | return nil, errors.New(fmt.Sprintf("GetNetInfoByName: no net info for name=%s", name)) 37 | } 38 | 39 | func (p *PodInfo)ToString() string { 40 | d, _ := json.Marshal(p) 41 | return string(d) 42 | } 43 | 44 | type RMData struct { 45 | Code int `json:"code"` 46 | ReqID string `json:"reqId"` 47 | Message string `json:"message"` 48 | Data []*NetInfo `json:"data"` 49 | } 50 | 51 | type NetInfo struct { 52 | Type string `json:"type"` 53 | PodIP string `json:"podIp"` 54 | IfName string `json:"ifName"` 55 | SubnetMask string `json:"subnetMask"` 56 | Gateway string `json:"gateway"` 57 | Master bool `json:"master"` 58 | } 59 | 60 | -------------------------------------------------------------------------------- /dockin-cni/internal/rm/rm.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) @2021 Webank Group Holding Limited 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | *

7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | *

9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | 15 | package rm 16 | 17 | import ( 18 | "encoding/json" 19 | "fmt" 20 | "io/ioutil" 21 | "net/http" 22 | "path/filepath" 23 | "time" 24 | 25 | "github.com/webankfintech/dockin-cni/internal/log" 26 | "github.com/webankfintech/dockin-cni/internal/model" 27 | ) 28 | 29 | func GetRMDataByMock(confDir, podName string) (*model.RMData, error) { 30 | confPath := filepath.Join(confDir, "mock.data") 31 | content, err := ioutil.ReadFile(confPath) 32 | if err != nil { 33 | return nil, log.Errorf("get mock rm data error, ReadFile, filepath=%v, err=%s", 34 | confPath, err.Error()) 35 | } 36 | log.Infof("get mock rm data success: filepath=%v, resp=%s", 37 | confPath, string(content)) 38 | 39 | rmd := &model.RMData{} 40 | if err := json.Unmarshal(content, rmd); err != nil { 41 | return nil, log.Errorf("get mock rm data error, Unmarshal, content=%v, err=%s", 42 | string(content), err.Error()) 43 | } 44 | 45 | if rmd.Code != 0 { 46 | return nil, log.Errorf("get mock rm data error, code != 0, content=%v", 47 | string(content)) 48 | } 49 | 50 | return rmd, nil 51 | } 52 | 53 | func GetRMDataByPodName(podName, backend string) (*model.RMData, error) { 54 | client := http.Client{ 55 | Timeout: time.Duration(5 * time.Second), 56 | } 57 | 58 | url := fmt.Sprintf("%s?podName=%s", backend, podName) 59 | log.Infof("get RM data by podName start: podName=%v, url=%v", 60 | podName, url) 61 | resp, err := client.Get(url) 62 | if err != nil { 63 | return nil, log.Errorf("http get error, RM HTTP GET, url=%v, err=%s", 64 | url, err.Error()) 65 | } 66 | 67 | content, err := ioutil.ReadAll(resp.Body) 68 | if err != nil { 69 | return nil, log.Errorf("parse http response error, HTTP.ReadAll, url=%v, err=%s", 70 | url, err.Error()) 71 | } 72 | log.Infof("get net info from rm success: url=%v, resp=%s", 73 | url, string(content)) 74 | 75 | rmd := &model.RMData{} 76 | if err := json.Unmarshal(content, rmd); err != nil { 77 | return nil, log.Errorf("unmarshal error, Unmarshal, content=%v, err=%s", 78 | string(content), err.Error()) 79 | } 80 | 81 | if rmd.Code != 0 { 82 | return nil, log.Errorf("getRMDataByPodName error, code != 0, content=%v", 83 | string(content)) 84 | } 85 | return rmd, nil 86 | } 87 | -------------------------------------------------------------------------------- /dockin-cni/internal/utils/net.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) @2021 Webank Group Holding Limited 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | *

7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | *

9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | 15 | package utils 16 | 17 | import ( 18 | "fmt" 19 | "net" 20 | "strconv" 21 | "strings" 22 | 23 | "github.com/webankfintech/dockin-cni/internal/log" 24 | 25 | "github.com/containernetworking/cni/pkg/skel" 26 | cnitypes "github.com/containernetworking/cni/pkg/types" 27 | "github.com/containernetworking/cni/pkg/types/current" 28 | "github.com/containernetworking/plugins/pkg/ns" 29 | "github.com/vishvananda/netlink" 30 | ) 31 | 32 | func DeleteDefaultGW(args *skel.CmdArgs, ifName string, res *cnitypes.Result) (*current.Result, error) { 33 | result, err := current.NewResultFromResult(*res) 34 | if err != nil { 35 | return nil, log.Errorf("delete default gateway error %v", err) 36 | } 37 | 38 | netns, err := ns.GetNS(args.Netns) 39 | if err != nil { 40 | return nil, log.Errorf("error getting netns %v", err) 41 | } 42 | defer netns.Close() 43 | 44 | err = netns.Do(func(_ ns.NetNS) error { 45 | var err error 46 | link, _ := netlink.LinkByName(ifName) 47 | routes, _ := netlink.RouteList(link, netlink.FAMILY_ALL) 48 | for _, nlroute := range routes { 49 | if nlroute.Dst == nil { 50 | err = netlink.RouteDel(&nlroute) 51 | } 52 | } 53 | return err 54 | }) 55 | var newRoutes []*cnitypes.Route 56 | for _, route := range result.Routes { 57 | if mask, _ := route.Dst.Mask.Size(); mask != 0 { 58 | newRoutes = append(newRoutes, route) 59 | } 60 | } 61 | result.Routes = newRoutes 62 | return result, err 63 | } 64 | 65 | func SetDefaultGW(args *skel.CmdArgs, ifName string, gateways []net.IP, res *cnitypes.Result) (*current.Result, error) { 66 | 67 | result, err := current.NewResultFromResult(*res) 68 | if err != nil { 69 | return nil, log.Errorf("set default gateway error %v", err) 70 | } 71 | 72 | netns, err := ns.GetNS(args.Netns) 73 | if err != nil { 74 | return nil, log.Errorf("error getting netns %v", err) 75 | } 76 | defer netns.Close() 77 | 78 | var newResultDefaultRoutes []*cnitypes.Route 79 | 80 | err = netns.Do(func(_ ns.NetNS) error { 81 | var err error 82 | 83 | link, _ := netlink.LinkByName(ifName) 84 | 85 | for _, gw := range gateways { 86 | 87 | log.Infof("adding default route on %v (index: %v) to %v", ifName, link.Attrs().Index, gw) 88 | newDefaultRoute := netlink.Route{ 89 | LinkIndex: link.Attrs().Index, 90 | Gw: gw, 91 | } 92 | 93 | 94 | _, dstipnet, _ := net.ParseCIDR("::0/0") 95 | if strings.Count(gw.String(), ":") < 2 { 96 | _, dstipnet, _ = net.ParseCIDR("0.0.0.0/0") 97 | } 98 | newResultDefaultRoutes = append(newResultDefaultRoutes, &cnitypes.Route{Dst: *dstipnet, GW: gw}) 99 | 100 | err = netlink.RouteAdd(&newDefaultRoute) 101 | if err != nil { 102 | log.Errorf("add route route: %v", err) 103 | } 104 | } 105 | return err 106 | }) 107 | 108 | result.Routes = newResultDefaultRoutes 109 | return result, err 110 | 111 | } 112 | 113 | func ParseIPv4Mask(s string) net.IPMask { 114 | mask := net.ParseIP(s) 115 | if mask == nil { 116 | if len(s) != 8 { 117 | return nil 118 | } 119 | m := []int{} 120 | for i := 0; i < 4; i++ { 121 | b := "0x" + s[2*i:2*i+2] 122 | d, err := strconv.ParseInt(b, 0, 0) 123 | if err != nil { 124 | return nil 125 | } 126 | m = append(m, int(d)) 127 | } 128 | s := fmt.Sprintf("%d.%d.%d.%d", m[0], m[1], m[2], m[3]) 129 | mask = net.ParseIP(s) 130 | if mask == nil { 131 | return nil 132 | } 133 | } 134 | return net.IPv4Mask(mask[12], mask[13], mask[14], mask[15]) 135 | } 136 | 137 | func ParseIPNet(s string) (*net.IPNet, error) { 138 | ip, ipNet, err := net.ParseCIDR(s) 139 | if err != nil { 140 | return nil, err 141 | } 142 | ipNet.IP = ip 143 | return ipNet, nil 144 | } 145 | -------------------------------------------------------------------------------- /dockin-ipam/Makefile: -------------------------------------------------------------------------------- 1 | BINARY="dockin-ipam" 2 | VERSION=0.1.0 3 | BUILD=`date +%FT%T%z` 4 | 5 | PACKAGES=`go list ./... | grep -v /vendor/` 6 | VETPACKAGES=`go list ./... | grep -v /vendor/ | grep -v /examples/` 7 | GOFILES=`find . -name "*.go" -type f -not -path "./vendor/*"` 8 | 9 | OS=linux 10 | ARCH=amd64 11 | 12 | default: 13 | go mod tidy 14 | go mod vendor 15 | mkdir -p build 16 | cd build && GOOS=${OS} GOARCH=${ARCH} go build -o ${BINARY} ../cmd 17 | 18 | 19 | list: 20 | echo ${PACKAGES} 21 | echo ${VETPACKAGES} 22 | echo ${GOFILES} 23 | 24 | fmt: 25 | gofmt -s -w ${GOFILES} 26 | 27 | fmt-check: 28 | diff=?(gofmt -s -d $(GOFILES)); \ 29 | if [ -n "$$diff" ]; then \ 30 | echo "Please run 'make fmt' and commit the result:"; \ 31 | echo "$${diff}"; \ 32 | exit 1; \ 33 | fi; 34 | 35 | vet: 36 | go vet $(VETPACKAGES) 37 | 38 | clean: 39 | if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi 40 | 41 | 42 | .PHONY: default fmt fmt-check install vet clean 43 | -------------------------------------------------------------------------------- /dockin-ipam/cmd/dockin-ipam.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) @2021 Webank Group Holding Limited 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | *

7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | *

9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | 15 | package main 16 | 17 | import ( 18 | "encoding/json" 19 | "fmt" 20 | "net" 21 | "strings" 22 | 23 | "github.com/containernetworking/cni/pkg/skel" 24 | "github.com/containernetworking/cni/pkg/types" 25 | types020 "github.com/containernetworking/cni/pkg/types/020" 26 | "github.com/containernetworking/cni/pkg/types/current" 27 | "github.com/containernetworking/cni/pkg/version" 28 | ) 29 | 30 | type Net struct { 31 | Name string `json:"name"` 32 | CNIVersion string `json:"cniVersion"` 33 | IPAM *IPAMConfig `json:"ipam"` 34 | 35 | RuntimeConfig struct { 36 | IPs []string `json:"ips,omitempty"` 37 | } `json:"runtimeConfig,omitempty"` 38 | Args *struct { 39 | A *IPAMArgs `json:"cni"` 40 | } `json:"args"` 41 | } 42 | 43 | type IPAMConfig struct { 44 | Name string 45 | Type string `json:"type"` 46 | Routes []*types.Route `json:"routes"` 47 | Addresses []Address `json:"addresses,omitempty"` 48 | DNS types.DNS `json:"dns"` 49 | } 50 | 51 | type IPAMEnvArgs struct { 52 | types.CommonArgs 53 | IP types.UnmarshallableString `json:"ip,omitempty"` 54 | GATEWAY types.UnmarshallableString `json:"gateway,omitempty"` 55 | } 56 | 57 | type IPAMArgs struct { 58 | IPs []string `json:"ips"` 59 | } 60 | 61 | type Address struct { 62 | AddressStr string `json:"address"` 63 | Gateway net.IP `json:"gateway,omitempty"` 64 | Address net.IPNet 65 | Version string 66 | } 67 | 68 | func main() { 69 | skel.PluginMain(cmdAdd, cmdCheck, cmdDel, version.All, "dockin ipam") 70 | } 71 | 72 | func loadNetConf(bytes []byte) (*types.NetConf, string, error) { 73 | n := &types.NetConf{} 74 | if err := json.Unmarshal(bytes, n); err != nil { 75 | return nil, "", fmt.Errorf("failed to load netconf: %v", err) 76 | } 77 | return n, n.CNIVersion, nil 78 | } 79 | 80 | func cmdCheck(args *skel.CmdArgs) error { 81 | ipamConf, _, err := LoadIPAMConfig(args.StdinData, args.Args) 82 | if err != nil { 83 | return err 84 | } 85 | 86 | n, _, err := loadNetConf(args.StdinData) 87 | if err != nil { 88 | return err 89 | } 90 | 91 | if n.RawPrevResult == nil { 92 | return fmt.Errorf("Required prevResult missing") 93 | } 94 | 95 | if err := version.ParsePrevResult(n); err != nil { 96 | return err 97 | } 98 | 99 | result, err := current.NewResultFromResult(n.PrevResult) 100 | if err != nil { 101 | return err 102 | } 103 | 104 | for _, rangeset := range ipamConf.Addresses { 105 | for _, ips := range result.IPs { 106 | 107 | if rangeset.Address.IP.Equal(ips.Address.IP) { 108 | if rangeset.Gateway == nil { 109 | break 110 | } else if rangeset.Gateway.Equal(ips.Gateway) { 111 | break 112 | } 113 | return fmt.Errorf("static: Failed to match addr %v on interface %v", ips.Address.IP, args.IfName) 114 | } 115 | } 116 | } 117 | 118 | return nil 119 | } 120 | 121 | func canonicalizeIP(ip *net.IP) error { 122 | if ip.To4() != nil { 123 | *ip = ip.To4() 124 | return nil 125 | } else if ip.To16() != nil { 126 | *ip = ip.To16() 127 | return nil 128 | } 129 | return fmt.Errorf("IP %s not v4 nor v6", *ip) 130 | } 131 | 132 | func LoadIPAMConfig(bytes []byte, envArgs string) (*IPAMConfig, string, error) { 133 | n := Net{} 134 | if err := json.Unmarshal(bytes, &n); err != nil { 135 | return nil, "", err 136 | } 137 | 138 | if envArgs != "" { 139 | e := IPAMEnvArgs{} 140 | err := types.LoadArgs(envArgs, &e) 141 | if err != nil { 142 | return nil, "", err 143 | } 144 | 145 | if e.IP != "" { 146 | for _, item := range strings.Split(string(e.IP), ",") { 147 | ipstr := strings.TrimSpace(item) 148 | 149 | ip, subnet, err := net.ParseCIDR(ipstr) 150 | if err != nil { 151 | return nil, "", fmt.Errorf("invalid CIDR %s: %s", ipstr, err) 152 | } 153 | 154 | addr := Address{ 155 | Address: net.IPNet{IP: ip, Mask: subnet.Mask}, 156 | AddressStr: ipstr, 157 | } 158 | n.IPAM.Addresses = append(n.IPAM.Addresses, addr) 159 | } 160 | } 161 | 162 | if e.GATEWAY != "" { 163 | for _, item := range strings.Split(string(e.GATEWAY), ",") { 164 | gwip := net.ParseIP(strings.TrimSpace(item)) 165 | if gwip == nil { 166 | return nil, "", fmt.Errorf("invalid gateway address: %s", item) 167 | } 168 | 169 | for i := range n.IPAM.Addresses { 170 | if n.IPAM.Addresses[i].Address.Contains(gwip) { 171 | n.IPAM.Addresses[i].Gateway = gwip 172 | } 173 | } 174 | } 175 | } 176 | } 177 | 178 | if n.Args != nil && n.Args.A != nil && len(n.Args.A.IPs) != 0 { 179 | n.IPAM.Addresses = make([]Address, 0, len(n.Args.A.IPs)) 180 | for _, addr := range n.Args.A.IPs { 181 | n.IPAM.Addresses = append(n.IPAM.Addresses, Address{AddressStr: addr}) 182 | } 183 | } 184 | 185 | if len(n.RuntimeConfig.IPs) != 0 { 186 | n.IPAM.Addresses = make([]Address, 0, len(n.RuntimeConfig.IPs)) 187 | for _, addr := range n.RuntimeConfig.IPs { 188 | n.IPAM.Addresses = append(n.IPAM.Addresses, Address{AddressStr: addr}) 189 | } 190 | } 191 | 192 | if n.IPAM == nil { 193 | return nil, "", fmt.Errorf("IPAM config missing 'ipam' key") 194 | } 195 | 196 | numV4 := 0 197 | numV6 := 0 198 | 199 | for i := range n.IPAM.Addresses { 200 | ip, addr, err := net.ParseCIDR(n.IPAM.Addresses[i].AddressStr) 201 | if err != nil { 202 | return nil, "", fmt.Errorf("invalid CIDR %s: %s", n.IPAM.Addresses[i].AddressStr, err) 203 | } 204 | n.IPAM.Addresses[i].Address = *addr 205 | n.IPAM.Addresses[i].Address.IP = ip 206 | 207 | if err := canonicalizeIP(&n.IPAM.Addresses[i].Address.IP); err != nil { 208 | return nil, "", fmt.Errorf("invalid address %d: %s", i, err) 209 | } 210 | 211 | if n.IPAM.Addresses[i].Address.IP.To4() != nil { 212 | n.IPAM.Addresses[i].Version = "4" 213 | numV4++ 214 | } else { 215 | n.IPAM.Addresses[i].Version = "6" 216 | numV6++ 217 | } 218 | } 219 | 220 | if numV4 > 1 || numV6 > 1 { 221 | for _, v := range types020.SupportedVersions { 222 | if n.CNIVersion == v { 223 | return nil, "", fmt.Errorf("CNI version %v does not support more than 1 address per family", n.CNIVersion) 224 | } 225 | } 226 | } 227 | 228 | n.IPAM.Name = n.Name 229 | 230 | return n.IPAM, n.CNIVersion, nil 231 | } 232 | 233 | func cmdAdd(args *skel.CmdArgs) error { 234 | ipamConf, confVersion, err := LoadIPAMConfig(args.StdinData, args.Args) 235 | if err != nil { 236 | return err 237 | } 238 | 239 | result := ¤t.Result{} 240 | result.DNS = ipamConf.DNS 241 | result.Routes = ipamConf.Routes 242 | for _, v := range ipamConf.Addresses { 243 | result.IPs = append(result.IPs, ¤t.IPConfig{ 244 | Version: v.Version, 245 | Address: v.Address, 246 | Gateway: v.Gateway}) 247 | } 248 | 249 | return types.PrintResult(result, confVersion) 250 | } 251 | 252 | func cmdDel(args *skel.CmdArgs) error { 253 | return nil 254 | } 255 | -------------------------------------------------------------------------------- /dockin-ipam/docs.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) @2021 Webank Group Holding Limited 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | *

7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | *

9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | 15 | package dockin_ipam 16 | -------------------------------------------------------------------------------- /dockin-ipam/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/webankfintech/dockin-ipam 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/containernetworking/cni v0.7.1 7 | github.com/kr/pretty v0.1.0 // indirect 8 | github.com/onsi/ginkgo v1.8.0 // indirect 9 | github.com/onsi/gomega v1.5.0 // indirect 10 | golang.org/x/net v0.0.0-20190613194153-d28f0bde5980 // indirect 11 | golang.org/x/sync v0.0.0-20190423024810-112230192c58 // indirect 12 | golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f // indirect 13 | golang.org/x/text v0.3.2 // indirect 14 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect 15 | gopkg.in/yaml.v2 v2.2.2 // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /dockin-ipam/go.sum: -------------------------------------------------------------------------------- 1 | github.com/containernetworking/cni v0.7.1 h1:fE3r16wpSEyaqY4Z4oFrLMmIGfBYIKpPrHK31EJ9FzE= 2 | github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= 3 | github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= 4 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 5 | github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= 6 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 7 | github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= 8 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 9 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 10 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 11 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 12 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 13 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 14 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 15 | github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= 16 | github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 17 | github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= 18 | github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 19 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 20 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 21 | golang.org/x/net v0.0.0-20190613194153-d28f0bde5980 h1:dfGZHvZk057jK2MCeWus/TowKpJ8y4AmooUzdBSR9GU= 22 | golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 23 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 24 | golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= 25 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 26 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 27 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 28 | golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f h1:25KHgbfyiSm6vwQLbM3zZIe1v9p/3ea4Rz+nnM5K/i4= 29 | golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 30 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 31 | golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= 32 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 33 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 34 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 35 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= 36 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 37 | gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= 38 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 39 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= 40 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 41 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 42 | gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= 43 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 44 | -------------------------------------------------------------------------------- /dockin-ipam/readme.md: -------------------------------------------------------------------------------- 1 | # static IP address management plugin 2 | 3 | ## Overview 4 | 5 | static IPAM is very simple IPAM plugin that assigns IPv4 and IPv6 addresses statically to container. This will be useful in debugging purpose and in case of assign same IP address in different vlan/vxlan to containers. 6 | 7 | 8 | ## Example configuration 9 | 10 | ``` 11 | { 12 | "ipam": { 13 | "type": "static", 14 | "addresses": [ 15 | { 16 | "address": "192.168.0.1/24", 17 | "gateway": "192.168.0.254" 18 | }, 19 | { 20 | "address": "3ffe:ffff:0:01ff::1/64", 21 | "gateway": "3ffe:ffff:0::1" 22 | } 23 | ], 24 | "routes": [ 25 | { "dst": "0.0.0.0/0" }, 26 | { "dst": "192.168.0.0/16", "gw": "192.168.1.1" }, 27 | { "dst": "3ffe:ffff:0:01ff::1/64" } 28 | ], 29 | "dns": { 30 | "nameservers" : ["8.8.8.8"], 31 | "domain": "example.com", 32 | "search": [ "example.com" ] 33 | } 34 | } 35 | } 36 | ``` 37 | 38 | ## Network configuration reference 39 | 40 | * `type` (string, required): "static" 41 | * `addresses` (array, optional): an array of ip address objects: 42 | * `address` (string, required): CIDR notation IP address. 43 | * `gateway` (string, optional): IP inside of "subnet" to designate as the gateway. 44 | * `routes` (string, optional): list of routes add to the container namespace. Each route is a dictionary with "dst" and optional "gw" fields. If "gw" is omitted, value of "gateway" will be used. 45 | * `dns` (string, optional): the dictionary with "nameservers", "domain" and "search". 46 | 47 | ## Supported arguments 48 | 49 | The following [CNI_ARGS](https://github.com/containernetworking/cni/blob/master/SPEC.md#parameters) are supported: 50 | 51 | * `IP`: request a specific CIDR notation IP addresses, comma separated 52 | * `GATEWAY`: request a specific gateway address 53 | 54 | (example: CNI_ARGS="IP=192.168.1.1/24;GATEWAY=192.168.1.254") 55 | 56 | The plugin also support following [capability argument](https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md). 57 | 58 | * `ips`: Pass IP addresses for CNI interface 59 | 60 | The following [args conventions](https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md#args-in-network-config) are supported: 61 | 62 | * `ips` (array of strings): A list of custom IPs to attempt to allocate, with prefix (e.g. '192.168.1.1/24') 63 | 64 | Notice: If some of above are used at same time, only one will work according to the priorities below 65 | 66 | 1. [capability argument](https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md) 67 | 1. [args conventions](https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md#args-in-network-config) 68 | 1. [CNI_ARGS](https://github.com/containernetworking/cni/blob/master/SPEC.md#parameters) 69 | -------------------------------------------------------------------------------- /docs/images/dockin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeBankFinTech/Dockin-CNI/2665816a0b8ee773189654062846fdcea9596f90/docs/images/dockin.png --------------------------------------------------------------------------------