Files
k8s-docker-suite-app-murano/Kubernetes/KubernetesCluster/package/Classes/KubernetesCluster.yaml
Stan Lagun a855e9a879 Adds support for several applications in single Pod
Kubernetes doesn't allow to add containers to a Pod that
is already deployed. With this change old pods will be deleted
and either new pod created which will include new container
or Replication Controller will be modified (before Pod delete
so that updated Pods be created instead)

Also now Pods are created only when replica number set to 0.
Otherwise Pods created by ReplicationController alone.

Change-Id: I8552793f39083de47ad07e7013dedb72e0550885
Closes-Bug: #1444208
2015-04-15 00:28:31 +00:00

486 lines
15 KiB
YAML

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')