1.1 Ansible介紹
Ansible是一種IT自動化工具。它可以配置系統,部署軟件以及協調更高級的IT任務,例如持續部署,滾動更新。Ansible適用於管理企業IT基礎設施,從具有少數主機的小規模到數千個實例的企業環境。Ansible也是一種簡單的自動化語言,可以完美地描述IT應用程序基礎結構。
具備以下三個特點:
-
-
強大:協調應用程序生命周期
-
無代理:可預測,可靠和安全
使用文檔: https://docs.ansible.com/
安裝Ansible:yum install ansible -y
-
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 通過與遠程機器。默認情況下,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步驟
-
服務器規划
角色 | 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 |
-
系統初始化
-
關閉selinux,firewalld
-
關閉swap
-
時間同步
-
寫hosts
-
-
Etcd集群部署
-
生成etcd證書
-
部署三個etcd集群
-
查看集群狀態
-
-
部署Master
-
生成apiserver證書
-
部署apiserver、controller-manager和scheduler組件
-
啟動TLS Bootstrapping
-
-
部署Node
-
安裝Docker
-
部署kubelet和kube-proxy
-
在Master上允許為新Node頒發證書
-
授權apiserver訪問kubelet
-
-
部署插件(准備好鏡像)
-
Calico
-
Web UI
-
CoreDNS
-
Ingress Controller
-
-
Master高可用
-
增加Master節點(與Master1一致)
-
部署Nginx負載均衡器
-
Nginx+Keepalived高可用
-
修改Node連接VIP
-
2 Roles組織K8S各組件部署解析
編寫建議:
-
梳理流程和Roles結構
-
如果配置文件有不固定內容,使用jinja渲染
-
人工干預改動的內容應統一寫到一個文件中
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 架構圖
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