-
Notifications
You must be signed in to change notification settings - Fork 0
/
setup-kubespray.sh
executable file
·422 lines (389 loc) · 10.8 KB
/
setup-kubespray.sh
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
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
#!/bin/sh
set -x
# Grab our libs
. "`dirname $0`/setup-lib.sh"
if [ -f $OURDIR/kubespray-done ]; then
exit 0
fi
logtstart "kubespray"
maybe_install_packages dma
maybe_install_packages mailutils
echo "$PFQDN" | $SUDO tee /etc/mailname
sleep 2
echo "Your ${EXPTTYPE} instance is setting up on $NFQDN ." \
| mail -s "${EXPTTYPE} Instance Setting Up" ${SWAPPER_EMAIL} &
# First, we need yq.
are_packages_installed yq
if [ ! $? -eq 1 ]; then
if [ ! "$ARCH" = "aarch64" ]; then
$SUDO apt-key adv --keyserver keyserver.ubuntu.com --recv-keys CC86BB64
$SUDO add-apt-repository -y ppa:rmescandon/yq
maybe_install_packages yq
fi
fi
which yq
if [ ! $? -eq 0 ]; then
fname=yq_linux_amd64
if [ "$ARCH" = "aarch64" ]; then
fname=yq_linux_arm64
fi
curl -L -o /tmp/$fname.tar.gz \
https://github.com/mikefarah/yq/releases/download/v4.13.2/$fname.tar.gz
tar -xzvf /tmp/$fname.tar.gz -C /tmp
chmod 755 /tmp/$fname
$SUDO mv /tmp/$fname /usr/local/bin/yq
fi
cd $OURDIR
if [ -e kubespray ]; then
rm -rf kubespray
fi
git clone $KUBESPRAYREPO kubespray
if [ -n "$KUBESPRAYVERSION" ]; then
cd kubespray && git checkout "$KUBESPRAYVERSION" && cd ..
fi
#
# Get Ansible and the kubespray python reqs installed.
#
maybe_install_packages ${PYTHON}
if [ $KUBESPRAYUSEVIRTUALENV -eq 1 ]; then
if [ -e $KUBESPRAY_VIRTUALENV ]; then
maybe_install_packages libffi-dev
. $KUBESPRAY_VIRTUALENV/bin/activate
else
maybe_install_packages virtualenv
mkdir -p $KUBESPRAY_VIRTUALENV
virtualenv $KUBESPRAY_VIRTUALENV --python=${PYTHON}
. $KUBESPRAY_VIRTUALENV/bin/activate
fi
$PIP install -r kubespray/requirements.txt
find $KUBESPRAY_VIRTUALENV -name ansible-playbook
if [ ! $? -eq 0 ]; then
$PIP install ansible==2.9
fi
else
maybe_install_packages software-properties-common ${PYTHONPKGPREFIX}-pip
$SUDO add-apt-repository --yes --update ppa:ansible/ansible
maybe_install_packages ansible libffi-dev
$PIP install -r kubespray/requirements.txt
fi
#
# Build the kubespray inventory file. The basic builder changes our
# hostname, and we don't want that. So do it manually. We generate
# .ini format because it's much simpler to do in shell.
#
INVDIR=$OURDIR/inventories/kubernetes
mkdir -p $INVDIR
cp -pR kubespray/inventory/sample/group_vars $INVDIR
mkdir -p $INVDIR/host_vars
HEAD_MGMT_IP=`getnodeip $HEAD $MGMTLAN`
HEAD_DATA_IP=`getnodeip $HEAD $DATALAN`
DATA_IP_REGEX=`getnetworkregex $HEAD $DATALAN`
INV=$INVDIR/inventory.ini
echo '[all]' > $INV
for node in $NODES ; do
mgmtip=`getnodeip $node $MGMTLAN`
dataip=`getnodeip $node $DATALAN`
if [ "$KUBEACCESSIP" = "mgmt" ]; then
accessip="$mgmtip"
else
accessip=`getcontrolip $node`
fi
echo "$node ansible_host=$mgmtip ip=$dataip access_ip=$accessip" >> $INV
touch $INVDIR/host_vars/$node.yml
done
# The first 2 nodes are kube-master.
echo '[kube-master]' >> $INV
for node in `echo $NODES | cut -d ' ' -f-2` ; do
echo "$node" >> $INV
done
# The first 3 nodes are etcd.
etcdcount=3
if [ $NODECOUNT -lt 3 ]; then
etcdcount=1
fi
echo '[etcd]' >> $INV
for node in `echo $NODES | cut -d ' ' -f-$etcdcount` ; do
echo "$node" >> $INV
done
# The last 2--N nodes are kube-node, unless there is only one node, or
# if user allows.
kubenodecount=2
if [ $KUBEALLWORKERS -eq 1 -o "$NODES" = `echo $NODES | cut -d ' ' -f2` ]; then
kubenodecount=1
fi
echo '[kube-node]' >> $INV
for node in `echo $NODES | cut -d ' ' -f${kubenodecount}-` ; do
echo "$node" >> $INV
done
cat <<EOF >> $INV
[k8s-cluster:children]
kube-master
kube-node
EOF
if [ $NODECOUNT -eq 1 ]; then
# We cannot use localhost; we have to use a dummy device, and that
# works fine. We need to fix things up because there is nothing in
# /etc/hosts, nor have ssh keys been scanned and placed in
# known_hosts.
ip=`getnodeip $HEAD $MGMTLAN`
nm=`getnetmask $MGMTLAN`
prefix=`netmask2prefix $nm`
cidr=$ip/$prefix
echo "$ip $HEAD $HEAD-$MGMTLAN" | $SUDO tee -a /etc/hosts
$SUDO ip link add type dummy name dummy0
$SUDO ip addr add $cidr dev dummy0
$SUDO ip link set dummy0 up
DISTRIB_MAJOR=`. /etc/lsb-release && echo $DISTRIB_RELEASE | cut -d. -f1`
if [ $DISTRIB_MAJOR -lt 18 ]; then
cat <<EOF | $SUDO tee /etc/network/interfaces.d/kube-single-node.conf
auto dummy0
iface dummy0 inet static
address $cidr
pre-up ip link add dummy0 type dummy
EOF
else
cat <<EOF | $SUDO tee /etc/systemd/network/dummy0.netdev
[NetDev]
Name=dummy0
Kind=dummy
EOF
cat <<EOF | $SUDO tee /etc/systemd/network/dummy0.network
[Match]
Name=dummy0
[Network]
DHCP=no
Address=$cidr
IPForward=yes
EOF
fi
ssh-keyscan $HEAD >> ~/.ssh/known_hosts
ssh-keyscan $ip >> ~/.ssh/known_hosts
fi
#
# Get our basic configuration into place.
#
OVERRIDES=$INVDIR/overrides.yml
cat <<EOF >> $OVERRIDES
override_system_hostname: false
disable_swap: true
ansible_python_interpreter: $PYTHONBIN
ansible_user: $SWAPPER
kube_apiserver_node_port_range: 2000-36767
kubeadm_enabled: true
dns_min_replicas: 1
dashboard_enabled: true
dashboard_token_ttl: 43200
EOF
if [ -n "${DOCKERVERSION}" ]; then
cat <<EOF >> $OVERRIDES
docker_version: ${DOCKERVERSION}
EOF
fi
if [ -n "${KUBEVERSION}" ]; then
cat <<EOF >> $OVERRIDES
kube_version: ${KUBEVERSION}
EOF
fi
if [ -n "$KUBEFEATUREGATES" ]; then
echo "kube_feature_gates: $KUBEFEATUREGATES" \
>> $OVERRIDES
fi
if [ -n "$KUBELETCUSTOMFLAGS" ]; then
echo "kubelet_custom_flags: $KUBELETCUSTOMFLAGS" \
>> $OVERRIDES
fi
if [ -n "$KUBELETMAXPODS" -a $KUBELETMAXPODS -gt 0 ]; then
echo "kubelet_max_pods: $KUBELETMAXPODS" \
>> $OVERRIDES
fi
if [ "$KUBENETWORKPLUGIN" = "calico" ]; then
cat <<EOF >> $OVERRIDES
kube_network_plugin: calico
docker_iptables_enabled: true
calico_ip_auto_method: "can-reach=$HEAD_DATA_IP"
EOF
elif [ "$KUBENETWORKPLUGIN" = "flannel" ]; then
cat <<EOF >> $OVERRIDES
kube_network_plugin: flannel
flannel_interface_regexp: '$DATA_IP_REGEX'
EOF
elif [ "$KUBENETWORKPLUGIN" = "weave" ]; then
cat <<EOF >> $OVERRIDES
kube_network_plugin: weave
EOF
elif [ "$KUBENETWORKPLUGIN" = "canal" ]; then
cat <<EOF >> $OVERRIDES
kube_network_plugin: canal
EOF
fi
if [ "$KUBEENABLEMULTUS" = "1" ]; then
cat <<EOF >> $OVERRIDES
kube_network_plugin_multus: true
multus_version: stable
EOF
fi
if [ "$KUBEPROXYMODE" = "iptables" ]; then
cat <<EOF >> $OVERRIDES
kube_proxy_mode: iptables
EOF
elif [ "$KUBEPROXYMODE" = "ipvs" ]; then
cat <<EOF >> $OVERRIDES
kube_proxy_mode: ipvs
EOF
fi
cat <<EOF >> $OVERRIDES
kube_pods_subnet: $KUBEPODSSUBNET
kube_service_addresses: $KUBESERVICEADDRESSES
EOF
#
# Enable helm.
#
echo "helm_enabled: true" >> $OVERRIDES
echo 'helm_stable_repo_url: "https://charts.helm.sh/stable"' >> $OVERRIDES
if [ -n "${HELMVERSION}" ]; then
echo "helm_version: ${HELMVERSION}" >> $OVERRIDES
fi
#
# Add a bunch of options most people will find useful.
#
DOCKOPTS='--insecure-registry={{ kube_service_addresses }} {{ docker_log_opts }}'
if [ "$MGMTLAN" = "$DATALANS" ]; then
DOCKOPTS="--insecure-registry=`getnodeip $HEAD $MGMTLAN`/`getnetmaskprefix $MGMTLAN` $DOCKOPTS"
else
for lan in $MGMTLAN $DATALANS ; do
DOCKOPTS="--insecure-registry=`getnodeip $HEAD $lan`/`getnetmaskprefix $lan` $DOCKOPTS"
done
fi
cat <<EOF >> $OVERRIDES
docker_dns_servers_strict: false
kubectl_localhost: true
kubeconfig_localhost: true
docker_options: "$DOCKOPTS ${DOCKEROPTIONS}"
metrics_server_enabled: true
kube_basic_auth: true
kube_api_pwd: "$ADMIN_PASS"
kube_users:
admin:
pass: "{{kube_api_pwd}}"
role: admin
groups:
- system:masters
EOF
#kube_api_anonymous_auth: false
#
# Add MetalLB support.
#
METALLB_PLAYBOOK=
if [ "$KUBEDOMETALLB" = "1" -a $PUBLICADDRCOUNT -gt 0 ]; then
if [ $KUBESPRAYVERSION = "release-2.13" ]; then
echo "kube_proxy_strict_arp: true" >> $INVDIR/group_vars/k8s-cluster/k8s-cluster.yml
METALLB_PLAYBOOK=contrib/metallb/metallb.yml
cat kubespray/contrib/metallb/roles/provision/defaults/main.yml | grep -v -- --- >> $OVERRIDES
echo "metallb:" >/tmp/metallb.yml
mi=0
for pip in $PUBLICADDRS ; do
if [ $mi -eq 0 ]; then
cat <<EOF >>/tmp/metallb.yml
ip_range:
- "$pip-$pip"
protocol: "layer2"
EOF
else
if [ $mi -eq 1 ]; then
cat <<EOF >>/tmp/metallb.yml
additional_address_pools:
EOF
fi
cat <<EOF >>/tmp/metallb.yml
kube_service_pool_$mi:
ip_range:
- "$pip-$pip"
protocol: "layer2"
auto_assign: true
EOF
fi
mi=`expr $mi + 1`
done
yq m --inplace --overwrite $OVERRIDES /tmp/metallb.yml
rm -f /tmp/metallb.yml
else
echo "kube_proxy_strict_arp: true" >> $OVERRIDES
cat <<EOF >> $OVERRIDES
metallb_enabled: true
metallb_speaker_enabled: true
EOF
mi=0
for pip in $PUBLICADDRS ; do
if [ $mi -eq 0 ]; then
cat <<EOF >> $OVERRIDES
metallb_ip_range:
- "$pip-$pip"
metallb_protocol: "layer2"
EOF
else
if [ $mi -eq 1 ]; then
cat <<EOF >> $OVERRIDES
metallb_additional_address_pools:
EOF
fi
cat <<EOF >> $OVERRIDES
kube_service_pool_$mi:
ip_range:
- "$pip-$pip"
protocol: "layer2"
auto_assign: true
EOF
fi
mi=`expr $mi + 1`
done
fi
fi
#
# Run ansible to build our kubernetes cluster.
#
cd $OURDIR/kubespray
ansible-playbook -i $INVDIR/inventory.ini \
cluster.yml $METALLB_PLAYBOOK -e @${OVERRIDES} -b -v
if [ ! $? -eq 0 ]; then
cd ..
echo "ERROR: ansible-playbook failed; check logfiles!"
exit 1
fi
cd ..
# kubespray sometimes installs python-is-python2; we can't allow that.
if [ -s $OURDIR/python-is-what ]; then
maybe_install_packages `cat $OURDIR/python-is-what`
fi
$SUDO rm -rf /root/.kube
$SUDO mkdir -p /root/.kube
$SUDO cp -p $INVDIR/artifacts/admin.conf /root/.kube/config
[ -d /users/$SWAPPER/.kube ] && rm -rf /users/$SWAPPER/.kube
mkdir -p /users/$SWAPPER/.kube
cp -p $INVDIR/artifacts/admin.conf /users/$SWAPPER/.kube/config
chown -R $SWAPPER /users/$SWAPPER/.kube
kubectl wait pod -n kube-system --for=condition=Ready --all
#
# If helm is not installed, do that manually. Seems that there is a
# kubespray bug (release-2.11) that causes this.
#
which helm
if [ ! $? -eq 0 -a -n "${HELM_VERSION}" ]; then
wget https://storage.googleapis.com/kubernetes-helm/helm-${HELM_VERSION}-linux-amd64.tar.gz
tar -xzvf helm-${HELM_VERSION}-linux-amd64.tar.gz
$SUDO mv linux-amd64/helm /usr/local/bin/helm
helm init --upgrade --force-upgrade --stable-repo-url "https://charts.helm.sh/stable"
kubectl create serviceaccount --namespace kube-system tiller
kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'
helm init --service-account tiller --upgrade
while [ 1 ]; do
helm ls
if [ $? -eq 0 ]; then
break
fi
sleep 4
done
kubectl wait pod -n kube-system --for=condition=Ready --all
fi
logtend "kubespray"
touch $OURDIR/kubespray-done