Stan Lagun 0549313491 [Docker] Do not try to delete container on destroyed host
When Environment get deleted both Docker/k8s host and
Docker applications get deleted. So it is possible that host
will try to delete container from an Instance that was already
destroyed. Attempt to send commands to such instance
will hang until timeout because there is no more agent
exist on the other side.

Change-Id: Ia6e8064ae50c24ce595ed08e446ed45b96b4a330
Closes-Bug: #1504623
Depends-On: I298f3f079a153ef87ed7213b7f1432c9e5e4b4b6
2015-10-12 11:23:27 +00:00

515 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()
isAvailable:
Body:
- Return: $.masterNode.isAvailable()
deploy:
Body:
- $.serviceEndpoints: $.getAttr(serviceEndpoints, list())
- 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)
- $prevNodeCount: $.getAttr(lastNodeCount, 0)
- $prevGatewayCount: $.getAttr(lastGatewayCount, 0)
- If: $prevNodeCount != $.nodeCount or $prevGatewayCount != $.gatewayCount
Then:
- $._environment.reporter.report($this, 'Setting up Kubernetes cluster')
- Parallel:
- $.masterNode.deployInstance()
- $.minionNodes.take($.nodeCount).pselect($.deployInstance())
- $.gatewayNodes.take($.gatewayCount).pselect($.deployInstance())
- $.masterNode.setupEtcd()
- $.minionNodes.take($.nodeCount).select($.setupEtcd())
- $.gatewayNodes.take($.gatewayCount).select($.setupEtcd())
- $.masterNode.setupNode()
- Parallel:
- $.minionNodes.take($.nodeCount).pselect($.setupNode())
- $.minionNodes.skip($.nodeCount).pselect($.removeFromCluster())
- $.gatewayNodes.take($.gatewayCount).pselect($.setupNode())
- $._environment.stack.push()
- $._updateServicePublicIps()
- $.setAttr(lastNodeCount, $.nodeCount)
- $.setAttr(lastGatewayCount, $.gatewayCount)
- $._environment.reporter.report($this, 'Kubernetes cluster is up and running')
- $.setAttr(serviceEndpoints, $.serviceEndpoints)
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)
createService:
Arguments:
- applicationName:
Contract: $.string().notNull()
- applicationPorts:
Contract:
- $.class(docker:ApplicationPort)
- podId:
Contract: $.string().notNull()
Body:
- $.serviceEndpoints: $.getAttr(serviceEndpoints, list())
- $currentEndpoints: $.serviceEndpoints.where($.applicationName = $applicationName and $.podId = $podId and $.scope = internal)
- $serviceName: format('svc-{0}', randomName())
- $endpointMap: {}
- For: endpoint
In: $currentEndpoints
Do:
- $serviceName: $endpoint.serviceName
- $key: format('{0}-{1}', $endpoint.containerPort, $endpoint.protocol)
- $endpointMap[$key]: $endpoint
- $serviceChanged: len(list($applicationPorts.where($.scope != host))) != len($currentEndpoints)
- $servicePorts: []
- For: applicationPort
In: $applicationPorts.where($.scope != host)
Do:
- $key: format('{0}-{1}', $applicationPort.port, $applicationPort.protocol)
- $endpoint: $endpointMap.get($key)
- If: $endpoint != null
Then:
- $record:
- assignedPort: $endpoint.port
applicationPort: $applicationPort
Else:
- $port: $._findUnusedPort($applicationPort.port, $applicationPort.protocol)
- $record:
- assignedPort: $port
applicationPort: $applicationPort
- $serviceChanged: true
- $securityGroupIngress:
- ToPort: $port
FromPort: $port
IpProtocol: toLower($applicationPort.protocol)
External: $applicationPort.scope = public
- $._environment.securityGroupManager.addGroupIngress($securityGroupIngress)
- $servicePorts: $servicePorts + $record
- If: $serviceChanged
Then:
- $serviceIp: $._createOrUpdateService(
name => $serviceName,
ports => $servicePorts,
podId => $podId,
isNew => len($currentEndpoints) = 0
)
- $._updateEndpoints(
ports => $servicePorts,
applicationName => $applicationName,
podId => $podId,
serviceName => $serviceName,
serviceIp => $serviceIp
)
- $._environment.stack.push()
- $.setAttr(serviceEndpoints, $.serviceEndpoints)
_createOrUpdateService:
Arguments:
- name:
Contract: $.string().notNull()
- ports:
Contract:
- assignedPort: $.int().notNull()
applicationPort: $.class(docker:ApplicationPort).notNull()
- podId:
Contract: $.string().notNull()
- isNew:
Contract: $.bool().notNull()
Body:
- $serviceDefinition:
apiVersion: v1
kind: Service
metadata:
labels:
name: $name
name: $name
spec:
ports: $ports.select(dict(
port => $.assignedPort,
targetPort => $.applicationPort.port,
protocol => $.applicationPort.protocol,
name => str($.assignedPort)
))
selector:
id: $podId
- If: $.gatewayCount = 0
Then:
- $serviceDefinition.spec.publicIPs: $.minionNodes.take($.nodeCount).select($.getIp())
- $resources: new(sys:Resources)
- $template: $resources.yaml('UpdateService.template').bind(dict(
serviceDefinition => $serviceDefinition,
isNew => $isNew
))
- Return: $.masterNode.instance.agent.call($template, $resources)
_updateEndpoints:
Arguments:
- ports:
Contract:
- assignedPort: $.int().notNull()
applicationPort: $.class(docker:ApplicationPort).notNull()
- applicationName:
Contract: $.string().notNull()
- podId:
Contract: $.string().notNull()
- serviceName:
Contract: $.string().notNull()
- serviceIp:
Contract: $.string().notNull()
Body:
- $.serviceEndpoints: $.serviceEndpoints.where($.applicationName != $applicationName or $.podId != $podId)
- For: port
In: $ports
Do:
- $newEndpoint:
port: $port.assignedPort
address: $serviceIp
scope: internal
portScope: $port.applicationPort.scope
applicationName: $applicationName
containerPort: $port.applicationPort.port
protocol: $port.applicationPort.protocol
podId: $podId
serviceName: $serviceName
- $.serviceEndpoints: $.serviceEndpoints + list($newEndpoint)
- If: $port.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 $port.applicationPort.scope = public
Then:
- $newEndpoint.address: $t.instance.floatingIpAddress
- $newEndpoint.scope: public
- $.serviceEndpoints: $.serviceEndpoints + list($newEndpoint)
- $newEndpoint:
port: $port.applicationPort.port
address: '127.0.0.1'
scope: host
portScope: $port.applicationPort.scope
containerPort: $port.applicationPort.port
protocol: $port.applicationPort.protocol
applicationName: $applicationName
podId: $podId
serviceName: null
- $.serviceEndpoints: $.serviceEndpoints + list($newEndpoint)
_updateServicePublicIps:
Body:
- $prevNodeCount: $.getAttr(lastNodeCount, 0)
- $prevGatewayCount: $.getAttr(lastGatewayCount, 0)
- $gatewayModeChanged: $prevGatewayCount != $.gatewayCount and $prevGatewayCount * $.gatewayCount = 0
- If: $prevGatewayCount > 0 and $.gatewayCount > 0
Then:
- Return:
- If: $prevGatewayCount = 0 and $.gatewayCount = 0 and $prevNodeCount = $.nodeCount
Then:
- Return:
- $serviceNameMap: {}
- For: endpoint
In: $.serviceEndpoints
Do:
- $serviceName: $endpoint.serviceName
- If: $serviceName != null
Then:
- $serviceNameMap[$serviceName]: true
- $uniqueServiceNames: $serviceNameMap.keys()
- If: len($uniqueServiceNames) > 0
Then:
- $publicIPs: $.minionNodes.take($.nodeCount).select($.getIp())
- $resources: new(sys:Resources)
- $template: $resources.yaml('PatchServices.template').bind(dict(
services => $uniqueServiceNames,
publicIPs => $publicIPs
))
- $.masterNode.instance.agent.call($template, $resources)
deleteServices:
Arguments:
- applicationName:
Contract: $.string().notNull()
- podId:
Contract: $.string().notNull()
Body:
- $.serviceEndpoints: $.getAttr(serviceEndpoints, list())
- $resources: new(sys:Resources)
- $services: $.serviceEndpoints.where($.scope = internal and $.podId = $podId).select($.serviceName)
- $template: $resources.yaml('DeleteServices.template').bind(dict(
services => $services
))
- $.masterNode.instance.agent.call($template, $resources)
- $.serviceEndpoints: $.serviceEndpoints.where($.podId != $podId)
- $.setAttr(serviceEndpoints, $.serviceEndpoints)
_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
scaleNodesUp:
Usage: Action
Body:
- If: $.nodeCount < len($.minionNodes)
Then:
- $._environment.reporter.report($this, 'Scaling up Kubernetes cluster')
- $.nodeCount: $.nodeCount + 1
- $.deploy()
Else:
- $._environment.reporter.report($this, 'The maximum number of nodes has been reached')
scaleNodesDown:
Usage: Action
Body:
- If: $.nodeCount > 1
Then:
- $._environment.reporter.report($this, 'Scaling Kubernetes cluster down')
- $.nodeCount: $.nodeCount - 1
- $.deploy()
Else:
- $._environment.reporter.report($this, 'At least one node must be in cluster')
scaleGatewaysUp:
Usage: Action
Body:
- If: $.gatewayCount < len($.gatewayNodes)
Then:
- $._environment.reporter.report($this, 'Adding new gateway node')
- $.gatewayCount: $.gatewayCount + 1
- $.deploy()
Else:
- $._environment.reporter.report($this, 'The maximum number of nodes has been reached')
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')
scaleRc:
Arguments:
- rcName:
Contract: $.string().notNull()
- newSize:
Contract: $.int().notNull()
Body:
- $resources: new(sys:Resources)
- $template: $resources.yaml('ScaleRc.template').bind(dict(
rcName => $rcName,
newSize => $newSize
))
- $.masterNode.instance.agent.call($template, $resources)