開發 Ansible Playbooks 部署 Kubernetes v1.11.x HA 叢集

本篇將介紹如何透過 Ansible Playbooks 來快速部署多節點 Kubernetes,一般自建 Kubernetes 叢集時,很多初步入門都會透過 kubeadm 或腳本來部署,雖然 kubeadm 簡化了很多流程,但是還是需要很多手動操作過程,這使得當節點超過 5 - 8 台時就覺得很麻煩,因此許多人會撰寫腳本來解決這個問題,但是腳本的靈活性不佳,一旦設定過程過於龐大時也會造成其複雜性增加,因此這邊採用 Ansible 來完成許多重複的部署過程,並提供相關變數來調整叢集部署的元件、Container Runtime 等等。

這邊我將利用自己撰寫的 kube-ansible 來部署一組 Kubernetes HA 叢集,而該 Playbooks 的 HA 是透過 HAProxy + Keepalived 來完成,這邊也會將 docker 取代成 containerd 來提供更輕量的 container runtime,另外該 Ansible 會採用全二進制檔案(kube-apiserver 等除外)方式進行安裝。

本次 Kubernetes 安裝版本:

  • Kubernetes v1.11.2
  • Etcd v3.2.9
  • containerd v1.1.2

節點資訊

本次安裝作業系統採用Ubuntu 16+,測試環境為實體主機:

IP Address Role CPU Memory
172.22.132.8 VIP
172.22.132.9 k8s-m1 4 16G
172.22.132.10 k8s-m2 4 16G
172.22.132.11 k8s-m3 4 16G
172.22.132.12 k8s-g1 4 16G
172.22.132.13 k8s-g2 4 16G

理論上CentOS 7.xDebian 8都可以。

事前準備

安裝前需要確認以下幾個項目:

  • 所有節點的網路之間可以互相溝通。
  • 部署節點對其他節點不需要 SSH 密碼即可登入。
  • 所有節點都擁有 Sudoer 權限,並且不需要輸入密碼。
  • 所有節點需要安裝 Python
  • 所有節點需要設定/etc/host解析到所有主機。
  • 部署節點需要安裝 Ansible。

Ubuntu 16.04 安裝 Ansible:

$ sudo apt-get install -y software-properties-common git cowsay
$ sudo apt-add-repository -y ppa:ansible/ansible
$ sudo apt-get update && sudo apt-get install -y ansible

CentOS 7 安裝 Ansible:

$ sudo yum install -y epel-release
$ sudo yum -y install ansible cowsay

Mac OS X 安裝 Ansible:

$ brew install ansible

透過 Ansible 部署 Kubernetes

本節將說明如何使用 Ansible 來部署 Kubernetes HA 叢集,首先我們透過 Git 取得專案:

$ git clone https://github.com/kairen/kube-ansible.git
$ cd kube-ansible

Kubernetes 叢集

首先建立一個檔案inventory/hosts.ini來描述被部署的節點與群組關析:

[etcds]
k8s-m[1:3] ansible_user=ubuntu

[masters]
k8s-m[1:3] ansible_user=ubuntu

[nodes]
k8s-g1 ansible_user=ubuntu
k8s-g2 ansible_user=ubuntu

[kube-cluster:children]
masters
nodes

ansible_user為作業系統 SSH 的使用者名稱。

接著編輯group_vars/all.yml來根據需求設定功能,如以下範例:


kube_version: 1.11.2

container_runtime: containerd

cni_enable: true
container_network: calico
cni_iface: "" # CNI 網路綁定的網卡

vip_interface: "" # VIP 綁定的網卡
vip_address: 172.22.132.8 # VIP 位址

etcd_iface: "" # etcd 綁定的網卡

enable_ingress: true
enable_dashboard: true
enable_logging: true
enable_monitoring: true
enable_metric_server: true

grafana_user: "admin"
grafana_password: "[email protected]"

上面綁定網卡若沒有輸入,通常會使用節點預設網卡(一般來說是第一張網卡)。

完成設定group_vars/all.yml檔案後,就可以先透過 Ansible 來檢查叢集狀態:

$ ansible -i inventory/hosts.ini all -m ping
k8s-g1 | SUCCESS => {
"changed": false,
"ping": "pong"
}
...

當叢集確認沒有問題後,即可執行cluster.yml來部署 Kubernetes 叢集:

