210 lines
6.2 KiB
Markdown
210 lines
6.2 KiB
Markdown
# Bootstrap an empty dev-k3s cluster
|
|
|
|
이 runbook은 폐기 가능한 개발 클러스터만 대상으로 합니다. production에
|
|
사용하지 않습니다.
|
|
|
|
## 1. Preflight
|
|
|
|
```bash
|
|
kubectl config current-context
|
|
kubectl cluster-info
|
|
make validate
|
|
```
|
|
|
|
의도한 dev cluster가 아니면 중단합니다. 내부 Gitea가 private이면 Argo CD가
|
|
root repository를 읽을 수 있는 read-only credential을 외부 secret
|
|
authority에서 먼저 provision해야 합니다. credential은 이 저장소에
|
|
commit하지 않습니다.
|
|
|
|
remote state backend 파일을 준비합니다.
|
|
|
|
```bash
|
|
mkdir -p .local/terraform-backend/dev-k3s
|
|
cp iac/terraform/backend/dev-k3s/vault-core.s3.hcl.example \
|
|
.local/terraform-backend/dev-k3s/vault-core.s3.hcl
|
|
cp iac/terraform/backend/dev-k3s/vault-database.s3.hcl.example \
|
|
.local/terraform-backend/dev-k3s/vault-database.s3.hcl
|
|
```
|
|
|
|
실제 bucket, endpoint와 workload identity를 설정합니다. backend credential은
|
|
파일에 넣지 않습니다.
|
|
|
|
## 2. Argo CD와 root Application
|
|
|
|
```bash
|
|
make bootstrap KUBE_CONTEXT="$(kubectl config current-context)"
|
|
kubectl -n argocd get application project-gitops-dev-k3s
|
|
```
|
|
|
|
이 명령이 수행하는 직접 cluster mutation은 Argo CD 설치와 root seed뿐입니다.
|
|
Child Application은 root가 생성합니다.
|
|
|
|
## 3. Dev Vault 초기화
|
|
|
|
Vault Pod가 생성될 때까지 기다린 뒤 operator workstation에서 forward합니다.
|
|
이 port-forward는 최초 dev bootstrap용이며 routine runner 모델이 아닙니다.
|
|
|
|
```bash
|
|
kubectl -n vault wait --for=create pod -l app=vault --timeout=300s
|
|
kubectl -n vault port-forward deployment/vault 8200:8200
|
|
```
|
|
|
|
별도 terminal:
|
|
|
|
```bash
|
|
export VAULT_ADDR=http://127.0.0.1:8200
|
|
./hack/vault-init.sh init
|
|
```
|
|
|
|
`.local/vault/dev-k3s-init.json`을 즉시 encrypted custody로 복사합니다.
|
|
dev-only 1-of-1 unseal key와 initial root token이 있으므로 일반 backup과
|
|
분리합니다.
|
|
|
|
## 4. Vault core
|
|
|
|
초기 root token을 shell history에 직접 적지 않습니다.
|
|
|
|
```bash
|
|
export TF_VAR_vault_addr="$VAULT_ADDR"
|
|
export TF_VAR_vault_token="$(
|
|
jq -r '.root_token' .local/vault/dev-k3s-init.json
|
|
)"
|
|
|
|
make terraform-plan \
|
|
TF_ROOT=vault-core \
|
|
BACKEND_CONFIG=.local/terraform-backend/dev-k3s/vault-core.s3.hcl
|
|
|
|
make terraform-apply \
|
|
TF_ROOT=vault-core \
|
|
BACKEND_CONFIG=.local/terraform-backend/dev-k3s/vault-core.s3.hcl \
|
|
APPROVE_APPLY=dev-k3s/vault-core
|
|
```
|
|
|
|
plan에서 mount, auth backend, policy, role, JWT Transit key 이외 객체가
|
|
나오면 apply하지 않습니다.
|
|
|
|
## 5. Runtime secret seed
|
|
|
|
Secret 값은 Git/Terraform을 통과하지 않습니다. 아래 변수는 terminal
|
|
session에만 유지합니다.
|
|
|
|
```bash
|
|
read -r -s -p "PostgreSQL superuser password: " POSTGRES_SUPERUSER_PASSWORD
|
|
echo
|
|
read -r -s -p "Auth database password: " AUTH_DB_PASSWORD
|
|
echo
|
|
read -r -s -p "Keycloak database password: " KEYCLOAK_DB_PASSWORD
|
|
echo
|
|
read -r -s -p "Keycloak bootstrap admin password: " KEYCLOAK_ADMIN_PASSWORD
|
|
echo
|
|
read -r -s -p "Auth-server Keycloak client secret: " KEYCLOAK_CLIENT_SECRET
|
|
echo
|
|
|
|
secret_file="$(mktemp)"
|
|
trap 'rm -f "$secret_file"' EXIT
|
|
chmod 0600 "$secret_file"
|
|
|
|
jq -n --arg password "$POSTGRES_SUPERUSER_PASSWORD" \
|
|
'{POSTGRES_SUPERUSER_PASSWORD: $password}' >"$secret_file"
|
|
vault kv put kv/dev/platform/postgres/superuser @"$secret_file"
|
|
|
|
jq -n \
|
|
--arg password "$AUTH_DB_PASSWORD" \
|
|
'{AUTH_DB_PASSWORD: $password, APP_DATASOURCE_USERNAME: "project_auth", APP_DATASOURCE_PASSWORD: $password}' >"$secret_file"
|
|
vault kv put kv/dev/platform/postgres/auth-server @"$secret_file"
|
|
|
|
jq -n --arg password "$KEYCLOAK_DB_PASSWORD" \
|
|
'{KEYCLOAK_DB_PASSWORD: $password}' >"$secret_file"
|
|
vault kv put kv/dev/platform/postgres/keycloak @"$secret_file"
|
|
|
|
jq -n --arg password "$KEYCLOAK_ADMIN_PASSWORD" \
|
|
'{KC_BOOTSTRAP_ADMIN_PASSWORD: $password}' >"$secret_file"
|
|
vault kv put kv/dev/platform/keycloak/bootstrap-admin @"$secret_file"
|
|
|
|
jq -n --arg secret "$KEYCLOAK_CLIENT_SECRET" \
|
|
'{KEYCLOAK_CLIENT_SECRET: $secret, APP_SECURITY_OAUTH2_KEYCLOAK_CLIENT_SECRET: $secret}' >"$secret_file"
|
|
vault kv put kv/dev/platform/keycloak/client-auth-server @"$secret_file"
|
|
|
|
rm -f "$secret_file"
|
|
trap - EXIT
|
|
```
|
|
|
|
PostgreSQL이 Vault Agent 주입 후 시작하는지 확인합니다.
|
|
|
|
```bash
|
|
kubectl -n platform rollout status statefulset/postgres --timeout=600s
|
|
```
|
|
|
|
## 6. Vault database state
|
|
|
|
초기 root token으로 TTL이 짧은 database 전용 token을 발급합니다.
|
|
|
|
```bash
|
|
export TF_VAR_vault_token="$(
|
|
vault token create \
|
|
-policy=vault-database-automation-dev \
|
|
-ttl=30m \
|
|
-format=json |
|
|
jq -r '.auth.client_token'
|
|
)"
|
|
export TF_VAR_postgres_admin_password="$POSTGRES_SUPERUSER_PASSWORD"
|
|
export TF_VAR_postgres_admin_password_version=1
|
|
|
|
make terraform-plan \
|
|
TF_ROOT=vault-database \
|
|
BACKEND_CONFIG=.local/terraform-backend/dev-k3s/vault-database.s3.hcl
|
|
|
|
make terraform-apply \
|
|
TF_ROOT=vault-database \
|
|
BACKEND_CONFIG=.local/terraform-backend/dev-k3s/vault-database.s3.hcl \
|
|
APPROVE_APPLY=dev-k3s/vault-database
|
|
```
|
|
|
|
## 7. Root token 폐기
|
|
|
|
Kubernetes auth operator login이 동작하는지 먼저 검증합니다.
|
|
|
|
```bash
|
|
operator_jwt="$(
|
|
kubectl -n vault create token vault-operator \
|
|
--audience=vault \
|
|
--duration=10m
|
|
)"
|
|
operator_token="$(
|
|
VAULT_TOKEN= vault write \
|
|
-format=json \
|
|
auth/kubernetes/login \
|
|
role=vault-operator-dev \
|
|
jwt="$operator_jwt" |
|
|
jq -r '.auth.client_token'
|
|
)"
|
|
VAULT_TOKEN="$operator_token" vault token lookup >/dev/null
|
|
```
|
|
|
|
검증 후 initial root token을 폐기합니다.
|
|
|
|
```bash
|
|
./hack/vault-init.sh revoke-root
|
|
unset operator_jwt operator_token
|
|
unset TF_VAR_vault_token TF_VAR_postgres_admin_password
|
|
unset POSTGRES_SUPERUSER_PASSWORD AUTH_DB_PASSWORD KEYCLOAK_DB_PASSWORD
|
|
unset KEYCLOAK_ADMIN_PASSWORD KEYCLOAK_CLIENT_SECRET
|
|
```
|
|
|
|
encrypted custody로 옮긴 init material의 local working copy는 조직의
|
|
dev recovery 정책에 따라 제거합니다.
|
|
|
|
## 8. 확인
|
|
|
|
```bash
|
|
kubectl -n argocd get applications
|
|
kubectl -n vault get pods
|
|
kubectl -n platform get pods
|
|
kubectl -n auth-dev get pods
|
|
kubectl -n api-dev get pods
|
|
```
|
|
|
|
모든 Application의 sync/health를 확인하고 DB migration 및 Keycloak client
|
|
sync hook 결과를 검토합니다. 실패한 hook을 고치기 위해 child manifest를
|
|
직접 apply하지 말고 Git PR을 사용합니다.
|