Browse Source

Support octavia-ingress-controller

- Add "octavia" as one of the "ingress_controller" options.
- Add label "octavia_ingress_controller_tag".
- Use external network ID in the heat templates.

Story: 2004838
Change-Id: I7d889a054cd5feb2eeef523b20607a6c7630d777
changes/30/631330/7
Lingxian Kong 3 years ago
parent
commit
a941822c8e
  1. 14
      doc/source/user/index.rst
  2. 22
      magnum/common/neutron.py
  3. 19
      magnum/drivers/common/templates/kubernetes/fragments/enable-ingress-controller.sh
  4. 122
      magnum/drivers/common/templates/kubernetes/fragments/enable-ingress-octavia.sh
  5. 2
      magnum/drivers/common/templates/kubernetes/fragments/write-heat-params-master.yaml
  6. 1
      magnum/drivers/common/templates/kubernetes/fragments/write-kube-os-config.sh
  7. 25
      magnum/drivers/heat/k8s_template_def.py
  8. 10
      magnum/drivers/k8s_fedora_atomic_v1/templates/kubecluster.yaml
  9. 8
      magnum/drivers/k8s_fedora_atomic_v1/templates/kubemaster.yaml
  10. 81
      magnum/tests/unit/common/test_neutron.py
  11. 20
      magnum/tests/unit/conductor/handlers/test_k8s_cluster_conductor.py
  12. 180
      magnum/tests/unit/drivers/test_template_definition.py
  13. 8
      releasenotes/notes/k8s-octavia-ingress-controller-32c0b97031fd0dd4.yaml

14
doc/source/user/index.rst

@ -347,6 +347,8 @@ the table are linked to more details elsewhere in the user guide.
+---------------------------------------+--------------------+---------------+
| `ingress_controller_role`_ | see below | "ingress" |
+---------------------------------------+--------------------+---------------+
| `octavia_ingress_controller_tag`_ | see below | see below |
+---------------------------------------+--------------------+---------------+
| `kubelet_options`_ | extra kubelet args | "" |
+---------------------------------------+--------------------+---------------+
| `kubeapi_options`_ | extra kubeapi args | "" |
@ -1235,8 +1237,11 @@ Magnum allows selecting one of multiple controller options via the
your own Ingress resources.
_`ingress_controller`
This label sets the Ingress Controller to be used. Currently only traefik
is supported. The default is '', meaning no Ingress Controller configured.
This label sets the Ingress Controller to be used. Currently 'traefik' and
'octavia' are supported. The default is '', meaning no Ingress Controller
configured. For more details about octavia-ingress-controller please refer
to `cloud-provider-openstack document
<https://github.com/kubernetes/cloud-provider-openstack/blob/master/docs/using-octavia-ingress-controller.md>`_
_`ingress_controller_role`
This label defines the role nodes should have to run an instance of the
@ -1247,6 +1252,11 @@ _`ingress_controller_role`
kubectl label node <node-name> role=ingress
This lable is not used for octavia-ingress-controller.
_`octavia_ingress_controller_tag`
The image tag for octavia-ingress-controller. Stain-default: 1.13.2-alpha
DNS
---

22
magnum/common/neutron.py

@ -53,3 +53,25 @@ def delete_floatingip(context, fix_port_id, cluster):
except Exception as e:
raise exception.PreDeletionFailed(cluster_uuid=cluster.uuid,
msg=str(e))
def get_network_id(context, network_name):
nets = []
n_client = clients.OpenStackClients(context).neutron()
ext_filter = {'router:external': True}
networks = n_client.list_networks(**ext_filter)
for net in networks.get('networks'):
if net.get('name') == network_name:
nets.append(net)
if len(nets) == 0:
raise exception.ExternalNetworkNotFound(network=network_name)
if len(nets) > 1:
raise exception.Conflict(
"Multiple networks exist with same name '%s'. Please use the "
"network ID instead." % network_name
)
return nets[0]["id"]

19
magnum/drivers/common/templates/kubernetes/fragments/enable-ingress-controller.sh

@ -3,9 +3,6 @@
step="enable-ingress-controller"
printf "Starting to run ${step}\n"
# Enables the specified ingress controller.
#
# Currently there is only support for traefik.
. /etc/sysconfig/heat-params
function writeFile {
@ -21,8 +18,20 @@ EOF
}
}
if [ "$(echo $INGRESS_CONTROLLER | tr '[:upper:]' '[:lower:]')" = "traefik" ]; then
ingress_controller=$(echo $INGRESS_CONTROLLER | tr '[:upper:]' '[:lower:]')
case "$ingress_controller" in
"")
echo "No ingress controller configured."
;;
"traefik")
$enable-ingress-traefik
fi
;;
"octavia")
$enable-ingress-octavia
;;
*)
echo "Ingress controller $ingress_controller not supported."
;;
esac
printf "Finished running ${step}\n"