$ ansible-playbook -i inventory/hosts.ini cluster.yml
...
PLAY RECAP ***********************************************************************************************************************
k8s-g1 : ok=64 changed=32 unreachable=0 failed=0
k8s-g2 : ok=62 changed=32 unreachable=0 failed=0
k8s-m1 : ok=171 changed=85 unreachable=0 failed=0
k8s-m2 : ok=144 changed=69 unreachable=0 failed=0
k8s-m3 : ok=144 changed=69 unreachable=0 failed=0

確認都沒發生錯誤後,表示部署完成。

這邊選擇一台 master 節點(k8s-m1)來 SSH 進入測試叢集是否正常,透過 kubectl 指令來查看:

# 查看元件狀態
$ kubectl get cs
NAME STATUS MESSAGE ERROR
controller-manager Healthy ok
scheduler Healthy ok
etcd-1 Healthy {"health": "true"}
etcd-2 Healthy {"health": "true"}
etcd-0 Healthy {"health": "true"}

# 查看節點狀態
$ kubectl get no
NAME STATUS ROLES AGE VERSION
k8s-g1 Ready <none> 3m v1.11.2
k8s-g2 Ready <none> 3m v1.11.2
k8s-m1 Ready master 5m v1.11.2
k8s-m2 Ready master 5m v1.11.2
k8s-m3 Ready master 5m v1.11.2

Addons 部署

確認節點沒問題後,就可以透過addons.yml來部署 Kubernetes extra addons:

$ ansible-playbook -i inventory/hosts.ini addons.yml
...
PLAY RECAP ***********************************************************************************************************************
k8s-m1 : ok=27 changed=22 unreachable=0 failed=0
k8s-m2 : ok=10 changed=5 unreachable=0 failed=0
k8s-m3 : ok=10 changed=5 unreachable=0 failed=0

完成後即可透過 kubectl 來檢查服務,如 kubernetes-dashboard:

$ kubectl get po,svc -n kube-system -l k8s-app=kubernetes-dashboard
NAME READY STATUS RESTARTS AGE
pod/kubernetes-dashboard-6948bdb78-bkqbr 1/1 Running 0 32m

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes-dashboard ClusterIP 10.105.199.72 <none> 443/TCP 32m

完成後,即可透過 API Server 的 Proxy 來存取 https://172.22.132.8:8443/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/。

測試是否有 HA

首先透過 etcdctl 來檢查狀態:

$ export PKI="/etc/kubernetes/pki/etcd"
$ ETCDCTL_API=3 etcdctl \
--cacert=${PKI}/etcd-ca.pem \
--cert=${PKI}/etcd.pem \
--key=${PKI}/etcd-key.pem \
--endpoints="https://172.22.132.9:2379" \
member list

c9c9f1e905ce83ae, started, k8s-m1, https://172.22.132.9:2380, https://172.22.132.9:2379
cb81b1446a3a689f, started, k8s-m3, https://172.22.132.11:2380, https://172.22.132.11:2379
db0b2674ebb24f80, started, k8s-m2, https://172.22.132.10:2380, https://172.22.132.10:2379

接著進入k8s-m1節點測試叢集 HA 功能,這邊先關閉該節點:

$ sudo poweroff

接著進入到k8s-m2節點,透過 kubectl 來檢查叢集是否能夠正常執行:

# 先檢查元件狀態
$ kubectl get cs
NAME STATUS MESSAGE ERROR
controller-manager Healthy ok
scheduler Healthy ok
etcd-2 Healthy {"health": "true"}
etcd-1 Healthy {"health": "true"}
etcd-0 Unhealthy Get https://172.22.132.9:2379/health: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)

# 檢查 nodes 狀態
$ kubectl get no
NAME STATUS ROLES AGE VERSION
k8s-g1 Ready <none> 10m v1.11.2
k8s-g2 Ready <none> 10m v1.11.2
k8s-m1 NotReady master 12m v1.11.2
k8s-m2 Ready master 12m v1.11.2
k8s-m3 Ready master 12m v1.11.2

# 測試是否可以建立 Pod
$ kubectl run nginx --image nginx --restart=Never --port 80
$ kubectl expose pod nginx --port 80 --type NodePort
$ kubectl get po,svc
NAME READY STATUS RESTARTS AGE
pod/nginx 1/1 Running 0 1m

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3h
service/nginx NodePort 10.102.191.102 <none> 80:31780/TCP 6s

透過 cURL 檢查 NGINX 服務是否正常:

$ curl 172.22.132.8:31780
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...

重置叢集

最後若想要重新部署叢集的話,可以透過reset-cluster.yml來清除叢集:

$ ansible-playbook -i inventory/hosts.ini reset-cluster.yml

Share Comments