Ansible 动态主机清单

Ansible 动态主机清单

使用动态主机清单

Ansible 会根据提供的主机清单执行任务,默认我们会在主机清单中将所有主机列出来(静态主机清单),这种方式在传统的数据中心是没有问题的,因为传统的数据中心不会频繁的更换主机。但是在虚拟化或者云环境中仍使用静态主机清单可能不是一个很好的选择,因为虚拟化或者云环境中虚拟机数量可能会频繁变化,今天创建 3 台,明天删除 2 台,这个时候如果还用静态主机清单就需要反复修改清单以保证主机清单的准确性。

Ansible 支持动态的获取主机信息,以下列出了部分集合中可用的主机清单插件。

[root@remote-host ansible]# ansible-navigator doc -t inventory -l
[DEPRECATION WARNING]: community.general.stackpath_compute has been deprecated. The company and the service were sunset in June 2024. This feature will be removed from community.general in version
11.0.0. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
ansible.builtin.advanced_host_list   Parses a 'host list' with ranges
ansible.builtin.auto                 Loads and executes an inventory plugin specified in a YAML config
ansible.builtin.constructed          Uses Jinja2 to construct vars and groups based on existing inventory
ansible.builtin.generator            Uses Jinja2 to construct hosts and groups from patterns
ansible.builtin.host_list            Parses a 'host list' string
ansible.builtin.ini                  Uses an Ansible INI file as inventory source
ansible.builtin.script               Executes an inventory script that returns JSON
ansible.builtin.toml                 Uses a specific TOML file as an inventory source
ansible.builtin.yaml                 Uses a specific YAML file as an inventory source
community.dns.hetzner_dns_records    Create inventory from Hetzner DNS records
community.dns.hosttech_dns_records   Create inventory from Hosttech DNS records
community.docker.docker_containers   Ansible dynamic inventory plugin for Docker containers
community.docker.docker_machine      Docker Machine inventory source
community.docker.docker_swarm        Ansible dynamic inventory plugin for Docker swarm nodes
community.general.cobbler            Cobbler inventory source
community.general.gitlab_runners     Ansible dynamic inventory plugin for GitLab runners
community.general.icinga2            Icinga2 inventory source
community.general.iocage             iocage inventory source
community.general.linode             Ansible dynamic inventory plugin for Linode
community.general.lxd                Returns Ansible inventory from lxd host
community.general.nmap               Uses nmap to find hosts to target
community.general.online             Scaleway (previously Online SAS or Online.net) inventory source
community.general.opennebula         OpenNebula inventory source
community.general.proxmox            Proxmox inventory source
community.general.scaleway           Scaleway inventory source
community.general.stackpath_compute  StackPath Edge Computing inventory source
community.general.virtualbox         virtualbox inventory source
community.general.xen_orchestra      Xen Orchestra inventory source
community.libvirt.libvirt            Libvirt inventory source
containers.podman.buildah_containers Inventory plugin that discovers Buildah working containers as hosts
containers.podman.podman_containers  Inventory plugin that discovers Podman containers as hosts

以下命令可以查看 PVE 的主机清单插件内容(就是 python 脚本):

[root@remote-host ansible]# ansible-navigator exec -- \
    cat /usr/share/ansible/collections/ansible_collections/community/general/plugins/inventory/proxmox.py

接下来用 PVE 虚拟化平台来做个演示,PVE 虚拟化平台可以通过 community.general.proxmox 主机清单插件来获取主机信息:

[root@remote-host ansible]# cat inventory/proxmox.yml
# inventory/proxmox.yml
plugin: community.general.proxmox

url: https://192.168.50.206:8006
user: root@pam
password: "redhat"
validate_certs: false

exclude_nodes: true
want_facts: true
want_proxmox_nodes_ansible_host: false

这里要注意几点:

  • 针对 PVE,动态主机清单文件名必须是 proxmox.yml
  • plugin: community.general.proxmox 表示调用 community.general.proxmox 主机清单插件
  • exclude_nodes 设置为 true 用于将 PVE 物理节点从主机清单中排除
  • want_facts 设置为 true 表示将虚拟机部分信息设置为 Ansible 变量
  • want_proxmox_nodes_ansible_host 用于设置是否自动将虚拟机第一个地址设置为 ansible_host ,建议为 false

我们来查询下主机列表:

[root@remote-host ansible]# ansible-navigator inventory \
    -i inventory/proxmox.yml --yaml --list
all:
  children:
    proxmox_all_qemu:
      hosts:
        mysql:
          proxmox_agent: '1'
          proxmox_agent_interfaces:
          - ip-addresses:
            - 127.0.0.1/8
            - ::1/128
            mac-address: 00:00:00:00:00:00
            name: lo
          - ip-addresses:
            - 192.168.50.219/24
            - fe80::6cf5:1ff:fe25:fd25/64
            mac-address: 6e:f5:01:25:fd:25
            name: ens18
          proxmox_boot:
            order: scsi0;ide2;net0
          proxmox_cores: 4
          proxmox_cpu: x86-64-v2-AES
          proxmox_digest: b077ccef985e0f4b23f8062dda94b77f4c222687
          proxmox_ide2:
            disk_image: local:iso/Fedora-Server-dvd-x86_64-43-1.6.iso
            media: cdrom
            size: 3402816K
          proxmox_ipconfig0:
            gw: 192.168.50.1
            ip: 192.168.50.219/24
          proxmox_memory: 8192
          proxmox_meta:
            creation-qemu: 8.0.2
            ctime: '1769431780'
          proxmox_name: mysql
          proxmox_net0:
            bridge: vmbr0
            firewall: '1'
            virtio: 6E:F5:01:25:FD:25
          proxmox_node: pve
          proxmox_numa: 0
          proxmox_ostype: l26
          proxmox_qmpstatus: running
          proxmox_sata0:
            disk_image: local:101/vm-101-cloudinit.qcow2
            media: cdrom
          proxmox_scsi0:
            disk_image: local-lvm:vm-101-disk-0
            iothread: '1'
            size: 32G
          proxmox_scsihw:
            disk_image: virtio-scsi-single
          proxmox_smbios1:
            uuid: 5aacfba5-8167-4465-97d7-1567f3d98a45
          proxmox_snapshots: []
          proxmox_sockets: 1
          proxmox_status: running
          proxmox_tags: database
          proxmox_tags_parsed:
          - database
          proxmox_vmgenid: 3a88a3f5-210f-451a-bd1a-8701d18abec7
          proxmox_vmid: 101
          proxmox_vmtype: qemu
        web:
          proxmox_agent: '1'
          proxmox_agent_interfaces:
          - ip-addresses:
            - 127.0.0.1/8
            - ::1/128
            mac-address: 00:00:00:00:00:00
            name: lo
          - ip-addresses:
            - 192.168.50.209/24
            - fe80::a4cb:47ff:fe06:c121/64
            mac-address: a6:cb:47:06:c1:21
            name: ens18
          proxmox_boot:
            order: scsi0;ide2;net0
          proxmox_cores: 2
          proxmox_cpu: x86-64-v2-AES
          proxmox_digest: b28a87e97e83316175dc63f48bac1c94028e63ae
          proxmox_ide0:
            disk_image: local-lvm:vm-100-cloudinit
            media: cdrom
          proxmox_ide2:
            disk_image: local:iso/Fedora-Server-dvd-x86_64-43-1.6.iso
            media: cdrom
            size: 3402816K
          proxmox_ipconfig0:
            gw: 192.168.50.1
            ip: 192.168.50.209/24
          proxmox_memory: 4096
          proxmox_meta:
            creation-qemu: 8.0.2
            ctime: '1769431736'
          proxmox_name: web
          proxmox_net0:
            bridge: vmbr0
            firewall: '1'
            virtio: A6:CB:47:06:C1:21
          proxmox_node: pve
          proxmox_numa: 0
          proxmox_ostype: l26
          proxmox_qmpstatus: running
          proxmox_scsi0:
            disk_image: local-lvm:vm-100-disk-0
            iothread: '1'
            size: 32G
          proxmox_scsihw:
            disk_image: virtio-scsi-single
          proxmox_smbios1:
            uuid: 6386b16c-95e4-4038-9566-9448631386d7
          proxmox_snapshots: []
          proxmox_sockets: 1
          proxmox_status: running
          proxmox_tags: web
          proxmox_tags_parsed:
          - web
          proxmox_vmgenid: 9946e95e-8314-420f-9744-0b592956c8ef
          proxmox_vmid: 100
          proxmox_vmtype: qemu
    proxmox_all_running:
      hosts:
        mysql: {}
        web: {}
    proxmox_pool_database:
      hosts:
        mysql: {}
    proxmox_pool_web:
      hosts:
        web: {}
    proxmox_pve_qemu:
      hosts:
        mysql: {}
        web: {}

