Container Infrastructure Management Service for OpenStack
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

272 lines
11 KiB

  1. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  2. # not use this file except in compliance with the License. You may obtain
  3. # a copy of the License at
  4. #
  5. # http://www.apache.org/licenses/LICENSE-2.0
  6. #
  7. # Unless required by applicable law or agreed to in writing, software
  8. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  9. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  10. # License for the specific language governing permissions and limitations
  11. # under the License.
  12. from oslo_config import cfg
  13. from oslo_log import log as logging
  14. from magnum.common import exception
  15. from magnum.common import keystone
  16. from magnum.common import neutron
  17. from magnum.drivers.heat import template_def
  18. CONF = cfg.CONF
  19. LOG = logging.getLogger(__name__)
  20. """kubernetes ports """
  21. KUBE_SECURE_PORT = '6443'
  22. KUBE_INSECURE_PORT = '8080'
  23. class K8sApiAddressOutputMapping(template_def.OutputMapping):
  24. def set_output(self, stack, cluster_template, cluster):
  25. if self.cluster_attr is None:
  26. return
  27. output_value = self.get_output_value(stack)
  28. if output_value is not None:
  29. # TODO(yuanying): port number is hardcoded, this will be fix
  30. protocol = 'https'
  31. port = KUBE_SECURE_PORT
  32. if cluster_template.tls_disabled:
  33. protocol = 'http'
  34. port = KUBE_INSECURE_PORT
  35. params = {
  36. 'protocol': protocol,
  37. 'address': output_value,
  38. 'port': port,
  39. }
  40. value = "%(protocol)s://%(address)s:%(port)s" % params
  41. setattr(cluster, self.cluster_attr, value)
  42. class ServerAddressOutputMapping(template_def.NodeGroupOutputMapping):
  43. public_ip_output_key = None
  44. private_ip_output_key = None
  45. def __init__(self, dummy_arg, nodegroup_attr=None, nodegroup_uuid=None):
  46. self.nodegroup_attr = nodegroup_attr
  47. self.nodegroup_uuid = nodegroup_uuid
  48. self.heat_output = self.public_ip_output_key
  49. self.is_stack_param = False
  50. def set_output(self, stack, cluster_template, cluster):
  51. if not cluster_template.floating_ip_enabled:
  52. self.heat_output = self.private_ip_output_key
  53. LOG.debug("Using heat_output: %s", self.heat_output)
  54. super(ServerAddressOutputMapping,
  55. self).set_output(stack, cluster_template, cluster)
  56. class MasterAddressOutputMapping(ServerAddressOutputMapping):
  57. public_ip_output_key = 'kube_masters'
  58. private_ip_output_key = 'kube_masters_private'
  59. class NodeAddressOutputMapping(ServerAddressOutputMapping):
  60. public_ip_output_key = 'kube_minions'
  61. private_ip_output_key = 'kube_minions_private'
  62. class K8sTemplateDefinition(template_def.BaseTemplateDefinition):
  63. """Base Kubernetes template."""
  64. def __init__(self):
  65. super(K8sTemplateDefinition, self).__init__()
  66. self.add_parameter('external_network',
  67. cluster_template_attr='external_network_id',
  68. required=True)
  69. self.add_parameter('fixed_network',
  70. cluster_attr='fixed_network')
  71. self.add_parameter('fixed_subnet',
  72. cluster_attr='fixed_subnet')
  73. self.add_parameter('network_driver',
  74. cluster_template_attr='network_driver')
  75. self.add_parameter('volume_driver',
  76. cluster_template_attr='volume_driver')
  77. self.add_parameter('tls_disabled',
  78. cluster_template_attr='tls_disabled',
  79. required=True)
  80. self.add_parameter('registry_enabled',
  81. cluster_template_attr='registry_enabled')
  82. self.add_parameter('cluster_uuid',
  83. cluster_attr='uuid',
  84. param_type=str)
  85. self.add_parameter('insecure_registry_url',
  86. cluster_template_attr='insecure_registry')
  87. self.add_parameter('kube_version',
  88. cluster_attr='coe_version')
  89. self.add_output('api_address',
  90. cluster_attr='api_address',
  91. mapping_type=K8sApiAddressOutputMapping)
  92. self.add_output('kube_minions_private',
  93. cluster_attr=None)
  94. self.add_output('kube_masters_private',
  95. cluster_attr=None)
  96. def get_nodegroup_param_maps(self, master_params=None, worker_params=None):
  97. master_params = master_params or dict()
  98. worker_params = worker_params or dict()
  99. master_params.update({
  100. 'master_flavor': 'flavor_id',
  101. 'master_image': 'image_id',
  102. 'master_role': 'role',
  103. 'master_nodegroup_name': 'name',
  104. })
  105. worker_params.update({
  106. 'number_of_minions': 'node_count',
  107. 'minion_flavor': 'flavor_id',
  108. 'minion_image': 'image_id',
  109. 'worker_role': 'role',
  110. 'worker_nodegroup_name': 'name',
  111. })
  112. return super(
  113. K8sTemplateDefinition, self).get_nodegroup_param_maps(
  114. master_params=master_params, worker_params=worker_params)
  115. def update_outputs(self, stack, cluster_template, cluster,
  116. nodegroups=None):
  117. nodegroups = nodegroups or [cluster.default_ng_worker,
  118. cluster.default_ng_master]
  119. for nodegroup in nodegroups:
  120. if nodegroup.role == 'master':
  121. self.add_output('kube_masters',
  122. nodegroup_attr='node_addresses',
  123. nodegroup_uuid=nodegroup.uuid,
  124. mapping_type=MasterAddressOutputMapping)
  125. else:
  126. self.add_output('kube_minions',
  127. nodegroup_attr='node_addresses',
  128. nodegroup_uuid=nodegroup.uuid,
  129. mapping_type=NodeAddressOutputMapping)
  130. self.add_output(
  131. 'number_of_minions', nodegroup_attr='node_count',
  132. nodegroup_uuid=nodegroup.uuid,
  133. mapping_type=template_def.NodeGroupOutputMapping,
  134. is_stack_param=True)
  135. super(K8sTemplateDefinition,
  136. self).update_outputs(stack, cluster_template, cluster,
  137. nodegroups=nodegroups)
  138. def get_params(self, context, cluster_template, cluster, **kwargs):
  139. extra_params = kwargs.pop('extra_params', {})
  140. extra_params['discovery_url'] = self.get_discovery_url(cluster)
  141. osc = self.get_osc(context)
  142. extra_params['magnum_url'] = osc.magnum_url()
  143. if cluster_template.tls_disabled:
  144. extra_params['loadbalancing_protocol'] = 'HTTP'
  145. extra_params['kubernetes_port'] = 8080
  146. extra_params['octavia_enabled'] = keystone.is_octavia_enabled()
  147. # NOTE(lxkong): Convert external network name to UUID, the template
  148. # field name is confused. If external_network_id is not specified in
  149. # cluster template use 'public' as the default value, which is the same
  150. # with the heat template default value as before.
  151. external_network = cluster_template.external_network_id or "public"
  152. extra_params['external_network'] = \
  153. neutron.get_external_network_id(context, external_network)
  154. # NOTE(brtknr): Convert fixed network UUID to name if the given network
  155. # name is UUID like because OpenStack Cloud Controller Manager only
  156. # accepts a name as an argument to internal-network-name in the
  157. # cloud-config file provided to it. The default fixed network name is
  158. # the same as that defined in the heat template.
  159. fixed_network = (cluster.fixed_network or
  160. cluster_template.fixed_network or
  161. "private")
  162. extra_params['fixed_network_name'] = \
  163. neutron.get_fixed_network_name(context, fixed_network)
  164. # NOTE(brtknr): Convert fixed subnet name to UUID. If fixed_subnet
  165. # is not specified in cluster template use 'private' as the default
  166. # value, which is the same as the heat template default value.
  167. fixed_subnet = (cluster.fixed_subnet or
  168. cluster_template.fixed_subnet or
  169. "private")
  170. extra_params['fixed_subnet'] = \
  171. neutron.get_fixed_subnet_id(context, fixed_subnet)
  172. label_list = ['flannel_network_cidr', 'flannel_backend',
  173. 'flannel_network_subnetlen',
  174. 'system_pods_initial_delay',
  175. 'system_pods_timeout',
  176. 'admission_control_list',
  177. 'prometheus_monitoring',
  178. 'grafana_admin_passwd',
  179. 'kube_dashboard_enabled',
  180. 'etcd_volume_size',
  181. 'cert_manager_api',
  182. 'ingress_controller_role',
  183. 'octavia_ingress_controller_tag',
  184. 'kubelet_options',
  185. 'kubeapi_options',
  186. 'kubeproxy_options',
  187. 'kubecontroller_options',
  188. 'kubescheduler_options',
  189. 'influx_grafana_dashboard_enabled']
  190. labels = self._get_relevant_labels(cluster, kwargs)
  191. for label in label_list:
  192. extra_params[label] = labels.get(label)
  193. ingress_controller = cluster.labels.get('ingress_controller',
  194. '').lower()
  195. if (ingress_controller == 'octavia'
  196. and not extra_params['octavia_enabled']):
  197. raise exception.InvalidParameterValue(
  198. 'Octavia service needs to be deployed for octavia ingress '
  199. 'controller.')
  200. extra_params["ingress_controller"] = ingress_controller
  201. cluser_ip_range = cluster.labels.get('service_cluster_ip_range')
  202. if cluser_ip_range:
  203. extra_params['portal_network_cidr'] = cluser_ip_range
  204. if cluster_template.registry_enabled:
  205. extra_params['swift_region'] = CONF.docker_registry.swift_region
  206. extra_params['registry_container'] = (
  207. CONF.docker_registry.swift_registry_container)
  208. kube_tag = (labels.get("kube_tag") or
  209. cluster_template.labels.get("kube_tag"))
  210. if kube_tag:
  211. extra_params['kube_version'] = kube_tag
  212. extra_params['master_kube_tag'] = kube_tag
  213. extra_params['minion_kube_tag'] = kube_tag
  214. return super(K8sTemplateDefinition,
  215. self).get_params(context, cluster_template, cluster,
  216. extra_params=extra_params,
  217. **kwargs)
  218. def get_scale_params(self, context, cluster, scale_manager=None,
  219. nodes_to_remove=None):
  220. scale_params = dict()
  221. if nodes_to_remove:
  222. scale_params['minions_to_remove'] = nodes_to_remove
  223. if scale_manager:
  224. hosts = self.get_output('kube_minions_private')
  225. scale_params['minions_to_remove'] = (
  226. scale_manager.get_removal_nodes(hosts))
  227. return scale_params