-
Notifications
You must be signed in to change notification settings - Fork 0
/
kube-local
executable file
·407 lines (360 loc) · 9.93 KB
/
kube-local
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
#!/bin/bash -e
API_PORT=8080
K8S_VERSION=v1.2.4
PREREQUISITES="docker docker-compose kubectl"
PROJECT_NAME=kz8slocal
DOCKER_COMPOSE="docker-compose --project-name $PROJECT_NAME"
KUBECTL="kubectl -s http://127.0.0.1:$API_PORT --context=\"\" --cluster=\"\""
DOCKER_HOST_IP=$(echo $DOCKER_HOST | awk -F'[/:]' '{print $4}')
: ${DOCKER_HOST_IP:=$(ifconfig docker0 \
| grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' \
| grep -Eo '([0-9]*\.){3}[0-9]*')}
DOCKER_MACHINE_ACTIVE=$(docker-machine active)
function version { cat <<EOF
$0 version 1.0.0
EOF
exit 0
}
function usage { cat <<EOF
Usage: $0 COMMAND
Run Kubernetes locally in docker.
Commands:
busybox Create busybox pod for testing
down Stop and remove a running local Kubernetes installation
events Receive real time events from containers
help Print usage
ip Print docker host ip address
kubeconfig Create kubeconfig file in current directory
kubectl Call kubectl with context for local Kubernetes
logs View output from containers
ps List containers
test Test cluster dns
up Create and start a local Kubernetes installation
version Print version information and quit
EOF
exit ${1:-0}
}
function assert-prereqs {
for prereq in $PREREQUISITES; do
command -v "$prereq" >/dev/null 2>&1 || { echo "✗ '$prereq' not found. Aborting!" >&2; exit 1; }
done
}
function docker-running {
docker info >/dev/null 2>&1 || { echo "✗ No running docker engine. Aborting!" >&2; exit 1; }
}
function compose-file { cat << EOF
kubernetes:
image: gcr.io/google_containers/hyperkube-amd64:$K8S_VERSION
net: host
pid: host
privileged: true
volumes:
- /:/rootfs:ro
- /sys:/sys:rw
- /var/lib/docker/:/var/lib/docker:rw
- /var/lib/kubelet/:/var/lib/kubelet:rw
- /var/run:/var/run:rw
command: >-
/hyperkube kubelet
--containerized
--hostname-override=127.0.0.1
--api-servers=http://localhost:8080
--config=/etc/kubernetes/manifests
--cluster-dns=10.0.0.10
--cluster-domain=cluster.local
--allow-privileged
--v=2
EOF
}
# TODO: change tunnel detection logic to account for docker-machine present on linux - eg ubuntu
function tunnel-up {
echo "❤ Checking for active docker-machine"
if ! hash docker-machine 2>/dev/null; then
echo "✓ docker-machine not found, skipping ssh tunnel setup"
return
fi
echo "❤ Setting up ssh tunnel to docker host on port $API_PORT"
local machine=$(docker-machine active)
if [ -z "$DOCKER_MACHINE_ACTIVE" ]; then
echo "✗ WARNING: ssh tunnel *not* enabled. Could not find active docker machine '$DOCKER_MACHINE_ACTIVE'" >&2
return
fi
echo "✓ Found active docker machine '$DOCKER_MACHINE_ACTIVE'"
if pgrep -f "ssh.*$API_PORT:localhost" > /dev/null; then
echo "✗ WARNING: There is an existing active ssh tunnel on port $API_PORT"
return
fi
echo "✓ No existing ssh tunnel found"
docker-machine ssh "$DOCKER_MACHINE_ACTIVE" -fNL "$API_PORT:localhost:$API_PORT"
echo "✓ Configured ssh tunnel on port $API_PORT to docker machine '$machine'"
}
function tunnel-down {
pkill -f "ssh.*docker.*$API_PORT:localhost:$API_PORT" ||:
}
function poll-for-k8s {
echo "❤ Commenced polling Kubernetes api-server for life, this may take a minute"
until curl -s http://localhost:$API_PORT
do echo "❤ Retrying Kubernetes api-server..." && sleep 7
done
curl -s http://localhost:$API_PORT/version
printf "\n"; echo "✓ Successfully connected to Kubernetes api-server"
}
function k8s-up {
echo "❤ Spinning up Kubernetes"
(compose-file) | $DOCKER_COMPOSE --file - up -d
echo "✓ Started Kubernetes"
}
function k8s-down {
echo "❤ Stopping docker-compose containers"
(compose-file) | $DOCKER_COMPOSE --file - stop
echo "❤ Removing docker-compose containers and volumes"
(compose-file) | $DOCKER_COMPOSE --file - rm --force -v
}
function remove-k8s-containers {
echo "❤ Looking for local Kubernetes containers to remove"
containers=$(docker ps --all --filter "name=k8s_" --quiet)
if [ -z "$containers" ]; then
echo "✗ WARNING: No kubernetes (k8s_*) containers to remove"
return
fi
docker stop $containers >/dev/null
docker rm --force --volumes $containers >/dev/null
echo "✓ Removed local Kubernetes containers"
}
function kube-system-namespace {
$KUBECTL create -f - <<EOF
kind: Namespace
apiVersion: v1
metadata:
name: kube-system
EOF
}
function kube-dns {
$KUBECTL --namespace=kube-system create -f - <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
name: kube-dns-v10
namespace: kube-system
labels:
k8s-app: kube-dns
version: v10
kubernetes.io/cluster-service: "true"
spec:
replicas: 1
selector:
k8s-app: kube-dns
version: v10
template:
metadata:
labels:
k8s-app: kube-dns
version: v10
kubernetes.io/cluster-service: "true"
spec:
containers:
- name: etcd
image: gcr.io/google_containers/etcd-amd64:2.2.1
resources:
# keep request = limit to keep this container in guaranteed class
limits:
cpu: 100m
memory: 50Mi
requests:
cpu: 100m
memory: 50Mi
command:
- /usr/local/bin/etcd
- -data-dir
- /var/etcd/data
- -listen-client-urls
- http://127.0.0.1:2379,http://127.0.0.1:4001
- -advertise-client-urls
- http://127.0.0.1:2379,http://127.0.0.1:4001
- -initial-cluster-token
- skydns-etcd
volumeMounts:
- name: etcd-storage
mountPath: /var/etcd/data
- name: kube2sky
image: gcr.io/google_containers/kube2sky:1.12
resources:
# keep request = limit to keep this container in guaranteed class
limits:
cpu: 100m
memory: 50Mi
requests:
cpu: 100m
memory: 50Mi
args:
# command = "/kube2sky"
- --domain=cluster.local
- name: skydns
image: gcr.io/google_containers/skydns:2015-10-13-8c72f8c
resources:
# keep request = limit to keep this container in guaranteed class
limits:
cpu: 100m
memory: 50Mi
requests:
cpu: 100m
memory: 50Mi
args:
# command = "/skydns"
- -machines=http://127.0.0.1:4001
- -addr=0.0.0.0:53
- -ns-rotate=false
- -domain=cluster.local
ports:
- containerPort: 53
name: dns
protocol: UDP
- containerPort: 53
name: dns-tcp
protocol: TCP
livenessProbe:
httpGet:
path: /healthz
port: 8080
scheme: HTTP
initialDelaySeconds: 30
timeoutSeconds: 5
readinessProbe:
httpGet:
path: /healthz
port: 8080
scheme: HTTP
initialDelaySeconds: 1
timeoutSeconds: 5
- name: healthz
image: gcr.io/google_containers/exechealthz:1.0
resources:
# keep request = limit to keep this container in guaranteed class
limits:
cpu: 10m
memory: 20Mi
requests:
cpu: 10m
memory: 20Mi
args:
- -cmd=nslookup kubernetes.default.svc.cluster.local 127.0.0.1 >/dev/null
- -port=8080
ports:
- containerPort: 8080
protocol: TCP
volumes:
- name: etcd-storage
emptyDir: {}
dnsPolicy: Default # Don't use cluster DNS.
---
apiVersion: v1
kind: Service
metadata:
name: kube-dns
namespace: kube-system
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: "true"
kubernetes.io/name: "KubeDNS"
spec:
selector:
k8s-app: kube-dns
clusterIP: 10.0.0.10
ports:
- name: dns
port: 53
protocol: UDP
- name: dns-tcp
port: 53
protocol: TCP
EOF
}
function kubeconfig { cat << EOF > kubeconfig
apiVersion: v1
kind: Config
clusters:
- cluster:
server: http://127.0.0.1:$API_PORT
name: local
contexts:
- context:
cluster: local
user: ""
name: local
current-context: local
preferences: {}
users: []
EOF
}
function busybox { $KUBECTL create -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: busybox
namespace: default
spec:
containers:
- image: busybox
command:
- sleep
- "3600"
imagePullPolicy: IfNotPresent
name: busybox
restartPolicy: Always
EOF
}
function nginx {
$KUBECTL run nginx --image=nginx --port=80
$KUBECTL expose deployment nginx --port=80
$KUBECTL get svc nginx --template={{.spec.clusterIP}}
}
function test {
busybox
echo -n "Waiting for busybox pod to enter 'Running' state"
until kubectl get pod busybox -o jsonpath='{.status.phase}' | grep Running >/dev/null 2>&1
do sleep 1 && echo -n .
done
echo .
$KUBECTL exec busybox -- nslookup kubernetes.default
$KUBECTL delete pod busybox
echo -n "Waiting for busybox pod to terminate"
until ! kubectl get pod busybox -o jsonpath='{.status.phase}' >/dev/null 2>&1
do sleep 1 && echo -n .
done
echo .
}
function clean-docker-machine { ssh $DOCKER_HOST_IP \
-ldocker \
-i ~/.docker/machine/machines/$DOCKER_MACHINE_ACTIVE/id_rsa \
-tt << EOF
sudo umount \$(cat /proc/mounts | grep /var/lib/kubelet | awk '{print \$2}')
sudo rm -rf /var/lib/kubelet
exit
EOF
}
# begin work
if [ -z "$1" ]; then usage; fi
assert-prereqs # check pre-reqs
docker-running # docker engine running ?
case "$1" in
busybox|kubeconfig|nginx|test) $1 ;;
down)
tunnel-down
k8s-down
remove-k8s-containers
clean-docker-machine
;;
events|logs|ps) (compose-file) | $DOCKER_COMPOSE --file - $1 ;;
help) usage ;;
ip) echo "✓ Docker host ip detected: $DOCKER_HOST_IP" ;;
kubectl) shift; $KUBECTL $@ ;;
up)
k8s-up
tunnel-up
poll-for-k8s
kube-system-namespace
kube-dns
;;
version) version ;;
*) usage ;;
esac