util.sh 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992
  1. #!/bin/bash
  2. # Copyright 2015 The Kubernetes Authors.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. # A library of helper functions that each provider hosting Kubernetes
  16. # must implement to use cluster/kube-*.sh scripts.
  17. set -e
  18. SSH_OPTS="-oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -oLogLevel=ERROR -C"
  19. MASTER=""
  20. MASTER_IP=""
  21. NODE_IPS=""
  22. # Assumed Vars:
  23. # KUBE_ROOT
  24. function test-build-release() {
  25. # Make a release
  26. "${KUBE_ROOT}/build/release.sh"
  27. }
  28. # From user input set the necessary k8s and etcd configuration information
  29. function setClusterInfo() {
  30. # Initialize NODE_IPS in setClusterInfo function
  31. # NODE_IPS is defined as a global variable, and is concatenated with other nodeIP
  32. # When setClusterInfo is called for many times, this could cause potential problems
  33. # Such as, you will have NODE_IPS=192.168.0.2,192.168.0.3,192.168.0.2,192.168.0.3,
  34. # which is obviously wrong.
  35. NODE_IPS=""
  36. local ii=0
  37. for i in $nodes; do
  38. nodeIP=${i#*@}
  39. if [[ "${roles_array[${ii}]}" == "ai" ]]; then
  40. MASTER_IP=$nodeIP
  41. MASTER=$i
  42. NODE_IPS="$nodeIP"
  43. elif [[ "${roles_array[${ii}]}" == "a" ]]; then
  44. MASTER_IP=$nodeIP
  45. MASTER=$i
  46. elif [[ "${roles_array[${ii}]}" == "i" ]]; then
  47. if [[ -z "${NODE_IPS}" ]];then
  48. NODE_IPS="$nodeIP"
  49. else
  50. NODE_IPS="$NODE_IPS,$nodeIP"
  51. fi
  52. else
  53. echo "unsupported role for ${i}. please check"
  54. exit 1
  55. fi
  56. ((ii=ii+1))
  57. done
  58. }
  59. # Sanity check on $CNI_PLUGIN_CONF and $CNI_PLUGIN_EXES
  60. function check-CNI-config() {
  61. if [ -z "$CNI_PLUGIN_CONF" ] && [ -n "$CNI_PLUGIN_EXES" ]; then
  62. echo "Warning: CNI_PLUGIN_CONF is emtpy but CNI_PLUGIN_EXES is not (it is $CNI_PLUGIN_EXES); Flannel will be used" >& 2
  63. elif [ -n "$CNI_PLUGIN_CONF" ] && [ -z "$CNI_PLUGIN_EXES" ]; then
  64. echo "Warning: CNI_PLUGIN_EXES is empty but CNI_PLUGIN_CONF is not (it is $CNI_PLUGIN_CONF); Flannel will be used" & 2
  65. elif [ -n "$CNI_PLUGIN_CONF" ] && [ -n "$CNI_PLUGIN_EXES" ]; then
  66. local problems=0
  67. if ! [ -r "$CNI_PLUGIN_CONF" ]; then
  68. echo "ERROR: CNI_PLUGIN_CONF is set to $CNI_PLUGIN_CONF but that is not a readable existing file!" >& 2
  69. let problems=1
  70. fi
  71. local ii=0
  72. for exe in $CNI_PLUGIN_EXES; do
  73. if ! [ -x "$exe" ]; then
  74. echo "ERROR: CNI_PLUGIN_EXES[$ii], which is $exe, is not an existing executable file!" >& 2
  75. let problems=problems+1
  76. fi
  77. let ii=ii+1
  78. done
  79. if (( problems > 0 )); then
  80. exit 1
  81. fi
  82. fi
  83. }
  84. # Verify ssh prereqs
  85. function verify-prereqs() {
  86. local rc
  87. rc=0
  88. ssh-add -L 1> /dev/null 2> /dev/null || rc="$?"
  89. # "Could not open a connection to your authentication agent."
  90. if [[ "${rc}" -eq 2 ]]; then
  91. eval "$(ssh-agent)" > /dev/null
  92. trap-add "kill ${SSH_AGENT_PID}" EXIT
  93. fi
  94. rc=0
  95. ssh-add -L 1> /dev/null 2> /dev/null || rc="$?"
  96. # "The agent has no identities."
  97. if [[ "${rc}" -eq 1 ]]; then
  98. # Try adding one of the default identities, with or without passphrase.
  99. ssh-add || true
  100. fi
  101. # Expect at least one identity to be available.
  102. if ! ssh-add -L 1> /dev/null 2> /dev/null; then
  103. echo "Could not find or add an SSH identity."
  104. echo "Please start ssh-agent, add your identity, and retry."
  105. exit 1
  106. fi
  107. }
  108. # Check if /tmp is mounted noexec
  109. function check-tmp-noexec() {
  110. if ssh $SSH_OPTS "$MASTER" "grep '/tmp' /proc/mounts | grep -q 'noexec'" >/dev/null 2>&1; then
  111. echo "/tmp is mounted noexec on $MASTER_IP, deploying master failed"
  112. exit 1
  113. fi
  114. }
  115. # Install handler for signal trap
  116. function trap-add() {
  117. local handler="$1"
  118. local signal="${2-EXIT}"
  119. local cur
  120. cur="$(eval "sh -c 'echo \$3' -- $(trap -p ${signal})")"
  121. if [[ -n "${cur}" ]]; then
  122. handler="${cur}; ${handler}"
  123. fi
  124. trap "${handler}" ${signal}
  125. }
  126. function verify-cluster() {
  127. local ii=0
  128. for i in ${nodes}
  129. do
  130. if [ "${roles_array[${ii}]}" == "a" ]; then
  131. verify-master
  132. elif [ "${roles_array[${ii}]}" == "i" ]; then
  133. verify-node "$i"
  134. elif [ "${roles_array[${ii}]}" == "ai" ]; then
  135. verify-master
  136. verify-node "$i"
  137. else
  138. echo "unsupported role for ${i}. please check"
  139. exit 1
  140. fi
  141. ((ii=ii+1))
  142. done
  143. }
  144. function verify-master() {
  145. # verify master has all required daemons
  146. echo -n "Validating master"
  147. local -a required_daemon=("kube-apiserver" "kube-controller-manager" "kube-scheduler")
  148. local validated="1"
  149. local try_count=1
  150. local max_try_count=30
  151. until [[ "$validated" == "0" ]]; do
  152. validated="0"
  153. local daemon
  154. for daemon in "${required_daemon[@]}"; do
  155. ssh $SSH_OPTS "$MASTER" "pgrep -f '${daemon}'" >/dev/null 2>&1 || {
  156. echo -n "."
  157. validated="1"
  158. ((try_count=try_count+1))
  159. if [[ ${try_count} -gt ${max_try_count} ]]; then
  160. echo -e "\nWarning: Process '${daemon}' failed to run on ${MASTER}, please check.\n"
  161. exit 1
  162. fi
  163. sleep 2
  164. }
  165. done
  166. done
  167. echo
  168. }
  169. function verify-node() {
  170. # verify node has all required daemons
  171. echo -n "Validating ${1}"
  172. local -a required_daemon=("kube-proxy" "kubelet" "docker")
  173. local validated="1"
  174. local try_count=1
  175. local max_try_count=30
  176. until [[ "$validated" == "0" ]]; do
  177. validated="0"
  178. local daemon
  179. for daemon in "${required_daemon[@]}"; do
  180. ssh $SSH_OPTS "$1" "pgrep -f '${daemon}'" >/dev/null 2>&1 || {
  181. echo -n "."
  182. validated="1"
  183. ((try_count=try_count+1))
  184. if [[ ${try_count} -gt ${max_try_count} ]]; then
  185. echo -e "\nWarning: Process '${daemon}' failed to run on ${1}, please check.\n"
  186. exit 1
  187. fi
  188. sleep 2
  189. }
  190. done
  191. done
  192. echo
  193. }
  194. # Create ~/kube/default/etcd with proper contents.
  195. # $1: The one IP address where the etcd leader listens.
  196. function create-etcd-opts() {
  197. cat <<EOF > ~/kube/default/etcd
  198. ETCD_OPTS="\
  199. -name infra\
  200. -listen-client-urls http://127.0.0.1:4001,http://${1}:4001\
  201. -advertise-client-urls http://${1}:4001"
  202. EOF
  203. }
  204. # Create ~/kube/default/kube-apiserver with proper contents.
  205. # $1: CIDR block for service addresses.
  206. # $2: Admission Controllers to invoke in the API server.
  207. # $3: A port range to reserve for services with NodePort visibility.
  208. # $4: The IP address on which to advertise the apiserver to members of the cluster.
  209. # $5: Tells kube-api to run in privileged mode
  210. function create-kube-apiserver-opts() {
  211. cat <<EOF > ~/kube/default/kube-apiserver
  212. KUBE_APISERVER_OPTS="\
  213. --insecure-bind-address=0.0.0.0\
  214. --insecure-port=8080\
  215. --etcd-servers=http://127.0.0.1:4001\
  216. --logtostderr=true\
  217. --service-cluster-ip-range=${1}\
  218. --admission-control=${2}\
  219. --service-node-port-range=${3}\
  220. --advertise-address=${4}\
  221. --allow-privileged=${5}\
  222. --client-ca-file=/srv/kubernetes/ca.crt\
  223. --tls-cert-file=/srv/kubernetes/server.cert\
  224. --tls-private-key-file=/srv/kubernetes/server.key"
  225. EOF
  226. }
  227. # Create ~/kube/default/kube-controller-manager with proper contents.
  228. function create-kube-controller-manager-opts() {
  229. cat <<EOF > ~/kube/default/kube-controller-manager
  230. KUBE_CONTROLLER_MANAGER_OPTS="\
  231. --master=127.0.0.1:8080\
  232. --root-ca-file=/srv/kubernetes/ca.crt\
  233. --service-account-private-key-file=/srv/kubernetes/server.key\
  234. --logtostderr=true"
  235. EOF
  236. }
  237. # Create ~/kube/default/kube-scheduler with proper contents.
  238. function create-kube-scheduler-opts() {
  239. cat <<EOF > ~/kube/default/kube-scheduler
  240. KUBE_SCHEDULER_OPTS="\
  241. --logtostderr=true\
  242. --master=127.0.0.1:8080"
  243. EOF
  244. }
  245. # Create ~/kube/default/kubelet with proper contents.
  246. # $1: The hostname or IP address by which the kubelet will identify itself.
  247. # $2: The one hostname or IP address at which the API server is reached (insecurely).
  248. # $3: If non-empty then the DNS server IP to configure in each pod.
  249. # $4: If non-empty then added to each pod's domain search list.
  250. # $5: Pathname of the kubelet config file or directory.
  251. # $6: Whether or not we run kubelet in privileged mode
  252. # $7: If empty then flannel is used otherwise CNI is used.
  253. function create-kubelet-opts() {
  254. if [ -n "$7" ] ; then
  255. cni_opts=" --network-plugin=cni --network-plugin-dir=/etc/cni/net.d"
  256. else
  257. cni_opts=""
  258. fi
  259. cat <<EOF > ~/kube/default/kubelet
  260. KUBELET_OPTS="\
  261. --hostname-override=${1} \
  262. --api-servers=http://${2}:8080 \
  263. --logtostderr=true \
  264. --cluster-dns=${3} \
  265. --cluster-domain=${4} \
  266. --config=${5} \
  267. --allow-privileged=${6}
  268. $cni_opts"
  269. EOF
  270. }
  271. # Create ~/kube/default/kube-proxy with proper contents.
  272. # $1: The hostname or IP address by which the node is identified.
  273. # $2: The one hostname or IP address at which the API server is reached (insecurely).
  274. function create-kube-proxy-opts() {
  275. cat <<EOF > ~/kube/default/kube-proxy
  276. KUBE_PROXY_OPTS="\
  277. --hostname-override=${1} \
  278. --master=http://${2}:8080 \
  279. --logtostderr=true \
  280. ${3}"
  281. EOF
  282. }
  283. # Create ~/kube/default/flanneld with proper contents.
  284. # $1: The one hostname or IP address at which the etcd leader listens.
  285. # $2: The IP address or network interface for the local Flannel daemon to use
  286. function create-flanneld-opts() {
  287. cat <<EOF > ~/kube/default/flanneld
  288. FLANNEL_OPTS="--etcd-endpoints=http://${1}:4001 \
  289. --ip-masq \
  290. --iface=${2}"
  291. EOF
  292. }
  293. # Detect the IP for the master
  294. #
  295. # Assumed vars:
  296. # MASTER_NAME
  297. # Vars set:
  298. # KUBE_MASTER_IP
  299. function detect-master() {
  300. source "${KUBE_CONFIG_FILE}"
  301. setClusterInfo
  302. export KUBE_MASTER="${MASTER}"
  303. export KUBE_MASTER_IP="${MASTER_IP}"
  304. echo "Using master ${MASTER_IP}"
  305. }
  306. # Detect the information about the nodes
  307. #
  308. # Assumed vars:
  309. # nodes
  310. # Vars set:
  311. # KUBE_NODE_IP_ADDRESS (array)
  312. function detect-nodes() {
  313. source "${KUBE_CONFIG_FILE}"
  314. KUBE_NODE_IP_ADDRESSES=()
  315. setClusterInfo
  316. local ii=0
  317. for i in ${nodes}
  318. do
  319. if [ "${roles_array[${ii}]}" == "i" ] || [ "${roles_array[${ii}]}" == "ai" ]; then
  320. KUBE_NODE_IP_ADDRESSES+=("${i#*@}")
  321. fi
  322. ((ii=ii+1))
  323. done
  324. if [[ -z "${KUBE_NODE_IP_ADDRESSES[@]}" ]]; then
  325. echo "Could not detect Kubernetes node nodes.\
  326. Make sure you've launched a cluster with 'kube-up.sh'" >&2
  327. exit 1
  328. fi
  329. }
  330. # Instantiate a kubernetes cluster on ubuntu
  331. function kube-up() {
  332. export KUBE_CONFIG_FILE=${KUBE_CONFIG_FILE:-${KUBE_ROOT}/cluster/ubuntu/config-default.sh}
  333. source "${KUBE_CONFIG_FILE}"
  334. # downloading tarball release
  335. "${KUBE_ROOT}/cluster/ubuntu/download-release.sh"
  336. # Fetch the hacked easyrsa that make-ca-cert.sh will use
  337. curl -L -O https://storage.googleapis.com/kubernetes-release/easy-rsa/easy-rsa.tar.gz > /dev/null 2>&1
  338. if ! check-CNI-config; then
  339. return
  340. fi
  341. setClusterInfo
  342. local ii=0
  343. for i in ${nodes}
  344. do
  345. {
  346. if [ "${roles_array[${ii}]}" == "a" ]; then
  347. provision-master
  348. elif [ "${roles_array[${ii}]}" == "ai" ]; then
  349. provision-masterandnode
  350. elif [ "${roles_array[${ii}]}" == "i" ]; then
  351. provision-node "$i"
  352. else
  353. echo "unsupported role for ${i}. Please check"
  354. exit 1
  355. fi
  356. }
  357. ((ii=ii+1))
  358. done
  359. wait
  360. export KUBECTL_PATH="${KUBE_ROOT}/cluster/ubuntu/binaries/kubectl"
  361. verify-cluster
  362. detect-master
  363. export CONTEXT="ubuntu"
  364. export KUBE_SERVER="http://${KUBE_MASTER_IP}:8080"
  365. source "${KUBE_ROOT}/cluster/common.sh"
  366. # set kubernetes user and password
  367. load-or-gen-kube-basicauth
  368. create-kubeconfig
  369. }
  370. function provision-master() {
  371. echo -e "\nDeploying master on machine ${MASTER_IP}"
  372. check-tmp-noexec
  373. ssh $SSH_OPTS "$MASTER" "mkdir -p ~/kube/default"
  374. # copy the binaries and scripts to the ~/kube directory on the master
  375. scp -r $SSH_OPTS \
  376. saltbase/salt/generate-cert/make-ca-cert.sh \
  377. easy-rsa.tar.gz \
  378. ubuntu/reconfDocker.sh \
  379. "${KUBE_CONFIG_FILE}" \
  380. ubuntu/util.sh \
  381. ubuntu/master/* \
  382. ubuntu/binaries/master/ \
  383. "${MASTER}:~/kube"
  384. if [ -z "$CNI_PLUGIN_CONF" ] || [ -z "$CNI_PLUGIN_EXES" ]; then
  385. # Flannel is being used: copy the flannel binaries and scripts, set reconf flag
  386. scp -r $SSH_OPTS ubuntu/master-flannel/* "${MASTER}:~/kube"
  387. NEED_RECONFIG_DOCKER=true
  388. else
  389. # CNI is being used: set reconf flag
  390. NEED_RECONFIG_DOCKER=false
  391. fi
  392. EXTRA_SANS=(
  393. IP:$MASTER_IP
  394. IP:${SERVICE_CLUSTER_IP_RANGE%.*}.1
  395. DNS:kubernetes
  396. DNS:kubernetes.default
  397. DNS:kubernetes.default.svc
  398. DNS:kubernetes.default.svc.cluster.local
  399. )
  400. EXTRA_SANS=$(echo "${EXTRA_SANS[@]}" | tr ' ' ,)
  401. BASH_DEBUG_FLAGS=""
  402. if [[ "$DEBUG" == "true" ]] ; then
  403. BASH_DEBUG_FLAGS="set -x"
  404. fi
  405. # remote login to MASTER and configue k8s master
  406. ssh $SSH_OPTS -t "${MASTER}" "
  407. set +e
  408. ${BASH_DEBUG_FLAGS}
  409. source ~/kube/util.sh
  410. setClusterInfo
  411. create-etcd-opts '${MASTER_IP}'
  412. create-kube-apiserver-opts \
  413. '${SERVICE_CLUSTER_IP_RANGE}' \
  414. '${ADMISSION_CONTROL}' \
  415. '${SERVICE_NODE_PORT_RANGE}' \
  416. '${MASTER_IP}' \
  417. '${ALLOW_PRIVILEGED}'
  418. create-kube-controller-manager-opts '${NODE_IPS}'
  419. create-kube-scheduler-opts
  420. create-flanneld-opts '127.0.0.1' '${MASTER_IP}'
  421. FLANNEL_OTHER_NET_CONFIG='${FLANNEL_OTHER_NET_CONFIG}' sudo -E -p '[sudo] password to start master: ' -- /bin/bash -ce '
  422. ${BASH_DEBUG_FLAGS}
  423. cp ~/kube/default/* /etc/default/
  424. cp ~/kube/init_conf/* /etc/init/
  425. cp ~/kube/init_scripts/* /etc/init.d/
  426. groupadd -f -r kube-cert
  427. ${PROXY_SETTING} DEBUG='${DEBUG}' ~/kube/make-ca-cert.sh \"${MASTER_IP}\" \"${EXTRA_SANS}\"
  428. mkdir -p /opt/bin/
  429. cp ~/kube/master/* /opt/bin/
  430. service etcd start
  431. if ${NEED_RECONFIG_DOCKER}; then FLANNEL_NET=\"${FLANNEL_NET}\" KUBE_CONFIG_FILE=\"${KUBE_CONFIG_FILE}\" DOCKER_OPTS=\"${DOCKER_OPTS}\" ~/kube/reconfDocker.sh a; fi
  432. '" || {
  433. echo "Deploying master on machine ${MASTER_IP} failed"
  434. exit 1
  435. }
  436. }
  437. function provision-node() {
  438. echo -e "\nDeploying node on machine ${1#*@}"
  439. ssh $SSH_OPTS $1 "mkdir -p ~/kube/default"
  440. # copy the binaries and scripts to the ~/kube directory on the node
  441. scp -r $SSH_OPTS \
  442. "${KUBE_CONFIG_FILE}" \
  443. ubuntu/util.sh \
  444. ubuntu/reconfDocker.sh \
  445. ubuntu/minion/* \
  446. ubuntu/binaries/minion \
  447. "${1}:~/kube"
  448. if [ -z "$CNI_PLUGIN_CONF" ] || [ -z "$CNI_PLUGIN_EXES" ]; then
  449. # Prep for Flannel use: copy the flannel binaries and scripts, set reconf flag
  450. scp -r $SSH_OPTS ubuntu/minion-flannel/* "${1}:~/kube"
  451. SERVICE_STARTS="service flanneld start"
  452. NEED_RECONFIG_DOCKER=true
  453. CNI_PLUGIN_CONF=''
  454. else
  455. # Prep for CNI use: copy the CNI config and binaries, adjust upstart config, set reconf flag
  456. ssh $SSH_OPTS "${1}" "rm -rf tmp-cni; mkdir -p tmp-cni/exes tmp-cni/conf"
  457. scp $SSH_OPTS "$CNI_PLUGIN_CONF" "${1}:tmp-cni/conf/"
  458. scp -p $SSH_OPTS $CNI_PLUGIN_EXES "${1}:tmp-cni/exes/"
  459. ssh $SSH_OPTS -t "${1}" '
  460. sudo -p "[sudo] password to prep node %h: " -- /bin/bash -ce "
  461. mkdir -p /opt/cni/bin /etc/cni/net.d
  462. cp ~$(id -un)/tmp-cni/conf/* /etc/cni/net.d/
  463. cp --preserve=mode ~$(id -un)/tmp-cni/exes/* /opt/cni/bin/
  464. '"sed -i.bak -e 's/start on started flanneld/start on started ${CNI_KUBELET_TRIGGER}/' -e 's/stop on stopping flanneld/stop on stopping ${CNI_KUBELET_TRIGGER}/' "'~$(id -un)/kube/init_conf/kubelet.conf
  465. '"sed -i.bak -e 's/start on started flanneld/start on started networking/' -e 's/stop on stopping flanneld/stop on stopping networking/' "'~$(id -un)/kube/init_conf/kube-proxy.conf
  466. "'
  467. SERVICE_STARTS='service kubelet start
  468. service kube-proxy start'
  469. NEED_RECONFIG_DOCKER=false
  470. fi
  471. BASH_DEBUG_FLAGS=""
  472. if [[ "$DEBUG" == "true" ]] ; then
  473. BASH_DEBUG_FLAGS="set -x"
  474. fi
  475. # remote login to node and configue k8s node
  476. ssh $SSH_OPTS -t "$1" "
  477. set +e
  478. ${BASH_DEBUG_FLAGS}
  479. source ~/kube/util.sh
  480. setClusterInfo
  481. create-kubelet-opts \
  482. '${1#*@}' \
  483. '${MASTER_IP}' \
  484. '${DNS_SERVER_IP}' \
  485. '${DNS_DOMAIN}' \
  486. '${KUBELET_CONFIG}' \
  487. '${ALLOW_PRIVILEGED}' \
  488. '${CNI_PLUGIN_CONF}'
  489. create-kube-proxy-opts \
  490. '${1#*@}' \
  491. '${MASTER_IP}' \
  492. '${KUBE_PROXY_EXTRA_OPTS}'
  493. create-flanneld-opts '${MASTER_IP}' '${1#*@}'
  494. sudo -E -p '[sudo] password to start node: ' -- /bin/bash -ce '
  495. ${BASH_DEBUG_FLAGS}
  496. cp ~/kube/default/* /etc/default/
  497. cp ~/kube/init_conf/* /etc/init/
  498. cp ~/kube/init_scripts/* /etc/init.d/
  499. mkdir -p /opt/bin/
  500. cp ~/kube/minion/* /opt/bin
  501. ${SERVICE_STARTS}
  502. if ${NEED_RECONFIG_DOCKER}; then KUBE_CONFIG_FILE=\"${KUBE_CONFIG_FILE}\" DOCKER_OPTS=\"${DOCKER_OPTS}\" ~/kube/reconfDocker.sh i; fi
  503. '" || {
  504. echo "Deploying node on machine ${1#*@} failed"
  505. exit 1
  506. }
  507. }
  508. function provision-masterandnode() {
  509. echo -e "\nDeploying master and node on machine ${MASTER_IP}"
  510. ssh $SSH_OPTS $MASTER "mkdir -p ~/kube/default"
  511. # copy the binaries and scripts to the ~/kube directory on the master
  512. # scp order matters
  513. scp -r $SSH_OPTS \
  514. saltbase/salt/generate-cert/make-ca-cert.sh \
  515. easy-rsa.tar.gz \
  516. "${KUBE_CONFIG_FILE}" \
  517. ubuntu/util.sh \
  518. ubuntu/minion/* \
  519. ubuntu/master/* \
  520. ubuntu/reconfDocker.sh \
  521. ubuntu/binaries/master/ \
  522. ubuntu/binaries/minion \
  523. "${MASTER}:~/kube"
  524. if [ -z "$CNI_PLUGIN_CONF" ] || [ -z "$CNI_PLUGIN_EXES" ]; then
  525. # Prep for Flannel use: copy the flannel binaries and scripts, set reconf flag
  526. scp -r $SSH_OPTS ubuntu/minion-flannel/* ubuntu/master-flannel/* "${MASTER}:~/kube"
  527. NEED_RECONFIG_DOCKER=true
  528. CNI_PLUGIN_CONF=''
  529. else
  530. # Prep for CNI use: copy the CNI config and binaries, adjust upstart config, set reconf flag
  531. ssh $SSH_OPTS "${MASTER}" "rm -rf tmp-cni; mkdir -p tmp-cni/exes tmp-cni/conf"
  532. scp $SSH_OPTS "$CNI_PLUGIN_CONF" "${MASTER}:tmp-cni/conf/"
  533. scp -p $SSH_OPTS $CNI_PLUGIN_EXES "${MASTER}:tmp-cni/exes/"
  534. ssh $SSH_OPTS -t "${MASTER}" '
  535. sudo -p "[sudo] password to prep master %h: " -- /bin/bash -ce "
  536. mkdir -p /opt/cni/bin /etc/cni/net.d
  537. cp ~$(id -un)/tmp-cni/conf/* /etc/cni/net.d/
  538. cp --preserve=mode ~$(id -un)/tmp-cni/exes/* /opt/cni/bin/
  539. '"sed -i.bak -e 's/start on started flanneld/start on started etcd/' -e 's/stop on stopping flanneld/stop on stopping etcd/' "'~$(id -un)/kube/init_conf/kube*.conf
  540. "'
  541. NEED_RECONFIG_DOCKER=false
  542. fi
  543. EXTRA_SANS=(
  544. IP:${MASTER_IP}
  545. IP:${SERVICE_CLUSTER_IP_RANGE%.*}.1
  546. DNS:kubernetes
  547. DNS:kubernetes.default
  548. DNS:kubernetes.default.svc
  549. DNS:kubernetes.default.svc.cluster.local
  550. )
  551. EXTRA_SANS=$(echo "${EXTRA_SANS[@]}" | tr ' ' ,)
  552. BASH_DEBUG_FLAGS=""
  553. if [[ "$DEBUG" == "true" ]] ; then
  554. BASH_DEBUG_FLAGS="set -x"
  555. fi
  556. # remote login to the master/node and configue k8s
  557. ssh $SSH_OPTS -t "$MASTER" "
  558. set +e
  559. ${BASH_DEBUG_FLAGS}
  560. source ~/kube/util.sh
  561. setClusterInfo
  562. create-etcd-opts '${MASTER_IP}'
  563. create-kube-apiserver-opts \
  564. '${SERVICE_CLUSTER_IP_RANGE}' \
  565. '${ADMISSION_CONTROL}' \
  566. '${SERVICE_NODE_PORT_RANGE}' \
  567. '${MASTER_IP}' \
  568. '${ALLOW_PRIVILEGED}'
  569. create-kube-controller-manager-opts '${NODE_IPS}'
  570. create-kube-scheduler-opts
  571. create-kubelet-opts \
  572. '${MASTER_IP}' \
  573. '${MASTER_IP}' \
  574. '${DNS_SERVER_IP}' \
  575. '${DNS_DOMAIN}' \
  576. '${KUBELET_CONFIG}' \
  577. '${ALLOW_PRIVILEGED}' \
  578. '${CNI_PLUGIN_CONF}'
  579. create-kube-proxy-opts \
  580. '${MASTER_IP}' \
  581. '${MASTER_IP}' \
  582. '${KUBE_PROXY_EXTRA_OPTS}'
  583. create-flanneld-opts '127.0.0.1' '${MASTER_IP}'
  584. FLANNEL_OTHER_NET_CONFIG='${FLANNEL_OTHER_NET_CONFIG}' sudo -E -p '[sudo] password to start master: ' -- /bin/bash -ce '
  585. ${BASH_DEBUG_FLAGS}
  586. cp ~/kube/default/* /etc/default/
  587. cp ~/kube/init_conf/* /etc/init/
  588. cp ~/kube/init_scripts/* /etc/init.d/
  589. groupadd -f -r kube-cert
  590. ${PROXY_SETTING} DEBUG='${DEBUG}' ~/kube/make-ca-cert.sh \"${MASTER_IP}\" \"${EXTRA_SANS}\"
  591. mkdir -p /opt/bin/
  592. cp ~/kube/master/* /opt/bin/
  593. cp ~/kube/minion/* /opt/bin/
  594. service etcd start
  595. if ${NEED_RECONFIG_DOCKER}; then FLANNEL_NET=\"${FLANNEL_NET}\" KUBE_CONFIG_FILE=\"${KUBE_CONFIG_FILE}\" DOCKER_OPTS=\"${DOCKER_OPTS}\" ~/kube/reconfDocker.sh ai; fi
  596. '" || {
  597. echo "Deploying master and node on machine ${MASTER_IP} failed"
  598. exit 1
  599. }
  600. }
  601. # check whether kubelet has torn down all of the pods
  602. function check-pods-torn-down() {
  603. local kubectl="${KUBE_ROOT}/cluster/kubectl.sh"
  604. local attempt=0
  605. while [[ ! -z "$(kubectl get pods --show-all --all-namespaces| tail -n +2)" ]]; do
  606. if (( attempt > 120 )); then
  607. echo "timeout waiting for tearing down pods" >> ~/kube/err.log
  608. fi
  609. echo "waiting for tearing down pods"
  610. attempt=$((attempt+1))
  611. sleep 5
  612. done
  613. }
  614. # Delete a kubernetes cluster
  615. function kube-down() {
  616. export KUBECTL_PATH="${KUBE_ROOT}/cluster/ubuntu/binaries/kubectl"
  617. export KUBE_CONFIG_FILE=${KUBE_CONFIG_FILE:-${KUBE_ROOT}/cluster/ubuntu/config-default.sh}
  618. source "${KUBE_CONFIG_FILE}"
  619. source "${KUBE_ROOT}/cluster/common.sh"
  620. tear_down_alive_resources
  621. check-pods-torn-down
  622. local ii=0
  623. for i in ${nodes}; do
  624. if [[ "${roles_array[${ii}]}" == "ai" || "${roles_array[${ii}]}" == "a" ]]; then
  625. echo "Cleaning on master ${i#*@}"
  626. ssh $SSH_OPTS -t "$i" "
  627. pgrep etcd && \
  628. sudo -p '[sudo] password to stop master: ' -- /bin/bash -c '
  629. service etcd stop
  630. rm -rf \
  631. /opt/bin/etcd* \
  632. /etc/init/etcd.conf \
  633. /etc/init.d/etcd \
  634. /etc/default/etcd
  635. rm -rf /infra*
  636. rm -rf /srv/kubernetes
  637. '
  638. " || echo "Cleaning on master ${i#*@} failed"
  639. if [[ "${roles_array[${ii}]}" == "ai" ]]; then
  640. ssh $SSH_OPTS -t "$i" "sudo rm -rf /var/lib/kubelet"
  641. fi
  642. elif [[ "${roles_array[${ii}]}" == "i" ]]; then
  643. echo "Cleaning on node ${i#*@}"
  644. ssh $SSH_OPTS -t "$i" "
  645. pgrep flanneld && \
  646. sudo -p '[sudo] password to stop node: ' -- /bin/bash -c '
  647. service flanneld stop
  648. rm -rf /var/lib/kubelet
  649. '
  650. " || echo "Cleaning on node ${i#*@} failed"
  651. else
  652. echo "unsupported role for ${i}"
  653. fi
  654. ssh $SSH_OPTS -t "$i" "sudo -- /bin/bash -c '
  655. rm -f \
  656. /opt/bin/kube* \
  657. /opt/bin/flanneld \
  658. /etc/init/kube* \
  659. /etc/init/flanneld.conf \
  660. /etc/init.d/kube* \
  661. /etc/init.d/flanneld \
  662. /etc/default/kube* \
  663. /etc/default/flanneld
  664. rm -rf ~/kube
  665. rm -f /run/flannel/subnet.env
  666. '" || echo "cleaning legacy files on ${i#*@} failed"
  667. ((ii=ii+1))
  668. done
  669. }
  670. # Perform common upgrade setup tasks
  671. function prepare-push() {
  672. # Use local binaries for kube-push
  673. if [[ -z "${KUBE_VERSION}" ]]; then
  674. echo "Use local binaries for kube-push"
  675. if [[ ! -d "${KUBE_ROOT}/cluster/ubuntu/binaries" ]]; then
  676. echo "No local binaries.Please check"
  677. exit 1
  678. else
  679. echo "Please make sure all the required local binaries are prepared ahead"
  680. sleep 3
  681. fi
  682. else
  683. # Run download-release.sh to get the required release
  684. export KUBE_VERSION
  685. "${KUBE_ROOT}/cluster/ubuntu/download-release.sh"
  686. fi
  687. }
  688. # Update a kubernetes master with expected release
  689. function push-master() {
  690. export KUBE_CONFIG_FILE=${KUBE_CONFIG_FILE:-${KUBE_ROOT}/cluster/ubuntu/config-default.sh}
  691. source "${KUBE_CONFIG_FILE}"
  692. if [[ ! -f "${KUBE_ROOT}/cluster/ubuntu/binaries/master/kube-apiserver" ]]; then
  693. echo "There is no required release of kubernetes, please check first"
  694. exit 1
  695. fi
  696. export KUBECTL_PATH="${KUBE_ROOT}/cluster/ubuntu/binaries/kubectl"
  697. setClusterInfo
  698. local ii=0
  699. for i in ${nodes}; do
  700. if [[ "${roles_array[${ii}]}" == "a" || "${roles_array[${ii}]}" == "ai" ]]; then
  701. echo "Cleaning master ${i#*@}"
  702. ssh $SSH_OPTS -t "$i" "
  703. pgrep etcd && sudo -p '[sudo] stop the all process: ' -- /bin/bash -c '
  704. service etcd stop
  705. sleep 3
  706. rm -rf \
  707. /etc/init/etcd.conf \
  708. /etc/init/kube* \
  709. /etc/init/flanneld.conf \
  710. /etc/init.d/etcd \
  711. /etc/init.d/kube* \
  712. /etc/init.d/flanneld \
  713. /etc/default/etcd \
  714. /etc/default/kube* \
  715. /etc/default/flanneld
  716. rm -f \
  717. /opt/bin/etcd* \
  718. /opt/bin/kube* \
  719. /opt/bin/flanneld
  720. rm -f /run/flannel/subnet.env
  721. rm -rf ~/kube
  722. '" || echo "Cleaning master ${i#*@} failed"
  723. fi
  724. if [[ "${roles_array[${ii}]}" == "a" ]]; then
  725. provision-master
  726. elif [[ "${roles_array[${ii}]}" == "ai" ]]; then
  727. provision-masterandnode
  728. elif [[ "${roles_array[${ii}]}" == "i" ]]; then
  729. ((ii=ii+1))
  730. continue
  731. else
  732. echo "unsupported role for ${i}, please check"
  733. exit 1
  734. fi
  735. ((ii=ii+1))
  736. done
  737. verify-cluster
  738. }
  739. # Update a kubernetes node with expected release
  740. function push-node() {
  741. export KUBE_CONFIG_FILE=${KUBE_CONFIG_FILE:-${KUBE_ROOT}/cluster/ubuntu/config-default.sh}
  742. source "${KUBE_CONFIG_FILE}"
  743. if [[ ! -f "${KUBE_ROOT}/cluster/ubuntu/binaries/minion/kubelet" ]]; then
  744. echo "There is no required release of kubernetes, please check first"
  745. exit 1
  746. fi
  747. export KUBECTL_PATH="${KUBE_ROOT}/cluster/ubuntu/binaries/kubectl"
  748. setClusterInfo
  749. local node_ip=${1}
  750. local ii=0
  751. local existing=false
  752. for i in ${nodes}; do
  753. if [[ "${roles_array[${ii}]}" == "i" && ${i#*@} == "$node_ip" ]]; then
  754. echo "Cleaning node ${i#*@}"
  755. ssh $SSH_OPTS -t "$i" "
  756. sudo -p '[sudo] stop the all process: ' -- /bin/bash -c '
  757. service flanneld stop
  758. rm -f /opt/bin/kube* \
  759. /opt/bin/flanneld
  760. rm -rf \
  761. /etc/init/kube* \
  762. /etc/init/flanneld.conf \
  763. /etc/init.d/kube* \
  764. /etc/init.d/flanneld \
  765. /etc/default/kube* \
  766. /etc/default/flanneld
  767. rm -f /run/flannel/subnet.env
  768. rm -rf ~/kube
  769. '" || echo "Cleaning node ${i#*@} failed"
  770. provision-node "$i"
  771. existing=true
  772. elif [[ "${roles_array[${ii}]}" == "a" || "${roles_array[${ii}]}" == "ai" ]] && [[ ${i#*@} == "$node_ip" ]]; then
  773. echo "${i} is master node, please try ./kube-push -m instead"
  774. existing=true
  775. elif [[ "${roles_array[${ii}]}" == "i" || "${roles_array[${ii}]}" == "a" || "${roles_array[${ii}]}" == "ai" ]]; then
  776. ((ii=ii+1))
  777. continue
  778. else
  779. echo "unsupported role for ${i}, please check"
  780. exit 1
  781. fi
  782. ((ii=ii+1))
  783. done
  784. if [[ "${existing}" == false ]]; then
  785. echo "node ${node_ip} does not exist"
  786. else
  787. verify-cluster
  788. fi
  789. }
  790. # Update a kubernetes cluster with expected source
  791. function kube-push() {
  792. prepare-push
  793. export KUBE_CONFIG_FILE=${KUBE_CONFIG_FILE:-${KUBE_ROOT}/cluster/ubuntu/config-default.sh}
  794. source "${KUBE_CONFIG_FILE}"
  795. if [[ ! -f "${KUBE_ROOT}/cluster/ubuntu/binaries/master/kube-apiserver" ]]; then
  796. echo "There is no required release of kubernetes, please check first"
  797. exit 1
  798. fi
  799. export KUBECTL_PATH="${KUBE_ROOT}/cluster/ubuntu/binaries/kubectl"
  800. #stop all the kube's process & etcd
  801. local ii=0
  802. for i in ${nodes}; do
  803. if [[ "${roles_array[${ii}]}" == "ai" || "${roles_array[${ii}]}" == "a" ]]; then
  804. echo "Cleaning on master ${i#*@}"
  805. ssh $SSH_OPTS -t "$i" "
  806. pgrep etcd && \
  807. sudo -p '[sudo] password to stop master: ' -- /bin/bash -c '
  808. service etcd stop
  809. rm -rf \
  810. /opt/bin/etcd* \
  811. /etc/init/etcd.conf \
  812. /etc/init.d/etcd \
  813. /etc/default/etcd
  814. '" || echo "Cleaning on master ${i#*@} failed"
  815. elif [[ "${roles_array[${ii}]}" == "i" ]]; then
  816. echo "Cleaning on node ${i#*@}"
  817. ssh $SSH_OPTS -t $i "
  818. pgrep flanneld && \
  819. sudo -p '[sudo] password to stop node: ' -- /bin/bash -c '
  820. service flanneld stop
  821. '" || echo "Cleaning on node ${i#*@} failed"
  822. else
  823. echo "unsupported role for ${i}"
  824. fi
  825. ssh $SSH_OPTS -t "$i" "sudo -- /bin/bash -c '
  826. rm -f \
  827. /opt/bin/kube* \
  828. /opt/bin/flanneld
  829. rm -rf \
  830. /etc/init/kube* \
  831. /etc/init/flanneld.conf \
  832. /etc/init.d/kube* \
  833. /etc/init.d/flanneld \
  834. /etc/default/kube* \
  835. /etc/default/flanneld
  836. rm -f /run/flannel/subnet.env
  837. rm -rf ~/kube
  838. '" || echo "Cleaning legacy files on ${i#*@} failed"
  839. ((ii=ii+1))
  840. done
  841. #provision all nodes,including master & nodes
  842. setClusterInfo
  843. local ii=0
  844. for i in ${nodes}; do
  845. if [[ "${roles_array[${ii}]}" == "a" ]]; then
  846. provision-master
  847. elif [[ "${roles_array[${ii}]}" == "i" ]]; then
  848. provision-node "$i"
  849. elif [[ "${roles_array[${ii}]}" == "ai" ]]; then
  850. provision-masterandnode
  851. else
  852. echo "unsupported role for ${i}. please check"
  853. exit 1
  854. fi
  855. ((ii=ii+1))
  856. done
  857. verify-cluster
  858. }
  859. # Perform preparations required to run e2e tests
  860. function prepare-e2e() {
  861. echo "Ubuntu doesn't need special preparations for e2e tests" 1>&2
  862. }