You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

install.sh 10 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. #!/bin/bash
  2. # Copyright 2021 The KubeEdge 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. # Influential env vars:
  16. #
  17. # SEDNA_GM_NODE | required | The node which Sedna gm will be deployed at
  18. # SEDNA_ACTION | optional | 'create'/'clean', default is 'create'
  19. # SEDNA_VERSION | optional | The Sedna version to be installed.
  20. # if not specified, it will get latest release version.
  21. # SEDNA_ROOT | optional | The Sedna offline directory
  22. set -o errexit
  23. set -o nounset
  24. set -o pipefail
  25. TMP_DIR=$(mktemp -d --suffix=.sedna)
  26. SEDNA_ROOT=${SEDNA_ROOT:-$TMP_DIR}
  27. GM_NODE_NAME=${SEDNA_GM_NODE:-}
  28. KB_NODE_NAME=${SEDNA_GM_NODE:-}
  29. DEFAULT_SEDNA_VERSION=v0.4.0
  30. trap "rm -rf '$TMP_DIR'" EXIT
  31. get_latest_version() {
  32. # get Sedna latest release version
  33. local repo=kubeedge/sedna
  34. # output of this latest page:
  35. # ...
  36. # "tag_name": "v1.0.0",
  37. # ...
  38. {
  39. curl -s https://api.github.com/repos/$repo/releases/latest |
  40. awk '/"tag_name":/&&$0=$2' |
  41. sed 's/[",]//g'
  42. } || echo $DEFAULT_SEDNA_VERSION # fallback
  43. }
  44. : ${SEDNA_VERSION:=$(get_latest_version)}
  45. : ${KB_VERSION:=v0.3.0}
  46. _download_yamls() {
  47. yaml_dir=$1
  48. mkdir -p ${SEDNA_ROOT}/$yaml_dir
  49. cd ${SEDNA_ROOT}/$yaml_dir
  50. for yaml in ${yaml_files[@]}; do
  51. # the yaml file already exists, no need to download
  52. [ -e "$yaml" ] && continue
  53. echo downloading $yaml into ${SEDNA_ROOT}/$yaml_dir
  54. local try_times=30 i=1 timeout=2
  55. while ! timeout ${timeout}s curl -sSO https://raw.githubusercontent.com/kubeedge/sedna/main/$yaml_dir/$yaml; do
  56. ((++i>try_times)) && {
  57. echo timeout to download $yaml
  58. exit 2
  59. }
  60. echo -en "retrying to download $yaml after $[i*timeout] seconds...\r"
  61. done
  62. done
  63. }
  64. download_yamls() {
  65. yaml_files=(
  66. sedna.io_datasets.yaml
  67. sedna.io_federatedlearningjobs.yaml
  68. sedna.io_incrementallearningjobs.yaml
  69. sedna.io_jointinferenceservices.yaml
  70. sedna.io_lifelonglearningjobs.yaml
  71. sedna.io_models.yaml
  72. )
  73. _download_yamls build/crds
  74. yaml_files=(
  75. gm.yaml
  76. )
  77. _download_yamls build/gm/rbac
  78. }
  79. prepare_install(){
  80. # need to create a namespace
  81. kubectl create ns sedna
  82. kubectl label node/$GM_NODE_NAME sedna=control-plane --overwrite
  83. }
  84. prepare() {
  85. mkdir -p ${SEDNA_ROOT}
  86. # we only need build directory
  87. # here don't use git clone because of large vendor directory
  88. download_yamls
  89. }
  90. cleanup(){
  91. kubectl label node/$SEDNA_GM_NODE sedna- | sed 's/labeled$/un&/' || true
  92. kubectl delete ns sedna
  93. }
  94. create_crds() {
  95. cd ${SEDNA_ROOT}
  96. kubectl create -f build/crds
  97. }
  98. delete_crds() {
  99. cd ${SEDNA_ROOT}
  100. kubectl delete -f build/crds --timeout=90s
  101. }
  102. create_kb(){
  103. cd ${SEDNA_ROOT}
  104. kubectl $action -f - <<EOF
  105. apiVersion: v1
  106. kind: Service
  107. metadata:
  108. name: kb
  109. namespace: sedna
  110. spec:
  111. selector:
  112. sedna: kb
  113. type: NodePort
  114. ports:
  115. - protocol: TCP
  116. port: 9020
  117. targetPort: 9020
  118. ---
  119. apiVersion: apps/v1
  120. kind: Deployment
  121. metadata:
  122. name: kb
  123. labels:
  124. sedna: kb
  125. namespace: sedna
  126. spec:
  127. replicas: 1
  128. selector:
  129. matchLabels:
  130. sedna: kb
  131. template:
  132. metadata:
  133. labels:
  134. sedna: kb
  135. spec:
  136. nodeSelector:
  137. sedna: control-plane
  138. serviceAccountName: sedna
  139. containers:
  140. - name: kb
  141. imagePullPolicy: IfNotPresent
  142. image: kubeedge/sedna-kb:$KB_VERSION
  143. env:
  144. - name: KB_URL
  145. value: "sqlite:///db/kb.sqlite3"
  146. volumeMounts:
  147. - name: kb-url
  148. mountPath: /db
  149. resources:
  150. requests:
  151. memory: 256Mi
  152. cpu: 100m
  153. limits:
  154. memory: 512Mi
  155. volumes:
  156. - name: kb-url
  157. hostPath:
  158. path: /opt/kb-data
  159. type: DirectoryOrCreate
  160. EOF
  161. }
  162. prepare_gm_config_map() {
  163. kb_node_port=$(kubectl -n sedna get svc kb -ojsonpath='{.spec.ports[0].nodePort}')
  164. # here try to get node ip by kubectl
  165. kb_node_ip=$(kubectl get node $KB_NODE_NAME -o jsonpath='{ .status.addresses[?(@.type=="ExternalIP")].address }')
  166. kb_node_internal_ip=$(kubectl get node $KB_NODE_NAME -o jsonpath='{ .status.addresses[?(@.type=="InternalIP")].address }')
  167. KB_ADDRESS=${kb_node_ip:-$kb_node_internal_ip}:$kb_node_port
  168. cm_name=${1:-gm-config}
  169. config_file=${TMP_DIR}/${2:-gm.yaml}
  170. if [ -n "${SEDNA_GM_CONFIG:-}" ] && [ -f "${SEDNA_GM_CONFIG}" ] ; then
  171. cp "$SEDNA_GM_CONFIG" $config_file
  172. else
  173. cat > $config_file << EOF
  174. kubeConfig: ""
  175. master: ""
  176. namespace: ""
  177. websocket:
  178. address: 0.0.0.0
  179. port: 9000
  180. localController:
  181. server: http://localhost:${SEDNA_LC_BIND_PORT:-9100}
  182. knowledgeBaseServer:
  183. server: http://$KB_ADDRESS
  184. EOF
  185. fi
  186. kubectl $action -n sedna configmap $cm_name --from-file=$config_file
  187. }
  188. create_gm() {
  189. cd ${SEDNA_ROOT}
  190. kubectl create -f build/gm/rbac/
  191. cm_name=gm-config
  192. config_file_name=gm.yaml
  193. prepare_gm_config_map $cm_name $config_file_name
  194. kubectl $action -f - <<EOF
  195. apiVersion: v1
  196. kind: Service
  197. metadata:
  198. name: gm
  199. namespace: sedna
  200. spec:
  201. selector:
  202. sedna: gm
  203. type: NodePort
  204. ports:
  205. - protocol: TCP
  206. port: 9000
  207. targetPort: 9000
  208. ---
  209. apiVersion: apps/v1
  210. kind: Deployment
  211. metadata:
  212. name: gm
  213. labels:
  214. sedna: gm
  215. namespace: sedna
  216. spec:
  217. replicas: 1
  218. selector:
  219. matchLabels:
  220. sedna: gm
  221. template:
  222. metadata:
  223. labels:
  224. sedna: gm
  225. spec:
  226. nodeSelector:
  227. sedna: control-plane
  228. serviceAccountName: sedna
  229. containers:
  230. - name: gm
  231. image: kubeedge/sedna-gm:$SEDNA_VERSION
  232. command: ["sedna-gm", "--config", "/config/$config_file_name", "-v2"]
  233. volumeMounts:
  234. - name: gm-config
  235. mountPath: /config
  236. resources:
  237. requests:
  238. memory: 32Mi
  239. cpu: 100m
  240. limits:
  241. memory: 128Mi
  242. volumes:
  243. - name: gm-config
  244. configMap:
  245. name: $cm_name
  246. EOF
  247. }
  248. delete_gm() {
  249. cd ${SEDNA_ROOT}
  250. kubectl delete -f build/gm/rbac/
  251. # no need to clean gm deployment alone
  252. }
  253. create_lc() {
  254. gm_node_port=$(kubectl -n sedna get svc gm -ojsonpath='{.spec.ports[0].nodePort}')
  255. # here try to get node ip by kubectl
  256. gm_node_ip=$(kubectl get node $GM_NODE_NAME -o jsonpath='{ .status.addresses[?(@.type=="ExternalIP")].address }')
  257. gm_node_internal_ip=$(kubectl get node $GM_NODE_NAME -o jsonpath='{ .status.addresses[?(@.type=="InternalIP")].address }')
  258. GM_ADDRESS=${gm_node_ip:-$gm_node_internal_ip}:$gm_node_port
  259. kubectl $action -f- <<EOF
  260. apiVersion: apps/v1
  261. kind: DaemonSet
  262. metadata:
  263. labels:
  264. sedna: lc
  265. name: lc
  266. namespace: sedna
  267. spec:
  268. selector:
  269. matchLabels:
  270. sedna: lc
  271. template:
  272. metadata:
  273. labels:
  274. sedna: lc
  275. spec:
  276. containers:
  277. - name: lc
  278. image: kubeedge/sedna-lc:$SEDNA_VERSION
  279. env:
  280. - name: GM_ADDRESS
  281. value: $GM_ADDRESS
  282. - name: BIND_PORT
  283. value: "${SEDNA_LC_BIND_PORT:-9100}"
  284. - name: NODENAME
  285. valueFrom:
  286. fieldRef:
  287. fieldPath: spec.nodeName
  288. - name: ROOTFS_MOUNT_DIR
  289. # the value of ROOTFS_MOUNT_DIR is same with the mount path of volume
  290. value: /rootfs
  291. resources:
  292. requests:
  293. memory: 32Mi
  294. cpu: 100m
  295. limits:
  296. memory: 128Mi
  297. volumeMounts:
  298. - name: localcontroller
  299. mountPath: /rootfs
  300. volumes:
  301. - name: localcontroller
  302. hostPath:
  303. path: /
  304. restartPolicy: Always
  305. hostNetwork: true
  306. EOF
  307. }
  308. delete_lc() {
  309. # ns would be deleted in delete_gm
  310. # so no need to clean lc alone
  311. return
  312. }
  313. wait_ok() {
  314. echo "Waiting control components to be ready..."
  315. kubectl -n sedna wait --for=condition=available --timeout=600s deployment/gm
  316. kubectl -n sedna wait pod --for=condition=Ready --selector=sedna
  317. kubectl -n sedna get pod
  318. }
  319. delete_pods() {
  320. # in case some nodes are not ready, here delete with a 60s timeout, otherwise force delete these
  321. kubectl -n sedna delete pod --all --timeout=60s || kubectl -n sedna delete pod --all --force --grace-period=0
  322. }
  323. check_kubectl () {
  324. kubectl get pod >/dev/null
  325. }
  326. check_action() {
  327. action=${SEDNA_ACTION:-create}
  328. support_action_list="create delete"
  329. if ! echo "$support_action_list" | grep -w -q "$action"; then
  330. echo "\`$action\` not in support action list: create/delete!" >&2
  331. echo "You need to specify it by setting $(red_text SEDNA_ACTION) environment variable when running this script!" >&2
  332. exit 2
  333. fi
  334. }
  335. check_node() {
  336. if [ -z "$GM_NODE_NAME" ] || ! kubectl get node $GM_NODE_NAME; then
  337. echo "ERROR: $(red_text GM node name \`$GM_NODE_NAME\` does not exist in k8s cluster)!" >&2
  338. echo "You need to specify it by setting $(red_text SEDNA_GM_NODE) environment variable when running this script!" >&2
  339. exit 1
  340. fi
  341. }
  342. do_check() {
  343. check_kubectl
  344. check_action
  345. check_node
  346. }
  347. show_debug_infos() {
  348. cat - <<EOF
  349. Sedna is $(green_text running):
  350. See GM status: kubectl -n sedna get deploy
  351. See LC status: kubectl -n sedna get ds lc
  352. See Pod status: kubectl -n sedna get pod
  353. EOF
  354. }
  355. NO_COLOR='\033[0m'
  356. RED='\033[0;31m'
  357. GREEN='\033[0;32m'
  358. green_text() {
  359. echo -ne "$GREEN$@$NO_COLOR"
  360. }
  361. red_text() {
  362. echo -ne "$RED$@$NO_COLOR"
  363. }
  364. do_check
  365. prepare
  366. case "$action" in
  367. create)
  368. echo "Installing Sedna $SEDNA_VERSION..."
  369. prepare_install
  370. create_crds
  371. create_kb
  372. create_gm
  373. create_lc
  374. wait_ok
  375. show_debug_infos
  376. ;;
  377. delete)
  378. delete_pods
  379. delete_gm
  380. delete_lc
  381. delete_crds
  382. cleanup
  383. echo "$(green_text Sedna is uninstalled successfully)"
  384. ;;
  385. esac