Bug 1841: LTS Support Helm
[osm/devops.git] / installers / install_kubeadm_cluster.sh
1 #!/bin/bash
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 #
15
16 set +eux
17
18 #installs kubernetes packages
19 function install_kube() {
20 [ -z "${DEBUG_INSTALL}" ] || DEBUG beginning of function
21 K8S_VERSION=1.23.3-00
22 # To check other available versions, run the following command
23 # curl -s https://packages.cloud.google.com/apt/dists/kubernetes-xenial/main/binary-amd64/Packages | grep Version | awk '{print $2}'
24 sudo apt-get update && sudo apt-get install -y apt-transport-https
25 sudo apt-get update && sudo apt-get install -y apt-transport-https
26 curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
27 sudo add-apt-repository "deb https://apt.kubernetes.io/ kubernetes-xenial main"
28 sudo apt-get update
29 echo "Installing Kubernetes Packages ..."
30 sudo apt-get install -y kubelet=${K8S_VERSION} kubeadm=${K8S_VERSION} kubectl=${K8S_VERSION}
31 cat << EOF | sudo tee -a /etc/default/kubelet
32 KUBELET_EXTRA_ARGS="--cgroup-driver=cgroupfs"
33 EOF
34 sudo apt-mark hold kubelet kubeadm kubectl
35 [ -z "${DEBUG_INSTALL}" ] || DEBUG end of function
36 }
37
38 #initializes kubernetes control plane
39 function init_kubeadm() {
40 [ -z "${DEBUG_INSTALL}" ] || DEBUG beginning of function
41 sudo swapoff -a
42 sudo sed -i.bak '/.*none.*swap/s/^\(.*\)$/#\1/g' /etc/fstab
43 sudo kubeadm init --config $1
44 sleep 5
45 [ -z "${DEBUG_INSTALL}" ] || DEBUG end of function
46 }
47
48 function kube_config_dir() {
49 [ -z "${DEBUG_INSTALL}" ] || DEBUG beginning of function
50 K8S_MANIFEST_DIR="/etc/kubernetes/manifests"
51 [ ! -d $K8S_MANIFEST_DIR ] && FATAL "Cannot Install Kubernetes"
52 mkdir -p $HOME/.kube
53 sudo cp /etc/kubernetes/admin.conf $HOME/.kube/config
54 sudo chown $(id -u):$(id -g) $HOME/.kube/config
55 [ -z "${DEBUG_INSTALL}" ] || DEBUG end of function
56 }
57
58 #deploys flannel as daemonsets
59 function deploy_cni_provider() {
60 [ -z "${DEBUG_INSTALL}" ] || DEBUG beginning of function
61 CNI_DIR="$(mktemp -d -q --tmpdir "flannel.XXXXXX")"
62 trap 'rm -rf "${CNI_DIR}"' EXIT
63 wget -q https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml -P $CNI_DIR
64 kubectl apply -f $CNI_DIR
65 [ $? -ne 0 ] && FATAL "Cannot Install Flannel"
66 [ -z "${DEBUG_INSTALL}" ] || DEBUG end of function
67 }
68
69 #taints K8s master node
70 function taint_master_node() {
71 [ -z "${DEBUG_INSTALL}" ] || DEBUG beginning of function
72 K8S_MASTER=$(kubectl get nodes | awk '$3~/master/'| awk '{print $1}')
73 kubectl taint node $K8S_MASTER node-role.kubernetes.io/master:NoSchedule-
74 sleep 5
75 [ -z "${DEBUG_INSTALL}" ] || DEBUG end of function
76 }
77
78 #Install Helm v3
79 function install_helm() {
80 [ -z "${DEBUG_INSTALL}" ] || DEBUG beginning of function
81 helm > /dev/null 2>&1
82 if [ $? != 0 ] ; then
83 # Helm is not installed. Install helm
84 echo "Helm is not installed, installing ..."
85 curl https://get.helm.sh/helm-v3.6.3-linux-amd64.tar.gz --output helm-v3.6.3.tar.gz
86 tar -zxvf helm-v3.6.3.tar.gz
87 sudo mv linux-amd64/helm /usr/local/bin/helm
88 rm -r linux-amd64
89 rm helm-v3.6.3.tar.gz
90 helm repo add stable https://charts.helm.sh/stable
91 helm repo update
92 fi
93 [ -z "${DEBUG_INSTALL}" ] || DEBUG end of function
94 }
95
96 function install_k8s_storageclass() {
97 [ -z "${DEBUG_INSTALL}" ] || DEBUG beginning of function
98 echo "Installing open-iscsi"
99 sudo apt-get update
100 sudo apt-get install open-iscsi
101 sudo systemctl enable --now iscsid
102 OPENEBS_VERSION="3.1.0"
103 echo "Installing OpenEBS"
104 helm repo add openebs https://openebs.github.io/charts
105 helm repo update
106 helm install --create-namespace --namespace openebs openebs openebs/openebs --version ${OPENEBS_VERSION}
107 helm ls -n openebs
108 local storageclass_timeout=400
109 local counter=0
110 local storageclass_ready=""
111 echo "Waiting for storageclass"
112 while (( counter < storageclass_timeout ))
113 do
114 kubectl get storageclass openebs-hostpath &> /dev/null
115
116 if [ $? -eq 0 ] ; then
117 echo "Storageclass available"
118 storageclass_ready="y"
119 break
120 else
121 counter=$((counter + 15))
122 sleep 15
123 fi
124 done
125 [ -n "$storageclass_ready" ] || FATAL "Storageclass not ready after $storageclass_timeout seconds. Cannot install openebs"
126 kubectl patch storageclass openebs-hostpath -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
127 [ -z "${DEBUG_INSTALL}" ] || DEBUG end of function
128 }
129
130 #installs metallb from helm
131 function install_helm_metallb() {
132 [ -z "${DEBUG_INSTALL}" ] || DEBUG beginning of function
133 echo "Installing MetalLB"
134 METALLB_VERSION="0.11.0"
135 METALLB_IP_RANGE="$DEFAULT_IP/32"
136 echo "configInline:
137 address-pools:
138 - name: default
139 protocol: layer2
140 addresses:
141 - $METALLB_IP_RANGE" | sudo tee -a ${OSM_DOCKER_WORK_DIR}/metallb-config.yaml
142 helm repo add metallb https://metallb.github.io/metallb
143 helm repo update
144 helm install --create-namespace --namespace metallb-system metallb metallb/metallb --version ${METALLB_VERSION} -f ${OSM_DOCKER_WORK_DIR}/metallb-config.yaml
145 [ -z "${DEBUG_INSTALL}" ] || DEBUG end of function
146 }
147
148 #checks openebs and metallb readiness
149 function check_for_readiness() {
150 [ -z "${DEBUG_INSTALL}" ] || DEBUG beginning of function
151 # Default input values
152 sampling_period=2 # seconds
153 time_for_readiness=20 # seconds ready
154 time_for_failure=200 # seconds broken
155 OPENEBS_NAMESPACE=openebs
156 METALLB_NAMESPACE=metallb-system
157 # STACK_NAME=osm # By default, "osm"
158
159 # Equivalent number of samples
160 oks_threshold=$((time_for_readiness/${sampling_period})) # No. ok samples to declare the system ready
161 failures_threshold=$((time_for_failure/${sampling_period})) # No. nok samples to declare the system broken
162 failures_in_a_row=0
163 oks_in_a_row=0
164
165 ####################################################################################
166 # Loop to check system readiness
167 ####################################################################################
168 while [[ (${failures_in_a_row} -lt ${failures_threshold}) && (${oks_in_a_row} -lt ${oks_threshold}) ]]
169 do
170 # State of OpenEBS
171 OPENEBS_STATE=$(kubectl get pod -n ${OPENEBS_NAMESPACE} --no-headers 2>&1)
172 OPENEBS_READY=$(echo "${OPENEBS_STATE}" | awk '$2=="1/1" || $2=="2/2" {printf ("%s\t%s\t\n", $1, $2)}')
173 OPENEBS_NOT_READY=$(echo "${OPENEBS_STATE}" | awk '$2!="1/1" && $2!="2/2" {printf ("%s\t%s\t\n", $1, $2)}')
174 COUNT_OPENEBS_READY=$(echo "${OPENEBS_READY}"| grep -v -e '^$' | wc -l)
175 COUNT_OPENEBS_NOT_READY=$(echo "${OPENEBS_NOT_READY}" | grep -v -e '^$' | wc -l)
176
177 # State of MetalLB
178 METALLB_STATE=$(kubectl get pod -n ${METALLB_NAMESPACE} --no-headers 2>&1)
179 METALLB_READY=$(echo "${METALLB_STATE}" | awk '$2=="1/1" || $2=="2/2" {printf ("%s\t%s\t\n", $1, $2)}')
180 METALLB_NOT_READY=$(echo "${METALLB_STATE}" | awk '$2!="1/1" && $2!="2/2" {printf ("%s\t%s\t\n", $1, $2)}')
181 COUNT_METALLB_READY=$(echo "${METALLB_READY}" | grep -v -e '^$' | wc -l)
182 COUNT_METALLB_NOT_READY=$(echo "${METALLB_NOT_READY}" | grep -v -e '^$' | wc -l)
183
184 # OK sample
185 if [[ $((${COUNT_OPENEBS_NOT_READY}+${COUNT_METALLB_NOT_READY})) -eq 0 ]]
186 then
187 ((++oks_in_a_row))
188 failures_in_a_row=0
189 echo -ne ===\> Successful checks: "${oks_in_a_row}"/${oks_threshold}\\r
190 # NOK sample
191 else
192 ((++failures_in_a_row))
193 oks_in_a_row=0
194 echo
195 echo Bootstraping... "${failures_in_a_row}" checks of ${failures_threshold}
196
197 # Reports failed pods in OpenEBS
198 if [[ "${COUNT_OPENEBS_NOT_READY}" -ne 0 ]]
199 then
200 echo "OpenEBS: Waiting for ${COUNT_OPENEBS_NOT_READY} of $((${COUNT_OPENEBS_NOT_READY}+${COUNT_OPENEBS_READY})) pods to be ready:"
201 echo "${OPENEBS_NOT_READY}"
202 echo
203 fi
204
205 # Reports failed statefulsets
206 if [[ "${COUNT_METALLB_NOT_READY}" -ne 0 ]]
207 then
208 echo "MetalLB: Waiting for ${COUNT_METALLB_NOT_READY} of $((${COUNT_METALLB_NOT_READY}+${COUNT_METALLB_READY})) pods to be ready:"
209 echo "${METALLB_NOT_READY}"
210 echo
211 fi
212 fi
213
214 #------------ NEXT SAMPLE
215 sleep ${sampling_period}
216 done
217
218 ####################################################################################
219 # OUTCOME
220 ####################################################################################
221 if [[ (${failures_in_a_row} -ge ${failures_threshold}) ]]
222 then
223 echo
224 FATAL "K8S CLUSTER IS BROKEN"
225 else
226 echo
227 echo "K8S CLUSTER IS READY"
228 fi
229 [ -z "${DEBUG_INSTALL}" ] || DEBUG end of function
230 }
231
232 #removes osm deployments and services
233 function remove_k8s_namespace() {
234 [ -z "${DEBUG_INSTALL}" ] || DEBUG beginning of function
235 kubectl delete ns $1
236 [ -z "${DEBUG_INSTALL}" ] || DEBUG end of function
237 }
238
239 # main
240 while getopts ":D:d:i:-: " o; do
241 case "${o}" in
242 i)
243 DEFAULT_IP="${OPTARG}"
244 ;;
245 d)
246 OSM_DOCKER_WORK_DIR="${OPTARG}"
247 ;;
248 D)
249 OSM_DEVOPS="${OPTARG}"
250 ;;
251 -)
252 [ "${OPTARG}" == "debug" ] && DEBUG_INSTALL="y" && continue
253 echo -e "Invalid option: '--$OPTARG'\n" >&2
254 exit 1
255 ;;
256 :)
257 echo "Option -$OPTARG requires an argument" >&2
258 exit 1
259 ;;
260 \?)
261 echo -e "Invalid option: '-$OPTARG'\n" >&2
262 exit 1
263 ;;
264 *)
265 exit 1
266 ;;
267 esac
268 done
269
270 source $OSM_DEVOPS/common/logging
271 source $OSM_DEVOPS/common/track
272
273 echo "DEBUG_INSTALL=$DEBUG_INSTALL"
274 echo "DEFAULT_IP=$DEFAULT_IP"
275 echo "OSM_DEVOPS=$OSM_DEVOPS"
276 echo "OSM_DOCKER_WORK_DIR=$OSM_DOCKER_WORK_DIR"
277 echo "INSTALL_K8S_MONITOR=$INSTALL_K8S_MONITOR"
278 echo "HOME=$HOME"
279
280
281 install_kube
282 track k8scluster install_k8s_ok
283 init_kubeadm $OSM_DOCKER_WORK_DIR/cluster-config.yaml
284 kube_config_dir
285 track k8scluster init_k8s_ok
286 if [ -n "$INSTALL_K8S_MONITOR" ]; then
287 # uninstall OSM MONITORING
288 uninstall_k8s_monitoring
289 track k8scluster uninstall_k8s_monitoring_ok
290 fi
291 #remove old namespace
292 remove_k8s_namespace osm
293 deploy_cni_provider
294 taint_master_node
295 install_helm
296 track k8scluster install_helm_ok
297 install_k8s_storageclass
298 track k8scluster k8s_storageclass_ok
299 install_helm_metallb
300 track k8scluster k8s_metallb_ok
301 check_for_readiness
302 track k8scluster k8s_ready_ok
303