第21章: Ansible自動化部署K8S-v1.20集群(離線版)


1.1 Ansible介紹

Ansible是一種IT自動化工具。它可以配置系統,部署軟件以及協調更高級的IT任務,例如持續部署,滾動更新。Ansible適用於管理企業IT基礎設施,從具有少數主機的小規模到數千個實例的企業環境。Ansible也是一種簡單的自動化語言,可以完美地描述IT應用程序基礎結構。

具備以下三個特點:

  • 簡單:減少學習成本

  • 強大:協調應用程序生命周期

  • 無代理:可預測,可靠和安全

使用文檔: https://docs.ansible.com/

安裝Ansible:yum install ansible -y

ansible

  • Inventory:Ansible管理的主機信息,包括IP地址、SSH端口、賬號、密碼等

  • Modules:任務均有模塊完成,也可以自定義模塊,例如經常用的腳本。

  • Plugins:使用插件增加Ansible核心功能,自身提供了很多插件,也可以自定義插件。例如connection插件,用於連接目標主機。

  • Playbooks:“劇本”,模塊化定義一系列任務,供外部統一調用。Ansible核心功能。

1.2 主機清單

# vim /etc/ansible/hosts
[webservers]
alpha.example.org
beta.example.org
172.16.1.81
www[001:006].example.com

[dbservers]
db01.intranet.mydomain.net
db02.intranet.mydomain.net
10.0.0.81
10.0.0.82
db-[99:101]-node.example.com

1.3 命令行使用

ad-hoc命令可以輸入內容,快速執行某個操作,但不希望留存記錄。

ad-hoc命令是理解Ansible和在學習playbooks之前需要掌握的基礎知識。

一般來說,Ansible的真正能力在於劇本。

1 連接遠程主機認證

開啟/etc/ansible/ansible.cfg配置文件中的host_key_checking = False參數,關閉遠程主機ssh指紋認證,實現免交互。

https://docs.ansible.com/ansible/2.9/reference_appendices/config.html

https://docs.ansible.com/ansible/2.9/user_guide/connection_details.html

(1) Ansible 通過SSH 協議與遠程機器通信。默認情況下,Ansible 使用本機 OpenSSH 並使用您當前的用戶名連接到遠程計算機,就像 SSH 一樣

(2) 優先級

https://docs.ansible.com/ansible/2.9/reference_appendices/general_precedence.html

Ansible 提供了四種控制其行為的來源。按照從最低(最容易覆蓋)到最高(覆蓋所有其他)的優先級順序,類別是:

  • 配置設置

  • 命令行選項

  • 劇本關鍵詞

  • 變量

1) 變量優先級:

命令行變量( -e ) > playbook變量 > inventory主機變量 > inventory組變量

第一優先級:全局范圍的變量(例如:執行臨時命令時指定的變量)。 第二優先級:playbook 里的變量。 第三優先級:主機范圍里的變量(例如:清單中的服務器或服務器組) 第四優先級:清單中的服務器優先級高於清單中的服務器組

2) 配置設置優先級:

ANSIBLE_CONFIG(如果設置了環境變量) > ./ansible.cfg(在當前目錄中) > ~/.ansible.cfg(當前用戶家目錄中) > /etc/ansible/ansible.cfg 檢查當前使用的是哪個配置文件:ansible --version 命令中顯示config file配置。

3) 連接遠端主機在命令行使用 -u -k 的優先級

inventory > playbook > ad-hoc(命令行)

(3) 主機清單

https://docs.ansible.com/ansible/2.9/user_guide/intro_inventory.html#inventory

https://docs.ansible.com/ansible/2.9/reference_appendices/YAMLSyntax.html#yaml-syntax

SSH密碼認證:

[webservers]
172.16.1.81 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass="123456"
172.16.1.82:22 ansible_ssh_user=root ansible_ssh_pass="123456"

SSH密鑰對認證:

# ssh-keygen
# ssh-copy-id <目標主機用戶名>@<目標主機>

