Ansible 用起来好爽😄

62 天前
 EyebrowsWhite

本人只是个前端,很早之前就听说过 ansible, terraform 这类运维工具,一直没机会上手玩一下,上个月借着 GCP 刚开通的 300 刀额度业余时间鼓捣了一下,到现在一个多月了,发现真的是个神器啊,特别是如果有个十来台服务器一起执行 playbook 的时候,有种莫名的爽感😄

8764 次点击
所在节点    程序员
68 条回复
defunct9
62 天前
一直用一直爽。但 k8s 比这个爽。
Kirkcong
62 天前
是啊是啊,超爽的,我们 1000+台机器,全靠 ansible
hausen
62 天前
问题是,好像个人使用没什么使用场景吧?
EyebrowsWhite
62 天前
@defunct9 等玩腻了 ansible 就折腾 k8s ,其实之前尝试上手过,但是如果不用 GKE 之类的基础设施就太复杂了,而如果用的话又没那种感觉 :) 毕竟我不是专业运维,没有业务需求和压力。很巧的是,我在用一个 ansible wireguard role 的时候看到作者就是纯自己搭建的 k8s ,打算后面跟着他的 blog( https://www.tauceti.blog/)搞一下
EyebrowsWhite
62 天前
EyebrowsWhite
62 天前
@Kirkcong 有个疑问,我想知道你们最多会在多少台机器执行任务啊,如果 1000 台一起执行,控制节点顶得住吗

@hausen 说实话,没有。我感觉就几台服务器反而会拖慢效率,不如 ssh 上去手敲命令,不过这种工具玩起来就很有趣
Kirkcong
62 天前
@EyebrowsWhite #6 看了下监控系统,目前是 1080 台机器。不会同时执行的,我们有不同的 team ,ansible 机器设置了 crontab 错开时间,总共 65 个 team 。倒不是 ansible 机器承受不住,是因为不同 team 配置不同,执行的 role 不同。

至于最多多少台机器执行,这个没法算,我们没有统计每个 team 机器数量。
Kirkcong
62 天前
@hausen #3
@EyebrowsWhite #6

当你机器配置繁琐的时候,即便数量少,上 ansible 也很轻松。
guanzhangzhang
62 天前
核心是 jinja2 ,这个熟悉了再会抽配置,就熟练了,很多人都只基础的文件拷贝执行命令啥的
defunct9
62 天前
kubespray 是个好东西,正在用它建新集群,参数多多啊。
EyebrowsWhite
62 天前
@Kirkcong 奥奥,感谢解答,我们使用场景不同,我就一个人玩,和你们团队生产用毕竟还是有很大差距

@guanzhangzhang 结合 AI 的话学习起来很快,jinja2 基础用法很简单,就是那些高级的功能比如 Custom Filters 啥的感觉复杂些
EyebrowsWhite
62 天前
@defunct9 看起来很强啊,教程还是用的 GCP ,那我不得不试一试了
Kirkcong
62 天前
@EyebrowsWhite #11 我个人的机器也在用 ansible ,包括 k8s 节点的创建,vps 的一些基础配置,比如加 key,创建用户,nfs 挂载,hostname,软件包的安装,有 ansible 会方便很多
Gannicus5
62 天前
作为一个 SRE ,我没怎么用过哈哈哈
Kirkcong
62 天前
---
# tasks file for common

- name: Account management tasks
block:
- name: Ensure group "admin" exists
ansible.builtin.group:
name: admin
gid: 4141
state: present

- name: Accounts configuration
ansible.builtin.user:
name: "{{ item.name }}"
uid: "{{ item.uid }}"
state: present
group: "{{ item.group }}"
loop: "{{ accounts }}"

- name: Set up multiple authorized keys
ansible.builtin.authorized_key:
user: "{{ item.user }}"
key: "{{ item.key }}"
manage_dir: true
loop: "{{ keys }}"

- name: Add sudoers for ansible and hola
ansible.builtin.lineinfile:
path: /etc/sudoers.d/systems
line: "{{ item.name }} ALL=(ALL) NOPASSWD:ALL"
create: true
loop: "{{ accounts }}"
when: item.admin | bool

- name: Change root password
ansible.builtin.user:
name: root
password: "{{ root_password }}"
state: present

- name: Change hola password
ansible.builtin.user:
name: hola
password: "{{ user_password }}"
state: present

- name: Install the packages when os is rhel
ansible.builtin.dnf:
name: "{{ item.name }}"
state: "{{ item.state }}"
loop: "{{ packages_rhel }}"
when: ansible_os_family == "RedHat"

- name: Install the packages when os is debian
ansible.builtin.apt:
name: "{{ item.name }}"
state: "{{ item.state }}"
loop: "{{ packages_debian }}"
when: ansible_os_family == "Debian" or ansible_os_family == "Ubuntu"

become: true
ignore_errors: false
remote_user: root
vars:
ansible_ssh_private_key_file: "~/ansi/key"




- name: Generate facts
block:
- name: Create directory for ansible custom facts
ansible.builtin.file:
state: directory
recurse: true
path: /etc/ansible/facts.d

- name: Chcek if exsit custom facts
ansible.builtin.stat:
path: /etc/ansible/facts.d/static.fact
register: host_facts_stat

- name: Install custom fact
ansible.builtin.copy:
src: static.fact
dest: /etc/ansible/facts.d
when: not host_facts_stat.stat.exists

- name: End the play after first time to create custom facts
meta: end_play
when: not host_facts_stat.stat.exists

become: true
ignore_errors: false
remote_user: root
vars:
ansible_ssh_private_key_file: "~/ansi/key"

- name: Load custom facts
ansible.builtin.setup:
filter: ansible_local




- name: System configuration tasks
block:
- name: Re-read facts after adding custom fact
ansible.builtin.setup:
filter: ansible_local

# Upgrade packages
# - name: Upgrade all packages for rhel
# ansible.builtin.dnf:
# name: "*"
# state: latest
# when: ansible_os_family == "RedHat"

# - name: Upgrade all packages for debian
# ansible.builtin.apt:
# name: "*"
# state: latest
# when: ansible_os_family == "Debian" or ansible_os_family == "Ubuntu"
- name: Set hostname
ansible.builtin.hostname:
name: "{{ ansible_local['static']['general']['hostname'] }}"
when: ansible_local['static']['general']['hostname'] is defined and ansible_local['static']['general']['hostname'] != ""

- name: Configure eth0 ip address
ansible.builtin.template:
src: nmconnection_eth0.j2
dest: /etc/NetworkManager/system-connections/eth0.nmconnection
owner: root
group: root
mode: 0700
register: nmconnection_eth0_result

- name: Reload eth0 configuration
command: |
nmcli connection reload
nmcli connection up eth0
when: nmconnection_eth0_result.changed

- name: Disable cloud-init network
ansible.builtin.lineinfile:
path: /etc/cloud/cloud.cfg
regexp: '^ renderers'
insertafter: '^ network:'
line: " config: disabled"
when: nmconnection_eth0_result.changed

- name: Configure eth1 ip address
ansible.builtin.template:
src: nmconnection_eth1.j2
dest: /etc/NetworkManager/system-connections/eth1.nmconnection
owner: root
group: root
mode: 0700
when: ansible_local['static']['general']['ipaddr_eth1'] is defined and ansible_local['static']['general']['ipaddr_eth1'] != ""
register: nmconnection_eth1_result

- name: Reload eth1 configuration
command: |
nmcli connection reload
nmcli connection up eth1
when: nmconnection_eth1_result.changed


# - name: Display all variables/facts known for a host
# debug:
# var: hostvars[inventory_hostname]
# tags: debug_info

- name: Install the packages when os is rhel
ansible.builtin.dnf:
name: "{{ item.name }}"
state: "{{ item.state }}"
loop: "{{ packages_rhel }}"
when: ansible_os_family == "RedHat"

- name: Install the packages when os is debian
ansible.builtin.apt:
name: "{{ item.name }}"
state: "{{ item.state }}"
loop: "{{ packages_debian }}"
when: ansible_os_family == "Debian" or ansible_os_family == "Ubuntu"

- name: Enable atop is enabled and started
ansible.builtin.systemd_service:
name: atop
enabled: true
state: started

- name: Disable SELinux persist
ansible.builtin.selinux:
state: permissive
policy: targeted

- name: Set SELinux in permissive mode at runtime
command: setenforce 0

- name: kernel parameters
ansible.builtin.sysctl:
name: "{{ item.name }}"
value: "{{ item.value }}"
loop: "{{ kernel_parameters }}"

- name: Update grubby
command: grubby --update-kernel=ALL --args="net.ifnames=0 biosdevname=0 crashkernel=256M intel_idle.max_cstate=0 processor.max_cstate=1 idle=poll console=tty1 ipv6.disable=1 pci=nommconf pcie_aspm=off mitigations=off"
when: ansible_os_family == "RedHat"

- name: Ensure bash profile history lines number is unlimited
ansible.builtin.lineinfile:
path: /etc/profile
regexp: '^HISTSIZE '
insertafter: '^#HISTSIZE '
line: HISTSIZE=-1

- name: Ensure bash profile history file size is unlimited
ansible.builtin.lineinfile:
path: /etc/profile
regexp: '^HISTFILESIZE '
insertafter: '^#HISTFILESIZE '
line: HISTFILESIZE=-1


become: true
ignore_errors: true
Kirkcong
62 天前
# tasks file for system configuration

- block:

- name: disable SWAP (Kubeadm requirement)
shell: |
swapoff -a

- name: disable SWAP in fstab (Kubeadm requirement)
replace:
path: /etc/fstab
regexp: '^([^#].*?\sswap\s+sw\s+.*)$'
replace: '# \1'

- name: create an empty file for the Containerd module
copy:
content: ""
dest: /etc/modules-load.d/containerd.conf
force: no

- name: configure modules for Containerd
blockinfile:
path: /etc/modules-load.d/containerd.conf
block: |
overlay
br_netfilter

- name: create an empty file for Kubernetes sysctl params
copy:
content: ""
dest: /etc/sysctl.d/99-kubernetes-cri.conf
force: no

- name: configure sysctl params for Kubernetes
lineinfile:
path: /etc/sysctl.d/99-kubernetes-cri.conf
line: "{{ item }}"
with_items:
- 'net.bridge.bridge-nf-call-iptables = 1'
- 'net.ipv4.ip_forward = 1'
- 'net.bridge.bridge-nf-call-ip6tables = 1'

- name: apply sysctl params without reboot
command: sysctl --system

- name: add Docker's dnf repository
get_url:
url: https://download.docker.com/linux/rhel/docker-ce.repo
dest: /etc/yum.repos.d/docker-ce.repo
mode: '0644'
force: true


- name: add Kubernetes' dnf repository
yum_repository:
name: Kubernetes
description: Kubernetes
baseurl: https://pkgs.k8s.io/core:/stable:/v{{ ansible_local['static']['kubernetes']['version'] }}/rpm/
gpgkey: https://pkgs.k8s.io/core:/stable:/v{{ ansible_local['static']['kubernetes']['version'] }}/rpm/repodata/repomd.xml.key
enabled: true
gpgcheck: true
state: present

- name: install Containerd
ansible.builtin.dnf:
name: containerd.io
state: present

- name: create Containerd directory
file:
path: /etc/containerd
state: directory

- name: add Containerd configuration
shell: /usr/bin/containerd config default > /etc/containerd/config.toml

- name: configuring the systemd cgroup driver for Containerd
lineinfile:
path: /etc/containerd/config.toml
regexp: ' SystemdCgroup = false'
line: ' SystemdCgroup = true'

- name: enable the Containerd service and start it
systemd:
name: containerd
state: restarted
enabled: yes
daemon-reload: yes

- name: install packages
dnf:
name:
- kubelet
- kubeadm
- kubectl
- iproute-tc
state: present
update_cache: true
register: packages

- name: download helm script
ansible.builtin.get_url:
url: https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
dest: /tmp/get-helm-3.sh
mode: '0755'
force: true

- name: install helm
ansible.builtin.shell:
cmd: /tmp/get-helm-3.sh

- name: enable the Kubelet service, and enable it persistently
service:
name: kubelet
enabled: yes

- name: load br_netfilter kernel module
modprobe:
name: br_netfilter
state: present

- name: set bridge-nf-call-iptables
sysctl:
name: net.bridge.bridge-nf-call-iptables
value: 1

- name: set ip_forward
sysctl:
name: net.ipv4.ip_forward
value: 1

- name: reboot and wait for reboot to complete
reboot:
when: packages.changed
defunct9
62 天前
GCP 和 AWS 可用不到 kubespray ,纯手搓才用得到。这东西也不是啥好东西,唉,要从 aws 搬家,有得忙了。
EyebrowsWhite
62 天前
@Kirkcong #13 我现在也在把个人服务器迁移为用 ansible 管理,如果是服务器初始化、加固、设置自动化备份之类的重复性任务是方便的,但是比如部署个 vaultwarden 啥的单个服务,由于这种服务我只会部署一个,所以感觉写个 playbook 反而不如直接上去敲命令。不过这只是目前的感受,可能随着服务越来越复杂感受也会变化 :)
EyebrowsWhite
62 天前
w568w
62 天前
ansible 主要问题是太太太慢了,我都搞不明白 Python 怎么能那么慢,五台服务器每次启动任务都要先等个 10 分钟,每个任务执行前后都要卡个四五秒,也不知道在初始化什么东西…… 网络连接肯定没问题的,ssh 也是秒连,服务器本身性能肯定足够

后来换 pyinfra 了,体验还可以: https://pyinfra.com/

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1154933

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX