Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Antrea IPAM for secondary networks managed by Multus #3529

Merged
merged 1 commit into from
Apr 8, 2022

Conversation

jianjuns
Copy link
Contributor

@jianjuns jianjuns commented Mar 28, 2022

Extend Antrea IPAM and Antrea CNI plugin to support IPAM for Pod
secondary networks. A CNI call that specifies a non-Antrea CNI type and
Antrea IPAM type is identified as an IPAM request for a secondary
network. The IPAM configuration of the CNI call should specify the
Antrea IPPool(s) to allocate IPs for the secondary network.
Additionally, Routes and DNS parameters are supported in the IPAM
configuration.

This implementation is for secondary network managed by Multus, not
Antrea native secondary network support. Only a single IPv4 IPPool is
supported as of now.

An example Multus NetworkAttachmentDefinition with Antrea IPAM:

kind: NetworkAttachmentDefinition
metadata:
  name: macvlan-network1
spec:
  config: '{
      "cniVersion": "0.3.0",
      "type": "macvlan",
      "master": "enp0s9",
      "mode": "bridge",
      "ipam": {
        "type": "antrea-ipam",
        "ippool": "macvlan-subnet1"
        "routes": [
          { "dst": "0.0.0.0/0" },
          { "dst": "192.168.0.0/16", "gw": "10.10.5.1" },
          { "dst": "3ffe:ffff:0:01ff::1/64" }
        ],
        "dns": {
          "nameservers" : ["8.8.8.8"],
          "domain": "example.com",
          "search": [ "example.com" ]
        }
      }
    }'

Signed-off-by: Jianjun Shen shenj@vmware.com

@jianjuns jianjuns added area/ipam Issues or PRs related to IP address management (IPAM). area/component/cni Issues or PRs related to the cni component labels Mar 28, 2022
@codecov-commenter
Copy link

codecov-commenter commented Mar 28, 2022

Codecov Report

Merging #3529 (257e52f) into main (03b3f2b) will decrease coverage by 18.29%.
The diff coverage is 20.49%.

❗ Current head 257e52f differs from pull request most recent head 9ba0b1f. Consider uploading reports for the commit 9ba0b1f to get more accurate results

Impacted file tree graph

@@             Coverage Diff             @@
##             main    #3529       +/-   ##
===========================================
- Coverage   64.26%   45.97%   -18.30%     
===========================================
  Files         278      362       +84     
  Lines       27821    51015    +23194     
===========================================
+ Hits        17878    23452     +5574     
- Misses       8045    25352    +17307     
- Partials     1898     2211      +313     
Flag Coverage Δ
e2e-tests 49.24% <20.49%> (?)
integration-tests 38.41% <ø> (?)
kind-e2e-tests ?
unit-tests ?

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
pkg/agent/cniserver/pod_configuration.go 42.77% <0.00%> (-11.05%) ⬇️
pkg/ipam/poolallocator/allocator.go 0.00% <0.00%> (-48.88%) ⬇️
pkg/agent/cniserver/ipam/antrea_ipam.go 6.00% <6.12%> (-76.98%) ⬇️
pkg/agent/cniserver/ipam/antrea_ipam_controller.go 20.54% <22.22%> (-59.46%) ⬇️
pkg/agent/cniserver/server.go 37.57% <31.57%> (-28.20%) ⬇️
pkg/agent/cniserver/ipam/ipam_service.go 44.94% <34.48%> (-7.24%) ⬇️
pkg/controller/ipam/validate.go 22.40% <62.50%> (-57.15%) ⬇️
pkg/agent/cniserver/ipam/ipam_delegator.go 54.54% <100.00%> (+5.70%) ⬆️
pkg/controller/networkpolicy/endpoint_querier.go 4.58% <0.00%> (-86.85%) ⬇️
pkg/agent/util/iptables/lock.go 0.00% <0.00%> (-81.82%) ⬇️
... and 390 more

@jianjuns
Copy link
Contributor Author

/test-flexible-ipam-e2e

@jianjuns jianjuns force-pushed the secnet-ipam branch 2 times, most recently from f6e5b4f to e283c2d Compare March 30, 2022 04:14
@jianjuns jianjuns marked this pull request as ready for review March 30, 2022 06:05
@jianjuns jianjuns requested review from gran-vmv, wenyingd and annakhm and removed request for gran-vmv and wenyingd March 30, 2022 06:05
@jianjuns
Copy link
Contributor Author

/test-e2e
/test-integration

