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 9.6 kB

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