k8s 學習(2)——使用 ansible-playbook 搭建 k8s 環境
上一篇博客記錄了一下在 CentOS 下搭建 k8s 環境的方式,主要是使用的 shell 腳本執行安裝部署命令。但是執行腳本終究只能人工執行,而且無法大批量安裝,而本篇博客就使用批量執行工具 ansible 來自動化安裝 k8s 環境。
步驟梳理
首先在介紹 ansible 編排之前,先梳理一下搭建 k8s 環境的步驟(之前的 shell 腳本部署方式有詳細步驟註釋)。
- 所有節點安裝 docker-ce
- 所有節點配置 k8s 環境
- master 節點安裝 k8s,並啓動 flannel 服務
- node 節點安裝 k8s,並執行 join 到主節點的命令
我將整個安裝步驟分爲這4個步驟,於是我的 ansible-playbook 裏面的 roles 也是分成4個 role 來執行任務。
代碼結構
代碼結構基本是按照 ansible-playbook 的結構來的,上面安裝的四個步驟對應的就是 roles 下面的四個目錄:docker、k8s_env、k8s_master、k8s_node,具體的文件作用可以看註釋。
項目代碼已經提交到 GitHub 倉庫,地址爲:https://github.com/Hopetree/k8s
+----deploy | +----ansible.cfg | +----group_vars | | +----all.yml # 部署所需參數 | +----hosts # 節點信息 | +----k8s_install.yml # 執行文件 | +----roles | | +----docker # 安裝docker | | | +----tasks | | | | +----main.yml | | | +----templates | | | | +----daemon.json.j2 | | +----k8s_env # 配置k8s環境 | | | +----tasks | | | | +----main.yml | | | +----templates | | | | +----k8s.conf.j2 | | +----k8s_master # 主節點安裝k8s | | | +----files | | | | +----kube-flannel.yml | | | +----tasks | | | | +----main.yml | | | +----templates | | | | +----kubernetes.repo.j2 | | +----k8s_node # node節點安裝k8s | | | +----tasks | | | | +----main.yml | | | +----templates | | | | +----kubernetes.repo.j2
然後看一下執行文件 k8s_install.yml 中是如何對每個步驟執行機進行劃分的:
---
- hosts: k8s
roles:
- role: docker
become: yes
- role: k8s_env
become: yes
- hosts: master
roles:
- role: k8s_master
become: yes
- hosts: node
roles:
- role: k8s_node
become: yes
其實劃分執行機很簡單,我在 hosts 裏面配置了執行機分類,k8s 就是所有節點,master 就是主節點,node 就是 node 節點,所有使用 hosts 來控制每個步驟的執行機。
安裝流程
安裝 docker(所有節點)
安裝 docker 的步驟跟之前 shell 腳本的流程一樣,只不過把原理的命令行形式改成 ansible 的模塊來編排即可,代碼如下:
---
- name: uninstall docker
yum: name={{ docker.remove_list }} state=absent
- name: rm docker dir
file: path={{ item }} state=absent
with_items:
- /var/lib/docker
- /var/run/docker
- name: install yum-utils
yum: name=yum-utils state=present
- name: add docker repo
shell: yum-config-manager --add-repo {{ docker.repo }}
- name: install docker-ce
yum: name={{ docker.version }} state=present update_cache=True
- name: set docker registry mirrors
template: src=daemon.json.j2 dest=/etc/docker/daemon.json
- name: start docker service
systemd: name=docker enabled=yes daemon_reload=yes state=started
可以把這個 yaml 文件裏面的編排步驟跟之前的 shell 腳本作對比,可以發現基本是每個 shell 命令的操作對應了一個 ansible 步驟。
配置 k8s 環境信息(所有節點)
配置 k8s 環境信息的任務是 k8s_env,具體編排如下:
---
- name: stop firewalld
systemd: name=firewalld state=stopped enabled=no
- name: disabled selinux
shell: "setenforce 0 && sed -i 's/SELINUX=permissive/SELINUX=disabled/' /etc/sysconfig/selinux;sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config"
- name: swap off
shell: "swapoff -a && sed -i 's/.*swap.*/#&/' /etc/fstab"
- name: set k8s conf
template: src=k8s.conf.j2 dest=/etc/sysctl.d/k8s.conf
- name: sysctl --system
shell: sysctl --system
其實這裏的 sed 命令可以使用 replace 模塊來編排,我這裏保留了 shell 命令行。
主節點安裝 k8s
執行編排如下:
---
- name: copy flannel file
copy: src=kube-flannel.yml dest={{ k8s.flannel.path }}
- name: change image url for flannel file
replace: path={{ k8s.flannel.path }} regexp="quay\.io" replace={{ k8s.flannel.image_url }}
- name: set k8s repo
template: src=kubernetes.repo.j2 dest=/etc/yum.repos.d/kubernetes.repo
- name: uninstall kubectl kubeadm kubelet
yum: name=kubectl,kubeadm,kubelet state=absent
- name: install kubectl
yum: name={{ k8s.kubectl }} state=present
- name: install kubelet
yum: name={{ k8s.kubelet }} state=present
- name: install kubeadm
yum: name={{ k8s.kubeadm }} state=present
- name: set systemd for kubelet
systemd: name=kubelet enabled=yes daemon_reload=yes state=started
- name: init kubeadm
shell: "kubeadm init --image-repository {{ k8s.image_repository }} --kubernetes-version {{ k8s.version }} --apiserver-advertise-address {{ ansible_ssh_host }} --pod-network-cidr={{ k8s.pod_netword }}/16 --token-ttl 0"
- name: copy kube config
shell: "mkdir -p $HOME/.kube && sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config && sudo chown $(id -u):$(id -g) $HOME/.kube/config"
- name: apply flannel
shell: "kubectl apply -f {{ k8s.flannel.path }}"
在安裝 kubelet 和 kubeadm 的時候,我遇到了問題,就是我之前是先安裝的 kubeadm 後安裝的 kubelet,然後一直導致 kubelet 的安裝版本跟我設置的版本不一樣,導致最終 k8s 初始化失敗。
後來我查看代碼執行輸出才發現問題,原因是 kubeadm 的安裝依賴於 kubelet,所以如果先安裝 kubeadm,那麼程序會自動安裝一個版本(目測是最新的)的 kubelet,於是後面執行 kubelet 安裝的時候因爲前面自動安裝了,所有會忽略掉,這就是最終導致安裝的版本跟自己設置的版本不一樣的原因。這也給我一個意識,就是如果要安裝多個軟件,如果軟件之前有依賴關係,應該先安裝被依賴的軟件。
node 節點安裝 k8s
看過之前手動部署 k8s 的文章應該記得一個步驟:當 node 節點安裝完 k8s 之後需要執行 join 主機點集羣的命令,而這個命令需要去主節點查詢得到,所有當時是手動查詢然後執行的。所以 ansible 如何做到在當前執行機操作步驟的時候到另外的執行機執行步驟,我當時查到了一種方案就是使用 delegate_to
參數,在模塊中添加這個參數,就可以將該步驟到這個參數指向的 IP 主機上面執行步驟。我這做的就是去主節點查詢命令,然後註冊成一個鍵值對給後面的步驟使用。
---
- name: set k8s repo
template: src=kubernetes.repo.j2 dest=/etc/yum.repos.d/kubernetes.repo
- name: uninstall kubectl kubeadm kubelet
yum: name=kubeadm,kubelet state=absent
- name: install kubelet
yum: name={{ k8s.kubelet }} state=present
- name: install kubeadm
yum: name={{ k8s.kubeadm }} state=present
- name: set systemd for kubelet
systemd: name=kubelet enabled=yes daemon_reload=yes state=started
- name: query kubeadm join command
shell: kubeadm token create --print-join-command
register: kubeadm_join_cmd
delegate_to: "{{ k8s.master_ip }}" # 在主節點上面執行這個任務
- name: print cmd
debug:
var: kubeadm_join_cmd.stdout
- name: join k8s
shell: "{{ kubeadm_join_cmd.stdout }}"
整個任務運行的命令是:
ansible-playbook k8s_install.yml -i hosts -u alex -k -K -v
執行結果如下:
PLAY RECAP ************************************************************************************************************ k8s-master : ok=25 changed=20 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 k8s-node01 : ok=22 changed=17 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 k8s-node02 : ok=22 changed=17 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
所有步驟都沒有報錯之後可以查詢 k8s 集羣狀態,最開始可能會發現只有主節點是 Ready,node 節點還是 NotReady 狀態,這是正常的,因爲之前的文章說過,node 節點需要拉取 flannel 鏡像啓動容器,比較慢,所有需要等一段時間。
過一段時間再查詢狀態可以看到所有節點都是準備好了:
[root@k8s-master alex]# kubectl get pods -o wide -n kube-system NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES coredns-58cc8c89f4-jsgjh 1/1 Running 0 4h56m 10.244.2.3 k8s-node02 <none> <none> coredns-58cc8c89f4-z4zhn 1/1 Running 0 4h56m 10.244.2.2 k8s-node02 <none> <none> etcd-k8s-master 1/1 Running 0 4h55m 192.168.31.76 k8s-master <none> <none> kube-apiserver-k8s-master 1/1 Running 0 4h55m 192.168.31.76 k8s-master <none> <none> kube-controller-manager-k8s-master 1/1 Running 0 4h56m 192.168.31.76 k8s-master <none> <none> kube-flannel-ds-amd64-2sg2q 1/1 Running 0 4h56m 192.168.31.76 k8s-master <none> <none> kube-flannel-ds-amd64-fwtvr 1/1 Running 0 4h55m 192.168.31.133 k8s-node01 <none> <none> kube-flannel-ds-amd64-sph6k 1/1 Running 0 4h55m 192.168.31.178 k8s-node02 <none> <none> kube-proxy-b9tp5 1/1 Running 0 4h55m 192.168.31.178 k8s-node02 <none> <none> kube-proxy-tnfpq 1/1 Running 0 4h55m 192.168.31.133 k8s-node01 <none> <none> kube-proxy-znf9h 1/1 Running 0 4h56m 192.168.31.76 k8s-master <none> <none> kube-scheduler-k8s-master 1/1 Running 0 4h55m 192.168.31.76 k8s-master <none> <none> [root@k8s-master alex]# kubectl get nodes NAME STATUS ROLES AGE VERSION k8s-master Ready master 4h57m v1.16.0 k8s-node01 Ready <none> 4h55m v1.16.0 k8s-node02 Ready <none> 4h55m v1.16.0
總結:使用 ansible 工具不僅可以將手動操作自動化,從而減少手動操作中漏掉或者重複執行步驟的問題,更重要的是可以批量執行任務,當 k8s 集羣規模比較大的時候,手動部署肯定是不可行的,此時 ansible 就能發揮它批量部署的能力。
版權聲明:如無特殊說明,文章均爲本站原創,轉載請註明出處
本文鏈接:https://tendcode.com/article/k8s_install-k8s-by-ansible/
許可協議:署名-非商業性使用 4.0 國際許可協議