使用 ansible-playbook 搭建 k8s 環境

k8s 學習(2)——使用 ansible-playbook 搭建 k8s 環境


2021年3月23日 20:52 閱讀 3997 評論 6

上一篇博客記錄了一下在 CentOS 下搭建 k8s 環境的方式,主要是使用的 shell 腳本執行安裝部署命令。但是執行腳本終究只能人工執行,而且無法大批量安裝,而本篇博客就使用批量執行工具 ansible 來自動化安裝 k8s 環境。

步驟梳理

首先在介紹 ansible 編排之前,先梳理一下搭建 k8s 環境的步驟(之前的 shell 腳本部署方式有詳細步驟註釋)。

  1. 所有節點安裝 docker-ce
  2. 所有節點配置 k8s 環境
  3. master 節點安裝 k8s,並啓動 flannel 服務
  4. 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 國際許可協議

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