122
magnum/drivers/common/templates/kubernetes/fragments/enable-ingress-octavia.sh

@ -0,0 +1,122 @@
# octavia-ingress-controller RBAC
OCTAVIA_INGRESS_CONTROLLER_RBAC=/srv/magnum/kubernetes/manifests/octavia-ingress-controller-rbac.yaml
OCTAVIA_INGRESS_CONTROLLER_RBAC_CONTENT=$(cat <<EOF
---
kind: ServiceAccount
apiVersion: v1
metadata:
name: octavia-ingress-controller
namespace: kube-system
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: octavia-ingress-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: octavia-ingress-controller
namespace: kube-system
EOF
)
writeFile $OCTAVIA_INGRESS_CONTROLLER_RBAC "$OCTAVIA_INGRESS_CONTROLLER_RBAC_CONTENT"
# octavia-ingress-controller config file
OCTAVIA_INGRESS_CONTROLLER_CONFIGMAP=/srv/magnum/kubernetes/manifests/octavia-ingress-controller-config.yaml
OCTAVIA_INGRESS_CONTROLLER_CONFIGMAP_CONTENT=$(cat <<EOF
---
kind: ConfigMap
apiVersion: v1
metadata:
name: octavia-ingress-controller-config
namespace: kube-system
data:
config: |
cluster_name: ${CLUSTER_UUID}
openstack:
auth_url: ${AUTH_URL}
user_id: ${TRUSTEE_USER_ID}
password: ${TRUSTEE_PASSWORD}
trust_id: ${TRUST_ID}
region: ${REGION_NAME}
ca_file: /etc/kubernetes/ca-bundle.crt
octavia:
subnet_id: ${CLUSTER_SUBNET}
floating_network_id: ${EXTERNAL_NETWORK_ID}
EOF
)
writeFile $OCTAVIA_INGRESS_CONTROLLER_CONFIGMAP "$OCTAVIA_INGRESS_CONTROLLER_CONFIGMAP_CONTENT"
# octavia-ingress-controller deployment
oic_image="${CONTAINER_INFRA_PREFIX:-docker.io/k8scloudprovider/}octavia-ingress-controller:${OCTAVIA_INGRESS_CONTROLLER_TAG}"
OCTAVIA_INGRESS_CONTROLLER=/srv/magnum/kubernetes/manifests/octavia-ingress-controller.yaml
OCTAVIA_INGRESS_CONTROLLER_CONTENT=$(cat <<EOF
---
kind: StatefulSet
apiVersion: apps/v1
metadata:
name: octavia-ingress-controller
namespace: kube-system
labels:
k8s-app: octavia-ingress-controller
spec:
replicas: 1
selector:
matchLabels:
k8s-app: octavia-ingress-controller
template:
metadata:
labels:
k8s-app: octavia-ingress-controller
spec:
serviceAccountName: octavia-ingress-controller
tolerations:
- effect: NoSchedule # Make sure the pod can be scheduled on master kubelet.
operator: Exists
- key: CriticalAddonsOnly # Mark the pod as a critical add-on for rescheduling.
operator: Exists
- effect: NoExecute
operator: Exists
nodeSelector:
node-role.kubernetes.io/master: "" # octavia-ingress-controller needs to access /etc/kubernetes folder.
containers:
- name: octavia-ingress-controller
image: ${oic_image}
imagePullPolicy: IfNotPresent
args:
- /bin/octavia-ingress-controller
- --config=/etc/config/octavia-ingress-controller-config.yaml
volumeMounts:
- mountPath: /etc/kubernetes
name: kubernetes-config
readOnly: true
- name: ingress-config
mountPath: /etc/config
hostNetwork: true
volumes:
- name: kubernetes-config
hostPath:
path: /etc/kubernetes
type: Directory
- name: ingress-config
configMap:
name: octavia-ingress-controller-config
items:
- key: config
path: octavia-ingress-controller-config.yaml
EOF
)
writeFile $OCTAVIA_INGRESS_CONTROLLER "$OCTAVIA_INGRESS_CONTROLLER_CONTENT"
echo "Waiting for Kubernetes API..."
until [ "ok" = "$(curl --silent http://127.0.0.1:8080/healthz)" ]
do
sleep 5
done
kubectl apply --validate=false -f $OCTAVIA_INGRESS_CONTROLLER_RBAC
kubectl apply --validate=false -f $OCTAVIA_INGRESS_CONTROLLER_CONFIGMAP
kubectl apply --validate=false -f $OCTAVIA_INGRESS_CONTROLLER

