比较提交

64 次代码提交

修改 151 个文件,包含 3516 行新增1298 行删除
+20
查看文件
@@ -0,0 +1,20 @@
# 华为云OBS S3凭据 (velero备份 + CNPG WAL归档)
S3_ACCESS_KEY_ID=placeholder
S3_ACCESS_SECRET_KEY=placeholder
# DNSPod API凭据 (cert-manager ACME DNS验证)
DNSPOD_SECRET_ID=placeholder
DNSPOD_SECRET_KEY=placeholder
# Gitea Actions Runner TokenGitea 启动后在 admin → Runners 生成,参见 flux/README.md “部署后手工步骤”)
GITEA_ACTIONS_TOKEN=placeholder
# Flux Operator Web OIDC 凭据(Gitea 启动后创建 OAuth2 应用获取,Redirect URI: https://cd.dev.cm/oauth2/callback
FLUX_WEB_OIDC_CLIENT_ID=placeholder
FLUX_WEB_OIDC_CLIENT_SECRET=placeholder
# Infra Net 凭据
NET_MAXMIND_LICENSE_KEY=placeholder
NET_CROWDSEC_BOUNCER_API_KEY=placeholder
NET_TURNSTILE_SITE_KEY=placeholder
NET_TURNSTILE_SECRET_KEY=placeholder
+6
查看文件
@@ -2,6 +2,12 @@
logs
*.log
# Secrets
.env
flux-git-auth
flux-git-auth.pub
known_hosts
# Editor directories and files
.vscode/*
!.vscode/extensions.json
+4 -4
查看文件
@@ -1,9 +1,9 @@
### k3s 部署仓库 让你快速拥有一个高可用的k3s集群 并且具有完备的生产级能力(监控、告警、防护、负载、备份)
#### install 集群安装相关
#### 集群安装相关
参见 [install/README.md](install/README.md)
参见 [ansible/README.md](ansible/README.md)
#### apps 相关应用
#### 应用相关
参见 [apps/README.md](apps/README.md)
参见 [flux/README.md](flux/README.md)
+15
查看文件
@@ -0,0 +1,15 @@
# 环境变量模板
# 复制为 .env 并填写实际值,然后 source .env
# Tailscale Auth Key (必须)
export TAILSCALE_AUTH_KEY=""
# K3s HA Server URL (添加节点时需要)
export HA_SERVER_URL="https://k3s.example.com:6443"
# SSH 密码 (如果使用密码认证,必须设置;如果使用密钥认证,留空)
export SSH_PASSWORD=""
# SSH 公钥路径 (默认 ~/.ssh/id_rsa.pub)
# export SSH_PUBKEY=""
+17
查看文件
@@ -0,0 +1,17 @@
# Ansible 临时文件
*.retry
# 敏感文件
kubeconfig.yaml
kubeconfig-*.yaml
*.pem
*.key
# 本地环境
.env
.env.local
# IDE
.idea/
.vscode/
+157
查看文件
@@ -0,0 +1,157 @@
# K3s Ansible 自动化安装
一键部署 K3s 集群,支持国内镜像加速、Tailscale 组网、SSH 安全加固。
## 目录结构
```
ansible/
├── ansible.cfg # Ansible 配置
├── inventory/
│ ├── hosts.yml # 主机清单 ⭐ 需修改
│ └── group_vars/all.yml # 全局变量
├── roles/
│ ├── ssh/ # SSH 安全加固
│ │ ├── tasks/main.yml
│ │ ├── handlers/main.yml
│ │ └── templates/sshd_config.j2
│ ├── common/ # 基础配置 (hostname, sysctl, tailscale)
│ │ ├── tasks/main.yml
│ │ └── handlers/main.yml
│ └── k3s/ # K3s 安装
│ ├── tasks/main.yml
│ └── templates/
│ ├── k3s-server.yaml.j2 # Server 配置 (统一 init/join)
│ ├── k3s-agent.yaml.j2 # Agent 配置
│ └── registries.yaml.j2 # 镜像加速
└── playbooks/
└── site.yml # 完整安装
```
## 快速开始
### 1. 配置主机清单
编辑 `inventory/hosts.yml`:
```yaml
masters:
hosts:
master1:
ansible_host: 10.0.0.1
node_hostname: master1
cluster_init: true # 首个节点设为 true
node_region: cn-sh # 区域标签
use_mirror: true # 使用镜像加速
enable_lb: true # 启用 LB
netfilter_mode: "" # 阿里云/华为云设为 nodivert
```
### 2. 设置环境变量
```bash
# 必须
export TAILSCALE_AUTH_KEY="tskey-auth-xxx"
# 首次安装 (SSH 加固)
export SSH_PASSWORD="your-root-password"
```
### 3. 执行安装
```bash
cd k3s/ansible
# 方式一: 首次安装 (含 SSH 加固,端口改为 2103,启用密钥认证)
ansible-playbook playbooks/site.yml --tags ssh,common,k3s,status
# 方式二: 常规安装 (已配置 SSH 密钥)
ansible-playbook playbooks/site.yml
# 方式三: 仅安装首个 master
ansible-playbook playbooks/site.yml -l first-master-name
# 方式四: 添加新节点
ansible-playbook playbooks/site.yml -l new-node-name
```
### 4. 获取 kubeconfig
```bash
# 安装完成后自动保存到 ansible/kubeconfig.yaml
sed -i '' 's/127.0.0.1/k3s.yourdomain.com/g' kubeconfig.yaml
export KUBECONFIG=$(pwd)/kubeconfig.yaml
kubectl get nodes
```
## 节点变量
| 变量 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `ansible_host` | string | - | 节点 IP |
| `node_hostname` | string | - | 主机名 |
| `cluster_init` | bool | false | 首个 master 设为 true |
| `node_region` | string | - | 区域标签 (cn-sh/hk/us-west) |
| `use_mirror` | bool | false | 使用镜像加速 |
| `enable_lb` | bool | - | 启用 K3s LB |
| `netfilter_mode` | string | "" | Tailscale netfilter: off/nodivert/on |
| `node_labels` | dict | - | 自定义标签 |
| `node_taints` | list | - | 节点污点 (格式: key=value:effect) |
## 环境变量
| 变量 | 必须 | 说明 |
|------|------|------|
| `TAILSCALE_AUTH_KEY` | ✅ | Tailscale Auth Key |
| `SSH_PASSWORD` | 首次安装 | SSH 密码 |
| `SSH_PUBKEY` | - | SSH 公钥 (默认 ~/.ssh/id_rsa.pub) |
## 镜像加速
`use_mirror: true` 时自动启用:
- K3s 安装脚本: `rancher-mirror.rancher.cn`
- 常规容器镜像加速
## SSH 安全加固
首次安装时 (`--tags ssh`) 自动执行:
1. 端口改为 2103
2. 禁用密码登录
3. 启用密钥认证
4. 自动添加本地公钥
## 集群安装流程
Playbook 按以下顺序执行:
1. **初始化节点安装**: 安装 `cluster_init: true` 的第一个 master 节点
2. **动态获取 Token**: 从初始化节点读取 `/var/lib/rancher/k3s/server/node-token`
3. **Token 注入**: 将 K3S_TOKEN 和 K3S_SERVER_URL 设置为所有节点的 fact
4. **其他 Master 节点**: 使用动态获取的 Token 加入集群
5. **Agent 节点**: 使用动态获取的 Token 加入集群
这样在一次性安装整个集群时,无需手动设置 `K3S_TOKEN` 环境变量。
## 常用命令
```bash
# 测试连接
ansible all -m ping
# 仅运行特定阶段
ansible-playbook playbooks/site.yml --tags common
ansible-playbook playbooks/site.yml --tags k3s
# 指定节点
ansible-playbook playbooks/site.yml -l master1,agent1
# 调试模式
ansible-playbook playbooks/site.yml -vvv
# 检查语法
ansible-playbook playbooks/site.yml --syntax-check
```
@@ -1,4 +1,4 @@
## 安装方法
## 手动安装方法
需要在每个节点上执行以下命令 节点系统需求 debian 11+ ubuntu 20.04+
@@ -39,12 +39,7 @@ sysctl -p /etc/sysctl.d/99-tailscale.conf
采用config.yaml的方式进行配置(非环境变量) 使集群配置能够进行git版本控制
- master-init.config.yaml 是第一个master节点的配置
- master.config.yaml 是master从节点的配置 (单节点不需要)
- agent.config.yaml 是agent节点的配置 (单节点不需要)
注意!! 将tls-san改为你自己的域名 如果你的节点没有配置域名 请将其替换为节点的ip地址,
`YOU_SHOULD_MODIFY_THIS_JOIN_KEY` 替换为你申请的tailscale auth key
参考roles/k3s/templates下的配置文件模版
根据节点类型, 将上述文件中的内容写入到此处
@@ -59,7 +54,7 @@ mkdir -p /etc/rancher/k3s && vim /etc/rancher/k3s/config.yaml
```shell
curl -sfL https://get.k3s.io | \
INSTALL_K3S_VERSION=v1.33.2+k3s1 \
INSTALL_K3S_VERSION=v1.34.2+k3s1 \
sh -s - server
```
@@ -69,7 +64,7 @@ curl -sfL https://get.k3s.io | \
```shell
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | \
INSTALL_K3S_VERSION=v1.33.2+k3s1 \
INSTALL_K3S_VERSION=v1.34.2+k3s1 \
INSTALL_K3S_MIRROR=cn \
sh -s - server
```
+21
查看文件
@@ -0,0 +1,21 @@
[defaults]
inventory = inventory/hosts.yml
roles_path = roles
host_key_checking = False
retry_files_enabled = False
stdout_callback = default
callbacks_enabled = ansible.builtin.default
interpreter_python = auto_silent
deprecation_warnings = False
[callback_default]
result_format = yaml
[privilege_escalation]
become = True
become_method = sudo
become_user = root
[ssh_connection]
pipelining = True
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
+47
查看文件
@@ -0,0 +1,47 @@
# K3s Ansible 全局变量
---
# ============================================
# 敏感信息 (通过环境变量传入)
# ============================================
tailscale_auth_key: "{{ lookup('env', 'TAILSCALE_AUTH_KEY') }}"
# 高可用集群的 server_url 需要指向负载均衡器地址,单节点集群则指向自身
ha_server_url: "{{ lookup('env', 'HA_SERVER_URL') | default('', true) }}"
# ============================================
# K3s 配置
# ============================================
# K3s Server URL (优先使用 HA_SERVER_URL,否则动态使用 init 节点地址)
k3s_server_url: "{{ ha_server_url if (ha_server_url | length > 0) else '' }}"
k3s_version: "v1.34.2+k3s1"
tailscale_version: "1.96.4"
# ETCD 配置
etcd_snapshot_retention: 1
etcd_snapshot_schedule_cron: "0 0 * * *"
etcd_snapshot_compress: true
# 禁用的组件
k3s_disable_components:
- traefik
# ============================================
# 安装源配置
# ============================================
# 国内镜像源
mirror_k3s_install_url: "https://rancher-mirror.rancher.cn/k3s/k3s-install.sh"
# 官方源
global_k3s_install_url: "https://get.k3s.io"
# ============================================
# 镜像加速配置 (use_mirror: true 时启用)
# ============================================
registry_mirrors:
docker.io:
- "docker.1ms.run"
- "docker.m.daocloud.io"
ghcr.io:
- "ghcr.m.daocloud.io"
registry.k8s.io:
- "k8s.m.daocloud.io"
quay.io:
- "quay.m.daocloud.io"
+130
查看文件
@@ -0,0 +1,130 @@
# K3s 集群主机清单
---
all:
vars:
# SSH 配置
ansible_user: root
# 默认端口,首次安装时使用22,后续会被动态覆盖
ansible_port: 22
ansible_password: "{{ lookup('env', 'SSH_PASSWORD') | default(omit, true) }}"
# SSH 安全配置
ssh_new_port: 2103
ssh_pubkey: "{{ lookup('env', 'SSH_PUBKEY') | default(lookup('file', '~/.ssh/id_rsa.pub'), true) }}"
children:
# Master 节点 (Server)
masters:
hosts:
tca:
ansible_host: tca.node.dev.cm
node_hostname: tca
cluster_init: true
node_region: cn-sh
use_mirror: true
node_taints:
- "node-role.kubernetes.io/control-plane:NoSchedule"
tcb:
ansible_host: tcb.node.dev.cm
node_hostname: tcb
node_region: cn-sh
use_mirror: true
node_taints:
- "node-role.kubernetes.io/control-plane:NoSchedule"
tcc:
ansible_host: tcc.node.dev.cm
node_hostname: tcc
node_region: cn-sh
use_mirror: true
node_taints:
- "node-role.kubernetes.io/control-plane:NoSchedule"
# Agent 节点 (Worker)
agents:
hosts:
tce:
ansible_host: tce.node.dev.cm
node_hostname: tce
node_region: cn-sh
use_mirror: true
tcd:
ansible_host: tcd.node.dev.cm
node_hostname: tcd
node_region: cn-sh
use_mirror: true
tchk:
ansible_host: tchk.node.dev.cm
node_hostname: tchk
node_region: cn-hk
tthk:
ansible_host: tthk.node.dev.cm
node_hostname: tthk
node_region: cn-hk
enable_lb: true
alihk:
ansible_host: alihk.node.dev.cm
node_hostname: alihk
node_region: cn-hk
enable_lb: true
netfilter_mode: nodivert
alihka:
ansible_host: alihka.node.dev.cm
node_hostname: alihka
node_region: cn-hk
netfilter_mode: nodivert
hwhk:
ansible_host: hwhk.node.dev.cm
node_hostname: hwhk
node_region: cn-hk
enable_lb: true
netfilter_mode: nodivert
hwsg:
ansible_host: hwsg.node.dev.cm
node_hostname: hwsg
node_region: sg-sg
enable_lb: true
netfilter_mode: nodivert
hwa:
ansible_host: hwa.node.dev.cm
node_hostname: hwa
node_region: cn-sh
use_mirror: true
netfilter_mode: nodivert
clawhk:
ansible_host: clawhk.node.dev.cm
node_hostname: clawhk
node_region: cn-hk
clawjp:
ansible_host: clawjp.node.dev.cm
node_hostname: clawjp
node_region: jp-tyo
orajpa:
ansible_host: orajpa.node.dev.cm
node_hostname: orajpa
node_region: jp-tyo
orakra:
ansible_host: orakra.node.dev.cm
node_hostname: orakra
node_region: kr-sel
orasga:
ansible_host: orasga.node.dev.cm
node_hostname: orasga
node_region: sg-sg
# 以下为内网节点 需要手动先配置好vpn才能访问
homea:
ansible_host: homea
node_hostname: homea
node_region: cn-sh
use_mirror: true
homeb:
ansible_host: homeb
node_hostname: homeb
node_region: cn-sh
use_mirror: true
# 节点分组
k3s_cluster:
children:
masters:
agents:
+203
查看文件
@@ -0,0 +1,203 @@
# K3s 集群安装 Playbook
---
# ============================================
# 阶段 0: 提前检测 检测环境变量和 SSH 端口
# ============================================
- name: Pre-check Environment and SSH Port
hosts: k3s_cluster
gather_facts: false
tags: [always]
tasks:
# 环境验证 (run_once 确保只执行一次)
- name: Check TAILSCALE_AUTH_KEY
ansible.builtin.fail:
msg: "请设置: export TAILSCALE_AUTH_KEY='tskey-auth-xxx'"
when: lookup('env', 'TAILSCALE_AUTH_KEY') | length == 0
run_once: true
delegate_to: localhost
- name: Check SSH credentials
ansible.builtin.debug:
msg: |
{% if lookup('env', 'SSH_PASSWORD') | length > 0 %}
✓ 优先使用密码登录
{% else %}
✓ 使用密钥登录
{% endif %}
run_once: true
delegate_to: localhost
# SSH 端口探测
- name: Try new SSH port ({{ ssh_new_port }})
ansible.builtin.wait_for:
host: "{{ ansible_host }}"
port: "{{ ssh_new_port }}"
timeout: 3
delegate_to: localhost
become: false
register: new_port_check
ignore_errors: true
- name: Set SSH port based on availability
ansible.builtin.set_fact:
ansible_port: "{{ ssh_new_port if new_port_check is succeeded else 22 }}"
- name: Display detected SSH port
ansible.builtin.debug:
msg: "{{ inventory_hostname }}: 使用端口 {{ ansible_port }}"
when: ansible_verbosity > 0
# ============================================
# 阶段 1: SSH 安全加固 (可选,首次安装时使用)
# ============================================
- name: SSH Security Hardening
hosts: k3s_cluster
gather_facts: false
tags: [ssh, never]
roles:
- ssh
# ============================================
# 阶段 2: 基础配置
# ============================================
- name: Common Setup
hosts: k3s_cluster
gather_facts: true
tags: [common]
roles:
- common
# ============================================
# 阶段 3: 安装 K3s (按顺序: init -> masters -> agents)
# ============================================
- name: Install K3s on init node
hosts: masters
gather_facts: true
serial: 1
tags: [k3s]
roles:
- role: k3s
when: cluster_init | default(false)
- name: Fetch K3S_TOKEN & K3S_SERVER_URL from init node
hosts: k3s_cluster
gather_facts: false
run_once: true
tags: [k3s]
tasks:
- name: Find init node
ansible.builtin.set_fact:
init_node: "{{ item }}"
loop: "{{ groups['masters'] }}"
when: hostvars[item].cluster_init | default(false)
- name: Detect init node SSH port
ansible.builtin.wait_for:
host: "{{ hostvars[init_node].ansible_host }}"
port: "{{ ssh_new_port }}"
timeout: 3
delegate_to: localhost
become: false
register: init_node_port_check
ignore_errors: true
- name: Set init node SSH port
ansible.builtin.set_fact:
init_node_port: "{{ ssh_new_port if init_node_port_check is succeeded else 22 }}"
- name: Read K3S_TOKEN from init node
ansible.builtin.slurp:
src: /var/lib/rancher/k3s/server/node-token
register: k3s_token_content
delegate_to: "{{ init_node }}"
vars:
ansible_port: "{{ hostvars[inventory_hostname].init_node_port }}"
- name: Determine K3S_SERVER_URL
ansible.builtin.set_fact:
# 优先使用 HA_SERVER_URL 环境变量,否则使用 init 节点地址
k3s_server_url: "{{ ha_server_url if (ha_server_url | length > 0) else 'https://' + hostvars[init_node].ansible_host + ':6443' }}"
- name: Set K3S_TOKEN and K3S_SERVER_URL for target hosts
ansible.builtin.set_fact:
k3s_token: "{{ k3s_token_content.content | b64decode | trim }}"
k3s_server_url: "{{ k3s_server_url }}"
delegate_to: "{{ item }}"
delegate_facts: true
loop: "{{ ansible_play_hosts }}"
- name: Install K3s on other masters
hosts: masters
gather_facts: true
serial: 1
tags: [k3s]
roles:
- role: k3s
when: not (cluster_init | default(false))
- name: Install K3s on agents
hosts: agents
gather_facts: true
tags: [k3s]
roles:
- k3s
# ============================================
# 阶段 4: 显示集群状态
# ============================================
- name: Show cluster status
hosts: masters
gather_facts: false
tags: [status]
run_once: true
tasks:
- name: Get nodes
ansible.builtin.command: kubectl get nodes -o wide
environment:
KUBECONFIG: /etc/rancher/k3s/k3s.yaml
register: nodes
changed_when: false
when: cluster_init | default(false)
- name: Display nodes
ansible.builtin.debug:
msg: |
══════════════════════════════════════════════════════════════
K3s 集群节点:
{{ nodes.stdout }}
══════════════════════════════════════════════════════════════
when: cluster_init | default(false)
# ============================================
# K3s 卸载 (需显式指定: --tags uninstall)
# ============================================
- name: Uninstall K3s agents
hosts: agents
gather_facts: false
tags: [uninstall, never]
tasks:
- name: Check agent uninstall script
ansible.builtin.stat:
path: /usr/local/bin/k3s-agent-uninstall.sh
register: agent_uninstall_script
- name: Run k3s-agent-uninstall.sh
ansible.builtin.command: /usr/local/bin/k3s-agent-uninstall.sh
when: agent_uninstall_script.stat.exists
changed_when: true
- name: Uninstall K3s masters
hosts: masters
gather_facts: false
serial: 1
tags: [uninstall, never]
tasks:
- name: Check server uninstall script
ansible.builtin.stat:
path: /usr/local/bin/k3s-uninstall.sh
register: server_uninstall_script
- name: Run k3s-uninstall.sh
ansible.builtin.command: /usr/local/bin/k3s-uninstall.sh
when: server_uninstall_script.stat.exists
changed_when: true
+4
查看文件
@@ -0,0 +1,4 @@
---
- name: Apply sysctl
ansible.builtin.command: sysctl --system
changed_when: true
+84
查看文件
@@ -0,0 +1,84 @@
# 基础配置 Role
# 功能: hostname、sysctl、Tailscale 安装
---
- name: Set hostname
ansible.builtin.hostname:
name: "{{ node_hostname }}"
when: node_hostname is defined
- name: Update /etc/hosts
ansible.builtin.lineinfile:
path: /etc/hosts
regexp: '^127\.0\.1\.1'
line: "127.0.1.1 {{ node_hostname }}"
when: node_hostname is defined
- name: Configure sysctl for IP forwarding
ansible.builtin.copy:
dest: /etc/sysctl.d/99-k3s.conf
content: |
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
mode: "0644"
notify: Apply sysctl
- name: Install dependencies
ansible.builtin.apt:
name:
- curl
- wget
- ca-certificates
state: present
update_cache: true
- name: Check if Tailscale is installed
ansible.builtin.command: which tailscale
register: common_tailscale_check
failed_when: false
changed_when: false
- name: Check current Tailscale version
ansible.builtin.shell: tailscale version | head -1
register: common_tailscale_version
failed_when: false
changed_when: false
when: common_tailscale_check.rc == 0
- name: Set Tailscale install flag
ansible.builtin.set_fact:
tailscale_needs_install: "{{
common_tailscale_check.rc != 0 or
(common_tailscale_version.stdout | default('') is not search(tailscale_version))
}}"
- name: Download Tailscale install script
ansible.builtin.get_url:
url: https://tailscale.com/install.sh
dest: /tmp/tailscale-install.sh
mode: "0755"
when: common_tailscale_check.rc != 0
- name: Install Tailscale via install script
ansible.builtin.command: /tmp/tailscale-install.sh
when: common_tailscale_check.rc != 0
changed_when: true
- name: Install specific Tailscale version
ansible.builtin.apt:
name:
- "tailscale={{ tailscale_version }}"
- "tailscaled={{ tailscale_version }}"
state: present
allow_downgrade: true
when: tailscale_needs_install
- name: Remove Tailscale install script
ansible.builtin.file:
path: /tmp/tailscale-install.sh
state: absent
- name: Enable Tailscale service
ansible.builtin.systemd:
name: tailscaled
enabled: true
state: started
+131
查看文件
@@ -0,0 +1,131 @@
# K3s 安装 Role (统一 Server 和 Agent)
---
- name: Validate TAILSCALE_AUTH_KEY
ansible.builtin.fail:
msg: "请设置环境变量: export TAILSCALE_AUTH_KEY='tskey-auth-xxx'"
when: (tailscale_auth_key | default('')) | length == 0
- name: Create K3s config directory
ansible.builtin.file:
path: /etc/rancher/k3s
state: directory
mode: "0755"
# 检查安装状态
- name: Check if K3s is installed
ansible.builtin.stat:
path: /usr/local/bin/k3s
register: k3s_binary
# 检查当前K3s版本
- name: Check current K3s version
ansible.builtin.command:
cmd: /usr/local/bin/k3s --version
register: k3s_current_version
failed_when: false
changed_when: false
when: k3s_binary.stat.exists
# 部署配置文件(注册变更状态)
- name: Deploy K3s server config
ansible.builtin.template:
src: k3s-server.yaml.j2
dest: /etc/rancher/k3s/config.yaml
mode: "0600"
when: "'masters' in group_names"
register: k3s_server_config
- name: Deploy K3s agent config
ansible.builtin.template:
src: k3s-agent.yaml.j2
dest: /etc/rancher/k3s/config.yaml
mode: "0600"
when: "'agents' in group_names"
register: k3s_agent_config
- name: Deploy registries.yaml
ansible.builtin.template:
src: registries.yaml.j2
dest: /etc/rancher/k3s/registries.yaml
mode: "0644"
when: use_mirror | default(false)
# 判断是否需要安装/重启
# 使用 -e force_reinstall=true 可强制重新安装
- name: Set K3s installation flag
ansible.builtin.set_fact:
k3s_needs_install: "{{
not k3s_binary.stat.exists or
(force_reinstall | default(false) | bool) or
(k3s_server_config.changed | default(false)) or
(k3s_agent_config.changed | default(false)) or
(k3s_binary.stat.exists and k3s_current_version.stdout is defined and k3s_version not in k3s_current_version.stdout)
}}"
# 设置安装变量
- name: Set K3s install variables
ansible.builtin.set_fact:
k3s_install_url: "{{ mirror_k3s_install_url if (use_mirror | default(false)) else global_k3s_install_url }}"
k3s_install_mirror: "{{ 'INSTALL_K3S_MIRROR=cn' if (use_mirror | default(false)) else '' }}"
# 下载安装脚本
- name: Download K3s install script
ansible.builtin.get_url:
url: "{{ k3s_install_url }}"
dest: /tmp/k3s-install.sh
mode: "0755"
when: k3s_needs_install
# 安装 K3s
- name: Install K3s server
ansible.builtin.command:
cmd: /tmp/k3s-install.sh server
environment:
INSTALL_K3S_VERSION: "{{ k3s_version }}"
INSTALL_K3S_MIRROR: "{{ 'cn' if (use_mirror | default(false)) else '' }}"
when:
- "'masters' in group_names"
- k3s_needs_install
changed_when: true
- name: Install K3s agent
ansible.builtin.command:
cmd: /tmp/k3s-install.sh agent
environment:
INSTALL_K3S_VERSION: "{{ k3s_version }}"
INSTALL_K3S_MIRROR: "{{ 'cn' if (use_mirror | default(false)) else '' }}"
when:
- "'agents' in group_names"
- k3s_needs_install
changed_when: true
# 清理安装脚本
- name: Remove install script
ansible.builtin.file:
path: /tmp/k3s-install.sh
state: absent
# 等待 K3s 就绪 (仅 Server)
- name: Wait for K3s server ready
ansible.builtin.wait_for:
path: /var/lib/rancher/k3s/server/node-token
timeout: 300
when: "'masters' in group_names"
# 保存 kubeconfig (仅 cluster-init)
- name: Fetch kubeconfig
ansible.builtin.fetch:
src: /etc/rancher/k3s/k3s.yaml
dest: "{{ playbook_dir }}/../kubeconfig.yaml"
flat: true
when: cluster_init | default(false)
- name: Update kubeconfig server address
ansible.builtin.replace:
path: "{{ playbook_dir }}/../kubeconfig.yaml"
regexp: 'server: https://127\.0\.0\.1:6443'
replace: "server: {{ k3s_server_url }}"
delegate_to: localhost
become: false
when: cluster_init | default(false)
@@ -0,0 +1,36 @@
# K3s Agent 配置模板
---
server: "{{ k3s_server_url }}"
token: "{{ k3s_token }}"
# Tailscale VPN
vpn-auth: "name=tailscale,joinKey={{ tailscale_auth_key }}{% if netfilter_mode | default('') %},extraArgs=--netfilter-mode={{ netfilter_mode }}{% endif %}"
# 节点标签
node-label:
{% if node_region is defined %}
- "topology.kubernetes.io/region={{ node_region }}"
{% endif %}
{% if enable_lb is defined %}
- "svccontroller.k3s.cattle.io/enablelb={{ enable_lb | string | lower }}"
{% endif %}
{% if node_labels is defined %}
{% for key, value in node_labels.items() %}
- "{{ key }}={{ value }}"
{% endfor %}
{% endif %}
# 节点污点
{% if node_taints is defined %}
node-taint:
{% for taint in node_taints %}
- "{{ taint }}"
{% endfor %}
{% endif %}
# Kubelet 资源预留
{% if kubelet_reserved is defined %}
kubelet-arg:
- "kube-reserved={{ kubelet_reserved }}"
{% endif %}
@@ -0,0 +1,56 @@
# K3s Server 统一配置模板 (master-init 和 master-join)
---
{% if cluster_init | default(false) %}
# 首个节点初始化集群
cluster-init: true
{% else %}
# 加入已有集群
server: "{{ k3s_server_url }}"
token: "{{ k3s_token }}"
{% endif %}
# TLS SAN: 包含 HA 地址 + 所有 master 节点地址
tls-san:
{% if ha_server_url | default('') | length > 0 %}
- "{{ ha_server_url | regex_replace('^https?://([^:]+)(:[0-9]+)?$', '\\1') }}"
{% endif %}
{% for host in groups['masters'] %}
- "{{ hostvars[host].ansible_host }}"
{% endfor %}
# ETCD 快照配置
etcd-snapshot-retention: {{ etcd_snapshot_retention }}
etcd-snapshot-schedule-cron: "{{ etcd_snapshot_schedule_cron }}"
etcd-snapshot-compress: {{ etcd_snapshot_compress | lower }}
# Tailscale VPN
vpn-auth: "name=tailscale,joinKey={{ tailscale_auth_key }}{% if netfilter_mode | default('') %},extraArgs=--netfilter-mode={{ netfilter_mode }}{% endif %}"
# 禁用组件
disable:
{% for component in k3s_disable_components %}
- {{ component }}
{% endfor %}
# 节点标签
node-label:
{% if node_region is defined %}
- "topology.kubernetes.io/region={{ node_region }}"
{% endif %}
{% if enable_lb is defined %}
- "svccontroller.k3s.cattle.io/enablelb={{ enable_lb | string | lower }}"
{% endif %}
{% if node_labels is defined %}
{% for key, value in node_labels.items() %}
- "{{ key }}={{ value }}"
{% endfor %}
{% endif %}
# 节点污点
{% if node_taints is defined %}
node-taint:
{% for taint in node_taints %}
- "{{ taint }}"
{% endfor %}
{% endif %}
@@ -0,0 +1,11 @@
# 镜像加速配置
---
mirrors:
{% for registry, endpoints in registry_mirrors.items() %}
"{{ registry }}":
endpoint:
{% for endpoint in endpoints %}
- "https://{{ endpoint }}"
{% endfor %}
{% endfor %}
+21
查看文件
@@ -0,0 +1,21 @@
---
- name: Restart sshd
ansible.builtin.systemd:
name: sshd
state: restarted
listen: Restart sshd
- name: Update ansible port
ansible.builtin.set_fact:
ansible_port: "{{ ssh_new_port }}"
listen: Update ansible port
- name: Wait for new SSH port
ansible.builtin.wait_for:
port: "{{ ssh_new_port }}"
host: "{{ ansible_host }}"
delay: 5
timeout: 60
delegate_to: localhost
become: false
listen: Wait for new SSH port
+33
查看文件
@@ -0,0 +1,33 @@
# SSH 安全加固 Role
# 功能: 修改端口、配置密钥认证、禁用密码登录
---
- name: Ensure .ssh directory exists
ansible.builtin.file:
path: /root/.ssh
state: directory
mode: "0700"
- name: Add SSH public key
ansible.builtin.authorized_key:
user: root
key: "{{ ssh_pubkey }}"
state: present
- name: Backup original sshd_config
ansible.builtin.copy:
src: /etc/ssh/sshd_config
dest: /etc/ssh/sshd_config.bak
remote_src: true
force: false
mode: "0600"
- name: Deploy secure sshd_config
ansible.builtin.template:
src: sshd_config.j2
dest: /etc/ssh/sshd_config
mode: "0600"
validate: "/usr/sbin/sshd -t -f %s"
notify:
- Restart sshd
- Update ansible port
- Wait for new SSH port
@@ -0,0 +1,12 @@
# SSH 配置模板
Port {{ ssh_new_port }}
PermitRootLogin prohibit-password
PasswordAuthentication no
PubkeyAuthentication yes
ChallengeResponseAuthentication no
UsePAM yes
X11Forwarding no
PrintMotd no
AcceptEnv LANG LC_*
Subsystem sftp /usr/lib/openssh/sftp-server
-70
查看文件
@@ -1,70 +0,0 @@
### apps
应用部署方法
```shell
kubectl apply -f apps/xxx -R
```
举例:
```shell
kubectl apply -f apps/infra/data/redis -R
```
你可以一次性将所有的应用部署到k8s集群中 但是此处建议分开部署 每个文件夹单独执行 以保证不会出现错误与性能问题
注意!! 在部署前你需要替换yaml中的YOU_SHOULD_MODIFY_THIS_ 开头的字段 替换为自己的值 这些值的来源部分是自己生成的、部分是需要你自己去申请的
比如说你需要去华为云申请一个access key id和secret key 还有一个bucket name 这些值需要你自己去申请
### 应用说明
./kube文件夹下的请全部执行 此文件架内部为集群优化相关内容 例如dns延迟优化
(patch-affinity.yaml 按需 仅在你想让k3s自带的system服务使用特定节点时使用 比如保留核心服务停留在高可用节点上)
- infra-net: 网络相关的应用
- nginx: 负载均衡服务 替换集群默认的ingress(traefik)
- crowdsec: 安全防护服务
- tailscale: 集群内网加速服务 如果对集群内网加速没有需求 可以不安装
- infra-data: 数据存储相关的应用
- redis: redis服务
- postgresql-ha: postgresql服务
- cloudnative: postgresql服务 操作符版本 推荐
- infra-devops: devops相关的应用
- gitea: git托管服务
- cert-manager: 证书管理服务
- reflector: 密钥同步服务
- velero: 备份服务
- infra-monitor: 监控相关的应用
- prometheus: 监控服务
- loki: 日志服务
- apps: 其他应用 个人应用部分
- whoami: 测试服务
### 调试集群内服务方法 运行此命令
```shell
kubectl run -i --tty --rm --restart=Never \
--overrides='{"apiVersion": "v1", "spec": {"nodeSelector": {"kubernetes.io/hostname": "homea"}}}' \
--image=nicolaka/netshoot:latest \
debug -- sh
```
### 密钥相关
可以将helm部署中使用到的密钥放到k8s的secret中
然后使用reflector将secret中的密钥同步到其他namespace中
```shell
kubectl -n infra-devops create secret generic s3-devcm-hw \
--from-literal=ACCESS_KEY_ID=xxxxx \
--from-literal=ACCESS_SECRET_KEY=xxxxx
kubectl -n infra-devops annotate secret s3-devcm-hw \
reflector.v1.k8s.emberstack.com/reflection-allowed=true \
reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces=infra-data \
reflector.v1.k8s.emberstack.com/reflection-auto-enabled=true \
reflector.v1.k8s.emberstack.com/reflection-auto-namespace=infra-data --overwrite
```
@@ -1,51 +0,0 @@
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cnpg17-cluster-hk
namespace: infra-data
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- preference:
matchExpressions:
- key: topology.kubernetes.io/region
operator: In
values:
- cn-hk
weight: 1
instances: 1
imageName: ghcr.io/cloudnative-pg/postgresql:17.4
enableSuperuserAccess: true
storage:
size: 10Gi
postgresql:
parameters:
archive_timeout: 30min
backup:
retentionPolicy: "7d"
barmanObjectStore:
destinationPath: s3://devcm/cnpg/
endpointURL: https://obs.cn-east-3.myhuaweicloud.com
s3Credentials:
accessKeyId:
name: s3-devcm-hw
key: ACCESS_KEY_ID
secretAccessKey:
name: s3-devcm-hw
key: ACCESS_SECRET_KEY
wal:
compression: gzip
---
apiVersion: postgresql.cnpg.io/v1
kind: ScheduledBackup
metadata:
name: cnpg17-cluster-hk-backups
namespace: infra-data
spec:
schedule: "0 0 0 * * *"
immediate: true
backupOwnerReference: self
cluster:
name: cnpg17-cluster-hk
@@ -1,51 +0,0 @@
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cnpg17-cluster-sh
namespace: infra-data
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- preference:
matchExpressions:
- key: topology.kubernetes.io/region
operator: In
values:
- cn-sh
weight: 1
instances: 1
imageName: ghcr.io/cloudnative-pg/postgresql:17.4
enableSuperuserAccess: true
storage:
size: 10Gi
postgresql:
parameters:
archive_timeout: 30min
backup:
retentionPolicy: "7d"
barmanObjectStore:
destinationPath: s3://devcm/cnpg/
endpointURL: https://obs.cn-east-3.myhuaweicloud.com
s3Credentials:
accessKeyId:
name: s3-devcm-hw
key: ACCESS_KEY_ID
secretAccessKey:
name: s3-devcm-hw
key: ACCESS_SECRET_KEY
wal:
compression: gzip
---
apiVersion: postgresql.cnpg.io/v1
kind: ScheduledBackup
metadata:
name: cnpg17-cluster-sh-backups
namespace: infra-data
spec:
schedule: "0 0 0 * * *"
immediate: true
backupOwnerReference: self
cluster:
name: cnpg17-cluster-sh
@@ -1,27 +0,0 @@
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
name: cloudnative-pg
namespace: infra-data
spec:
repo: https://cloudnative-pg.github.io/charts
chart: cloudnative-pg
targetNamespace: infra-data
version: 0.25.0
valuesContent: |-
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/region
operator: In
values:
- "cn-sh"
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists"
effect: "NoSchedule"
image:
tag: "1.25.3"
-28
查看文件
@@ -1,28 +0,0 @@
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
name: redis-cluster-sh
namespace: infra-data
spec:
chart: oci://registry-1.docker.io/bitnamicharts/redis
targetNamespace: infra-data
version: 20.7.0
valuesContent: |-
global:
redis:
password: ribiPwYQNU6GWxCYR0Nj
master:
nodeAffinityPreset:
type: soft
key: topology.kubernetes.io/region
values:
- cn-sh
replica:
replicaCount: 0
nodeAffinityPreset:
type: soft
key: topology.kubernetes.io/region
values:
- cn-sh
@@ -1,35 +0,0 @@
# 安装后需要将clusterIssuer的cnameStrategy策略设置为Follow
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
name: cert-manager-webhook-dnspod
namespace: infra-devops
spec:
chart: oci://registry-1.docker.io/imroc/cert-manager-webhook-dnspod
targetNamespace: infra-devops
version: 1.4.5
valuesContent: |-
namespace: infra-devops
certManager:
namespace: infra-devops
groupName: cert.dev.cm
clusterIssuer:
# 此处需在部署后修改clusterIssuer 添加在dns01下
# cnameStrategy: Follow
staging: false
email: admin@dev.cm
secretId: AKIDzmKdvDSfonogKip55pIVR6h7ScjaBWcg
secretKey: zudDdtytkPr8HI9oKeniSxIRPCmCe0CD
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/region
operator: In
values:
- "cn-sh"
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists"
effect: "NoSchedule"
@@ -1,62 +0,0 @@
# 需要提前安装crds
# kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.18.2/cert-manager.crds.yaml
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
name: cert-manager
namespace: infra-devops
spec:
repo: https://charts.jetstack.io
chart: cert-manager
targetNamespace: infra-devops
version: v1.19.2
valuesContent: |-
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/region
operator: In
values:
- "cn-sh"
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists"
effect: "NoSchedule"
webhook:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/region
operator: In
values:
- "cn-sh"
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists"
effect: "NoSchedule"
cainjector:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/region
operator: In
values:
- "cn-sh"
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists"
effect: "NoSchedule"
# 在删除证书时同时删除secret
enableCertificateOwnerRef: true
prometheus:
enabled: true
servicemonitor:
enabled: true
interval: 300s
prometheusInstance: kube-prometheus
@@ -1,28 +0,0 @@
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
name: reflector
namespace: infra-devops
spec:
repo: https://emberstack.github.io/helm-charts
chart: reflector
targetNamespace: infra-devops
version: 9.1.45
valuesContent: |-
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/region
operator: In
values:
- "cn-sh"
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- tce
-65
查看文件
@@ -1,65 +0,0 @@
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
name: velero
namespace: infra-devops
spec:
repo: https://vmware-tanzu.github.io/helm-charts
chart: velero
targetNamespace: infra-devops
version: 11.3.2
valuesContent: |-
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/region
operator: In
values:
- "cn-sh"
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- homea
deployNodeAgent: true
snapshotsEnabled: false
configuration:
backupSyncPeriod: 1h0m0s
defaultRepoMaintainFrequency: 3h0m0s
repositoryMaintenanceJob:
repositoryConfigData:
global:
keepLatestMaintenanceJobs: 1
backupStorageLocation:
- name: devcm-hw
default: true
provider: aws
bucket: devcm
prefix: velero
config:
region: cn-east-3
s3ForcePathStyle: false
s3Url: https://obs.cn-east-3.myhuaweicloud.com
checksumAlgorithm: ""
credentials:
useSecret: true
secretContents:
cloud: |
[default]
aws_access_key_id = A9RI5BC15F3L9EI8T51T
aws_secret_access_key = ky1n3OlNNu7wjgctVjCqb03HWxjZucRGhvcEBp51
initContainers:
- name: velero-plugin-for-aws
image: velero/velero-plugin-for-aws:v1.13.0
volumeMounts:
- mountPath: /target
name: plugins
nodeAgent:
nodeSelector:
backup.velero.io/enable: "true"
-25
查看文件
@@ -1,25 +0,0 @@
apiVersion: fluxcd.controlplane.io/v1
kind: FluxInstance
metadata:
name: flux
namespace: infra-gitops
spec:
distribution:
version: "2.x"
registry: "ghcr.io/fluxcd"
artifact: "oci://ghcr.io/controlplaneio-fluxcd/flux-operator-manifests"
components:
- source-controller
- source-watcher
- kustomize-controller
- helm-controller
- notification-controller
cluster:
type: kubernetes
size: small
multitenant: false
networkPolicy: true
domain: "cluster.local"
storage:
class: "local-path"
size: "10Gi"
@@ -1,21 +0,0 @@
#!/bin/bash
# 更新 ConfigMap 中的静态文件
cat > configmap-static.yaml << 'EOF'
apiVersion: v1
kind: ConfigMap
metadata:
name: static
namespace: infra-net
data:
EOF
# 直接遍历 static 目录并追加到文件
for file in static/*; do
filename=$(basename "$file")
echo " $filename: |" >> configmap-static.yaml
sed 's/^/ /' "$file" >> configmap-static.yaml
echo "" >> configmap-static.yaml
done
echo "ConfigMap updated successfully!"
-302
查看文件
@@ -1,302 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta content="width=device-width,initial-scale=1,user-scalable=no,viewport-fit=cover" name="viewport">
<title>出于安全原因 请完成验证</title>
<script src="{{captcha_frontend_js}}" async defer></script>
<style>
* {
-webkit-box-sizing: border-box;
box-sizing: border-box
}
body {
padding: 0;
margin: 0
}
#error {
position: relative;
height: 100vh
}
#error .error {
position: absolute;
left: 50%;
top: 50%;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%)
}
#error .error-bg {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
overflow: hidden
}
#error .error-bg > div {
position: absolute;
top: 0;
bottom: 0;
width: 1px;
background-color: #eee
}
#error .error-bg > div:nth-child(1) {
left: 20%
}
#error .error-bg > div:nth-child(2) {
left: 40%
}
#error .error-bg > div:nth-child(3) {
left: 60%
}
#error .error-bg > div:nth-child(4) {
left: 80%
}
#error .error-bg > div:after {
content: '';
position: absolute;
top: 0;
left: -.5px;
-webkit-transform: translateY(-160px);
-ms-transform: translateY(-160px);
transform: translateY(-160px);
height: 160px;
width: 2px;
background-color: #1cfafe
}
@-webkit-keyframes drop {
90% {
height: 20px
}
100% {
height: 160px;
-webkit-transform: translateY(calc(100vh + 160px));
transform: translateY(calc(100vh + 160px))
}
}
@keyframes drop {
90% {
height: 20px
}
100% {
height: 160px;
-webkit-transform: translateY(calc(100vh + 160px));
transform: translateY(calc(100vh + 160px))
}
}
#error .error-bg > div:nth-child(1):after {
-webkit-animation: drop 3s infinite linear;
animation: drop 3s infinite linear;
-webkit-animation-delay: .2s;
animation-delay: .2s
}
#error .error-bg > div:nth-child(2):after {
-webkit-animation: drop 2s infinite linear;
animation: drop 2s infinite linear;
-webkit-animation-delay: .7s;
animation-delay: .7s
}
#error .error-bg > div:nth-child(3):after {
-webkit-animation: drop 3s infinite linear;
animation: drop 3s infinite linear;
-webkit-animation-delay: .9s;
animation-delay: .9s
}
#error .error-bg > div:nth-child(4):after {
-webkit-animation: drop 2s infinite linear;
animation: drop 2s infinite linear;
-webkit-animation-delay: 1.2s;
animation-delay: 1.2s
}
.error {
max-width: 520px;
width: 100%;
padding: 20px;
text-align: center
}
.error .error-code {
height: 210px;
line-height: 210px
}
.error .error-code h1 {
font-family: oswald, sans-serif;
font-size: 80px;
font-weight: 700;
margin: 0;
text-shadow: 4px 4px 0 #1cfafe
}
.error h2 {
font-family: oswald, sans-serif;
font-size: 42px;
font-weight: 700;
margin: 0;
text-transform: uppercase;
letter-spacing: 1.6px
}
.error p {
font-family: lato, sans-serif;
color: #000;
font-weight: 400;
margin-top: 20px;
margin-bottom: 25px
}
.error a {
font-family: lato, sans-serif;
padding: 10px 30px;
display: inline-block;
color: #000;
font-weight: 400;
text-transform: uppercase;
-webkit-box-shadow: 0 0 0 2px #000, 2px 2px 0 2px #1cfafe;
box-shadow: 0 0 0 2px #000, 2px 2px 0 2px #1cfafe;
text-decoration: none;
-webkit-transition: .2s all;
transition: .2s all
}
.error a:not(:first-of-type) {
margin-left: 20px
}
.error a:hover {
background-color: #1cfafe;
-webkit-box-shadow: 0 0 0 0 #000, 0 0 0 2px #1cfafe;
box-shadow: 0 0 0 0 #000, 0 0 0 2px #1cfafe
}
.error-social > a {
width: 40px;
height: 40px;
line-height: 40px;
padding: 0;
margin: 0 5px
}
.error-social > a:hover {
background-color: #1cfafe;
-webkit-box-shadow: 0 0 0 0 #000, 0 0 0 2px #1cfafe;
box-shadow: 0 0 0 0 #000, 0 0 0 2px #1cfafe
}
#captcha-form {
position: relative;
width: 300px;
height: 65px;
overflow: hidden;
margin: 0 auto 30px;
background-color: #fff;
-webkit-box-shadow: 0 0 0 2px #000, 2px 2px 0 2px #1cfafe;
box-shadow: 0 0 0 2px #000, 2px 2px 0 2px #1cfafe;
}
.loading {
position: absolute;
top: 0;
left: 0;
z-index: 1;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 65px;
gap: 10px;
}
.loading:has(+ *) {
display: none;
}
.loading::before {
content: "";
width: 20px;
height: 20px;
border: 2px solid #000;
border-right-color: #1cfafe;
border-radius: 50%;
animation: spin 1s linear infinite;
}
#captcha {
position: relative;
z-index: 2;
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@media only screen and (max-width: 480px) {
.error .error-code {
height: 122px;
line-height: 122px
}
.error .error-code h1 {
font-size: 60px
}
.error h2 {
font-size: 26px
}
}
</style>
</head>
<body>
<div id="error">
<div class="error-bg">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class="error">
<div class="error-code">
<h1>FillCode</h1>
</div>
<h2>请完成验证</h2>
<p>请完成下面验证, 页面将会自动跳转到访问页面。</p>
<form id="captcha-form" method="POST">
<div id="captcha" class="{{captcha_frontend_key}}" data-sitekey="{{captcha_site_key}}"
data-callback="captchaCallback" data-size="flexible"></div>
<div class="loading">验证码加载中, 请稍等...</div>
</form>
<a href="mailto:admin@dev.cm">联系我们</a>
</div>
</div>
<script>
function captchaCallback() {
setTimeout(() => document.querySelector('#captcha-form').submit(), 500)
}
</script>
</body>
</html>
-59
查看文件
@@ -1,59 +0,0 @@
'use strict'
// 配置
const pwaCdnConfig = {
cdnUrl: 'https://cdn.fillcode.com/',
serviceWorkerUrl: '/__static/sw-cdn.js',
staticRegex: /\.(js|css|png|jpg|jpeg|gif|svg|webp|woff|woff2|ttf|ico)$/,
debug: false,
}
/**
* PWA 初始化函数
*/
async function initializePWA() {
// 检查支持
if (!('serviceWorker' in navigator)) return console.log('PWA-CDN: Service Worker not supported')
let registration;
try {
// 注册Service Worker - 使用相对路径
registration = await navigator.serviceWorker.register(pwaCdnConfig.serviceWorkerUrl, {scope: '/'})
console.log('PWA-CDN: Service Worker registered')
} catch (error) {
console.error('PWA-CDN: Failed to register Service Worker:', error)
}
// 发送初始配置
const sendConfig = () => {
registration.active.postMessage({type: 'CONFIG', config: pwaCdnConfig})
}
// 如果注册失败,直接返回错误
if(!registration) return console.error('PWA-CDN: Service Worker registration failed, cannot send config')
// 更新配置函数
window.updatePWACDNConfig = (newConfig) => {
Object.assign(pwaCdnConfig, newConfig)
sendConfig()
}
// 等待Service Worker激活后发送配置
if (registration.active) sendConfig()
// 监听Service Worker更新事件
registration.addEventListener('updatefound', () => {
const newWorker = registration.installing
newWorker.addEventListener('statechange', () => {
if (newWorker.state === 'activated') sendConfig()
})
})
}
/**
* 启动 PWA-CDN
* */
initializePWA().catch(console.error)
-88
查看文件
@@ -1,88 +0,0 @@
'use strict'
// Service Worker 配置 - 默认值
let config = {
cdnUrl: 'https://cdn.fillcode.com/',
serviceWorkerUrl: '/__static/sw-cdn.js',
staticRegex: /(.*\.(css|js|png|jpg|jpeg|gif|svg|webp|ico|woff|woff2|ttf|eot)|avatars[^/]+)$/,
debug: false,
}
// 监听配置更新消息
self.addEventListener('message', e => {
if (e.data.type !== 'CONFIG') return
config = e.data.config
if (config.debug) console.log('PWA-CDN: Config updated', config)
})
// 拦截网络请求
self.addEventListener('fetch', e => {
const url = new URL(e.request.url)
// 如果请求不是GET方法,直接返回
if (e.request.method !== 'GET') return
// 如果请求的域名不是当前页面的域名
if (url.origin !== self.location.origin) return
// 过滤__static路径下的请求
if (url.pathname.startsWith('/__static/')) return
// 如果请求的路径不匹配静态资源正则表达式,直接返回
if (!config.staticRegex.test(url.pathname)) return
// 判断是否是强制需要同源请求
const requiresSameOrigin = ['worker', 'sharedworker', 'serviceworker'].includes(e.request.destination)
// 如果是强制需要同源请求的资源类型,直接返回
if (requiresSameOrigin) return
// 开始处理静态资源请求
e.respondWith(handleStaticResource(e.request, url))
})
// 处理静态资源请求
async function handleStaticResource(request, url) {
// 生成CDN子路径
const hostname = self.location.hostname
const cdnPath = hostname.replace(/\./g, '-')
const targetUrl = config.cdnUrl + cdnPath + url.pathname + url.search
if (config.debug) console.log('PWA-CDN:', url.href, '->', targetUrl)
try {
// 创建新请求
const newRequest = new Request(targetUrl, {
...request,
mode: 'cors',
redirect: 'error',
})
// 请求目标域名,浏览器会自动处理缓存
const response = await fetch(newRequest)
// 检查响应状态
if (!response.ok) throw new Error('PWA-CDN: Non-2xx response detected')
return response
} catch (error) {
if (config.debug) console.warn('PWA-CDN: Fallback to original request for', url.href, error)
// 失败时回退到原始请求
return fetch(request)
}
}
// Service Worker 生命周期
self.addEventListener('install', () => {
if (config.debug) console.log('PWA-CDN: Service Worker installing')
self.skipWaiting().catch(console.error)
})
self.addEventListener('activate', () => {
if (config.debug) console.log('PWA-CDN: Service Worker activated')
self.clients.claim().catch(console.error)
})
-4
查看文件
@@ -1,4 +0,0 @@
### path core中服务的节点亲和性 使他们只运行在master节点上
```shell
kubectl patch -n kube-system deployment coredns --patch-file=apps/kube/patch-affinity.yaml
```
-12
查看文件
@@ -1,12 +0,0 @@
spec:
template:
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-role.kubernetes.io/control-plane
operator: In
values:
- "true"
+142
查看文件
@@ -0,0 +1,142 @@
# Flux GitOps
## 目录结构
```
flux/
├── clusters/
│ ├── base/ # 基础集群编排,仅部署 infrastructure
│ │ ├── kustomization.yaml # infrastructure 资源列表
│ │ ├── sources.yaml # infrastructure HelmRepository 源
│ │ ├── kube-system.yaml # CoreDNS / NodeLocalDNS
│ │ ├── infra-devops.yaml # cert-manager / reflector / velero
│ │ ├── infra-data.yaml # CNPG / Valkey
│ │ ├── infra-monitor.yaml # Loki / Prometheus (+ post: Promtail)
│ │ ├── infra-net.yaml # Nginx / CrowdSec / Tailscale
│ │ └── infra-gitops.yaml # Gitea (+ post: Gitea Actions / Flux Web)
│ └── dev-cm/ # dev-cm 集群 overlay,额外部署 apps
│ ├── kustomization.yaml # 引入 base,并追加 apps / app 依赖层
│ ├── apps-sources.yaml # app HelmRepository 源
│ ├── apps-secrets.yaml # apps namespace 与 app 专属 Secret
│ ├── apps.yaml # Halo / RustDesk / Fillcode / SinceAI
│ └── apps-post.yaml # CDN Ingress(依赖 apps
├── infrastructure/
│ ├── sources/ # 所有 HelmRepository 定义
│ ├── kube-system/ # CoreDNS 自定义 + NodeLocalDNS
│ ├── infra-devops/ # cert-manager, webhook-dnspod, reflector, velero
│ │ └── post/ # ClusterIssuer + cert-manager ServiceMonitor values
│ ├── infra-data/ # CNPG operator, Barman, Valkey
│ │ ├── post-1/ # PG Cluster / ObjectStore / databases / LB
│ │ └── post-2/ # Reflector secret annotations
│ ├── infra-net/ # ingress-nginx, CrowdSec, Tailscale DERP, 证书
│ ├── infra-monitor/ # Loki, Prometheus+Grafana
│ │ └── post/ # Promtail(依赖 infra-net,打破循环)
│ └── infra-gitops/ # Gitea
│ └── post/ # Gitea Actions + flux-operator WebOIDC/Ingress
└── apps/
├── sources/ # app HelmRepository 定义
├── secrets/ # apps namespace 与 app 专属 Secret
├── post/ # CDN Ingress(依赖 apps,且引用部分 infra 服务)
├── helmrelease-halo.yaml # Halo
├── helmrelease-rustdesk.yaml # RustDesk
└── ... # app 证书与 Ingress
```
## 前置准备
需要提前生成git访问凭证
```shell
ssh-keygen -t ed25519 -C "flux" -f ./flux-git-auth -N ""
ssh-keyscan github.com > ./known_hosts
kubectl -n infra-gitops create secret generic flux-git-auth \
--from-file=identity=./flux-git-auth \
--from-file=identity.pub=./flux-git-auth.pub \
--from-file=known_hosts=./known_hosts
```
然后将 `flux-git-auth.pub` 文件内容添加到远端仓库中
应用flux实例 后续将自动开启部署流程
```shell
kubectl apply -f flux/flux-instance.yaml
```
## 部署顺序
```
sources → secrets → kube-system → infra-devops → infra-data → infra-data-post-1 → infra-data-post-2
→ infra-monitor → infra-net → infra-devops-post
→ infra-monitor-post (Promtail)
→ infra-gitops
→ apps-sources → apps-secrets → apps
→ apps-post (CDN Ingress)
→ infra-gitops-post (suspend=true,需手工凭据)
```
`clusters/base` 只包含到 `infra-gitops-post` 为止的 infrastructure 部署;`apps-sources``apps-secrets``apps``apps-post` 只在 `clusters/dev-cm` 中声明。Kustomization 间通过 `dependsOn` + `wait: true` 串行等待,避免顺序错乱。
## 部署后手工步骤(infra-gitops-post
`infra-gitops-post` 在 base 层硬编码 `spec.suspend: true` 默认暂停,因为它依赖两类只能在 Gitea 启动后获取的凭据:
1. **Flux Operator Web 的 OIDC 客户端**
2. **Gitea Actions Runner Token**
凭据就绪、`flux-env` Secret 重新注入后,可以先用 `flux resume kustomization infra-gitops-post -n infra-gitops` 手工放行。
注意:**手工 `resume` 只会修改集群里的 live 对象,不会改 Git 中的期望状态。** 由于 base 层仍然声明了 `spec.suspend: true`,当上层 `Kustomization` 重新协调(如 30 分钟周期、Git 变更、手工 reconcile)时,它会再次把 `infra-gitops-post` 改回暂停。
如果希望恢复后保持开启,需要把 Git 中的期望状态也改掉,例如在环境 overlay(如 `clusters/dev-cm/infra-gitops-post.yaml`)中覆盖:
```yaml
spec:
suspend: false
```
步骤:
1. 浏览器访问 `https://git.dev.cm`,首个注册账号自动成为 admin。
2. **创建 OAuth2 应用**
- Site Administration → Integrations → Applications → Create OAuth2 Application
- Redirect URI: `https://cd.dev.cm/oauth2/callback`
- 记录 Client ID 与 Client Secret。
3. **生成 Runner Token**
- Site Administration → Actions → Runners → Create new Runner → 复制 registration token。
4. 更新 `.env`
```
FLUX_WEB_OIDC_CLIENT_ID=<step 2 client id>
FLUX_WEB_OIDC_CLIENT_SECRET=<step 2 client secret>
GITEA_ACTIONS_TOKEN=<step 3 token>
```
5. 重新注入 `flux-env` Secret 并协调:
```bash
kubectl -n infra-gitops create secret generic flux-env \
--from-env-file=.env \
--dry-run=client -o yaml | kubectl apply -f -
flux reconcile kustomization secrets -n infra-gitops
flux resume kustomization infra-gitops-post -n infra-gitops
flux reconcile kustomization infra-gitops-post -n infra-gitops --with-source
```
6. 验证:
```bash
kubectl -n infra-gitops get helmrelease gitea-actions
kubectl -n infra-gitops get deploy flux-operator -o yaml | grep -A2 args # 看到 --web-*
curl -I https://cd.dev.cm # 走 Gitea OIDC
```
## 为何拆出 \*-post 层?
- **`infra-devops-post`**cert-manager 首次安装时不能依赖 `ServiceMonitor` CRD;post 层只在监控栈就绪后下发 `ClusterIssuer` 与可选 values ConfigMap,避免多个 Kustomization 共同管理同一个 HelmRelease。
- **`infra-monitor-post` (Promtail)**Promtail 依赖至少一个带 `devcm-log-collecting/enabled` 标签的 Podingress-nginx);而 `infra-net` 又依赖 `infra-monitor` 的 CRD。Promtail 放到 post 层并 `dependsOn: infra-net`,打破循环。
- **`apps-post` (CDN Ingress)**CDN Ingress 会引用 `apps`、`infra-gitops`、`infra-monitor` 中的服务,因此不属于 base;只在 `dev-cm` 中声明,并依赖对应服务层。
- **`infra-gitops-post` (Gitea Actions + Flux Web)**:凭据必须在 Gitea 启动后手工创建;放在 post 层并默认 suspend,避免阻塞 bootstrap。
@@ -1,35 +1,31 @@
apiVersion: helm.cattle.io/v1
kind: HelmChart
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: halo
namespace: apps
spec:
repo: https://halo-sigs.github.io/charts/
chart: halo
targetNamespace: apps
version: 1.3.2
valuesContent: |-
affinity:
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
cnpg.io/cluster: cnpg17-cluster-hk
role: primary
topologyKey: kubernetes.io/hostname
namespaceSelector: {}
interval: 30m
timeout: 15m
chart:
spec:
chart: halo
version: 1.3.2
sourceRef:
kind: HelmRepository
name: halo
namespace: infra-gitops
interval: 12h
values:
image:
repository: halohub/halo-pro
tag: 2.22.13
tag: 2.24.2
service:
type: ClusterIP
ingress:
enabled: true
ingressClassName: nginx
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
nginx.ingress.kubernetes.io/proxy-body-size: "100m"
nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_set_header Accept-Encoding "";
subs_filter_types text/html;
@@ -41,6 +37,9 @@ spec:
pathType: Prefix
podAnnotations:
backup.velero.io/backup-volumes: halo-data
persistence:
annotations:
helm.sh/resource-policy: keep
metrics:
enabled: true
mysql:
@@ -49,13 +48,11 @@ spec:
enabled: false
externalDatabase:
platform: postgresql
host: cnpg17-cluster-hk-rw.infra-data
host: cnpg17-cluster-rw.infra-data
port: 5432
user: app
password: FybaFtf6NV5jnxhj5bOPpHbO6KypZeHiyiskgAWkM5nioW2j82HtCf6GnW9xVKjE
password: from-secret
database: halo
existingSecret: cnpg17-cluster-app
haloUsername: rohow
haloExternalUrl: https://dev.cm
@@ -1,27 +1,33 @@
apiVersion: helm.cattle.io/v1
kind: HelmChart
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: rustdesk
namespace: apps
spec:
repo: https://devcm-repo.github.io/helm-charts
chart: rustdesk-server
targetNamespace: apps
version: 0.0.5
valuesContent: |-
nodeSelector:
kubernetes.io/hostname: tcd
interval: 30m
timeout: 15m
chart:
spec:
chart: rustdesk-server
version: 0.0.7
sourceRef:
kind: HelmRepository
name: devcm-repo
namespace: infra-gitops
interval: 12h
values:
rustdeskServer:
encryptedOnly: true
mustLogin: true
server: desk-server.dev.cm
podAnnotations:
backup.velero.io/backup-volumes: data
extraEnvs:
- name: TZ
value: "Asia/Shanghai"
- name: RUSTDESK_API_LANG
value: "zh-CN"
rustdeskApi:
server: desk.dev.cm
ingress:
@@ -1,14 +1,21 @@
apiVersion: helm.cattle.io/v1
kind: HelmChart
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: fillcode-whoami
namespace: apps
spec:
repo: https://cowboysysop.github.io/charts/
chart: whoami
targetNamespace: apps
version: 5.1.2
valuesContent: |-
interval: 30m
timeout: 15m
chart:
spec:
chart: whoami
version: 5.1.2
sourceRef:
kind: HelmRepository
name: cowboysysop
namespace: infra-gitops
interval: 12h
values:
ingress:
enabled: true
ingressClassName: nginx
@@ -20,5 +27,3 @@ spec:
- host: whoami.fillcode.com
paths:
- /
@@ -3,7 +3,6 @@ kind: Ingress
metadata:
name: fillcode
namespace: apps
annotations:
spec:
ingressClassName: nginx
rules:
@@ -21,4 +20,3 @@ spec:
- hosts:
- fillcode.com
secretName: fillcode-com-crt
@@ -4,8 +4,8 @@ metadata:
name: halo-static
namespace: apps
annotations:
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/proxy-buffering: "on"
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_cache cache;
proxy_cache_valid 200 302 7d;
@@ -28,3 +28,6 @@ spec:
name: halo
port:
number: 80
tls:
- hosts:
- dev.cm
@@ -9,6 +9,9 @@ metadata:
rewrite ^/(.*)$ https://dev.cm/$1 permanent;
spec:
ingressClassName: nginx
tls:
- hosts:
- www.dev.cm
rules:
- host: www.dev.cm
http:
@@ -20,4 +23,3 @@ spec:
name: halo
port:
number: 80
@@ -4,7 +4,6 @@ metadata:
name: sinceai-shop
namespace: apps
annotations:
# 302 跳转到https://sinceai.taobao.com/
nginx.ingress.kubernetes.io/configuration-snippet: |
rewrite ^/(.*)$ https://sinceai.taobao.com/$1? permanent;
spec:
@@ -24,4 +23,3 @@ spec:
- hosts:
- shop.sinceai.com
secretName: sinceai-com-crt
+12
查看文件
@@ -0,0 +1,12 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- certificate-fillcode-com.yaml
- certificate-sinceai-com.yaml
- helmrelease-halo.yaml
- ingress-fillcode.yaml
- ingress-halo-www.yaml
- ingress-halo-static.yaml
- ingress-sinceai-shop.yaml
- helmrelease-whoami.yaml
- helmrelease-rustdesk.yaml
+4
查看文件
@@ -0,0 +1,4 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ingress-cdn.yaml
+4
查看文件
@@ -0,0 +1,4 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- namespaces.yaml
+21
查看文件
@@ -0,0 +1,21 @@
# whoami
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
name: cowboysysop
namespace: infra-gitops
spec:
interval: 168h
timeout: 5m
url: https://cowboysysop.github.io/charts/
---
# halo
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
name: halo
namespace: infra-gitops
spec:
interval: 168h
timeout: 5m
url: https://halo-sigs.github.io/charts/
+4
查看文件
@@ -0,0 +1,4 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- helm-repositories.yaml
+58
查看文件
@@ -0,0 +1,58 @@
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: infra-data
namespace: infra-gitops
spec:
interval: 30m
timeout: 15m
retryInterval: 1m
sourceRef:
kind: GitRepository
name: flux
path: ./flux/infrastructure/infra-data
prune: true
force: true
wait: true
dependsOn:
- name: infra-devops
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: infra-data-post-1
namespace: infra-gitops
spec:
interval: 30m
timeout: 15m
retryInterval: 1m
sourceRef:
kind: GitRepository
name: flux
path: ./flux/infrastructure/infra-data/post-1
prune: true
force: true
wait: true
dependsOn:
- name: infra-data
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: infra-data-post-2
namespace: infra-gitops
spec:
interval: 30m
timeout: 15m
retryInterval: 1m
sourceRef:
kind: GitRepository
name: flux
path: ./flux/infrastructure/infra-data/post-2
prune: true
force: true
wait: true
dependsOn:
- name: infra-data-post-1
+38
查看文件
@@ -0,0 +1,38 @@
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: infra-devops
namespace: infra-gitops
spec:
interval: 30m
timeout: 15m
retryInterval: 1m
sourceRef:
kind: GitRepository
name: flux
path: ./flux/infrastructure/infra-devops
prune: true
wait: true
dependsOn:
- name: sources
- name: secrets
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: infra-devops-post
namespace: infra-gitops
spec:
interval: 30m
timeout: 15m
retryInterval: 1m
sourceRef:
kind: GitRepository
name: flux
path: ./flux/infrastructure/infra-devops/post
prune: true
force: true
wait: true
dependsOn:
- name: infra-monitor
+45
查看文件
@@ -0,0 +1,45 @@
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: infra-gitops
namespace: infra-gitops
spec:
interval: 30m
timeout: 15m
retryInterval: 1m
sourceRef:
kind: GitRepository
name: flux
path: ./flux/infrastructure/infra-gitops
prune: true
wait: true
dependsOn:
- name: infra-data-post-2
- name: infra-monitor
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: infra-gitops-post
namespace: infra-gitops
spec:
# 默认暂停:post 层依赖 Gitea 启动后才能获取的 OIDC / Runner Token 凭据。
# 凭据就绪并写入 flux-env Secret 后,使用 `flux resume kustomization infra-gitops-post -n infra-gitops` 放行。
suspend: true
interval: 30m
timeout: 15m
retryInterval: 1m
sourceRef:
kind: GitRepository
name: flux
path: ./flux/infrastructure/infra-gitops/post
prune: true
wait: true
dependsOn:
- name: infra-gitops
- name: infra-net
postBuild:
substituteFrom:
- kind: Secret
name: flux-env
+39
查看文件
@@ -0,0 +1,39 @@
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: infra-monitor
namespace: infra-gitops
spec:
interval: 30m
timeout: 15m
retryInterval: 1m
sourceRef:
kind: GitRepository
name: flux
path: ./flux/infrastructure/infra-monitor
prune: true
force: true
wait: true
dependsOn:
- name: infra-data-post-2
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: infra-monitor-post
namespace: infra-gitops
spec:
interval: 30m
timeout: 15m
retryInterval: 1m
sourceRef:
kind: GitRepository
name: flux
path: ./flux/infrastructure/infra-monitor/post
prune: true
force: true
wait: true
dependsOn:
- name: infra-monitor
- name: infra-net
+20
查看文件
@@ -0,0 +1,20 @@
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: infra-net
namespace: infra-gitops
spec:
interval: 30m
timeout: 15m
retryInterval: 1m
sourceRef:
kind: GitRepository
name: flux
path: ./flux/infrastructure/infra-net
prune: true
wait: true
dependsOn:
- name: kube-system
- name: infra-devops
- name: infra-devops-post
- name: infra-monitor
+15
查看文件
@@ -0,0 +1,15 @@
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: kube-system
namespace: infra-gitops
spec:
interval: 30m
timeout: 15m
retryInterval: 1m
sourceRef:
kind: GitRepository
name: flux
path: ./flux/infrastructure/kube-system
prune: false
wait: true
+11
查看文件
@@ -0,0 +1,11 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- sources.yaml
- secrets.yaml
- kube-system.yaml
- infra-devops.yaml
- infra-data.yaml
- infra-net.yaml
- infra-monitor.yaml
- infra-gitops.yaml
+23
查看文件
@@ -0,0 +1,23 @@
# 密钥管理层 - 通过postBuild从flux-env Secret注入变量
# 所有环境流程一致: kubectl create secret generic flux-env -n infra-gitops --from-env-file=.env
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: secrets
namespace: infra-gitops
spec:
interval: 30m
timeout: 15m
retryInterval: 1m
sourceRef:
kind: GitRepository
name: flux
path: ./flux/infrastructure/secrets
prune: false
wait: true
dependsOn:
- name: sources
postBuild:
substituteFrom:
- kind: Secret
name: flux-env
+15
查看文件
@@ -0,0 +1,15 @@
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: sources
namespace: infra-gitops
spec:
interval: 30m
timeout: 15m
retryInterval: 1m
sourceRef:
kind: GitRepository
name: flux
path: ./flux/infrastructure/sources
prune: true
wait: true
+20
查看文件
@@ -0,0 +1,20 @@
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: apps-post
namespace: infra-gitops
spec:
interval: 30m
timeout: 15m
retryInterval: 1m
sourceRef:
kind: GitRepository
name: flux
path: ./flux/apps/post
prune: true
wait: true
dependsOn:
- name: infra-net
- name: infra-gitops
- name: infra-monitor
- name: apps
+21
查看文件
@@ -0,0 +1,21 @@
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: apps-secrets
namespace: infra-gitops
spec:
interval: 30m
timeout: 15m
retryInterval: 1m
sourceRef:
kind: GitRepository
name: flux
path: ./flux/apps/secrets
prune: false
wait: true
dependsOn:
- name: apps-sources
postBuild:
substituteFrom:
- kind: Secret
name: flux-env
+17
查看文件
@@ -0,0 +1,17 @@
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: apps-sources
namespace: infra-gitops
spec:
interval: 30m
timeout: 15m
retryInterval: 1m
sourceRef:
kind: GitRepository
name: flux
path: ./flux/apps/sources
prune: true
wait: true
dependsOn:
- name: sources
+56
查看文件
@@ -0,0 +1,56 @@
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: apps
namespace: infra-gitops
spec:
interval: 30m
timeout: 15m
retryInterval: 1m
sourceRef:
kind: GitRepository
name: flux
path: ./flux/apps
prune: true
dependsOn:
- name: apps-sources
- name: apps-secrets
- name: infra-data-post-2
- name: infra-net
patches:
- target:
kind: HelmRelease
name: halo
patch: |
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: halo
spec:
values:
externalDatabase:
host: cnpg17-cluster-hk-rw.infra-data
existingSecret: cnpg17-cluster-hk-app
affinity:
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
cnpg.io/cluster: cnpg17-cluster-hk
role: primary
topologyKey: kubernetes.io/hostname
namespaceSelector: {}
- target:
kind: HelmRelease
name: rustdesk
patch: |
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: rustdesk
spec:
values:
nodeSelector:
kubernetes.io/hostname: tcd
@@ -0,0 +1,69 @@
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: infra-data
spec:
patches:
- target:
kind: HelmRelease
name: cloudnative-pg
patch: |
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: cloudnative-pg
spec:
values:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/region
operator: In
values:
- "cn-sh"
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists"
effect: "NoSchedule"
- target:
kind: HelmRelease
name: cloudnative-pg-plugin-barman
patch: |
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: cloudnative-pg-plugin-barman
spec:
values:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/region
operator: In
values:
- "cn-sh"
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists"
effect: "NoSchedule"
- target:
kind: HelmRelease
name: valkey-cluster
patch: |
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: valkey-cluster
spec:
values:
fullnameOverride: valkey-cluster-sh
valkey:
nodeAffinityPreset:
type: hard
key: topology.kubernetes.io/region
values:
- cn-sh
@@ -0,0 +1,42 @@
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cnpg17-cluster-hk
namespace: infra-data
spec:
imageName: ghcr.io/cloudnative-pg/postgresql:17.4
enableSuperuserAccess: true
enablePDB: false
instances: 1
storage:
size: 10Gi
postgresql:
parameters:
archive_timeout: 30min
env:
- name: AWS_REQUEST_CHECKSUM_CALCULATION
value: when_required
- name: AWS_RESPONSE_CHECKSUM_VALIDATION
value: when_required
plugins:
- name: barman-cloud.cloudnative-pg.io
isWALArchiver: true
parameters:
barmanObjectName: cnpg17-objectstore-hw
serverName: cnpg17-cluster-hk
---
apiVersion: postgresql.cnpg.io/v1
kind: ScheduledBackup
metadata:
name: cnpg17-cluster-hk-backups
namespace: infra-data
spec:
schedule: "0 0 0 * * *"
immediate: true
backupOwnerReference: self
method: plugin
pluginConfiguration:
name: barman-cloud.cloudnative-pg.io
cluster:
name: cnpg17-cluster-hk
@@ -0,0 +1,42 @@
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cnpg17-cluster-sh
namespace: infra-data
spec:
imageName: ghcr.io/cloudnative-pg/postgresql:17.4
enableSuperuserAccess: true
enablePDB: false
instances: 1
storage:
size: 10Gi
postgresql:
parameters:
archive_timeout: 30min
env:
- name: AWS_REQUEST_CHECKSUM_CALCULATION
value: when_required
- name: AWS_RESPONSE_CHECKSUM_VALIDATION
value: when_required
plugins:
- name: barman-cloud.cloudnative-pg.io
isWALArchiver: true
parameters:
barmanObjectName: cnpg17-objectstore-hw
serverName: cnpg17-cluster-sh
---
apiVersion: postgresql.cnpg.io/v1
kind: ScheduledBackup
metadata:
name: cnpg17-cluster-sh-backups
namespace: infra-data
spec:
schedule: "0 0 0 * * *"
immediate: true
backupOwnerReference: self
method: plugin
pluginConfiguration:
name: barman-cloud.cloudnative-pg.io
cluster:
name: cnpg17-cluster-sh
@@ -0,0 +1,20 @@
apiVersion: barmancloud.cnpg.io/v1
kind: ObjectStore
metadata:
name: cnpg17-objectstore-hw
namespace: infra-data
spec:
retentionPolicy: "7d"
configuration:
destinationPath: s3://devcm/cnpg/
endpointURL: https://obs.cn-east-3.myhuaweicloud.com
s3Credentials:
accessKeyId:
name: s3-devcm-hw
key: ACCESS_KEY_ID
secretAccessKey:
name: s3-devcm-hw
key: ACCESS_SECRET_KEY
wal:
compression: gzip
maxParallel: 8
@@ -0,0 +1,43 @@
apiVersion: postgresql.cnpg.io/v1
kind: Database
metadata:
name: cnpg17-cluster-sh-gitea
namespace: infra-data
spec:
name: gitea
owner: app
cluster:
name: cnpg17-cluster-sh
---
apiVersion: postgresql.cnpg.io/v1
kind: Database
metadata:
name: cnpg17-cluster-sh-grafana
namespace: infra-data
spec:
name: grafana
owner: app
cluster:
name: cnpg17-cluster-sh
---
apiVersion: postgresql.cnpg.io/v1
kind: Database
metadata:
name: cnpg17-cluster-hk-halo
namespace: infra-data
spec:
name: halo
owner: app
cluster:
name: cnpg17-cluster-hk
---
apiVersion: postgresql.cnpg.io/v1
kind: Database
metadata:
name: cnpg17-cluster-hk-crowdsec
namespace: infra-data
spec:
name: crowdsec
owner: app
cluster:
name: cnpg17-cluster-hk
@@ -0,0 +1,9 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- cnpg17-objectstore-hw.yaml
- cnpg17-cluster-hk.yaml
- cnpg17-cluster-sh.yaml
- databases.yaml
- loadbalancer-hk.yaml
- loadbalancer-sh.yaml
@@ -9,6 +9,6 @@ spec:
role: primary
ports:
- protocol: TCP
port: 65432
port: 65431
targetPort: 5432
type: LoadBalancer
@@ -0,0 +1,59 @@
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: infra-data-post-1
spec:
path: ./flux/clusters/dev-cm/infra-data/post-1
patches:
- target:
kind: Cluster
name: cnpg17-cluster-hk
patch: |
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cnpg17-cluster-hk
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/region
operator: In
values:
- "cn-hk"
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- clawhk
- target:
kind: Cluster
name: cnpg17-cluster-sh
patch: |
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cnpg17-cluster-sh
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/region
operator: In
values:
- "cn-sh"
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- homea
@@ -0,0 +1,4 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- reflector-secret-annotations.yaml
@@ -0,0 +1,6 @@
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: infra-data-post-2
spec:
path: ./flux/clusters/dev-cm/infra-data/post-2
@@ -0,0 +1,38 @@
apiVersion: v1
kind: Secret
metadata:
name: cnpg17-cluster-hk-app
namespace: infra-data
annotations:
kustomize.toolkit.fluxcd.io/prune: disabled
kustomize.toolkit.fluxcd.io/ssa: Merge
reflector.v1.k8s.emberstack.com/reflection-allowed: "true"
reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces: "apps,infra-net"
reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true"
reflector.v1.k8s.emberstack.com/reflection-auto-namespaces: "apps,infra-net"
---
apiVersion: v1
kind: Secret
metadata:
name: cnpg17-cluster-sh-app
namespace: infra-data
annotations:
kustomize.toolkit.fluxcd.io/prune: disabled
kustomize.toolkit.fluxcd.io/ssa: Merge
reflector.v1.k8s.emberstack.com/reflection-allowed: "true"
reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces: "apps,infra-gitops,infra-monitor"
reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true"
reflector.v1.k8s.emberstack.com/reflection-auto-namespaces: "apps,infra-gitops,infra-monitor"
---
apiVersion: v1
kind: Secret
metadata:
name: valkey-cluster-sh
namespace: infra-data
annotations:
kustomize.toolkit.fluxcd.io/prune: disabled
kustomize.toolkit.fluxcd.io/ssa: Merge
reflector.v1.k8s.emberstack.com/reflection-allowed: "true"
reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces: "apps,infra-gitops"
reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true"
reflector.v1.k8s.emberstack.com/reflection-auto-namespaces: "apps,infra-gitops"
+124
查看文件
@@ -0,0 +1,124 @@
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: infra-devops
spec:
patches:
- target:
kind: HelmRelease
name: cert-manager
patch: |
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: cert-manager
spec:
values:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/region
operator: In
values:
- "cn-sh"
webhook:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/region
operator: In
values:
- "cn-sh"
cainjector:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/region
operator: In
values:
- "cn-sh"
- target:
kind: HelmRelease
name: cert-manager-webhook-dnspod
patch: |
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: cert-manager-webhook-dnspod
spec:
values:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/region
operator: In
values:
- "cn-sh"
- target:
kind: HelmRelease
name: reflector
patch: |
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: reflector
spec:
values:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/region
operator: In
values:
- "cn-sh"
- target:
kind: HelmRelease
name: velero
patch: |
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: velero
spec:
values:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/region
operator: In
values:
- "cn-sh"
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- homeb
nodeAgent:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-role.kubernetes.io/control-plane
operator: NotIn
values:
- "true"
- key: svccontroller.k3s.cattle.io/enablelb
operator: NotIn
values:
- "true"
@@ -0,0 +1,20 @@
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: infra-gitops-post
spec:
suspend: false
patches:
- target:
kind: HelmRelease
name: gitea-actions
patch: |
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: gitea-actions
spec:
values:
statefulset:
nodeSelector:
dev-cm-runner/enabled: "true"
+59
查看文件
@@ -0,0 +1,59 @@
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: infra-gitops
spec:
patches:
- target:
kind: HelmRelease
name: gitea
patch: |
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: gitea
spec:
values:
gitea:
config:
database:
HOST: cnpg17-cluster-sh-rw.infra-data:5432
additionalConfigFromEnvs:
- name: GITEA__DATABASE__PASSWD
valueFrom:
secretKeyRef:
name: cnpg17-cluster-sh-app
key: password
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: valkey-cluster-sh
key: valkey-password
- name: GITEA__SESSION__PROVIDER_CONFIG
value: "redis://:$(REDIS_PASSWORD)@valkey-cluster-sh-headless.infra-data:6379/0?pool_size=100&idle_timeout=180s"
- name: GITEA__CACHE__HOST
value: "redis://:$(REDIS_PASSWORD)@valkey-cluster-sh-headless.infra-data:6379/0?pool_size=100&idle_timeout=180s"
- name: GITEA__QUEUE__CONN_STR
value: "redis://:$(REDIS_PASSWORD)@valkey-cluster-sh-headless.infra-data:6379/0?pool_size=100&idle_timeout=180s"
affinity:
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
cnpg.io/cluster: cnpg17-cluster-sh
role: primary
app.kubernetes.io/name: redis
app.kubernetes.io/component: master
topologyKey: kubernetes.io/hostname
namespaceSelector: {}
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- homea
@@ -0,0 +1,18 @@
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: infra-monitor-post
spec:
patches:
- target:
kind: HelmRelease
name: loki-promtail
patch: |
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: loki-promtail
spec:
values:
nodeSelector:
svccontroller.k3s.cattle.io/enablelb: "true"
+94
查看文件
@@ -0,0 +1,94 @@
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: infra-monitor
spec:
patches:
- target:
kind: HelmRelease
name: loki
patch: |
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: loki
spec:
values:
lokiCanary:
nodeSelector:
svccontroller.k3s.cattle.io/enablelb: "true"
resultsCache:
nodeSelector:
kubernetes.io/hostname: tce
chunksCache:
nodeSelector:
kubernetes.io/hostname: tce
singleBinary:
nodeSelector:
kubernetes.io/hostname: tce
- target:
kind: HelmRelease
name: loki-promtail
patch: |
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: loki-promtail
spec:
values:
nodeSelector:
svccontroller.k3s.cattle.io/enablelb: "true"
- target:
kind: HelmRelease
name: prometheus
patch: |
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: prometheus
spec:
values:
prometheusOperator:
nodeSelector:
kubernetes.io/hostname: hwa
kube-state-metrics:
nodeSelector:
kubernetes.io/hostname: hwa
grafana:
envValueFrom:
GF_DATABASE_PASSWORD:
secretKeyRef:
name: cnpg17-cluster-sh-app
key: password
grafana.ini:
database:
host: cnpg17-cluster-sh-rw.infra-data:5432
affinity:
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
cnpg.io/cluster: cnpg17-cluster-sh
role: primary
topologyKey: kubernetes.io/hostname
namespaceSelector: {}
persistence:
storageClassName: local-path
prometheus:
prometheusSpec:
nodeSelector:
kubernetes.io/hostname: hwa
storageSpec:
volumeClaimTemplate:
spec:
storageClassName: local-path
alertmanager:
alertmanagerSpec:
nodeSelector:
kubernetes.io/hostname: hwa
storage:
volumeClaimTemplate:
spec:
storageClassName: local-path
+120
查看文件
@@ -0,0 +1,120 @@
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: infra-net
spec:
patches:
- target:
kind: HelmRelease
name: ingress-nginx
patch: |
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: ingress-nginx
spec:
values:
controller:
nodeSelector:
svccontroller.k3s.cattle.io/enablelb: "true"
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists"
effect: "NoSchedule"
dnsPolicy: "None"
dnsConfig:
nameservers:
- "169.254.20.10"
- "10.43.0.10"
defaultBackend:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/region
operator: In
values:
- "cn-sh"
- "cn-hk"
- target:
kind: HelmRelease
name: crowdsec
patch: |
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: crowdsec
spec:
values:
lapi:
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: cnpg17-cluster-hk-app
key: password
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: topology.kubernetes.io/region
operator: In
values:
- cn-hk
config:
config.yaml.local: |
db_config:
type: postgresql
host: cnpg17-cluster-hk-rw.infra-data
port: 5432
db_name: crowdsec
user: app
password: ${DB_PASSWORD}
sslmode: require
api:
server:
auto_registration:
enabled: true
token: "${REGISTRATION_TOKEN}"
allowed_ranges:
- "127.0.0.1/32"
- "192.168.0.0/16"
- "172.16.0.0/12"
- "10.0.0.0/8"
agent:
affinity:
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app.kubernetes.io/name: loki
topologyKey: kubernetes.io/hostname
namespaceSelector: {}
appsec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: topology.kubernetes.io/region
operator: In
values:
- cn-hk
- target:
kind: HelmRelease
name: tailscale-derp-hk
patch: |
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: tailscale-derp-hk
spec:
values:
nodeSelector:
kubernetes.io/hostname: tchk
+30
查看文件
@@ -0,0 +1,30 @@
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: kube-system
spec:
patches:
- target:
kind: Deployment
name: "(coredns|local-path-provisioner|metrics-server)"
patch: |
apiVersion: apps/v1
kind: Deployment
metadata:
name: placeholder
spec:
template:
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-role.kubernetes.io/control-plane
operator: In
values:
- "true"
tolerations:
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
+49
查看文件
@@ -0,0 +1,49 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../base
- apps-sources.yaml
- apps-secrets.yaml
- apps.yaml
- apps-post.yaml
patches:
- target:
kind: Kustomization
name: kube-system
path: kube-system.yaml
- target:
kind: Kustomization
name: infra-devops
path: infra-devops.yaml
- target:
kind: Kustomization
name: infra-data
path: infra-data/patch.yaml
- target:
kind: Kustomization
name: infra-data-post-1
path: infra-data/post-1/patch.yaml
- target:
kind: Kustomization
name: infra-data-post-2
path: infra-data/post-2/patch.yaml
- target:
kind: Kustomization
name: infra-net
path: infra-net.yaml
- target:
kind: Kustomization
name: infra-monitor
path: infra-monitor.yaml
- target:
kind: Kustomization
name: infra-monitor-post
path: infra-monitor-post.yaml
- target:
kind: Kustomization
name: infra-gitops
path: infra-gitops.yaml
- target:
kind: Kustomization
name: infra-gitops-post
path: infra-gitops-post.yaml
+66
查看文件
@@ -0,0 +1,66 @@
apiVersion: fluxcd.controlplane.io/v1
kind: FluxInstance
metadata:
name: flux
namespace: infra-gitops
spec:
distribution:
version: "2.8.5"
registry: "ghcr.io/fluxcd"
artifact: "oci://ghcr.io/controlplaneio-fluxcd/flux-operator-manifests"
components:
- source-controller
- kustomize-controller
- helm-controller
- notification-controller
cluster:
type: kubernetes
size: small
multitenant: false
networkPolicy: true
domain: "cluster.local"
storage:
class: "local-path"
size: "10Gi"
sync:
kind: GitRepository
url: ssh://git@github.com/devcm-repo/k3s.git
ref: refs/heads/main
path: flux/clusters/dev-cm
pullSecret: flux-git-auth
name: flux
kustomize:
patches:
# source-controller 需要良好的国际网络环境,优先调度到网络较好的节点上
- target:
kind: Deployment
name: (source-controller)
patch: |
- op: add
path: /spec/template/spec/affinity
value:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- clawjp
- target:
kind: Deployment
name: (helm-controller|kustomize-controller|notification-controller)
patch: |
- op: add
path: /spec/template/spec/affinity
value:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- homea
@@ -0,0 +1,19 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: cloudnative-pg-plugin-barman
namespace: infra-data
spec:
interval: 30m
timeout: 15m
dependsOn:
- name: cloudnative-pg
chart:
spec:
chart: plugin-barman-cloud
version: 0.5.0
sourceRef:
kind: HelmRepository
name: cloudnative-pg
namespace: infra-gitops
interval: 12h
@@ -0,0 +1,21 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: cloudnative-pg
namespace: infra-data
spec:
interval: 30m
timeout: 15m
chart:
spec:
chart: cloudnative-pg
version: 0.27.1
sourceRef:
kind: HelmRepository
name: cloudnative-pg
namespace: infra-gitops
interval: 12h
install:
crds: CreateReplace
upgrade:
crds: CreateReplace
@@ -0,0 +1,23 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: valkey-cluster
namespace: infra-data
spec:
interval: 30m
timeout: 15m
chart:
spec:
chart: valkey-cluster
version: 3.0.23
sourceRef:
kind: HelmRepository
name: bitnami
namespace: infra-gitops
interval: 12h
values:
image:
repository: bitnamilegacy/valkey-cluster
cluster:
nodes: 1
replicas: 0
@@ -0,0 +1,7 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- namespace.yaml
- helmrelease-cloudnative-pg.yaml
- helmrelease-barman-plugin.yaml
- helmrelease-valkey-cluster.yaml
@@ -1,4 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: infra-net
name: infra-data
@@ -0,0 +1,42 @@
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cnpg17-cluster
namespace: infra-data
spec:
imageName: ghcr.io/cloudnative-pg/postgresql:17.4
enableSuperuserAccess: true
enablePDB: false
instances: 1
storage:
size: 10Gi
postgresql:
parameters:
archive_timeout: 30min
env:
- name: AWS_REQUEST_CHECKSUM_CALCULATION
value: when_required
- name: AWS_RESPONSE_CHECKSUM_VALIDATION
value: when_required
plugins:
- name: barman-cloud.cloudnative-pg.io
isWALArchiver: true
parameters:
barmanObjectName: cnpg17-objectstore-hw
serverName: cnpg17-cluster
---
apiVersion: postgresql.cnpg.io/v1
kind: ScheduledBackup
metadata:
name: cnpg17-cluster-backups
namespace: infra-data
spec:
schedule: "0 0 0 * * *"
immediate: true
backupOwnerReference: self
method: plugin
pluginConfiguration:
name: barman-cloud.cloudnative-pg.io
cluster:
name: cnpg17-cluster
@@ -0,0 +1,20 @@
apiVersion: barmancloud.cnpg.io/v1
kind: ObjectStore
metadata:
name: cnpg17-objectstore-hw
namespace: infra-data
spec:
retentionPolicy: "7d"
configuration:
destinationPath: s3://devcm/cnpg/
endpointURL: https://obs.cn-east-3.myhuaweicloud.com
s3Credentials:
accessKeyId:
name: s3-devcm-hw
key: ACCESS_KEY_ID
secretAccessKey:
name: s3-devcm-hw
key: ACCESS_SECRET_KEY
wal:
compression: gzip
maxParallel: 8
@@ -0,0 +1,43 @@
apiVersion: postgresql.cnpg.io/v1
kind: Database
metadata:
name: cnpg17-cluster-gitea
namespace: infra-data
spec:
name: gitea
owner: app
cluster:
name: cnpg17-cluster
---
apiVersion: postgresql.cnpg.io/v1
kind: Database
metadata:
name: cnpg17-cluster-grafana
namespace: infra-data
spec:
name: grafana
owner: app
cluster:
name: cnpg17-cluster
---
apiVersion: postgresql.cnpg.io/v1
kind: Database
metadata:
name: cnpg17-cluster-halo
namespace: infra-data
spec:
name: halo
owner: app
cluster:
name: cnpg17-cluster
---
apiVersion: postgresql.cnpg.io/v1
kind: Database
metadata:
name: cnpg17-cluster-crowdsec
namespace: infra-data
spec:
name: crowdsec
owner: app
cluster:
name: cnpg17-cluster
@@ -0,0 +1,7 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- cnpg17-objectstore-hw.yaml
- cnpg17-cluster.yaml
- databases.yaml
- loadbalancer.yaml
@@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
name: cnpg17-cluster-lb
namespace: infra-data
spec:
selector:
cnpg.io/cluster: cnpg17-cluster
role: primary
ports:
- protocol: TCP
port: 5432
targetPort: 5432
type: LoadBalancer
@@ -0,0 +1,4 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- reflector-secret-annotations.yaml
@@ -0,0 +1,25 @@
apiVersion: v1
kind: Secret
metadata:
name: cnpg17-cluster-app
namespace: infra-data
annotations:
kustomize.toolkit.fluxcd.io/prune: disabled
kustomize.toolkit.fluxcd.io/ssa: Merge
reflector.v1.k8s.emberstack.com/reflection-allowed: "true"
reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces: "infra-net,infra-gitops,infra-monitor"
reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true"
reflector.v1.k8s.emberstack.com/reflection-auto-namespaces: "infra-net,infra-gitops,infra-monitor"
---
apiVersion: v1
kind: Secret
metadata:
name: valkey-cluster
namespace: infra-data
annotations:
kustomize.toolkit.fluxcd.io/prune: disabled
kustomize.toolkit.fluxcd.io/ssa: Merge
reflector.v1.k8s.emberstack.com/reflection-allowed: "true"
reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces: "infra-gitops"
reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true"
reflector.v1.k8s.emberstack.com/reflection-auto-namespaces: "infra-gitops"
@@ -0,0 +1,41 @@
# 安装后需要将clusterIssuer的cnameStrategy策略设置为Follow
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: cert-manager-webhook-dnspod
namespace: infra-devops
spec:
interval: 30m
timeout: 15m
dependsOn:
- name: cert-manager
chart:
spec:
chart: cert-manager-webhook-dnspod
version: 1.5.2
sourceRef:
kind: HelmRepository
name: imroc
namespace: infra-gitops
interval: 12h
# 启用漂移检测,集群中资源被误删时 Flux 会自动重建
driftDetection:
mode: enabled
# 升级失败或资源被删除时,允许卸载后重装以恢复
install:
remediation:
retries: 3
upgrade:
remediation:
retries: 3
remediateLastFailure: true
values:
image:
tag: "1.5.2"
namespace: infra-devops
certManager:
namespace: infra-devops
groupName: cert.dev.cm
# 此处关闭 选择手动创建 以支持cnameStrategy
clusterIssuer:
enabled: false

某些文件未显示,因为此 diff 中更改的文件太多 显示更多