Skip to content

feat: introduce FAQ for installation of Global DR#157

Merged
IceCodeNew merged 16 commits intomasterfrom
upgrade-doc
Sep 1, 2025
Merged

feat: introduce FAQ for installation of Global DR#157
IceCodeNew merged 16 commits intomasterfrom
upgrade-doc

Conversation

@IceCodeNew
Copy link
Copy Markdown
Contributor

@IceCodeNew IceCodeNew commented Aug 29, 2025

Summary by CodeRabbit

  • Documentation
    • Clarified Primary vs Standby naming; added DR installation warnings and resource requirements (Platform Access domain/TLS, two VIPs, preconfigured LB routing for required ports).
    • Reworked DR install flow: copy/merge etcd encryption keys, enable/configure/verify etcd synchronization via Marketplace, added sync output interpretation and re-trigger steps.
    • Added post-recovery service-restart guidance, detailed FAQ for key sync, and note to use --dest-repo when uploading to standby.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Aug 29, 2025

Walkthrough

Restructures the Global DR installation doc to clarify Primary vs Standby roles and naming, require a user-provisioned load balancer forwarding TCP ports (including 2379), instruct copying Primary ETCD encryption keys to standby control-plane nodes via SSH/SCP, add UI/CLI etcd-synchronizer install and verification steps, expand DR recovery procedures and encryption-key sync FAQ, and add upload/package guidance.

Changes

Cohort / File(s) Summary of Changes
Global DR doc (single file)
docs/en/install/global_dr.mdx
Major restructure and content additions: Primary/Standby terminology and naming guidance, directive/warning blocks, expanded requirements, step renumbering, and overall editorial edits.
Install / process flow edits
docs/en/install/global_dr.mdx
Steps revised: point domain to Primary VIP for install; copy ETCD encryption config using scp/ssh with remote-user placeholders and temp path; examples updated; step order changed.
LB & networking requirements
docs/en/install/global_dr.mdx
Require user-provisioned load balancer with TCP forwarding for 80, 443, 6443, 2379, 11443; unify domain as Platform Access Address; require shared TLS cert/private key and two VIPs.
etcd-synchronizer enablement & ops
docs/en/install/global_dr.mdx
Replace port-forwarding approach with LB TCP forwarding for 2379; add Marketplace/UI and CLI install steps, default sync interval, logging guidance, re-trigger/verify commands (curl/CLI), pod recreation guidance, and etcd-sync output interpretation.
Disaster recovery & post-recovery actions
docs/en/install/global_dr.mdx
Overhauled recovery flow: restart Elasticsearch/Victoria Metrics/cluster-transformer/warlock when applicable, uninstall etcd-synchronizer, remove 2379 forwarding, switch DNS to standby VIP, verify resolution/platform state, and convert original Primary into new Standby.
Encryption-key sync & upload guidance
docs/en/install/global_dr.mdx
New FAQ and step-by-step encryption-key merge/export guidance (unique key names, distribute to control planes, restart pods); note to use --dest-repo with the standby VIP when uploading DR packages.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Admin
  participant LB as "Load Balancer\n(TCP forward)"
  participant Primary as "Primary\nControl Plane"
  participant Standby as "Standby\nControl Plane"
  participant EtcdSync as "etcd-synchronizer\n(UI / Pod)"
  participant Kube as "kube-apiserver / pods"

  Note over Admin,LB: Preconfigure LB to forward TCP 80,443,6443,2379,11443 -> control-plane VIPs
  Admin->>LB: Configure TCP forwarding for control-plane VIPs
  Admin->>Primary: Install Primary cluster (domain -> Primary VIP)
  Admin->>Standby: Copy ETCD encryption config (scp user@primary:/path/to/encryption-provider.conf /tmp/)
  Admin->>EtcdSync: Install/Enable etcd-synchronizer (Marketplace or CLI)
  EtcdSync->>Primary: Read ETCD keys/state
  EtcdSync->>Standby: Read ETCD keys/state
  EtcdSync-->>Admin: Report key differences / sync status

  alt Standby missing keys
    Admin->>Primary: Merge/export unique keys
    Admin->>Standby: Deploy updated encryption-provider.conf to control planes
    Admin->>Kube: Restart kube-apiserver / related pods to apply keys
  end

  Admin->>EtcdSync: Trigger/force sync (curl / UI)
  EtcdSync-->>Admin: Sync result (success / errors)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

I hop between clusters with a nimble twitch,
copying keys beneath the moon's soft stitch.
VIPs hum as TCP paths align,
syncs nudge keys until states combine.
A rabbit cheers — DR ready, carrots all mine 🥕🐇

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch upgrade-doc

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
docs/en/install/global_dr.mdx (2)

209-217: Harden kubectl selectors to return a single pod name.

--no-headers | head -1 can break; use jsonpath or -o name.

Apply:

-kubectl get po -n cpaas-system -l app=etcd-sync
-kubectl logs -n cpaas-system $(kubectl get po -n cpaas-system -l app=etcd-sync --no-headers | head -1) | grep -i "Start Sync update"
+kubectl get po -n cpaas-system -l app=etcd-sync
+pod=$(kubectl get po -n cpaas-system -l app=etcd-sync -o jsonpath='{.items[0].metadata.name}')
+kubectl logs -n cpaas-system "$pod" | grep -i "Start Sync update"
-kubectl delete po -n cpaas-system $(kubectl get po -n cpaas-system -l app=etcd-sync --no-headers | head -1)
+pod=$(kubectl get po -n cpaas-system -l app=etcd-sync -o jsonpath='{.items[0].metadata.name}')
+kubectl delete po -n cpaas-system "$pod"

268-270: kubectl exec targets a Deployment; exec requires a Pod name.

Replace with a pod selector to avoid failures.

Apply:

-    kubectl exec -it -n cpaas-system deployments/sentry -- nslookup <platform access domain>
+    kubectl exec -it -n cpaas-system $(kubectl get pod -n cpaas-system -l app=sentry -o jsonpath='{.items[0].metadata.name}') -- nslookup <platform access domain>
🧹 Nitpick comments (3)
docs/en/install/global_dr.mdx (3)

222-231: Use explicit scheme and fail-fast curl; keep IPv6 handling.

Make the check robust and explicit.

Apply:

-curl $mirror_new_svc/check
+curl -sS --fail "http://$mirror_new_svc/check"

304-305: Consistent IPv6-safe check (reuse method from Step 3).

The Routine Checks curl will break on IPv6-only clusters.

Apply:

-curl $(kubectl get svc -n cpaas-system etcd-sync-monitor -o jsonpath='{.spec.clusterIP}')/check
+svc=$(kubectl get svc -n cpaas-system etcd-sync-monitor -o jsonpath='{.spec.clusterIP}')
+if [[ $svc =~ ^[0-9a-fA-F:]+$ ]]; then svc="[$svc]"; fi
+curl -sS --fail "http://$svc/check"

157-171: State preconditions: run as root or with sudo on all control plane nodes.

The steps assume write access to /etc/kubernetes and ability to restart kubelet. Make that explicit to avoid partial updates.

Add:

+Prerequisite: Run the following commands as root (or prefix with sudo) on the indicated nodes.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 8b7f0e5 and 414364d.

📒 Files selected for processing (1)
  • docs/en/install/global_dr.mdx (2 hunks)
🧰 Additional context used
🪛 Gitleaks (8.27.2)
docs/en/install/global_dr.mdx

151-151: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

Comment thread docs/en/install/global_dr.mdx Outdated
Comment thread docs/en/install/global_dr.mdx Outdated
Comment thread docs/en/install/global_dr.mdx Outdated
Comment thread docs/en/install/global_dr.mdx Outdated
Comment thread docs/en/install/global_dr.mdx Outdated
Comment thread docs/en/install/global_dr.mdx Outdated
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Aug 29, 2025

Deploying acp-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: 8d2c6fc
Status: ✅  Deploy successful!
Preview URL: https://8c6cb94f.acp-docs.pages.dev
Branch Preview URL: https://upgrade-doc.acp-docs.pages.dev

View logs

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (7)
docs/en/install/global_dr.mdx (7)

95-101: Harden key copy: fix grammar, require sudo, and set secure perms (600).

Copying directly to /etc without sudo and leaving world-readable perms is unsafe; also fix the English in comments.

-    # Let the control plane nodes of the primary cluster are 1.1.1.1, 2.2.2.2 & 3.3.3.3
-    # the control plane nodes of the standby cluster are 4.4.4.4, 5.5.5.5 & 6.6.6.6
+    # Assume the primary cluster control plane nodes are 1.1.1.1, 2.2.2.2 & 3.3.3.3
+    # and the standby cluster control plane nodes are 4.4.4.4, 5.5.5.5 & 6.6.6.6
     for i in 4.4.4.4 5.5.5.5 6.6.6.6  # Replace with standby cluster control plane node IPs
     do
-      ssh "<user>@$i" "mkdir -p /etc/kubernetes/"
-      scp /etc/kubernetes/encryption-provider.conf "<user>@$i:/etc/kubernetes/encryption-provider.conf"
+      ssh "<user>@$i" "sudo mkdir -p /etc/kubernetes/"
+      scp /etc/kubernetes/encryption-provider.conf "<user>@$i:/tmp/encryption-provider.conf"
+      ssh "<user>@$i" "sudo install -o root -g root -m 600 /tmp/encryption-provider.conf /etc/kubernetes/encryption-provider.conf && rm -f /tmp/encryption-provider.conf"
     done

117-117: Add security caveat for 2379 exposure and LB behavior.

Call out “no internet exposure, allow-list only, pure TCP pass-through (no TLS termination at LB).”

-1. Configure the load balancer to forward port `2379` to the control plane nodes of both clusters. ONLY TCP mode is supported; forwarding on L7 is not supported.
+1. Configure the load balancer to forward port `2379` to the control plane nodes of both clusters. ONLY TCP mode is supported; forwarding on L7 is not supported.
+   Security: Never expose 2379 to the public internet. Restrict by network ACLs/firewalls to only the control-plane/load-balancer addresses, and ensure the LB does TCP pass-through (no TLS termination or L7 inspection).

255-266: Replace real-looking base64 secret with explicit placeholder; add disclaimer.

             - name: key1
-              secret: MTE0NTE0MTkxOTgxMA==
+              secret: <BASE64_32_BYTE_KEY_FROM_STANDBY_EXAMPLE_ONLY>
+> Note: Replace placeholders with your own 32‑byte keys encoded in base64. Do not reuse example values.

270-283: Same issue: placeholders for secrets in merged config; add disclaimer.

             - name: key1
-              secret: My.1415926535897
+              secret: <BASE64_32_BYTE_KEY_FROM_PRIMARY_EXAMPLE_ONLY>
             - name: key2
-              secret: MTE0NTE0MTkxOTgxMA==
+              secret: <BASE64_32_BYTE_KEY_FROM_STANDBY_EXAMPLE_ONLY>
+> Note: Replace placeholders with your own 32‑byte keys encoded in base64. Do not reuse example values.

270-283: Call out key order semantics to avoid dual-write divergence.

+Important: The first key in the list is used for writes; all keys are used for reads. Keep the Primary’s active key listed first on both clusters until rotation completes. Reorder/remove keys only during a planned rotation window after verifying re-encryption.

287-310: Fix remote distribution script: sudo, perms, interpolation, and restart sequence.

Avoid ${i} inside single-quoted heredoc, copy to /tmp + sudo install 600, and just restart kubelet (static pod will be recreated). This also avoids incorrect crictl usage.

-        scp /etc/kubernetes/encryption-provider.conf "<user>@${i}:/etc/kubernetes/encryption-provider.conf"
-        ssh "<user>@${i}" '
-    #!/bin/bash
-    _pod_name="kube-apiserver"
-    _pod_id=$(crictl ps --name "${_pod_name}" --no-trunc --quiet)
-    if [[ -z "${_pod_id}" ]]; then
-        echo "FATAL: could not find pod 'kube-apiserver' on node ${i}"
-        exit 1
-    fi
-    crictl rm --force "${_pod_id}"
-    systemctl restart kubelet.service
-    '
+        scp /etc/kubernetes/encryption-provider.conf "<user>@${i}:/tmp/encryption-provider.conf"
+        ssh "<user>@${i}" "sudo install -o root -g root -m 600 /tmp/encryption-provider.conf /etc/kubernetes/encryption-provider.conf && rm -f /tmp/encryption-provider.conf && sudo systemctl restart kubelet"

312-323: Fix restart on node 1.1.1.1: undefined ${i}, sudo, and crictl misuse.

Variable ${i} isn’t defined here; use kubelet restart (static pod). Also require sudo.

-    _pod_name="kube-apiserver"
-    _pod_id=$(crictl ps --name "${_pod_name}" --no-trunc --quiet)
-    if [[ -z "${_pod_id}" ]]; then
-        echo "FATAL: could not find pod 'kube-apiserver' on node ${i}"
-        exit 1
-    fi
-    crictl rm --force "${_pod_id}"
-    systemctl restart kubelet.service
+    # Restart kubelet to recreate the static kube-apiserver pod after config change
+    sudo systemctl restart kubelet
🧹 Nitpick comments (1)
docs/en/install/global_dr.mdx (1)

245-246: Fix grammar of FAQ lead-in.

-* Here are the instructions in case that the ETCD encryption key of the standby cluster has not synced with the one of **primary cluster** before Installing the standby cluster.
+* Use this procedure if the standby cluster’s etcd encryption key did not sync with the **Primary Cluster** before installing the standby cluster.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 414364d and 27aeb5a.

📒 Files selected for processing (1)
  • docs/en/install/global_dr.mdx (4 hunks)
🧰 Additional context used
🪛 Gitleaks (8.27.2)
docs/en/install/global_dr.mdx

280-280: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🔇 Additional comments (1)
docs/en/install/global_dr.mdx (1)

172-187: Add strict error handling and conditional restart
Include set -euo pipefail and change the block so it only deletes Elasticsearch pods—and reruns the check—when the ensure-asm-template.sh script actually returns a 401 error. Manually verify that /root/ensure-asm-template.sh exits non-zero on failure and outputs “401” on authentication errors before applying this change.

Comment thread docs/en/install/global_dr.mdx
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (6)
docs/en/install/global_dr.mdx (6)

106-112: Secure copy of encryption config: sudo, atomic install, and perms 600

Avoid writing to /etc without privilege; enforce root ownership and 0600. Also tweak the preface lines for grammar.

-    # Let the control plane nodes of the primary cluster are 1.1.1.1, 2.2.2.2 & 3.3.3.3
-    # the control plane nodes of the standby cluster are 4.4.4.4, 5.5.5.5 & 6.6.6.6
+    # Assume the primary control-plane nodes are 1.1.1.1, 2.2.2.2, 3.3.3.3
+    # and the standby control-plane nodes are 4.4.4.4, 5.5.5.5, 6.6.6.6
     for i in 4.4.4.4 5.5.5.5 6.6.6.6  # Replace with standby cluster control plane node IPs
     do
-      ssh "<user>@$i" "mkdir -p /etc/kubernetes/"
-      scp /etc/kubernetes/encryption-provider.conf "<user>@$i:/etc/kubernetes/encryption-provider.conf"
+      ssh "<user>@$i" "sudo mkdir -p /etc/kubernetes/"
+      scp /etc/kubernetes/encryption-provider.conf "<user>@$i:/tmp/encryption-provider.conf"
+      ssh "<user>@$i" "sudo install -o root -g root -m 600 /tmp/encryption-provider.conf /etc/kubernetes/encryption-provider.conf && rm -f /tmp/encryption-provider.conf"
     done

266-271: Require sudo to read encryption config

Reading /etc requires root. Use sudo and tighten placeholders.

-    ssh <user>@<STANDBY cluster control plane node> cat /etc/kubernetes/encryption-provider.conf
+    ssh "<user>@<standby_control_plane_node>" "sudo cat /etc/kubernetes/encryption-provider.conf"

306-329: Remote script: quoting, sudo, correct crictl usage, and atomic install

Single-quoted SSH script won’t expand ${i}; commands need sudo; use crictl pods stopp/rmp or just restart kubelet. Also install file with 0600.

-        scp /etc/kubernetes/encryption-provider.conf "<user>@${i}:/etc/kubernetes/encryption-provider.conf"
-        ssh "<user>@${i}" '
-    #!/bin/bash
-    _pod_name="kube-apiserver"
-    _pod_id=$(crictl ps --name "${_pod_name}" --no-trunc --quiet)
-    if [[ -z "${_pod_id}" ]]; then
-        echo "FATAL: could not find pod 'kube-apiserver' on node ${i}"
-        exit 1
-    fi
-    crictl rm --force "${_pod_id}"
-    systemctl restart kubelet.service
-    '
+        scp /etc/kubernetes/encryption-provider.conf "<user>@${i}:/tmp/encryption-provider.conf"
+        ssh "<user>@${i}" "
+          set -euo pipefail
+          sudo install -o root -g root -m 600 /tmp/encryption-provider.conf /etc/kubernetes/encryption-provider.conf && rm -f /tmp/encryption-provider.conf
+          _pod_name='kube-apiserver'
+          _pod_id=\$(sudo crictl pods --name \"\${_pod_name}\" -q || true)
+          if [[ -z \"\${_pod_id}\" ]]; then
+            echo 'WARN: kube-apiserver pod not found; restarting kubelet'
+            sudo systemctl restart kubelet
+          else
+            sudo crictl stopp \"\${_pod_id}\" || true
+            sudo crictl rmp \"\${_pod_id}\" || true
+            sudo systemctl restart kubelet
+          fi
+        "

331-342: Same restart-sequence issues on node 1.1.1.1

Mirror sudo + crictl pods fix here as well; or simply restart kubelet.

-    _pod_name="kube-apiserver"
-    _pod_id=$(crictl ps --name "${_pod_name}" --no-trunc --quiet)
-    if [[ -z "${_pod_id}" ]]; then
-        echo "FATAL: could not find pod 'kube-apiserver' on node ${i}"
-        exit 1
-    fi
-    crictl rm --force "${_pod_id}"
-    systemctl restart kubelet.service
+    set -euo pipefail
+    _pod_name="kube-apiserver"
+    _pod_id=$(sudo crictl pods --name "${_pod_name}" -q || true)
+    if [[ -z "${_pod_id}" ]]; then
+      echo "WARN: kube-apiserver pod not found; restarting kubelet"
+      sudo systemctl restart kubelet
+    else
+      sudo crictl stopp "${_pod_id}" || true
+      sudo crictl rmp "${_pod_id}" || true
+      sudo systemctl restart kubelet
+    fi

136-137: Security caveat for etcd (2379): restrict exposure and require L4 passthrough

Add explicit warning not to expose 2379 publicly; allow-list control-plane/LB IPs only; no TLS termination on LB.

-1. Configure the load balancer to forward port `2379` to the control plane nodes of both clusters. ONLY TCP mode is supported; forwarding on L7 is not supported.
+1. Configure the load balancer to forward port `2379` to the control-plane nodes of both clusters. ONLY TCP (L4) is supported; no L7. Security: do NOT expose 2379 publicly—restrict access via network ACLs/firewalls to the specific control-plane and LB addresses, and ensure pure TCP pass-through (no TLS termination) on the LB.

289-303: Use placeholders and call out key-order semantics (writes use first key)

Prevent dual-write divergence by keeping Primary key first on both clusters until rotation completes.

@@
-            - name: key1
-              secret: My4xNDE1OTI2NTM1ODk3
-            - name: key2
-              secret: MTE0NTE0MTkxOTgxMA==
+            - name: key1
+              secret: <BASE64_32_BYTE_KEY_FROM_PRIMARY_EXAMPLE_ONLY>
+            - name: key2
+              secret: <BASE64_32_BYTE_KEY_FROM_STANDBY_EXAMPLE_ONLY>

Add after the YAML:

+Important: Kubernetes writes with the first key and reads with all keys. Keep the Primary cluster’s active key listed first on both clusters. Rotate by reordering/removing keys only after confirming re-encryption has completed.
🧹 Nitpick comments (6)
docs/en/install/global_dr.mdx (6)

30-31: Grammar fix for node-naming guidance

“to indicates” → “to indicate.” Also tighten wording.

-* In favor of facilitating troubleshooting and management, it is recommended to name nodes in a style like `standby-global-m1`, to indicates which cluster the node belongs to (Primary or Standby).
+* To facilitate troubleshooting and management, name nodes like `standby-global-m1` to indicate which cluster (Primary or Standby) they belong to.

63-70: Tighten Process Overview phrasing and ownership

Clarify subjects and article use; minor grammar.

-2. Point the domain to the **Primary Cluster's** VIP and install the **Primary Cluster**;
+2. Point the domain to the **Primary Cluster** VIP and install the **Primary Cluster**;
-4. Copy the ETCD encryption key of the **Primary Cluster** to the nodes that will later be the control plane nodes of Standby Cluster;
+4. Copy the etcd encryption key from the **Primary Cluster** to the nodes that will be the Standby cluster’s control plane;
-5. Install and enable the etcd synchronization plugin;
+5. Install and enable the etcd synchronization plugin;
-6. Verify sync status and perform regular checks;
+6. Verify sync status and schedule regular checks;
-7. In case of failure, switch DNS to the standby cluster to complete disaster recovery.
+7. In case of failure, switch DNS to the Standby cluster to complete disaster recovery.

73-79: LB bullet: clarity and ports; grammar fix

Simplify sentence; make subject/object clear.

-* One domain name used as the `Platform Access Address` for both clusters;
-* A set of TLS certificate and private key for that unified domain;
-* Two virtual IPs for both clusters (Primary and Standby);
+* One domain name used as the `Platform Access Address` for both clusters.
+* A TLS certificate and private key for that domain.
+* Two virtual IPs (VIPs), one for each cluster (Primary and Standby).
-  * Pre-configure the Load Balancer to route TCP traffic, which destination port is `80`, `443`, `6443`, `2379` or `11443`, to the control plane nodes of the cluster which endpoint IP is the VIP of LB.
+  * Preconfigure the Load Balancer to route TCP ports `80`, `443`, `6443`, `2379`, and `11443` to the cluster’s control-plane nodes behind each VIP.

83-93: Step 1 WARNING block: concise language and consistency

Reduce verbosity, fix grammar, and keep options consistent.

-While installing the primary cluster of the DR (Disaster Recovery Environment),
-
-* First of all, documenting all of the parameters set while following the guide of the installation web UI. It is necessary to keep some options the same while installing the standby cluster.
+When installing the Primary cluster for DR:
+
+* First, document all parameters used in the installation UI. You must reuse some of them when installing the Standby cluster.
 * The `Self-built VIP` option is NOT available. A **User-provisioned** Load Balancer is required for routing traffic sent to the virtual IP.
-* The `Platform Access Address` MUST be a domain, while `Cluster Endpoint` MUST be the virtual IP address.
+* The `Platform Access Address` MUST be the domain; the `Cluster Endpoint` MUST be the VIP.
 * The `Self-signed Certificate` option is NOT available. It is NECESSARY for both of the clusters to be configured with `An Existing Certificate`.
-* In case the `Image Repository` is set to `Platform Deployment`, the `Username` and `Password` of `Image Repository` MUST NOT be empty; the `IP/Domain` option MUST be set to the unified domain name, which is the `Platform Access Address`.
+* If `Image Repository` is `Platform Deployment`, `Username` and `Password` MUST be set; `IP/Domain` MUST be the unified `Platform Access Address` domain.
 * The `HTTP Port` and `HTTPS Port` options of `Platform Access Address` MUST be 80 and 443.
-* The `Other Platform Access Addresses` option, which is at the second page of the installation web UI (Named `Advanced`), MUST include the virtual IP of the primary cluster.
+* In `Advanced` (page 2), `Other Platform Access Addresses` MUST include the Primary cluster VIP.

117-127: Step 2 WARNING block: grammar and clarity; fix “same of”

Minor English fixes; emphasize sameness.

-While installing the standby cluster of the DR (Disaster Recovery Environment),
+When installing the Standby cluster for DR:
@@
-* The `Cluster Endpoint` option MUST be the virtual IP address.
+* The `Cluster Endpoint` MUST be the VIP.
@@
-the following options MUST be set to the same as the **primary cluster**:
+Set the following options the same as the **Primary cluster**:
@@
-* The options about `Image Repository`. It is IMPORTANT to make sure the credentials of image repository are the same of the **primary cluster**.
+* The `Image Repository` options. Ensure the repository credentials are the same as the **Primary cluster**.

259-261: Clarify violet flag and target

Tiny tweak for clarity; quote flag and entity.

-When using **`violet`** to upload packages to a standby cluster, you must specify the `--dest-repo` parameter with the VIP of the standby cluster.
+When using `violet` to upload packages to the Standby cluster, specify `--dest-repo` with the Standby cluster VIP.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 27aeb5a and ef89b1e.

📒 Files selected for processing (1)
  • docs/en/install/global_dr.mdx (4 hunks)
🧰 Additional context used
🪛 LanguageTool
docs/en/install/global_dr.mdx

[grammar] ~64-~64: There might be a mistake here.
Context: ...VIP and install the Primary Cluster; 3. Temporarily switch DNS resolution to the...

(QB_NEW_EN)


[grammar] ~65-~65: There might be a mistake here.
Context: ...ndby VIP to install the Standby Cluster; 4. Copy the ETCD encryption key of the **Pr...

(QB_NEW_EN)


[grammar] ~66-~66: There might be a mistake here.
Context: ...t will later be the control plane nodes of Standby Cluster; 5. Install and enable ...

(QB_NEW_EN)


[grammar] ~66-~66: There might be a mistake here.
Context: ... control plane nodes of Standby Cluster; 5. Install and enable the etcd synchronizat...

(QB_NEW_EN)


[grammar] ~67-~67: There might be a mistake here.
Context: ... enable the etcd synchronization plugin; 6. Verify sync status and perform regular c...

(QB_NEW_EN)


[grammar] ~68-~68: There might be a mistake here.
Context: ... sync status and perform regular checks; 7. In case of failure, switch DNS to the st...

(QB_NEW_EN)


[grammar] ~73-~73: There might be a mistake here.
Context: ...tform Access Address` for both clusters; * A set of TLS certificate and private key...

(QB_NEW_EN)


[grammar] ~74-~74: There might be a mistake here.
Context: ...and private key for that unified domain; * Two virtual IPs for both clusters (Prima...

(QB_NEW_EN)


[style] ~86-~86: Often, this adverbial phrase is redundant. Consider using an alternative.
Context: ... DR (Disaster Recovery Environment), * First of all, documenting all of the parameters set ...

(FIRST_OF_ALL)


[style] ~86-~86: Consider removing “of” to be more concise
Context: ...ironment), * First of all, documenting all of the parameters set while following the guid...

(ALL_OF_THE)


[grammar] ~87-~87: There might be a mistake here.
Context: ... routing traffic sent to the virtual IP. * The Platform Access Address MUST be a ...

(QB_NEW_EN)


[grammar] ~88-~88: There might be a mistake here.
Context: ...ndpointMUST be the virtual IP address. * TheSelf-signed Certificate` option is ...

(QB_NEW_EN)


[grammar] ~97-~97: There might be a mistake here.
Context: ...stallation: * Prepare for Installation * Installing ### Step ...

(QB_NEW_EN)


[grammar] ~123-~123: There might be a mistake here.
Context: ... to the same as the primary cluster: * The options about `Platform Access Addre...

(QB_NEW_EN)


[grammar] ~124-~124: There might be a mistake here.
Context: ...options about Platform Access Address. * The options about Certificate. * The o...

(QB_NEW_EN)


[grammar] ~126-~126: There might be a mistake here.
Context: ... IMPORTANT to make sure the credentials of image repository are the same of the **...

(QB_NEW_EN)


[grammar] ~131-~131: There might be a mistake here.
Context: ...stallation: * Prepare for Installation * Installing ### Step ...

(QB_NEW_EN)

🪛 Gitleaks (8.27.2)
docs/en/install/global_dr.mdx

299-299: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

Comment thread docs/en/install/global_dr.mdx
Comment thread docs/en/install/global_dr.mdx
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/en/install/global_dr.mdx (1)

147-156: kubectl name extraction bug: command uses full row, not pod name

kubectl get po --no-headers | head -1 returns multiple columns; kubectl logs/delete will fail. Use -o name or jsonpath.

-kubectl logs -n cpaas-system $(kubectl get po -n cpaas-system -l app=etcd-sync --no-headers | head -1) | grep -i "Start Sync update"
+kubectl logs -n cpaas-system "$(kubectl get po -n cpaas-system -l app=etcd-sync -o name | head -1)" | grep -i "Start Sync update"
@@
-kubectl delete po -n cpaas-system $(kubectl get po -n cpaas-system -l app=etcd-sync --no-headers | head -1)
+kubectl delete po -n cpaas-system "$(kubectl get po -n cpaas-system -l app=etcd-sync -o name | sed 's|.*/||' | head -1)"
♻️ Duplicate comments (6)
docs/en/install/global_dr.mdx (6)

137-137: Security caveat for etcd (2379) exposure

Re‑add the warning not to expose 2379 publicly; restrict to allow‑listed peers; ensure pure TCP pass‑through (no TLS termination).

-1. Configure the load balancer to forward port `2379` to the control plane nodes of both clusters. ONLY TCP mode is supported; forwarding on L7 is not supported.
+1. Configure the load balancer to forward port `2379` to the control‑plane nodes of both clusters. Use TCP pass‑through only (no L7/TLS termination), and restrict access to the specific peer/load‑balancer addresses. Do not expose 2379 publicly.

192-208: Re-run ES template script after restart (as instructed)

You say “then execute the script to check the cluster again,” but you don’t re-run it.

 xargs -r -t -- kubectl delete po -n cpaas-system <<< "${_es_pods}"
+sleep 5
+# Re-run the check after pods restart
+bash /root/ensure-asm-template.sh

290-304: Replace remaining Base64 secrets with placeholders and call out key‑order semantics

Also document “first key writes, all keys read.”

-            - name: key1
-              secret: My4xNDE1OTI2NTM1ODk3
-            - name: key2
-              secret: MTE0NTE0MTkxOTgxMA==
+            - name: key1
+              secret: <BASE64_32_BYTE_KEY_FROM_PRIMARY_EXAMPLE_ONLY>
+            - name: key2
+              secret: <BASE64_32_BYTE_KEY_FROM_STANDBY_EXAMPLE_ONLY>

Add after the YAML:

+Important: Kubernetes writes using the first key and reads with all keys. Keep the Primary’s active key listed first on both clusters until rotation completes to avoid dual‑write divergence.

270-286: Replace Base64 literal secret with explicit placeholder + add disclaimer

Avoid secret-scanner hits and accidental reuse.

-            - name: key1
-              secret: MTE0NTE0MTkxOTgxMA==
+            - name: key1
+              secret: <BASE64_32_BYTE_KEY_FROM_STANDBY_EXAMPLE_ONLY>

Add immediately below the YAML:

+> Note: Replace placeholders with your own randomly generated 32‑byte keys encoded in base64. Do not reuse example values.

106-113: Encryption config copy: reduce file permissions to 600

Sensitive file; 640 exposes group read. Use 600.

-ssh "<user>@$i" "sudo install -o root -g root -m 640 /tmp/encryption-provider.conf /etc/kubernetes/encryption-provider.conf && rm -f /tmp/encryption-provider.conf"
+ssh "<user>@$i" "sudo install -o root -g root -m 600 /tmp/encryption-provider.conf /etc/kubernetes/encryption-provider.conf && rm -f /tmp/encryption-provider.conf"

305-333: Remote restart script: incorrect crictl usage, quoting, and message variable

  • Uses crictl ps/rm (containers) while treating them as pods.
  • Single‑quoted here‑doc prevents local ${i} expansion; echo references ${i} which isn’t defined remotely.
  • Prefer simple kubelet restart; static pod will be recreated.
-        scp /etc/kubernetes/encryption-provider.conf "<user>@${i}:/tmp/encryption-provider.conf"
-        ssh "<user>@${i}" '
-    #!/bin/bash
-    set -euo pipefail
-    
-    sudo install -o root -g root -m 640 /tmp/encryption-provider.conf /etc/kubernetes/encryption-provider.conf && rm -f /tmp/encryption-provider.conf
-    _pod_name="kube-apiserver"
-    _pod_id=$(sudo crictl ps --name "${_pod_name}" --no-trunc --quiet)
-    if [[ -z "${_pod_id}" ]]; then
-        echo "FATAL: could not find pod 'kube-apiserver' on node ${i}"
-        exit 1
-    fi
-    sudo crictl rm --force "${_pod_id}"
-    sudo systemctl restart kubelet.service
-    '
+        scp /etc/kubernetes/encryption-provider.conf "<user>@${i}:/tmp/encryption-provider.conf"
+        ssh "<user>@${i}" "bash -s" <<'EOF'
+set -euo pipefail
+sudo install -o root -g root -m 600 /tmp/encryption-provider.conf /etc/kubernetes/encryption-provider.conf && rm -f /tmp/encryption-provider.conf
+# For static kube-apiserver, restarting kubelet is sufficient
+sudo systemctl restart kubelet.service
+EOF
🧹 Nitpick comments (9)
docs/en/install/global_dr.mdx (9)

30-31: Grammar/clarity: tighten node-naming guidance

“to indicates” → “to indicate”. Suggest simpler phrasing.

-* In favor of facilitating troubleshooting and management, it is recommended to name nodes in a style like `standby-global-m1`, to indicates which cluster the node belongs to (Primary or Standby).
+* To aid troubleshooting and management, name nodes like `standby-global-m1` to indicate which cluster they belong to (Primary or Standby).

63-70: Process wording and parallelism

Improve grammar; use “standby control-plane nodes”; avoid repeated semicolons.

-2. Point the domain to the **Primary Cluster's** VIP and install the **Primary Cluster**;
-3. Temporarily switch DNS resolution to the standby VIP to install the Standby Cluster;
-4. Copy the ETCD encryption key of the **Primary Cluster** to the nodes that will later be the control plane nodes of Standby Cluster;
-5. Install and enable the etcd synchronization plugin;
-6. Verify sync status and perform regular checks;
-7. In case of failure, switch DNS to the standby cluster to complete disaster recovery.
+2. Point the domain to the **Primary Cluster** VIP and install the **Primary Cluster**.
+3. Temporarily switch DNS to the standby VIP and install the Standby Cluster.
+4. Copy the Primary’s ETCD encryption config to the standby control‑plane nodes.
+5. Install and enable the etcd synchronization plugin.
+6. Verify sync status and perform routine checks.
+7. On failure, switch DNS to the standby cluster to complete recovery.

73-77: Resources list grammar and LB sentence

Tighten grammar; clarify LB VIP wording.

-* One domain name used as the `Platform Access Address` for both clusters;
-* A set of TLS certificate and private key for that unified domain;
-* Two virtual IPs for both clusters (Primary and Standby);
-  * Pre-configure the Load Balancer to route TCP traffic, which destination port is `80`, `443`, `6443`, `2379` or `11443`, to the control plane nodes of the cluster which endpoint IP is the VIP of LB.
+* One domain name used as the `Platform Access Address` for both clusters.
+* A TLS certificate and private key for that domain.
+* Two virtual IPs (Primary and Standby).
+  * Pre‑configure the Load Balancer to TCP‑forward ports `80`, `443`, `6443`, `2379`, and `11443` to the control‑plane nodes behind each VIP.

83-93: Installation WARNING block: grammar and clarity

Reduce awkward phrasing; improve imperative wording; tighten certificate/image repo notes.

-While installing the primary cluster of the DR (Disaster Recovery Environment),
-* First of all, documenting all of the parameters set while following the guide of the installation web UI. It is necessary to keep some options the same while installing the standby cluster.
+When installing the primary cluster for DR:
+* Record all parameters set in the installation UI. You must reuse several of them when installing the standby cluster.
@@
-* The `Platform Access Address` MUST be a domain, while `Cluster Endpoint` MUST be the virtual IP address.
+* The `Platform Access Address` MUST be a domain; the `Cluster Endpoint` MUST be the virtual IP address.
@@
-* In case the `Image Repository` is set to `Platform Deployment`, the `Username` and `Password` of `Image Repository` MUST NOT be empty; the `IP/Domain` option MUST be set to the unified domain name, which is the `Platform Access Address`.
+* If `Image Repository` is set to `Platform Deployment`, `Username` and `Password` MUST be set; `IP/Domain` MUST be the unified domain (the `Platform Access Address`).

116-129: Step 2 wording and capitalization

Sentence case; clarify “same as primary”.

-3. Install the standby cluster in the same way as the primary cluster
+3. Install the standby cluster in the same way as the Primary Cluster.
@@
-While installing the standby cluster of the DR (Disaster Recovery Environment),
+When installing the standby cluster:
@@
-the following options MUST be set to the same as the **primary cluster**:
+set the following options to match the **Primary Cluster**:
@@
-* The options about `Image Repository`. It is IMPORTANT to make sure the credentials of image repository are the same of the **primary cluster**.
+* `Image Repository` options. Ensure the credentials are identical to the **Primary Cluster**.

160-169: Add curl timeout and quiet flags; keep IPv6 handling

Improve operability.

-curl $mirror_new_svc/check
+curl -fsS --connect-timeout 5 "$mirror_new_svc/check"

252-254: Routine check: IPv6-safe curl like Step 3

Inline variant lacks IPv6 bracket logic.

-curl $(kubectl get svc -n cpaas-system etcd-sync-monitor -o jsonpath='{.spec.clusterIP}')/check
+ip=$(kubectl get svc -n cpaas-system etcd-sync-monitor -o jsonpath='{.spec.clusterIP}')
+[[ $ip =~ ^[0-9a-fA-F:]+$ ]] && ip="[$ip]"
+curl -fsS --connect-timeout 5 "$ip/check"

270-271: Placeholder token formatting

Avoid spaces inside angle‑bracket placeholders; they’re confusing in CLI.

-ssh <user>@<STANDBY cluster control plane node> sudo cat /etc/kubernetes/encryption-provider.conf
+ssh "<user>@<standby_control_plane_node>" "sudo cat /etc/kubernetes/encryption-provider.conf"

213-214: DNS switch wording

Clarify exact action.

-5. Switch the platform domain DNS to the standby VIP, which now becomes the Primary Cluster;
+5. Update the platform domain’s A/AAAA record from the Primary VIP to the standby VIP (the standby now becomes the Primary).
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ef89b1e and be400a5.

📒 Files selected for processing (1)
  • docs/en/install/global_dr.mdx (4 hunks)
🧰 Additional context used
🪛 LanguageTool
docs/en/install/global_dr.mdx

[grammar] ~64-~64: There might be a mistake here.
Context: ...VIP and install the Primary Cluster; 3. Temporarily switch DNS resolution to the...

(QB_NEW_EN)


[grammar] ~65-~65: There might be a mistake here.
Context: ...ndby VIP to install the Standby Cluster; 4. Copy the ETCD encryption key of the **Pr...

(QB_NEW_EN)


[grammar] ~66-~66: There might be a mistake here.
Context: ...t will later be the control plane nodes of Standby Cluster; 5. Install and enable ...

(QB_NEW_EN)


[grammar] ~66-~66: There might be a mistake here.
Context: ... control plane nodes of Standby Cluster; 5. Install and enable the etcd synchronizat...

(QB_NEW_EN)


[grammar] ~67-~67: There might be a mistake here.
Context: ... enable the etcd synchronization plugin; 6. Verify sync status and perform regular c...

(QB_NEW_EN)


[grammar] ~68-~68: There might be a mistake here.
Context: ... sync status and perform regular checks; 7. In case of failure, switch DNS to the st...

(QB_NEW_EN)


[grammar] ~73-~73: There might be a mistake here.
Context: ...tform Access Address` for both clusters; * A set of TLS certificate and private key...

(QB_NEW_EN)


[grammar] ~74-~74: There might be a mistake here.
Context: ...and private key for that unified domain; * Two virtual IPs for both clusters (Prima...

(QB_NEW_EN)


[style] ~86-~86: Often, this adverbial phrase is redundant. Consider using an alternative.
Context: ... DR (Disaster Recovery Environment), * First of all, documenting all of the parameters set ...

(FIRST_OF_ALL)


[style] ~86-~86: Consider removing “of” to be more concise
Context: ...ironment), * First of all, documenting all of the parameters set while following the guid...

(ALL_OF_THE)


[grammar] ~87-~87: There might be a mistake here.
Context: ... routing traffic sent to the virtual IP. * The Platform Access Address MUST be a ...

(QB_NEW_EN)


[grammar] ~88-~88: There might be a mistake here.
Context: ...ndpointMUST be the virtual IP address. * TheSelf-signed Certificate` option is ...

(QB_NEW_EN)


[grammar] ~97-~97: There might be a mistake here.
Context: ...stallation: * Prepare for Installation * Installing ### Step ...

(QB_NEW_EN)


[grammar] ~124-~124: There might be a mistake here.
Context: ... to the same as the primary cluster: * The options about `Platform Access Addre...

(QB_NEW_EN)


[grammar] ~125-~125: There might be a mistake here.
Context: ...options about Platform Access Address. * The options about Certificate. * The o...

(QB_NEW_EN)


[grammar] ~127-~127: There might be a mistake here.
Context: ... IMPORTANT to make sure the credentials of image repository are the same of the **...

(QB_NEW_EN)


[grammar] ~132-~132: There might be a mistake here.
Context: ...stallation: * Prepare for Installation * Installing ### Step ...

(QB_NEW_EN)

🪛 Gitleaks (8.27.2)
docs/en/install/global_dr.mdx

300-300: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

Comment thread docs/en/install/global_dr.mdx
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
docs/en/install/global_dr.mdx (2)

148-156: kubectl logs/delete selection is wrong; use -o name.

--no-headers | head -1 returns multiple columns; commands will fail.

-kubectl logs -n cpaas-system $(kubectl get po -n cpaas-system -l app=etcd-sync --no-headers | head -1) | grep -i "Start Sync update"
+pod=$(kubectl get po -n cpaas-system -l app=etcd-sync -o name | head -1)
+kubectl logs -n cpaas-system "$pod" | grep -i "Start Sync update"
@@
-kubectl delete po -n cpaas-system $(kubectl get po -n cpaas-system -l app=etcd-sync --no-headers | head -1)
+kubectl delete -n cpaas-system "$(kubectl get po -n cpaas-system -l app=etcd-sync -o name | head -1)"

248-254: IPv6-safe routine check (align with earlier logic).

Use the bracketed IPv6 handling as above to avoid curl failures.

-curl $(kubectl get svc -n cpaas-system etcd-sync-monitor -o jsonpath='{.spec.clusterIP}')/check
+ip=$(kubectl get svc -n cpaas-system etcd-sync-monitor -o jsonpath='{.spec.clusterIP}')
+if [[ "$ip" =~ ^[0-9a-fA-F:]+$ ]]; then svc="[$ip]"; else svc="$ip"; fi
+curl "$svc"/check
♻️ Duplicate comments (5)
docs/en/install/global_dr.mdx (5)

137-138: Add security caveat for etcd (2379): restrict access and L4 pass‑through only.

Avoid exposing etcd publicly; allow‑list control‑plane/LB IPs; no TLS termination on LB.

-1. Configure the load balancer to forward port `2379` to the control plane nodes of both clusters. ONLY TCP mode is supported; forwarding on L7 is not supported.
+1. Configure the load balancer to forward port `2379` to the control plane nodes of both clusters. ONLY TCP (L4) is supported; L7 forwarding is not supported.
+> Security: Do NOT expose 2379 publicly. Restrict access via network ACLs/firewalls to control‑plane and LB IPs only, and ensure pure TCP pass‑through (no TLS termination or inspection).

192-208: Re-run ES check after restart (as stated).

Doc says “then execute the script again” but snippet doesn’t. Add a second run after pod restarts.

-        # In case the script returned the 401 error, restart Elasticsearch
-        # then execute the script to check the cluster again
-        bash /root/ensure-asm-template.sh
+        # If the script returns 401, restart Elasticsearch then re-run the check
+        bash /root/ensure-asm-template.sh
@@
-        xargs -r -t -- kubectl delete po -n cpaas-system <<< "${_es_pods}"
+        xargs -r -t -- kubectl delete po -n cpaas-system <<< "${_es_pods}"
+        # Re-run after restart
+        bash /root/ensure-asm-template.sh

270-286: Replace Base64 key with explicit placeholder + add disclaimer.

Avoid secret‑scanner hits and accidental reuse.

-            - name: key1
-              secret: MTE0NTE0MTkxOTgxMA==
+            - name: key1
+              secret: <BASE64_32_BYTE_KEY_FROM_STANDBY_EXAMPLE_ONLY>
+> Note: Replace placeholders with your own 32‑byte keys encoded in base64. Do not reuse example values.

288-304: Replace Base64 literals, and call out key‑order semantics.

K8s writes with the first key and reads with all. Keep the Primary’s key first until rotation completes.

-            - name: key1
-              secret: My4xNDE1OTI2NTM1ODk3
-            - name: key2
-              secret: MTE0NTE0MTkxOTgxMA==
+            - name: key1
+              secret: <BASE64_32_BYTE_KEY_FROM_PRIMARY_EXAMPLE_ONLY>
+            - name: key2
+              secret: <BASE64_32_BYTE_KEY_FROM_STANDBY_EXAMPLE_ONLY>
+> Important: The first key is used for writes. Keep the Primary’s key first on both clusters to avoid dual‑write divergence. Reorder/remove keys only during a planned rotation window after confirming migration.

335-346: Prefer kubelet restart over crictl pod/ctr manipulation.

Simpler, less error‑prone, and consistent with earlier step.

-_pod_name="kube-apiserver"
-_pod_id=$(sudo crictl ps --name "${_pod_name}" --no-trunc --quiet)
-if [[ -z "${_pod_id}" ]]; then
-    echo "FATAL: could not find pod 'kube-apiserver' on current node"
-    exit 1
-fi
-sudo crictl rm --force "${_pod_id}"
-sudo systemctl restart kubelet.service
+sudo systemctl restart kubelet.service
🧹 Nitpick comments (5)
docs/en/install/global_dr.mdx (5)

30-31: Grammar fix: “to indicates” → “to indicate”.

Small readability tweak.

-* In favor of facilitating troubleshooting and management, it is recommended to name nodes in a style like `standby-global-m1`, to indicates which cluster the node belongs to (Primary or Standby).
+* To facilitate troubleshooting and management, name standby nodes like `standby-global-m1` to indicate which cluster the node belongs to (Primary or Standby).

64-70: Tighten Process Overview phrasing.

Minor grammar/consistency.

-2. Point the domain to the **Primary Cluster's** VIP and install the **Primary Cluster**;
-3. Temporarily switch DNS resolution to the standby VIP to install the Standby Cluster;
-4. Copy the ETCD encryption key of the **Primary Cluster** to the nodes that will later be the control plane nodes of Standby Cluster;
+2. Point the domain to the **Primary Cluster** VIP and install the **Primary Cluster**.
+3. Temporarily point DNS to the standby VIP and install the **Standby Cluster**.
+4. Copy the ETCD encryption key from the **Primary Cluster** to the future control‑plane nodes of the **Standby Cluster**.
-5. Install and enable the etcd synchronization plugin;
-6. Verify sync status and perform regular checks;
-7. In case of failure, switch DNS to the standby cluster to complete disaster recovery.
+5. Install and enable the etcd synchronization plugin.
+6. Verify sync status and perform regular checks.
+7. If the primary fails, switch DNS to the standby cluster to complete disaster recovery.

73-78: Resource list grammar + LB wording.

Clearer phrasing.

-* One domain name used as the `Platform Access Address` for both clusters;
-* A set of TLS certificate and private key for that unified domain;
+* One domain name used as the `Platform Access Address` for both clusters.
+* A TLS certificate and private key for that unified domain.
-* Two virtual IPs for both clusters (Primary and Standby);
+* Two virtual IPs (VIPs): one per cluster (Primary and Standby).
@@
-  * Pre-configure the Load Balancer to route TCP traffic, which destination port is `80`, `443`, `6443`, `2379` or `11443`, to the control plane nodes of the cluster which endpoint IP is the VIP of LB.
+  * Pre‑configure the Load Balancer to TCP‑forward ports `80`, `443`, `6443`, `2379`, and `11443` to the control‑plane nodes behind the cluster VIP.

83-93: Step 1 warning block: tighten language and consistency.

Improve clarity; keep MUST/NOT consistent.

-While installing the primary cluster of the DR (Disaster Recovery Environment),
-* First of all, documenting all of the parameters set while following the guide of the installation web UI. It is necessary to keep some options the same while installing the standby cluster.
+While installing the Primary cluster in the DR environment:
+* First, record all parameters used in the installation UI. Some options must match when installing the Standby cluster.
@@
-* The `Platform Access Address` MUST be a domain, while `Cluster Endpoint` MUST be the virtual IP address.
+* The `Platform Access Address` MUST be a domain; the `Cluster Endpoint` MUST be the virtual IP address (VIP).
@@
-* In case the `Image Repository` is set to `Platform Deployment`, the `Username` and `Password` of `Image Repository` MUST NOT be empty; the `IP/Domain` option MUST be set to the unified domain name, which is the `Platform Access Address`.
+* If `Image Repository` is `Platform Deployment`, `Username` and `Password` MUST NOT be empty; `IP/Domain` MUST be the unified domain (the `Platform Access Address`).
@@
-* The `Other Platform Access Addresses` option, which is at the second page of the installation web UI (Named `Advanced`), MUST include the virtual IP of the primary cluster.
+* On the Advanced page, `Other Platform Access Addresses` MUST include the Primary VIP.

118-128: Step 2 warning block: grammar and consistency.

Match Primary/Standby capitalization; fix “same of”.

-While installing the standby cluster of the DR (Disaster Recovery Environment),
+While installing the Standby cluster in the DR environment:
@@
-* The `Cluster Endpoint` option MUST be the virtual IP address.
+* The `Cluster Endpoint` MUST be the virtual IP address (VIP).
@@
-the following options MUST be set to the same as the **primary cluster**:
-* The options about `Platform Access Address`.
-* The options about `Certificate`.
-* The options about `Image Repository`. It is IMPORTANT to make sure the credentials of image repository are the same of the **primary cluster**.
+The following options MUST match the **Primary Cluster**:
+* `Platform Access Address`.
+* `Certificate`.
+* `Image Repository` (use the same credentials as the **Primary Cluster**).
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between be400a5 and 6e9fcee.

📒 Files selected for processing (1)
  • docs/en/install/global_dr.mdx (4 hunks)
🧰 Additional context used
🪛 LanguageTool
docs/en/install/global_dr.mdx

[grammar] ~64-~64: There might be a mistake here.
Context: ...VIP and install the Primary Cluster; 3. Temporarily switch DNS resolution to the...

(QB_NEW_EN)


[grammar] ~65-~65: There might be a mistake here.
Context: ...ndby VIP to install the Standby Cluster; 4. Copy the ETCD encryption key of the **Pr...

(QB_NEW_EN)


[grammar] ~66-~66: There might be a mistake here.
Context: ...t will later be the control plane nodes of Standby Cluster; 5. Install and enable ...

(QB_NEW_EN)


[grammar] ~66-~66: There might be a mistake here.
Context: ... control plane nodes of Standby Cluster; 5. Install and enable the etcd synchronizat...

(QB_NEW_EN)


[grammar] ~67-~67: There might be a mistake here.
Context: ... enable the etcd synchronization plugin; 6. Verify sync status and perform regular c...

(QB_NEW_EN)


[grammar] ~68-~68: There might be a mistake here.
Context: ... sync status and perform regular checks; 7. In case of failure, switch DNS to the st...

(QB_NEW_EN)


[grammar] ~73-~73: There might be a mistake here.
Context: ...tform Access Address` for both clusters; * A set of TLS certificate and private key...

(QB_NEW_EN)


[grammar] ~74-~74: There might be a mistake here.
Context: ...and private key for that unified domain; * Two virtual IPs for both clusters (Prima...

(QB_NEW_EN)


[style] ~86-~86: Often, this adverbial phrase is redundant. Consider using an alternative.
Context: ... DR (Disaster Recovery Environment), * First of all, documenting all of the parameters set ...

(FIRST_OF_ALL)


[style] ~86-~86: Consider removing “of” to be more concise
Context: ...ironment), * First of all, documenting all of the parameters set while following the guid...

(ALL_OF_THE)


[grammar] ~87-~87: There might be a mistake here.
Context: ... routing traffic sent to the virtual IP. * The Platform Access Address MUST be a ...

(QB_NEW_EN)


[grammar] ~88-~88: There might be a mistake here.
Context: ...ndpointMUST be the virtual IP address. * TheSelf-signed Certificate` option is ...

(QB_NEW_EN)


[grammar] ~97-~97: There might be a mistake here.
Context: ...stallation: * Prepare for Installation * Installing ### Step ...

(QB_NEW_EN)


[grammar] ~124-~124: There might be a mistake here.
Context: ... to the same as the primary cluster: * The options about `Platform Access Addre...

(QB_NEW_EN)


[grammar] ~125-~125: There might be a mistake here.
Context: ...options about Platform Access Address. * The options about Certificate. * The o...

(QB_NEW_EN)


[grammar] ~127-~127: There might be a mistake here.
Context: ... IMPORTANT to make sure the credentials of image repository are the same of the **...

(QB_NEW_EN)


[grammar] ~132-~132: There might be a mistake here.
Context: ...stallation: * Prepare for Installation * Installing ### Step ...

(QB_NEW_EN)

🪛 Gitleaks (8.27.2)
docs/en/install/global_dr.mdx

300-300: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

Comment thread docs/en/install/global_dr.mdx
Comment thread docs/en/install/global_dr.mdx
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (6)
docs/en/install/global_dr.mdx (6)

192-208: Re-run the ES verification script after restart, as instructed.
The text says “then execute the script to check the cluster again” but the snippet doesn’t re-run it post-restart.

-        # In case the script returned the 401 error, restart Elasticsearch
-        # then execute the script to check the cluster again
-        bash /root/ensure-asm-template.sh
+        # If the script returns 401, run it once, then restart Elasticsearch and re-run the check
+        bash /root/ensure-asm-template.sh
@@
-        xargs -r -t -- kubectl delete po -n cpaas-system <<< "${_es_pods}"
+        xargs -r -t -- kubectl delete po -n cpaas-system <<< "${_es_pods}"
+        # Re-run after pods are recreated
+        bash /root/ensure-asm-template.sh

137-138: Add explicit security warning for etcd forwarding (2379).
Call out “no public exposure, L4 pass‑through only.”

-1. Configure the load balancer to forward port `2379` to the control plane nodes of both clusters. ONLY TCP mode is supported; forwarding on L7 is not supported.
+1. Configure the load balancer to forward port `2379` to the control-plane nodes of both clusters. ONLY TCP (L4) mode is supported; L7 forwarding is not supported.
+   Security: Do not expose `2379` publicly. Restrict access via network ACLs/allow-lists to control‑plane and LB addresses only, with pure TCP pass‑through (no TLS termination).

270-286: Replace Base64 literals with placeholders and add a disclaimer.
These look like real secrets and will trigger secret scanners or be reused accidentally.

-            - name: key1
-              secret: MTE0NTE0MTkxOTgxMA==
+            - name: key1
+              secret: <BASE64_32_BYTE_KEY_FROM_STANDBY_EXAMPLE_ONLY>

Add right below the YAML block:

+> Note: Replace placeholders with your own 32‑byte keys encoded in Base64. Do not reuse example values.

290-303: Use placeholders in both examples and document key-order semantics.

  • Swap Base64 strings for explicit placeholders.
  • Important: Kubernetes writes with the first key; keep the Primary’s key first on both clusters until rotation completes to avoid dual-writes.
             - name: key1
-              secret: My4xNDE1OTI2NTM1ODk3
+              secret: <BASE64_32_BYTE_KEY_FROM_PRIMARY_EXAMPLE_ONLY>
             - name: key2
-              secret: MTE0NTE0MTkxOTgxMA==
+              secret: <BASE64_32_BYTE_KEY_FROM_STANDBY_EXAMPLE_ONLY>

Add immediately after the YAML:

+Important: The first key in the list is used for writes, while all keys are used for reads. Keep the Primary cluster’s active key first on both clusters until rotation completes.

305-333: Remote script: fix variable expansion, drop brittle crictl usage, keep perms hardened.

  • ${i} won’t expand inside single quotes on the remote; the message prints literally.
  • crictl logic is brittle and unnecessary for static pod reload; restarting kubelet is sufficient after replacing the file.
  • Keep install -m 600.
-        scp /etc/kubernetes/encryption-provider.conf "<user>@${i}:/tmp/encryption-provider.conf"
-        ssh "<user>@${i}" '
-    #!/bin/bash
-    set -euo pipefail
-    
-    sudo install -o root -g root -m 600 /tmp/encryption-provider.conf /etc/kubernetes/encryption-provider.conf && rm -f /tmp/encryption-provider.conf
-    _pod_name="kube-apiserver"
-    _pod_id=$(sudo crictl ps --name "${_pod_name}" --no-trunc --quiet)
-    if [[ -z "${_pod_id}" ]]; then
-        echo "FATAL: could not find pod 'kube-apiserver' on node ${i}"
-        exit 1
-    fi
-    sudo crictl rm --force "${_pod_id}"
-    sudo systemctl restart kubelet.service
-    '
+        scp /etc/kubernetes/encryption-provider.conf "<user>@${i}:/tmp/encryption-provider.conf"
+        ssh "<user>@${i}" "bash -s" <<'REMOTE'
+set -euo pipefail
+sudo install -o root -g root -m 600 /tmp/encryption-provider.conf /etc/kubernetes/encryption-provider.conf && rm -f /tmp/encryption-provider.conf
+# For static pods, kubelet restart is sufficient to pick up the new config
+sudo systemctl restart kubelet.service
+REMOTE

335-346: Single-node restart: simplify and avoid undefined ${i}; prefer kubelet restart.
The crictl path is brittle; restarting kubelet after replacing the file is reliable for static pods.

-    _pod_name="kube-apiserver"
-    _pod_id=$(sudo crictl ps --name "${_pod_name}" --no-trunc --quiet)
-    if [[ -z "${_pod_id}" ]]; then
-        echo "FATAL: could not find pod 'kube-apiserver' on current node"
-        exit 1
-    fi
-    sudo crictl rm --force "${_pod_id}"
-    sudo systemctl restart kubelet.service
+    sudo systemctl restart kubelet.service
🧹 Nitpick comments (4)
docs/en/install/global_dr.mdx (4)

30-31: Grammar: fix “to indicates” and tighten phrasing.
[建议] Change “to indicates” → “to indicate” and simplify the sentence.

-* In favor of facilitating troubleshooting and management, it is recommended to name nodes in a style like `standby-global-m1`, to indicates which cluster the node belongs to (Primary or Standby).
+* To simplify troubleshooting and management, name nodes like `standby-global-m1` to indicate which cluster the node belongs to (Primary or Standby).

83-93: Polish the WARNING block for clarity and grammar.
Minor edits improve readability; content unchanged.

-While installing the primary cluster of the DR (Disaster Recovery Environment),
-
-* First of all, documenting all of the parameters set while following the guide of the installation web UI. It is necessary to keep some options the same while installing the standby cluster.
+When installing the primary cluster for the DR environment:
+
+* First, document all parameters configured in the installation UI. You must reuse several of them when installing the standby cluster.
@@
-* The `Platform Access Address` MUST be a domain, while `Cluster Endpoint` MUST be the virtual IP address.
+* The `Platform Access Address` MUST be a domain, and the `Cluster Endpoint` MUST be the virtual IP address.
@@
-* The `Other Platform Access Addresses` option, which is at the second page of the installation web UI (Named `Advanced`), MUST include the virtual IP of the primary cluster.
+* On the `Advanced` page, the `Other Platform Access Addresses` option MUST include the primary cluster’s VIP.

118-128: Tighten grammar and ensure “match Primary Cluster” phrasing.

-while installing the standby cluster of the DR (Disaster Recovery Environment),
+when installing the standby cluster in the DR environment:
@@
-the following options MUST be set to the same as the **primary cluster**:
+the following options MUST match the **Primary Cluster**:
@@
-* The options about `Image Repository`. It is IMPORTANT to make sure the credentials of image repository are the same of the **primary cluster**.
+* `Image Repository` options. Ensure the image repository credentials are identical to the **Primary Cluster**.

252-254: IPv6-safe curl in Routine Checks.
Match the IPv6-bracketing logic used earlier to avoid failures with IPv6 ClusterIP.

-curl $(kubectl get svc -n cpaas-system etcd-sync-monitor -o jsonpath='{.spec.clusterIP}')/check
+mirror_svc=$(kubectl get svc -n cpaas-system etcd-sync-monitor -o jsonpath='{.spec.clusterIP}')
+if [[ $mirror_svc =~ ^[0-9a-fA-F:]+$ ]]; then mirror_svc="[$mirror_svc]"; fi
+curl "${mirror_svc}/check"
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 6e9fcee and 5f8b2de.

📒 Files selected for processing (1)
  • docs/en/install/global_dr.mdx (4 hunks)
🧰 Additional context used
🪛 LanguageTool
docs/en/install/global_dr.mdx

[grammar] ~64-~64: There might be a mistake here.
Context: ...VIP and install the Primary Cluster; 3. Temporarily switch DNS resolution to the...

(QB_NEW_EN)


[grammar] ~65-~65: There might be a mistake here.
Context: ...ndby VIP to install the Standby Cluster; 4. Copy the ETCD encryption key of the **Pr...

(QB_NEW_EN)


[grammar] ~66-~66: There might be a mistake here.
Context: ...t will later be the control plane nodes of Standby Cluster; 5. Install and enable ...

(QB_NEW_EN)


[grammar] ~66-~66: There might be a mistake here.
Context: ... control plane nodes of Standby Cluster; 5. Install and enable the etcd synchronizat...

(QB_NEW_EN)


[grammar] ~67-~67: There might be a mistake here.
Context: ... enable the etcd synchronization plugin; 6. Verify sync status and perform regular c...

(QB_NEW_EN)


[grammar] ~68-~68: There might be a mistake here.
Context: ... sync status and perform regular checks; 7. In case of failure, switch DNS to the st...

(QB_NEW_EN)


[grammar] ~73-~73: There might be a mistake here.
Context: ...tform Access Address` for both clusters; * A set of TLS certificate and private key...

(QB_NEW_EN)


[grammar] ~74-~74: There might be a mistake here.
Context: ...and private key for that unified domain; * Two virtual IPs for both clusters (Prima...

(QB_NEW_EN)


[style] ~86-~86: Often, this adverbial phrase is redundant. Consider using an alternative.
Context: ... DR (Disaster Recovery Environment), * First of all, documenting all of the parameters set ...

(FIRST_OF_ALL)


[style] ~86-~86: Consider removing “of” to be more concise
Context: ...ironment), * First of all, documenting all of the parameters set while following the guid...

(ALL_OF_THE)


[grammar] ~87-~87: There might be a mistake here.
Context: ... routing traffic sent to the virtual IP. * The Platform Access Address MUST be a ...

(QB_NEW_EN)


[grammar] ~88-~88: There might be a mistake here.
Context: ...ndpointMUST be the virtual IP address. * TheSelf-signed Certificate` option is ...

(QB_NEW_EN)


[grammar] ~97-~97: There might be a mistake here.
Context: ...stallation: * Prepare for Installation * Installing ### Step ...

(QB_NEW_EN)


[grammar] ~124-~124: There might be a mistake here.
Context: ... to the same as the primary cluster: * The options about `Platform Access Addre...

(QB_NEW_EN)


[grammar] ~125-~125: There might be a mistake here.
Context: ...options about Platform Access Address. * The options about Certificate. * The o...

(QB_NEW_EN)


[grammar] ~127-~127: There might be a mistake here.
Context: ... IMPORTANT to make sure the credentials of image repository are the same of the **...

(QB_NEW_EN)


[grammar] ~132-~132: There might be a mistake here.
Context: ...stallation: * Prepare for Installation * Installing ### Step ...

(QB_NEW_EN)

🪛 Gitleaks (8.27.2)
docs/en/install/global_dr.mdx

300-300: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🔇 Additional comments (1)
docs/en/install/global_dr.mdx (1)

106-113: Secure copy flow LGTM.
Using sudo, temp path, and install -m 600 is correct. Nice hardening.

Comment thread docs/en/install/global_dr.mdx Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (6)
docs/en/install/global_dr.mdx (6)

73-78: Load balancer: add etcd security caveat and wording fixes

Explicitly forbid public exposure of 2379 and require pure L4 pass-through. Also fix wording.

-* One domain name used as the `Platform Access Address` for both clusters;
-* A set of TLS certificate and private key for that unified domain;
-* Two virtual IPs for both clusters (Primary and Standby);
+* One domain name used as the `Platform Access Address` for both clusters.
+* A TLS certificate and private key for that unified domain.
+* Two virtual IPs (VIPs), one per cluster (Primary and Standby).
@@
-  * Preconfigure the load balancer to route TCP traffic on ports `80`, `443`, `6443`, `2379`, and `11443` to the control-plane nodes behind the corresponding VIP.
+  * Preconfigure the load balancer to route TCP traffic on ports `80`, `443`, `6443`, `2379`, and `11443` to the control-plane nodes behind the corresponding VIP.
+  * Security: Never expose port `2379` (etcd) to the public internet. Restrict access to control-plane and LB addresses only via network ACLs/firewalls, and ensure the LB performs TCP pass-through only (no TLS termination or L7 inspection).

137-137: Add security warning for 2379 here too

Reinforce that etcd must not be internet-exposed and LB must be L4 pass-through.

-1. Configure the load balancer to forward port `2379` to the control plane nodes of both clusters. ONLY TCP mode is supported; forwarding on L7 is not supported.
+1. Configure the load balancer to forward port `2379` to the control-plane nodes of both clusters. Use TCP pass-through only (no L7/TLS termination). Security: do NOT expose `2379` publicly; restrict access to control-plane/LB addresses via ACLs/firewalls.

265-286: Do not publish real-looking Base64 secrets; use placeholders + disclaimer

Replace Base64 literals with placeholders and add a note to avoid secret-scanner noise and accidental reuse.

-            - name: key1
-              secret: MTE0NTE0MTkxOTgxMA==
+            - name: key1
+              secret: <BASE64_32_BYTE_KEY_FROM_STANDBY_EXAMPLE_ONLY>

Add immediately below the YAML:

+> Note: Replace placeholders with your own randomly generated 32-byte keys encoded in Base64. Do not reuse example values.

288-304: Merge example: placeholders and key-order semantics

Use placeholders for both secrets and add a note that the first key is used for writes across both clusters until rotation completes.

-            - name: key1
-              secret: My4xNDE1OTI2NTM1ODk3
-            - name: key2
-              secret: MTE0NTE0MTkxOTgxMA==
+            - name: key1
+              secret: <BASE64_32_BYTE_KEY_FROM_PRIMARY_EXAMPLE_ONLY>
+            - name: key2
+              secret: <BASE64_32_BYTE_KEY_FROM_STANDBY_EXAMPLE_ONLY>

Add below the YAML:

+Important: Kubernetes writes with the first key and reads with all keys. Keep the Primary’s active key listed first on both clusters to avoid dual-write divergence. Reorder/remove keys only during a planned rotation after confirming re-encryption is complete.

335-346: Single-node restart: avoid crictl; just restart kubelet

This avoids container/pod mismatch and works reliably with static pods.

-_pod_name="kube-apiserver"
-_pod_id=$(sudo crictl ps --name "${_pod_name}" --no-trunc --quiet)
-if [[ -z "${_pod_id}" ]]; then
-    echo "FATAL: could not find pod 'kube-apiserver' on current node"
-    exit 1
-fi
-sudo crictl rm --force "${_pod_id}"
-sudo systemctl restart kubelet.service
+sudo systemctl restart kubelet.service

305-333: Remote script: ${i} won’t expand; crictl misuse; simplify to kubelet restart

The here-doc or double-quoted script is needed if you reference ${i}. Also, removing containers via crictl is brittle; restarting kubelet is sufficient for static pods.

-        scp /etc/kubernetes/encryption-provider.conf "<user>@${i}:/tmp/encryption-provider.conf"
-        ssh "<user>@${i}" '
-    #!/bin/bash
-    set -euo pipefail
-    
-    sudo install -o root -g root -m 600 /tmp/encryption-provider.conf /etc/kubernetes/encryption-provider.conf && rm -f /tmp/encryption-provider.conf
-    _pod_name="kube-apiserver"
-    _pod_id=$(sudo crictl ps --name "${_pod_name}" --no-trunc --quiet)
-    if [[ -z "${_pod_id}" ]]; then
-        echo "FATAL: could not find pod 'kube-apiserver' on node ${i}"
-        exit 1
-    fi
-    sudo crictl rm --force "${_pod_id}"
-    sudo systemctl restart kubelet.service
-    '
+        scp /etc/kubernetes/encryption-provider.conf "<user>@${i}:/tmp/encryption-provider.conf"
+        ssh "<user>@${i}" "bash -s" <<'REMOTE'
+set -euo pipefail
+sudo install -o root -g root -m 600 /tmp/encryption-provider.conf /etc/kubernetes/encryption-provider.conf && rm -f /tmp/encryption-provider.conf
+# Static pod will be reconciled by kubelet
+sudo systemctl restart kubelet.service
+REMOTE
🧹 Nitpick comments (6)
docs/en/install/global_dr.mdx (6)

30-31: Grammar: fix “to indicates …”

Prefer “indicate” and tighten the sentence.

-* In favor of facilitating troubleshooting and management, it is recommended to name nodes in a style like `standby-global-m1`, to indicates which cluster the node belongs to (Primary or Standby).
+* To simplify troubleshooting and management, name nodes like `standby-global-m1` to indicate which cluster (Primary or Standby) the node belongs to.

64-70: Process overview: minor grammar and consistency

Add periods and consistent article/capitalization.

-2. Point the domain to the **Primary Cluster's** VIP and install the **Primary Cluster**;
+2. Point the domain to the **Primary Cluster’s** VIP and install the **Primary Cluster**.
-3. Temporarily switch DNS resolution to the standby VIP to install the Standby Cluster;
+3. Temporarily switch DNS to the standby VIP to install the Standby Cluster.
-4. Copy the ETCD encryption key of the **Primary Cluster** to the nodes that will later be the control plane nodes of Standby Cluster;
+4. Copy the etcd encryption key from the **Primary Cluster** to the nodes that will be the control-plane nodes of the Standby Cluster.
-5. Install and enable the etcd synchronization plugin;
+5. Install and enable the etcd synchronization plugin.
-6. Verify sync status and perform regular checks;
+6. Verify sync status and perform regular checks.
-7. In case of failure, switch DNS to the standby cluster to complete disaster recovery.
+7. If a failure occurs, switch DNS to the standby cluster to complete disaster recovery.

83-93: Step 1 warning: tighten grammar; clarify must/shall; avoid “First of all”

Make bullets concise and precise.

-While installing the primary cluster of the DR (Disaster Recovery Environment),
-
-* First of all, documenting all of the parameters set while following the guide of the installation web UI. It is necessary to keep some options the same while installing the standby cluster.
+While installing the primary cluster in the Disaster Recovery Environment:
+
+* Record all parameters used in the installation UI. Certain options must match when installing the standby cluster.
@@
-* The `Platform Access Address` MUST be a domain, while `Cluster Endpoint` MUST be the virtual IP address.
+* The `Platform Access Address` MUST be a domain; the `Cluster Endpoint` MUST be the virtual IP address.
@@
-* In case the `Image Repository` is set to `Platform Deployment`, the `Username` and `Password` of `Image Repository` MUST NOT be empty; the `IP/Domain` option MUST be set to the unified domain name, which is the `Platform Access Address`.
+* If `Image Repository` is `Platform Deployment`, `Username` and `Password` MUST be set; `IP/Domain` MUST be the unified domain (the `Platform Access Address`).
@@
-* The `Other Platform Access Addresses` option, which is at the second page of the installation web UI (Named `Advanced`), MUST include the virtual IP of the primary cluster.
+* In `Advanced` (page 2), `Other Platform Access Addresses` MUST include the primary cluster VIP.

116-128: Step 2 wording and consistency

Minor grammar and “same as” fixes.

-3. Install the standby cluster in the same way as the primary cluster
+3. Install the standby cluster in the same way as the primary cluster.
@@
-While installing the standby cluster of the DR (Disaster Recovery Environment),
+While installing the standby cluster in the Disaster Recovery Environment:
@@
-the following options MUST be set to the same as the **primary cluster**:
+set the following options the same as the **Primary Cluster**:
@@
-* The options about `Image Repository`. It is IMPORTANT to make sure the credentials of image repository are the same of the **primary cluster**.
+* `Image Repository` options. Ensure the image repository credentials are the same as the **Primary Cluster**.

192-208: Elasticsearch flow: re-run the check after restart

You say “then execute the script to check the cluster again,” but the script isn’t re-run post-restart.

-        # In case the script returned the 401 error, restart Elasticsearch
-        # then execute the script to check the cluster again
-        bash /root/ensure-asm-template.sh
+        # If the script returns 401, restart Elasticsearch and then re-run the check
+        bash /root/ensure-asm-template.sh
@@
-        xargs -r -t -- kubectl delete po -n cpaas-system <<< "${_es_pods}"
+        xargs -r -t -- kubectl delete po -n cpaas-system <<< "${_es_pods}"
+        # Re-run after restart
+        bash /root/ensure-asm-template.sh

253-254: IPv6-safe check URL

Mirror the IPv6-bracketing logic used earlier to avoid malformed curl URLs when the Service has an IPv6 ClusterIP.

-curl $(kubectl get svc -n cpaas-system etcd-sync-monitor -o jsonpath='{.spec.clusterIP}')/check
+ip=$(kubectl get svc -n cpaas-system etcd-sync-monitor -o jsonpath='{.spec.clusterIP}')
+[[ "$ip" =~ : ]] && ip="[$ip]"
+curl "$ip/check"
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5f8b2de and ef4869c.

📒 Files selected for processing (1)
  • docs/en/install/global_dr.mdx (4 hunks)
🧰 Additional context used
🪛 LanguageTool
docs/en/install/global_dr.mdx

[grammar] ~64-~64: There might be a mistake here.
Context: ...VIP and install the Primary Cluster; 3. Temporarily switch DNS resolution to the...

(QB_NEW_EN)


[grammar] ~65-~65: There might be a mistake here.
Context: ...ndby VIP to install the Standby Cluster; 4. Copy the ETCD encryption key of the **Pr...

(QB_NEW_EN)


[grammar] ~66-~66: There might be a mistake here.
Context: ...t will later be the control plane nodes of Standby Cluster; 5. Install and enable ...

(QB_NEW_EN)


[grammar] ~66-~66: There might be a mistake here.
Context: ... control plane nodes of Standby Cluster; 5. Install and enable the etcd synchronizat...

(QB_NEW_EN)


[grammar] ~67-~67: There might be a mistake here.
Context: ... enable the etcd synchronization plugin; 6. Verify sync status and perform regular c...

(QB_NEW_EN)


[grammar] ~68-~68: There might be a mistake here.
Context: ... sync status and perform regular checks; 7. In case of failure, switch DNS to the st...

(QB_NEW_EN)


[grammar] ~73-~73: There might be a mistake here.
Context: ...tform Access Address` for both clusters; * A set of TLS certificate and private key...

(QB_NEW_EN)


[grammar] ~74-~74: There might be a mistake here.
Context: ...and private key for that unified domain; * Two virtual IPs for both clusters (Prima...

(QB_NEW_EN)


[style] ~86-~86: Often, this adverbial phrase is redundant. Consider using an alternative.
Context: ... DR (Disaster Recovery Environment), * First of all, documenting all of the parameters set ...

(FIRST_OF_ALL)


[style] ~86-~86: Consider removing “of” to be more concise
Context: ...ironment), * First of all, documenting all of the parameters set while following the guid...

(ALL_OF_THE)


[grammar] ~87-~87: There might be a mistake here.
Context: ... routing traffic sent to the virtual IP. * The Platform Access Address MUST be a ...

(QB_NEW_EN)


[grammar] ~88-~88: There might be a mistake here.
Context: ...ndpointMUST be the virtual IP address. * TheSelf-signed Certificate` option is ...

(QB_NEW_EN)


[grammar] ~97-~97: There might be a mistake here.
Context: ...stallation: * Prepare for Installation * Installing ### Step ...

(QB_NEW_EN)


[grammar] ~124-~124: There might be a mistake here.
Context: ... to the same as the primary cluster: * The options about `Platform Access Addre...

(QB_NEW_EN)


[grammar] ~125-~125: There might be a mistake here.
Context: ...options about Platform Access Address. * The options about Certificate. * The o...

(QB_NEW_EN)


[grammar] ~127-~127: There might be a mistake here.
Context: ... IMPORTANT to make sure the credentials of image repository are the same of the **...

(QB_NEW_EN)


[grammar] ~132-~132: There might be a mistake here.
Context: ...stallation: * Prepare for Installation * Installing ### Step ...

(QB_NEW_EN)

🪛 Gitleaks (8.27.2)
docs/en/install/global_dr.mdx

300-300: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🔇 Additional comments (1)
docs/en/install/global_dr.mdx (1)

106-113: Secure copy flow looks good

Using a temp path, sudo install, and mode 600 is correct.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/en/install/global_dr.mdx (1)

145-156: Bug: pod name extraction will pass an entire table row to kubectl.

Using --no-headers | head -1 returns the whole line, not just the name. Use jsonpath or -o name.

-kubectl get po -n cpaas-system -l app=etcd-sync
-kubectl logs -n cpaas-system $(kubectl get po -n cpaas-system -l app=etcd-sync --no-headers | head -1) | grep -i "Start Sync update"
+kubectl get po -n cpaas-system -l app=etcd-sync
+pod=$(kubectl get po -n cpaas-system -l app=etcd-sync -o jsonpath='{.items[0].metadata.name}')
+kubectl logs -n cpaas-system "$pod" | grep -i "Start Sync update"
@@
-kubectl delete po -n cpaas-system $(kubectl get po -n cpaas-system -l app=etcd-sync --no-headers | head -1)
+kubectl delete po -n cpaas-system "$pod"
♻️ Duplicate comments (4)
docs/en/install/global_dr.mdx (4)

192-208: Re-run ES template check after restart (missing).

You mention “then execute the script again” but it isn’t re-run.

         # Restart Elasticsearch
         xargs -r -t -- kubectl delete po -n cpaas-system <<< "${_es_pods}"
+        # Re-run the check after pods restart
+        bash /root/ensure-asm-template.sh

265-303: Replace Base64 secrets with placeholders and add key-order note.

Avoid secret-scanner hits and accidental reuse; document write-key ordering.

     ```yaml
@@
             keys:
-            - name: key1
-              secret: MTE0NTE0MTkxOTgxMA==
+            - name: primary-key
+              secret: <BASE64_32_BYTE_KEY_FROM_STANDBY_EXAMPLE_ONLY>
     ```
+> Note: Replace placeholders with your own 32‑byte keys encoded in Base64. Do not reuse example values.
@@
             keys:
-            - name: key1
-              secret: My4xNDE1OTI2NTM1ODk3
-            - name: key2
-              secret: MTE0NTE0MTkxOTgxMA==
+            - name: primary-key
+              secret: <BASE64_32_BYTE_KEY_FROM_PRIMARY_EXAMPLE_ONLY>
+            - name: standby-key
+              secret: <BASE64_32_BYTE_KEY_FROM_STANDBY_EXAMPLE_ONLY>
     ```
+Important: Kubernetes writes with the first key and reads with all keys. Keep the Primary’s active key listed first on both clusters until rotation completes to avoid dual-write divergence.

137-138: Call out etcd exposure risks explicitly here.

Reinforce the L4-only, non-public requirement in this step.

-1. Configure the load balancer to forward port `2379` to the control plane nodes of both clusters. ONLY TCP mode is supported; forwarding on L7 is not supported.
+1. Configure the load balancer to forward port `2379` to the control plane nodes of both clusters. TCP only (no L7), no TLS termination, and NEVER expose `2379` publicly—restrict to control‑plane/LB IPs only.

317-332: Remote SSH script runs bashisms under /bin/sh; simplify and harden.

set -o pipefail needs bash; the inline shebang won’t apply; also crictl removal is brittle. Use a bash here-doc and just restart kubelet.

-        scp /etc/kubernetes/encryption-provider.conf "<user>@${i}:/tmp/encryption-provider.conf"
-        ssh "<user>@${i}" '
-    #!/bin/bash
-    set -euo pipefail
-    
-    sudo install -o root -g root -m 600 /tmp/encryption-provider.conf /etc/kubernetes/encryption-provider.conf && rm -f /tmp/encryption-provider.conf
-    _pod_name="kube-apiserver"
-    _pod_id=$(sudo crictl ps --name "${_pod_name}" --no-trunc --quiet)
-    if [[ -z "${_pod_id}" ]]; then
-        echo "FATAL: could not find pod `kube-apiserver` on node $(hostname)"
-        exit 1
-    fi
-    sudo crictl rm --force "${_pod_id}"
-    sudo systemctl restart kubelet.service
-    '
+        scp /etc/kubernetes/encryption-provider.conf "<user>@${i}:/tmp/encryption-provider.conf"
+        ssh "<user>@${i}" "bash -s" <<'REMOTE'
+set -euo pipefail
+sudo install -o root -g root -m 600 /tmp/encryption-provider.conf /etc/kubernetes/encryption-provider.conf
+rm -f /tmp/encryption-provider.conf
+# Restart kubelet to pick up the static pod change
+sudo systemctl restart kubelet.service
+REMOTE
🧹 Nitpick comments (7)
docs/en/install/global_dr.mdx (7)

30-31: Grammar: “to indicates” → “to indicate”.

Minor clarity fix.

-* In favor of facilitating troubleshooting and management, it is recommended to name nodes in a style like `standby-global-m1`, to indicates which cluster the node belongs to (Primary or Standby).
+* To facilitate troubleshooting and management, name nodes like `standby-global-m1` to indicate which cluster the node belongs to (Primary or Standby).

83-93: Tighten wording in WARNING block.

Shorten and fix grammar; keep meaning unchanged.

-While installing the primary cluster of the DR (Disaster Recovery Environment),
-* First of all, documenting all of the parameters set while following the guide of the installation web UI. It is necessary to keep some options the same while installing the standby cluster.
+While installing the primary cluster in the DR environment:
+* First, document all parameters used in the installation UI. Some options must match when installing the standby cluster.
 * The `Self-built VIP` option is NOT available. A **User-provisioned** Load Balancer is required for routing traffic sent to the virtual IP.
 * The `Platform Access Address` MUST be a domain, while `Cluster Endpoint` MUST be the virtual IP address.
 * The `Self-signed Certificate` option is NOT available. It is NECESSARY for both of the clusters to be configured with `An Existing Certificate`.
 * In case the `Image Repository` is set to `Platform Deployment`, the `Username` and `Password` of `Image Repository` MUST NOT be empty; the `IP/Domain` option MUST be set to the unified domain name, which is the `Platform Access Address`.
 * The `HTTP Port` and `HTTPS Port` options of `Platform Access Address` MUST be 80 and 443.
-* The `Other Platform Access Addresses` option, which is at the second page of the installation web UI (Named `Advanced`), MUST include the virtual IP of the primary cluster.
+* On the `Advanced` page, `Other Platform Access Addresses` MUST include the primary cluster VIP.

116-128: Consistency and grammar: capitalize “Primary/Standby Cluster”; fix phrasing.

Minor readability improvements.

-3. Install the standby cluster in the same way as the primary cluster
+3. Install the Standby Cluster in the same way as the Primary Cluster.
@@
-While installing the standby cluster of the DR (Disaster Recovery Environment),
+While installing the Standby Cluster in the DR environment:
@@
-the following options MUST be set to the same as the **primary cluster**:
+the following options MUST match those of the **Primary Cluster**:
@@
-* The options about `Image Repository`. It is IMPORTANT to make sure the credentials of image repository are the same of the **primary cluster**.
+* The options about `Image Repository`. Ensure the image repository credentials are the same as the **Primary Cluster**.

102-113: Source file read requires root; offer sudo-friendly alternative.

If the local session isn’t root, scp will fail to read /etc. Provide a no-root alternative.

     for i in 4.4.4.4 5.5.5.5 6.6.6.6  # Replace with standby cluster control plane node IPs
     do
       ssh "<user>@$i" "sudo mkdir -p /etc/kubernetes/"
-      scp /etc/kubernetes/encryption-provider.conf "<user>@$i:/tmp/encryption-provider.conf"
+      # If not running as root locally, use sudo+stdin to avoid read-permission issues:
+      # sudo cat /etc/kubernetes/encryption-provider.conf | ssh "<user>@$i" "cat > /tmp/encryption-provider.conf"
+      scp /etc/kubernetes/encryption-provider.conf "<user>@$i:/tmp/encryption-provider.conf"
       ssh "<user>@$i" "sudo install -o root -g root -m 600 /tmp/encryption-provider.conf /etc/kubernetes/encryption-provider.conf && rm -f /tmp/encryption-provider.conf"
     done

248-254: IPv6-safe curl like Step 3.

Mirror the IPv6 handling used earlier to avoid bracket issues.

-curl $(kubectl get svc -n cpaas-system etcd-sync-monitor -o jsonpath='{.spec.clusterIP}')/check
+ip=$(kubectl get svc -n cpaas-system etcd-sync-monitor -o jsonpath='{.spec.clusterIP}')
+if [[ $ip =~ ^[0-9a-fA-F:]+$ ]]; then ip="[$ip]"; fi
+curl "$ip"/check

335-346: Prefer kubelet restart over crictl container deletion.

Static-pod containers are managed by kubelet; deleting containers is unnecessary and runtime-coupled.

-_pod_name="kube-apiserver"
-_pod_id=$(sudo crictl ps --name "${_pod_name}" --no-trunc --quiet)
-if [[ -z "${_pod_id}" ]]; then
-    echo "FATAL: could not find pod `kube-apiserver` on node $(hostname)"
-    exit 1
-fi
-sudo crictl rm --force "${_pod_id}"
-sudo systemctl restart kubelet.service
+sudo systemctl restart kubelet.service

210-218: DNS cutover ops tip (TTL/negative caching).

Optional but helpful during failover.

 5. Switch the platform domain DNS to the standby VIP, which now becomes the Primary Cluster;
 6. Verify DNS resolution:
+   - Tip: Lower the DNS TTL ahead of drills/cutovers and clear negative-caching on resolvers if propagation seems slow.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ef4869c and 002c727.

📒 Files selected for processing (1)
  • docs/en/install/global_dr.mdx (4 hunks)
🧰 Additional context used
🪛 LanguageTool
docs/en/install/global_dr.mdx

[grammar] ~64-~64: There might be a mistake here.
Context: ...VIP and install the Primary Cluster; 3. Temporarily switch DNS resolution to the...

(QB_NEW_EN)


[grammar] ~65-~65: There might be a mistake here.
Context: ...ndby VIP to install the Standby Cluster; 4. Copy the ETCD encryption key of the **Pr...

(QB_NEW_EN)


[grammar] ~66-~66: There might be a mistake here.
Context: ...t will later be the control plane nodes of Standby Cluster; 5. Install and enable ...

(QB_NEW_EN)


[grammar] ~66-~66: There might be a mistake here.
Context: ... control plane nodes of Standby Cluster; 5. Install and enable the etcd synchronizat...

(QB_NEW_EN)


[grammar] ~67-~67: There might be a mistake here.
Context: ... enable the etcd synchronization plugin; 6. Verify sync status and perform regular c...

(QB_NEW_EN)


[grammar] ~68-~68: There might be a mistake here.
Context: ... sync status and perform regular checks; 7. In case of failure, switch DNS to the st...

(QB_NEW_EN)


[grammar] ~73-~73: There might be a mistake here.
Context: ...tform Access Address` for both clusters; * A set of TLS certificate and private key...

(QB_NEW_EN)


[grammar] ~74-~74: There might be a mistake here.
Context: ...and private key for that unified domain; * Two virtual IPs for both clusters (Prima...

(QB_NEW_EN)


[style] ~86-~86: Often, this adverbial phrase is redundant. Consider using an alternative.
Context: ... DR (Disaster Recovery Environment), * First of all, documenting all of the parameters set ...

(FIRST_OF_ALL)


[style] ~86-~86: Consider removing “of” to be more concise
Context: ...ironment), * First of all, documenting all of the parameters set while following the guid...

(ALL_OF_THE)


[grammar] ~87-~87: There might be a mistake here.
Context: ... routing traffic sent to the virtual IP. * The Platform Access Address MUST be a ...

(QB_NEW_EN)


[grammar] ~88-~88: There might be a mistake here.
Context: ...ndpointMUST be the virtual IP address. * TheSelf-signed Certificate` option is ...

(QB_NEW_EN)


[grammar] ~97-~97: There might be a mistake here.
Context: ...stallation: * Prepare for Installation * Installing ### Step ...

(QB_NEW_EN)


[grammar] ~124-~124: There might be a mistake here.
Context: ... to the same as the primary cluster: * The options about `Platform Access Addre...

(QB_NEW_EN)


[grammar] ~125-~125: There might be a mistake here.
Context: ...options about Platform Access Address. * The options about Certificate. * The o...

(QB_NEW_EN)


[grammar] ~127-~127: There might be a mistake here.
Context: ... IMPORTANT to make sure the credentials of image repository are the same of the **...

(QB_NEW_EN)


[grammar] ~132-~132: There might be a mistake here.
Context: ...stallation: * Prepare for Installation * Installing ### Step ...

(QB_NEW_EN)

🪛 Gitleaks (8.27.2)
docs/en/install/global_dr.mdx

300-300: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

Comment thread docs/en/install/global_dr.mdx Outdated
Comment thread docs/en/install/global_dr.mdx
Comment thread docs/en/install/global_dr.mdx Outdated
Comment thread docs/en/install/global_dr.mdx Outdated
Comment thread docs/en/install/global_dr.mdx Outdated
Comment thread docs/en/install/global_dr.mdx Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (7)
docs/en/install/global_dr.mdx (7)

191-207: Re-run the ES template check after restarting pods, as the text promises.

Currently the script runs before the restart only. Add a second invocation.

-        # In case the script returned the 401 error, restart Elasticsearch
-        # then execute the script to check the cluster again
-        bash /root/ensure-asm-template.sh
+        # If the script returns 401, restart Elasticsearch, then re-run the script
+        bash /root/ensure-asm-template.sh
@@
-        xargs -r -t -- kubectl delete po -n cpaas-system <<< "${_es_pods}"
+        xargs -r -t -- kubectl delete po -n cpaas-system <<< "${_es_pods}"
+        # Re-run the check after pods restart
+        bash /root/ensure-asm-template.sh

304-332: Simplify remote restart; avoid brittle crictl usage and harden quoting.

For static pods, restarting kubelet is sufficient. Remove container-runtime coupling and keep perms at 600. Also avoid single-quoted inline script; use a here‑doc.

-        scp /etc/kubernetes/encryption-provider.conf "<user>@${i}:/tmp/encryption-provider.conf"
-        ssh "<user>@${i}" '
-    #!/bin/bash
-    set -euo pipefail
-    
-    sudo install -o root -g root -m 600 /tmp/encryption-provider.conf /etc/kubernetes/encryption-provider.conf && rm -f /tmp/encryption-provider.conf
-    _pod_name="kube-apiserver"
-    _pod_id=$(sudo crictl ps --name "${_pod_name}" --no-trunc --quiet)
-    if [[ -z "${_pod_id}" ]]; then
-        echo "FATAL: could not find pod `kube-apiserver` on node $(hostname)"
-        exit 1
-    fi
-    sudo crictl rm --force "${_pod_id}"
-    sudo systemctl restart kubelet.service
-    '
+        scp /etc/kubernetes/encryption-provider.conf "<user>@${i}:/tmp/encryption-provider.conf"
+        ssh "<user>@${i}" "bash -s" <<'REMOTE'
+set -euo pipefail
+sudo install -o root -g root -m 600 /tmp/encryption-provider.conf /etc/kubernetes/encryption-provider.conf
+rm -f /tmp/encryption-provider.conf
+sudo systemctl restart kubelet.service
+REMOTE

334-345: Apply the same simplified restart on node 1.1.1.1.

Mirror the kubelet restart approach and drop crictl dependency.

-_pod_name="kube-apiserver"
-_pod_id=$(sudo crictl ps --name "${_pod_name}" --no-trunc --quiet)
-if [[ -z "${_pod_id}" ]]; then
-    echo "FATAL: could not find pod `kube-apiserver` on node $(hostname)"
-    exit 1
-fi
-sudo crictl rm --force "${_pod_id}"
-sudo systemctl restart kubelet.service
+sudo systemctl restart kubelet.service

73-77: Add explicit etcd (2379) security caveat and clarify wording.

Do not expose 2379 publicly; require pure L4 pass‑through. Matches earlier feedback.

-* A unified domain which will be the `Platform Access Address`, and the TLS certificate plus private key for serving HTTPS on that domain;
+* A unified domain to use as the `Platform Access Address`, and a TLS certificate plus private key for serving HTTPS on that domain.
 * A dedicated virtual IP address for each cluster — one for the **Primary Cluster** and another for the Standby Cluster;
 
-  * Preconfigure the load balancer to route TCP traffic on ports `80`, `443`, `6443`, `2379`, and `11443` to the control-plane nodes behind the corresponding VIP.
+  * Preconfigure the load balancer to route TCP traffic on ports `80`, `443`, `6443`, `2379`, and `11443` to the control-plane nodes behind the corresponding VIP.
+  * Security: Never expose port `2379` (etcd) to the public internet. Restrict access to control‑plane/LB addresses via ACLs/allow‑lists, and ensure pure L4 TCP pass‑through (no TLS termination or L7 inspection).

136-136: Call out L4 pass‑through and access controls for 2379.

Add “no TLS termination/L7” and explicit allow‑lists. Mirrors earlier guidance.

-1. Configure the load balancer to forward port `2379` to control plane nodes of the corresponding cluster. ONLY TCP mode is supported; forwarding on L7 is not supported.
+1. Configure the load balancer to forward port `2379` to control plane nodes of the corresponding cluster. ONLY L4/TCP pass‑through is supported (no TLS termination/L7). Restrict access to control‑plane/LB addresses via ACLs/allow‑lists.

274-285: Replace Base64 secret with an explicit placeholder and add a disclaimer.

Avoid secret-scanner hits and accidental reuse.

@@
             keys:
-            - name: key1
-              secret: MTE0NTE0MTkxOTgxMA==
+            - name: key1
+              secret: <BASE64_32_BYTE_KEY_FROM_STANDBY_EXAMPLE_ONLY>

Add immediately below the YAML:

+> Note: Replace placeholders with your own randomly generated 32‑byte keys encoded in base64. Do not reuse example values.

289-303: Use placeholders for all secrets and document key-order semantics.

Kubernetes writes with the first key and reads with all. Keep the Primary’s key first across both clusters to avoid dual-write divergence. Replace Base64 literals.

@@
             keys:
             - name: key1
-              secret: My4xNDE1OTI2NTM1ODk3
+              secret: <BASE64_32_BYTE_KEY_FROM_PRIMARY_EXAMPLE_ONLY>
             - name: key2
-              secret: MTE0NTE0MTkxOTgxMA==
+              secret: <BASE64_32_BYTE_KEY_FROM_STANDBY_EXAMPLE_ONLY>

Add immediately below the YAML:

+Important: The first key is used for writes, all keys are used for reads. Keep the Primary’s active key listed first on both clusters until rotation completes to prevent each cluster from encrypting with different keys.
+> Note: Replace placeholders with your own randomly generated 32‑byte keys encoded in base64. Do not reuse example values.
🧹 Nitpick comments (7)
docs/en/install/global_dr.mdx (7)

30-31: Fix grammar in node-naming guidance.

“to indicates” → “to indicate”.

-* In favor of facilitating troubleshooting and management, it is recommended to name nodes in a style like `standby-global-m1`, to indicates which cluster the node belongs to (Primary or Standby).
+* In favor of facilitating troubleshooting and management, it is recommended to name nodes in a style like `standby-global-m1`, to indicate which cluster the node belongs to (Primary or Standby).

63-70: Tighten wording in Process Overview.

Minor grammar/flow improvements; no behavior change.

-1. Prepare a unified domain name for platform access;
-2. Point the domain to the **Primary Cluster's** VIP and install the **Primary Cluster**;
-3. Temporarily switch DNS resolution to the standby VIP to install the Standby Cluster;
-4. Copy the ETCD encryption key of the **Primary Cluster** to the nodes that will later be the control plane nodes of Standby Cluster;
-5. Install and enable the etcd synchronization plugin;
-6. Verify sync status and perform regular checks;
-7. In case of failure, switch DNS to the standby cluster to complete disaster recovery.
+1. Prepare a unified domain for platform access.
+2. Point the domain to the **Primary Cluster** VIP and install the **Primary Cluster**.
+3. Temporarily switch DNS to the standby VIP to install the Standby Cluster.
+4. Copy the etcd encryption key from the **Primary Cluster** to the nodes that will become the Standby control plane.
+5. Install and enable the etcd synchronization plugin.
+6. Verify sync status and perform regular checks.
+7. If the Primary fails, switch DNS to the standby cluster to complete disaster recovery.

82-92: Polish WARNING text; remove “First of all” and tighten phrasing.

Improves clarity without changing meaning.

-While installing the primary cluster of the DR (Disaster Recovery Environment),
-
-* First of all, documenting all of the parameters set while following the guide of the installation web UI. It is necessary to keep some options the same while installing the standby cluster.
+While installing the primary cluster of the DR (Disaster Recovery Environment),
+
+* Record all parameters set in the installation UI. Some options must match when installing the standby cluster.
@@
-* The `Self-signed Certificate` option is NOT available. It is NECESSARY for both of the clusters to be configured with `An Existing Certificate`.
+* The `Self-signed Certificate` option is NOT available. Both clusters MUST use `An Existing Certificate`.
@@
-* The `Other Platform Access Addresses` option, which is at the second page of the installation web UI (Named `Advanced`), MUST include the virtual IP of the primary cluster.
+* On the `Advanced` page, the `Other Platform Access Addresses` option MUST include the Primary cluster VIP.

115-116: Add punctuation and consistency.

-3. Install the standby cluster in the same way as the primary cluster
+3. Install the standby cluster in the same way as the primary cluster.

117-127: Clarify “same as primary” list and tighten grammar.

-While installing the standby cluster of the DR (Disaster Recovery Environment),
+While installing the standby cluster of the DR (Disaster Recovery Environment),
@@
-the following options MUST be set to the same as the **primary cluster**:
-* The options about `Platform Access Address`.
-* The options about `Certificate`.
-* The options about `Image Repository`. It is IMPORTANT to make sure the credentials of image repository are the same of the **primary cluster**.
+Set the following options to match the **Primary Cluster** exactly:
+* `Platform Access Address`
+* `Certificate`
+* `Image Repository` (including credentials)

249-253: IPv6-safe Routine Check (align with Step 3).

The simple curl against ClusterIP will fail on IPv6 without brackets. Reuse the IPv6-safe snippet used earlier.

-curl $(kubectl get svc -n cpaas-system etcd-sync-monitor -o jsonpath='{.spec.clusterIP}')/check
+mirror_svc=$(kubectl get svc -n cpaas-system etcd-sync-monitor -o jsonpath='{.spec.clusterIP}')
+if [[ $mirror_svc =~ ^[0-9a-fA-F:]+$ ]]; then mirror_svc="[$mirror_svc]"; fi
+curl "$mirror_svc/check"

57-58: Clarify image registry note.

If registries differ, explicitly state uploads must target each registry endpoint.

-* If both clusters are set to use built-in image registries, container images must be uploaded separately to each;
+* If both clusters use built-in image registries, upload container images to each cluster’s registry separately (they are not shared).
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 002c727 and 65ffe1f.

📒 Files selected for processing (1)
  • docs/en/install/global_dr.mdx (4 hunks)
🧰 Additional context used
🪛 LanguageTool
docs/en/install/global_dr.mdx

[grammar] ~63-~63: There might be a mistake here.
Context: ...unified domain name for platform access; 2. Point the domain to the **Primary Cluste...

(QB_NEW_EN)


[grammar] ~64-~64: There might be a mistake here.
Context: ...VIP and install the Primary Cluster; 3. Temporarily switch DNS resolution to the...

(QB_NEW_EN)


[grammar] ~65-~65: There might be a mistake here.
Context: ...ndby VIP to install the Standby Cluster; 4. Copy the ETCD encryption key of the **Pr...

(QB_NEW_EN)


[grammar] ~66-~66: There might be a mistake here.
Context: ...t will later be the control plane nodes of Standby Cluster; 5. Install and enable ...

(QB_NEW_EN)


[grammar] ~66-~66: There might be a mistake here.
Context: ... control plane nodes of Standby Cluster; 5. Install and enable the etcd synchronizat...

(QB_NEW_EN)


[grammar] ~67-~67: There might be a mistake here.
Context: ... enable the etcd synchronization plugin; 6. Verify sync status and perform regular c...

(QB_NEW_EN)


[grammar] ~68-~68: There might be a mistake here.
Context: ... sync status and perform regular checks; 7. In case of failure, switch DNS to the st...

(QB_NEW_EN)


[grammar] ~73-~73: There might be a mistake here.
Context: ...te key for serving HTTPS on that domain; * A dedicated virtual IP address for each ...

(QB_NEW_EN)


[style] ~85-~85: Often, this adverbial phrase is redundant. Consider using an alternative.
Context: ... DR (Disaster Recovery Environment), * First of all, documenting all of the parameters set ...

(FIRST_OF_ALL)


[style] ~85-~85: Consider removing “of” to be more concise
Context: ...ironment), * First of all, documenting all of the parameters set while following the guid...

(ALL_OF_THE)


[grammar] ~86-~86: There might be a mistake here.
Context: ... routing traffic sent to the virtual IP. * The Platform Access Address MUST be a ...

(QB_NEW_EN)


[grammar] ~87-~87: There might be a mistake here.
Context: ...ndpointMUST be the virtual IP address. * TheSelf-signed Certificate` option is ...

(QB_NEW_EN)


[grammar] ~96-~96: There might be a mistake here.
Context: ...stallation: * Prepare for Installation * Installing ### Step ...

(QB_NEW_EN)


[grammar] ~123-~123: There might be a mistake here.
Context: ... to the same as the primary cluster: * The options about `Platform Access Addre...

(QB_NEW_EN)


[grammar] ~124-~124: There might be a mistake here.
Context: ...options about Platform Access Address. * The options about Certificate. * The o...

(QB_NEW_EN)


[grammar] ~126-~126: There might be a mistake here.
Context: ... IMPORTANT to make sure the credentials of image repository are the same of the **...

(QB_NEW_EN)


[grammar] ~131-~131: There might be a mistake here.
Context: ...stallation: * Prepare for Installation * Installing ### Step ...

(QB_NEW_EN)

🪛 Gitleaks (8.27.2)
docs/en/install/global_dr.mdx

299-299: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🔇 Additional comments (1)
docs/en/install/global_dr.mdx (1)

269-269: Ensure sudo and quoting on remote read (already correct) — LGTM.

Comment thread docs/en/install/global_dr.mdx
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (6)
docs/en/install/global_dr.mdx (6)

331-342: Simplify kube‑apiserver restart on node 1.1.1.1.

Avoid force‑removing containers; kubelet restart is enough for static pods.

-    _pod_name="kube-apiserver"
-    _pod_id=$(sudo crictl ps --name "${_pod_name}" --no-trunc --quiet)
-    if [[ -z "${_pod_id}" ]]; then
-        echo "FATAL: could not find pod `kube-apiserver` on node $(hostname)"
-        exit 1
-    fi
-    sudo crictl rm --force "${_pod_id}"
-    sudo systemctl restart kubelet.service
+    sudo systemctl restart kubelet.service

133-133: Reinforce etcd exposure risk and L4 requirement.

Mention restriction and pass‑through here as well for operators who skim steps.

-1. Configure the load balancer to forward port `2379` to control plane nodes of the corresponding cluster. ONLY TCP mode is supported; forwarding on L7 is not supported.
+1. Configure the load balancer to forward port `2379` to control‑plane nodes of the corresponding cluster. Use pure L4 TCP pass‑through (no L7/TLS termination), and never expose `2379` publicly—restrict access to control‑plane/LB addresses only.

188-204: Re-run verification after Elasticsearch restart.

The text says “then execute the script again,” but it isn’t re-run post‑restart.

-        # In case the script returned the 401 error, restart Elasticsearch
-        # then execute the script to check the cluster again
-        bash /root/ensure-asm-template.sh
-
-        # Restart Elasticsearch
-        xargs -r -t -- kubectl delete po -n cpaas-system <<< "${_es_pods}"
+        # If the script returns 401, restart Elasticsearch and then re-run the script
+        bash /root/ensure-asm-template.sh
+        # Restart Elasticsearch
+        xargs -r -t -- kubectl delete po -n cpaas-system <<< "${_es_pods}"
+        # Re-run the check after pods restart
+        bash /root/ensure-asm-template.sh

259-299: Replace real-looking Base64 secrets with placeholders and add disclaimers; document key-order semantics.

These literals trigger secret scanners and risk accidental reuse; also call out “first key writes” rule.

@@
-            - name: key1
-              secret: MTE0NTE0MTkxOTgxMA==
+            - name: key1
+              secret: <BASE64_32_BYTE_KEY_FROM_STANDBY_EXAMPLE_ONLY>
@@
-            - name: key1
-              secret: My.1415926535897
-            - name: key2
-              secret: MTE0NTE0MTkxOTgxMA==
+            - name: key1
+              secret: <BASE64_32_BYTE_KEY_FROM_PRIMARY_EXAMPLE_ONLY>
+            - name: key2
+              secret: <BASE64_32_BYTE_KEY_FROM_STANDBY_EXAMPLE_ONLY>
+
+> Note: Replace placeholders with your own randomly generated 32‑byte keys encoded in base64. Do not reuse example values.
+
+Important: The first key in the list is used for writes; all keys are used for reads. Keep the Primary’s active key listed first on both clusters until rotation completes to avoid divergence.

301-329: Harden remote update: avoid brittle crictl usage, fix quoting, keep perms 600, and just restart kubelet.

Single‑quoted SSH block is fine here, but the crictl container removal is unnecessary risk. A kubelet restart is sufficient to pick up the updated static‑pod config.

-    for i in \
+    for i in \
         2.2.2.2 3.3.3.3 \
         4.4.4.4 5.5.5.5 6.6.6.6 \
     ; do
         scp /etc/kubernetes/encryption-provider.conf "<user>@${i}:/tmp/encryption-provider.conf"
-        ssh "<user>@${i}" '
-    #!/bin/bash
-    set -euo pipefail
-    
-    sudo install -o root -g root -m 600 /tmp/encryption-provider.conf /etc/kubernetes/encryption-provider.conf && rm -f /tmp/encryption-provider.conf
-    _pod_name="kube-apiserver"
-    _pod_id=$(sudo crictl ps --name "${_pod_name}" --no-trunc --quiet)
-    if [[ -z "${_pod_id}" ]]; then
-        echo "FATAL: could not find pod `kube-apiserver` on node $(hostname)"
-        exit 1
-    fi
-    sudo crictl rm --force "${_pod_id}"
-    sudo systemctl restart kubelet.service
-    '
+        ssh "<user>@${i}" "bash -s" <<'REMOTE'
+set -euo pipefail
+sudo install -o root -g root -m 600 /tmp/encryption-provider.conf /etc/kubernetes/encryption-provider.conf
+rm -f /tmp/encryption-provider.conf
+sudo systemctl restart kubelet.service
+REMOTE
     done

73-76: Add explicit etcd (2379) security caveat under LB requirements.

Do not expose 2379 publicly; require pure L4 pass‑through.

   * Preconfigure the load balancer to route TCP traffic on ports `80`, `443`, `6443`, `2379`, and `11443` to the control-plane nodes behind the corresponding VIP.
+  * Security: Never expose port `2379` (etcd) to the public internet. Restrict access to control‑plane/LB addresses only and ensure pure L4 TCP pass‑through (no TLS termination/L7 inspection).
🧹 Nitpick comments (3)
docs/en/install/global_dr.mdx (3)

30-31: Fix grammar in node-naming guidance.

“to indicates” → “to indicate”.

-* In favor of facilitating troubleshooting and management, it is recommended to name nodes in a style like `standby-global-m1`, to indicates which cluster the node belongs to (Primary or Standby).
+* To facilitate troubleshooting and management, name nodes like `standby-global-m1` to indicate which cluster the node belongs to (Primary or Standby).

57-58: Clarify target of “each”.

Be explicit that images must be uploaded to each cluster.

-* If both clusters are set to use built-in image registries, container images must be uploaded separately to each;
+* If both clusters use built‑in image registries, upload container images to each cluster separately;

115-124: Polish punctuation and consistency; clarify credential parity.

Minor grammar fixes and clearer intent.

-3. Install the standby cluster in the same way as the primary cluster
+3. Install the standby cluster in the same way as the primary cluster.
@@
-* All fields of `Image Repository`
-* Important: ensure the credentials of image repository and the ACP admin user match those set on the **Primary Cluster**.
+* All fields of `Image Repository`.
+* Important: ensure the image‑repository credentials and the ACP admin user credentials match those on the **Primary Cluster**.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 65ffe1f and 9b73a11.

📒 Files selected for processing (1)
  • docs/en/install/global_dr.mdx (4 hunks)
🧰 Additional context used
🪛 LanguageTool
docs/en/install/global_dr.mdx

[style] ~85-~85: Often, this adverbial phrase is redundant. Consider using an alternative.
Context: ... DR (Disaster Recovery Environment), * First of all, documenting all of the parameters set ...

(FIRST_OF_ALL)


[style] ~85-~85: Consider removing “of” to be more concise
Context: ...ironment), * First of all, documenting all of the parameters set while following the guid...

(ALL_OF_THE)

🪛 Gitleaks (8.27.2)
docs/en/install/global_dr.mdx

296-296: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

Comment thread docs/en/install/global_dr.mdx Outdated
Comment thread docs/en/install/global_dr.mdx
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/en/install/global_dr.mdx (1)

135-141: Call out access restrictions explicitly for 2379.

Add “do not expose publicly” guidance next to the instruction.

-1. Configure the load balancer to forward port `2379` to control plane nodes of the corresponding cluster. ONLY TCP mode is supported; forwarding on L7 is not supported.
+1. Configure the load balancer to forward port `2379` to the control‑plane nodes of the corresponding cluster. ONLY TCP (L4) is supported; L7 is not supported. Do NOT expose `2379` publicly—restrict access to control‑plane/LB addresses only.
♻️ Duplicate comments (6)
docs/en/install/global_dr.mdx (6)

190-206: Re-run the ES check after restarting pods.

Your text says to re-run, but the snippet doesn’t. Add the second invocation after the delete.

-        # In case the script returned the 401 error, restart Elasticsearch
-        # then execute the script to check the cluster again
-        bash /root/ensure-asm-template.sh
+        # If the script returns 401, restart Elasticsearch and then re-run the check
+        bash /root/ensure-asm-template.sh
@@
-        xargs -r -t -- kubectl delete po -n cpaas-system <<< "${_es_pods}"
+        xargs -r -t -- kubectl delete po -n cpaas-system <<< "${_es_pods}"
+        # Re-run after pods restart
+        bash /root/ensure-asm-template.sh

281-301: Replace real-looking Base64 secrets with placeholders and add key-order note.

Secret scanners will flag these; avoid accidental reuse. Also call out that the first key is used for writes.

-            - name: key1
-              secret: MTE0NTE0MTkxOTgxMA==
+            - name: key1
+              secret: <BASE64_32_BYTE_KEY_FROM_STANDBY_EXAMPLE_ONLY>
-            - name: key1
-              secret: My4xNDE1OTI2NTM1ODk3
-            - name: key2
-              secret: MTE0NTE0MTkxOTgxMA==
+            - name: key1
+              secret: <BASE64_32_BYTE_KEY_FROM_PRIMARY_EXAMPLE_ONLY>
+            - name: key2
+              secret: <BASE64_32_BYTE_KEY_FROM_STANDBY_EXAMPLE_ONLY>
+> Note: Replace placeholders with your own 32‑byte keys encoded in base64. Do not reuse example values.
+
+Important: The first key in the list is used for writes. Keep the Primary’s key first on both clusters to avoid each cluster encrypting with different keys. Rotate by reordering and re‑encrypting during a planned window only.

73-77: Add mandatory security caveat for etcd (2379) at the LB requirement.

Do not expose 2379; require pure L4 pass-through.

 * A dedicated virtual IP address for each cluster — one for the **Primary Cluster** and another for the Standby Cluster;
 
   * Preconfigure the load balancer to route TCP traffic on ports `80`, `443`, `6443`, `2379`, and `11443` to the control-plane nodes behind the corresponding VIP.
+  * Security: Never expose `2379` (etcd) to the public internet. Restrict L4 access to control‑plane/LB addresses only and use TCP pass‑through (no TLS termination or L7 inspection).

333-344: Single-node restart: simplify to kubelet restart (avoid crictl).

Same rationale as above; kubelet will recreate the apiserver static pod.

-_pod_name="kube-apiserver"
-_pod_id=$(sudo crictl ps --name "${_pod_name}" --no-trunc --quiet)
-if [[ -z "${_pod_id}" ]]; then
-    echo "FATAL: could not find pod `kube-apiserver` on node $(hostname)"
-    exit 1
-fi
-sudo crictl rm --force "${_pod_id}"
-sudo systemctl restart kubelet.service
+sudo systemctl restart kubelet.service

303-331: Remote restart sequence: drop brittle crictl usage; just restart kubelet.

Static pods are recreated by kubelet; removing containers is unnecessary and can fail. Also avoid single-quoted here-script; use a heredoc.

-        scp /etc/kubernetes/encryption-provider.conf "<user>@${i}:/tmp/encryption-provider.conf"
-        ssh "<user>@${i}" '
-    #!/bin/bash
-    set -euo pipefail
-    
-    sudo install -o root -g root -m 600 /tmp/encryption-provider.conf /etc/kubernetes/encryption-provider.conf && rm -f /tmp/encryption-provider.conf
-    _pod_name="kube-apiserver"
-    _pod_id=$(sudo crictl ps --name "${_pod_name}" --no-trunc --quiet)
-    if [[ -z "${_pod_id}" ]]; then
-        echo "FATAL: could not find pod `kube-apiserver` on node $(hostname)"
-        exit 1
-    fi
-    sudo crictl rm --force "${_pod_id}"
-    sudo systemctl restart kubelet.service
-    '
+        scp /etc/kubernetes/encryption-provider.conf "<user>@${i}:/tmp/encryption-provider.conf"
+        ssh "<user>@${i}" "bash -s" <<'REMOTE'
+set -euo pipefail
+sudo install -o root -g root -m 600 /tmp/encryption-provider.conf /etc/kubernetes/encryption-provider.conf
+rm -f /tmp/encryption-provider.conf
+sudo systemctl restart kubelet.service
+REMOTE

82-92: Rewrite WARNING block for grammar and precision.

Fix awkward phrasing (“First of all…”, “has be”, “the of the installation guide”).

-<Directive type="warning" title="NOTES OF DR (Disaster Recovery Environment) INSTALLING">
-While installing the primary cluster of the DR Environment,
-
-* First of all, documenting all of the parameters set while following the guide of the installation web UI. It is necessary to keep some options the same while installing the standby cluster.
-* A **User-provisioned** Load Balancer MUST be preconfigured to route traffic sent to the virtual IP. The `Self-built VIP` option is NOT available.
-* The `Platform Access Address` field MUST be a domain, while the `Cluster Endpoint` MUST be the virtual IP address.
-* Both clusters MUST be configured to use `An Existing Certificate` (has be the same one), request a legit certificate if necessary. The `Self-signed Certificate` option is NOT available.
-* When `Image Repository` is set to `Platform Deployment`, both `Username` and `Password` fields MUST NOT be empty; The `IP/Domain` field MUST be set to the domain used as the `Platform Access Address`.
-* Both `HTTP Port` and `HTTPS Port` fields of `Platform Access Address` MUST be 80 and 443.
-* When coming to the second page the of the installation guide (Step: `Advanced`), the `Other Platform Access Addresses` field MUST include the virtual IP of current Cluster.
-</Directive>
+<Directive type="warning" title="NOTES FOR INSTALLING DR PRIMARY">
+Record all parameters you set in the installer UI; you will reuse the same values when installing the standby cluster.
+
+* A **User‑provisioned** Load Balancer MUST be preconfigured to route traffic to the VIP. The `Self‑built VIP` option is NOT available.
+* The `Platform Access Address` MUST be a domain, and the `Cluster Endpoint` MUST be the VIP.
+* Both clusters MUST use `An Existing Certificate` (the same certificate). Request a valid certificate if necessary. The `Self‑signed Certificate` option is NOT available.
+* If `Image Repository` is `Platform Deployment`, `Username` and `Password` MUST be set, and `IP/Domain` MUST be the `Platform Access Address` domain.
+* `Platform Access Address` ports MUST be `80` and `443`.
+* On the `Advanced` step, the `Other Platform Access Addresses` field MUST include the current cluster’s VIP.
+</Directive>
🧹 Nitpick comments (5)
docs/en/install/global_dr.mdx (5)

30-31: Grammar: fix “to indicates” and tighten the sentence.

Clearer wording; subject-verb agreement.

-* In favor of facilitating troubleshooting and management, it is recommended to name nodes in a style like `standby-global-m1`, to indicates which cluster the node belongs to (Primary or Standby).
+* To facilitate troubleshooting and management, name nodes like `standby-global-m1` to indicate which cluster the node belongs to (Primary or Standby).

63-70: Polish step wording for consistency and clarity.

Align tense/grammar; clarify what becomes control plane for Standby.

-2. Point the domain to the **Primary Cluster's** VIP and install the **Primary Cluster**;
-3. Temporarily switch DNS resolution to the standby VIP to install the Standby Cluster;
-4. Copy the ETCD encryption key of the **Primary Cluster** to the nodes that will later be the control plane nodes of Standby Cluster;
-5. Install and enable the etcd synchronization plugin;
-6. Verify sync status and perform regular checks;
-7. In case of failure, switch DNS to the standby cluster to complete disaster recovery.
+2. Point the domain to the **Primary Cluster** VIP and install the **Primary Cluster**.
+3. Temporarily switch DNS to the Standby VIP and install the **Standby Cluster**.
+4. Copy the ETCD encryption key from the **Primary Cluster** to the nodes that will become the **Standby Cluster** control plane.
+5. Install and enable the etcd synchronization plugin.
+6. Verify sync status and perform regular checks.
+7. If a failure occurs, switch DNS to the **Standby Cluster** to complete disaster recovery.

115-126: Tighten wording in standby install notes.

Parallel phrasing; minor grammar polish.

-<Directive type="warning" title="NOTES FOR INSTALLING STANDBY CLUSTER">
-While installing the standby cluster of the DR Environment,
-the following options MUST be set to the same as the **primary cluster**:
+<Directive type="warning" title="NOTES FOR INSTALLING STANDBY CLUSTER">
+When installing the standby cluster, set the following options to match the **Primary Cluster**:
@@
-* All fields of `Image Repository`
-* Important: ensure the credentials of image repository and the ACP admin user match those set on the **Primary Cluster**.
+* All fields of `Image Repository`.
+* Important: ensure image‑repository credentials and the ACP admin user match the **Primary Cluster**.
@@
-and MAKE SURE you followed the `NOTES OF DR (Disaster Recovery Environment) INSTALLING` in Step 1.
+Also make sure you followed the “NOTES FOR INSTALLING DR PRIMARY” in Step 1.
 </Directive>

263-271: FAQ intro: grammar and clarity.

Tighten wording and casing.

-* Here are the instructions in case that the ETCD encryption key of the standby cluster has not synced with the one of **primary cluster** before Installing the standby cluster.
+* If the standby cluster’s ETCD encryption key was not synced with the **Primary Cluster** before installing the standby cluster, follow these steps.

258-259: Minor: show a concrete violet example with --dest-repo.

Optional but helpful to prevent misuploads.

-When using **`violet`** to upload packages to a standby cluster, you must specify the `--dest-repo` parameter with the VIP of the standby cluster.
+When using **`violet`** to upload packages to a standby cluster, specify `--dest-repo` with the standby VIP, for example:
+`violet upload --dest-repo https://<standby_vip> ...`
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9b73a11 and 8d2c6fc.

📒 Files selected for processing (1)
  • docs/en/install/global_dr.mdx (4 hunks)
🧰 Additional context used
🪛 LanguageTool
docs/en/install/global_dr.mdx

[grammar] ~63-~63: There might be a mistake here.
Context: ...unified domain name for platform access; 2. Point the domain to the **Primary Cluste...

(QB_NEW_EN)


[grammar] ~64-~64: There might be a mistake here.
Context: ...VIP and install the Primary Cluster; 3. Temporarily switch DNS resolution to the...

(QB_NEW_EN)


[grammar] ~65-~65: There might be a mistake here.
Context: ...ndby VIP to install the Standby Cluster; 4. Copy the ETCD encryption key of the **Pr...

(QB_NEW_EN)


[grammar] ~66-~66: There might be a mistake here.
Context: ...t will later be the control plane nodes of Standby Cluster; 5. Install and enable ...

(QB_NEW_EN)


[grammar] ~66-~66: There might be a mistake here.
Context: ... control plane nodes of Standby Cluster; 5. Install and enable the etcd synchronizat...

(QB_NEW_EN)


[grammar] ~67-~67: There might be a mistake here.
Context: ... enable the etcd synchronization plugin; 6. Verify sync status and perform regular c...

(QB_NEW_EN)


[grammar] ~68-~68: There might be a mistake here.
Context: ... sync status and perform regular checks; 7. In case of failure, switch DNS to the st...

(QB_NEW_EN)


[grammar] ~73-~73: There might be a mistake here.
Context: ...te key for serving HTTPS on that domain; * A dedicated virtual IP address for each ...

(QB_NEW_EN)


[style] ~85-~85: Often, this adverbial phrase is redundant. Consider using an alternative.
Context: ...imary cluster of the DR Environment, * First of all, documenting all of the parameters set ...

(FIRST_OF_ALL)


[style] ~85-~85: Consider removing “of” to be more concise
Context: ...vironment, * First of all, documenting all of the parameters set while following the guid...

(ALL_OF_THE)


[grammar] ~89-~89: There might be a mistake here.
Context: ...n used as the Platform Access Address. * Both HTTP Port and HTTPS Port fields...

(QB_NEW_EN)


[grammar] ~91-~91: There might be a mistake here.
Context: ...sses` field MUST include the virtual IP of current Cluster. Refer to...

(QB_NEW_EN)


[grammar] ~96-~96: There might be a mistake here.
Context: ...stallation: * Prepare for Installation * Installing ### Step ...

(QB_NEW_EN)


[grammar] ~130-~130: There might be a mistake here.
Context: ...stallation: * Prepare for Installation * Installing ### Step ...

(QB_NEW_EN)

🪛 Gitleaks (8.27.2)
docs/en/install/global_dr.mdx

298-298: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🔇 Additional comments (1)
docs/en/install/global_dr.mdx (1)

101-112: Copy/perm flow looks solid.

Uses sudo, temp path, and 600 perms; good hardening.

Comment thread docs/en/install/global_dr.mdx
Comment thread docs/en/install/global_dr.mdx
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (8)
docs/en/install/global_dr.mdx (8)

82-92: Rewrite warning directive for clarity and grammar.

Improves readability; keeps semantics unchanged.

-<Directive type="warning" title="NOTES OF DR (Disaster Recovery Environment) INSTALLING">
-While installing the primary cluster of the DR Environment,
-
-* First of all, documenting all of the parameters set while following the guide of the installation web UI. It is necessary to keep some options the same while installing the standby cluster.
-* A **User-provisioned** Load Balancer MUST be preconfigured to route traffic sent to the virtual IP. The `Self-built VIP` option is NOT available.
-* The `Platform Access Address` field MUST be a domain, while the `Cluster Endpoint` MUST be the virtual IP address.
-* Both clusters MUST be configured to use `An Existing Certificate` (has be the same one), request a legit certificate if necessary. The `Self-signed Certificate` option is NOT available.
-* When `Image Repository` is set to `Platform Deployment`, both `Username` and `Password` fields MUST NOT be empty; The `IP/Domain` field MUST be set to the domain used as the `Platform Access Address`.
-* Both `HTTP Port` and `HTTPS Port` fields of `Platform Access Address` MUST be 80 and 443.
-* When coming to the second page the of the installation guide (Step: `Advanced`), the `Other Platform Access Addresses` field MUST include the virtual IP of current Cluster.
+<Directive type="warning" title="DR (Disaster Recovery) installation notes">
+When installing the Primary cluster:
+
+* Record all parameters set in the installer UI; you will reuse them when installing the Standby cluster.
+* A user‑provisioned load balancer MUST route traffic to the VIP. The `Self-built VIP` option is NOT available.
+* `Platform Access Address` MUST be a domain; `Cluster Endpoint` MUST be the VIP.
+* Both clusters MUST use `An Existing Certificate` (the same certificate). Request a valid certificate if necessary. `Self-signed Certificate` is NOT available.
+* If `Image Repository` is `Platform Deployment`, `Username` and `Password` MUST be set; `IP/Domain` MUST be the `Platform Access Address` domain.
+* `HTTP Port` and `HTTPS Port` MUST be 80 and 443.
+* On the `Advanced` step, `Other Platform Access Addresses` MUST include the Primary cluster VIP.
 </Directive>

135-141: Add explicit security warning for 2379 here as well.

Prevent accidental public exposure; require L4 pass‑through.

-1. Configure the load balancer to forward port `2379` to control plane nodes of the corresponding cluster. ONLY TCP mode is supported; forwarding on L7 is not supported.
+1. Configure the load balancer to forward port `2379` to control‑plane nodes of the corresponding cluster. ONLY L4 TCP pass‑through is supported (no TLS termination/L7).
+   Security: Never expose `2379` publicly; restrict to control‑plane/LB addresses via firewall/ACL allow‑lists.

190-209: Re-run the ES check after restart (missing).

Docs say “restart then execute the script again,” but the snippet doesn’t re-run it.

         # Restart Elasticsearch
         xargs -r -t -- kubectl delete po -n cpaas-system <<< "${_es_pods}"
+        # Re-run the check after pods restart
+        bash /root/ensure-asm-template.sh

73-77: Add security caveat for etcd (2379) and clarify LB requirements.

Exposing 2379 is high risk; enforce L4 pass‑through and allow‑listing.

-* A unified domain which will be the `Platform Access Address`, and the TLS certificate plus private key for serving HTTPS on that domain;
-* A dedicated virtual IP address for each cluster — one for the **Primary Cluster** and another for the Standby Cluster;
-
-  * Preconfigure the load balancer to route TCP traffic on ports `80`, `443`, `6443`, `2379`, and `11443` to the control-plane nodes behind the corresponding VIP.
+* A unified domain for the `Platform Access Address`, with a TLS certificate and private key for that domain.
+* A dedicated virtual IP address for each cluster — one for the **Primary Cluster** and one for the **Standby Cluster**.
+
+  * Preconfigure the load balancer to route TCP traffic on ports `80`, `443`, `6443`, `2379`, and `11443` to the control‑plane nodes behind the corresponding VIP.
+  * Security: Never expose port `2379` (etcd) to the public internet. Restrict access to control‑plane/LB addresses via network ACLs/allow‑lists, and use pure L4 TCP pass‑through (no TLS termination or L7 inspection).

276-288: Replace real-looking Base64 secret with a placeholder and add disclaimer.

Avoid secret‑scanner hits and accidental reuse.

             - name: key1
-              secret: MTE0NTE0MTkxOTgxMA==
+              secret: <BASE64_32_BYTE_KEY_FROM_STANDBY_EXAMPLE_ONLY>

Add immediately below the YAML:

+> Note: Replace placeholders with your own randomly generated 32‑byte keys encoded in base64. Do not reuse example values.
+> Important: Kubernetes writes with the first key and reads with all. Keep the Primary’s key listed first on both clusters until rotation completes to avoid dual‑write divergence.

291-304: Replace both Base64 secrets with placeholders and call out key‑order semantics.

Two literal secrets remain; also document “first key writes” rule.

             - name: key1
-              secret: My4xNDE1OTI2NTM1ODk3
+              secret: <BASE64_32_BYTE_KEY_FROM_PRIMARY_EXAMPLE_ONLY>
             - name: key2
-              secret: MTE0NTE0MTkxOTgxMA==
+              secret: <BASE64_32_BYTE_KEY_FROM_STANDBY_EXAMPLE_ONLY>

Add immediately below the YAML (if not already added above):

+> Note: Replace placeholders with your own randomly generated 32‑byte keys encoded in base64. Do not reuse example values.
+> Important: The first key is used for writes. Keep the Primary’s key first on both clusters until rotation is finalized.

306-334: Remote script: brittle crictl usage, improper backticks, and quoting. Simplify to restart kubelet.

Backticks in the echo will try to execute kube-apiserver. Use a here‑doc, drop crictl, and just restart kubelet after installing the file.

-    ; do
-        scp /etc/kubernetes/encryption-provider.conf "<user>@${i}:/tmp/encryption-provider.conf"
-        ssh "<user>@${i}" '
-    #!/bin/bash
-    set -euo pipefail
-    
-    sudo install -o root -g root -m 600 /tmp/encryption-provider.conf /etc/kubernetes/encryption-provider.conf && rm -f /tmp/encryption-provider.conf
-    _pod_name="kube-apiserver"
-    _pod_id=$(sudo crictl ps --name "${_pod_name}" --no-trunc --quiet)
-    if [[ -z "${_pod_id}" ]]; then
-        echo "FATAL: could not find pod `kube-apiserver` on node $(hostname)"
-        exit 1
-    fi
-    sudo crictl rm --force "${_pod_id}"
-    sudo systemctl restart kubelet.service
-    '
-    done
+    ; do
+        scp /etc/kubernetes/encryption-provider.conf "<user>@${i}:/tmp/encryption-provider.conf"
+        ssh "<user>@${i}" "bash -s" <<'REMOTE'
+set -euo pipefail
+sudo install -o root -g root -m 600 /tmp/encryption-provider.conf /etc/kubernetes/encryption-provider.conf
+rm -f /tmp/encryption-provider.conf
+# Restart kubelet to reload the static pod
+sudo systemctl restart kubelet.service
+REMOTE
+    done

336-347: Single‑node restart: same crictl/backticks issues—restart kubelet only.

Mirror the simplified approach; remove backticks.

-_pod_name="kube-apiserver"
-_pod_id=$(sudo crictl ps --name "${_pod_name}" --no-trunc --quiet)
-if [[ -z "${_pod_id}" ]]; then
-    echo "FATAL: could not find pod `kube-apiserver` on node $(hostname)"
-    exit 1
-fi
-sudo crictl rm --force "${_pod_id}"
-sudo systemctl restart kubelet.service
+sudo systemctl restart kubelet.service
🧹 Nitpick comments (4)
docs/en/install/global_dr.mdx (4)

30-31: Grammar: “to indicates” → “to indicate”.

Minor fix for readability.

-* In favor of facilitating troubleshooting and management, it is recommended to name nodes in a style like `standby-global-m1`, to indicates which cluster the node belongs to (Primary or Standby).
+* In favor of facilitating troubleshooting and management, it is recommended to name nodes in a style like `standby-global-m1`, to indicate which cluster the node belongs to (Primary or Standby).

63-69: Tighten step wording and punctuation.

Make the overview steps parallel and concise.

-1. Prepare a unified domain name for platform access;
-2. Point the domain to the **Primary Cluster's** VIP and install the **Primary Cluster**;
-3. Temporarily switch DNS resolution to the standby VIP to install the Standby Cluster;
-4. Copy the ETCD encryption key of the **Primary Cluster** to the nodes that will later be the control plane nodes of Standby Cluster;
-5. Install and enable the etcd synchronization plugin;
-6. Verify sync status and perform regular checks;
-7. In case of failure, switch DNS to the standby cluster to complete disaster recovery.
+1. Prepare a unified domain name for platform access.
+2. Point the domain to the **Primary Cluster** VIP and install the **Primary Cluster**.
+3. Temporarily point the domain to the standby VIP and install the **Standby Cluster**.
+4. Copy the **Primary Cluster** ETCD encryption key to the nodes that will become the standby control plane.
+5. Install and enable the etcd synchronization plugin.
+6. Verify sync status and perform routine checks.
+7. On failure, switch DNS to the standby cluster to complete disaster recovery.

115-126: Tone and consistency in standby notes.

Normalize emphasis and punctuation; avoid “MAKE SURE”.

-<Directive type="warning" title="NOTES FOR INSTALLING STANDBY CLUSTER">
-While installing the standby cluster of the DR Environment,
-the following options MUST be set to the same as the **primary cluster**:
+<Directive type="warning" title="Standby cluster installation notes">
+While installing the standby cluster, set the following to match the **Primary Cluster**:
@@
-* All fields of `Image Repository`
-* Important: ensure the credentials of image repository and the ACP admin user match those set on the **Primary Cluster**.
+* All fields of `Image Repository`.
+* Important: ensure the image‑repository credentials and the ACP admin user credentials match those on the **Primary Cluster**.
@@
-and MAKE SURE you followed the `NOTES OF DR (Disaster Recovery Environment) INSTALLING` in Step 1.
+Ensure you followed the DR installation notes in Step 1.
 </Directive>

270-273: Quote placeholders and use consistent casing.

Minor: quote the SSH command and standardize the placeholder name.

-ssh <user>@<STANDBY cluster control plane node> sudo cat /etc/kubernetes/encryption-provider.conf
+ssh "<user>@<standby_control_plane_node>" "sudo cat /etc/kubernetes/encryption-provider.conf"
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 8d2c6fc and 7b1a705.

📒 Files selected for processing (1)
  • docs/en/install/global_dr.mdx (4 hunks)
🧰 Additional context used
🪛 LanguageTool
docs/en/install/global_dr.mdx

[grammar] ~63-~63: There might be a mistake here.
Context: ...unified domain name for platform access; 2. Point the domain to the **Primary Cluste...

(QB_NEW_EN)


[grammar] ~64-~64: There might be a mistake here.
Context: ...VIP and install the Primary Cluster; 3. Temporarily switch DNS resolution to the...

(QB_NEW_EN)


[grammar] ~65-~65: There might be a mistake here.
Context: ...ndby VIP to install the Standby Cluster; 4. Copy the ETCD encryption key of the **Pr...

(QB_NEW_EN)


[grammar] ~66-~66: There might be a mistake here.
Context: ...t will later be the control plane nodes of Standby Cluster; 5. Install and enable ...

(QB_NEW_EN)


[grammar] ~66-~66: There might be a mistake here.
Context: ... control plane nodes of Standby Cluster; 5. Install and enable the etcd synchronizat...

(QB_NEW_EN)


[grammar] ~67-~67: There might be a mistake here.
Context: ... enable the etcd synchronization plugin; 6. Verify sync status and perform regular c...

(QB_NEW_EN)


[grammar] ~68-~68: There might be a mistake here.
Context: ... sync status and perform regular checks; 7. In case of failure, switch DNS to the st...

(QB_NEW_EN)


[grammar] ~73-~73: There might be a mistake here.
Context: ...te key for serving HTTPS on that domain; * A dedicated virtual IP address for each ...

(QB_NEW_EN)


[style] ~85-~85: Often, this adverbial phrase is redundant. Consider using an alternative.
Context: ...imary cluster of the DR Environment, * First of all, documenting all of the parameters set ...

(FIRST_OF_ALL)


[style] ~85-~85: Consider removing “of” to be more concise
Context: ...vironment, * First of all, documenting all of the parameters set while following the guid...

(ALL_OF_THE)


[grammar] ~89-~89: There might be a mistake here.
Context: ...n used as the Platform Access Address. * Both HTTP Port and HTTPS Port fields...

(QB_NEW_EN)


[grammar] ~91-~91: There might be a mistake here.
Context: ...sses` field MUST include the virtual IP of current Cluster. Refer to...

(QB_NEW_EN)


[grammar] ~96-~96: There might be a mistake here.
Context: ...stallation: * Prepare for Installation * Installing ### Step ...

(QB_NEW_EN)


[grammar] ~130-~130: There might be a mistake here.
Context: ...stallation: * Prepare for Installation * Installing ### Step ...

(QB_NEW_EN)

🪛 Gitleaks (8.27.2)
docs/en/install/global_dr.mdx

301-301: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🔇 Additional comments (1)
docs/en/install/global_dr.mdx (1)

101-113: Secure copy and perms look good.

Use of sudo and mode 600 avoids key exposure; temp file cleanup is correct.

@IceCodeNew IceCodeNew merged commit 88cc9b5 into master Sep 1, 2025
1 of 2 checks passed
@IceCodeNew IceCodeNew deleted the upgrade-doc branch September 1, 2025 09:02
IceCodeNew added a commit that referenced this pull request Sep 1, 2025
* feat: introduce FAQ for installation of Global DR

* chore: instructions on restarting ES

* chore: refine the prerequisites of LB part

* chore: favored style of naming nodes

* feat: Strong warnings about the MUST-DO while installing the DR env

* chore: apply suggestions of coderabbitai

* fix: typo

* security: restrict file permission of encryption-provider.conf

* fix: Wording is awkward 🥹

* fix: ${i} won’t expand

* chore: wordy

* fix: avoid indistinct instructions

* fix: redundant instructions; reword

* fix: ensure the admin usr of standby cluster is set to the same

* fix: bug

* fix: switch to the root user
IceCodeNew added a commit that referenced this pull request Sep 1, 2025
* fix: notes of etcd backup task when upgrading from 3.16 to 4.0

* chore: preparing for release 4.0.4

* feat: introduce FAQ for installation of Global DR (#157)

* feat: introduce FAQ for installation of Global DR

* chore: instructions on restarting ES

* chore: refine the prerequisites of LB part

* chore: favored style of naming nodes

* feat: Strong warnings about the MUST-DO while installing the DR env

* chore: apply suggestions of coderabbitai

* fix: typo

* security: restrict file permission of encryption-provider.conf

* fix: Wording is awkward 🥹

* fix: ${i} won’t expand

* chore: wordy

* fix: avoid indistinct instructions

* fix: redundant instructions; reword

* fix: ensure the admin usr of standby cluster is set to the same

* fix: bug

* fix: switch to the root user
IceCodeNew added a commit that referenced this pull request Sep 1, 2025
* feat: introduce FAQ for installation of Global DR

* chore: instructions on restarting ES

* chore: refine the prerequisites of LB part

* chore: favored style of naming nodes

* feat: Strong warnings about the MUST-DO while installing the DR env

* chore: apply suggestions of coderabbitai

* fix: typo

* security: restrict file permission of encryption-provider.conf

* fix: Wording is awkward 🥹

* fix: ${i} won’t expand

* chore: wordy

* fix: avoid indistinct instructions

* fix: redundant instructions; reword

* fix: ensure the admin usr of standby cluster is set to the same

* fix: bug

* fix: switch to the root user
IceCodeNew added a commit that referenced this pull request Sep 1, 2025
* feat: introduce FAQ for installation of Global DR

* chore: instructions on restarting ES

* chore: refine the prerequisites of LB part

* chore: favored style of naming nodes

* feat: Strong warnings about the MUST-DO while installing the DR env

* chore: apply suggestions of coderabbitai

* fix: typo

* security: restrict file permission of encryption-provider.conf

* fix: Wording is awkward 🥹

* fix: ${i} won’t expand

* chore: wordy

* fix: avoid indistinct instructions

* fix: redundant instructions; reword

* fix: ensure the admin usr of standby cluster is set to the same

* fix: bug

* fix: switch to the root user
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants