Ansible 自动化项目结构与 Harbor 安装示例(基于 kubeasz)①
- Playbook:Ansible 中的剧本文件,定义了一系列的任务,这些任务将按照顺序执行。
- Role:Ansible 角色是一种组织 Playbook 的方式,它使得代码更加模块化和可复用。
- Task:Ansible 中的一个独立的操作步骤。
- Variable:变量可以在 Playbook 和 Role 中使用,用来存储动态信息或配置项。
- Template:使用 Jinja2 模板语言来生成配置文
一、Ansible 项目通用结构说明
| 文件/目录 | 是否必需 | 说明 |
|---|---|---|
playbook.yml(或类似名称) | ✅ 是 | 主 Playbook 文件,定义要执行的任务、目标主机、使用的角色等。Ansible 执行的入口点。 |
inventory(或 hosts、inventory.ini) | ✅ 是(除非命令行指定) | 主机清单文件,定义目标主机及其分组。可为静态(INI/YAML)或动态脚本。 |
roles/ | ❌ 否(但强烈推荐) | 角色目录,每个角色封装独立功能(如安装 Nginx),包含 tasks/、handlers/、templates/ 等子目录,实现模块化与复用。 |
group_vars/ | ❌ 否 | 主机组变量目录,如 group_vars/webservers.yml,为某组主机统一设置变量。 |
host_vars/ | ❌ 否 | 主机级变量目录,如 host_vars/web01.yml,为单个主机覆盖或定制变量。 |
vars/ 或 vars.yml | ❌ 否 | 通用变量文件,可在 Playbook 中通过 vars_files 引入,适用于跨角色共享配置。 |
templates/ | ❌ 否 | Jinja2 模板目录,存放 .j2 文件,用于动态生成配置(如 nginx.conf.j2)。 |
files/ | ❌ 否 | 静态文件目录,存放需通过 copy 模块分发的文件(如证书、安装包)。 |
handlers/ | ❌ 否 | 处理器目录,定义由任务 notify 触发的操作(如重启服务),仅在被通知时执行一次。 |
ansible.cfg | ❌ 否 | 全局配置文件,控制 Ansible 行为(如 inventory 路径、并发数、SSH 设置等)。 |
requirements.yml | ❌ 否 | 依赖声明文件,列出需从 Ansible Galaxy 安装的角色或集合,执行 ansible-galaxy install -r 安装。 |
.ansible-lint / .yamllint | ❌ 否 | 代码规范配置,用于自动化检查 Playbook 风格与语法。 |
README.md | ❌ 否 | 项目说明文档,描述用途、使用方法、变量含义、部署步骤等。 |
最小可行项目:只需
playbook.yml+inventory两个文件即可运行。
最佳实践:使用roles组织任务,提升可读性、可测试性与复用性。
变量优先级(从低到高):
role defaults<role vars<group_vars / host_vars<playbook vars<extra vars (-e)
示例目录结构(推荐用于中大型项目)
my-ansible-project/
├── ansible.cfg # 全局配置
├── inventory # 主机清单
├── playbook.yml # 主 Playbook
├── group_vars/ # 主机组变量
│ └── webservers.yml
├── host_vars/ # 主机级变量
│ └── db01.yml
├── roles/ # 角色目录
│ └── nginx/
│ ├── tasks/main.yml # 核心任务
│ ├── handlers/main.yml # 服务重启等处理器
│ ├── templates/nginx.conf.j2 # 配置模板
│ └── vars/main.yml # 角色内部变量
├── files/ # 静态文件(如安装包)
│ └── app.tar.gz
└── requirements.yml # 外部角色依赖
二、kubeasz 项目中 Harbor 安装示例
1. Inventory 文件(inventory)
# ================================
# ETCD 集群节点定义
# ================================
# etcd 是 Kubernetes 的核心键值存储,用于保存集群状态。
# ⚠️ 必须为奇数个节点(1, 3, 5...),以支持 Raft 协议正常选举 leader,避免脑裂。
[etcd]
192.168.1.1
192.168.1.2
192.168.1.3# ================================
# Kubernetes 控制平面(Master)节点
# ================================
# 运行 kube-apiserver、kube-controller-manager、kube-scheduler 等组件。
# k8s_nodename 用于 Kubernetes 内部识别节点,命名需符合 DNS 子域名规范。
[kube_master]
192.168.1.1 k8s_nodename='master-01'
192.168.1.2 k8s_nodename='master-02'
192.168.1.3 k8s_nodename='master-03'# ================================
# Kubernetes 工作节点(Worker/Node)
# ================================
# 运行应用 Pod,由 kubelet 管理容器生命周期。
[kube_node]
192.168.1.4 k8s_nodename='worker-01'
192.168.1.5 k8s_nodename='worker-02'# ================================
# [可选] Harbor 私有镜像仓库节点
# ================================
# NEW_INSTALL:
# - true → 在此节点全新安装 Harbor(需 Docker 环境)
# - false → 仅配置集群使用已有 Harbor(不安装)
# 注释整行表示不启用 Harbor 功能。
[harbor]
#192.168.1.8 NEW_INSTALL=false# ================================
# [可选] 外部负载均衡器(HA API Server)
# ================================
# 使用 keepalived + haproxy 实现高可用 LB,对外暴露统一 VIP。
# LB_ROLE: master(主)或 backup(备)
# EX_APISERVER_VIP: 虚拟 IP(需与节点同网段)
# EX_APISERVER_PORT: 对外端口(如 6443 或 8443)
[ex_lb]
#192.168.1.6 LB_ROLE=backup EX_APISERVER_VIP=192.168.1.250 EX_APISERVER_PORT=8443
#192.168.1.7 LB_ROLE=master EX_APISERVER_VIP=192.168.1.250 EX_APISERVER_PORT=8443# ================================
# [可选] 时间同步服务器(Chrony/NTP)
# ================================
# Kubernetes 要求所有节点时间同步(误差 < 1 秒),否则可能导致证书或调度异常。
# 若未定义此组,则默认使用公网 NTP 服务器。
[chrony]
#192.168.1.1# ================================
# 全局变量(适用于所有主机)
# ================================
[all:vars]# --- 核心 Kubernetes 配置 ---
SECURE_PORT="6443" # API Server 安全通信端口
CONTAINER_RUNTIME="containerd" # 容器运行时(K8s 1.24+ 推荐 containerd)
CLUSTER_NETWORK="calico" # CNI 网络插件(calico/flannel/cilium 等)
PROXY_MODE="ipvs" # kube-proxy 模式(iptables/ipvs)
SERVICE_CIDR="10.68.0.0/16" # Service ClusterIP 范围(不可与物理网络冲突)
CLUSTER_CIDR="172.20.0.0/16" # Pod IP 范围(由 CNI 分配)
NODE_PORT_RANGE="30000-32767" # NodePort 端口范围
CLUSTER_DNS_DOMAIN="cluster.local" # 集群内部 DNS 域名后缀# --- 路径与系统配置 ---
bin_dir="/opt/kube/bin" # 二进制文件安装目录
base_dir="/etc/kubeasz" # kubeasz 工具根目录
cluster_dir="{{ base_dir }}/clusters/_cluster_name_" # 当前集群专属配置目录(_cluster_name_ 会被替换)
ca_dir="/etc/kubernetes/ssl" # TLS 证书存储目录
k8s_nodename='' # 默认空值,由各节点单独指定
ansible_python_interpreter=/usr/bin/python3 # Ansible 使用的 Python 解释器路径
2. Ansible 配置文件(ansible.cfg)
[defaults]
# -------------------------------
# 基础路径与行为
# -------------------------------
roles_path = /etc/kubeasz/roles # 自定义角色搜索路径(指向 kubeasz 角色库)
host_key_checking = False # 禁用 SSH 主机密钥检查(避免首次连接交互,适合自动化)
gathering = smart # 智能收集 facts:首次收集,后续跳过(提升效率)
gather_timeout = 7 # facts 收集超时(秒)
private_role_vars = True # 角色变量私有化,避免污染全局命名空间
display_skipped_hosts = False # 不显示被跳过的主机(减少输出噪音)
display_args_to_stdout = False # 不在任务标题中显示参数(防止敏感信息泄露)
error_on_undefined_vars = True # 模板中引用未定义变量时报错(提前暴露配置错误)
system_warnings = False # 禁用系统警告(如缺少 Python 包)
deprecation_warnings = False # 禁用弃用警告
retry_files_enabled = False # 失败时不生成 .retry 文件
pipelining = True # 启用 SSH pipelining:复用连接,避免临时文件,大幅提升性能
forks = 10 # 并发执行主机数(默认 5,可适当调高)# SSH 控制路径(避免路径过长导致 socket 错误)
control_path_dir = /tmp
control_path = /tmp/ansible-ssh-%%h-%%p-%%r[ssh_connection]
# 启用 SSH 连接复用和压缩,显著提升大规模部署性能
ssh_args = -C -o ControlMaster=auto -o ControlPersist=60s
pipelining = True
关键注释:
pipelining = True需确保目标主机/etc/sudoers中 禁用requiretty(即包含Defaults !requiretty)。host_key_checking = False虽方便,但在高安全环境应设为True并预置 known_hosts。error_on_undefined_vars = True是开发阶段的“安全网”,避免因拼写错误导致配置异常。
3. Harbor 安装 Playbook(deploy-harbor.yml)
---
# =============================================
# Playbook:部署 Harbor 镜像仓库并集成到 Kubernetes 集群
# =============================================# 第一部分:在 Harbor 节点上安装 Harbor(仅当 NEW_INSTALL=true 时执行)
- name: Install and configure Harbor on designated hosthosts: harborroles:# 1. 操作系统安全加固(可选)- role: os-hardenwhen: NEW_INSTALL | bool and OS_HARDEN | bool# 注释:仅当全新安装且启用了 OS_HARDEN 变量时执行。# |bool 过滤器将字符串 "true"/"false" 转为布尔值,避免类型错误。# 2. 配置时间同步(若 chrony 组存在)- role: chronywhen: NEW_INSTALL | bool and groups['chrony'] | length > 0# 注释:groups['chrony'] 是 Ansible 内置变量,表示 chrony 组的主机列表。# 仅当该组非空且为全新安装时才配置 chrony。# 3. 系统预配置(关闭 swap、加载内核模块等)- role: preparewhen: NEW_INSTALL | bool# 4. 安装 Docker(Harbor 依赖)- role: dockerwhen: NEW_INSTALL | bool# 5. 安装 Harbor(基于 docker-compose)- role: harborwhen: NEW_INSTALL | bool# 注释:角色内部会读取 HARBOR_DOMAIN、HARBOR_ADMIN_PASSWORD 等变量。# 第二部分:配置所有 Kubernetes 节点信任 Harbor(用于无 DNS 环境)
- name: Configure Kubernetes nodes to resolve Harbor domain via /etc/hostshosts:- kube_master- kube_nodetasks:- name: Add /etc/hosts entry for Harbor domainlineinfile:dest: /etc/hostsstate: presentregexp: '{{ HARBOR_DOMAIN }}' # 若已存在含域名的行,则替换line: "{{ groups['harbor'][0] }} {{ HARBOR_DOMAIN }}" # 格式:IP 域名when: ># 多条件判断:确保 harbor 组存在、非空、且定义了 HARBOR_DOMAINgroups['harbor'] is defined andgroups['harbor'] | length > 0 andhostvars[groups['harbor'][0]].get('HARBOR_DOMAIN', '') != ''# 注释:# - groups['harbor'][0]:取 harbor 组第一台主机的 IP(假设 inventory 中已定义)# - hostvars[host]:获取指定主机的所有变量# - .get('key', ''):安全获取变量,避免 KeyError
设计亮点:
- 条件驱动:所有任务均受
NEW_INSTALL控制,支持“仅配置”模式。- 安全防护:多层条件判断防止空变量或未定义组导致任务失败。
- 环境适配:适用于无 DNS 的内网环境,通过
/etc/hosts实现域名解析。- 幂等性:
lineinfile模块确保重复执行不会产生重复行。
4.roles由于篇幅见下篇文章 https://blog.csdn.net/m0_66705547/article/details/153972665
