ansible是在运维过程中必不可少的一个自动化工具了,它的实用性、重要性不必多说,几乎每一位运维人都要去掌握它,下面是我们在使用过程中的一些经验与分享。
首先说一下几个应用场景
设置hosts解析,当我们部署一个集群时,我们可能需要设置hosts文件,保证每一台机器通过hostname就可以互相连通,那我们如何结合ansible-playbook来完成呢?
首先我们不想去做重复的操作,我们在清单文件中设置好组名,填好IP地址,设置好每一个IP地址对应的hostname之后,就希望每一个主机都自动设置好/etc/hosts文件,有人可能会说,那还不简单,我这样设置就好了,啪啪啪,一顿操作如下:
先写一个最简单的playbook,目录结构如下:
# tree . ├── host │ └── hosts ├── roles │ └── test-server │ ├── tasks │ │ └── main.yaml │ ├── files │ │ ├── hosts └── setup.yaml
来看一下这些文件都是如何写的
hosts清单文件
# cat host/hosts
[all-server] 192.168.1.221192.168.1.222 [all:vars] ansible_ssh_port=22 ansible_ssh_pass=root ansible_ssh_user=root
tasks文件
# cat roles/test-server/tasks/main.yaml - name: Copy file file: src: hosts dest: /etc/hosts
templates文件
# cat roles/test-server/files/hosts 192.168.1.221 test01 192.168.1.222 test02
setup文件
# cat setup.yaml - hosts: all-server tags: nfs roles: - role: test-server
到这里,看起来思路异常的清晰,提前设置好hosts文件,把所有用到的IP和hostname都设置好,嗯,非常不错!但是我们是不是做了一些重复的工作呢?设置完清单文件,还有再手动设置hosts文件,啊啊啊啊,真的好繁琐啊,也low!还有没有更好的方法?当然有!
这里我们修改下清单文件的内容
# cat host/hosts [all-server] 192.168.1.221 host_name=test01 192.168.1.222 host_name=test02 [all:vars] ansible_ssh_port=22 ansible_ssh_pass=root ansible_ssh_user=root
然后,我们使用ansible的模板功能,创建一个目录 templates,如下目录结构
# tree -d . ├── host └── roles └── test-server ├── tasks ├── templates
然后我们就可以写我们的模板文件了,不要眨眼!
# cat roles/test-server/templates/hosts.j2 {% for host in groups[‘all-server‘] %} {{ hostvars[host][‘ansible_eth0‘][‘ipv4‘][‘address‘] }} {{ hostvars[host][‘host_name‘] }} {% endfor %}
OK!写完了,首先遍历"all-server"组里的所有主机,然后获取每一个主机的IP地址和每一个主机对应的host_name这个变量,分别对应的是
{{ hostvars[host][‘ansible_eth0‘][‘ipv4‘][‘address‘] }} 和 {{ hostvars[host][‘host_name‘] }}
接下来修改下tasks那个文件
# cat roles/test-server/tasks/main.yaml - name: Copy file template: src: hosts.j2 dest: /etc/hosts
欸,这样不管你设置了多少主机,他都会遍历整个组,是不是很方便!
前端时间我在写安装k8s集群的部署脚本时,遇到了一个问题,我们由于某些原因吧,使用的nodePort的方式,通过nginx做的代理来进行服务的访问,即nginx代理k8s集群的nodePort,nodeIP + nodePort这种形式,在进行设置nginx的upstream配置时,由于每个集群的数量规模是不一样的,所以在代理时需要把所有node节点的IP地址列一遍,类似于下面这种样子
upstream test { server 192.168.1.1:32001; server 192.168.1.2:32001; server 192.168.1.3:32001; }
看起来就很麻烦,这样如果每次一个新的k8s集群部署时,都要再设置一遍这个就非常的麻烦,我之前的做法也是比较麻烦,后来有一天无意发现了遍历组里的主机和变量之后,就又做了修改,如下:
# cat roles/test-server/templates/upstream.j2 {% for server in server_groups %} upstream {{ server.name }} { {% if k8s_deploy_type == ‘cluster‘ %} {% for host in groups[‘k8s-server‘] %} {% if hostvars[host][‘k8s_ha_role‘] == ‘node‘ %} server {{ hostvars[host][‘inventory_hostname‘] }}:{{ server.port }} weight=1 max_fails=3 fail_timeout=30s; {% endif %} {% endfor %} {% elif k8s_deploy_type == ‘simple‘ %} {% for host in groups[‘k8s-single-server‘] %} {% if hostvars[host][‘k8s_role‘] == ‘node‘ %} server {{ hostvars[host][‘inventory_hostname‘] }}:{{ server.port }} weight=1 max_fails=3 fail_timeout=30s; {% endif %} {% endfor %} {% endif %} } {% endfor %}
不要觉着很麻烦,其实逻辑非常简单,因为k8s集群,根据业务场景,有时候需要部署单机版的,有时候需要部署高可用版的,所以我这里做了一层判断,所以清单文件和setup.yaml文件修改如下:
# cat host/hosts [all-server] 192.168.1.221 host_name=test01 192.168.1.222 host_name=test02 [k8s-server] 192.168.1.1 k8s_ha_role=master1 192.168.1.2 k8s_ha_role=master2 192.168.1.3 k8s_ha_role=master3 192.168.1.4 k8s_ha_role=node 192.168.1.5 k8s_ha_role=node 192.168.1.6 k8s_ha_role=node [k8s-single-server] 192.168.1.1 k8s_role=master 192.168.1.2 k8s_role=node 192.168.1.3 k8s_role=node [all:vars] ansible_ssh_port=22 ansible_ssh_pass=root ansible_ssh_user=root
setup.yaml文件参考
# cat setup.yaml - hosts: all-server tags: nfs roles: - role: test-server vars: k8s_deploy_type: cluster
到这里你可能还有一点疑惑,那就是{{ server.port }}这个是哪里来的?server_groups又是个什么鬼?别急,你是不是有很多的疑问?我们解决了node节点的IP问题,但是端口呢?我们的k8s集群,不可能只有一个nodePort吧,我们肯定有一堆的端口,所以不光要解决IP的问题,还要解决nodePort的问题,那么该如何解决呢?
由于nodePort我们根据具体的服务设置具体的端口,所以是可以提前写死的,那么根据这个情形,我们是不是可以设置一个专门存放upstream名和端口的组呢?
# cat roles/test-server/vars/main.yaml server_groups: - name: cloudweb port: 32028 - name: cloudwebapi port: 32009 - name: cloudupload port: 32037 - name: rms-resource port: 32018 - name: usermanage port: 32022 - name: mbusermanage port: 32752 - name: userapi port: 32021 - name: mbuserapi port: 32750
走着,这里就是模板文件中的{% for server in server_groups %} ,先去迭代这个组,然后再去迭代清单文件里的组,然后得到nodeIP:nodePort这样的一个endports
欢迎小伙伴们来关注我的公众号哦
原文:https://www.cnblogs.com/dogfei/p/12676883.html