使用kubeasz自動化部署K8s

本文首發於我的個人網站: https://hewanyue.com/
本文作者: Hechao
本文鏈接: https://hewanyue.com/blog/8f374cb8.html

  本文使用kubeasz項目基於二進制方式部署和利用ansible-playbook實現自動化部署K8s。
  架構圖如下所示
在這裏插入圖片描述
kubeasz官方文檔中高可用集羣所需節點配置如下

角色 數量 描述
管理節點 1 運行ansible/easzctl腳本,可以複用master,建議使用獨立節點(1c1g)
etcd節點 3 注意etcd集羣需要1,3,5,7…奇數個節點,一般複用master節點
master節點 2 高可用集羣至少2個master節點
node節點 3 運行應用負載的節點,可根據需要提升機器配置/增加節點數

配置集羣環境

  此次部署節點設置如下:
ansible安裝節點&master1:172.18.32.18
master2:172.18.32.19
harbor:172.19.32.20
node1:172.18.32.21
node2:172.18.32.22
etcd1:172.18.32.23
etcd2:172.18.32.24
etcd3:172.18.32.25
haproxy1+keepalived:172.18.32.183
haproxy2+keepalived:172.18.32.184 VIP:172.18.32.250

配置免密登錄

  先將ansible安裝節點也就是master1主機(可以不復用主機)的祕鑰分發至各個主機。

vim fenfamiyao.sh

#!/bin/bash
#目標主機列表
PASSWORD="password"
PORT="22"

IP="
172.18.32.18
172.18.32.19
172.18.32.20
172.18.32.21
172.18.32.22
172.18.32.23
172.18.32.24
172.18.32.25
"

[ -a /root/.ssh/id_rsa ] || ssh-keygen -t rsa 
which sshpass &> /dev/null || yum install sshpass -y #適用於CentOS

for node in ${IP};do
        sshpass -p $PASSWORD ssh-copy-id -p$PORT -o StrictHostKeyChecking=no ${node}
#        if [ $? -eq 0 ];then
#                echo "${node} 祕鑰 copy 完成,準備環境初始化....."
#                ssh -p$PORT ${node} "mkdir /etc/docker/certs.d/harbor.hechao.com -p"
#                echo "Harbor 證書目錄創建成功!"
#                scp -P$PORT /usr/local/src/harbor/certs/harbor-ca.crt ${node}:/etc/docker/certs.d/harbor.hechao.com/harbor-ca.crt
#                echo "Harbor 證書拷貝成功!"
#                scp -P$PORT /etc/hosts ${node}:/etc/hosts
#                echo "host 文件拷貝完成"
#                scp -r -P$PORT /root/.docker ${node}:/root/
#                echo "Harbor 認證文件拷貝完成!"
#                scp -r -P$PORT /etc/resolv.conf ${node}:/etc/
                 echo "鏡像加速鏈接同步!"
                 ssh ${node} "mkdir -p /etc/docker"
                 scp -r -p$PORT /etc/docker/daemon.json ${node}:/etc/docker/daemon.json
#        else
#                echo "${node} 祕鑰 copy 失敗"
#        fi
done

安裝ansible環境

  因爲要使用ansible批量自動化部署K8s集羣,每個主機都要先安裝ansible環境。
  ubuntu默認的python版本是3.6,而ansible需要python2.7。

apt update
apt install python2.7
ln -s /usr/bin/python2.7 /usr/bin/python

  master1上安裝ansible

apt install ansible

  centos一般是自帶python2.X環境,所以一般不需要在進行額外操作。
  在master1上檢查各節點連通性

ansible all -m ping

配置kubeasz

下載kubeasz

  官方文檔地址爲https://github.com/easzlab/kubeasz,根據適配的K8s版本選擇合適的kubeasz版本。根據官方文檔,目前支持以下版本

集羣版本 kubernetes v1.13, v1.14, v1.15, v1.16
操作系統 CentOS/RedHat 7, Debian 9/10, Ubuntu 1604/1804
運行時 docker 18.06.x-ce, 18.09.x, containerd 1.2.6
網絡 calico, cilium, flannel, kube-ovn, kube-router

  我們下載2.0.3版本的kubeasz,並給予執行權限

curl -C- -fLO --retry 3 https://github.com/easzlab/kubeasz/releases/download/2.0.3/easzup
chmod +x easzup

  可以用file easzup命令看到這是一個ASCII文本文件,其實就是一個shell腳本。

root@DockerUbuntu18:~# file easzup
easzup: Bourne-Again shell script, ASCII text executable

  用vim編輯修改此文件。
  大部分地方無需修改,不過可以設置docker版本爲18.09.9和K8s的版本爲v1.15.5,其他地方不用動。

export DOCKER_VER=18.09.9
export K8S_BIN_VER=v1.15.5

  執行-- help查看腳本使用方法。

root@DockerUbuntu18:~# ./easzup --help
./easzup: illegal option -- -
Usage: easzup [options] [args]
  option: -{DdekSz}
    -C         stop&clean all local containers
    -D         download all into /etc/ansible
    -S         start kubeasz in a container
    -d <ver>   set docker-ce version, default "18.09.9"
    -e <ver>   set kubeasz-ext-bin version, default "0.3.0"
    -k <ver>   set kubeasz-k8s-bin version, default "v1.15.5"
    -m <str>   set docker registry mirrors, default "CN"(used in Mainland,China)
    -p <ver>   set kubeasz-sys-pkg version, default "0.3.2"
    -z <ver>   set kubeasz version, default "2.0.3"
  
see more at https://github.com/kubeasz/dockerfiles

  先將/etc/ansible目錄下所有自帶的配置文件以及hosts文件刪掉

\rm -rf /etc/ansible/*

  執行腳本下載所有需要的鏡像和二進制文件

./easzup -D

  稍等片刻之後,下載好需要的鏡像和二進制文件,此時就可以開始ansible自動部署安裝K8s集羣了。

ansible部署K8s

  kubeasz工具都已經寫好了playbook,只需要設定好hosts文件即可一鍵安裝了。先進入/etc/ansible目錄,然後複製提供好的host模版文件並編輯。

cd /etc/ansible/
cp example/hosts.multi-node hosts
vim hosts
root@DockerUbuntu18:/etc/ansible# grep -v ^# hosts|grep -v ^$
[etcd]
172.18.32.23 NODE_NAME=etcd1
172.18.32.24 NODE_NAME=etcd2
172.18.32.25 NODE_NAME=etcd3
[kube-master]
172.18.32.18
172.18.32.19
[kube-node]
172.18.32.21
172.18.32.22
[harbor]
[ex-lb]
[chrony]
[all:vars]
CONTAINER_RUNTIME="docker"
CLUSTER_NETWORK="calico"
SERVICE_CIDR="10.68.0.0/16"
CLUSTER_CIDR="172.20.0.0/16"
NODE_PORT_RANGE="30000-65000"
CLUSTER_DNS_DOMAIN="cluster.local."
bin_dir="/usr/kube/bin"
ca_dir="/etc/kubernetes/ssl"
base_dir="/etc/ansible"

  以爲我本地已經搭好harbor服務器了,所以就不要設置harbor服務讓他來安裝了。除了各節點IP以外,需要修改的就是bin_dir目錄,這樣就省去了創建軟鏈接的步驟,也省去配置PATH變量了。我選擇的網卡是calico,也可以使用默認的flannel,之後具體區別會再詳細介紹。
  直接執行 playbook劇本90.setup.yml可以直接一鍵安裝完成,不過如果出現問題我們不好排錯,推薦一個劇本一個劇本的來跑。

  • 01.prepare.yml
ansible-playbook 01.prepare.yml

  這個劇本總共三個環節,一般來說都不會報錯(如果提示軟鏈接創建失敗,則可忽略)。
  1.如果設置了chrony服務器,則master、node、etcd主機都會向chrony服務器同步時間。
  2.控制節點上創建CA、創建集羣參數及客戶端認證參數
  3分發證書工具CFSSL及kubeconfig配置文件

  • 02.etcd.yml
ansible-playbook 02.etcd.yml

  這個劇本是在配置etcd服務器。在3個etcd節點上,創建etcd目錄並分發證書,導入之前下載在控制端的二進制程序etcdetcdctl及導入etcd的systemctl unit文件,設置開機自動啓動etcd服務。這步也很簡單,一般也不會出現什麼問題。

  • 03.docker.yml

  因爲我們在hosts文件中設置了運行時爲docker,所以我們第三個劇本選擇03.docker.yml,選擇執行03.containerd,yml劇本也不會執行,裏面做了條件判斷

root@DockerUbuntu18:/etc/ansible# cat 03.containerd.yml 
# to install containerd service
- hosts:
  - kube-master
  - kube-node
  roles:
  - { role: containerd, when: "CONTAINER_RUNTIME == 'containerd'" } 

  這個階段的劇本比較複雜,要在每一個節點上安裝docker,在執行這一步之前,先檢查一下模版二進制文件的docker版本是否和我們之前預設的一樣。

/etc/ansible/bin/docker -v
Docker version 18.09.6, build 481bc77

  如果不一樣,可以去/opt/kube/bin/目錄下找一下之前下好的二進制文件,確認下版本。

/opt/kube/bin/docker -v

  這個目錄下的版本一般是不會錯的,將此目錄下的二進制文件複製至模版目錄/etc/ansible/bin/

cp /opt/kube/bin/* /etc/ansible/bin/

  執行ansible劇本

ansible-playbook 03.docker.yml
  • 04.kube-master.yml

  這個劇本是對兩個master節點操作,執行了以下操作
  1.創建kubernetes簽名請求以及證書和私鑰
  2.導入配置文件,啓動kube-apiserver、kube-controller-manager及kube-scheduler服務
  3.設置主節點的kube-apiserver.service文件,並設置apiserver的IP地址並創建配置用戶rbac權限。
  此時使用命令kubectl get node可以看到兩個主節點都是出於ready狀態了。

root@DockerUbuntu18:~# kubectl get node
NAME           STATUS                     ROLES    AGE    VERSION
172.18.32.18   Ready,SchedulingDisabled   master   1m    v1.15.5
172.18.32.19   Ready,SchedulingDisabled   master   1m    v1.15.5
  • 05…kube-node.yml

  這個劇本主要是將幾個node節點加到集羣中來。流程比較複雜,大致有以下步驟:
  1,創建kube-node目錄:/var/lib/kubelet、/var/lib/kube-proxy和/etc/cni/net.d目錄
  2.導入之前準備好的二進制可執行文件kubectl、kubelet、kube-proxy、bridge、host-local和loopback
  3.配置haproxy,監聽本地的127.0.0.1:6443端口,代理至兩個主節點的6443端口
  4.生成node節點的kubelet的配置文件,並分發至各個node節點。kubelet連接主節點的apiserver。
  5.node節點連接後,對node節點標記爲kubernetes.io/role=node

  這步很容易出現kubelet服務無法啓動,或者一直處於loaded狀態,返回值爲255。這是因爲node節點的kubelet的認證失敗。可以去node節點主機上查看服務kubelet服務狀態。

systemctl status kubectl
journalctl -u kubelet -e

  我遇到幾次node節點kubelet無法正常啓動的情況,但是換了個全新的node節點就可以加進去了,說明問題不是在主節點上,一般將node節點還原至乾淨系統都可以解決問題。
  還有一次返回值255但報錯提示是,找不到/run/systemd/resolve/resolv.conf文件,於是創建一個

mkdir /run/systemd/resolve/;echo "nameserver 233.5.5.5" > /run/systemd/resolve/resolv.conf

  自己創建一個解析之後問題解決。
  順利的話,使用kubectl get node可以看到主節點和node節點都處於ready狀態。

root@DockerUbuntu18:/etc/ansible# kubectl get node
NAME           STATUS                     ROLES    AGE   VERSION
172.18.32.18   Ready,SchedulingDisabled   master   2h   v1.15.5
172.18.32.19   Ready,SchedulingDisabled   master   2h   v1.15.5
172.18.32.21   Ready                      node     2h   v1.15.5
172.18.32.22   Ready                      node     2h   v1.15.5
  • 06.network.yml

  在這個劇本中,主要是配置各個pod之間的網絡訪問。需要在每個物理節點上都生成一個calico-node服務的pod,再啓動一個calico-kube-controllers服務的pod來管理他們,(因爲默認主節點設置了不可調度,所以這個calico-kube-contronllers一般是在node節點上生成)。因爲使用的是pod方式啓動,所以這個劇本中,除了配置calicao證書及私鑰外,主要是生成了一個calico DaemonSet yaml文件,路徑爲/opt/kube/kube-system/calico.yaml,所以之後如果修改網絡配置,可以直接在此路徑下修改這個yaml文件,例如如果想要修改鏡像地址爲私有harbor地址,則

kubectl delete -f /opt/kube/kube-system/calico.yaml
vim /opt/kube/kube-system/calico.yaml
kubectl apply -f /opt/kube/kube-system/calico.yaml

  需要注意的是,如果將yaml文件中拉取鏡像的地址改爲了私有harbor,則需要在yaml文件中加入Secret資源,使用imagePullSecrets拉取。
  當我們的node節點不需要跨網段時,通常會選擇將IPIP模式(ip-in-ip疊加模式)關掉,使用calico的BGP模式,以節約大量主機內部訪問時封裝的性能損耗。
  查看路由,可以看到目前榮期間通信的網絡接口爲tunl0

root@DockerUbuntu18:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.18.0.1      0.0.0.0         UG    0      0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
172.18.0.0      0.0.0.0         255.255.0.0     U     0      0        0 eth0
172.20.185.64   0.0.0.0         255.255.255.192 U     0      0        0 *
172.20.233.128  172.18.32.19    255.255.255.192 UG    0      0        0 tunl0
172.20.250.128  172.18.32.22    255.255.255.192 UG    0      0        0 tunl0
172.20.250.192  172.18.32.21    255.255.255.192 UG    0      0        0 tunl0
192.168.0.0     0.0.0.0         255.255.0.0     U     0      0        0 eth1

  於是可以編輯/etc/ansible/roles/calico/defaults/main.yml或者直接修改/opt/kube/kube-system/calico.yaml文件,將其中的 CALICO_IPV4POOL_IPIP修改爲off,將name: FELIX_IPINIPMTU屬性註釋掉,改爲FELIX_IPINIPENABLED值爲false

            - name: CALICO_IPV4POOL_IPIP
              value: "off"
              
            - name: FELIX_IPINIPENABLED
              value: "false"

  然後執行kubectl delete -f /opt/kube/kube-system/calico.yaml將網絡組件calico的pod都先停掉,reboot重啓後,使用命令ifconfig就會發現,之前使用的tunl0網卡就不見了。再使用命令kubectl apply -f /opt/kube/kube-system/calico.yaml,將k8s網絡連接起來,使用命令route -n查看路由信息,就會發現,跨主機通信直接使用eth0網卡了。此時模式從IPIP修改爲BGP模式。

root@DockerUbuntu18:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.18.0.1      0.0.0.0         UG    0      0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
172.18.0.0      0.0.0.0         255.255.0.0     U     0      0        0 eth0
172.20.185.64   0.0.0.0         255.255.255.192 U     0      0        0 *
172.20.233.128  172.18.32.19    255.255.255.192 UG    0      0        0 eth0
172.20.250.128  172.18.32.22    255.255.255.192 UG    0      0        0 eth0
172.20.250.192  172.18.32.21    255.255.255.192 UG    0      0        0 eth0
192.168.0.0     0.0.0.0         255.255.0.0     U     0      0        0 eth1
  • 07.cluster-addon.yml

  第七步是安裝一些功能插件,如在node節點生成dns解析(默認使用的是coredns,可以在roles/cluster-addon/defaults/main.yml文件中設置),安裝dashboard(可視化web界面)。我們也可以選擇自己安裝這些功能插件。
  可參考官方文檔https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/#deploying-the-dashboard-ui
  dashboard默認是1.6.3版本的,比較老。我們這裏手動安裝dashboard1.10.1版本,過程如下

cd /etc/ansible/manifests/dashboard
mkdir 1.10.1
cp 1.6.3/ui* 1.10.1/
cd 1.10.1

  先下載yaml文檔

wget https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml

  再創建admin tokenvim admin-user-sa-rbac.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kube-system

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kube-system

  創建集羣角色vim read-user-sa-rbac.yaml

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: dashboard-read-clusterrole
rules:
- apiGroups:
  - ""
  resources:
  - configmaps
  - endpoints
  - persistentvolumeclaims
  - pods
  - replicationcontrollers
  - replicationcontrollers/scale
  - serviceaccounts
  - services
  - nodes
  - persistentvolumeclaims
  - persistentvolumes
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - bindings
  - events
  - limitranges
  - namespaces/status
  - pods/log
  - pods/status
  - replicationcontrollers/status
  - resourcequotas
  - resourcequotas/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - namespaces
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - apps
  resources:
  - daemonsets
  - deployments
  - deployments/scale
  - replicasets
  - replicasets/scale
  - statefulsets
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - autoscaling
  resources:
  - horizontalpodautoscalers
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - batch
  resources:
  - cronjobs
  - jobs
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - extensions
  resources:
  - daemonsets
  - deployments
  - deployments/scale
  - ingresses
  - networkpolicies
  - replicasets
  - replicasets/scale
  - replicationcontrollers/scale
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - policy
  resources:
  - poddisruptionbudgets
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - networking.k8s.io
  resources:
  - networkpolicies
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - storage.k8s.io
  resources:
  - storageclasses
  - volumeattachments
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - rbac.authorization.k8s.io
  resources:
  - clusterrolebindings
  - clusterroles
  - roles
  - rolebindings
  verbs:
  - get
  - list
  - watch

  此時目錄結構如下

root@DockerUbuntu18:/etc/ansible/manifests/dashboard/1.10.1# tree
.
├── admin-user-sa-rbac.yaml
├── kubernetes-dashboard.yaml
├── read-user-sa-rbac.yaml
├── ui-admin-rbac.yaml
└── ui-read-rbac.yaml

0 directories, 5 files

  然後通過yaml文件啓動dashboard的pod

kubectl apply -f .

  可以通過命令查看pod 是否啓動成功。

kubectl get pods --all-namespaces | grep dashboard

  看到狀態running之後,輸入命令開啓認證生成登陸用戶名密碼

easzctl basic-auth -s
[INFO]basic-auth for apiserver is enabled!
BASIC_AUTH_USER: 'admin'
BASIC_AUTH_PASS: '4fe554e56c32f27b'
[INFO] Action successed : basic-auth basic-auth -s`

  通過命令kubectl cluster-info查看集羣信息來查看登陸url

kubectl cluster-info

  使用命令來獲取token

kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')

  這時就可以登陸web界面查看K8s集羣信息了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章