Skip to content

Configure service DNS / ingress

TL;DR — Adds a Kubernetes ingress rule for a backend microservice in ops-k8s-infra for dev, rc, and/or sandbox. Production DNS changes require a DevOps ticket — this workflow explicitly skips prod.

Overview

Backend microservices are exposed via ingress rules in securitize_dev/ops-k8s-infra. Each environment × service-type combination maps to a specific YAML file. This workflow:

  1. Collects service name, type, port, and target environments from the developer.
  2. Loads the file path table and host patterns from the wiki (SSOT).
  3. Checks whether the rule already exists.
  4. Appends the rule for environments where it is missing.
  5. Creates a PR in ops-k8s-infra.

File paths, host patterns, and service type descriptions live exclusively in wiki/repositories/ops-repos.md → Ingress and DNS configuration. Load that wiki page before Step 2 — do not rely on memory for file paths.

Production DNS is not in scope

ops-k8s-infra covers dev, rc, and sandbox only. Production DNS / ingress changes require a DevOps ticket via the Service Desk. Do not attempt to add prod rules — stop and redirect the developer.

Inputs

Collect all of these from the developer before cloning anything:

Input Description Values
service_name K8s service name — must match the deployment name in ops-scripts e.g. my-svc
service_type How the service is exposed internal, public, or gateway
port Service port default 8080
environments Which environments to add the rule to any subset of dev, rc, sandbox

If the developer is unsure which service_type to pick, point them to the wiki's "Service types and browser URLs" table — it lists who can reach each type and the resulting browser URL.

For gateway, the YAML host differs from the browser URL — always use the host string the wiki resolves for the service type (see the wiki's "Why gateway browser URL and YAML host don't match" tip for the full explanation).

Steps

Shell-session note — If you run each bash command in a separate subshell, REPO_DIR does not persist. Re-derive it in any step after Step 1 as:

REPO_DIR=$(ls -dt "$HOME"/.securitize/tmp/ops-k8s-infra-*/ 2>/dev/null | head -1)
REPO_DIR="${REPO_DIR%/}"

1. Clone ops-k8s-infra

REPO_DIR="$HOME/.securitize/tmp/ops-k8s-infra-$(date +%Y%m%d%H%M%S)"
mkdir -p "$HOME/.securitize/tmp"
git clone --depth 1 git@bitbucket.org:securitize_dev/ops-k8s-infra.git "$REPO_DIR"

# Confirm mainline is master — every ops-* repo branches from master, not dev
git -C "$REPO_DIR" rev-parse --abbrev-ref HEAD   # must print: master

If the clone fails, ask the developer to verify SSH access to securitize_dev, then stop. If the confirm command does not print master, stop — ops-k8s-infra uses master as its mainline; do not proceed on any other branch.

2. Load the wiki and check whether the rule already exists

Before doing anything in the repo, load the ingress reference from the wiki — it is the SSOT for file paths, host patterns, and the current vs at capacity model:

get_wiki_file(path="references/ops-repos.md")

Read the "Ingress and DNS configuration" section. From it, extract, for each requested environment × service_type: - The read set — every file listed in the wiki's "Read target — full file set per env × service_type" table. - The current file — the single write target from the wiki's "Write target — the current file per env × type" table. - The host string format for the service type.

Build the grep from the wiki's read set — never a single file

Including every file from the read set in one grep is mandatory. The wiki explains why (the at capacity model and the ALB rule limit). A single-file grep yields false MISSING and duplicated rules on apply.

For each requested environment, run one grep across the full read set:

HOST="<computed_host>"
# Replace placeholders with EVERY file from the wiki's read set for this env × service_type:
grep -l "host: $HOST" \
  "$REPO_DIR/<file_1>" \
  "$REPO_DIR/<file_2>" \
  ... \
  2>/dev/null
  • Any printed file → status EXISTS (note which file matched).
  • No output → status MISSING.

Build a summary table — include the matched file (or (no match)) so the check is auditable:

Env Read set (from wiki) Host Grep match Status
<env> <file_1> (current), <file_2> (at capacity), ... <host> (no match) MISSING
<env> <file_1> (current), <file_2> (at capacity), ... <host> <matched_file> EXISTS — skip

Show the table to the developer before writing anything. If all environments are EXISTS, stop — there is nothing to add. Otherwise ask for confirmation before proceeding to Step 3.

3. Append missing rules

For each environment with status MISSING, append the rule to the current file for that env × service_type (from the wiki's "Write target" table). Never write to a file marked at capacity — see the wiki for the reason.

Detect the indentation from the last existing - host: entry and append at the end of the file:

YAML_FILE="$REPO_DIR/<current_file>"
HOST="<computed_host>"
SERVICE_NAME="<service_name>"
PORT=<port>

# Detect indentation from existing entries (fallback: 4 spaces)
INDENT=$(grep "- host:" "$YAML_FILE" | tail -1 | sed 's/- host:.*//')
[ -z "$INDENT" ] && INDENT="    "

I0="${INDENT}"
I2="${INDENT}  "
I4="${INDENT}    "
I6="${INDENT}      "
I8="${INDENT}        "
I10="${INDENT}          "
I12="${INDENT}            "
I14="${INDENT}              "

# Ensure file ends with a newline before appending
[ -n "$(tail -c 1 "$YAML_FILE")" ] && echo "" >> "$YAML_FILE"

cat >> "$YAML_FILE" <<EOF
${I0}- host: ${HOST}
${I2}http:
${I4}paths:
${I6}- path: /*
${I8}pathType: ImplementationSpecific
${I8}backend:
${I10}service:
${I12}name: ${SERVICE_NAME}
${I12}port:
${I14}number: ${PORT}
EOF

Repeat for each MISSING environment.

4. Show the diff and confirm

cd "$REPO_DIR" && git diff

Show the full diff to the developer. If they want adjustments, return to Step 3. Do not proceed until they confirm.

5. Create branch (from master) and push

Branch from master, not dev

ops-k8s-infra — like every ops-* repo — uses master as its mainline. Do not substitute dev even if a generic PR procedure suggests it as a default. This workflow's branching base is non-negotiable: the PR destination is master (Step 6) and the source branch must also be cut from master.

BRANCH="feature/dns-${SERVICE_NAME}-$(date +%Y%m%d%H%M%S)"
cd "$REPO_DIR"
git checkout -b "$BRANCH" master   # explicit base = master — do not change to dev
git add .
git commit -m "chore: add ingress rule for ${SERVICE_NAME} (${SERVICE_TYPE})"
git push origin "$BRANCH"

6. Open the Pull Request

Target: securitize_dev/ops-k8s-infra, source = branch from Step 5, destination = master.

Preferred — open the PR through any Bitbucket-capable MCP you have available. Tool names and parameter shapes vary by server (mcp__bitbucket__*, mcp__atlassian__*, custom servers, etc.); scan your tool list for tools that act on Bitbucket pull requests. Whatever the surface, perform two operations:

  1. Resolve the repo's effective default reviewers for workspace=securitize_dev, repo=ops-k8s-infra. Keep the returned user identifiers (UUIDs / account IDs / whatever the server uses).
  2. Create the pull request with:
  3. source = {BRANCH} (from Step 5)
  4. destination = master
  5. title = chore: add ingress rule for {service_name} ({service_type})
  6. description = summary table from Step 2
  7. reviewers = the identifiers from (1)

Fallback — no Bitbucket MCP available. Show the developer the manual URL and stop:

https://bitbucket.org/securitize_dev/ops-k8s-infra/pull-requests/new?source={BRANCH}&dest=master

In either path, show the final PR link to the developer.

7. Clean up

rm -rf "$REPO_DIR"

Verification

  • PR is open on securitize_dev/ops-k8s-infra against master.
  • The diff contains exactly one - host: block per requested environment, in the correct YAML files.
  • No rule was duplicated — each host appeared as MISSING before being appended.

Rollback

This workflow writes nothing outside the temporary clone until the branch is pushed.

  • Before push (Steps 1-5): rm -rf "$REPO_DIR" discards everything.
  • After push, before merge: close the PR in Bitbucket; delete the remote branch.
  • After merge: open a revert PR in ops-k8s-infra removing the - host: block(s) from the affected YAML files.

See also

Tags

workflow #ops-k8s-infra #dns #ingress #k8s