[webservers]
172.16.1.81 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_key=/root/.ssh/id_rsa
172.16.1.82:22 ansible_ssh_user=root

也可以ansible.cfg在配置文件中指定:
[defaults]
private_key_file = /root/.ssh/id_rsa # 默認路徑

2 常用選項

選項 描述
-C, --check 運行檢查,不執行任何操作
-e EXTRA_VARS,--extra-vars=EXTRA_VARS 設置附加變量 key=value
-u REMOTE_USER, --user=REMOTE_USER SSH連接用戶,默認None
-k, --ask-pass SSH連接用戶密碼
-b, --become 提權,默認root
-K, --ask-become-pass 提權密碼

3 命令行使用

https://docs.ansible.com/ansible/2.9/user_guide/intro_adhoc.html

ansible all -m ping
ansible all -m shell -a "ls /root" -u root -k
ansible webservers -m copy –a "src=/etc/hosts dest=/tmp/hosts"

1.4 常用模塊

ansible-doc –l 查看所有模塊

ansible-doc –s copy 查看模塊文檔

模塊文檔:https://docs.ansible.com/ansible/2.9/modules/modules_by_category.html

1 shell

https://docs.ansible.com/ansible/2.9/modules/shell_module.html#shell-module

在目標主機執行shell命令。

 
           
- name: 將命令結果輸出到指定文件
  shell: somescript.sh >> somelog.txt
- name: 切換目錄執行命令
  shell:
    cmd: ls -l | grep log
    chdir: somedir/
- name: 編寫腳本
  shell: |
      if [ 0 -eq 0 ]; then
         echo yes > /tmp/result
      else
         echo no > /tmp/result
      fi
  args:
    executable: /bin/bash

2 copy

https://docs.ansible.com/ansible/2.9/modules/copy_module.html#copy-module

將文件復制到遠程主機。

 
           
- name: 拷貝文件
  copy:
    src: /srv/myfiles/foo.conf
    dest: /etc/foo.conf
    owner: foo
    group: foo
    mode: u=rw,g=r,o=r
    # mode: u+rw,g-wx,o-rwx
    # mode: '0644'
    backup: yes

3 file

管理文件和文件屬性。

https://docs.ansible.com/ansible/2.9/modules/file_module.html#file-module

 
           
- name: 創建目錄
  file:
    path: /etc/some_directory
    state: directory
    #state: link
    #state: hard
    #state: touch
    owner: foo
    group: foo
    mode: '0755'
- name: 刪除文件
  file:
    path: /etc/foo.txt
    state: absent
- name: 遞歸刪除目錄
  file:
    path: /etc/foo
    state: absent

touch: 表示創建文件

4 yum

軟件包管理。

https://docs.ansible.com/ansible/2.9/modules/yum_module.html#yum-module

 
           
- name: 安裝最新版apache
  yum:
    name: httpd
    state: latest
- name: 安裝列表中所有包
  yum:
    name:
      - nginx
      - postgresql
      - postgresql-server
    state: present
- name: 卸載apache包
  yum:
    name: httpd
    state: absent
- name: 更新所有包
  yum:
    name: '*'
    state: latest
- name: 安裝nginx來自遠程repo
  yum:
    name: http://nginx.org/packages/rhel/7/x86_64/RPMS/nginx-1.14.0-1.el7_4.ngx.x86_64.rpm
    # name: /usr/local/src/nginx-release-centos-6-0.el6.ngx.noarch.rpm
    state: present

present,latest:表示安裝

absent:表示卸載

5 service/systemd

管理服務。

https://docs.ansible.com/ansible/2.9/modules/service_module.html#service-module

控制遠程主機上的服務。支持的初始化系統包括 BSD init、OpenRC、SysV、Solaris SMF、systemd、upstart。


  
  
  
          
- name: 服務管理
  service:
    name: etcd
    state: started
    #state: stopped
    #state: restarted
    #state: reloaded