@jianjuns jianjuns force-pushed the secnet-ipam branch 2 times, most recently from 996a1ac to ed94010 Compare April 1, 2022 04:07
"keyA": ["some more", "plugin specific", "configuration"],
"ipam": {
"type": "antrea",
"ippools": [ "test-ippool-ipv4-1" ],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a question, where does this parameter come from?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created the IPPool named "test-ippool-ipv4-1" in this test. Check line 30 - 46.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To clarify this question, I want to ask how this parameter passed in this cniNetworkConfig.
From the PR description, we have a NetworkAttachmentDefinition, and I know some special config will be passed in CNI call, but I think we still need some other configuration to make the whole pipeline work.

Another question: do we want to cover dns/routes support in this PR or in Antrea?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the real usage with Multus, Multus will pass the whole CNI config json in NetworkAttachmentDefinition to the main CNI plugin (e.g. MACVLAN), which then passes the json to the IPAM plugin (just like how Antrea invokes node-ipam plugin). The behavior of the latter part (from main CNI to IPAM CNI) is defined in the CNI spec.

I have not heard about any request to support dns/routes for the primary CNI. Added them for secondary network also for feature parity with Whereabouts.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. Thanks.

if err != nil {
if !errors.IsNotFound(err) {
err = fmt.Errorf("failed to get IPPool %s: %v", p, err)
break
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not return error directly? If not, err would be reset in line 223, and the real error would be lost.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I wanted not to repeat "mineTrue, allocator, ips, reservedOwner, err", as I feel that is harder to track all 4 return values. But if you think return directly is better, I can change to that too.

if !s.enableSecondaryNetworkIPAM {
return s.unsupportedFieldResponse("type", cniConfig.Type)
}
if ipamType != ipam.AntreaIPAMType {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So only AntreaIPAM is the supported IPAM type for Multus secondary network, it also requires CNI type is not "antrea"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. If another IPAM type is required, antrea CNI should not be called; Multus should execute that IPAM CNI.

Today Antrea cannot be secondary CNI with Multus. If later we really allow that, we can revisit the CNI type here can be "antrea" or not.

return nil, resp
}
if !s.isChaining && !cniConfig.secondaryNetworkIPAM {
s.updateLocalIPAMSubnet(cniConfig)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just confirm: if secondaryNetworkIPAM == true, cniConfig.NetworkConfig.IPAM.Ranges is possibly empty. Then that means we forbid to allocate IP from AntreaIPAM to host-local in secondary network case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, as I said this should be for Antrea native IPAM with IPPool only. If users want to use host-local, they should just set IPAM type to "host-local", then antrea CNI will be not called.

return s.ipamFailureResponse(err), nil
}
klog.InfoS("Allocated IP addresses", "container", cniConfig.ContainerId, "result", ipamResult)
return resultToResponse(ipamResult), nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So Antrea only allocates IP in this scenario? Since no OVS port or memory interfaceConfig created, other features in Antrea would not know this second IP. Besides, who will configure IP address inside the container? If we assume another CNI plugin processes it, does it mean kubelet should send request to both two CNI plugins (antrea and the other plugin) at the same time?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, Antrea is only doing IPAM - as it is configured as IPAM plugin, not the CNI plugin in CNI NetworkConfiguration.

Typically, antrea CNI is executed by the CNI plugin specified in "Type" (just like Antrea agent executes host-local plugin).

pkg/agent/cniserver/ipam/antrea_ipam_controller.go Outdated Show resolved Hide resolved
cmd/antrea-agent/agent.go Outdated Show resolved Hide resolved
}

func (s *CNIServer) ipamCheck(cniConfig *CNIConfig) (*cnipb.CniCmdResponse, error) {
if err := ipam.SecondaryNetworkCheck(cniConfig.CniCmdArgs, cniConfig.K8sArgs, cniConfig.NetworkConfig); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since ipam.SecondaryNetworkCheck always returns error, line 415 won't execute.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but I hope to keep the ipamCheck() complete and independent of the SecondaryNetworkCheck() implementation. I added some comments to explain this.

var ips []net.IP
var reservedOwner *crdv1a2.IPAddressOwner
pod, err := c.podLister.Pods(namespace).Get(name)
if err != nil {
// For CNI DEL case, getting Pod may fail. Try to get information from allocated IPs of all IPPools.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic is removed in the new code, is it possible to lead to IP leak in CNI DEL event because IPPool fails to get as Pod is removed?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checked Jianjun's change, I think it will use a new function to check ipPool when CNIDel, thus this is OK.
func (d *AntreaIPAM) del(podOwner *crdv1a2.PodOwner) (foundAllocation bool, err error)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I changed the code to always look up IPPools by Pod. I think it might be possible a pool status update is not received by agent yet when CNI DEL comes, and so we might not be able to release the allocated IP (@gran-vmv : do you agree?). But this can happen even with the existing code.

I made change more for secondary network and primary network to share the same DEL code. Also, I feel in this way the code for ADD is also simpler.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jianjuns I think your method should work, but not sure if the cost for searching PodOwner in IPPools for all PodDel is acceptable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But the cache is indexed by Pod name (+ Namespace)? Beside code sharing, I also feel this approach is safer - it can cover Pod annotation or CNI config change (for secondary network).

@gran-vmv gran-vmv self-requested a review April 7, 2022 14:22
gran-vmv
gran-vmv previously approved these changes Apr 7, 2022
Copy link
Contributor

@gran-vmv gran-vmv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Do we need to add milestone for this PR?
We also need to inform user the difference between enableAntreaIPAM and enableAntreaIPAM+enableBridgeMode.

@jianjuns jianjuns added this to the Antrea v1.7 release milestone Apr 7, 2022
@jianjuns
Copy link
Contributor Author

jianjuns commented Apr 7, 2022

Do we need to add milestone for this PR? We also need to inform user the difference between enableAntreaIPAM and enableAntreaIPAM+enableBridgeMode.

Sure. I added the milestone for 1.7.

I am also working on the documentation for secondary network IPAM, in which I will make it clear AntreaIPAM feature gate is needed by both secondary network IPAM and bridging mode. However, I plan to create the documentation PR, after an enhancement of support IPv6/dual stack, after merging this PR.

@jianjuns
Copy link
Contributor Author

jianjuns commented Apr 7, 2022

/test-e2e

Extend Antrea IPAM and Antrea CNI plugin to support IPAM for Pod
secondary networks. A CNI call that specifies a non-Antrea CNI type and
Antrea IPAM type is identified as an IPAM request for a secondary
network. The IPAM configuration of the CNI call should specify the
Antrea IPPool(s) to allocate IPs for the secondary network.
Additionally, Routes and DNS parameters are supported in the IPAM
configuration.

This implementation is for secondary network managed by Multus, not
Antrea native secondary network support. Only a single IPv4 IPPool is
supported as of now.

An example Multus NetworkAttachmentDefinition with Antrea IPAM:

kind: NetworkAttachmentDefinition
metadata:
  name: macvlan-network1
spec:
  config: '{
      "cniVersion": "0.3.0",
      "type": "macvlan",
      "master": "enp0s9",
      "mode": "bridge",
      "ipam": {
        "type": "antrea-ipam",
        "ippool": "macvlan-subnet1"
        "routes": [
          { "dst": "0.0.0.0/0" },
          { "dst": "192.168.0.0/16", "gw": "10.10.5.1" },
          { "dst": "3ffe:ffff:0:01ff::1/64" }
        ],
        "dns": {
          "nameservers" : ["8.8.8.8"],
          "domain": "example.com",
          "search": [ "example.com" ]
        }
      }
    }'

Signed-off-by: Jianjun Shen <shenj@vmware.com>
wenyingd
wenyingd previously approved these changes Apr 8, 2022
Copy link
Contributor

@wenyingd wenyingd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jianjuns
Copy link
Contributor Author

jianjuns commented Apr 8, 2022

/test-all
/test-flexible-ipam-e2e

@jianjuns
Copy link
Contributor Author

jianjuns commented Apr 8, 2022

@wenyingd @gran-vmv : could I have another approval? I made a small change to add "sudo" to execute Antrea CNI via SSH, as it requires root permission to connect to the CNI socket.

I meant in e2e test TestSecondaryNetworkIPAM().

@gran-vmv gran-vmv self-requested a review April 8, 2022 01:16
Copy link
Contributor

@wenyingd wenyingd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jianjuns jianjuns merged commit 7fea8d3 into antrea-io:main Apr 8, 2022
err = allocator.ReleaseContainerIfPresent(owner.Pod.ContainerID)
return true, err
// If no allocation found, pass CNI DEL to the next driver.
return foundAllocation, nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here if allocation was not found (due to duplicate del, for example) we might be passing irrelevant request to next driver. I see no functional harm in it but it might be confusing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. But we have no way to know we indeed should pass to the next driver or not right? @gran-vmv: as you implemented the behavior, you might comment have you verified any issue if the next driver (host-local) does not handle the allocation? I assume it will just silently return no error.

But maybe we can add more comments here to explain the situation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous implementation was more robust since it mainly relied on annotation rather than pool status. But I tend to think that code simplicity that resulted from your refactoring is worth this cost.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But on the another aspect - it is not safe to rely on the Pod annotation either as it can be changed. And even the previous implementation can still get the same when the Pod resource is already deleted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/component/cni Issues or PRs related to the cni component area/ipam Issues or PRs related to IP address management (IPAM).
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants