Skip to content

Commit 1cf73d1

Browse files
Keerthan Malamboersma
authored andcommitted
docs(k8s): add k8s integration documentation in customizing schedulers
1 parent 91484b1 commit 1cf73d1

8 files changed

Lines changed: 214 additions & 39 deletions

File tree

contrib/coreos/user-data.example

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,9 @@ write_files:
159159
- path: /etc/deis-release
160160
content: |
161161
DEIS_RELEASE=v1.8.0
162+
- path: /etc/k8environment
163+
content: |
164+
K8S_VERSION=v1.0.1
162165
- path: /etc/motd
163166
content: " \e[31m* * \e[34m* \e[32m***** \e[39mddddd eeeeeee iiiiiii ssss\n\e[31m* * \e[34m* * \e[32m* * \e[39md d e e i s s\n \e[31m* * \e[34m***** \e[32m***** \e[39md d e i s\n\e[32m***** \e[31m* * \e[34m* \e[39md d e i s\n\e[32m* * \e[31m* * \e[34m* * \e[39md d eee i sss\n\e[32m***** \e[31m* * \e[34m***** \e[39md d e i s\n \e[34m* \e[32m***** \e[31m* * \e[39md d e i s\n \e[34m* * \e[32m* * \e[31m* * \e[39md d e e i s s\n\e[34m***** \e[32m***** \e[31m* * \e[39mddddd eeeeeee iiiiiii ssss\n\n\e[39mWelcome to Deis\t\t\tPowered by Core\e[38;5;45mO\e[38;5;206mS\e[39m\n"
164167
- path: /etc/profile.d/nse-function.sh
@@ -350,4 +353,89 @@ write_files:
350353
/bin/openssl genrsa -out /opt/bin/kube-serviceaccount.key 2048 2>/dev/null
351354
etcdctl set /kube-serviceaccount < /opt/bin/kube-serviceaccount.key
352355
fi
356+
- path: /opt/bin/wupiao
357+
permissions: '0755'
358+
content: |
359+
#!/bin/bash
360+
# [w]ait [u]ntil [p]ort [i]s [a]ctually [o]pen
361+
[ -n "$1" ] && \
362+
until curl -o /dev/null -sIf http://${1}; do \
363+
sleep 1 && echo .;
364+
done;
365+
exit $?
366+
- path: /opt/bin/download-k8s-binary
367+
permissions: '0755'
368+
content: |
369+
#!/bin/bash
370+
371+
. /etc/k8environment
372+
373+
mkdir -p /opt/bin
374+
375+
FILE=$1
376+
if [ ! -f /opt/bin/$FILE ]; then
377+
curl -sSL -o /opt/bin/$FILE https://storage.googleapis.com/kubernetes-release/release/${K8S_VERSION}/bin/linux/amd64/$FILE
378+
chmod +x /opt/bin/$FILE
379+
else
380+
# we check the version of the binary
381+
INSTALLED_VERSION=$(/opt/bin/$FILE --version)
382+
MATCH=$(echo "${INSTALLED_VERSION}" | grep -c "${K8S_VERSION}")
383+
if [ $MATCH -eq 0 ]; then
384+
# the version is different
385+
curl -sSL -o /opt/bin/$FILE https://storage.googleapis.com/kubernetes-release/release/${K8S_VERSION}/bin/linux/amd64/$FILE
386+
chmod +x /opt/bin/$FILE
387+
fi
388+
fi
389+
- path: /opt/bin/kube-serviceaccount
390+
permissions: '0755'
391+
content: |
392+
#!/bin/bash
393+
394+
if etcdctl get /kube-serviceaccount >/dev/null 2>&1; then
395+
etcdctl get /kube-serviceaccount > /opt/bin/kube-serviceaccount.key
396+
else
397+
/bin/openssl genrsa -out /opt/bin/kube-serviceaccount.key 2048 2>/dev/null
398+
etcdctl set /kube-serviceaccount < /opt/bin/kube-serviceaccount.key
399+
fi
400+
- path: /opt/bin/scheduler-policy.json
401+
content: |
402+
{
403+
"kind": "Policy",
404+
"apiVersion": "v1",
405+
"predicates": [
406+
{
407+
"name": "PodFitsPorts"
408+
},
409+
{
410+
"name": "PodFitsResources"
411+
},
412+
{
413+
"name": "NoDiskConflict"
414+
},
415+
{
416+
"name": "MatchNodeSelector"
417+
},
418+
{
419+
"name": "HostName"
420+
}
421+
],
422+
"priorities": [
423+
{
424+
"name": "LeastRequestedPriority",
425+
"weight": 1
426+
},
427+
{
428+
"name": "BalancedResourceAllocation",
429+
"weight": 1
430+
},
431+
{
432+
"name": "ServiceSpreadingPriority",
433+
"weight": 2
434+
},
435+
{
436+
"name": "EqualPriority",
437+
"weight": 1
438+
}
439+
]
440+
}
353441
manage_etc_hosts: localhost

controller/scheduler/k8s.py

Lines changed: 68 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,15 @@
3939
"replicas":$num,
4040
"selector":{
4141
"name":"$id",
42-
"version":"$appversion"
42+
"version":"$appversion",
43+
"type":"$type"
4344
},
4445
"template":{
4546
"metadata":{
4647
"labels":{
4748
"name":"$id",
48-
"version":"$appversion"
49+
"version":"$appversion",
50+
"type":"$type"
4951
}
5052
},
5153
"spec":{
@@ -78,7 +80,8 @@
7880
}
7981
],
8082
"selector":{
81-
"name":"$label"
83+
"name":"$label",
84+
"type":"$type"
8285
}
8386
}
8487
}'''
@@ -101,7 +104,7 @@ def __init__(self, target, auth, options, pkey):
101104
self.apiversion = "v1"
102105
self.conn = httplib.HTTPConnection(self.target+":"+self.port)
103106

104-
def _get_old_rc(self, name):
107+
def _get_old_rc(self, name, app_type):
105108
con_app = httplib.HTTPConnection(self.target+":"+self.port)
106109
con_app.request('GET', '/api/'+self.apiversion +
107110
'/namespaces/default/replicationcontrollers')
@@ -118,7 +121,8 @@ def _get_old_rc(self, name):
118121
exists = False
119122
prev_rc = []
120123
for rc in parsed_json['items']:
121-
if 'name' in rc['metadata']['labels'] and name == rc['metadata']['labels']['name']:
124+
if('name' in rc['metadata']['labels'] and name == rc['metadata']['labels']['name'] and
125+
'type' in rc['spec']['selector'] and app_type == rc['spec']['selector']['type']):
122126
exists = True
123127
prev_rc = rc
124128
break
@@ -154,7 +158,8 @@ def _get_rc_(self, name):
154158

155159
def deploy(self, name, image, command, **kwargs):
156160
app_name = kwargs.get('aname', {})
157-
old_rc = self._get_old_rc(app_name)
161+
app_type = name.split(".")[1]
162+
old_rc = self._get_old_rc(app_name, app_type)
158163
new_rc = self._create_rc(name, image, command, **kwargs)
159164
desired = int(old_rc["spec"]["replicas"])
160165
old_rc_name = old_rc["metadata"]["name"]
@@ -257,12 +262,12 @@ def _scale_app(self, name, num):
257262
self._scale_rc(js_template)
258263

259264
def scale(self, name, image, command, **kwargs):
260-
rc_name = name.split(".")[0]
265+
rc_name = name.replace(".", "-")
261266
rc_name = rc_name.replace("_", "-")
262267
if not 200 <= self._get_rc_status(rc_name) <= 299:
263268
self.create(name, image, command, **kwargs)
264269
return
265-
name = name.split(".")[0]
270+
name = name.replace(".", "-")
266271
name = name.replace("_", "-")
267272
num = kwargs.get('num', {})
268273
js_template = self._get_rc_(name)
@@ -279,7 +284,7 @@ def _create_rc(self, name, image, command, **kwargs):
279284
app_name = kwargs.get('aname', {})
280285
app_type = name.split(".")[1]
281286
container_name = app_name+"-"+app_type
282-
name = name.split(".")[0]
287+
name = name.replace(".", "-")
283288
name = name.replace("_", "-")
284289
args = command.split()
285290

@@ -292,6 +297,7 @@ def _create_rc(self, name, image, command, **kwargs):
292297
l["image"] = self.registry+"/"+image
293298
l['num'] = num
294299
l['containername'] = container_name
300+
l['type'] = app_type
295301
template = string.Template(RC_TEMPLATE).substitute(l)
296302
js_template = json.loads(template)
297303
containers = js_template["spec"]["template"]["spec"]["containers"]
@@ -338,17 +344,36 @@ def _create_rc(self, name, image, command, **kwargs):
338344

339345
def create(self, name, image, command, **kwargs):
340346
self._create_rc(name, image, command, **kwargs)
341-
name = name.split(".")[0]
347+
app_type = name.split(".")[1]
348+
name = name.replace(".", "-")
342349
name = name.replace("_", "-")
343350
app_name = kwargs.get('aname', {})
344351
try:
345-
self._create_service(name, app_name)
352+
self._create_service(name, app_name, app_type)
346353
except Exception as e:
354+
self._scale_app(name, 0)
347355
self._delete_rc(name)
348356
err = '{} (create): {}'.format(name, e)
349357
raise RuntimeError(err)
350358

351-
def _create_service(self, name, app_name):
359+
def _get_service(self, name):
360+
con_get = httplib.HTTPConnection(self.target+":"+self.port)
361+
con_get.request('GET', '/api/'+self.apiversion+'/namespaces/default/services/'+name)
362+
resp = con_get.getresponse()
363+
reason = resp.reason
364+
status = resp.status
365+
data = resp.read()
366+
con_get.close()
367+
if not 200 <= status <= 299:
368+
errmsg = "Failed to get Service: {} {} - {}".format(
369+
status, reason, data)
370+
raise RuntimeError(errmsg)
371+
return (status, data, reason)
372+
373+
def _create_service(self, name, app_name, app_type):
374+
random.seed(app_name)
375+
app_id = random.randint(1, 100000)
376+
appname = "app-"+str(app_id)
352377
actual_pod = {}
353378
for _ in xrange(300):
354379
status, data, reason = self._get_pods()
@@ -370,9 +395,8 @@ def _create_service(self, name, app_name):
370395
l["version"] = self.apiversion
371396
l["label"] = app_name
372397
l["port"] = port
373-
random.seed(app_name)
374-
app_id = random.randint(1, 100000)
375-
l["name"] = "app-"+str(app_id)
398+
l['type'] = app_type
399+
l["name"] = appname
376400
template = string.Template(SERVICE_TEMPLATE).substitute(l)
377401
headers = {'Content-Type': 'application/json'}
378402
conn_serv = httplib.HTTPConnection(self.target+":"+self.port)
@@ -383,7 +407,27 @@ def _create_service(self, name, app_name):
383407
reason = resp.reason
384408
status = resp.status
385409
conn_serv.close()
386-
if not 200 <= status <= 299:
410+
if status == 409:
411+
status, data, reason = self._get_service(appname)
412+
srv = json.loads(data)
413+
if srv['spec']['selector']['type'] == 'web':
414+
return
415+
srv['spec']['selector']['type'] = app_type
416+
srv['spec']['ports'][0]['targetPort'] = port
417+
headers = {'Content-Type': 'application/json'}
418+
conn_scalepod = httplib.HTTPConnection(self.target+":"+self.port)
419+
conn_scalepod.request('PUT', '/api/'+self.apiversion+'/namespaces/default/' +
420+
'services/'+appname, headers=headers, body=json.dumps(srv))
421+
resp = conn_scalepod.getresponse()
422+
data = resp.read()
423+
reason = resp.reason
424+
status = resp.status
425+
conn_scalepod.close()
426+
if not 200 <= status <= 299:
427+
errmsg = "Failed to update the Service:{} {} {} - {}".format(
428+
name, status, reason, data)
429+
raise RuntimeError(errmsg)
430+
elif not 200 <= status <= 299:
387431
errmsg = "Failed to create Service:{} {} {} - {}".format(
388432
name, status, reason, data)
389433
raise RuntimeError(errmsg)
@@ -417,9 +461,10 @@ def _delete_rc(self, name):
417461

418462
def destroy(self, name):
419463
"""
420-
Destroy a container
464+
Destroy a the app
421465
"""
422-
name = name.split(".")[0]
466+
name = name.split(".")
467+
name = name[0]+'-'+name[1]
423468
name = name.replace("_", "-")
424469
appname = ''
425470
try:
@@ -454,7 +499,7 @@ def destroy(self, name):
454499
status = resp.status
455500
data = resp.read()
456501
con_serv.close()
457-
if not 200 <= status <= 299:
502+
if status != 404 and not 200 <= status <= 299:
458503
errmsg = "Failed to delete service:{} {} {} - {}".format(
459504
name, status, reason, data)
460505
raise RuntimeError(errmsg)
@@ -529,7 +574,7 @@ def _pod_log(self, name):
529574
return (status, data, reason)
530575

531576
def logs(self, name):
532-
name = name.split(".")[0]
577+
name = name.replace(".", "-")
533578
name = name.replace("_", "-")
534579
status, data, reason = self._get_pods()
535580
parsed_json = json.loads(data)
@@ -544,7 +589,7 @@ def run(self, name, image, entrypoint, command):
544589
"""
545590
Run a one-off command
546591
"""
547-
name = name.split(".")[0]
592+
name = name.replace(".", "-")
548593
name = name.replace("_", "-")
549594
l = {}
550595
l["id"] = name
@@ -603,7 +648,8 @@ def run(self, name, image, entrypoint, command):
603648

604649
def _get_pod_state(self, name):
605650
try:
606-
name = name.split(".")[0]
651+
name = name.split(".")
652+
name = name[0]+'-'+name[1]
607653
name = name.replace("_", "-")
608654
for _ in xrange(120):
609655
status, data, reason = self._get_pods()

deisctl/units/deis-kube-apiserver.service

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@ ExecStart=/bin/bash -c "/opt/bin/kube-apiserver \
1919
--kubelet_https=true \
2020
--secure_port=6443 \
2121
--service-cluster-ip-range=10.100.0.0/16 \
22-
--etcd_servers=http://$(curl -s 127.0.0.1:4001/v2/machines | sed 's/ //g') \
22+
--etcd_servers=$(curl -s 127.0.0.1:4001/v2/machines | sed 's/ //g') \
2323
--public_address_override=${COREOS_PRIVATE_IPV4} \
2424
--logtostderr=true \
2525
--runtime_config=api/v1"
26+
ExecStartPost=/bin/bash -c "fleetctl stop deis-kube-scheduler deis-kube-controller-manager deis-kube-kubelet deis-kube-proxy; sleep 2; fleetctl start deis-kube-scheduler deis-kube-controller-manager deis-kube-kubelet deis-kube-proxy"
2627
Restart=always
2728
RestartSec=10
2829
[Install]

deisctl/units/deis-kube-controller-manager.service

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ After=deis-kube-apiserver.service
66
[Service]
77
EnvironmentFile=/etc/environment
88
ExecStartPre=/bin/bash -c "/opt/bin/download-k8s-binary kube-controller-manager"
9+
ExecStartPre=/bin/bash -c "/opt/bin/wupiao $(/usr/bin/etcdctl get /deis/scheduler/k8s/master):8080"
910
ExecStart=/opt/bin/kube-controller-manager \
1011
--service_account_private_key_file=/opt/bin/kube-serviceaccount.key \
1112
--master=127.0.0.1:8080 \

deisctl/units/deis-kube-kubelet.service

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Documentation=https://github.com/GoogleCloudPlatform/kubernetes
44
[Service]
55
EnvironmentFile=/etc/environment
66
ExecStartPre=/bin/bash -c "/opt/bin/download-k8s-binary kubelet"
7+
ExecStartPre=/bin/bash -c "/opt/bin/wupiao $(/usr/bin/etcdctl get /deis/scheduler/k8s/master):8080"
78
ExecStartPre=/usr/bin/mkdir -p /opt/kubernetes/manifests/
89
ExecStart=/bin/bash -c '/opt/bin/kubelet --address=0.0.0.0 --port=10250 --hostname_override=$COREOS_PRIVATE_IPV4 --api_servers=`/usr/bin/etcdctl get /deis/scheduler/k8s/master`:8080 --allow_privileged=true --cluster_dns=10.100.0.10 --cluster_domain=cluster.local --logtostderr=true --config=/opt/kubernetes/manifests/ --healthz_bind_address=0.0.0.0 --healthz_port=10248'
910
Restart=always

deisctl/units/deis-kube-proxy.service

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Documentation=https://github.com/GoogleCloudPlatform/kubernetes
44
[Service]
55
EnvironmentFile=/etc/environment
66
ExecStartPre=/bin/bash -c "/opt/bin/download-k8s-binary kube-proxy"
7+
ExecStartPre=/bin/bash -c "/opt/bin/wupiao $(/usr/bin/etcdctl get /deis/scheduler/k8s/master):8080"
78
ExecStart=/bin/bash -c '/opt/bin/kube-proxy --master=`/usr/bin/etcdctl get /deis/scheduler/k8s/master`:8080 --logtostderr=true'
89
Restart=always
910
RestartSec=10

deisctl/units/deis-kube-scheduler.service

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ After=deis-kube-apiserver.service
66
[Service]
77
EnvironmentFile=/etc/environment
88
ExecStartPre=/bin/bash -c "/opt/bin/download-k8s-binary kube-scheduler"
9+
ExecStartPre=/bin/bash -c "/opt/bin/wupiao $(/usr/bin/etcdctl get /deis/scheduler/k8s/master):8080"
910
ExecStart=/opt/bin/kube-scheduler \
10-
--master=127.0.0.1:8080
11+
--master=127.0.0.1:8080 \
12+
--policy-config-file=/opt/bin/scheduler-policy.json
1113
Restart=always
1214
RestartSec=10
1315
[X-Fleet]

0 commit comments

Comments
 (0)