Skip to content

Commit 3241eab

Browse files
authored
Merge pull request docker-archive#446 from dgageot/improved-swarm
Improved Swarm Templates for GCP
2 parents 9c9fb6d + 705c1b9 commit 3241eab

File tree

13 files changed

+226
-97
lines changed

13 files changed

+226
-97
lines changed

gcp/Makefile

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
# Copyright 2016 Docker Inc. All rights reserved.
22

3-
auth:
4-
docker run -it --name gcloud-config google/cloud-sdk gcloud init
3+
GCLOUD_IMAGE_TAG = sha256:3a4e572df0c716196b3ffdeacaba3ebdd36f8cdfdac6d5ee4bd50cd405366736
4+
GCLOUD = docker run --rm -ti -v $(CURDIR)/configuration:/configuration --volumes-from gcloud-config google/cloud-sdk gcloud
5+
DEPLOYMENTS = $(GCLOUD) deployment-manager deployments
6+
7+
all: auth create
8+
9+
auth: revoke
10+
docker run -it --name gcloud-config google/cloud-sdk@$(GCLOUD_IMAGE_TAG) true
11+
$(GCLOUD) init
512

613
revoke:
7-
docker rm -f gcloud-config
14+
docker rm gcloud-config || true
815

916
create:
10-
docker run --rm -ti -v $(CURDIR)/configuration:/configuration --volumes-from gcloud-config google/cloud-sdk gcloud deployment-manager deployments create docker --config configuration/docker.yaml
17+
$(DEPLOYMENTS) create docker --config configuration/docker.yaml
1118

1219
describe:
13-
docker run --rm -ti -v $(CURDIR)/configuration:/configuration --volumes-from gcloud-config google/cloud-sdk gcloud deployment-manager deployments describe docker
20+
$(DEPLOYMENTS) describe docker
1421

1522
delete:
16-
docker run --rm -ti -v $(CURDIR)/configuration:/configuration --volumes-from gcloud-config google/cloud-sdk gcloud deployment-manager deployments delete docker -q
23+
$(DEPLOYMENTS) delete docker -q

gcp/README.md

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,12 @@ make revoke
2525
+ External load balancer
2626
+ Better UX
2727
+ Use Moby
28-
+ Logs
28+
+ Use Google Log driver
2929
+ Monitoring
30-
+ Configure project
31-
+ Multiple managers
32-
+ Different machine types for workers and managers
3330
+ SSH keys
3431
+ Additional swarm properties
3532
+ Publish the templates
3633
+ See how the Cloud Shell fits in the big picture
3734
+ DTR/DDC
38-
+ List the Apis we need
39-
+ Auto-enable all the Apis we need
35+
+ Have each worker increment a counter to be able to wait from outside
36+
+ Diagnostics

gcp/configuration/docker.yaml

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
# Copyright 2016 Docker Inc. All rights reserved.
22

33
imports:
4+
- path: templates/disk-image.py
45
- path: templates/swarm.py
56
- path: templates/manager.py
7+
- path: templates/managers.py
68
- path: templates/worker.py
79
- path: templates/workers.py
810
- path: templates/network.py
@@ -16,10 +18,3 @@ resources:
1618
type: runtimeconfig.v1beta1.config
1719
properties:
1820
config: swarm-config
19-
20-
- name: swarm-token
21-
type: runtimeconfig.v1beta1.variable
22-
properties:
23-
parent: $(ref.swarm-config.name)
24-
variable: token
25-
value: ""
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Copyright 2016 Docker Inc. All rights reserved.
2+
3+
"""Moby disk image used for all the instances."""
4+
5+
def GenerateConfig(context):
6+
resources = [{
7+
'name': context.env['name'],
8+
'type': 'compute.v1.image',
9+
'properties': {
10+
'family': 'docker',
11+
'rawDisk': {
12+
'source': 'https://storage.cloud.google.com/docker-image/docker.image.tar.gz'
13+
}
14+
}
15+
}]
16+
17+
return {'resources': resources}

gcp/configuration/templates/firewall.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,38 +6,39 @@ def GenerateConfig(context):
66
network = '$(ref.' + context.properties['network'] + '.selfLink)'
77

88
resources = [{
9-
'name': 'ssh',
9+
'name': 'allow-ssh',
1010
'type': 'compute.v1.firewall',
1111
'properties': {
1212
'network': network,
1313
'sourceRanges': ['0.0.0.0/0'],
1414
'allowed': [{
15-
'IPProtocol': 'TCP',
16-
'ports': [22]
15+
'IPProtocol': 'tcp',
16+
'ports': ['22']
1717
}]
1818
}
1919
},{
20-
'name': 'http',
20+
'name': 'allow-http',
2121
'type': 'compute.v1.firewall',
2222
'properties': {
2323
'network': network,
2424
'sourceRanges': ['0.0.0.0/0'],
2525
'allowed': [{
26-
'IPProtocol': 'TCP',
27-
'ports': [80]
28-
},{
29-
'IPProtocol': 'TCP',
30-
'ports': [443]
26+
'IPProtocol': 'tcp',
27+
'ports': ['80', '443']
3128
}]
3229
}
3330
},{
34-
'name': 'internal',
31+
'name': 'allow-internal',
3532
'type': 'compute.v1.firewall',
3633
'properties': {
3734
'network': network,
38-
'sourceTags': ['swarm'],
35+
'sourceRanges': ['10.128.0.0/9'],
3936
'allowed': [{
40-
'IPProtocol': 'TCP'
37+
'IPProtocol': 'tcp',
38+
"ports": ['0-65535']
39+
},{
40+
'IPProtocol': 'udp',
41+
"ports": ['0-65535']
4142
}]
4243
}
4344
}]

