forked from openstack/kuryr-kubernetes
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add MACVLAN based interfaces for nested containers
Currently nested containers can only be run by using trunk support and vlan based interfaces. This patch introduces the additional option of MACVLAN slave interfaces for pods running in VMs. This patch includes both a new VIF driver on the controller side and the binding driver for the CNI plugin. Implements: blueprint macvlan-pod-in-vm Depends-On: Ib71204d2d14d3d4f15beada701094e37d89d7801 Co-Authored-By: Marco Chiappero <[email protected]> Change-Id: I03c536bb0057bba0a5eb4d1c135baa8ab625e400
- Loading branch information
Showing
13 changed files
with
825 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -57,8 +57,8 @@ vif binding executables. For example, if you installed it on Debian or Ubuntu:: | |
bindir = /usr/local/libexec/kuryr | ||
|
||
|
||
How to try out nested-pods locally | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
How to try out nested-pods locally (VLAN + trunk) | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
Following are the instructions for an all-in-one setup where K8s will also be | ||
running inside the same Nova VM in which Kuryr-controller and Kuryr-cni will be | ||
|
@@ -110,6 +110,52 @@ running. 4GB memory and 2 vCPUs, is the minimum resource requirement for the VM: | |
|
||
Now launch pods using kubectl, Undercloud Neutron will serve the networking. | ||
|
||
How to try out nested-pods locally (MACVLAN) | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
Following are the instructions for an all-in-one setup, as above, but using the | ||
nested MACVLAN driver rather than VLAN and trunk ports. | ||
|
||
1. To install OpenStack services run devstack with ``devstack/local.conf.pod-in-vm.undercloud.sample``. | ||
2. Launch a Nova VM with MACVLAN support | ||
3. Log into the VM and set up Kubernetes along with Kuryr using devstack: | ||
- Since undercloud Neutron will be used by pods, Neutron services should be | ||
disabled in localrc. | ||
- Run devstack with ``devstack/local.conf.pod-in-vm.overcloud.sample``. | ||
With this config devstack will not configure Neutron resources for the | ||
local cloud. These variables have to be added manually | ||
to ``/etc/kuryr/kuryr.conf``. | ||
|
||
4. Once devstack is done and all services are up inside VM: | ||
- Configure ``/etc/kuryr/kuryr.conf`` with the following content, replacing | ||
the values with correct UUIDs of Neutron resources from the undercloud:: | ||
|
||
[neutron_defaults] | ||
pod_security_groups = <UNDERCLOUD_DEFAULT_SG_UUID> | ||
pod_subnet = <UNDERCLOUD_SUBNET_FOR_PODS_UUID> | ||
project = <UNDERCLOUD_DEFAULT_PROJECT_UUID> | ||
service_subnet = <UNDERCLOUD_SUBNET_FOR_SERVICES_UUID> | ||
|
||
- Configure worker VMs subnet:: | ||
|
||
[pod_vif_nested] | ||
worker_nodes_subnet = <UNDERCLOUD_SUBNET_WORKER_NODES_UUID> | ||
|
||
- Configure “pod_vif_driver” as “nested-macvlan”:: | ||
|
||
[kubernetes] | ||
pod_vif_driver = nested-macvlan | ||
|
||
- Configure binding section:: | ||
|
||
[binding] | ||
link_iface = <VM interface name eg. eth0> | ||
|
||
- Restart kuryr-k8s-controller:: | ||
|
||
sudo systemctl restart [email protected] | ||
|
||
Now launch pods using kubectl, Undercloud Neutron will serve the networking. | ||
|
||
How to watch K8S api-server over HTTPS | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
145 changes: 145 additions & 0 deletions
145
kuryr_kubernetes/controller/drivers/nested_macvlan_vif.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
# All Rights Reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); you may | ||
# not use this file except in compliance with the License. You may obtain | ||
# a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
# License for the specific language governing permissions and limitations | ||
# under the License. | ||
|
||
import threading | ||
|
||
from neutronclient.common import exceptions as n_exc | ||
from oslo_log import log as logging | ||
|
||
from kuryr_kubernetes import clients | ||
from kuryr_kubernetes.controller.drivers import nested_vif | ||
from kuryr_kubernetes import exceptions as k_exc | ||
from kuryr_kubernetes import os_vif_util as ovu | ||
|
||
LOG = logging.getLogger(__name__) | ||
|
||
|
||
class NestedMacvlanPodVIFDriver(nested_vif.NestedPodVIFDriver): | ||
"""Manages ports for nested-containers using MACVLAN to provide VIFs.""" | ||
|
||
def __init__(self): | ||
self.lock = threading.Lock() | ||
|
||
def request_vif(self, pod, project_id, subnets, security_groups): | ||
neutron = clients.get_neutron_client() | ||
req = self._get_port_request(pod, project_id, subnets, | ||
security_groups) | ||
container_port = neutron.create_port(req).get('port') | ||
|
||
container_mac = container_port['mac_address'] | ||
container_ips = frozenset(entry['ip_address'] for entry in | ||
container_port['fixed_ips']) | ||
|
||
with self.lock: | ||
self.lock.acquire() | ||
vm_port = self._get_parent_port(neutron, pod) | ||
self._add_to_allowed_address_pairs(neutron, vm_port, | ||
container_ips, container_mac) | ||
|
||
return ovu.neutron_to_osvif_vif_nested_macvlan(container_port, subnets) | ||
|
||
def request_vifs(self, pod, project_id, subnets, security_groups, | ||
num_ports): | ||
# TODO(mchiappe): provide an implementation | ||
raise NotImplementedError() | ||
|
||
def release_vif(self, pod, vif): | ||
neutron = clients.get_neutron_client() | ||
container_port = neutron.show_port(vif.id).get('port') | ||
|
||
container_mac = container_port['mac_address'] | ||
container_ips = frozenset(entry['ip_address'] for entry in | ||
container_port['fixed_ips']) | ||
|
||
with self.lock: | ||
self.lock.acquire() | ||
vm_port = self._get_parent_port(neutron, pod) | ||
self._remove_from_allowed_address_pairs(neutron, vm_port, | ||
container_ips, container_mac) | ||
|
||
try: | ||
neutron.delete_port(vif.id) | ||
except n_exc.PortNotFoundClient: | ||
LOG.warning("Unable to release port %s as it no longer exists.", | ||
vif.id) | ||
|
||
def activate_vif(self, pod, vif): | ||
# NOTE(mchiappe): there is no way to get feedback on the actual | ||
# interface creation or activation as no plugging can happen for this | ||
# interface type. However the status of the port is not relevant as | ||
# it is used for IPAM purposes only, thus just set 'active' | ||
# immediately to let the CNI driver make progress. | ||
vif.active = True | ||
|
||
def _add_to_allowed_address_pairs(self, neutron, port, ip_addresses, | ||
mac_address=None): | ||
if not ip_addresses: | ||
raise k_exc.IntegrityError("Cannot add pair from the " | ||
"allowed_address_pairs of port %s: missing IP address", | ||
port['id']) | ||
|
||
mac = mac_address if mac_address else port['mac_address'] | ||
address_pairs = port['allowed_address_pairs'] | ||
|
||
# look for duplicates or near-matches | ||
for pair in address_pairs: | ||
if pair['ip_address'] in ip_addresses: | ||
if pair['mac_address'] is mac: | ||
raise k_exc.AllowedAddressAlreadyPresent("Pair %s already " | ||
"present in the 'allowed_address_pair' list. This is " | ||
"due to a misconfiguration or a bug", pair) | ||
else: | ||
LOG.warning("A pair with IP %s but different MAC address " | ||
"is already present in the 'allowed_address_pair'. " | ||
"This could indicate a misconfiguration or a " | ||
"bug", pair['ip_address']) | ||
|
||
for ip in ip_addresses: | ||
address_pairs.append({'ip_address': ip, 'mac_address': mac}) | ||
|
||
self._update_port_address_pairs(neutron, port['id'], address_pairs) | ||
|
||
def _remove_from_allowed_address_pairs(self, neutron, port, ip_addresses, | ||
mac_address=None): | ||
if not ip_addresses: | ||
raise k_exc.IntegrityError("Cannot remove pair from the " | ||
"allowed_address_pairs of port %s: missing IP address", | ||
port['id']) | ||
|
||
mac = mac_address if mac_address else port['mac_address'] | ||
address_pairs = port['allowed_address_pairs'] | ||
updated = False | ||
|
||
for ip in ip_addresses: | ||
try: | ||
address_pairs.remove({'ip_address': ip, 'mac_address': mac}) | ||
updated = True | ||
except ValueError: | ||
LOG.error("No {'ip_address': %s, 'mac_address': %s} pair " | ||
"found in the 'allowed_address_pair' list while " | ||
"trying to remove it.", ip, mac) | ||
|
||
if updated: | ||
self._update_port_address_pairs(neutron, port['id'], address_pairs) | ||
|
||
def _update_port_address_pairs(self, neutron, port_id, address_pairs): | ||
try: | ||
neutron.update_port( | ||
port_id, | ||
{'port': {'allowed_address_pairs': address_pairs}} | ||
) | ||
except n_exc.NeutronClientException as ex: | ||
LOG.error("Error happened during updating Neutron " | ||
"port %s: %s", port_id, ex) | ||
raise ex |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.