2
magnum/drivers/common/templates/kubernetes/fragments/write-heat-params-master.yaml

@ -67,6 +67,7 @@ write_files:
CALICO_IPV4POOL="$CALICO_IPV4POOL"
INGRESS_CONTROLLER="$INGRESS_CONTROLLER"
INGRESS_CONTROLLER_ROLE="$INGRESS_CONTROLLER_ROLE"
OCTAVIA_INGRESS_CONTROLLER_TAG="$OCTAVIA_INGRESS_CONTROLLER_TAG"
KUBELET_OPTIONS="$KUBELET_OPTIONS"
KUBECONTROLLER_OPTIONS="$KUBECONTROLLER_OPTIONS"
KUBEAPI_OPTIONS="$KUBEAPI_OPTIONS"
@ -81,3 +82,4 @@ write_files:
KEYSTONE_AUTH_ENABLED="$KEYSTONE_AUTH_ENABLED"
K8S_KEYSTONE_AUTH_TAG="$K8S_KEYSTONE_AUTH_TAG"
PROJECT_ID="$PROJECT_ID"
EXTERNAL_NETWORK_ID="$EXTERNAL_NETWORK_ID"

1
magnum/drivers/common/templates/kubernetes/fragments/write-kube-os-config.sh

@ -23,6 +23,7 @@ ca-file=/etc/kubernetes/ca-bundle.crt
[LoadBalancer]
use-octavia=$OCTAVIA_ENABLED
subnet-id=$CLUSTER_SUBNET
floating-network-id=$EXTERNAL_NETWORK_ID
create-monitor=yes
monitor-delay=1m
monitor-timeout=30s

25
magnum/drivers/heat/k8s_template_def.py