- name: 設置開機啟動
  service:
    name: httpd
    enabled: yes

https://docs.ansible.com/ansible/2.9/modules/systemd_module.html#systemd-module

控制遠程主機上的 systemd 服務。


  
  
  
          
- name: 服務管理
  systemd:
    name: etcd
    state: restarted
    enabled: yes
    daemon_reload: yes

6 unarchive

https://docs.ansible.com/ansible/2.9/modules/unarchive_module.html#unarchive-module


  
  
  
          
- name: 解壓
  unarchive:
    src=test.tar.gz
    dest=/tmp

7 debug

執行過程中打印語句。

https://docs.ansible.com/ansible/2.9/modules/debug_module.html#debug-module


  
  
  
          
# 打印每個主機的地址
- debug: msg="{{ inventory_hostname }}"
- debug: var=inventory_hostname
- debug:
    msg: System "{{ inventory_hostname }}"
- debug:
    var: inventory_hostname

- name: Get hostname
  debug: msg="{{ inventory_hostname }}"
- name: Get hostname
  debug: var=inventory_hostname
- name: Get hostname
  debug:
    msg:
      - "{{ inventory_hostname }}"
- name: 顯示主機已知的所有變量
  debug:
    var: hostvars[inventory_hostname]
    #verbosity: 4

(1) hostvars
hostvars[]是一個字典,包括ansible默認變量、inventory變量、遠程主機信息變量,[]內填寫的是遠程主機的連接方式(IP地址或DNS可以解析的
名稱)。要獲得遠程主機信息變量需要設置gather_facts: true參數(默認是true)。

(2) inventory_hostname
inventory_hostname是在ansible清單文件中配置連接遠程主機的變量(例如:/etc/ansible/hosts),它可以是IP地址或DNS可以解析的名稱。
例:
---
- hosts: webservers
  vars:
    http_port: 80
    server_name: www.lc.com
  remote_user: root
  gather_facts: false
  tasks:
  - name: Get hostname
    debug:
      msg:
        - "{{ hostvars[inventory_hostname].inventory_hostname }}"
        - "{{ inventory_hostname }}"

(3) ansible_hostname
ansible_hostname是遠程主機信息變量。
例:
---
- hosts: webservers
  vars:
    http_port: 80
    server_name: www.lc.com
  remote_user: root
  gather_facts: true
  tasks:
  - name: Get hostname
    debug:
      msg:
        - "{{ hostvars[inventory_hostname].ansible_hostname }}"
        - "{{ ansible_hostname }}"

(4) {{  }} 或 var 表示引用變量

1.5 Playbook

Playbooks是Ansible的配置,部署和編排語言。他們可以描述您希望在遠程機器做哪些事或者描述IT流程中一系列步驟。使用易讀的YAML格式組織Playbook文件。

如果Ansible模塊是您工作中的工具,那么Playbook就是您的使用說明書,而您的主機資產文件就是您的原材料。

與adhoc任務執行模式相比,Playbooks使用ansible是一種完全不同的方式,並且功能特別強大。

https://docs.ansible.com/ansible/2.9/user_guide/playbooks.html


  
  
  
          
---
- hosts: webservers
  vars:
    http_port: 80
    server_name: www.lc.com
  remote_user: root
  gather_facts: false
  tasks:
  - name: 安裝nginx最新版
    yum: name=nginx state=latest
  - name: 寫入nginx配置文件
    template: src=/srv/nginx.j2 dest=/etc/nginx/nginx.conf
    notify:
    - restart nginx
  - name: 確保nginx正在運行
    service: name=nginx state=started enabled=yes
  handlers:
    - name: restart nginx
      service: name=nginx state=restarted
      
# ansible-playbook -i /etc/ansible/hosts nginx.yaml

1 主機和用戶

https://docs.ansible.com/ansible/2.9/user_guide/become.html


  
  
  
          
---
- hosts: webservers
  remote_user: lc
  become: yes
  become_user: root

ansible-playbook nginx.yaml -u lc -k -b -K

