From 5dcfcad0989476c3d581ff6b7615d1000d029ad9 Mon Sep 17 00:00:00 2001 From: panxiao81 Date: Thu, 1 Oct 2026 16:54:03 +0000 Subject: [PATCH] =?UTF-8?q?=E4=B8=BA=20Ayatori=20=E5=AE=B9=E5=99=A8?= =?UTF-8?q?=E5=9B=BA=E5=AE=9A=E9=9D=99=E6=80=81=E5=9C=B0=E5=9D=80=E5=B9=B6?= =?UTF-8?q?=E5=8F=91=E5=B8=83=20AD=20DNS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - dev 192.168.10.11、prod 192.168.10.12,位于 NEC IX DHCP 池之外 - 地址仅在 records.yml 声明一次,netplan 与 Samba DNS 同源读取 - 容器内禁用 cloud-init 网络模块,避免重启后回到 DHCP - dns.yml 扩展到 ayatori-dev / ayatori-prod 两条 A 记录 Co-Authored-By: Claude Opus 5.5 --- infrastructure/dns/records.yml | 4 ++ infrastructure/incus/README.md | 15 +++--- infrastructure/incus/ansible/containers.yml | 11 +++- infrastructure/incus/ansible/dns.yml | 16 +++--- .../incus/ansible/tasks/container-network.yml | 52 +++++++++++++++++++ 5 files changed, 84 insertions(+), 14 deletions(-) create mode 100644 infrastructure/incus/ansible/tasks/container-network.yml diff --git a/infrastructure/dns/records.yml b/infrastructure/dns/records.yml index 3a9e119..13e7c62 100644 --- a/infrastructure/dns/records.yml +++ b/infrastructure/dns/records.yml @@ -7,6 +7,10 @@ homelab_dns: # RRsets are reconciled; Samba-generated AD/Kerberos records are untouched. records: - { zone: ad.ddupan.top, name: incus, type: A, values: [192.168.10.127] } + # Static, outside the NEC IX pool (.128-.250); infrastructure/incus/ansible/containers.yml + # reads these same values to pin each container's netplan address. + - { zone: ad.ddupan.top, name: ayatori-dev, type: A, values: [192.168.10.11] } + - { zone: ad.ddupan.top, name: ayatori-prod, type: A, values: [192.168.10.12] } - { zone: ad.ddupan.top, name: bao, type: A, values: [192.168.10.8] } - { zone: ad.ddupan.top, name: pve1, type: A, values: [192.168.10.4] } - { zone: ad.ddupan.top, name: pve2, type: A, values: [192.168.10.7] } diff --git a/infrastructure/incus/README.md b/infrastructure/incus/README.md index 531492c..a496ec0 100644 --- a/infrastructure/incus/README.md +++ b/infrastructure/incus/README.md @@ -61,7 +61,7 @@ CLI 可使用 `incus remote add laptop https://incus.ad.ddupan.top --auth-type=o - `ansible/templates/gateway.yaml.j2`:独立 namespace、Service/EndpointSlice、HTTPRoute、 BackendTLSPolicy。入口复用现有通配符证书,后端以 Incus 的公共 server.crt 验证 `laptop` SAN,不跳过 TLS 验证。公共证书由 playbook 读取,不复制私钥。 -- `infrastructure/dns/records.yml`:唯一 DNS 声明;`ansible/dns.yml` 只协调 Incus 记录。 +- `infrastructure/dns/records.yml`:唯一 DNS 声明;`ansible/dns.yml` 只协调 Incus 与两个 Ayatori 容器的记录。 入口资源由此 Ansible playbook 管理,尚未交由 Flux。共享 Gateway 的后端 TLS 兼容配置由 Flux 管理:EnvoyProxy `eg` 允许 TLS 1.2–1.3,以连接要求 TLS 1.3 @@ -110,9 +110,12 @@ ANSIBLE_CONFIG=ansible.cfg ANSIBLE_COLLECTIONS_PATH=collections ANSIBLE_LOCAL_TE 2 GiB 内存、20 GiB rootfs,禁用容器 swap,自动启动。没有安装 Ayatori、k0s、 kube-apiserver、controller 或数据库;准备 Prod 空容器不代表生产服务已上线。 -网络使用既有 `br0` 的 DHCP,固定 MAC 分别为 `02:16:3e:aa:00:01`、 -`02:16:3e:aa:00:02`。地址不是静态分配,不发布 DNS;后续固定服务地址前应建立 -DHCP reservation 或核对地址池后配置静态地址。 +网络接入既有 `br0`,固定 MAC 分别为 `02:16:3e:aa:00:01`、`02:16:3e:aa:00:02`。 +首次启动走 DHCP,随后 `ansible/containers.yml` 改为静态地址:Dev `192.168.10.11`、 +Prod `192.168.10.12`(`ayatori-{dev,prod}.ad.ddupan.top`)。地址只在 +`infrastructure/dns/records.yml` 声明一次,netplan 与 AD DNS 均从此读取;须位于 +NEC IX DHCP 池(`.128–.250`)之外。容器内禁用 cloud-init 网络模块,否则每次启动都会 +重写回 DHCP。 初始账号 `panxiao81`,使用 `ansible/files/panxiao81.pub` 公钥登录,可 sudo; 密码登录关闭。宿主也可使用 `incus exec local:ayatori-dev -- bash`。 @@ -141,5 +144,5 @@ cloud-init 用户设置主要在首次启动执行,修改声明不能替代后 `mkdir ... file exists` 竞争;按上面的串行 apply 执行。失败后先重新 plan, 保留已成功创建的实例,不清理或销毁其资源。 -当前 DHCP 地址:Dev `192.168.10.131`,Prod `192.168.10.132`(2026-09-25)。 -`ansible/containers.yml` 通过本机 Incus exec 幂等安装并启用 SSH server。 +`ansible/containers.yml` 通过本机 Incus exec 幂等固定静态地址,并安装、启用 SSH server; +走 exec 而非 SSH,切换地址不会切断 Ansible 自身连接。 diff --git a/infrastructure/incus/ansible/containers.yml b/infrastructure/incus/ansible/containers.yml index dc55d01..ab38033 100644 --- a/infrastructure/incus/ansible/containers.yml +++ b/infrastructure/incus/ansible/containers.yml @@ -1,8 +1,17 @@ --- -- name: 准备 Ayatori 基础容器的 SSH 入口 +- name: 准备 Ayatori 基础容器的网络与 SSH 入口 hosts: incus_hosts gather_facts: false + # 静态地址与 AD DNS 记录同源,避免两处地址漂移。 + vars_files: + - ../../dns/records.yml tasks: + - name: 按容器协调静态地址 + ansible.builtin.include_tasks: tasks/container-network.yml + loop: [ayatori-dev, ayatori-prod] + loop_control: + loop_var: incus_container + - name: 按容器协调 SSH ansible.builtin.include_tasks: tasks/container-ssh.yml loop: [ayatori-dev, ayatori-prod] diff --git a/infrastructure/incus/ansible/dns.yml b/infrastructure/incus/ansible/dns.yml index 639d26e..396452e 100644 --- a/infrastructure/incus/ansible/dns.yml +++ b/infrastructure/incus/ansible/dns.yml @@ -1,21 +1,23 @@ --- -- name: 仅协调 Incus 的 AD DNS 记录 +- name: 仅协调 Incus 与 Ayatori 容器的 AD DNS 记录 hosts: samba_dc become: true gather_facts: false + vars: + incus_dns_names: [incus, ayatori-dev, ayatori-prod] vars_files: - ../../dns/records.yml - ../../samba-ad/ansible/group_vars/all/vars.yml tasks: - - name: 从共享清单选择 Incus RRset + - name: 从共享清单选择 Incus 相关 RRset ansible.builtin.set_fact: - incus_dns_records: "{{ homelab_dns.samba.records | selectattr('name', 'equalto', 'incus') | selectattr('zone', 'equalto', 'ad.ddupan.top') | list }}" - - name: 确认只有一个受管 A 记录 + incus_dns_records: "{{ homelab_dns.samba.records | selectattr('name', 'in', incus_dns_names) | selectattr('zone', 'equalto', 'ad.ddupan.top') | list }}" + - name: 确认每个名称恰有一个受管 A 记录 ansible.builtin.assert: that: - - incus_dns_records | length == 1 - - incus_dns_records[0].type == 'A' - - name: 协调 Incus A 记录 + - incus_dns_records | length == incus_dns_names | length + - incus_dns_records | map(attribute='type') | unique == ['A'] + - name: 协调 A 记录 ddupan.homelab.samba_dns_record: server: "{{ samba_ad_dc_ip }}" zone: "{{ item.zone }}" diff --git a/infrastructure/incus/ansible/tasks/container-network.yml b/infrastructure/incus/ansible/tasks/container-network.yml new file mode 100644 index 0000000..1287808 --- /dev/null +++ b/infrastructure/incus/ansible/tasks/container-network.yml @@ -0,0 +1,52 @@ +--- +# 地址必须在 NEC IX DHCP 池(.128–.250)之外;池由路由器手工维护,没有 reservation 可声明。 +# 用 incus exec 而非 SSH 执行,切换地址不会断开 Ansible 自身的连接。 +- name: 读取容器的 AD DNS 地址 + ansible.builtin.set_fact: + container_ipv4: >- + {{ (homelab_dns.samba.records + | selectattr('zone', 'equalto', 'ad.ddupan.top') + | selectattr('name', 'equalto', incus_container) + | first)['values'] | first }} + +# cloud-init 网络模块每次启动都会重写 50-cloud-init.yaml,必须先禁用它,静态配置才能持久。 +# 网关与 resolver 照搬原 DHCP 下发值(.1 网关;Blocky .127 优先、路由器 .1 兜底)。 +- name: 声明静态网络 + ansible.builtin.command: + argv: + - incus + - exec + - "local:{{ incus_container }}" + - --env + - "CLOUD_CFG={{ container_cloud_cfg }}" + - --env + - "NETPLAN={{ container_netplan }}" + - -- + - sh + - -euc + - | + changed=0 + put() { + if [ "$(cat "$1" 2>/dev/null)" != "$2" ]; then + printf '%s\n' "$2" > "$1"; chmod 600 "$1"; changed=1 + fi + } + put /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg "$CLOUD_CFG" + put /etc/netplan/60-static.yaml "$NETPLAN" + if [ -e /etc/netplan/50-cloud-init.yaml ]; then + rm /etc/netplan/50-cloud-init.yaml; changed=1 + fi + if [ "$changed" = 1 ]; then netplan apply; echo CHANGED; fi + vars: + container_cloud_cfg: "network: {config: disabled}" + container_netplan: |- + network: + version: 2 + ethernets: + eth0: + dhcp4: false + addresses: [{{ container_ipv4 }}/24] + routes: [{to: default, via: 192.168.10.1}] + nameservers: {addresses: [192.168.10.127, 192.168.10.1]} + register: container_network + changed_when: "'CHANGED' in container_network.stdout"