Compare commits
22
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
93f803a0d9 | ||
|
|
f7d9579221 | ||
|
|
9fe910a4c9 | ||
|
|
28c20fd3e5 | ||
|
|
28f1de35cb | ||
|
|
ad4ed1f0d6 | ||
|
|
611a5a3d3a
|
||
|
|
7582990655
|
||
|
|
ec3ce94e12 | ||
|
|
6eb4875db6
|
||
|
|
518dba6036 | ||
|
|
4c823f8181
|
||
|
|
8290082fb4 | ||
|
|
159a75b710
|
||
|
|
e0e629794b
|
||
|
|
90ba945d85 | ||
|
|
d526fd75d3
|
||
|
|
18cb2858b9 | ||
|
|
99d1ec1d6f | ||
|
|
583dab526a
|
||
|
|
3dbd4c5f31
|
||
|
|
e67bce5121
|
@@ -6,11 +6,12 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
dependsOn:
|
dependsOn:
|
||||||
- name: external-secrets
|
- name: external-secrets
|
||||||
- name: nats
|
|
||||||
- name: spire
|
- name: spire
|
||||||
interval: 10m
|
interval: 10m
|
||||||
path: ./platform/dynamic-runner
|
path: ./platform/dynamic-runner
|
||||||
prune: false
|
# The runner backends are replaceable. Prune is required when a retired
|
||||||
|
# worker is removed from the component; otherwise it keeps consuming work.
|
||||||
|
prune: true
|
||||||
sourceRef:
|
sourceRef:
|
||||||
kind: GitRepository
|
kind: GitRepository
|
||||||
name: flux-system
|
name: flux-system
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ Root bootstrap 已完成。后续按依赖顺序分别引入:
|
|||||||
1. 监控 CRD、kube-state-metrics 以及 kubelet/cAdvisor 抓取配置;
|
1. 监控 CRD、kube-state-metrics 以及 kubelet/cAdvisor 抓取配置;
|
||||||
2. SPIRE Agent、SPIFFE CSI Driver 与 workload registration;
|
2. SPIRE Agent、SPIFFE CSI Driver 与 workload registration;
|
||||||
3. Kata Containers、`block-plain` RuntimeClass;
|
3. Kata Containers、`block-plain` RuntimeClass;
|
||||||
4. OpenSandbox operator/server 及 `ci-pod`、`ci-vm` Pools。
|
4. 独立 External Secrets Operator 与 sandbox 专用 OpenBao auth backend;
|
||||||
|
5. OpenSandbox controller/server;CI Pool 与 runner 调度器随后独立接入。
|
||||||
|
|
||||||
每一阶段单独合并并等待对应 Flux Kustomization Ready,不在 bootstrap 时一次性部署。
|
每一阶段单独合并并等待对应 Flux Kustomization Ready,不在 bootstrap 时一次性部署。
|
||||||
第一阶段监控拆为 `monitoring-operator` 与依赖它的 `monitoring`,防止 VM CR 在
|
第一阶段监控拆为 `monitoring-operator` 与依赖它的 `monitoring`,防止 VM CR 在
|
||||||
@@ -42,15 +43,25 @@ attestation。Server 使用 external bundle publisher 持续维护 sandbox
|
|||||||
显式关闭 Server 与 OIDC Provider,只部署 Agent DaemonSet 和 SPIFFE CSI Driver;因此
|
显式关闭 Server 与 OIDC Provider,只部署 Agent DaemonSet 和 SPIFFE CSI Driver;因此
|
||||||
不会产生第二个 trust root。
|
不会产生第二个 trust root。
|
||||||
|
|
||||||
`spire-smoke` namespace、ServiceAccount 和 `sandbox-spire-smoke` ClusterSPIFFEID 是
|
`spire-smoke` namespace、ServiceAccount 和 `sandbox-spire-smoke` ClusterSPIFFEID 只用于
|
||||||
普通 Pod 与后续 Kata guest 的回归夹具,稳定身份为
|
普通 Pod 的 CSI 回归夹具,稳定身份为 `spiffe://ddupan.top/sandbox/smoke`。Kata guest
|
||||||
`spiffe://ddupan.top/sandbox/smoke`。测试 Pod 临时创建并在验收后删除,身份声明保留。
|
不能复用 node Agent 暴露的 Unix socket;virtio-fs 只能呈现 socket 路径,不能把连接
|
||||||
|
跨过 VM 边界。Kata workload 必须使用 guest 内 Agent,具体约束见
|
||||||
|
`platform/sandbox-kata/README.md`。测试 Pod 临时创建并在验收后删除,普通 Pod 的身份
|
||||||
|
声明保留。
|
||||||
|
|
||||||
Kata 阶段使用官方 4.1.0 `kata-deploy` chart 的短生命周期 `job` 模式,逐节点安装并
|
Kata 阶段使用官方 4.1.0 `kata-deploy` chart 的短生命周期 `job` 模式,逐节点安装并
|
||||||
重启 K3s。只启用 `kata-clh-runtime-rs`,不创建默认 `kata` 别名;该 handler 的
|
重启 K3s。只启用 `kata-clh-runtime-rs`,不创建默认 `kata` 别名;该 handler 的
|
||||||
`emptyDir` 固定使用 `block-plain`,为 Docker/BuildKit overlay2 与 kind 提供 guest
|
`emptyDir` 固定使用 `block-plain`,为 Docker/BuildKit overlay2 与 kind 提供 guest
|
||||||
内块设备文件系统。详细限制与上线验收见 `platform/sandbox-kata/README.md`。
|
内块设备文件系统。详细限制与上线验收见 `platform/sandbox-kata/README.md`。
|
||||||
|
|
||||||
|
Sandbox 的 ESO 通过独立 `auth/kubernetes-sandbox` 向 OpenBao 证明 ServiceAccount
|
||||||
|
身份,只能读取共享的 `kv/k8s/opensandbox-api`。它不保存 reviewer JWT 或长期 Bao token;相关
|
||||||
|
Terraform 与 Flux 边界见 `platform/sandbox-external-secrets/README.md`。
|
||||||
|
|
||||||
|
OpenSandbox 阶段固定官方源码 commit 与 umbrella chart `0.2.2`,只部署 controller、
|
||||||
|
ClusterIP server 和 CRD。API key 由 ESO 从 OpenBao 投影,明文不进入 Git。
|
||||||
|
|
||||||
## 监控边界
|
## 监控边界
|
||||||
|
|
||||||
这里只管理 sandbox LXC 内的 Kubernetes 监控,不负责 PVE 宿主监控。LXC 与宿主共享
|
这里只管理 sandbox LXC 内的 Kubernetes 监控,不负责 PVE 宿主监控。LXC 与宿主共享
|
||||||
|
|||||||
+3
-2
@@ -2,13 +2,14 @@
|
|||||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
metadata:
|
metadata:
|
||||||
name: opensandbox-pools
|
name: ci-runners
|
||||||
namespace: flux-system
|
namespace: flux-system
|
||||||
spec:
|
spec:
|
||||||
dependsOn:
|
dependsOn:
|
||||||
- name: opensandbox
|
- name: opensandbox
|
||||||
|
- name: spire-agents
|
||||||
interval: 10m
|
interval: 10m
|
||||||
path: ./platform/sandbox-opensandbox-pools
|
path: ./platform/sandbox-ci-runners
|
||||||
prune: true
|
prune: true
|
||||||
sourceRef:
|
sourceRef:
|
||||||
kind: GitRepository
|
kind: GitRepository
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||||
|
kind: Kustomization
|
||||||
|
metadata:
|
||||||
|
name: external-secrets-operator
|
||||||
|
namespace: flux-system
|
||||||
|
spec:
|
||||||
|
dependsOn:
|
||||||
|
- name: monitoring-operator
|
||||||
|
interval: 10m
|
||||||
|
path: ./platform/sandbox-external-secrets/operator
|
||||||
|
prune: true
|
||||||
|
sourceRef:
|
||||||
|
kind: GitRepository
|
||||||
|
name: flux-system
|
||||||
|
timeout: 10m
|
||||||
|
wait: true
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||||
|
kind: Kustomization
|
||||||
|
metadata:
|
||||||
|
name: external-secrets
|
||||||
|
namespace: flux-system
|
||||||
|
spec:
|
||||||
|
dependsOn:
|
||||||
|
- name: external-secrets-operator
|
||||||
|
interval: 10m
|
||||||
|
path: ./platform/sandbox-external-secrets/config
|
||||||
|
prune: true
|
||||||
|
sourceRef:
|
||||||
|
kind: GitRepository
|
||||||
|
name: flux-system
|
||||||
|
timeout: 10m
|
||||||
|
wait: true
|
||||||
@@ -6,13 +6,14 @@ metadata:
|
|||||||
namespace: flux-system
|
namespace: flux-system
|
||||||
spec:
|
spec:
|
||||||
dependsOn:
|
dependsOn:
|
||||||
|
- name: external-secrets
|
||||||
- name: kata
|
- name: kata
|
||||||
- name: spire-agents
|
- name: monitoring-operator
|
||||||
interval: 10m
|
interval: 10m
|
||||||
path: ./platform/sandbox-opensandbox
|
path: ./platform/sandbox-opensandbox
|
||||||
prune: true
|
prune: true
|
||||||
sourceRef:
|
sourceRef:
|
||||||
kind: GitRepository
|
kind: GitRepository
|
||||||
name: flux-system
|
name: flux-system
|
||||||
timeout: 20m
|
timeout: 15m
|
||||||
wait: true
|
wait: true
|
||||||
|
|||||||
@@ -7,5 +7,7 @@ resources:
|
|||||||
- apps/spire-bootstrap.yaml
|
- apps/spire-bootstrap.yaml
|
||||||
- apps/spire-agents.yaml
|
- apps/spire-agents.yaml
|
||||||
- apps/kata.yaml
|
- apps/kata.yaml
|
||||||
|
- apps/external-secrets-operator.yaml
|
||||||
|
- apps/external-secrets.yaml
|
||||||
- apps/opensandbox.yaml
|
- apps/opensandbox.yaml
|
||||||
- apps/opensandbox-pools.yaml
|
- apps/ci-runners.yaml
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ few things Terraform must not own.**
|
|||||||
| secrets engine mounts (`kv`, `pki`, `ssh-client-signer`) | the daemon, Raft, TLS files, systemd |
|
| secrets engine mounts (`kv`, `pki`, `ssh-client-signer`) | the daemon, Raft, TLS files, systemd |
|
||||||
| PKI role, issuing/CRL URLs, cluster paths, **ACME** | `bao operator init` / unseal (manual, PGP-wrapped) |
|
| PKI role, issuing/CRL URLs, cluster paths, **ACME** | `bao operator init` / unseal (manual, PGP-wrapped) |
|
||||||
| SSH signing role (`ai-agent`) | **PKI root CA + SSH CA signing key** |
|
| SSH signing role (`ai-agent`) | **PKI root CA + SSH CA signing key** |
|
||||||
| OIDC auth *mount* and *role* | OIDC **client secret** (`auth/oidc/config`) |
|
| OIDC/Kubernetes auth mount、config 与 role | OIDC **client secret** (`auth/oidc/config`) |
|
||||||
| all policies | snapshot token + script + systemd timer |
|
| all policies | snapshot token + script + systemd timer |
|
||||||
| | host-level CA trust distribution (`openbao_ssh_ca_trust`) |
|
| | host-level CA trust distribution (`openbao_ssh_ca_trust`) |
|
||||||
|
|
||||||
@@ -92,6 +92,13 @@ then `VAULT_ADDR`/`VAULT_TOKEN`), mirroring how `smtp-relay/terraform` uses
|
|||||||
native `openbao/openbao` provider is published only to the OpenTofu registry and
|
native `openbao/openbao` provider is published only to the OpenTofu registry and
|
||||||
cannot be resolved by the HashiCorp `terraform` CLI.
|
cannot be resolved by the HashiCorp `terraform` CLI.
|
||||||
|
|
||||||
|
Sandbox 集群使用独立的 `auth/kubernetes-sandbox`。其 API 地址、公开 Kubernetes CA、
|
||||||
|
ESO role 与只读 `kv/k8s/opensandbox-api` policy 全部由 Terraform 管理;CA 位于
|
||||||
|
`terraform/certs/sandbox-kubernetes-ca.crt`。集群重建并轮换 CA 后,先更新该文件并
|
||||||
|
apply,再让 Flux 恢复 ESO reconciliation。该 backend 不保存 reviewer JWT,而是使用
|
||||||
|
ESO 的短期登录 JWT 执行 TokenReview。该组资源已于 2026-09-18 apply,随后复验 plan
|
||||||
|
为 zero-diff。
|
||||||
|
|
||||||
## DNS
|
## DNS
|
||||||
|
|
||||||
`bao.ad.ddupan.top` is an **internal-only** name — not a public Cloudflare record and
|
`bao.ad.ddupan.top` is an **internal-only** name — not a public Cloudflare record and
|
||||||
|
|||||||
@@ -59,3 +59,33 @@ resource "vault_kubernetes_auth_backend_role" "external_secrets" {
|
|||||||
# in a long TTL and every extra hour is a longer-lived credential in memory.
|
# in a long TTL and every extra hour is a longer-lived credential in memory.
|
||||||
token_ttl = 3600
|
token_ttl = 3600
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# A Kubernetes auth mount can validate identities from only the API server it is
|
||||||
|
# configured against. The sandbox cluster therefore cannot reuse auth/kubernetes,
|
||||||
|
# whose TokenReview endpoint belongs to homelab.
|
||||||
|
resource "vault_auth_backend" "sandbox_kubernetes" {
|
||||||
|
type = "kubernetes"
|
||||||
|
path = "kubernetes-sandbox"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vault_kubernetes_auth_backend_config" "sandbox" {
|
||||||
|
backend = vault_auth_backend.sandbox_kubernetes.path
|
||||||
|
kubernetes_host = "https://10.60.0.13:6443"
|
||||||
|
kubernetes_ca_cert = file("${path.module}/certs/sandbox-kubernetes-ca.crt")
|
||||||
|
disable_local_ca_jwt = true
|
||||||
|
|
||||||
|
# Deliberately omit token_reviewer_jwt. OpenBao uses the login JWT for
|
||||||
|
# TokenReview; the sandbox external-secrets ServiceAccount is bound only to
|
||||||
|
# system:auth-delegator and all issued JWTs remain short-lived.
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "vault_kubernetes_auth_backend_role" "sandbox_external_secrets" {
|
||||||
|
backend = vault_auth_backend.sandbox_kubernetes.path
|
||||||
|
role_name = "external-secrets"
|
||||||
|
|
||||||
|
bound_service_account_names = ["external-secrets"]
|
||||||
|
bound_service_account_namespaces = ["external-secrets"]
|
||||||
|
|
||||||
|
token_policies = [vault_policy.sandbox_external_secrets.name]
|
||||||
|
token_ttl = 3600
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIBdjCCAR2gAwIBAgIBADAKBggqhkjOPQQDAjAjMSEwHwYDVQQDDBhrM3Mtc2Vy
|
||||||
|
dmVyLWNhQDE3ODk2NTI4NTcwHhcNMjYwOTE3MTI0NzM3WhcNMzYwOTE0MTI0NzM3
|
||||||
|
WjAjMSEwHwYDVQQDDBhrM3Mtc2VydmVyLWNhQDE3ODk2NTI4NTcwWTATBgcqhkjO
|
||||||
|
PQIBBggqhkjOPQMBBwNCAAR4SbqzTXZnlZdUPz7viN6+dYbB1Maw44Qiepn9r5XG
|
||||||
|
sOzkYkN8t1aG3Ugo8TqQ3xJaKkM89n1Rluj0vbOhiNajo0IwQDAOBgNVHQ8BAf8E
|
||||||
|
BAMCAqQwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUyLSGoKAKAJuiniuRdBLG
|
||||||
|
XYaDQC8wCgYIKoZIzj0EAwIDRwAwRAIgFkVzyUZexk/ynnxBEOg+3foJv3WKqAei
|
||||||
|
hTSRjO1gL0UCIFbBKR7BMrJJAgW3DJFeeBM+b+tTg93jNx55qZACbFOL
|
||||||
|
-----END CERTIFICATE-----
|
||||||
@@ -35,3 +35,10 @@ resource "vault_policy" "external_secrets" {
|
|||||||
name = "external-secrets"
|
name = "external-secrets"
|
||||||
policy = file("${path.module}/policies/external-secrets.hcl")
|
policy = file("${path.module}/policies/external-secrets.hcl")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# The sandbox cluster has its own Kubernetes auth backend and a deliberately
|
||||||
|
# narrower KV view than the homelab ESO instance.
|
||||||
|
resource "vault_policy" "sandbox_external_secrets" {
|
||||||
|
name = "sandbox-external-secrets"
|
||||||
|
policy = file("${path.module}/policies/sandbox-external-secrets.hcl")
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# Read only the shared OpenSandbox control-plane API key. The same Bao object is
|
||||||
|
# consumed by the server in sandbox and, later, by the scheduler in homelab.
|
||||||
|
path "kv/data/k8s/opensandbox-api" {
|
||||||
|
capabilities = ["read"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "kv/metadata/k8s/opensandbox-api" {
|
||||||
|
capabilities = ["read"]
|
||||||
|
}
|
||||||
@@ -83,6 +83,11 @@ vyos_postgresql_primary_address: "10.60.0.11"
|
|||||||
vyos_sandbox_k3s_api_address: "10.60.0.13"
|
vyos_sandbox_k3s_api_address: "10.60.0.13"
|
||||||
vyos_sandbox_k3s_api_interface: eth1
|
vyos_sandbox_k3s_api_interface: eth1
|
||||||
vyos_sandbox_k3s_api_port: 6443
|
vyos_sandbox_k3s_api_port: 6443
|
||||||
|
vyos_opensandbox_api_port: 8080
|
||||||
|
vyos_opensandbox_node_port: 30080
|
||||||
|
# Lifecycle create is synchronous and a cold Kata image pull can exceed the
|
||||||
|
# HAProxy 50-second default. Keep this below OpenSandbox's overall timeout.
|
||||||
|
vyos_opensandbox_api_timeout: 600
|
||||||
vyos_sandbox_k3s_servers:
|
vyos_sandbox_k3s_servers:
|
||||||
- name: sandbox1
|
- name: sandbox1
|
||||||
address: "10.60.0.11"
|
address: "10.60.0.11"
|
||||||
|
|||||||
@@ -15,6 +15,20 @@ set interfaces ethernet {{ i.iface }} address {{ i.address }}
|
|||||||
set interfaces ethernet {{ i.iface }} description '{{ i.description }}'
|
set interfaces ethernet {{ i.iface }} description '{{ i.description }}'
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
{# OpenSandbox stays on a NodePort; VyOS owns the stable routed frontend. #}
|
||||||
|
set load-balancing haproxy service opensandbox-api listen-address {{ vyos_sandbox_k3s_api_address }}
|
||||||
|
set load-balancing haproxy service opensandbox-api port {{ vyos_opensandbox_api_port }}
|
||||||
|
set load-balancing haproxy service opensandbox-api mode 'tcp'
|
||||||
|
set load-balancing haproxy service opensandbox-api backend 'opensandbox-api'
|
||||||
|
set load-balancing haproxy service opensandbox-api timeout client {{ vyos_opensandbox_api_timeout }}
|
||||||
|
set load-balancing haproxy backend opensandbox-api mode 'tcp'
|
||||||
|
set load-balancing haproxy backend opensandbox-api timeout server {{ vyos_opensandbox_api_timeout }}
|
||||||
|
{% for server in vyos_sandbox_k3s_servers %}
|
||||||
|
set load-balancing haproxy backend opensandbox-api server {{ server.name }} address {{ server.address }}
|
||||||
|
set load-balancing haproxy backend opensandbox-api server {{ server.name }} port {{ vyos_opensandbox_node_port }}
|
||||||
|
set load-balancing haproxy backend opensandbox-api server {{ server.name }} check
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
{# --- default route out; OSPF carries the rest --- #}
|
{# --- default route out; OSPF carries the rest --- #}
|
||||||
set protocols static route 0.0.0.0/0 next-hop {{ vyos_lan_gateway }}
|
set protocols static route 0.0.0.0/0 next-hop {{ vyos_lan_gateway }}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ Flux 管理以下 Kubernetes 资源:
|
|||||||
- Kata Containers 和 CI 专用的 `block-plain` RuntimeClass;
|
- Kata Containers 和 CI 专用的 `block-plain` RuntimeClass;
|
||||||
- SPIRE Agent、SPIFFE CSI Driver 与 workload identity 声明;
|
- SPIRE Agent、SPIFFE CSI Driver 与 workload identity 声明;
|
||||||
- vmagent、kube-state-metrics、kubelet/cAdvisor scrape 配置和告警;
|
- vmagent、kube-state-metrics、kubelet/cAdvisor scrape 配置和告警;
|
||||||
- OpenSandbox operator/server、`ci-pod` 与 `ci-vm` Pools。
|
- sandbox External Secrets Operator、OpenSandbox controller/server;CI Pool 与 runner
|
||||||
|
调度器由 runner 项目接入。
|
||||||
|
|
||||||
同一个对象只能有一个 owner。Ansible 不直接部署上述集群内 workload;Flux 不管理
|
同一个对象只能有一个 owner。Ansible 不直接部署上述集群内 workload;Flux 不管理
|
||||||
LXC、K3s datastore 或 K3s 本身。
|
LXC、K3s datastore 或 K3s 本身。
|
||||||
@@ -92,6 +93,13 @@ ansible-playbook site.yml
|
|||||||
ansible-playbook k3s.yml
|
ansible-playbook k3s.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
|
只 reconcile Flux controllers 与 root sync manifest(不触碰 LXC、PostgreSQL 或
|
||||||
|
K3s lifecycle):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible-playbook flux.yml
|
||||||
|
```
|
||||||
|
|
||||||
K3s 外部 datastore URI 由运行时 `SANDBOX_K3S_DB_PASSWORD` 生成,密码在 URI 中
|
K3s 外部 datastore URI 由运行时 `SANDBOX_K3S_DB_PASSWORD` 生成,密码在 URI 中
|
||||||
进行 URL 编码,最终仅持久化于节点 root 可读的 `/etc/rancher/k3s/config.yaml`
|
进行 URL 编码,最终仅持久化于节点 root 可读的 `/etc/rancher/k3s/config.yaml`
|
||||||
(mode `0600`)。首节点生成的 K3s join token 仅在同一次 Ansible run 内传给第二节点;
|
(mode `0600`)。首节点生成的 K3s join token 仅在同一次 Ansible run 内传给第二节点;
|
||||||
@@ -106,7 +114,9 @@ ansible-playbook verify.yml
|
|||||||
当前已经声明 LXC 生命周期、最小 OS baseline、PostgreSQL 和 K3s,包括系统级
|
当前已经声明 LXC 生命周期、最小 OS baseline、PostgreSQL 和 K3s,包括系统级
|
||||||
homelab CA trust。Flux `v2.9.5` controllers 与 root sync 也由 Ansible 通过 K3s
|
homelab CA trust。Flux `v2.9.5` controllers 与 root sync 也由 Ansible 通过 K3s
|
||||||
server manifests 管理;root 使用 homelab CA 访问公开 Gitea 仓库,不保存 Git token。
|
server manifests 管理;root 使用 homelab CA 访问公开 Gitea 仓库,不保存 Git token。
|
||||||
集群内 workload 由 `clusters/sandbox/` 分阶段纳入 Flux。
|
集群内 workload 由 `clusters/sandbox/` 分阶段纳入 Flux。root Kustomization 的健康检查
|
||||||
|
timeout 为 40 分钟,用于覆盖 Kata 等首次安装时会逐节点重启 K3s 的子
|
||||||
|
Kustomization;各子项仍保留自己的更短 timeout,故障会在对应子项先行暴露。
|
||||||
|
|
||||||
## SPIRE 跨集群 bootstrap
|
## SPIRE 跨集群 bootstrap
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
- name: Reconcile Flux controllers and root sync
|
||||||
|
hosts: sandbox1
|
||||||
|
gather_facts: false
|
||||||
|
roles:
|
||||||
|
- sandbox_flux
|
||||||
+1
-1
@@ -35,5 +35,5 @@ spec:
|
|||||||
sourceRef:
|
sourceRef:
|
||||||
kind: GitRepository
|
kind: GitRepository
|
||||||
name: flux-system
|
name: flux-system
|
||||||
timeout: 3m
|
timeout: 40m
|
||||||
wait: true
|
wait: true
|
||||||
|
|||||||
@@ -1,51 +1,40 @@
|
|||||||
# Gitea dynamic runner controller
|
# Gitea dynamic runner controller
|
||||||
|
|
||||||
此目录只管理 homelab 中的 controller 部署。controller、worker、Cloud Hypervisor
|
controller 接收 Gitea `workflow_job` webhook,对带 `[self-hosted, pod]` 或
|
||||||
launcher 和 guest runner 的源码与发布位于独立仓库
|
`[self-hosted, vm]` 的 queued job 直接调用 OpenSandbox Lifecycle API。链路不使用
|
||||||
`panxiao81/gitea-dynamic-runner`。
|
NATS、消息队列或平台侧 webhook worker。
|
||||||
|
|
||||||
当前 bootstrap controller 接收 Gitea `workflow_job` webhook,将 `[self-hosted, pod]` 和
|
|
||||||
`[self-hosted, vm]` 的 queued job 分别发布到 NATS。Pod worker 在本集群创建一次性
|
|
||||||
privileged host runner;Docker、BuildKit 和 kind 由 workflow 自行 setup。内部
|
|
||||||
endpoint:
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
http://dynamic-runner-controller.dynamic-runner.svc.cluster.local:8787/webhook
|
Gitea -> dynamic-runner-controller -> http://10.60.0.13:8080/v1/sandboxes
|
||||||
|
-> ci-pod / ci-vm Pool
|
||||||
```
|
```
|
||||||
|
|
||||||
OpenBao 路径:
|
`10.60.0.13:8080` 是 VyOS 上的内网 HAProxy frontend,后端是 sandbox 节点的
|
||||||
|
`30080` NodePort。它只依赖现有跨网段路由,不暴露公网,也不经过 Cloudflare
|
||||||
|
Tunnel。controller 自身的 `192.168.10.127:8787` 仅供 Gitea webhook 和 sandbox
|
||||||
|
通过一次性 nonce 领取 registration token。
|
||||||
|
|
||||||
- `kv/k8s/nats.ci_producer_password`:已有 NATS producer 密码。
|
## Secret 边界
|
||||||
- `kv/k8s/nats.ci_worker_password`:已有 NATS worker 密码。
|
|
||||||
- `kv/k8s/dynamic-runner.webhook_secret`:Gitea webhook HMAC secret。
|
|
||||||
- `kv/k8s/gitea-runner.token`:现有 instance runner registration token。
|
|
||||||
|
|
||||||
首期 controller 与 runner 镜像由 laptop 本机构建后导入 k3s containerd,作为 CI
|
homelab 的 `ExternalSecret/dynamic-runner` 从既有 `ClusterSecretStore/openbao` 读取:
|
||||||
发布链路建立前的 bootstrap。部署使用 `imagePullPolicy: Never`。正式发布 workflow
|
|
||||||
获得专用 SPIFFE ID 后,必须将 image 改为 zot digest 并移除本地导入步骤。
|
|
||||||
|
|
||||||
## 身份绑定
|
- `kv/k8s/opensandbox-api:api_key` -> `opensandbox-api-key`;
|
||||||
|
- `kv/k8s/dynamic-runner:webhook_secret` -> `webhook-secret`;
|
||||||
|
- `kv/k8s/gitea-runner:token` -> `token`。
|
||||||
|
|
||||||
queued webhook 只负责创建没有业务身份的 Pod。runner 实际领取任务后,Gitea 的
|
API key 以只读文件挂载,controller 通过 `OPEN-SANDBOX-API-KEY` header 使用。不要把
|
||||||
`in_progress` webhook 会携带实际 `runner_name`;controller 将 binding 消息发布到
|
key 复制到 Git、Lifecycle 请求、BatchSandbox 或 sandbox 集群 Secret。本目录不创建
|
||||||
NATS,Pod worker 再给对应 Pod 添加:
|
Bao token,也不拥有 sandbox 平台侧的 ESO/Bao Terraform。
|
||||||
|
|
||||||
```text
|
## 调度与身份
|
||||||
ci.ddupan.top/identity-bound=true
|
|
||||||
ci.ddupan.top/spiffe-path=<owner>/<repository>/<percent-encoded-job-name>
|
|
||||||
```
|
|
||||||
|
|
||||||
`ClusterSPIFFEID/gitea-dynamic-runner` 只匹配已经绑定的 Pod,并签发
|
Lifecycle 请求只按 `ci-pod` / `ci-vm` 选择 Pool,并携带稳定的
|
||||||
`spiffe://ddupan.top/ci/<owner>/<repository>/<job-name>`。runner 的 job-start hook 在
|
`spiffe://ddupan.top/ci/<owner>/<repository>/<task>`。job ID 只用于日志和诊断 metadata。
|
||||||
SVID 可用之前不会放行第一步,因此不能根据 queued 事件错配身份。
|
runner labels 始终以 `self-hosted` 开头。
|
||||||
|
|
||||||
每个 runner Pod 使用 `gitea-dynamic-runner` ServiceAccount。该 ServiceAccount 没有
|
registration token 通过 controller 内存中的单次 nonce URL 投递。成功领取后 nonce
|
||||||
Kubernetes API 权限;只有 `dynamic-runner-pod-worker` ServiceAccount 能在本 namespace
|
立即失效;沙箱结束、创建失败或超时时也会撤销。OpenSandbox DELETE 是最终的正常
|
||||||
create/get/patch/delete Pod。
|
回收路径,OpenSandbox timeout 是 controller 异常退出时的兜底。
|
||||||
|
|
||||||
长期实现将由兼容 Gitea RunnerService 的 scheduler 直接领取 task,再交给 Pod/VM
|
完整部署和验收步骤见
|
||||||
executor;届时删除 webhook、临时 runner 注册和 identity binding 消息。跟踪见
|
[`platform/sandbox-ci-runners/README.md`](../sandbox-ci-runners/README.md)。
|
||||||
`panxiao81/gitea-dynamic-runner` issue #7。
|
|
||||||
|
|
||||||
Gitea webhook 只订阅 `workflow_job`,content type 使用 JSON,secret 与 Bao 中值
|
|
||||||
一致。不要启用 `send_everything`,否则 controller 会收到无关仓库事件。
|
|
||||||
|
|||||||
@@ -40,19 +40,29 @@ spec:
|
|||||||
mountPath: /trust
|
mountPath: /trust
|
||||||
containers:
|
containers:
|
||||||
- name: controller
|
- name: controller
|
||||||
# Bootstrap import on laptop. Replace with a zot digest after the
|
image: zot.ad.ddupan.top/panxiao81/gitea-dynamic-runner-controller@sha256:b65a39a8adcdb2b886f0fb956fc6e6bae822bfbc1ff8c48213948e4c0a7d551a
|
||||||
# repository's image publishing workflow has a dedicated identity.
|
imagePullPolicy: IfNotPresent
|
||||||
image: gitea-dynamic-runner-controller:0.3.0-bootstrap
|
|
||||||
imagePullPolicy: Never
|
|
||||||
env:
|
env:
|
||||||
- name: NATS_URL
|
- name: NATS_URL
|
||||||
value: tls://nats.ad.ddupan.top:4222
|
value: tls://nats.ad.ddupan.top:4222
|
||||||
- name: NATS_CA_FILE
|
- name: NATS_CA_FILE
|
||||||
value: /run/trust/ca.pem
|
value: /run/trust/ca.pem
|
||||||
- name: NATS_PASSWORD_FILE
|
- name: NATS_PRODUCER_PASSWORD_FILE
|
||||||
value: /run/dynamic-runner-secrets/nats-password
|
value: /run/dynamic-runner-secrets/nats-password
|
||||||
|
- name: NATS_WORKER_PASSWORD_FILE
|
||||||
|
value: /run/dynamic-runner-secrets/nats-worker-password
|
||||||
|
- name: POD_CONSUMER_ENABLED
|
||||||
|
value: "true"
|
||||||
- name: WEBHOOK_SECRET_FILE
|
- name: WEBHOOK_SECRET_FILE
|
||||||
value: /run/dynamic-runner-secrets/webhook-secret
|
value: /run/dynamic-runner-secrets/webhook-secret
|
||||||
|
- name: REGISTRATION_TOKEN_FILE
|
||||||
|
value: /run/dynamic-runner-secrets/token
|
||||||
|
- name: OPENSANDBOX_API
|
||||||
|
value: http://10.60.0.13:8080
|
||||||
|
- name: OPENSANDBOX_API_KEY_FILE
|
||||||
|
value: /run/dynamic-runner-secrets/opensandbox-api-key
|
||||||
|
- name: RUNNER_TOKEN_BASE_URL
|
||||||
|
value: http://192.168.10.127:8787/token
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
containerPort: 8787
|
containerPort: 8787
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ spec:
|
|||||||
remoteRef:
|
remoteRef:
|
||||||
key: k8s/nats
|
key: k8s/nats
|
||||||
property: ci_worker_password
|
property: ci_worker_password
|
||||||
|
- secretKey: opensandbox-api-key
|
||||||
|
remoteRef:
|
||||||
|
key: k8s/opensandbox-api
|
||||||
|
property: api_key
|
||||||
- secretKey: webhook-secret
|
- secretKey: webhook-secret
|
||||||
remoteRef:
|
remoteRef:
|
||||||
key: k8s/dynamic-runner
|
key: k8s/dynamic-runner
|
||||||
|
|||||||
@@ -6,5 +6,4 @@ resources:
|
|||||||
- rbac.yaml
|
- rbac.yaml
|
||||||
- clusterspiffeid.yaml
|
- clusterspiffeid.yaml
|
||||||
- deployment.yaml
|
- deployment.yaml
|
||||||
- pod-worker-deployment.yaml
|
|
||||||
- service.yaml
|
- service.yaml
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ metadata:
|
|||||||
name: dynamic-runner-controller
|
name: dynamic-runner-controller
|
||||||
namespace: dynamic-runner
|
namespace: dynamic-runner
|
||||||
spec:
|
spec:
|
||||||
|
type: LoadBalancer
|
||||||
|
loadBalancerIP: 192.168.10.127
|
||||||
selector:
|
selector:
|
||||||
app.kubernetes.io/name: dynamic-runner-controller
|
app.kubernetes.io/name: dynamic-runner-controller
|
||||||
ports:
|
ports:
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
# OpenSandbox Gitea runner Pools
|
||||||
|
|
||||||
|
本目录部署 `ci-vm` 和 `ci-pod` 两个零预热 Pool、sandbox 内的 SPIFFE identity
|
||||||
|
controller,以及仅供内网 VyOS 转发的 OpenSandbox NodePort。`ci-vm` 使用
|
||||||
|
`kata-clh-runtime-rs`,`ci-pod` 使用默认 runtime;两者均为单任务、用后删除。
|
||||||
|
|
||||||
|
Pool 中 task-executor 接收 Lifecycle API 下发的进程环境。guest-local SPIRE Agent 用
|
||||||
|
Pod-bound PSAT 向中央 SPIRE 注册;identity controller 从 BatchSandbox allocation
|
||||||
|
取得真实 Pod UID,再创建精确的 `ClusterStaticEntry`。runner 只有拿到请求中的完整
|
||||||
|
repository/task SVID 后才领取一次性 Gitea registration token。
|
||||||
|
|
||||||
|
这些 `ClusterStaticEntry` 位于 sandbox 集群,由 central SPIRE Server 内的
|
||||||
|
`spire-controller-manager-sandbox` 通过受限 external kubeconfig reconcile。必须在
|
||||||
|
`platform/spire/values.yaml` 显式启用 external controller-manager 的
|
||||||
|
`reconcile.clusterStaticEntries`(chart 默认关闭);仅看到 CR 存在但没有 status,不算
|
||||||
|
身份链路就绪。
|
||||||
|
|
||||||
|
## 部署依赖
|
||||||
|
|
||||||
|
- OpenSandbox chart 和 CRD 已 Ready;
|
||||||
|
- RuntimeClass `kata-clh-runtime-rs` 已存在;
|
||||||
|
- 中央 SPIRE 已发布 `ConfigMap/opensandbox/spire-bundle-pem`;
|
||||||
|
- VyOS `10.60.0.13:8080` 转发 sandbox1/2 的 NodePort `30080`;
|
||||||
|
- runner/controller 镜像均使用 Zot digest,而不是可变 tag。
|
||||||
|
|
||||||
|
本目录不读取 OpenBao,也不修改 OpenSandbox 平台侧 ExternalSecret、ClusterSecretStore
|
||||||
|
或 Bao policy。OpenSandbox API key 只存在于平台 server Secret 和 homelab controller
|
||||||
|
Secret,两边由各自身份读取同一 Bao 资源。
|
||||||
|
|
||||||
|
## 上线验收
|
||||||
|
|
||||||
|
先确认 Secret 和 API 认证,命令不得输出 key:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl -n dynamic-runner wait externalsecret/dynamic-runner --for=condition=Ready --timeout=2m
|
||||||
|
kubectl -n dynamic-runner exec deploy/dynamic-runner-controller -- \
|
||||||
|
wget -qO- http://10.60.0.13:8080/health
|
||||||
|
```
|
||||||
|
|
||||||
|
然后触发一个 `runs-on: [self-hosted, vm]` 的最小 workflow,并同时观察:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl -n dynamic-runner logs deploy/dynamic-runner-controller -f
|
||||||
|
kubectl -n opensandbox get pool,batchsandbox,pod -w
|
||||||
|
kubectl get clusterstaticentry -l app.kubernetes.io/component=opensandbox-identity -w
|
||||||
|
kubectl -n opensandbox logs deploy/opensandbox-identity -f
|
||||||
|
```
|
||||||
|
|
||||||
|
合格证据必须同时包含:
|
||||||
|
|
||||||
|
1. Lifecycle create 成功并选择 `ci-vm`;
|
||||||
|
2. 分配 Pod 的 `runtimeClassName` 为 `kata-clh-runtime-rs`;
|
||||||
|
3. entry 的 parent ID 包含该 Pod 的 UID,SPIFFE ID 使用 repository/task;
|
||||||
|
4. Gitea 显示临时 runner 带 `self-hosted,vm` labels 并完成真实任务;
|
||||||
|
5. 任务后 BatchSandbox、Pod、ClusterStaticEntry 和临时 runner 均消失。
|
||||||
|
|
||||||
|
清理超时对象时只调用 Lifecycle DELETE,不直接删除 Pool Pod。若 controller 已不可用,
|
||||||
|
可从 OpenSandbox API 按 metadata 定位 sandbox 后执行 DELETE;不要绕过 API 伪造状态。
|
||||||
|
|
||||||
|
## 故障定位
|
||||||
|
|
||||||
|
- `401`:检查 homelab ExternalSecret Ready 和文件挂载,不打印 Secret;
|
||||||
|
- `PoolCapacityExhausted`:检查 `ci-vm` 的 `poolMax` 及残留 BatchSandbox;
|
||||||
|
- runner 等待 SVID:核对 allocation Pod UID、ClusterStaticEntry parentID、guest Agent 日志;
|
||||||
|
- runner 等待 token:核对 `192.168.10.127:8787` 的 sandbox 到 homelab 路由;
|
||||||
|
- Docker 任务失败:检查 `docker` sidecar 和 `/run/docker/docker.sock` 的 group 2000。
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: gitea-ci-spire-agent
|
||||||
|
namespace: opensandbox
|
||||||
|
data:
|
||||||
|
agent.conf: |
|
||||||
|
agent {
|
||||||
|
data_dir = "/run/spire/data"
|
||||||
|
log_level = "INFO"
|
||||||
|
server_address = "spire-server.ad.ddupan.top"
|
||||||
|
server_port = "8081"
|
||||||
|
socket_path = "/run/spire/agent-sockets/spire-agent.sock"
|
||||||
|
trust_bundle_path = "/run/spire/bundle/bundle.pem"
|
||||||
|
trust_domain = "ddupan.top"
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
NodeAttestor "k8s_psat" {
|
||||||
|
plugin_data {
|
||||||
|
cluster = "sandbox-kata"
|
||||||
|
token_path = "/run/spire/tokens/token"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
KeyManager "memory" {
|
||||||
|
plugin_data {}
|
||||||
|
}
|
||||||
|
WorkloadAttestor "unix" {
|
||||||
|
plugin_data {}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: opensandbox-identity
|
||||||
|
namespace: opensandbox
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: opensandbox-identity
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: opensandbox-identity
|
||||||
|
spec:
|
||||||
|
serviceAccountName: opensandbox-identity
|
||||||
|
containers:
|
||||||
|
- name: controller
|
||||||
|
image: zot.ad.ddupan.top/panxiao81/gitea-dynamic-runner-controller@sha256:dfbfaf2a7aa5951d1dc4e7f941a8cd05ceb4a860ac1ab23eb8be234861edcb55
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
command: [/venv/bin/gitea-dynamic-runner-opensandbox-identity]
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 10m
|
||||||
|
memory: 32Mi
|
||||||
|
limits:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 96Mi
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop: [ALL]
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 65532
|
||||||
|
runAsGroup: 65532
|
||||||
|
seccompProfile:
|
||||||
|
type: RuntimeDefault
|
||||||
|
securityContext:
|
||||||
|
seccompProfile:
|
||||||
|
type: RuntimeDefault
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- service.yaml
|
||||||
|
- agent-config.yaml
|
||||||
|
- rbac.yaml
|
||||||
|
- identity-controller.yaml
|
||||||
|
- pools.yaml
|
||||||
@@ -0,0 +1,301 @@
|
|||||||
|
---
|
||||||
|
apiVersion: sandbox.opensandbox.io/v1alpha1
|
||||||
|
kind: Pool
|
||||||
|
metadata:
|
||||||
|
name: ci-vm
|
||||||
|
namespace: opensandbox
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: gitea-ci-vm
|
||||||
|
app.kubernetes.io/component: runner-pool
|
||||||
|
spec:
|
||||||
|
capacitySpec:
|
||||||
|
bufferMax: 0
|
||||||
|
bufferMin: 0
|
||||||
|
poolMax: 2
|
||||||
|
poolMin: 0
|
||||||
|
recycleStrategy:
|
||||||
|
type: Delete
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: gitea-ci-vm
|
||||||
|
ci.ddupan.top/backend: vm
|
||||||
|
spec:
|
||||||
|
runtimeClassName: kata-clh-runtime-rs
|
||||||
|
serviceAccountName: gitea-ci
|
||||||
|
restartPolicy: Never
|
||||||
|
terminationGracePeriodSeconds: 30
|
||||||
|
shareProcessNamespace: true
|
||||||
|
securityContext:
|
||||||
|
fsGroup: 2000
|
||||||
|
fsGroupChangePolicy: OnRootMismatch
|
||||||
|
initContainers:
|
||||||
|
- name: task-executor-installer
|
||||||
|
image: sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/task-executor:v0.1.0
|
||||||
|
command: [/bin/sh, -c]
|
||||||
|
args:
|
||||||
|
- cp /workspace/server /opt/opensandbox/task-executor && chmod 0755 /opt/opensandbox/task-executor
|
||||||
|
volumeMounts:
|
||||||
|
- name: opensandbox-bin
|
||||||
|
mountPath: /opt/opensandbox
|
||||||
|
- name: execd-installer
|
||||||
|
image: sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/execd:v1.0.22
|
||||||
|
command: [/bin/sh, -c]
|
||||||
|
args:
|
||||||
|
- cp ./execd /opt/opensandbox/execd && cp ./bootstrap.sh /opt/opensandbox/bootstrap.sh && chmod 0755 /opt/opensandbox/execd /opt/opensandbox/bootstrap.sh
|
||||||
|
volumeMounts:
|
||||||
|
- name: opensandbox-bin
|
||||||
|
mountPath: /opt/opensandbox
|
||||||
|
containers:
|
||||||
|
- name: sandbox
|
||||||
|
image: zot.ad.ddupan.top/panxiao81/gitea-dynamic-runner-runner@sha256:a45875fd2d0e67429b0b7bc3914735581669c705bb4e1a05d712134d2bceb86f
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
command: [/opt/opensandbox/task-executor]
|
||||||
|
args:
|
||||||
|
- -listen-addr=0.0.0.0:5758
|
||||||
|
- -log-dir=/tmp
|
||||||
|
- -data-dir=/tmp/tasks
|
||||||
|
env:
|
||||||
|
- name: SANDBOX_MAIN_CONTAINER
|
||||||
|
value: sandbox
|
||||||
|
- name: EXECD_ENVS
|
||||||
|
value: /opt/opensandbox/.env
|
||||||
|
- name: EXECD
|
||||||
|
value: /opt/opensandbox/execd
|
||||||
|
- name: GITEA_INSTANCE_URL
|
||||||
|
value: https://git.ddupan.top
|
||||||
|
- name: HOME
|
||||||
|
value: /data
|
||||||
|
- name: DOCKER_HOST
|
||||||
|
value: unix:///run/docker/docker.sock
|
||||||
|
ports:
|
||||||
|
- name: task-executor
|
||||||
|
containerPort: 5758
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop: [ALL]
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 2000
|
||||||
|
runAsGroup: 2000
|
||||||
|
volumeMounts:
|
||||||
|
- name: opensandbox-bin
|
||||||
|
mountPath: /opt/opensandbox
|
||||||
|
- name: runner-data
|
||||||
|
mountPath: /data
|
||||||
|
- name: docker-socket
|
||||||
|
mountPath: /run/docker
|
||||||
|
- name: spire-socket
|
||||||
|
mountPath: /run/spire/agent-sockets
|
||||||
|
- name: spire-agent
|
||||||
|
image: ghcr.io/spiffe/spire-agent:1.15.3@sha256:41b0dcd8b258a69db9e2768292a060766fb76fd866e4bc925849981ea1b825ff
|
||||||
|
args: [-config, /run/spire/config/agent.conf]
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop: [ALL]
|
||||||
|
volumeMounts:
|
||||||
|
- name: spire-config
|
||||||
|
mountPath: /run/spire/config
|
||||||
|
readOnly: true
|
||||||
|
- name: spire-bundle
|
||||||
|
mountPath: /run/spire/bundle
|
||||||
|
readOnly: true
|
||||||
|
- name: spire-token
|
||||||
|
mountPath: /run/spire/tokens
|
||||||
|
readOnly: true
|
||||||
|
- name: spire-data
|
||||||
|
mountPath: /run/spire/data
|
||||||
|
- name: spire-socket
|
||||||
|
mountPath: /run/spire/agent-sockets
|
||||||
|
- name: docker
|
||||||
|
image: docker.io/library/docker:29.1.5-dind
|
||||||
|
command: [/bin/sh, -c]
|
||||||
|
args:
|
||||||
|
- test -e /dev/kmsg || mknod /dev/kmsg c 1 11; exec dockerd --host=unix:///run/docker/docker.sock --group=2000 --storage-driver=overlay2
|
||||||
|
securityContext:
|
||||||
|
privileged: true
|
||||||
|
volumeMounts:
|
||||||
|
- name: docker-socket
|
||||||
|
mountPath: /run/docker
|
||||||
|
- name: docker-data
|
||||||
|
mountPath: /var/lib/docker
|
||||||
|
volumes:
|
||||||
|
- name: opensandbox-bin
|
||||||
|
emptyDir: {}
|
||||||
|
- name: runner-data
|
||||||
|
emptyDir: {}
|
||||||
|
- name: docker-data
|
||||||
|
emptyDir: {}
|
||||||
|
- name: docker-socket
|
||||||
|
emptyDir:
|
||||||
|
medium: Memory
|
||||||
|
- name: spire-data
|
||||||
|
emptyDir:
|
||||||
|
medium: Memory
|
||||||
|
- name: spire-socket
|
||||||
|
emptyDir:
|
||||||
|
medium: Memory
|
||||||
|
- name: spire-config
|
||||||
|
configMap:
|
||||||
|
name: gitea-ci-spire-agent
|
||||||
|
- name: spire-bundle
|
||||||
|
configMap:
|
||||||
|
name: spire-bundle-pem
|
||||||
|
- name: spire-token
|
||||||
|
projected:
|
||||||
|
sources:
|
||||||
|
- serviceAccountToken:
|
||||||
|
audience: spire-server
|
||||||
|
expirationSeconds: 3600
|
||||||
|
path: token
|
||||||
|
---
|
||||||
|
apiVersion: sandbox.opensandbox.io/v1alpha1
|
||||||
|
kind: Pool
|
||||||
|
metadata:
|
||||||
|
name: ci-pod
|
||||||
|
namespace: opensandbox
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: gitea-ci-pod
|
||||||
|
app.kubernetes.io/component: runner-pool
|
||||||
|
spec:
|
||||||
|
capacitySpec:
|
||||||
|
bufferMax: 0
|
||||||
|
bufferMin: 0
|
||||||
|
poolMax: 4
|
||||||
|
poolMin: 0
|
||||||
|
recycleStrategy:
|
||||||
|
type: Delete
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: gitea-ci-pod
|
||||||
|
ci.ddupan.top/backend: pod
|
||||||
|
spec:
|
||||||
|
serviceAccountName: gitea-ci
|
||||||
|
restartPolicy: Never
|
||||||
|
terminationGracePeriodSeconds: 30
|
||||||
|
shareProcessNamespace: true
|
||||||
|
securityContext:
|
||||||
|
fsGroup: 2000
|
||||||
|
fsGroupChangePolicy: OnRootMismatch
|
||||||
|
initContainers:
|
||||||
|
- name: task-executor-installer
|
||||||
|
image: sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/task-executor:v0.1.0
|
||||||
|
command: [/bin/sh, -c]
|
||||||
|
args:
|
||||||
|
- cp /workspace/server /opt/opensandbox/task-executor && chmod 0755 /opt/opensandbox/task-executor
|
||||||
|
volumeMounts:
|
||||||
|
- name: opensandbox-bin
|
||||||
|
mountPath: /opt/opensandbox
|
||||||
|
- name: execd-installer
|
||||||
|
image: sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/execd:v1.0.22
|
||||||
|
command: [/bin/sh, -c]
|
||||||
|
args:
|
||||||
|
- cp ./execd /opt/opensandbox/execd && cp ./bootstrap.sh /opt/opensandbox/bootstrap.sh && chmod 0755 /opt/opensandbox/execd /opt/opensandbox/bootstrap.sh
|
||||||
|
volumeMounts:
|
||||||
|
- name: opensandbox-bin
|
||||||
|
mountPath: /opt/opensandbox
|
||||||
|
containers:
|
||||||
|
- name: sandbox
|
||||||
|
image: zot.ad.ddupan.top/panxiao81/gitea-dynamic-runner-runner@sha256:a45875fd2d0e67429b0b7bc3914735581669c705bb4e1a05d712134d2bceb86f
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
command: [/opt/opensandbox/task-executor]
|
||||||
|
args:
|
||||||
|
- -listen-addr=0.0.0.0:5758
|
||||||
|
- -log-dir=/tmp
|
||||||
|
- -data-dir=/tmp/tasks
|
||||||
|
env:
|
||||||
|
- name: SANDBOX_MAIN_CONTAINER
|
||||||
|
value: sandbox
|
||||||
|
- name: EXECD_ENVS
|
||||||
|
value: /opt/opensandbox/.env
|
||||||
|
- name: EXECD
|
||||||
|
value: /opt/opensandbox/execd
|
||||||
|
- name: GITEA_INSTANCE_URL
|
||||||
|
value: https://git.ddupan.top
|
||||||
|
- name: HOME
|
||||||
|
value: /data
|
||||||
|
- name: DOCKER_HOST
|
||||||
|
value: unix:///run/docker/docker.sock
|
||||||
|
ports:
|
||||||
|
- name: task-executor
|
||||||
|
containerPort: 5758
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop: [ALL]
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 2000
|
||||||
|
runAsGroup: 2000
|
||||||
|
volumeMounts:
|
||||||
|
- name: opensandbox-bin
|
||||||
|
mountPath: /opt/opensandbox
|
||||||
|
- name: runner-data
|
||||||
|
mountPath: /data
|
||||||
|
- name: docker-socket
|
||||||
|
mountPath: /run/docker
|
||||||
|
- name: spire-socket
|
||||||
|
mountPath: /run/spire/agent-sockets
|
||||||
|
- name: spire-agent
|
||||||
|
image: ghcr.io/spiffe/spire-agent:1.15.3@sha256:41b0dcd8b258a69db9e2768292a060766fb76fd866e4bc925849981ea1b825ff
|
||||||
|
args: [-config, /run/spire/config/agent.conf]
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop: [ALL]
|
||||||
|
volumeMounts:
|
||||||
|
- name: spire-config
|
||||||
|
mountPath: /run/spire/config
|
||||||
|
readOnly: true
|
||||||
|
- name: spire-bundle
|
||||||
|
mountPath: /run/spire/bundle
|
||||||
|
readOnly: true
|
||||||
|
- name: spire-token
|
||||||
|
mountPath: /run/spire/tokens
|
||||||
|
readOnly: true
|
||||||
|
- name: spire-data
|
||||||
|
mountPath: /run/spire/data
|
||||||
|
- name: spire-socket
|
||||||
|
mountPath: /run/spire/agent-sockets
|
||||||
|
- name: docker
|
||||||
|
image: docker.io/library/docker:29.1.5-dind
|
||||||
|
command: [/bin/sh, -c]
|
||||||
|
args:
|
||||||
|
- test -e /dev/kmsg || mknod /dev/kmsg c 1 11; exec dockerd --host=unix:///run/docker/docker.sock --group=2000 --storage-driver=overlay2
|
||||||
|
securityContext:
|
||||||
|
privileged: true
|
||||||
|
volumeMounts:
|
||||||
|
- name: docker-socket
|
||||||
|
mountPath: /run/docker
|
||||||
|
- name: docker-data
|
||||||
|
mountPath: /var/lib/docker
|
||||||
|
volumes:
|
||||||
|
- name: opensandbox-bin
|
||||||
|
emptyDir: {}
|
||||||
|
- name: runner-data
|
||||||
|
emptyDir: {}
|
||||||
|
- name: docker-data
|
||||||
|
emptyDir: {}
|
||||||
|
- name: docker-socket
|
||||||
|
emptyDir:
|
||||||
|
medium: Memory
|
||||||
|
- name: spire-data
|
||||||
|
emptyDir:
|
||||||
|
medium: Memory
|
||||||
|
- name: spire-socket
|
||||||
|
emptyDir:
|
||||||
|
medium: Memory
|
||||||
|
- name: spire-config
|
||||||
|
configMap:
|
||||||
|
name: gitea-ci-spire-agent
|
||||||
|
- name: spire-bundle
|
||||||
|
configMap:
|
||||||
|
name: spire-bundle-pem
|
||||||
|
- name: spire-token
|
||||||
|
projected:
|
||||||
|
sources:
|
||||||
|
- serviceAccountToken:
|
||||||
|
audience: spire-server
|
||||||
|
expirationSeconds: 3600
|
||||||
|
path: token
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: gitea-ci
|
||||||
|
namespace: opensandbox
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: opensandbox-identity
|
||||||
|
namespace: opensandbox
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: opensandbox-identity
|
||||||
|
namespace: opensandbox
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: [pods]
|
||||||
|
verbs: [get, list, watch]
|
||||||
|
- apiGroups: [sandbox.opensandbox.io]
|
||||||
|
resources: [batchsandboxes]
|
||||||
|
verbs: [get, list, watch]
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: RoleBinding
|
||||||
|
metadata:
|
||||||
|
name: opensandbox-identity
|
||||||
|
namespace: opensandbox
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: opensandbox-identity
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: opensandbox-identity
|
||||||
|
namespace: opensandbox
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: opensandbox-identity
|
||||||
|
rules:
|
||||||
|
- apiGroups: [spire.spiffe.io]
|
||||||
|
resources: [clusterstaticentries]
|
||||||
|
verbs: [create, delete, get, list, watch]
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: opensandbox-identity
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: opensandbox-identity
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: opensandbox-identity
|
||||||
|
namespace: opensandbox
|
||||||
|
---
|
||||||
|
# The central SPIRE external controller uses this existing sandbox credential
|
||||||
|
# to publish a PEM bundle for guest-local Agents. It cannot read Secrets here.
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: spire-runner-bundle-publisher
|
||||||
|
namespace: opensandbox
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: [configmaps]
|
||||||
|
verbs: [create, delete, get, list, patch, update, watch]
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: RoleBinding
|
||||||
|
metadata:
|
||||||
|
name: spire-runner-bundle-publisher
|
||||||
|
namespace: opensandbox
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: spire-runner-bundle-publisher
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: spire-controller-manager
|
||||||
|
namespace: spire-system
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: opensandbox-server-internal
|
||||||
|
namespace: opensandbox-system
|
||||||
|
spec:
|
||||||
|
type: NodePort
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/instance: opensandbox
|
||||||
|
app.kubernetes.io/name: opensandbox-server
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 80
|
||||||
|
targetPort: http
|
||||||
|
nodePort: 30080
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
# Sandbox External Secrets Operator
|
||||||
|
|
||||||
|
本目录在 sandbox 集群部署独立的 External Secrets Operator `2.8.0`,并通过
|
||||||
|
`ClusterSecretStore/openbao` 读取 OpenBao KV v2 中共享的 OpenSandbox API key。它不复用
|
||||||
|
homelab 集群的 ESO Pod、ServiceAccount 或 Kubernetes auth backend。
|
||||||
|
|
||||||
|
## 当前状态
|
||||||
|
|
||||||
|
- OpenBao `auth/kubernetes-sandbox`、backend config、`external-secrets` role 与
|
||||||
|
`sandbox-external-secrets` policy 已于 2026-09-18 由 Terraform 创建;apply 后 plan
|
||||||
|
为 zero-diff;
|
||||||
|
- `kv/k8s/opensandbox-api` 已由本机 `spiffe://ddupan.top/dev/panxiao81` 身份生成并写入,
|
||||||
|
值未输出或落盘;
|
||||||
|
- sandbox ESO operator、`ClusterSecretStore/openbao` 与 OpenSandbox `ExternalSecret`
|
||||||
|
由 Flux 管理;
|
||||||
|
- 线上 `ClusterSecretStore/openbao` 为 `Valid/Ready`,`ExternalSecret/opensandbox-api-key`
|
||||||
|
为 `SecretSynced/Ready`;
|
||||||
|
- OpenSandbox 已切换到 API key:无 key 请求返回 `401`,正确 key 请求返回 `200`;
|
||||||
|
- homelab runner 对同一 key 的投影不在本目录,留给 runner 项目管理。
|
||||||
|
|
||||||
|
OpenBao 的 `auth/kubernetes-sandbox`、对应 role、policy、sandbox API 地址与公开 CA
|
||||||
|
完全由 `infrastructure/openbao/terraform/` 管理。CA 文件提交到 Git 是刻意设计:CA
|
||||||
|
是公开信任材料,版本化后集群重建造成的 trust root 变化会产生可审计的 Terraform diff。
|
||||||
|
|
||||||
|
ESO 使用 TokenRequest 生成短期 ServiceAccount JWT。OpenBao 未配置长期
|
||||||
|
`token_reviewer_jwt`,而是使用登录 JWT 调用 sandbox TokenReview;因此
|
||||||
|
`external-secrets` ServiceAccount 仅额外绑定内建 `system:auth-delegator`。
|
||||||
|
|
||||||
|
## 重建顺序
|
||||||
|
|
||||||
|
1. 在 OpenBao 写入 OpenSandbox API key:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
openssl rand -hex 32 | bao kv put kv/k8s/opensandbox-api api_key=-
|
||||||
|
```
|
||||||
|
|
||||||
|
2. 在 `infrastructure/openbao/terraform` 执行 `terraform plan` 和 `terraform apply`,
|
||||||
|
创建 `kubernetes-sandbox` auth mount、backend config、role 与只允许读取
|
||||||
|
`kv/k8s/opensandbox-api` 的最小权限 policy。
|
||||||
|
3. 合并 Flux 变更。依次等待 `flux-system/external-secrets-operator`、
|
||||||
|
`flux-system/external-secrets` Ready,再等待 `flux-system/opensandbox` 滚动完成。
|
||||||
|
|
||||||
|
operator 与配置拆成两个 Flux Kustomization,确保全新集群先安装 CRD,再声明
|
||||||
|
`ClusterSecretStore`;不要为了减少目录而把两层重新合并。
|
||||||
|
|
||||||
|
## 验收
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get clustersecretstore openbao
|
||||||
|
kubectl -n opensandbox-system get externalsecret opensandbox-api-key
|
||||||
|
kubectl -n opensandbox-system get secret opensandbox-api-key
|
||||||
|
```
|
||||||
|
|
||||||
|
只检查 Secret 是否存在及 key 名,不输出 `data`。`ClusterSecretStore` 或
|
||||||
|
`ExternalSecret` 不 Ready 时,先检查 `auth/kubernetes-sandbox`,不要临时创建静态
|
||||||
|
Bao token Secret。
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: sandbox-external-secrets-token-review
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: system:auth-delegator
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: external-secrets
|
||||||
|
namespace: external-secrets
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
apiVersion: external-secrets.io/v1
|
||||||
|
kind: ClusterSecretStore
|
||||||
|
metadata:
|
||||||
|
name: openbao
|
||||||
|
spec:
|
||||||
|
provider:
|
||||||
|
vault:
|
||||||
|
server: https://bao.ad.ddupan.top:8200
|
||||||
|
path: kv
|
||||||
|
version: v2
|
||||||
|
auth:
|
||||||
|
kubernetes:
|
||||||
|
mountPath: kubernetes-sandbox
|
||||||
|
role: external-secrets
|
||||||
|
serviceAccountRef:
|
||||||
|
name: external-secrets
|
||||||
|
namespace: external-secrets
|
||||||
+3
-1
@@ -1,4 +1,6 @@
|
|||||||
|
---
|
||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
resources:
|
resources:
|
||||||
- pools.yaml
|
- auth-delegator.yaml
|
||||||
|
- clustersecretstore.yaml
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
---
|
||||||
|
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||||
|
kind: HelmRelease
|
||||||
|
metadata:
|
||||||
|
name: external-secrets
|
||||||
|
namespace: external-secrets
|
||||||
|
spec:
|
||||||
|
chart:
|
||||||
|
spec:
|
||||||
|
chart: external-secrets
|
||||||
|
interval: 1h
|
||||||
|
sourceRef:
|
||||||
|
kind: HelmRepository
|
||||||
|
name: external-secrets
|
||||||
|
version: 2.8.0
|
||||||
|
driftDetection:
|
||||||
|
mode: enabled
|
||||||
|
install:
|
||||||
|
crds: CreateReplace
|
||||||
|
strategy:
|
||||||
|
name: RetryOnFailure
|
||||||
|
retryInterval: 5m
|
||||||
|
interval: 30m
|
||||||
|
releaseName: external-secrets
|
||||||
|
targetNamespace: external-secrets
|
||||||
|
timeout: 10m
|
||||||
|
upgrade:
|
||||||
|
crds: CreateReplace
|
||||||
|
strategy:
|
||||||
|
name: RetryOnFailure
|
||||||
|
retryInterval: 5m
|
||||||
|
valuesFrom:
|
||||||
|
- kind: ConfigMap
|
||||||
|
name: external-secrets-values
|
||||||
|
valuesKey: values.yaml
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- namespace.yaml
|
||||||
|
- repository.yaml
|
||||||
|
- values.yaml
|
||||||
|
- helmrelease.yaml
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: external-secrets
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
apiVersion: source.toolkit.fluxcd.io/v1
|
||||||
|
kind: HelmRepository
|
||||||
|
metadata:
|
||||||
|
name: external-secrets
|
||||||
|
namespace: external-secrets
|
||||||
|
spec:
|
||||||
|
interval: 1h
|
||||||
|
url: https://charts.external-secrets.io
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: external-secrets-values
|
||||||
|
namespace: external-secrets
|
||||||
|
data:
|
||||||
|
values.yaml: |
|
||||||
|
replicaCount: 1
|
||||||
|
|
||||||
|
webhook:
|
||||||
|
replicaCount: 1
|
||||||
|
resources:
|
||||||
|
requests: {cpu: 10m, memory: 32Mi}
|
||||||
|
limits: {memory: 128Mi}
|
||||||
|
|
||||||
|
certController:
|
||||||
|
replicaCount: 1
|
||||||
|
resources:
|
||||||
|
requests: {cpu: 10m, memory: 32Mi}
|
||||||
|
limits: {memory: 128Mi}
|
||||||
|
|
||||||
|
resources:
|
||||||
|
requests: {cpu: 10m, memory: 64Mi}
|
||||||
|
limits: {memory: 256Mi}
|
||||||
|
|
||||||
|
serviceAccount:
|
||||||
|
create: true
|
||||||
|
name: external-secrets
|
||||||
|
|
||||||
|
installCRDs: true
|
||||||
@@ -28,6 +28,32 @@ Pod 删除后的 backing-file/VMM 回收和真实构建基准必须作为上线
|
|||||||
由 `VMPodScrape` 写入中央 VictoriaMetrics。它不拥有 Kubernetes API 凭据或 host 写
|
由 `VMPodScrape` 写入中央 VictoriaMetrics。它不拥有 Kubernetes API 凭据或 host 写
|
||||||
权限。
|
权限。
|
||||||
|
|
||||||
|
## Guest 内 SPIFFE 身份
|
||||||
|
|
||||||
|
Kata guest 不能直接使用 node SPIRE Agent 的 CSI socket。Unix socket 的路径即使通过
|
||||||
|
virtio-fs 出现在 guest 中,连接也不能跨 VM 边界。CI Pod 应以 native sidecar 在同一
|
||||||
|
guest 内启动临时 SPIRE Agent,并满足以下约束:
|
||||||
|
|
||||||
|
1. 外层 Pod 挂载 `audience=spire-server` 的 Pod-bound projected ServiceAccount token;
|
||||||
|
2. 内层 Agent 使用 `k8s_psat` 向中央 Server attestation,Server cluster profile 必须
|
||||||
|
启用 `use_pod_uid_for_agent_id`,使 Agent ID 包含 Pod UID;
|
||||||
|
3. 调度器为该具体 Agent 创建 registration entry;SPIFFE ID 使用仓库和任务名等稳定的
|
||||||
|
业务语义,Pod UID 只作为 parent binding,不进入业务身份;
|
||||||
|
4. Agent 与 workload 通过 guest 内 `emptyDir` 上的 Unix socket 通信;Pod 必须设置
|
||||||
|
`shareProcessNamespace: true`,否则 `unix` workload attestor 无法从共享 `/proc`
|
||||||
|
解析客户端的 `SO_PEERCRED` PID;
|
||||||
|
5. 调度器必须在 registration entry 已同步到 Agent 后才放行 workload。Pod 删除后同步
|
||||||
|
删除 entry,并 evict 对应的临时 Agent 记录。
|
||||||
|
|
||||||
|
2026-09-17 的 live PoC 已验证:以 Pod UID 作为 parent 的临时 Agent 成功注册,
|
||||||
|
`unix:uid:2000` workload 从 guest-local socket 获得
|
||||||
|
`spiffe://ddupan.top/ci/poc/task/build` X.509-SVID,Pod 正常退出。PoC 资源随后全部清理,
|
||||||
|
中央 SPIRE 恢复声明式配置。
|
||||||
|
|
||||||
|
SPIRE 1.15.3 已支持 `use_pod_uid_for_agent_id`,但当前使用的 hardened chart 0.30.2
|
||||||
|
尚未把它暴露到 values/template。正式部署应先给 chart 补齐该字段并向上游提交,随后
|
||||||
|
采用包含修复的 release;不得把手工修改 Server ConfigMap 作为运行方案。
|
||||||
|
|
||||||
## 上线验收
|
## 上线验收
|
||||||
|
|
||||||
Flux reconciliation 完成后至少确认:
|
Flux reconciliation 完成后至少确认:
|
||||||
@@ -35,8 +61,8 @@ Flux reconciliation 完成后至少确认:
|
|||||||
1. 两个节点重新回到 Ready,`RuntimeClass/kata-clh-runtime-rs` 存在;
|
1. 两个节点重新回到 Ready,`RuntimeClass/kata-clh-runtime-rs` 存在;
|
||||||
2. Kata Pod 内核与 LXC host 内核不同,且 `/dev/kvm` 可用;
|
2. Kata Pod 内核与 LXC host 内核不同,且 `/dev/kvm` 可用;
|
||||||
3. Cloud Hypervisor API 的 `vm.info.config.memory.shared` 为 `true`;
|
3. Cloud Hypervisor API 的 `vm.info.config.memory.shared` 为 `true`;
|
||||||
4. `spire-smoke` ServiceAccount 的 Kata Pod 可获得
|
4. Kata Pod 内层 Agent 的 ID 包含该 Pod UID;只有调度器创建的业务 entry 所匹配的
|
||||||
`spiffe://ddupan.top/sandbox/smoke`,错误 ServiceAccount 无法获得身份;
|
workload UID 能从 guest-local socket 获得预期 SPIFFE ID;
|
||||||
5. block-backed `emptyDir` 上 Docker 使用 `overlay2`,BuildKit 与 kind smoke test
|
5. block-backed `emptyDir` 上 Docker 使用 `overlay2`,BuildKit 与 kind smoke test
|
||||||
通过;kind 的 dockerd bootstrap 需要先在 guest 内执行
|
通过;kind 的 dockerd bootstrap 需要先在 guest 内执行
|
||||||
`mknod /dev/kmsg c 1 11`;
|
`mknod /dev/kmsg c 1 11`;
|
||||||
|
|||||||
@@ -1,123 +0,0 @@
|
|||||||
---
|
|
||||||
apiVersion: sandbox.opensandbox.io/v1alpha1
|
|
||||||
kind: Pool
|
|
||||||
metadata:
|
|
||||||
name: ci-pod
|
|
||||||
namespace: opensandbox
|
|
||||||
spec:
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
ci.ddupan.top/backend: pod
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: sandbox
|
|
||||||
image: sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/code-interpreter:v1.1.0
|
|
||||||
command: [/opt/opensandbox/task-executor]
|
|
||||||
args: [-listen-addr=0.0.0.0:5758, -log-dir=/tmp]
|
|
||||||
env:
|
|
||||||
- name: SANDBOX_MAIN_CONTAINER
|
|
||||||
value: sandbox
|
|
||||||
- name: EXECD_ENVS
|
|
||||||
value: /opt/opensandbox/.env
|
|
||||||
- name: EXECD
|
|
||||||
value: /opt/opensandbox/execd
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
cpu: 100m
|
|
||||||
memory: 256Mi
|
|
||||||
limits:
|
|
||||||
cpu: "2"
|
|
||||||
memory: 4Gi
|
|
||||||
volumeMounts:
|
|
||||||
- name: opensandbox-bin
|
|
||||||
mountPath: /opt/opensandbox
|
|
||||||
- name: sandbox-storage
|
|
||||||
mountPath: /var/lib/sandbox
|
|
||||||
initContainers:
|
|
||||||
- name: task-executor-installer
|
|
||||||
image: sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/task-executor:v0.1.0
|
|
||||||
command: [/bin/sh, -c]
|
|
||||||
args: [cp /workspace/server /opt/opensandbox/task-executor && chmod 0755 /opt/opensandbox/task-executor]
|
|
||||||
volumeMounts:
|
|
||||||
- name: opensandbox-bin
|
|
||||||
mountPath: /opt/opensandbox
|
|
||||||
- name: execd-installer
|
|
||||||
image: sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/execd:v1.0.22
|
|
||||||
command: [/bin/sh, -c]
|
|
||||||
args: [cp ./execd /opt/opensandbox/execd && cp ./bootstrap.sh /opt/opensandbox/bootstrap.sh && chmod 0755 /opt/opensandbox/execd /opt/opensandbox/bootstrap.sh]
|
|
||||||
volumeMounts:
|
|
||||||
- name: opensandbox-bin
|
|
||||||
mountPath: /opt/opensandbox
|
|
||||||
volumes:
|
|
||||||
- name: opensandbox-bin
|
|
||||||
emptyDir: {}
|
|
||||||
- name: sandbox-storage
|
|
||||||
emptyDir: {}
|
|
||||||
capacitySpec:
|
|
||||||
bufferMax: 1
|
|
||||||
bufferMin: 0
|
|
||||||
poolMax: 4
|
|
||||||
poolMin: 0
|
|
||||||
---
|
|
||||||
apiVersion: sandbox.opensandbox.io/v1alpha1
|
|
||||||
kind: Pool
|
|
||||||
metadata:
|
|
||||||
name: ci-vm
|
|
||||||
namespace: opensandbox
|
|
||||||
spec:
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
ci.ddupan.top/backend: vm
|
|
||||||
spec:
|
|
||||||
runtimeClassName: kata-clh-runtime-rs
|
|
||||||
containers:
|
|
||||||
- name: sandbox
|
|
||||||
image: sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/code-interpreter:v1.1.0
|
|
||||||
command: [/opt/opensandbox/task-executor]
|
|
||||||
args: [-listen-addr=0.0.0.0:5758, -log-dir=/tmp]
|
|
||||||
env:
|
|
||||||
- name: SANDBOX_MAIN_CONTAINER
|
|
||||||
value: sandbox
|
|
||||||
- name: EXECD_ENVS
|
|
||||||
value: /opt/opensandbox/.env
|
|
||||||
- name: EXECD
|
|
||||||
value: /opt/opensandbox/execd
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
cpu: 250m
|
|
||||||
memory: 512Mi
|
|
||||||
limits:
|
|
||||||
cpu: "4"
|
|
||||||
memory: 8Gi
|
|
||||||
volumeMounts:
|
|
||||||
- name: opensandbox-bin
|
|
||||||
mountPath: /opt/opensandbox
|
|
||||||
- name: sandbox-storage
|
|
||||||
mountPath: /var/lib/sandbox
|
|
||||||
initContainers:
|
|
||||||
- name: task-executor-installer
|
|
||||||
image: sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/task-executor:v0.1.0
|
|
||||||
command: [/bin/sh, -c]
|
|
||||||
args: [cp /workspace/server /opt/opensandbox/task-executor && chmod 0755 /opt/opensandbox/task-executor]
|
|
||||||
volumeMounts:
|
|
||||||
- name: opensandbox-bin
|
|
||||||
mountPath: /opt/opensandbox
|
|
||||||
- name: execd-installer
|
|
||||||
image: sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/execd:v1.0.22
|
|
||||||
command: [/bin/sh, -c]
|
|
||||||
args: [cp ./execd /opt/opensandbox/execd && cp ./bootstrap.sh /opt/opensandbox/bootstrap.sh && chmod 0755 /opt/opensandbox/execd /opt/opensandbox/bootstrap.sh]
|
|
||||||
volumeMounts:
|
|
||||||
- name: opensandbox-bin
|
|
||||||
mountPath: /opt/opensandbox
|
|
||||||
volumes:
|
|
||||||
- name: opensandbox-bin
|
|
||||||
emptyDir: {}
|
|
||||||
- name: sandbox-storage
|
|
||||||
emptyDir: {}
|
|
||||||
capacitySpec:
|
|
||||||
bufferMax: 1
|
|
||||||
bufferMin: 0
|
|
||||||
poolMax: 2
|
|
||||||
poolMin: 0
|
|
||||||
@@ -1,19 +1,44 @@
|
|||||||
# OpenSandbox
|
# Sandbox OpenSandbox
|
||||||
|
|
||||||
Flux installs the upstream all-in-one OpenSandbox chart pinned to
|
本目录在独立 sandbox k3s 集群部署 OpenSandbox controller、server 与 CRD。Flux 从
|
||||||
`helm/opensandbox/0.2.2` (`8f01e935`). The API is cluster-internal and intentionally runs a
|
上游 commit `8f01e935c2cabba778cf37a152033fae062fa0f4` 构建官方 umbrella chart
|
||||||
single replica until shared server state and HA behaviour have been validated.
|
`0.2.2`;该源码渲染结果已与 release `opensandbox-0.2.2.tgz` 对比一致。不要改为跟随
|
||||||
|
浮动 branch 或 tag。
|
||||||
|
|
||||||
`ci-pod` uses `runc`; `ci-vm` uses the separately managed
|
server 只提供集群内 `opensandbox-server.opensandbox-system.svc:80` ClusterIP,不部署
|
||||||
`kata-clh-runtime-rs` RuntimeClass. Both Pools start at zero and create capacity
|
Gateway、Ingress 或 LoadBalancer。sandbox workload 位于 `opensandbox` namespace,
|
||||||
on demand. They currently use the upstream interpreter image to validate the
|
默认使用 `kata-clh-runtime-rs`;CI Pool、runner 镜像、动态 SPIFFE registration 均由
|
||||||
Lifecycle API and Pool allocation independently of the CI scheduler cutover.
|
runner 项目后续声明,本目录不预制。
|
||||||
|
|
||||||
The dynamic runner worker, runner image, guest-local SPIRE Agent and Docker
|
## API 认证
|
||||||
sidecar are introduced only after this layer is Ready. In particular, do not
|
|
||||||
mount the host SPIFFE CSI socket into `ci-vm`: Unix sockets do not cross the
|
|
||||||
Kata VM boundary.
|
|
||||||
|
|
||||||
Smoke test both backends through the same API by creating sandboxes with
|
`ExternalSecret/opensandbox-api-key` 从 OpenBao
|
||||||
`extensions.poolRef` set to `ci-pod` and `ci-vm`, then confirm their
|
`kv/k8s/opensandbox-api:api_key` 投影同名 Secret。这个路径不归属于某个 Kubernetes
|
||||||
BatchSandboxes, Pods and VMMs disappear after deletion.
|
集群:sandbox server 与 homelab runner 调度器分别通过自己的 Bao 身份读取。server 只通过
|
||||||
|
`secretKeyRef` 读取:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: OPENSANDBOX_SERVER_API_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: opensandbox-api-key
|
||||||
|
key: api-key
|
||||||
|
```
|
||||||
|
|
||||||
|
仓库与 Helm values 均不保存 API key。OpenSandbox 不支持更丰富的原生 workload
|
||||||
|
authentication;runner 后续读取同一 Bao 路径并在请求头中使用 API key。
|
||||||
|
`opensandbox-values` 带 Flux watch label,values 变化会立即触发 Helm reconcile,不依赖
|
||||||
|
30 分钟的 HelmRelease interval。
|
||||||
|
|
||||||
|
## 验收
|
||||||
|
|
||||||
|
合并后等待 `flux-system/opensandbox` 与 `opensandbox-system/opensandbox` Ready,并确认:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get crd batchsandboxes.sandbox.opensandbox.io pools.sandbox.opensandbox.io
|
||||||
|
kubectl -n opensandbox-system get deploy,pod,svc
|
||||||
|
kubectl get runtimeclass kata-clh-runtime-rs
|
||||||
|
```
|
||||||
|
|
||||||
|
控制面上线不创建 CI Pool,也不产生 sandbox workload。首个 runner 集成应另行提交 Pool
|
||||||
|
与完整的 Lifecycle API smoke test。
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
apiVersion: external-secrets.io/v1
|
||||||
|
kind: ExternalSecret
|
||||||
|
metadata:
|
||||||
|
name: opensandbox-api-key
|
||||||
|
namespace: opensandbox-system
|
||||||
|
spec:
|
||||||
|
refreshInterval: 1h
|
||||||
|
secretStoreRef:
|
||||||
|
kind: ClusterSecretStore
|
||||||
|
name: openbao
|
||||||
|
target:
|
||||||
|
name: opensandbox-api-key
|
||||||
|
creationPolicy: Owner
|
||||||
|
data:
|
||||||
|
- secretKey: api-key
|
||||||
|
remoteRef:
|
||||||
|
key: k8s/opensandbox-api
|
||||||
|
property: api_key
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
---
|
||||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||||
kind: HelmRelease
|
kind: HelmRelease
|
||||||
metadata:
|
metadata:
|
||||||
@@ -15,6 +16,7 @@ spec:
|
|||||||
driftDetection:
|
driftDetection:
|
||||||
mode: enabled
|
mode: enabled
|
||||||
install:
|
install:
|
||||||
|
crds: CreateReplace
|
||||||
strategy:
|
strategy:
|
||||||
name: RetryOnFailure
|
name: RetryOnFailure
|
||||||
retryInterval: 5m
|
retryInterval: 5m
|
||||||
@@ -23,9 +25,11 @@ spec:
|
|||||||
targetNamespace: opensandbox-system
|
targetNamespace: opensandbox-system
|
||||||
timeout: 15m
|
timeout: 15m
|
||||||
upgrade:
|
upgrade:
|
||||||
|
crds: CreateReplace
|
||||||
strategy:
|
strategy:
|
||||||
name: RetryOnFailure
|
name: RetryOnFailure
|
||||||
retryInterval: 5m
|
retryInterval: 5m
|
||||||
valuesFrom:
|
valuesFrom:
|
||||||
- kind: ConfigMap
|
- kind: ConfigMap
|
||||||
name: opensandbox-values
|
name: opensandbox-values
|
||||||
|
valuesKey: values.yaml
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
|
---
|
||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
resources:
|
resources:
|
||||||
- namespaces.yaml
|
- namespace.yaml
|
||||||
|
- external-secret.yaml
|
||||||
- repository.yaml
|
- repository.yaml
|
||||||
|
- template.yaml
|
||||||
- values.yaml
|
- values.yaml
|
||||||
- helmrelease.yaml
|
- helmrelease.yaml
|
||||||
|
- monitor-scrape.yaml
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
apiVersion: operator.victoriametrics.com/v1beta1
|
||||||
|
kind: VMPodScrape
|
||||||
|
metadata:
|
||||||
|
name: opensandbox-controller
|
||||||
|
namespace: monitoring
|
||||||
|
spec:
|
||||||
|
namespaceSelector:
|
||||||
|
matchNames:
|
||||||
|
- opensandbox-system
|
||||||
|
podMetricsEndpoints:
|
||||||
|
- interval: 30s
|
||||||
|
port: metrics
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: opensandbox
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: opensandbox-system
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: opensandbox
|
||||||
|
labels:
|
||||||
|
pod-security.kubernetes.io/enforce: privileged
|
||||||
|
pod-security.kubernetes.io/audit: restricted
|
||||||
|
pod-security.kubernetes.io/warn: restricted
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Namespace
|
|
||||||
metadata:
|
|
||||||
name: opensandbox-system
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Namespace
|
|
||||||
metadata:
|
|
||||||
name: opensandbox
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
---
|
||||||
apiVersion: source.toolkit.fluxcd.io/v1
|
apiVersion: source.toolkit.fluxcd.io/v1
|
||||||
kind: GitRepository
|
kind: GitRepository
|
||||||
metadata:
|
metadata:
|
||||||
@@ -6,6 +7,5 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
interval: 1h
|
interval: 1h
|
||||||
ref:
|
ref:
|
||||||
tag: helm/opensandbox/0.2.2
|
commit: 8f01e935c2cabba778cf37a152033fae062fa0f4
|
||||||
timeout: 60s
|
url: https://github.com/opensandbox-group/OpenSandbox.git
|
||||||
url: https://github.com/alibaba/OpenSandbox.git
|
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: opensandbox-batchsandbox-template
|
||||||
|
namespace: opensandbox-system
|
||||||
|
data:
|
||||||
|
batchsandbox-template.yaml: |
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
ddupan.top/workload-class: sandbox
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
restartPolicy: Never
|
||||||
|
terminationGracePeriodSeconds: 30
|
||||||
@@ -1,41 +1,52 @@
|
|||||||
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: ConfigMap
|
kind: ConfigMap
|
||||||
metadata:
|
metadata:
|
||||||
name: opensandbox-values
|
name: opensandbox-values
|
||||||
namespace: opensandbox-system
|
namespace: opensandbox-system
|
||||||
|
labels:
|
||||||
|
reconcile.fluxcd.io/watch: Enabled
|
||||||
data:
|
data:
|
||||||
values.yaml: |
|
values.yaml: |
|
||||||
opensandbox-controller:
|
opensandbox-controller:
|
||||||
controller:
|
controller:
|
||||||
logLevel: info
|
|
||||||
replicaCount: 1
|
|
||||||
metrics:
|
metrics:
|
||||||
enabled: true
|
enabled: true
|
||||||
secure: false
|
|
||||||
port: 8080
|
port: 8080
|
||||||
resources:
|
secure: false
|
||||||
requests:
|
|
||||||
cpu: 25m
|
|
||||||
memory: 64Mi
|
|
||||||
limits:
|
|
||||||
cpu: 500m
|
|
||||||
memory: 256Mi
|
|
||||||
|
|
||||||
opensandbox-server:
|
opensandbox-server:
|
||||||
server:
|
server:
|
||||||
replicaCount: 1
|
replicaCount: 1
|
||||||
|
env:
|
||||||
|
- name: OPENSANDBOX_SERVER_API_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: opensandbox-api-key
|
||||||
|
key: api-key
|
||||||
resources:
|
resources:
|
||||||
requests:
|
|
||||||
cpu: 100m
|
|
||||||
memory: 256Mi
|
|
||||||
limits:
|
limits:
|
||||||
cpu: "1"
|
cpu: "1"
|
||||||
memory: 1Gi
|
memory: 1Gi
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 256Mi
|
||||||
|
volumeMounts:
|
||||||
|
- name: batchsandbox-template
|
||||||
|
mountPath: /etc/opensandbox/batchsandbox-template.yaml
|
||||||
|
subPath: batchsandbox-template.yaml
|
||||||
|
readOnly: true
|
||||||
|
volumes:
|
||||||
|
- name: batchsandbox-template
|
||||||
|
configMap:
|
||||||
|
name: opensandbox-batchsandbox-template
|
||||||
|
|
||||||
configToml: |
|
configToml: |
|
||||||
[server]
|
[server]
|
||||||
host = "0.0.0.0"
|
host = "0.0.0.0"
|
||||||
port = 80
|
port = 80
|
||||||
api_key = ""
|
api_key = ""
|
||||||
|
max_sandbox_timeout_seconds = 86400
|
||||||
|
|
||||||
[log]
|
[log]
|
||||||
level = "INFO"
|
level = "INFO"
|
||||||
@@ -44,6 +55,10 @@ data:
|
|||||||
type = "kubernetes"
|
type = "kubernetes"
|
||||||
execd_image = "sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/execd:v1.0.22"
|
execd_image = "sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/execd:v1.0.22"
|
||||||
|
|
||||||
|
[storage]
|
||||||
|
allowed_host_paths = []
|
||||||
|
volume_default_size = "1Gi"
|
||||||
|
|
||||||
[kubernetes]
|
[kubernetes]
|
||||||
kubeconfig_path = ""
|
kubeconfig_path = ""
|
||||||
namespace = "opensandbox"
|
namespace = "opensandbox"
|
||||||
@@ -52,11 +67,17 @@ data:
|
|||||||
informer_watch_timeout_seconds = 60
|
informer_watch_timeout_seconds = 60
|
||||||
snapshot_create_timeout_seconds = 900
|
snapshot_create_timeout_seconds = 900
|
||||||
workload_provider = "batchsandbox"
|
workload_provider = "batchsandbox"
|
||||||
batchsandbox_template_file = "/etc/opensandbox/example.batchsandbox-template.yaml"
|
image_pull_policy = "IfNotPresent"
|
||||||
|
batchsandbox_template_file = "/etc/opensandbox/batchsandbox-template.yaml"
|
||||||
|
|
||||||
[egress]
|
[egress]
|
||||||
image = "sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/egress:v1.1.6"
|
image = "sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/egress:v1.1.6"
|
||||||
mode = "dns+nft"
|
mode = "dns+nft"
|
||||||
|
disable_ipv6 = true
|
||||||
|
|
||||||
|
[secure_runtime]
|
||||||
|
type = "kata"
|
||||||
|
k8s_runtime_class = "kata-clh-runtime-rs"
|
||||||
|
|
||||||
opensandbox-node-agent:
|
opensandbox-node-agent:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|||||||
@@ -43,6 +43,10 @@ spire-server:
|
|||||||
externalSecret:
|
externalSecret:
|
||||||
name: spire-external-kubeconfigs
|
name: spire-external-kubeconfigs
|
||||||
key: sandbox-controller
|
key: sandbox-controller
|
||||||
|
sandbox-runner-bundle:
|
||||||
|
externalSecret:
|
||||||
|
name: spire-external-kubeconfigs
|
||||||
|
key: sandbox-controller
|
||||||
nodeAttestor:
|
nodeAttestor:
|
||||||
externalK8sPSAT:
|
externalK8sPSAT:
|
||||||
enabled: true
|
enabled: true
|
||||||
@@ -55,12 +59,19 @@ spire-server:
|
|||||||
kubeConfigName: sandbox
|
kubeConfigName: sandbox
|
||||||
serviceAccountAllowList:
|
serviceAccountAllowList:
|
||||||
- spire-smoke:spire-smoke
|
- spire-smoke:spire-smoke
|
||||||
|
- opensandbox:gitea-ci
|
||||||
usePodUIDForAgentID: true
|
usePodUIDForAgentID: true
|
||||||
externalControllerManagers:
|
externalControllerManagers:
|
||||||
enabled: true
|
enabled: true
|
||||||
clusters:
|
clusters:
|
||||||
sandbox:
|
sandbox:
|
||||||
kubeConfigName: sandbox-controller
|
kubeConfigName: sandbox-controller
|
||||||
|
# Dynamic OpenSandbox runner identities are exact Pod-UID-bound
|
||||||
|
# ClusterStaticEntries created in the sandbox cluster. The chart
|
||||||
|
# defaults this reconciler to false, so enable the central registration
|
||||||
|
# path explicitly.
|
||||||
|
reconcile:
|
||||||
|
clusterStaticEntries: true
|
||||||
bundlePublisher:
|
bundlePublisher:
|
||||||
externalK8sConfigMap:
|
externalK8sConfigMap:
|
||||||
enabled: true
|
enabled: true
|
||||||
@@ -71,6 +82,12 @@ spire-server:
|
|||||||
configMapName: spire-bundle
|
configMapName: spire-bundle
|
||||||
configMapKey: bundle.spiffe
|
configMapKey: bundle.spiffe
|
||||||
format: spiffe
|
format: spiffe
|
||||||
|
sandbox-runner-bundle:
|
||||||
|
kubeConfigName: sandbox-runner-bundle
|
||||||
|
namespace: opensandbox
|
||||||
|
configMapName: spire-bundle-pem
|
||||||
|
configMapKey: bundle.pem
|
||||||
|
format: pem
|
||||||
persistence:
|
persistence:
|
||||||
# PostgreSQL stores registrations, but the disk KeyManager still needs durable
|
# PostgreSQL stores registrations, but the disk KeyManager still needs durable
|
||||||
# storage for the trust-domain signing keys.
|
# storage for the trust-domain signing keys.
|
||||||
|
|||||||
Reference in New Issue
Block a user