@ -11,8 +11,11 @@
# under the License.
from oslo_config import cfg
from oslo_utils import uuidutils
from magnum.common import exception
from magnum.common import keystone
from magnum.common import neutron
from magnum.drivers.heat import template_def
CONF = cfg.CONF
@ -104,6 +107,17 @@ class K8sTemplateDefinition(template_def.BaseTemplateDefinition):
extra_params['octavia_enabled'] = keystone.is_octavia_enabled()
# NOTE(lxkong): Convert external network name to UUID, the template
# field name is confused. If external_network_id is not specified in
# cluster template use 'public' as the default value, which is the same
# with the heat template default value as before.
ext_net = cluster_template.external_network_id or "public"
if not uuidutils.is_uuid_like(ext_net):
ext_net_id = neutron.get_network_id(context, ext_net)
extra_params['external_network'] = ext_net_id
else:
extra_params['external_network'] = ext_net
label_list = ['flannel_network_cidr', 'flannel_backend',
'flannel_network_subnetlen',
'system_pods_initial_delay',
@ -114,8 +128,8 @@ class K8sTemplateDefinition(template_def.BaseTemplateDefinition):
'kube_dashboard_enabled',
'etcd_volume_size',
'cert_manager_api',
'ingress_controller',
'ingress_controller_role',
'octavia_ingress_controller_tag',
'kubelet_options',
'kubeapi_options',
'kubeproxy_options',
@ -126,6 +140,15 @@ class K8sTemplateDefinition(template_def.BaseTemplateDefinition):
for label in label_list:
extra_params[label] = cluster.labels.get(label)
ingress_controller = cluster.labels.get('ingress_controller',
'').lower()
if (ingress_controller == 'octavia'
and not extra_params['octavia_enabled']):
raise exception.InvalidParameterValue(
'Octavia service needs to be deployed for octavia ingress '
'controller.')
extra_params["ingress_controller"] = ingress_controller
cluser_ip_range = cluster.labels.get('service_cluster_ip_range')
if cluser_ip_range:
extra_params['portal_network_cidr'] = cluser_ip_range

10
magnum/drivers/k8s_fedora_atomic_v1/templates/kubecluster.yaml

@ -14,8 +14,7 @@ parameters:
external_network:
type: string
description: uuid/name of a network to use for floating ip addresses
default: public
description: uuid of a network to use for floating ip addresses
fixed_network:
type: string
@ -454,6 +453,11 @@ parameters:
node role where the ingress controller backend should run
default: "ingress"
octavia_ingress_controller_tag:
type: string
description: Octavia ingress controller docker image tag.
default: "1.13.2-alpha"
kubelet_options:
type: string
description: >
@ -754,6 +758,7 @@ resources:
pods_network_cidr: {get_param: pods_network_cidr}
ingress_controller: {get_param: ingress_controller}
ingress_controller_role: {get_param: ingress_controller_role}
octavia_ingress_controller_tag: {get_param: octavia_ingress_controller_tag}
kubelet_options: {get_param: kubelet_options}
kubeapi_options: {get_param: kubeapi_options}
kubeproxy_options: {get_param: kubeproxy_options}
@ -791,6 +796,7 @@ resources:
- str_replace:
params:
$enable-ingress-traefik: {get_file: ../../common/templates/kubernetes/fragments/enable-ingress-traefik.sh}
$enable-ingress-octavia: {get_file: ../../common/templates/kubernetes/fragments/enable-ingress-octavia.sh}
template: {get_file: ../../common/templates/kubernetes/fragments/enable-ingress-controller.sh}
- get_file: ../../common/templates/kubernetes/fragments/kube-dashboard-service.sh
- get_file: ../../common/templates/kubernetes/fragments/enable-keystone-auth.sh

8
magnum/drivers/k8s_fedora_atomic_v1/templates/kubemaster.yaml

@ -25,7 +25,7 @@ parameters:
external_network:
type: string
description: uuid/name of a network to use for floating ip addresses
description: uuid of a network to use for floating ip addresses
portal_network_cidr:
type: string
@ -341,6 +341,10 @@ parameters:
description: >
node role where the ingress controller should run
octavia_ingress_controller_tag:
type: string
description: Octavia ingress controller docker image tag.
kubelet_options:
type: string
description: >
@ -504,6 +508,7 @@ resources:
"$CALICO_IPV4POOL": {get_param: calico_ipv4pool}
"$INGRESS_CONTROLLER": {get_param: ingress_controller}
"$INGRESS_CONTROLLER_ROLE": {get_param: ingress_controller_role}
"$OCTAVIA_INGRESS_CONTROLLER_TAG": {get_param: octavia_ingress_controller_tag}
"$KUBELET_OPTIONS": {get_param: kubelet_options}
"$KUBEAPI_OPTIONS": {get_param: kubeapi_options}
"$KUBECONTROLLER_OPTIONS": {get_param: kubecontroller_options}
@ -518,6 +523,7 @@ resources:
"$KEYSTONE_AUTH_ENABLED": {get_param: keystone_auth_enabled}
"$K8S_KEYSTONE_AUTH_TAG": {get_param: k8s_keystone_auth_tag}
"$PROJECT_ID": {get_param: project_id}
"$EXTERNAL_NETWORK_ID": {get_param: external_network}
install_openstack_ca:
type: OS::Heat::SoftwareConfig

81
magnum/tests/unit/common/test_neutron.py

@ -136,3 +136,84 @@ class NeutronTest(base.TestCase):
fake_port_id,
self.cluster
)
@mock.patch('magnum.common.clients.OpenStackClients')
def test_get_network_id(self, mock_clients):
fake_name = "fake_network"
fake_id = "24fe5da0-1ac0-11e9-84cd-00224d6b7bc1"
mock_nclient = mock.MagicMock()
mock_nclient.list_networks.return_value = {
'networks': [
{
'id': fake_id,
'name': fake_name,
'router:external': True
}
]
}
osc = mock.MagicMock()
mock_clients.return_value = osc
osc.neutron.return_value = mock_nclient
network_id = neutron.get_network_id(self.context, fake_name)
self.assertEqual(fake_id, network_id)
@mock.patch('magnum.common.clients.OpenStackClients')
def test_get_network_id_notfound(self, mock_clients):
fake_name = "fake_network"
fake_id = "24fe5da0-1ac0-11e9-84cd-00224d6b7bc1"
mock_nclient = mock.MagicMock()
mock_nclient.list_networks.return_value = {
'networks': [
{
'id': fake_id,
'name': fake_name,
'router:external': True
}
]
}
osc = mock.MagicMock()
mock_clients.return_value = osc
osc.neutron.return_value = mock_nclient
self.assertRaises(
exception.ExternalNetworkNotFound,
neutron.get_network_id,
self.context,
"another_network"
)
@mock.patch('magnum.common.clients.OpenStackClients')
def test_get_network_id_conflict(self, mock_clients):
fake_name = "fake_network"
fake_id_1 = "24fe5da0-1ac0-11e9-84cd-00224d6b7bc1"
fake_id_2 = "93781f82-1ac0-11e9-84cd-00224d6b7bc1"
mock_nclient = mock.MagicMock()
mock_nclient.list_networks.return_value = {
'networks': [
{
'id': fake_id_1,
'name': fake_name,
'router:external': True
},
{
'id': fake_id_2,
'name': fake_name,
'router:external': True
}
]
}
osc = mock.MagicMock()
mock_clients.return_value = osc
osc.neutron.return_value = mock_nclient
self.assertRaises(
exception.Conflict,
neutron.get_network_id,
self.context,
fake_name
)

20
magnum/tests/unit/conductor/handlers/test_k8s_cluster_conductor.py

@ -33,7 +33,7 @@ class TestClusterConductorWithK8s(base.TestCase):
'master_flavor_id': 'master_flavor_id',
'keypair_id': 'keypair_id',
'dns_nameserver': 'dns_nameserver',
'external_network_id': 'external_network_id',
'external_network_id': 'e2a6c8b0-a3c2-42a3-b3f4-01400a30896e',
'fixed_network': 'fixed_network',
'fixed_subnet': 'fixed_subnet',
'network_driver': 'network_driver',
@ -232,7 +232,7 @@ class TestClusterConductorWithK8s(base.TestCase):
}
expected = {
'ssh_key_name': 'keypair_id',
'external_network': 'external_network_id',
'external_network': 'e2a6c8b0-a3c2-42a3-b3f4-01400a30896e',
'fixed_network': 'fixed_network',
'fixed_subnet': 'fixed_subnet',
'network_driver': 'network_driver',
@ -282,6 +282,7 @@ class TestClusterConductorWithK8s(base.TestCase):
'cert_manager_api': 'False',
'ingress_controller': 'i-controller',
'ingress_controller_role': 'i-controller-role',
'octavia_ingress_controller_tag': None,
'kubelet_options': '--kubelet',
'kubeapi_options': '--kubeapi',
'kubecontroller_options': '--kubecontroller',
@ -358,7 +359,7 @@ class TestClusterConductorWithK8s(base.TestCase):
'docker_volume_size': 20,
'docker_volume_type': 'lvmdriver-1',
'etcd_volume_size': None,
'external_network': 'external_network_id',
'external_network': 'e2a6c8b0-a3c2-42a3-b3f4-01400a30896e',
'fixed_network': 'fixed_network',
'fixed_subnet': 'fixed_subnet',
'flannel_backend': 'vxlan',
@ -403,6 +404,7 @@ class TestClusterConductorWithK8s(base.TestCase):
'cert_manager_api': 'False',
'ingress_controller': 'i-controller',
'ingress_controller_role': 'i-controller-role',
'octavia_ingress_controller_tag': None,
'kubelet_options': '--kubelet',
'kubeapi_options': '--kubeapi',
'kubecontroller_options': '--kubecontroller',
@ -476,7 +478,7 @@ class TestClusterConductorWithK8s(base.TestCase):
'docker_volume_size': 20,
'master_flavor': 'master_flavor_id',
'minion_flavor': 'flavor_id',
'external_network': 'external_network_id',
'external_network': 'e2a6c8b0-a3c2-42a3-b3f4-01400a30896e',
'flannel_backend': 'vxlan',
'flannel_network_cidr': '10.101.0.0/16',
'flannel_network_subnetlen': '26',
@ -511,6 +513,7 @@ class TestClusterConductorWithK8s(base.TestCase):
'cert_manager_api': 'False',
'ingress_controller': 'i-controller',
'ingress_controller_role': 'i-controller-role',
'octavia_ingress_controller_tag': None,
'kubelet_options': '--kubelet',
'kubeapi_options': '--kubeapi',
'kubecontroller_options': '--kubecontroller',
@ -561,7 +564,7 @@ class TestClusterConductorWithK8s(base.TestCase):
expected = {
'ssh_key_name': 'keypair_id',
'external_network': 'external_network_id',
'external_network': 'e2a6c8b0-a3c2-42a3-b3f4-01400a30896e',
'fixed_network': 'fixed_network',
'fixed_subnet': 'fixed_subnet',
'availability_zone': 'az_1',
@ -612,6 +615,7 @@ class TestClusterConductorWithK8s(base.TestCase):
'cert_manager_api': 'False',
'ingress_controller': 'i-controller',
'ingress_controller_role': 'i-controller-role',
'octavia_ingress_controller_tag': None,
'kubelet_options': '--kubelet',
'kubeapi_options': '--kubeapi',
'kubecontroller_options': '--kubecontroller',
@ -657,7 +661,7 @@ class TestClusterConductorWithK8s(base.TestCase):
expected = {
'ssh_key_name': 'keypair_id',
'availability_zone': 'az_1',
'external_network': 'external_network_id',
'external_network': 'e2a6c8b0-a3c2-42a3-b3f4-01400a30896e',
'fixed_network': 'fixed_network',
'fixed_subnet': 'fixed_subnet',
'dns_nameserver': 'dns_nameserver',
@ -707,6 +711,7 @@ class TestClusterConductorWithK8s(base.TestCase):
'cert_manager_api': 'False',
'ingress_controller': 'i-controller',
'ingress_controller_role': 'i-controller-role',
'octavia_ingress_controller_tag': None,
'kubelet_options': '--kubelet',
'kubeapi_options': '--kubeapi',
'kubecontroller_options': '--kubecontroller',
@ -896,7 +901,7 @@ class TestClusterConductorWithK8s(base.TestCase):
expected = {
'ssh_key_name': 'keypair_id',
'external_network': 'external_network_id',
'external_network': 'e2a6c8b0-a3c2-42a3-b3f4-01400a30896e',
'fixed_network': 'fixed_network',
'fixed_subnet': 'fixed_subnet',
'dns_nameserver': 'dns_nameserver',
@ -946,6 +951,7 @@ class TestClusterConductorWithK8s(base.TestCase):
'cert_manager_api': 'False',
'ingress_controller': 'i-controller',
'ingress_controller_role': 'i-controller-role',
'octavia_ingress_controller_tag': None,
'kubelet_options': '--kubelet',
'kubeapi_options': '--kubeapi',
'kubecontroller_options': '--kubecontroller',

180
magnum/tests/unit/drivers/test_template_definition.py

@ -326,6 +326,8 @@ class AtomicK8sTemplateDefinitionTestCase(BaseK8sTemplateDefinitionTestCase):
mock_cluster_template.tls_disabled = False
mock_cluster_template.registry_enabled = False
mock_cluster_template.network_driver = 'flannel'
external_network_id = '17e4e301-b7f3-4996-b3dd-97b3a700174b'
mock_cluster_template.external_network_id = external_network_id
mock_cluster = mock.MagicMock()
mock_cluster.uuid = '5d12f6fd-a196-4bf0-ae4c-1f639a523a52'
del mock_cluster.stack_id
@ -384,9 +386,11 @@ class AtomicK8sTemplateDefinitionTestCase(BaseK8sTemplateDefinitionTestCase):
cgroup_driver = mock_cluster.labels.get(
'cgroup_driver')
ingress_controller = mock_cluster.labels.get(
'ingress_controller')
'ingress_controller').lower()
ingress_controller_role = mock_cluster.labels.get(
'ingress_controller_role')
octavia_ingress_controller_tag = mock_cluster.labels.get(
'octavia_ingress_controller_tag')
kubelet_options = mock_cluster.labels.get(
'kubelet_options')
kubeapi_options = mock_cluster.labels.get(
@ -459,6 +463,7 @@ class AtomicK8sTemplateDefinitionTestCase(BaseK8sTemplateDefinitionTestCase):
'pods_network_cidr': pods_network_cidr,
'ingress_controller': ingress_controller,
'ingress_controller_role': ingress_controller_role,
'octavia_ingress_controller_tag': octavia_ingress_controller_tag,
'octavia_enabled': False,
'kube_service_account_key': 'public_key',
'kube_service_account_private_key': 'private_key',
@ -469,6 +474,7 @@ class AtomicK8sTemplateDefinitionTestCase(BaseK8sTemplateDefinitionTestCase):
'keystone_auth_enabled': keystone_auth_enabled,
'k8s_keystone_auth_tag': k8s_keystone_auth_tag,
'project_id': project_id,
'external_network': external_network_id
}}
mock_get_params.assert_called_once_with(mock_context,
mock_cluster_template,
@ -486,6 +492,170 @@ class AtomicK8sTemplateDefinitionTestCase(BaseK8sTemplateDefinitionTestCase):
mock_cluster,
)
@mock.patch('magnum.common.neutron.get_network_id')
@mock.patch('magnum.common.keystone.is_octavia_enabled')
@mock.patch('magnum.common.clients.OpenStackClients')
@mock.patch('magnum.drivers.k8s_fedora_atomic_v1.template_def'
'.AtomicK8sTemplateDefinition.get_discovery_url')
@mock.patch('magnum.drivers.heat.template_def.BaseTemplateDefinition'
'.get_params')
@mock.patch('magnum.drivers.heat.template_def.TemplateDefinition'
'.get_output')
@mock.patch('magnum.common.x509.operations.generate_csr_and_key')
def test_k8s_get_params_external_network_id(self,
mock_generate_csr_and_key,
mock_get_output,
mock_get_params,
mock_get_discovery_url,
mock_osc_class,
mock_enable_octavia,
mock_network_id):
mock_generate_csr_and_key.return_value = {'csr': 'csr',
'private_key': 'private_key',
'public_key': 'public_key'}
mock_enable_octavia.return_value = False
mock_get_discovery_url.return_value = 'fake_discovery_url'
external_network_id = 'e2a6c8b0-a3c2-42a3-b3f4-01400a30896e'
mock_network_id.return_value = external_network_id
mock_context = mock.MagicMock()
mock_context.auth_token = 'AUTH_TOKEN'
mock_context.auth_url = 'http://192.168.10.10:5000/v3'
mock_context.user_name = 'fake_user'
mock_cluster_template = mock.MagicMock()
mock_cluster_template.tls_disabled = False
mock_cluster_template.registry_enabled = False
mock_cluster_template.network_driver = 'calico'
mock_cluster_template.external_network_id = "public"
mock_cluster = mock.MagicMock()
mock_cluster.labels = {}
mock_cluster.uuid = '5d12f6fd-a196-4bf0-ae4c-1f639a523a52'
mock_osc = mock.MagicMock()
mock_osc.magnum_url.return_value = 'http://127.0.0.1:9511/v1'
mock_osc.cinder_region_name.return_value = 'RegionOne'
mock_osc_class.return_value = mock_osc
k8s_def = k8sa_tdef.AtomicK8sTemplateDefinition()
k8s_def.get_params(mock_context, mock_cluster_template, mock_cluster)
actual_params = mock_get_params.call_args[1]["extra_params"]
self.assertEqual(
external_network_id,
actual_params.get("external_network")
)
mock_network_id.assert_called_once_with(
mock_context,
mock_cluster_template.external_network_id
)
@mock.patch('magnum.common.keystone.is_octavia_enabled')
@mock.patch('magnum.common.clients.OpenStackClients')
@mock.patch('magnum.drivers.k8s_fedora_atomic_v1.template_def'
'.AtomicK8sTemplateDefinition.get_discovery_url')
@mock.patch('magnum.drivers.heat.template_def.BaseTemplateDefinition'
'.get_params')
@mock.patch('magnum.drivers.heat.template_def.TemplateDefinition'
'.get_output')
@mock.patch('magnum.common.x509.operations.generate_csr_and_key')
def test_k8s_get_params_octavia_disabled(self,
mock_generate_csr_and_key,
mock_get_output,
mock_get_params,
mock_get_discovery_url,
mock_osc_class,
mock_enable_octavia):
mock_generate_csr_and_key.return_value = {'csr': 'csr',
'private_key': 'private_key',
'public_key': 'public_key'}
mock_enable_octavia.return_value = False
mock_get_discovery_url.return_value = 'fake_discovery_url'
mock_context = mock.MagicMock()
mock_context.auth_token = 'AUTH_TOKEN'
mock_context.auth_url = 'http://192.168.10.10:5000/v3'
mock_context.user_name = 'fake_user'
mock_cluster_template = mock.MagicMock()
mock_cluster_template.tls_disabled = False
mock_cluster_template.registry_enabled = False
mock_cluster_template.network_driver = 'calico'
external_network_id = 'e2a6c8b0-a3c2-42a3-b3f4-01400a30896e'
mock_cluster_template.external_network_id = external_network_id
mock_cluster = mock.MagicMock()
mock_cluster.labels = {"ingress_controller": "octavia"}
mock_cluster.uuid = '5d12f6fd-a196-4bf0-ae4c-1f639a523a52'
mock_osc = mock.MagicMock()
mock_osc.magnum_url.return_value = 'http://127.0.0.1:9511/v1'
mock_osc.cinder_region_name.return_value = 'RegionOne'
mock_osc_class.return_value = mock_osc
k8s_def = k8sa_tdef.AtomicK8sTemplateDefinition()
self.assertRaises(
exception.InvalidParameterValue,
k8s_def.get_params,
mock_context,
mock_cluster_template,
mock_cluster,
)
@mock.patch('magnum.common.keystone.is_octavia_enabled')
@mock.patch('magnum.common.clients.OpenStackClients')
@mock.patch('magnum.drivers.k8s_fedora_atomic_v1.template_def'
'.AtomicK8sTemplateDefinition.get_discovery_url')
@mock.patch('magnum.drivers.heat.template_def.BaseTemplateDefinition'
'.get_params')
@mock.patch('magnum.drivers.heat.template_def.TemplateDefinition'
'.get_output')
@mock.patch('magnum.common.x509.operations.generate_csr_and_key')
def test_k8s_get_params_octavia_enabled(self,
mock_generate_csr_and_key,
mock_get_output,
mock_get_params,
mock_get_discovery_url,
mock_osc_class,
mock_enable_octavia):
mock_generate_csr_and_key.return_value = {'csr': 'csr',
'private_key': 'private_key',
'public_key': 'public_key'}
mock_enable_octavia.return_value = True
mock_get_discovery_url.return_value = 'fake_discovery_url'
mock_context = mock.MagicMock()
mock_context.auth_token = 'AUTH_TOKEN'
mock_context.auth_url = 'http://192.168.10.10:5000/v3'
mock_context.user_name = 'fake_user'
mock_cluster_template = mock.MagicMock()
mock_cluster_template.tls_disabled = False
mock_cluster_template.registry_enabled = False
mock_cluster_template.network_driver = 'calico'
external_network_id = 'e2a6c8b0-a3c2-42a3-b3f4-01400a30896e'
mock_cluster_template.external_network_id = external_network_id
mock_cluster = mock.MagicMock()
mock_cluster.labels = {"ingress_controller": "octavia"}
mock_cluster.uuid = '5d12f6fd-a196-4bf0-ae4c-1f639a523a52'
mock_osc = mock.MagicMock()
mock_osc.magnum_url.return_value = 'http://127.0.0.1:9511/v1'
mock_osc.cinder_region_name.return_value = 'RegionOne'
mock_osc_class.return_value = mock_osc
k8s_def = k8sa_tdef.AtomicK8sTemplateDefinition()
k8s_def.get_params(mock_context, mock_cluster_template, mock_cluster)
actual_params = mock_get_params.call_args[1]["extra_params"]
self.assertEqual(
"octavia",
actual_params.get("ingress_controller")
)
@mock.patch('magnum.common.keystone.is_octavia_enabled')
@mock.patch('magnum.common.clients.OpenStackClients')
@mock.patch('magnum.drivers.heat.template_def'
@ -513,6 +683,8 @@ class AtomicK8sTemplateDefinitionTestCase(BaseK8sTemplateDefinitionTestCase):
mock_cluster_template.tls_disabled = True
mock_cluster_template.registry_enabled = False
mock_cluster_template.network_driver = 'calico'
external_network_id = '17e4e301-b7f3-4996-b3dd-97b3a700174b'
mock_cluster_template.external_network_id = external_network_id
mock_cluster = mock.MagicMock()
mock_cluster.uuid = '5d12f6fd-a196-4bf0-ae4c-1f639a523a52'
del mock_cluster.stack_id
@ -571,9 +743,11 @@ class AtomicK8sTemplateDefinitionTestCase(BaseK8sTemplateDefinitionTestCase):
cgroup_driver = mock_cluster.labels.get(
'cgroup_driver')
ingress_controller = mock_cluster.labels.get(
'ingress_controller')
'ingress_controller').lower()
ingress_controller_role = mock_cluster.labels.get(
'ingress_controller_role')
octavia_ingress_controller_tag = mock_cluster.labels.get(
'octavia_ingress_controller_tag')
kubelet_options = mock_cluster.labels.get(
'kubelet_options')
kubeapi_options = mock_cluster.labels.get(
@ -648,6 +822,7 @@ class AtomicK8sTemplateDefinitionTestCase(BaseK8sTemplateDefinitionTestCase):
'pods_network_cidr': pods_network_cidr,
'ingress_controller': ingress_controller,
'ingress_controller_role': ingress_controller_role,
'octavia_ingress_controller_tag': octavia_ingress_controller_tag,
'octavia_enabled': False,
'kube_service_account_key': 'public_key',
'kube_service_account_private_key': 'private_key',
@ -658,6 +833,7 @@ class AtomicK8sTemplateDefinitionTestCase(BaseK8sTemplateDefinitionTestCase):
'keystone_auth_enabled': keystone_auth_enabled,
'k8s_keystone_auth_tag': k8s_keystone_auth_tag,
'project_id': project_id,
'external_network': external_network_id
}}
mock_get_params.assert_called_once_with(mock_context,
mock_cluster_template,

8
releasenotes/notes/k8s-octavia-ingress-controller-32c0b97031fd0dd4.yaml

@ -0,0 +1,8 @@
---
features:
- |
Add a new option 'octavia' for the label 'ingress_controller' and a new
label 'octavia_ingress_controller_tag' to enable the deployment of
`octavia-ingress-controller <https://github.com/kubernetes/cloud-provider-openstack/blob/master/docs/using-octavia-ingress-controller.md>`_
in the kubernetes cluster. The 'ingress_controller_role' label is not used
for this option.
Loading…
Cancel
Save