
* LICENSE file placed to every package * License information is shown during application creation * License added to every file Change-Id: I682f3d9a09d0c0b575206d79223c1822c4b94f27 Closes-Bug: #1446121
498 lines
16 KiB
YAML
498 lines
16 KiB
YAML
# 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.
|
|
|
|
Namespaces:
|
|
=: io.murano.apps.docker.kubernetes
|
|
std: io.murano
|
|
res: io.murano.resources
|
|
sys: io.murano.system
|
|
docker: io.murano.apps.docker
|
|
|
|
|
|
Name: KubernetesCluster
|
|
|
|
Extends: std:Application
|
|
|
|
Properties:
|
|
name:
|
|
Contract: $.string().notNull()
|
|
|
|
masterNode:
|
|
Contract: $.class(KubernetesMasterNode).notNull()
|
|
|
|
minionNodes:
|
|
Contract:
|
|
- $.class(KubernetesMinionNode).notNull()
|
|
- 1
|
|
|
|
nodeCount:
|
|
Contract: $.int().notNull().check($ > 0)
|
|
Usage: InOut
|
|
|
|
gatewayCount:
|
|
Contract: $.int().notNull()
|
|
Usage: InOut
|
|
|
|
gatewayNodes:
|
|
Contract:
|
|
- $.class(KubernetesGatewayNode).notNull()
|
|
|
|
dockerRegistry:
|
|
Contract: $.string()
|
|
|
|
serviceEndpoints:
|
|
Contract:
|
|
- port: $.int().notNull().check($ > 0)
|
|
address: $.string().notNull()
|
|
scope: $.string().notNull().check($ in list(public, cloud, internal, host))
|
|
portScope: $.string().notNull().check($ in list(public, cloud, internal, host))
|
|
containerPort: $.int().notNull().check($ > 0)
|
|
protocol: $.string().notNull().check($ in list(TCP, UDP))
|
|
applicationName: $.string().notNull()
|
|
podId: $.string().notNull()
|
|
serviceName: $.string()
|
|
Default: []
|
|
Usage: Out
|
|
|
|
|
|
Methods:
|
|
initialize:
|
|
Body:
|
|
- $._environment: $.find(std:Environment).require()
|
|
|
|
|
|
deploy:
|
|
Body:
|
|
- If: not $.getAttr(deployed, false)
|
|
Then:
|
|
- $._environment.reporter.report($this, 'Creating VMs for Kubernetes cluster')
|
|
- $securityGroupIngress:
|
|
- ToPort: 4001
|
|
FromPort: 4001
|
|
IpProtocol: tcp
|
|
External: false
|
|
- ToPort: 7001
|
|
FromPort: 7001
|
|
IpProtocol: tcp
|
|
External: false
|
|
- ToPort: 10250
|
|
FromPort: 10250
|
|
IpProtocol: tcp
|
|
External: false
|
|
- ToPort: 8080
|
|
FromPort: 8080
|
|
IpProtocol: tcp
|
|
External: $.masterNode.instance.assignFloatingIp
|
|
- ToPort: 2380
|
|
FromPort: 2380
|
|
IpProtocol: tcp
|
|
External: false
|
|
- ToPort: 8285
|
|
FromPort: 8285
|
|
IpProtocol: udp
|
|
External: false
|
|
- $._environment.securityGroupManager.addGroupIngress($securityGroupIngress)
|
|
- $.setAttr(deployed, true)
|
|
|
|
- $._environment.reporter.report($this, 'Setting up Kubernetes cluster')
|
|
- Parallel:
|
|
- Do: $.masterNode.deployInstance()
|
|
- Do: $.minionNodes.take($.nodeCount).pselect($.deployInstance())
|
|
- Do: $.gatewayNodes.take($.gatewayCount).pselect($.deployInstance())
|
|
|
|
- $.masterNode.setupEtcd()
|
|
- $.minionNodes.take($.nodeCount).select($.setupEtcd())
|
|
- $.gatewayNodes.take($.gatewayCount).select($.setupEtcd())
|
|
|
|
- $.masterNode.setupNode()
|
|
- Parallel:
|
|
- Do: $.minionNodes.take($.nodeCount).pselect($.setupNode())
|
|
- Do: $.minionNodes.skip($.nodeCount).pselect($.removeFromCluster())
|
|
- Do: $.gatewayNodes.take($.gatewayCount).pselect($.setupNode())
|
|
- $._updateEndpoints()
|
|
- $._environment.reporter.report($this, 'Kubernetes cluster is up and running')
|
|
|
|
|
|
getIp:
|
|
Body:
|
|
Return: $.masterNode.getIp()
|
|
|
|
|
|
createPod:
|
|
Arguments:
|
|
- definition:
|
|
Contract: {}
|
|
- isNew:
|
|
Contract: $.bool().notNull()
|
|
Default: true
|
|
Body:
|
|
- $.deploy()
|
|
- $resources: new(sys:Resources)
|
|
- $template: $resources.yaml('UpdatePod.template').bind(dict(
|
|
podDefinition => $definition,
|
|
isNew => $isNew
|
|
))
|
|
- $.masterNode.instance.agent.call($template, $resources)
|
|
|
|
|
|
createReplicationController:
|
|
Arguments:
|
|
- definition:
|
|
Contract: {}
|
|
- isNew:
|
|
Contract: $.bool().notNull()
|
|
Default: true
|
|
Body:
|
|
- $.deploy()
|
|
- $resources: new(sys:Resources)
|
|
- $template: $resources.yaml('UpdateReplicationController.template').bind(dict(
|
|
controllerDefinition => $definition,
|
|
isNew => $isNew
|
|
))
|
|
- $.masterNode.instance.agent.call($template, $resources)
|
|
|
|
|
|
deleteReplicationController:
|
|
Arguments:
|
|
- id:
|
|
Contract: $.string().notNull()
|
|
Body:
|
|
- $.deploy()
|
|
- $resources: new(sys:Resources)
|
|
- $template: $resources.yaml('DeleteReplicationController.template').bind(dict(rcId => $id))
|
|
- $.masterNode.instance.agent.call($template, $resources)
|
|
|
|
|
|
deletePods:
|
|
Arguments:
|
|
- labels:
|
|
Contract:
|
|
$.string().notNull(): $.string().notNull()
|
|
Body:
|
|
- $.deploy()
|
|
- $resources: new(sys:Resources)
|
|
- $template: $resources.yaml('DeletePods.template').bind(dict(labels => $labels))
|
|
- $.masterNode.instance.agent.call($template, $resources)
|
|
|
|
|
|
createServices:
|
|
Arguments:
|
|
- applicationName:
|
|
Contract: $.string().notNull()
|
|
- applicationPorts:
|
|
Contract:
|
|
- $.class(docker:ApplicationPort)
|
|
- podId:
|
|
Contract: $.string().notNull()
|
|
Body:
|
|
- $resources: new(sys:Resources)
|
|
|
|
- $applicationServices: {}
|
|
- For: endpoint
|
|
In: $.serviceEndpoints.where($.applicationName = $applicationName).where($.serviceName != null)
|
|
Do:
|
|
- $serviceName: $endpoint.serviceName
|
|
- $applicationServices[$serviceName]: $endpoint
|
|
|
|
- $.serviceEndpoints: $.serviceEndpoints.where($.applicationName != $applicationName)
|
|
|
|
- $servicesUsed: []
|
|
- For: applicationPort
|
|
In: $applicationPorts
|
|
Do:
|
|
- If: $applicationPort.scope != host
|
|
Then:
|
|
- $serviceName: null
|
|
- $reuseEndpoint: null
|
|
- For: service
|
|
In: $applicationServices.keys()
|
|
Do:
|
|
- $endpoint: $applicationServices.get($service)
|
|
- If: $endpoint.containerPort = $applicationPort.port and $endpoint.protocol = $applicationPort.protocol
|
|
Then:
|
|
- $serviceName: $service
|
|
- $reuseEndpoint: $endpoint
|
|
- Break:
|
|
|
|
- If: $serviceName = null
|
|
Then:
|
|
- $serviceName: format('svc-{0}', randomName())
|
|
- $servicePort: $._findUnusedPort($applicationPort.port, $applicationPort.protocol)
|
|
- $serviceIp: $._createService($podId, $serviceName, $servicePort, $applicationPort)
|
|
Else:
|
|
- $servicesUsed: $servicesUsed + list($serviceName)
|
|
- $servicePort: $reuseEndpoint.port
|
|
- $serviceIp: $._updateService($podId, $reuseEndpoint)
|
|
|
|
- $newEndpoint:
|
|
port: $servicePort
|
|
address: $serviceIp
|
|
scope: internal
|
|
portScope: $applicationPort.scope
|
|
applicationName: $applicationName
|
|
containerPort: $applicationPort.port
|
|
protocol: $applicationPort.protocol
|
|
podId: $podId
|
|
serviceName: $serviceName
|
|
- $.serviceEndpoints: $.serviceEndpoints + list($newEndpoint)
|
|
|
|
- If: $applicationPort.scope in list(public, cloud)
|
|
Then:
|
|
- If: $.gatewayCount > 0
|
|
Then:
|
|
- $nodes: $.gatewayNodes.take($.gatewayCount)
|
|
Else:
|
|
- $nodes: $.minionNodes.take($.nodeCount)
|
|
|
|
- For: t
|
|
In: $nodes
|
|
Do:
|
|
- $newEndpoint.address: $t.getIp()
|
|
- $newEndpoint.scope: cloud
|
|
- $.serviceEndpoints: $.serviceEndpoints + list($newEndpoint)
|
|
|
|
- If: $t.instance.floatingIpAddress != null and $applicationPort.scope = public
|
|
Then:
|
|
- $newEndpoint.address: $t.instance.floatingIpAddress
|
|
- $newEndpoint.scope: public
|
|
- $.serviceEndpoints: $.serviceEndpoints + list($newEndpoint)
|
|
- $newEndpoint:
|
|
port: $applicationPort.port
|
|
address: '127.0.0.1'
|
|
scope: host
|
|
portScope: $applicationPort.scope
|
|
containerPort: $applicationPort.port
|
|
protocol: $applicationPort.protocol
|
|
applicationName: $applicationName
|
|
podId: $podId
|
|
serviceName: null
|
|
- $.serviceEndpoints: $.serviceEndpoints + list($newEndpoint)
|
|
|
|
- For: service
|
|
In: $applicationServices.keys()
|
|
Do:
|
|
- If: not $service in $servicesUsed
|
|
Then:
|
|
- $._deleteService($service)
|
|
- $._environment.stack.push()
|
|
|
|
|
|
_createService:
|
|
Arguments:
|
|
- podId:
|
|
Contract: $.string().notNull()
|
|
- serviceName:
|
|
Contract: $.string().notNull()
|
|
- servicePort:
|
|
Contract: $.int().notNull()
|
|
- applicationPort:
|
|
Contract: $.class(docker:ApplicationPort)
|
|
Body:
|
|
- $resources: new(sys:Resources)
|
|
- $serviceDefinition: $._buildServiceDefinition(
|
|
$serviceName,
|
|
$servicePort,
|
|
$applicationPort.protocol,
|
|
$applicationPort.port,
|
|
$podId,
|
|
$.gatewayCount = 0
|
|
)
|
|
- $template: $resources.yaml('UpdateService.template').bind(dict(
|
|
serviceDefinition => $serviceDefinition,
|
|
isNew => true
|
|
))
|
|
- $securityGroupIngress:
|
|
- ToPort: $servicePort
|
|
FromPort: $servicePort
|
|
IpProtocol: toLower($applicationPort.protocol)
|
|
External: $applicationPort.scope = public
|
|
|
|
- $._environment.securityGroupManager.addGroupIngress($securityGroupIngress)
|
|
|
|
- Return: $.masterNode.instance.agent.call($template, $resources)
|
|
|
|
|
|
_updateService:
|
|
Arguments:
|
|
- podId:
|
|
Contract: $.string().notNull()
|
|
- endpoint:
|
|
Contract:
|
|
port: $.int().notNull().check($ > 0)
|
|
address: $.string().notNull()
|
|
scope: $.string().notNull().check($ in list(public, cloud, internal, host))
|
|
containerPort: $.int().notNull().check($ > 0)
|
|
protocol: $.string().notNull().check($ in list(TCP, UDP))
|
|
applicationName: $.string().notNull()
|
|
podId: $.string().notNull()
|
|
serviceName: $.string()
|
|
|
|
Body:
|
|
- $resources: new(sys:Resources)
|
|
- $prevNodeCount: $.getAttr(lastNodeCount, 0-1) # 0-1 instead of -1 because YAQL 0.2 doesn't understand unary operators
|
|
- $prevGatewayCount: $.getAttr(lastGatewayCount, 0-1)
|
|
- $gatewayModeChanged: $prevGatewayCount != $.gatewayCount and $prevGatewayCount * $.gatewayCount = 0
|
|
|
|
- $serviceChanged: $endpoint.podId != $podId or
|
|
$endpoint.portScope in list(public, cloud) and (
|
|
$gatewayModeChanged or $.gatewayCount = 0 and $prevNodeCount != $.nodeCount)
|
|
- If: $serviceChanged
|
|
Then:
|
|
- $serviceDefinition: $._buildServiceDefinition(
|
|
$endpoint.serviceName,
|
|
$endpoint.port,
|
|
$endpoint.protocol,
|
|
$endpoint.containerPort,
|
|
$podId,
|
|
$.gatewayCount = 0
|
|
)
|
|
- $template: $resources.yaml('UpdateService.template').bind(dict(
|
|
serviceDefinition => $serviceDefinition,
|
|
isNew => false
|
|
))
|
|
- $serviceIp: $.masterNode.instance.agent.call($template, $resources)
|
|
Else:
|
|
- $serviceIp: $endpoint.address
|
|
- Return: $serviceIp
|
|
|
|
|
|
_updateEndpoints:
|
|
Body:
|
|
- For: endpoint
|
|
In: $.serviceEndpoints
|
|
Do:
|
|
- $._updateService($endpoint.podId, $endpoint)
|
|
- $.setAttr(lastNodeCount, $.nodeCount)
|
|
- $.setAttr(lastGatewayCount, $.gatewayCount)
|
|
|
|
|
|
_deleteService:
|
|
Arguments:
|
|
serviceName:
|
|
Contract: $.string().notNull()
|
|
Body:
|
|
- $resources: new(sys:Resources)
|
|
- $template: $resources.yaml('DeleteService.template').bind(dict(
|
|
serviceId => $service
|
|
))
|
|
- $.masterNode.instance.agent.call($template, $resources)
|
|
|
|
|
|
deleteService:
|
|
Arguments:
|
|
- applicationName:
|
|
Contract: $.string().notNull()
|
|
- podId:
|
|
Contract: $.string().notNull()
|
|
Body:
|
|
- $._deleteService($applicationName, $podId)
|
|
|
|
|
|
_findUnusedPort:
|
|
Arguments:
|
|
- initial:
|
|
Contract: $.int().notNull()
|
|
- protocol:
|
|
Contract: $.string().notNull()
|
|
Body:
|
|
- If: initial != 22 and $._checkIfPortIsNotUsed($initial, $protocol)
|
|
Then:
|
|
Return: $initial
|
|
|
|
- $port: 1025
|
|
- While: not $._checkIfPortIsNotUsed($port, $protocol)
|
|
Do:
|
|
$port: $port + 1
|
|
- Return: $port
|
|
|
|
|
|
_checkIfPortIsNotUsed:
|
|
Arguments:
|
|
- port:
|
|
Contract: $.int().notNull()
|
|
- protocol:
|
|
Contract: $.string().notNull()
|
|
Body:
|
|
- Return: len(list($.serviceEndpoints.where($.port = $port).where($.protocol = $protocol))) = 0
|
|
|
|
|
|
_buildServiceDefinition:
|
|
Arguments:
|
|
- serviceName:
|
|
Contract: $.string().notNull()
|
|
- servicePort:
|
|
Contract: $.int().notNull()
|
|
- protocol:
|
|
Contract: $.string().notNull()
|
|
- containerPort:
|
|
Contract: $.int().notNull()
|
|
- podId:
|
|
Contract: $.string().notNull()
|
|
- withNodeIps:
|
|
Contract: $.bool().notNull()
|
|
Body:
|
|
- $result:
|
|
id: $serviceName
|
|
kind: Service
|
|
apiVersion: v1beta1
|
|
port: $servicePort
|
|
containerPort: $containerPort
|
|
protocol: $protocol
|
|
selector:
|
|
id: $podId
|
|
- If: $withNodeIps
|
|
Then:
|
|
- $result.publicIPs: $.minionNodes.take($.nodeCount).select($.getIp())
|
|
- Return: $result
|
|
|
|
|
|
scaleNodesUp:
|
|
Usage: Action
|
|
Body:
|
|
- If: $.nodeCount < len($.minionNodes)
|
|
Then:
|
|
- $._environment.reporter.report($this, 'Scaling up Kubernetes cluster')
|
|
- $.nodeCount: $.nodeCount + 1
|
|
- $.deploy()
|
|
|
|
|
|
scaleNodesDown:
|
|
Usage: Action
|
|
Body:
|
|
- If: $.nodeCount > 1
|
|
Then:
|
|
- $._environment.reporter.report($this, 'Scaling Kubernetes cluster down')
|
|
- $.nodeCount: $.nodeCount - 1
|
|
- $.deploy()
|
|
|
|
|
|
scaleGatewaysUp:
|
|
Usage: Action
|
|
Body:
|
|
- If: $.gatewayCount < len($.gatewayNodes)
|
|
Then:
|
|
- $._environment.reporter.report($this, 'Adding new gateway node')
|
|
- $.gatewayCount: $.gatewayCount + 1
|
|
- $.deploy()
|
|
|
|
|
|
exportConfig:
|
|
Usage: Action
|
|
Body:
|
|
- $._environment.reporter.report($this, 'Action exportConfig called')
|
|
- $resources: new(sys:Resources)
|
|
- $template: $resources.yaml('ExportConfig.template')
|
|
- $result: $.masterNode.instance.agent.call($template, $resources)
|
|
- $._environment.reporter.report($this, 'Got archive from Kubernetes')
|
|
- Return: new(std:File, base64Content => $result.content,
|
|
filename => 'application.tar.gz')
|