gcp/configuration/templates/manager.py

Lines changed: 69 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -6,68 +6,91 @@ def GenerateConfig(context):
66
project = context.env['project']
77
zone = context.properties['zone']
88
machineType = context.properties['machineType']
9+
image = context.properties['image']
910
network = '$(ref.' + context.properties['network'] + '.selfLink)'
1011

1112
script = r"""
1213
#!/bin/bash
1314
set -x
1415
1516
service docker start
16-
docker swarm init --advertise-addr ens4:2377 --listen-addr ens4:2377
17+
docker swarm init --advertise-addr eth0:2377 --listen-addr eth0:2377
1718
18-
TOKEN=$(docker swarm join-token worker -q)
1919
PROJECT=$(curl -s http://metadata.google.internal/computeMetadata/v1/project/project-id -H "Metadata-Flavor: Google")
2020
ACCESS_TOKEN=$(curl -s http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token -H "Metadata-Flavor: Google" | jq -r ".access_token")
2121
22-
curl -s -X PUT -H "Content-Type: application/json" -d "{\"text\":\"${TOKEN}\"}" https://runtimeconfig.googleapis.com/v1beta1/projects/${PROJECT}/configs/swarm-config/variables/token -H "Authorization":"Bearer ${ACCESS_TOKEN}"
23-
"""
22+
LEADER_IP=$(curl -s http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ip -H "Metadata-Flavor: Google")
23+
curl -f -s -X POST -H "Content-Type: application/json" -d "{'name':'projects/${PROJECT}/configs/swarm-config/variables/leader-ip','text':'${LEADER_IP}'}" https://runtimeconfig.googleapis.com/v1beta1/projects/${PROJECT}/configs/swarm-config/variables -H "Authorization":"Bearer ${ACCESS_TOKEN}"
2424
25-
outputs = [{
26-
'name': 'internalIP',
27-
'value': '$(ref.' + context.env['name'] + '.networkInterfaces[0].networkIP)'
28-
}]
25+
if [ $? -eq 0 ]; then
26+
echo "I'm a leader"
27+
28+
WORKER_TOKEN=$(docker swarm join-token worker -q)
29+
curl -s -X POST -H "Content-Type: application/json" -d "{'name':'projects/${PROJECT}/configs/swarm-config/variables/worker-token','text':'${WORKER_TOKEN}'}" https://runtimeconfig.googleapis.com/v1beta1/projects/${PROJECT}/configs/swarm-config/variables -H "Authorization":"Bearer ${ACCESS_TOKEN}"
30+
31+
MANAGER_TOKEN=$(docker swarm join-token manager -q)
32+
curl -s -X POST -H "Content-Type: application/json" -d "{'name':'projects/${PROJECT}/configs/swarm-config/variables/manager-token','text':'${MANAGER_TOKEN}'}" https://runtimeconfig.googleapis.com/v1beta1/projects/${PROJECT}/configs/swarm-config/variables -H "Authorization":"Bearer ${ACCESS_TOKEN}"
33+
else
34+
echo "I'm not a leader"
35+
36+
docker swarm leave --force
37+
38+
for i in $(seq 1 300); do
39+
LEADER_IP=$(curl -sSL "https://runtimeconfig.googleapis.com/v1beta1/projects/${PROJECT}/configs/swarm-config/variables/leader-ip" -H "Authorization":"Bearer ${ACCESS_TOKEN}" | jq -r ".text // empty")
40+
if [ ! -z "${LEADER_IP}" ]; then
41+
TOKEN=$(curl -sSL "https://runtimeconfig.googleapis.com/v1beta1/projects/${PROJECT}/configs/swarm-config/variables/manager-token" -H "Authorization":"Bearer ${ACCESS_TOKEN}" | jq -r ".text // empty")
42+
docker swarm join --token "${TOKEN}" "${LEADER_IP}" --advertise-addr eth0:2377 --listen-addr eth0:2377
43+
break
44+
fi
45+
46+
sleep 1
47+
done
48+
fi
49+
"""
2950

3051
resources = [{
3152
'name': context.env['name'],
32-
'type': 'compute.v1.instance',
53+
'type': 'compute.v1.instanceTemplate',
3354
'properties': {
34-
'zone': zone,
35-
'tags': {
36-
'items': ['swarm', 'swarm-manager']
37-
},
38-
'machineType': '/'.join(['projects', project,
39-
'zones', zone,
40-
'machineTypes', machineType]),
41-
'disks': [{
42-
'deviceName': 'boot',
43-
'type': 'PERSISTENT',
44-
'boot': True,
45-
'autoDelete': True,
46-
'initializeParams': {
47-
'sourceImage': '/'.join(['projects', project,
48-
'global',
49-
'images', 'docker2'])
50-
}
51-
}],
52-
'networkInterfaces': [{
53-
'network': network,
54-
'accessConfigs': [{
55-
'name': 'External NAT',
56-
'type': 'ONE_TO_ONE_NAT'
55+
'properties': {
56+
'zone': zone,
57+
'machineType': machineType,
58+
'tags': {
59+
'items': ['swarm', 'swarm-manager']
60+
},
61+
'disks': [{
62+
'deviceName': 'boot',
63+
'type': 'PERSISTENT',
64+
'boot': True,
65+
'autoDelete': True,
66+
'initializeParams': {
67+
'sourceImage': image
68+
}
69+
}],
70+
'networkInterfaces': [{
71+
'network': network,
72+
'accessConfigs': [{
73+
'name': 'External NAT',
74+
'type': 'ONE_TO_ONE_NAT'
75+
}]
76+
}],
77+
'metadata': {
78+
'items': [{
79+
'key': 'startup-script',
80+
'value': script
81+
}]
82+
},
83+
'scheduling': {
84+
'preemptible': False,
85+
'onHostMaintenance': 'TERMINATE',
86+
'automaticRestart': False
87+
},
88+
'serviceAccounts': [{
89+
'scopes': [
90+
'https://www.googleapis.com/auth/cloudruntimeconfig'
91+
]
5792
}]
58-
}],
59-
'metadata': {
60-
'items': [{
61-
'key': 'startup-script',
62-
'value': script
63-
}]
64-
},
65-
'serviceAccounts': [{
66-
'scopes': [
67-
'https://www.googleapis.com/auth/cloudruntimeconfig'
68-
]
69-
}]
93+
}
7094
}
7195
}]
72-
73-
return {'resources': resources, 'outputs': outputs}
96+
return {'resources': resources}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Copyright 2016 Docker Inc. All rights reserved.
2+
3+
"""Manager Instance Group."""
4+
5+
def GenerateConfig(context):
6+
project = context.env['project']
7+
zone = context.properties['zone']
8+
size = context.properties['size']
9+
template = context.properties['template']
10+
11+
resources = [{
12+
'name': context.env['name'],
13+
'type': 'compute.v1.instanceGroupManager',
14+
'properties': {
15+
'zone': zone,
16+
'instanceTemplate': '/'.join(['projects', project,
17+
'global',
18+
'instanceTemplates', template]),
19+
'baseInstanceName': context.env['name'],
20+
'targetSize': size,
21+
'autoHealingPolicies': [{
22+
'initialDelaySec': 300
23+
}]
24+
}
25+
}]
26+
return {'resources': resources}

gcp/configuration/templates/network.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ def GenerateConfig(context):
77
'name': context.env['name'],
88
'type': 'compute.v1.network',
99
'properties': {
10-
'IPv4Range': '10.0.0.1/16'
10+
'autoCreateSubnetworks': True
1111
}
1212
}]
1313
return {'resources': resources}

gcp/configuration/templates/swarm.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,33 +4,49 @@
44

55
def GenerateConfig(context):
66
zone = context.properties['zone']
7-
machineType = context.properties['machineType']
8-
size = context.properties['size']
7+
managerCount = context.properties['managerCount']
8+
managerMachineType = context.properties['managerMachineType']
9+
workerCount = context.properties['workerCount']
10+
workerMachineType = context.properties['workerMachineType']
11+
preemptible = context.properties['preemptible']
912

1013
resources = [{
14+
'name': 'docker',
15+
'type': 'templates/disk-image.py'
16+
}, {
1117
'name': 'manager',
1218
'type': 'templates/manager.py',
1319
'properties': {
1420
'zone': zone,
15-
'machineType': machineType,
21+
'machineType': managerMachineType,
22+
'image': '$(ref.docker.selfLink)',
1623
'network': 'swarm-network'
1724
}
25+
}, {
26+
'name': 'managers',
27+
'type': 'templates/managers.py',
28+
'properties': {
29+
'zone': zone,
30+
'template': '$(ref.manager.name)',
31+
'size': managerCount
32+
}
1833
}, {
1934
'name': 'worker',
2035
'type': 'templates/worker.py',
2136
'properties': {
2237
'zone': zone,
23-
'machineType': machineType,
38+
'machineType': workerMachineType,
39+
'preemptible': preemptible,
40+
'image': '$(ref.docker.selfLink)',
2441
'network': 'swarm-network',
25-
'managerIP': '$(ref.manager.internalIP)'
2642
}
2743
}, {
2844
'name': 'workers',
2945
'type': 'templates/workers.py',
3046
'properties': {
3147
'zone': zone,
3248
'template': '$(ref.worker.name)',
33-
'size': size
49+
'size': workerCount
3450
}
3551
}, {
3652
'name': 'swarm-network',

0 commit comments

Comments
 (0)