这里有个比较重要的变量 proxmox_ipconfig0,如果虚拟机使用了 cloud-init,那么就会有 proxmox_ipconfig0 变量,这个变量里有 cloud-init 要设置的虚拟机地址,可以将它设置为虚拟机的 ansible_host 变量用于主机连接。

参考以下例子:

[root@remote-host ansible]# cat inventory/proxmox.yml
# inventory/proxmox.yml
plugin: community.general.proxmox

url: https://192.168.50.206:8006
user: root@pam
password: "redhat"
validate_certs: false

exclude_nodes: true
want_facts: true
want_proxmox_nodes_ansible_host: false

keyed_groups:
- key: proxmox_tags_parsed
  separator: ""
  prefix: group
groups:
  webservers: "'web' in (proxmox_tags_parsed|list)"
  databaseservers: "'database' in (proxmox_tags_parsed|list)"

compose:
  ansible_host: proxmox_ipconfig0.ip | default(proxmox_net0.ip) | ipaddr('address')
  ansible_port: 22
  ansible_user: "'root'"
  ansible_password: >
    "redhat"
  • compose 用于设置变量,其中 ansible_host 通过 proxmox_ipconfig0.ip | default(proxmox_net0.ip) | ipaddr('address') 设置
  • keyed_groupsgroups 可以根据虚拟机标签对虚拟机进行分组

通过上述动态主机清单获取的主机信息如下:

[root@remote-host ansible]# ansible-navigator inventory \
    -i inventory/proxmox.yml --yaml --list
[DEPRECATION WARNING]: Use 'ansible.utils.ipaddr' module instead. This feature will be removed from ansible.netcommon in a release after 2024-01-01. Deprecation warnings can be disabled by setting
deprecation_warnings=False in ansible.cfg.
all:
  children:
    databaseservers:
      hosts:
        mysql: {}
    groupdatabase:
      hosts:
        mysql: {}
    groupweb:
      hosts:
        web: {}
    proxmox_all_qemu:
      hosts:
        mysql:
          ansible_host: 192.168.50.219
          ansible_password: redhat
          ansible_port: '22'
          ansible_user: root
          proxmox_agent: '1'
          proxmox_agent_interfaces:
          - ip-addresses:
            - 127.0.0.1/8
            - ::1/128
            mac-address: 00:00:00:00:00:00
            name: lo
          - ip-addresses:
            - 192.168.50.219/24
            - fe80::6cf5:1ff:fe25:fd25/64
            mac-address: 6e:f5:01:25:fd:25
            name: ens18
          proxmox_boot:
            order: scsi0;ide2;net0
          proxmox_cores: 4
          proxmox_cpu: x86-64-v2-AES
          proxmox_digest: b077ccef985e0f4b23f8062dda94b77f4c222687
          proxmox_ide2:
            disk_image: local:iso/Fedora-Server-dvd-x86_64-43-1.6.iso
            media: cdrom
            size: 3402816K
          proxmox_ipconfig0:
            gw: 192.168.50.1
            ip: 192.168.50.219/24
          proxmox_memory: 8192
          proxmox_meta:
            creation-qemu: 8.0.2
            ctime: '1769431780'
          proxmox_name: mysql
          proxmox_net0:
            bridge: vmbr0
            firewall: '1'
            virtio: 6E:F5:01:25:FD:25
          proxmox_node: pve
          proxmox_numa: 0
          proxmox_ostype: l26
          proxmox_qmpstatus: running
          proxmox_sata0:
            disk_image: local:101/vm-101-cloudinit.qcow2
            media: cdrom
          proxmox_scsi0:
            disk_image: local-lvm:vm-101-disk-0
            iothread: '1'
            size: 32G
          proxmox_scsihw:
            disk_image: virtio-scsi-single
          proxmox_smbios1:
            uuid: 5aacfba5-8167-4465-97d7-1567f3d98a45
          proxmox_snapshots: []
          proxmox_sockets: 1
          proxmox_status: running
          proxmox_tags: database
          proxmox_tags_parsed:
          - database
          proxmox_vmgenid: 3a88a3f5-210f-451a-bd1a-8701d18abec7
          proxmox_vmid: 101
          proxmox_vmtype: qemu
        web:
          ansible_host: 192.168.50.209
          ansible_password: redhat
          ansible_port: '22'
          ansible_user: root
          proxmox_agent: '1'
          proxmox_agent_interfaces:
          - ip-addresses:
            - 127.0.0.1/8
            - ::1/128
            mac-address: 00:00:00:00:00:00
            name: lo
          - ip-addresses:
            - 192.168.50.209/24
            - fe80::a4cb:47ff:fe06:c121/64
            mac-address: a6:cb:47:06:c1:21
            name: ens18
          proxmox_boot:
            order: scsi0;ide2;net0
          proxmox_cores: 2
          proxmox_cpu: x86-64-v2-AES
          proxmox_digest: b28a87e97e83316175dc63f48bac1c94028e63ae
          proxmox_ide0:
            disk_image: local-lvm:vm-100-cloudinit
            media: cdrom
          proxmox_ide2:
            disk_image: local:iso/Fedora-Server-dvd-x86_64-43-1.6.iso
            media: cdrom
            size: 3402816K
          proxmox_ipconfig0:
            gw: 192.168.50.1
            ip: 192.168.50.209/24
          proxmox_memory: 4096
          proxmox_meta:
            creation-qemu: 8.0.2
            ctime: '1769431736'
          proxmox_name: web
          proxmox_net0:
            bridge: vmbr0
            firewall: '1'
            virtio: A6:CB:47:06:C1:21
          proxmox_node: pve
          proxmox_numa: 0
          proxmox_ostype: l26
          proxmox_qmpstatus: running
          proxmox_scsi0:
            disk_image: local-lvm:vm-100-disk-0
            iothread: '1'
            size: 32G
          proxmox_scsihw:
            disk_image: virtio-scsi-single
          proxmox_smbios1:
            uuid: 6386b16c-95e4-4038-9566-9448631386d7
          proxmox_snapshots: []
          proxmox_sockets: 1
          proxmox_status: running
          proxmox_tags: web
          proxmox_tags_parsed:
          - web
          proxmox_vmgenid: 9946e95e-8314-420f-9744-0b592956c8ef
          proxmox_vmid: 100
          proxmox_vmtype: qemu
    proxmox_all_running:
      hosts:
        mysql: {}
        web: {}
    proxmox_pool_database:
      hosts:
        mysql: {}
    proxmox_pool_web:
      hosts:
        web: {}
    proxmox_pve_qemu:
      hosts:
        mysql: {}
        web: {}
    webservers:
      hosts:
        web: {}

这里的 [DEPRECATION WARNING] 告警主要是提示 ipaddr 过滤器插件在未来的版本里将从 ansible.netcommon 集合迁移到 ansible.utils 中。

再来个简洁的:

[root@remote-host ansible]# ansible-navigator inventory \
    -i inventory/proxmox.yml --graph
[DEPRECATION WARNING]: Use 'ansible.utils.ipaddr' module instead. This feature will be removed from ansible.netcommon in a release after 2024-01-01. Deprecation warnings can be disabled by setting
deprecation_warnings=False in ansible.cfg.
@all:
  |--@ungrouped:
  |--@proxmox_all_lxc:
  |--@proxmox_all_qemu:
  |  |--web
  |  |--mysql
  |--@proxmox_all_running:
  |  |--web
  |  |--mysql
  |--@proxmox_all_stopped:
  |--@proxmox_pve_lxc:
  |--@proxmox_pve_qemu:
  |  |--web
  |  |--mysql
  |--@webservers:
  |  |--web
  |--@groupweb:
  |  |--web
  |--@databaseservers:
  |  |--mysql
  |--@groupdatabase:
  |  |--mysql
  |--@proxmox_pool_database:
  |  |--mysql
  |--@proxmox_pool_web:
  |  |--web

最后测试一下是否能通过这个主机清单执行任务:

[root@remote-host ansible]# ansible-navigator exec \
    -- "ansible -i inventory/proxmox.yml all -m ping"
[DEPRECATION WARNING]: Use 'ansible.utils.ipaddr' module instead. This feature will be removed from ansible.netcommon in a release after 2024-01-01. Deprecation warnings can be disabled by setting
deprecation_warnings=False in ansible.cfg.
web | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
mysql | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}

自定义动态主机清单

除了使用开源社区现有的动态主机清单插件,也可以自己写一个动态主机清单脚本。

我们先看下静态主机清单被 Ansible 解析的内容:

[root@remote-host ansible]# cat inventory.bak

[k8s_master]

base-k8s-master-1

[k8s_worker]

base-k8s-worker-1 base-k8s-worker-2

[k8s_master:vars]

role=master

[k8s_worker:vars]

role=worker

[ntp_client]

[ntp_client:children] k8s_worker

[all:vars]

ansible_ssh_user=remote-manager ansible_ssh_password=redhat ansible_become_password=redhat [root@remote-host ansible]# ansible-navigator inventory -i inventory.bak –list { “_meta”: { “hostvars”: { “base-k8s-master-1”: { “ansible_become_password”: “redhat”, “ansible_ssh_password”: “redhat”, “ansible_ssh_user”: “remote-manager”, “role”: “master” }, “base-k8s-worker-1”: { “ansible_become_password”: “redhat”, “ansible_ssh_password”: “redhat”, “ansible_ssh_user”: “remote-manager”, “role”: “worker” }, “base-k8s-worker-2”: { “ansible_become_password”: “redhat”, “ansible_ssh_password”: “redhat”, “ansible_ssh_user”: “remote-manager”, “role”: “worker” } } }, “all”: { “children”: [ “ungrouped”, “k8s_master”, “ntp_client” ] }, “k8s_master”: { “hosts”: [ “base-k8s-master-1” ] }, “k8s_worker”: { “hosts”: [ “base-k8s-worker-1”, “base-k8s-worker-2” ] }, “ntp_client”: { “children”: [ “k8s_worker” ] } } [root@remote-host ansible]# ansible-navigator inventory -i inventory.bak –host base-k8s-master-1 { “ansible_become_password”: “redhat”, “ansible_ssh_password”: “redhat”, “ansible_ssh_user”: “remote-manager”, “role”: “master” }

针对上边这个输出说一下动态主机清单脚本的要求:

  • 脚本要添加适当的解析器,如 #!/usr/bin/python
  • 脚本的输出内容和上边 --list 的输出结构类似
  • 脚本必须支持 --list--host <hostname> 两个参数,--list 列出所有主机(包括主机组信息)和其变量,--host <hostname> 列出特定主机在主机清单中定义的变量

更多请参考 https://docs.ansible.com/projects/ansible/latest/dev_guide/developing_inventory.html#developing-inventory-scripts。

来个简单演示:

下边这个脚本是用 AI 写的,脚本支持 --list--host 两个参数。

先执行下脚本看看:

# 直接执行脚本
[root@remote-host ansible]# inventory/custom_dynamic_inventory.py
{
  "all": {
    "children": [
      "ungrouped",
      "k8s_master",
      "ntp_client"
    ]
  },
  "k8s_master": {
    "hosts": [
      "base-k8s-master-1"
    ],
    "vars": {
      "ansible_become_password": "redhat",
      "ansible_ssh_password": "redhat",
      "ansible_ssh_user": "remote-manager",
      "role": "master"
    }
  },
  "k8s_worker": {
    "hosts": [
      "base-k8s-worker-1",
      "base-k8s-worker-2"
    ],
    "vars": {
      "ansible_become_password": "redhat",
      "ansible_ssh_password": "redhat",
      "ansible_ssh_user": "remote-manager",
      "role": "worker"
    }
  },
  "ntp_client": {
    "children": [
      "k8s_worker"
    ]
  },
  "_meta": {
    "hostvars": {
      "base-k8s-master-1": {
        "ansible_become_password": "redhat",
        "ansible_ssh_password": "redhat",
        "ansible_ssh_user": "remote-manager",
        "role": "master",
        "ansible_host": "base-k8s-master-1"
      },
      "base-k8s-worker-1": {
        "ansible_become_password": "redhat",
        "ansible_ssh_password": "redhat",
        "ansible_ssh_user": "remote-manager",
        "role": "worker",
        "ansible_host": "base-k8s-worker-1"
      },
      "base-k8s-worker-2": {
        "ansible_become_password": "redhat",
        "ansible_ssh_password": "redhat",
        "ansible_ssh_user": "remote-manager",
        "role": "worker",
        "ansible_host": "base-k8s-worker-2"
      }
    }
  }
}

# 执行脚本并添加 --list 参数
[root@remote-host ansible]# inventory/custom_dynamic_inventory.py --list
{
  "all": {
    "children": [
      "ungrouped",
      "k8s_master",
      "ntp_client"
    ]
  },
  "k8s_master": {
    "hosts": [
      "base-k8s-master-1"
    ],
    "vars": {
      "ansible_become_password": "redhat",
      "ansible_ssh_password": "redhat",
      "ansible_ssh_user": "remote-manager",
      "role": "master"
    }
  },
  "k8s_worker": {
    "hosts": [
      "base-k8s-worker-1",
      "base-k8s-worker-2"
    ],
    "vars": {
      "ansible_become_password": "redhat",
      "ansible_ssh_password": "redhat",
      "ansible_ssh_user": "remote-manager",
      "role": "worker"
    }
  },
  "ntp_client": {
    "children": [
      "k8s_worker"
    ]
  },
  "_meta": {
    "hostvars": {
      "base-k8s-master-1": {
        "ansible_become_password": "redhat",
        "ansible_ssh_password": "redhat",
        "ansible_ssh_user": "remote-manager",
        "role": "master",
        "ansible_host": "base-k8s-master-1"
      },
      "base-k8s-worker-1": {
        "ansible_become_password": "redhat",
        "ansible_ssh_password": "redhat",
        "ansible_ssh_user": "remote-manager",
        "role": "worker",
        "ansible_host": "base-k8s-worker-1"
      },
      "base-k8s-worker-2": {
        "ansible_become_password": "redhat",
        "ansible_ssh_password": "redhat",
        "ansible_ssh_user": "remote-manager",
        "role": "worker",
        "ansible_host": "base-k8s-worker-2"
      }
    }
  }
}

# 执行脚本并添加 --host 参数
[root@remote-host ansible]# inventory/custom_dynamic_inventory.py --host base-k8s-master-1
{
  "ansible_become_password": "redhat",
  "ansible_ssh_password": "redhat",
  "ansible_ssh_user": "remote-manager",
  "role": "master",
  "ansible_host": "base-k8s-master-1"
}

再用 Ansible 调用脚本看看:

[root@remote-host ansible]# ansible-navigator inventory -i inventory/custom_dynamic_inventory.py --graph
@all:
  |--@ungrouped:
  |--@k8s_master:
  |  |--base-k8s-master-1
  |--@ntp_client:
  |  |--@k8s_worker:
  |  |  |--base-k8s-worker-1
  |  |  |--base-k8s-worker-2

[root@remote-host ansible]# ansible-navigator inventory -i inventory/custom_dynamic_inventory.py --host base-k8s-worker-1
{
    "ansible_become_password": "redhat",
    "ansible_host": "base-k8s-worker-1",
    "ansible_ssh_password": "redhat",
    "ansible_ssh_user": "remote-manager",
    "role": "worker"
}

[root@remote-host ansible]# ansible-navigator exec -- ansible -i inventory/custom_dynamic_inventory.py all --list-hosts
  hosts (3):
    base-k8s-master-1
    base-k8s-worker-1
    base-k8s-worker-2
Ansible 动态主机清单
https://www.linuxstudynotes.com/2026/02/08/ansible/ansible-%e5%8a%a8%e6%80%81%e4%b8%bb%e6%9c%ba%e6%b8%85%e5%8d%95/
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