2 定義變量

變量是應用於多個主機的便捷方式; 實際在主機執行之前,變量會對每個主機添加,然后在執行中引用。

  • 命令行傳遞

    -e VAR=VALUE
  • 主機變量與組變量

在Inventory中定義變量。

[webservers]
172.16.1.81 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass="123456" hostname=web1
172.16.1.82:22 ansible_ssh_user=root ansible_ssh_pass="123456" hostname=web2

[webservers:vars]
hostname=web3
  • 單文件存儲

Ansible中的首選做法是不將變量存儲在Inventory中。除了將變量直接存儲在Inventory文件之外,主機和組變量還可以存儲在相對於Inventory文件的單個文件中。Ansible 通過搜索相對於inventory file or the playbook file的路徑來加載主機組變量文件。

https://docs.ansible.com/ansible/2.9/user_guide/intro_inventory.html#inventory

組變量:

group_vars 存放的是組變量目錄

group_vars/all.yml 表示所有主機有效,等同於[all:vars]

grous_vars/etcd.yml 表示etcd組主機有效,等同於[etcd:vars]

# vi /etc/ansible/group_vars/all.yml
work_dir: /data
# vi /etc/ansible/host_vars/webservers.yml
nginx_port: 80

  
  
  
          
- hosts: webservers
  vars:
    http_port: 80
    server_name: www.lc.com
  • Register變量


  
  
  
          
- shell: /usr/bin/uptime
  register: result
- debug: msg="{{result.stdout}}"
- debug: var=result.stdout

3 任務列表

每個play包含一系列任務。這些任務按照順序執行,在play中,所有主機都會執行相同的任務指令。play目的是將選擇的主機映射到任務。


  
  
  
          
tasks:
- name: 安裝nginx最新版
  yum: pkg=nginx state=latest

4 語法檢查與調試

語法檢查:ansible-playbook --check /path/to/playbook.yaml

測試運行,不實際操作:ansible-playbook -C /path/to/playbook.yaml

debug模塊在執行期間打印語句,對於調試變量或表達式,而不必停止play。與'when:'指令一起調試更佳。


  
  
  
          
- debug: msg="{{group_names}}"
- name: 主機名
  debug:
    msg: "{{inventory_hostname}}"

5 任務控制

如果你有一個大的劇本,那么能夠在不運行整個劇本的情況下運行特定部分可能會很有用。


  
  
  
          
tasks:
- name: 安裝nginx最新版
  yum: pkg=nginx state=latest
  tags: install
- name: 寫入nginx配置文件
  template: src=/srv/nginx.j2 dest=/etc/nginx/nginx.conf
  tags: config

使用:

# ansible-playbook example.yml --tags "install"
# ansible-playbook example.yml --tags "install,config"
# ansible-playbook example.yml --skip-tags "install"

6 流程控制

條件:

https://docs.ansible.com/ansible/2.9/user_guide/playbooks_conditionals.html


  
  
  
          
tasks:
- name: 只在172.16.1.81運行任務
  debug: msg="{{ansible_default_ipv4.address}}"
  when: ansible_default_ipv4.address == '172.16.1.81'

循環:

https://docs.ansible.com/ansible/2.9/user_guide/playbooks_loops.html


  
  
  
          
tasks:
- name: 批量創建用戶
  user: name={{ item }} state=present groups=wheel
  with_items:
    - testuser1
    - testuser2

  
  
  
          
- name: 批量拷貝
  copy: src={{ item }} dest=/tmp
  with_fileglob:
    - "/tmp/*.txt"

常用循環語句:

語句 描述
with_items 標准循環
with_fileglob 遍歷目錄文件
with_dict 遍歷字典

7 模板

https://docs.ansible.com/ansible/2.9/user_guide/playbooks_templating.html


  
  
  
          
vars:
  domain: "www.lc.com"
tasks:
- name: 寫入nginx配置文件
  template: src=/srv/nginx.j2 dest=/etc/nginx/conf.d/server.conf

  
  
  
          
