4bb91fef9cdc459cf9817b149b9ee0ce1cae4f0c
[it/dep.git] / ric-infra / 00-Kubernetes / heat / scripts / k8s_vm_install.sh
1 #!/bin/bash -x
2 ################################################################################
3 #   Copyright (c) 2019 AT&T Intellectual Property.                             #
4 #   Copyright (c) 2019 Nokia.                                                  #
5 #                                                                              #
6 #   Licensed under the Apache License, Version 2.0 (the "License");            #
7 #   you may not use this file except in compliance with the License.           #
8 #   You may obtain a copy of the License at                                    #
9 #                                                                              #
10 #       http://www.apache.org/licenses/LICENSE-2.0                             #
11 #                                                                              #
12 #   Unless required by applicable law or agreed to in writing, software        #
13 #   distributed under the License is distributed on an "AS IS" BASIS,          #
14 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
15 #   See the License for the specific language governing permissions and        #
16 #   limitations under the License.                                             #
17 ################################################################################
18
19
20 # first parameter: number of expected running pods
21 # second parameter: namespace (all-namespaces means all namespaces)
22 # third parameter: [optional] keyword
23 wait_for_pods_running () {
24   NS="$2"
25   CMD="kubectl get pods --all-namespaces "
26   if [ "$NS" != "all-namespaces" ]; then
27     CMD="kubectl get pods -n $2 "
28   fi
29   KEYWORD="Running"
30   if [ "$#" == "3" ]; then
31     KEYWORD="${3}.*Running"
32   fi
33
34   CMD2="$CMD | grep \"$KEYWORD\" | wc -l"
35   NUMPODS=$(eval "$CMD2")
36   echo "waiting for $NUMPODS/$1 pods running in namespace [$NS] with keyword [$KEYWORD]"
37   while [  $NUMPODS -lt $1 ]; do
38     sleep 5
39     NUMPODS=$(eval "$CMD2")
40     echo "> waiting for $NUMPODS/$1 pods running in namespace [$NS] with keyword [$KEYWORD]"
41   done 
42 }
43
44
45 # first parameter: interface name
46 start_ipv6_if () {
47   # enable ipv6 interface
48   # standard Ubuntu cloud image does not have dual interface configuration or ipv6
49   IPv6IF="$1"
50   if ifconfig -a $IPv6IF; then
51     echo "" >> /etc/network/interfaces.d/50-cloud-init.cfg
52     #echo "auto ${IPv6IF}" >> /etc/network/interfaces.d/50-cloud-init.cfg
53     echo "allow-hotplug ${IPv6IF}" >> /etc/network/interfaces.d/50-cloud-init.cfg
54     echo "iface ${IPv6IF} inet6 auto" >> /etc/network/interfaces.d/50-cloud-init.cfg
55     #dhclient -r $IPv6IF
56     #systemctl restart networking
57     ifconfig ${IPv6IF} up
58   fi
59 }
60
61 echo "k8s_vm_install.sh"
62 set -x
63 export DEBIAN_FRONTEND=noninteractive
64 echo "__host_private_ip_addr__ $(hostname)" >> /etc/hosts
65 printenv
66
67 mkdir -p /opt/config
68 echo "__docker_version__" > /opt/config/docker_version.txt
69 echo "__k8s_version__" > /opt/config/k8s_version.txt
70 echo "__k8s_cni_version__" > /opt/config/k8s_cni_version.txt
71 echo "__helm_version__" > /opt/config/helm_version.txt
72 echo "__host_private_ip_addr__" > /opt/config/host_private_ip_addr.txt
73 echo "__k8s_mst_floating_ip_addr__" > /opt/config/k8s_mst_floating_ip_addr.txt
74 echo "__k8s_mst_private_ip_addr__" > /opt/config/k8s_mst_private_ip_addr.txt
75 echo "__mtu__" > /opt/config/mtu.txt
76 echo "__cinder_volume_id__" > /opt/config/cinder_volume_id.txt
77 echo "__stack_name__" > /opt/config/stack_name.txt
78
79 ISAUX='false'
80 if [[ $(cat /opt/config/stack_name.txt) == *aux* ]]; then
81   ISAUX='true'
82 fi
83
84 modprobe -- ip_vs
85 modprobe -- ip_vs_rr
86 modprobe -- ip_vs_wrr
87 modprobe -- ip_vs_sh
88 modprobe -- nf_conntrack_ipv4
89 modprobe -- nf_conntrack_ipv6
90 modprobe -- nf_conntrack_proto_sctp
91
92 start_ipv6_if ens4
93
94 # disable swap
95 SWAPFILES=$(grep swap /etc/fstab | sed '/^#/ d' |cut -f1 -d' ')
96 if [ ! -z $SWAPFILES ]; then
97   for SWAPFILE in $SWAPFILES
98   do
99     if [ ! -z $SWAPFILE ]; then
100       echo "disabling swap file $SWAPFILE"
101       if [[ $SWAPFILE == UUID* ]]; then
102         UUID=$(echo $SWAPFILE | cut -f2 -d'=')
103         swapoff -U $UUID
104       else
105         swapoff $SWAPFILE
106       fi
107       # edit /etc/fstab file, remove line with /swapfile
108       sed -i -e "/$SWAPFILE/d" /etc/fstab
109     fi
110   done
111 fi
112 # disable swap
113 #swapoff /swapfile
114 # edit /etc/fstab file, remove line with /swapfile
115 #sed -i -e '/swapfile/d' /etc/fstab
116
117
118 DOCKERV=$(cat /opt/config/docker_version.txt)
119 KUBEV=$(cat /opt/config/k8s_version.txt)
120 KUBECNIV=$(cat /opt/config/k8s_cni_version.txt)
121
122 KUBEVERSION="${KUBEV}-00"
123 CNIVERSION="${KUBECNIV}-00"
124 DOCKERVERSION="${DOCKERV}"
125 curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
126 echo 'deb http://apt.kubernetes.io/ kubernetes-xenial main' > /etc/apt/sources.list.d/kubernetes.list
127
128 # tell apt to retry 3 times if failed
129 mkdir -p /etc/apt/apt.conf.d
130 echo "APT::Acquire::Retries \"3\";" > /etc/apt/apt.conf.d/80-retries
131
132 # install low latency kernel, docker.io, and kubernetes
133 apt-get update
134 apt-get install -y virt-what
135 if ! echo $(virt-what) | grep "virtualbox"; then
136   # this version of low latency kernel causes virtualbox VM to hand.  
137   # install if identifying the VM not being a virtualbox VM.
138   apt-get install -y linux-image-4.15.0-45-lowlatency
139 fi
140 if [ -z ${DOCKERVERSION} ]; then
141   apt-get install -y curl jq netcat docker.io
142 else
143   apt-get install -y curl jq netcat docker.io=${DOCKERVERSION}
144 fi
145 apt-get install -y kubernetes-cni=${CNIVERSION}
146 apt-get install -y --allow-unauthenticated kubeadm=${KUBEVERSION} kubelet=${KUBEVERSION} kubectl=${KUBEVERSION}
147 apt-mark hold docker.io kubernetes-cni kubelet kubeadm kubectl
148
149
150 # test access to k8s docker registry
151 kubeadm config images pull
152
153
154 # non-master nodes have hostnames ending with -[0-9][0-9]
155 if [[ $(hostname) == *-[0-9][0-9] ]]; then
156   echo "Done for non-master node"
157   echo "Starting an NC TCP server on port 29999 to indicate we are ready"
158   nc -l -p 29999 &
159 else 
160   # below are steps for initializating master node, only run on the master node.  
161   # minion node join will be triggered from the caller of the stack creation as ssh command.
162
163
164   # create kubenetes config file
165   if [[ ${KUBEV} == 1.13.* ]]; then
166     cat <<EOF >/root/config.yaml
167 apiVersion: kubeadm.k8s.io/v1alpha3
168 kubernetesVersion: v${KUBEV}
169 kind: ClusterConfiguration
170 apiServerExtraArgs:
171   feature-gates: SCTPSupport=true
172 networking:
173   dnsDomain: cluster.local
174   podSubnet: 10.244.0.0/16
175   serviceSubnet: 10.96.0.0/12
176
177 ---
178 apiVersion: kubeproxy.config.k8s.io/v1alpha1
179 kind: KubeProxyConfiguration
180 mode: ipvs
181 EOF
182
183   elif [[ ${KUBEV} == 1.14.* ]]; then
184     cat <<EOF >/root/config.yaml
185 apiVersion: kubeadm.k8s.io/v1beta1
186 kubernetesVersion: v${KUBEV}
187 kind: ClusterConfiguration
188 apiServerExtraArgs:
189   feature-gates: SCTPSupport=true
190 networking:
191   dnsDomain: cluster.local
192   podSubnet: 10.244.0.0/16
193   serviceSubnet: 10.96.0.0/12
194
195 ---
196 apiVersion: kubeproxy.config.k8s.io/v1alpha1
197 kind: KubeProxyConfiguration
198 mode: ipvs
199 EOF
200
201   else
202     echo "Unsupported Kubernetes version requested.  Bail."
203     exit
204   fi
205
206
207   # create a RBAC file for helm (tiller)
208   cat <<EOF > /root/rbac-config.yaml
209 apiVersion: v1
210 kind: ServiceAccount
211 metadata:
212   name: tiller
213   namespace: kube-system
214 ---
215 apiVersion: rbac.authorization.k8s.io/v1
216 kind: ClusterRoleBinding
217 metadata:
218   name: tiller
219 roleRef:
220   apiGroup: rbac.authorization.k8s.io
221   kind: ClusterRole
222   name: cluster-admin
223 subjects:
224   - kind: ServiceAccount
225     name: tiller
226     namespace: kube-system
227 EOF
228
229   # start cluster (make sure CIDR is enabled with the flag)
230   kubeadm init --config /root/config.yaml
231
232
233   # install Helm
234   HELMV=$(cat /opt/config/helm_version.txt)
235   HELMVERSION=${HELMV}
236   cd /root
237   mkdir Helm
238   cd Helm
239   wget https://storage.googleapis.com/kubernetes-helm/helm-v${HELMVERSION}-linux-amd64.tar.gz
240   tar -xvf helm-v${HELMVERSION}-linux-amd64.tar.gz
241   mv linux-amd64/helm /usr/local/bin/helm
242
243   # set up kubectl credential and config
244   cd /root
245   rm -rf .kube
246   mkdir -p .kube
247   cp -i /etc/kubernetes/admin.conf /root/.kube/config
248   chown root:root /root/.kube/config
249
250   # at this point we should be able to use kubectl
251   kubectl get pods --all-namespaces
252
253   # install flannel
254   kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/bc79dd1505b0c8681ece4de4c0d86c5cd2643275/Documentation/kube-flannel.yml
255
256
257   # waiting for all 8 kube-system pods to be in running state
258   # (at this point, minions have not joined yet)
259   wait_for_pods_running 8 kube-system
260
261   # if running a single node cluster, need to enable master node to run pods
262   kubectl taint nodes --all node-role.kubernetes.io/master-
263
264   cd /root
265   # install RBAC for Helm
266   kubectl create -f rbac-config.yaml
267
268
269   rm -rf /root/.helm
270   helm init --service-account tiller
271   export HELM_HOME="/root/.helm"
272
273   # waiting for tiller pod to be in running state
274   wait_for_pods_running 1 kube-system tiller-deploy
275
276   while ! helm version; do
277     echo "Waiting for Helm to be ready"
278     sleep 15
279   done
280
281   echo "Preparing a master node (lowser ID) for using local FS for PV"
282   PV_NODE_NAME=$(kubectl get nodes |grep master | cut -f1 -d' ' | sort | head -1)
283   kubectl label --overwrite nodes $PV_NODE_NAME local-storage=enable
284   if [ "$PV_NODE_NAME" == "$(hostname)" ]; then
285     mkdir -p /opt/data/dashboard-data
286   fi
287
288   echo "Starting an NC TCP server on port 29999 to indicate we are ready"
289   nc -l -p 29999 &
290
291   echo "Done with master node setup"
292 fi
293
294
295 # add rancodev CI tool hostnames
296 if [[ ! -z "${__RUNRICENV_GERRIT_IP__}" && ! -z "${__RUNRICENV_GERRIT_HOST__}" ]]; then 
297   echo "${__RUNRICENV_GERRIT_IP__} ${__RUNRICENV_GERRIT_HOST__}" >> /etc/hosts
298 fi
299 if [[ ! -z "${__RUNRICENV_DOCKER_IP__}" && ! -z "${__RUNRICENV_DOCKER_HOST__}" ]]; then 
300   echo "${__RUNRICENV_DOCKER_IP__} ${__RUNRICENV_DOCKER_HOST__}" >> /etc/hosts
301 fi
302 if [[ ! -z "${__RUNRICENV_HELMREPO_IP__}" && ! -z "${__RUNRICENV_HELMREPO_HOST__}" ]]; then 
303   echo "${__RUNRICENV_HELMREPO_IP__} ${__RUNRICENV_HELMREPO_HOST__}" >> /etc/hosts
304 fi
305
306 if [ ! -z "${__RUNRICENV_HELMREPO_CERT__}" ]; then
307   cat <<EOF >/etc/ca-certificates/update.d/helm.crt
308 ${__RUNRICENV_HELMREPO_CERT__}
309 EOF
310 fi
311
312 # add cert for accessing docker registry in Azure
313 if [ ! -z "${__RUNRICENV_DOCKER_CERT__}" ]; then
314   mkdir -p /etc/docker/certs.d/${__RUNRICENV_DOCKER_HOST__}:${__RUNRICENV_DOCKER_PORT__}
315   cat <<EOF >/etc/docker/ca.crt
316 ${__RUNRICENV_DOCKER_CERT__}
317 EOF
318   cp /etc/docker/ca.crt /etc/docker/certs.d/${__RUNRICENV_DOCKER_HOST__}:${__RUNRICENV_DOCKER_PORT__}/ca.crt
319
320   service docker restart
321   systemctl enable docker.service
322   docker login -u ${__RUNRICENV_DOCKER_USER__} -p ${__RUNRICENV_DOCKER_PASS__} ${__RUNRICENV_DOCKER_HOST__}:${__RUNRICENV_DOCKER_PORT__}
323   docker pull ${__RUNRICENV_DOCKER_HOST__}:${__RUNRICENV_DOCKER_PORT__}/whoami:0.0.1
324 fi
325