# nginx.j2
{% set domain_name = domain %}
upstream web {
  {% for host in groups['webservers'] %}
    server {{ hostvars[host].inventory_hostname }}
  {{ endfor }}
}
server {
   listen 80;
   server_name {{ domain_name }};
   location / {
        root /usr/share/html;
   }
}

在jinja里使用ansible變量直接{{ }}引用。使用ansible變量賦值jinja變量不用{{ }}引用。

定義變量

{% set local_ip = inventory_hostname %}

條件和循環


  
  
  
          
{% set list=['one', 'two', 'three'] %}
{% for i in list %}
    {% if i == 'two' %}
        -> two
    {% elif loop.index == 3 %}
        -> 3
    {% else %}
        {{ i }}
    {% endif %}
{% endfor %}

例如:生成連接etcd字符串


  
  
  
          
{% for host in groups['etcd'] %}
    https://{{ hostvars[host].inventory_hostname }}:2379
    {% if not loop.last %},{% endif %}
{% endfor %}

里面也可以用ansible的變量。

1.6 Roles

Roles是基於已知文件結構自動加載某些變量文件,任務和處理程序的方法。按角色對內容進行分組,適合構建復雜的部署環境。

https://docs.ansible.com/ansible/2.9/user_guide/playbooks_reuse_roles.html

1 定義Roles

Roles目錄結構:


  
  
  
          
site.yml
webservers.yml
fooservers.yml
roles/
    common/
        tasks/
        handlers/
        files/
        templates/
        vars/
        defaults/
        meta/
    webservers/
        tasks/
        defaults/
        meta/
  • tasks -包含角色要執行的任務的主要列表。

  • handlers -包含處理程序,此角色甚至在此角色之外的任何地方都可以使用這些處理程序。

  • defaults-角色的默認變量

  • vars-角色的其他變量

  • files -包含可以通過此角色部署的文件。

  • templates -包含可以通過此角色部署的模板。

  • meta-為此角色定義一些元數據。請參閱下面的更多細節。

1 創建Roles目錄結構的步驟


  
  
  
          
(1) 創建一個目錄
# mkdir -p /root/ansible-install-k8s/
# cd /root/ansible-install-k8s/
(2) 創建組變量目錄,用於存放組變量文件,和hosts清單文件在同級目錄下
# mkdir -p group_vars/
(3) 創建主機清單文件
# touch hosts
(4) 創建roles分組目錄
# mkdir -p roles/
(5) 創建roles分組目錄的入口文件
# touch multi-master-deploy.yml
(6) 在roles分組目錄下創建具體的roles
# mkdir -p roles/master/{tasks,files,templates}
# 創建該roles的執行入口文件
# touch roles/master/tasks/main.yml
(7) 注
1) 可以使用命令生成roles,然后刪除不需要的
# ansible-galaxy init roles/master
2) 創建ansible.cfg文件,執行時當前目錄下的生效
# touch ansible.cfg

# tree ansible-install-k8s/
ansible-install-k8s/
├── group_vars
├── hosts
├── multi-master-deploy.yml
└── roles
    └── master
        ├── files
        ├── tasks
        │   └── main.yml
        └── templates

6 directories, 3 files

2 角色控制


  
  
  
          
---
- name: 0.系統初始化
  gather_facts: false
  hosts: all
  roles:
    - common
  tags: common

- name: 1.自簽證書
  gather_facts: false
  hosts: localhost
  roles:
    - tls
  tags: tls

1.7 部署步驟

注:確保所有節點系統時間一致

操作系統要求:CentOS7.x_x64

所有節點root密碼保持一致

示例參考:https://github.com/ansible/ansible-examples

1 熟悉二進制部署K8S步驟

  1. 服務器規划

角色 IP 組件
k8s-master1 172.16.1.81 kube-apiserver kube-controller-manager kube-scheduler kubectl etcd kube-proxy kubelet docker
k8s-master2 172.16.1.82 kube-apiserver kube-controller-manager kube-scheduler kubectl etcd kube-proxy kubelet docker
k8s-node1 172.16.1.83 etcd kube-proxy kubelet docker
k8s-node2 172.16.1.84 kube-proxy kubelet docker
Load Balancer(Master) 172.16.1.81 VIP: 172.16.1.80 nginx keepalived
Load Balancer(Backup) 172.16.1.82 nginx keepalived
  1. 系統初始化

    1. 關閉selinux,firewalld

    2. 關閉swap

    3. 時間同步

    4. 寫hosts

  2. Etcd集群部署

    1. 生成etcd證書

    2. 部署三個etcd集群

    3. 查看集群狀態

  3. 部署Master

    1. 生成apiserver證書

    2. 部署apiserver、controller-manager和scheduler組件

    3. 啟動TLS Bootstrapping

  4. 部署Node

    1. 安裝Docker

    2. 部署kubelet和kube-proxy

    3. 在Master上允許為新Node頒發證書

    4. 授權apiserver訪問kubelet

  5. 部署插件(准備好鏡像)

    1. Calico

    2. Web UI

    3. CoreDNS

    4. Ingress Controller

  6. Master高可用

    1. 增加Master節點(與Master1一致)

    2. 部署Nginx負載均衡器

    3. Nginx+Keepalived高可用

    4. 修改Node連接VIP

2 Roles組織K8S各組件部署解析

編寫建議:

  1. 梳理流程和Roles結構

  2. 如果配置文件有不固定內容,使用jinja渲染

  3. 人工干預改動的內容應統一寫到一個文件中

3 找一台服務器安裝Ansible

# yum install epel-release -y
# yum install ansible -y

4 下載所需文件

下載Ansible部署文件:

# git clone https://github.com/HyjyLc/ansible-install-k8s
# cd ansible-install-k8s

下載准備好軟件包(包含所有涉及文件和鏡像,比較大),解壓到/root目錄:

雲盤鏈接:https://pan.baidu.com/s/1uCLylsj1-W2HigS_Tn9b5g 提取碼:bicc

# tar zxf binary_pkg.tar.gz

5 修改Ansible文件

修改hosts文件,根據規划修改對應IP和名稱。

# vi hosts
...

修改group_vars/all.yml文件,修改軟件包目錄和證書可信任IP。

# vim group_vars/all.yml
software_dir: '/root/binary_pkg'
...
cert_hosts:
k8s:
etcd:

6 架構圖

單Master架構 single-master

多Master架構 multi-master

7 部署命令

單Master版:

# ansible-playbook -i hosts single-master-deploy.yml -uroot -k

多Master版:

# ansible-playbook -i hosts multi-master-deploy.yml -uroot -k

本文檔使用多Master版本部署

8 查看集群節點

# kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-master1 Ready <none> 1m v1.20.4
k8s-master2 Ready <none> 1m v1.20.4
k8s-node1 Ready <none> 53s v1.20.4
k8s-node2 Ready <none> 1m v1.20.4

9 其他

(1) 部署控制

如果安裝某個階段失敗,可針對性測試.

例如:只運行部署插件

# ansible-playbook -i hosts single-master-deploy.yml -uroot -k --tags addons

(2) 節點擴容

1)修改hosts,添加新節點ip

# vi hosts
...
[newnode]
172.16.1.85 node_name=k8s-node3

2)執行部署

# ansible-playbook -i hosts add-node.yml -uroot -k

(3) 所有HTTPS證書存放路徑

部署產生的證書都會存放到目錄“ansible-install-k8s-master/ssl”,一定要保存好,后面還會用到~

(4) 連接api的地址(nginx vip地址)

kube-controller-manager.kubeconfig
kube-scheduler.kubeconfig

kube-proxy.kubeconfig
kubelet.kubeconfig

(5) 連接本地api-server地址(也可以改為nginx vip地址)

/root/.kube/config


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM