<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Mongkol Thongkraikaew</title>
    <description>The latest articles on Forem by Mongkol Thongkraikaew (@mongkol_tho).</description>
    <link>https://forem.com/mongkol_tho</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2442353%2Fa247a8f1-4d52-4284-940a-656afc6475aa.JPG</url>
      <title>Forem: Mongkol Thongkraikaew</title>
      <link>https://forem.com/mongkol_tho</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mongkol_tho"/>
    <language>en</language>
    <item>
      <title>Building a Multi-Region Failover System with Amazon EKS (Step-By-Step) [Thai language]</title>
      <dc:creator>Mongkol Thongkraikaew</dc:creator>
      <pubDate>Wed, 05 Nov 2025 05:03:23 +0000</pubDate>
      <link>https://forem.com/mongkol_tho/building-a-multi-region-failover-system-with-amazon-eks-step-by-step-thai-language-aoo</link>
      <guid>https://forem.com/mongkol_tho/building-a-multi-region-failover-system-with-amazon-eks-step-by-step-thai-language-aoo</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/mongkol_tho" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2442353%2Fa247a8f1-4d52-4284-940a-656afc6475aa.JPG" alt="mongkol_tho"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/mongkol_tho/maalngsraangrabb-failover-aebb-multi-region-kab-amazon-eks-aebb-step-by-step-51c6" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;มาลองสร้างระบบ Failover แบบ Multi-Region กับ Amazon EKS (แบบ Step-by-step)&lt;/h2&gt;
      &lt;h3&gt;Mongkol Thongkraikaew ・ Nov 5&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#eks&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#aws&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#failover&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#devops&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>eks</category>
      <category>aws</category>
      <category>failover</category>
      <category>devops</category>
    </item>
    <item>
      <title>มาลองสร้างระบบ Failover แบบ Multi-Region กับ Amazon EKS (แบบ Step-by-step)</title>
      <dc:creator>Mongkol Thongkraikaew</dc:creator>
      <pubDate>Wed, 05 Nov 2025 05:01:33 +0000</pubDate>
      <link>https://forem.com/mongkol_tho/maalngsraangrabb-failover-aebb-multi-region-kab-amazon-eks-aebb-step-by-step-51c6</link>
      <guid>https://forem.com/mongkol_tho/maalngsraangrabb-failover-aebb-multi-region-kab-amazon-eks-aebb-step-by-step-51c6</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;มีใครได้ลองคิดหรือเตรียมตัวเผื่อไว้หรือยังหาก Region ที่เราใช้งานอยู่ ล่มไปในช่วงเวลาที่มีผู้ใช้งานระบบเราอยู่จำนวนมาก เราจะทำอย่างไร?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;ช่วงนี้หลายคนน่าจะได้เห็นข่าวหรือเจอเหตุการณ์ AWS ในบาง Region เกิดปัญหาจนระบบต่าง ๆ ใช้งานไม่ได้ ซึ่งเป็นอีกหนึ่ง Reminder ว่าระบบที่เราทำงานอยู่จะมองข้ามเรื่อง Availability หรือการเตรียมพร้อมรับมือกับปัญหาลักษณะแบบนี้ไม่ได้เลย &lt;/p&gt;

&lt;p&gt;ในบทความนี้ ผมจะพามาลองตั้งค่าระบบ Failover แบบ Multi-Region กับ Amazon EKS แบบ Step-by-step ให้เห็นกันชัด ๆ ว่าทำอย่างไร เหมาะสำหรับเอาไปปรับใช้กับระบบงานที่ทุกคนใช้กันอยู่ได้ เพื่อเพิ่ม resiliency ให้กับระบบของเรามากขึ้น&lt;/p&gt;

&lt;h2&gt;
  
  
  เครื่องมือที่จำเป็นสำหรับ workshop นี้
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;AWS Account
&lt;/li&gt;
&lt;li&gt;Route 53 (Public Hosted Zone)
&lt;/li&gt;
&lt;li&gt;AWS CloudShell
&lt;/li&gt;
&lt;li&gt;CLI ที่ต้องใช้: &lt;code&gt;aws&lt;/code&gt;, &lt;code&gt;envsubst&lt;/code&gt;, &lt;code&gt;eksctl&lt;/code&gt;, &lt;code&gt;kubectl&lt;/code&gt;, &lt;code&gt;kubectx&lt;/code&gt;, &lt;code&gt;kubens&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;เมื่อพร้อมแล้ว มาลองลงมือสร้างระบบไปพร้อม ๆ กันได้เลยครับ ทุกคนสามารถรันคำสั่งตามขั้นตอนที่ผมโชว์ไว้ได้ทันที&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzhvvgd1pb84hfbfw7dy0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzhvvgd1pb84hfbfw7dy0.png" alt="Diagram Workshop" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ขั้นตอนที่ 1 : ติดตั้งและตั้งค่า EKS Cluster
&lt;/h2&gt;

&lt;p&gt;1.1 เปิด CloudShell ขึ้นมาก่อน&lt;br&gt;
&lt;em&gt;***ในบทความนี้ ผมจะรันทุกคำสั่งจาก CloudShell ที่ Region: Singapore เท่านั้น เนื่องจากตอนนี้ CloudShell ยังไม่มีให้บริการที่ Region: Thailand&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;1.2 ตั้งค่าพื้นฐานและติดตั้งเครื่องมือที่ต้องใช้งาน&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export ACCOUNT_ID=$(aws sts get-caller-identity --output text --query Account)
export Region1=ap-southeast-7
export Region2=ap-southeast-1
export Region1ClusterName=eks-cluster-th
export Region2ClusterName=eks-cluster-sg
export ALBName=web-alb

# เปลี่ยนตาม domain ของแต่ละคน
export apphostname=web-demo.cloudation101.net
export HostedZoneName=cloudation101.net
export HostedZoneId=$(aws route53 list-hosted-zones-by-name --dns-name $HostedZoneName --query 'HostedZones[0].Id' --output text |  cut -d'/' -f3)

# Install envsubst cli 
sudo yum install gettext -y 

# Install eksctl
ARCH=amd64
PLATFORM=$(uname -s)_$ARCH
curl -sLO "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_$PLATFORM.tar.gz"
tar -xzf eksctl_$PLATFORM.tar.gz -C /tmp &amp;amp;&amp;amp; rm eksctl_$PLATFORM.tar.gz
sudo install -m 0755 /tmp/eksctl /usr/local/bin &amp;amp;&amp;amp; rm /tmp/eksctl

# Install kubectx, kubens cli
sudo git clone https://github.com/ahmetb/kubectx /opt/kubectx
sudo ln -s /opt/kubectx/kubectx /usr/local/bin/kubectx
sudo ln -s /opt/kubectx/kubens /usr/local/bin/kubens
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;1.3 สร้าง EKS Cluster ในทั้ง 2 Region&lt;br&gt;
ดำเนินการสร้าง EKS Cluster ใน Region หลักและ Region สำรอง เตรียมพร้อมสำหรับการทำ Multi-Region&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create EKS cluster auto mode in Region: Thailand
eksctl create cluster --name=$Region1ClusterName --enable-auto-mode --region=$Region1

# Create EKS cluster auto mode in Region: Singapore
eksctl create cluster --name=$Region2ClusterName --enable-auto-mode --region=$Region2

# Validate cluster status (Status: Active)
aws eks describe-cluster \--name $Region1ClusterName \--region $Region1 \--output json \--query 'cluster.status'

aws eks describe-cluster \--name $Region2ClusterName \--region $Region2 \--output json \--query 'cluster.status'

# รอประมาณ 15 นาทีในการสร้างแต่ละ cluster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
เมื่อ EKS Cluster สร้างแล้ว เราจะพบว่ามี EKS Cluster ถูกสร้างขึ้นในแต่ละ Region&lt;/p&gt;

&lt;p&gt;Region: Thailand&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1jurf433rgenukbbxqd4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1jurf433rgenukbbxqd4.png" alt="EKS Cluster Region: Thailand" width="800" height="198"&gt;&lt;/a&gt;&lt;br&gt;
Region: Sigapore&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxzr8nsuhqpqza7wshbje.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxzr8nsuhqpqza7wshbje.png" alt="EKS Cluster Region: Singapore" width="800" height="174"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
1.4 ทดสอบเชื่อมต่อกับ EKS Cluster ด้วย &lt;code&gt;kubectl&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectx $(kubectx | grep "eks-cluster-th")
kubectl get node

kubectx $(kubectx | grep "eks-cluster-sg")
kubectl get node 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ตัวอย่างผลลัพธ์การทดสอบเรียก EKS API&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fza6xtfa26177htqjakxf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fza6xtfa26177htqjakxf.png" alt="Kubectl get node result" width="800" height="288"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  ขั้นตอนที่ 2 : Deploy Web Application
&lt;/h2&gt;

&lt;p&gt;2.1 สร้าง IngressClass &lt;code&gt;alb&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Config ingressclassconfiguration for Thailand
kubectx $(kubectx | grep "eks-cluster-th")
curl -s https://raw.githubusercontent.com/aws-samples/multi-region-ingress/refs/heads/main/ingressclassconfiguration.yaml | kubectl apply -f -
kubectl get ingressclass,ingressclassparams

# Config ingressclassconfiguration for Singapore
kubectx $(kubectx | grep "eks-cluster-sg")
curl -s https://raw.githubusercontent.com/aws-samples/multi-region-ingress/refs/heads/main/ingressclassconfiguration.yaml | kubectl apply -f -
kubectl get ingressclass,ingressclassparams
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2.2 สร้าง ServiceAccount, Clusterrole, Service และ Deploy Web App Demo&lt;br&gt;
&lt;strong&gt;Deploy Web App @ Region: Thailand&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Switch EKS cluster
kubectx $(kubectx | grep "eks-cluster-th")

cat &amp;lt;&amp;lt;EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
  name: webapp-sa
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: webapp-clusterrole
rules:
  - apiGroups: [""]
    resources: ["nodes"]
    verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: webapp-clusterrolebinding
subjects:
  - kind: ServiceAccount
    name: webapp-sa
    namespace: default
roleRef:
  kind: ClusterRole
  name: webapp-clusterrole
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: webapp
  template:
    metadata:
      labels:
        app: webapp
    spec:
      serviceAccountName: webapp-sa
      containers:
      - image: dumlutimuralp/demoapp
        name: webapp
        env:
        - name: APP_NAME
          value: "WebApp_Demo_TH"
        - name: BG_COLOR
          value: "green" 
        - name: HEALTH
          value: "webapphealth"  
        - name: MY_NODENAME
          valueFrom:
            fieldRef:
              fieldPath: spec.nodeName
---
apiVersion: v1
kind: Service
metadata:
  name: webappservice
spec:
  selector:
    app: webapp
  ports:
    - protocol: TCP
      port: 80
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Deploy Web App @ Region: Singapore&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Switch EKS cluster
kubectx $(kubectx | grep "eks-cluster-sg")

cat &amp;lt;&amp;lt;EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
  name: webapp-sa
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: webapp-clusterrole
rules:
  - apiGroups: [""]
    resources: ["nodes"]
    verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: webapp-clusterrolebinding
subjects:
  - kind: ServiceAccount
    name: webapp-sa
    namespace: default
roleRef:
  kind: ClusterRole
  name: webapp-clusterrole
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: webapp
  template:
    metadata:
      labels:
        app: webapp
    spec:
      serviceAccountName: webapp-sa
      containers:
      - image: dumlutimuralp/demoapp
        name: webapp
        env:
        - name: APP_NAME
          value: "WebApp_Demo_SG"
        - name: BG_COLOR
          value: "red" 
        - name: HEALTH
          value: "webapphealth"  
        - name: MY_NODENAME
          valueFrom:
            fieldRef:
              fieldPath: spec.nodeName
---
apiVersion: v1
kind: Service
metadata:
  name: webappservice
spec:
  selector:
    app: webapp
  ports:
    - protocol: TCP
      port: 80
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2.3 สร้าง Ingress สำหรับ Web App ทั้ง Thailand และ Singapore Region&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Switch EKS cluster to Thailand
kubectx $(kubectx | grep "eks-cluster-th")

cat &amp;lt;&amp;lt;EOF | envsubst | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: webapp-ingress 
  annotations:
    alb.ingress.kubernetes.io/load-balancer-name: $ALBName
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
spec:
  ingressClassName: alb 
  rules:
  - host: $apphostname
    http:
      paths:
      - path: / 
        pathType: Prefix
        backend:
          service:
            name: webappservice 
            port:
               number: 80 
  - http:
      paths:
      - path: /webapphealth
        pathType: Prefix
        backend:
          service:
            name: webappservice
            port:
               number: 80 
EOF

# Switch EKS cluster to Singapore
kubectx $(kubectx | grep "eks-cluster-sg")

cat &amp;lt;&amp;lt;EOF | envsubst | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: webapp-ingress 
  annotations:
    alb.ingress.kubernetes.io/load-balancer-name: $ALBName
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
spec:
  ingressClassName: alb 
  rules:
  - host: $apphostname
    http:
      paths:
      - path: / 
        pathType: Prefix
        backend:
          service:
            name: webappservice 
            port:
               number: 80 
  - http:
      paths:
      - path: /webapphealth
        pathType: Prefix
        backend:
          service:
            name: webappservice
            port:
               number: 80 
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2.4 ตรวจสอบ Resource ที่ถูกสร้างในทั้ง 2 Region ขั้นตอนนี้ เราควรจะเห็น resource อย่างเช่น Deployment และ Ingress ถูกสร้างขึ้นครบถ้วนทั้ง 2 Region&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectx $(kubectx | grep "eks-cluster-th")
kubectl get all,ingress

kubectx $(kubectx | grep "eks-cluster-sg")
kubectl get all,ingress
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ตัวอย่างผลลัพธ์ Kubernetes resource&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb4tvz42ap9o99ayvuiyq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb4tvz42ap9o99ayvuiyq.png" alt="kubectl get all,ingress result" width="800" height="474"&gt;&lt;/a&gt;&lt;br&gt;
ทดสอบเข้าถึง website ทั้งสอง region ด้วย ALB domain&lt;br&gt;
Region: Thailand (สีเขียว)&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj5avv8bcf9peh020kq1f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj5avv8bcf9peh020kq1f.png" alt="Example website of thailand region" width="751" height="139"&gt;&lt;/a&gt;&lt;br&gt;
Region: Singapore (สีแดง)&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flscc12okbl06h1q2wbzd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flscc12okbl06h1q2wbzd.png" alt="Example website of singapore region" width="743" height="167"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  ขั้นตอนที่ 3 : ตั้งค่า Route 53 Health Check และ Record
&lt;/h2&gt;

&lt;p&gt;3.1 ตั้งค่า Health Check เพื่อคอยตรวจสอบสถานะ web application ในทั้ง 2 Region ว่ายังทำงานปกติหรือไม่&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Find ALB Domain
export Region1ALB=$(aws elbv2 describe-load-balancers --region $Region1 --query "LoadBalancers[?contains(LoadBalancerName, '$ALBName')].DNSName | [0]" --output text)
export Region2ALB=$(aws elbv2 describe-load-balancers --region $Region2 --query "LoadBalancers[?contains(LoadBalancerName, '$ALBName')].DNSName | [0]" --output text)

# Create Route 53 health check for Thailand region
aws route53 create-health-check --caller-reference "RegionTH-WebApp-$(date +%s)" \
--health-check-config "{\"Port\":80,\"Type\":\"HTTP\",\"ResourcePath\":\"/webapphealth\",\"FullyQualifiedDomainName\":\"$Region1ALB\",\"RequestInterval\":10,\"FailureThreshold\":2,\"MeasureLatency\":true,\"Inverted\":false,\"Disabled\":false,\"EnableSNI\":false}"

# Create Route 53 health check for Singapore region
aws route53 create-health-check --caller-reference "RegionSG-WebApp-$(date +%s)" \
--health-check-config "{\"Port\":80,\"Type\":\"HTTP\",\"ResourcePath\":\"/webapphealth\",\"FullyQualifiedDomainName\":\"$Region2ALB\",\"RequestInterval\":10,\"FailureThreshold\":2,\"MeasureLatency\":true,\"Inverted\":false,\"Disabled\":false,\"EnableSNI\":false}"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ตัวอย่างผลลัพธ์การสร้าง Route 53 Health Check&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2imhjcetn3ss07ad1w31.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2imhjcetn3ss07ad1w31.png" alt=" " width="800" height="155"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3.2 สร้าง Route 53 Alias Record ซึ่งเราจะสร้าง 2 Alias record สำหรับ domain: web-demo.cloudation101.net ไปยัง ALB ของทั้ง 2 region และผมจะทำการ associate แต่ละ record ด้วย healthcheck ที่ถูกสร้างขึ้นก่อนหน้านี้&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Find Health Check ID
export HealthCheckRegion1AppId=$(aws route53 list-health-checks \
  --query "HealthChecks[?HealthCheckConfig.FullyQualifiedDomainName=='$Region1ALB' &amp;amp;&amp;amp; HealthCheckConfig.ResourcePath=='/webapphealth'] | [0].Id" \
  --output text)

export HealthCheckRegion2AppId=$(aws route53 list-health-checks \
  --query "HealthChecks[?HealthCheckConfig.FullyQualifiedDomainName=='$Region2ALB' &amp;amp;&amp;amp; HealthCheckConfig.ResourcePath=='/webapphealth'] | [0].Id" \
  --output text)

# Find Hosted Zone ID of your domain
export Region1ALBHostedZoneId=$(aws elbv2 describe-load-balancers --region $Region1 --query "LoadBalancers[?DNSName=='$Region1ALB'].CanonicalHostedZoneId" --output text)
export Region2ALBHostedZoneId=$(aws elbv2 describe-load-balancers --region $Region2 --query "LoadBalancers[?DNSName=='$Region2ALB'].CanonicalHostedZoneId" --output text)

# Create the alias record for ALB's Thailand
aws route53 change-resource-record-sets --hosted-zone-id $HostedZoneId \
  --change-batch "{\"Changes\":[{\"Action\":\"CREATE\",\"ResourceRecordSet\":{\"Name\":\"$apphostname\",\"Type\":\"A\",\"SetIdentifier\":\"Region1-Primary\",\"Weight\":100,\"HealthCheckId\":\"$HealthCheckRegion1AppId\",\"AliasTarget\":{\"HostedZoneId\":\"$Region1ALBHostedZoneId\",\"DNSName\":\"$Region1ALB\",\"EvaluateTargetHealth\":false}}}]}"

# Create the alias record for ALB's Singapore
aws route53 change-resource-record-sets --hosted-zone-id $HostedZoneId \
  --change-batch "{\"Changes\":[{\"Action\":\"CREATE\",\"ResourceRecordSet\":{\"Name\":\"$apphostname\",\"Type\":\"A\",\"SetIdentifier\":\"Region2-Secondary\",\"Weight\":0,\"HealthCheckId\":\"$HealthCheckRegion2AppId\",\"AliasTarget\":{\"HostedZoneId\":\"$Region2ALBHostedZoneId\",\"DNSName\":\"$Region2ALB\",\"EvaluateTargetHealth\":false}}}]}"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;หมายเหตุ:&lt;br&gt;
ผมเลือกใช้ Routing Policy แบบ Weighted เพื่อกำหนดให้ Route 53 ตอบ ALB IP จาก Region: Thailand เป็นลำดับแรกเสมอ ตราบใดที่ Health Check ของ web app ในทั้ง 2 region ยัง healthty ทุกตัว&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;ตรวจสอบว่า DNS Record ถูกสร้างใน Hosted Zone ตามที่ต้องการแล้วหรือยัง&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws route53 list-resource-record-sets --hosted-zone-id $HostedZoneId --query "ResourceRecordSets[?Name=='$apphostname.']"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ตัวอย่างผลลัพธ์ &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk1aswc5c99ob9wn3bvsu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk1aswc5c99ob9wn3bvsu.png" alt=" " width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjpq31wq6xzr51v8g6a2w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjpq31wq6xzr51v8g6a2w.png" alt=" " width="800" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;หากทำการสร้าง Route 53 record เรียบร้อยแล้ว เราสามารถทดสอบเข้าใช้งาน website ผ่าน URL ที่เรากำหนดได้เลย (ตัวอย่าง &lt;a href="http://web-demo.cloudation101.net" rel="noopener noreferrer"&gt;http://web-demo.cloudation101.net&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fds1zga8ofx1z22z1gvmz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fds1zga8ofx1z22z1gvmz.png" alt=" " width="800" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ขั้นตอนที่ 4 : Test application failure
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4y37nbzhz0pncxauch06.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4y37nbzhz0pncxauch06.png" alt=" " width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ในขั้นตอนนี้ เราจะจำลองสถานการณ์ที่ web application ใน Region: Thailand มีปัญหา &lt;/p&gt;

&lt;p&gt;4.1 Scale down web application ในฝั่ง Thailand region&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectx $(kubectx | grep "eks-cluster-th")
kubectl scale deployment webapp --replicas=0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;หลังจากที่เราทำการ scale down (ลดจำนวน pod) ของ web application ใน Region: Thailand แล้ว จะเห็นได้ว่า Health Check ของ Route 53 สำหรับฝั่งนี้จะเปลี่ยนสถานะเป็น Unhealthy ทันที&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbdxibht294p4zhu6m7nm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbdxibht294p4zhu6m7nm.png" alt=" " width="800" height="182"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;เมื่อเราทดสอบเข้าเว็บไซต์ผ่าน URL เดิมอีกครั้ง ระบบ Route 53 จะเปลี่ยนเส้นทางการเข้าถึงไปยัง web application ในฝั่ง Singapore region ให้โดยอัตโนมัติ&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff1csngl0j7ahrjq4f44e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff1csngl0j7ahrjq4f44e.png" alt=" " width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;หมายเหตุ:&lt;br&gt;
ความเร็วในการเปลี่ยนเส้นทาง (redirect) ผู้ใช้ไปยัง Singapore region จะขึ้นอยู่กับหลายปัจจัย เช่น เงื่อนไขของ Health Check ที่ตั้งไว้, ค่า DNS TTL ของฝั่ง client, รวมถึงการตั้งค่า ALB และค่า HTTP Keepalive ของ ALB ด้วย&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  ขั้นตอนที่ 5 : Clean up Environment
&lt;/h2&gt;

&lt;p&gt;5.1 Delete Route53 Alias Record&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws route53 change-resource-record-sets --hosted-zone-id $HostedZoneId \
  --change-batch "{\"Changes\":[{\"Action\":\"DELETE\",\"ResourceRecordSet\":{\"Name\":\"$apphostname\",\"Type\":\"A\",\"SetIdentifier\":\"Region1-Primary\",\"Weight\":100,\"HealthCheckId\":\"$HealthCheckRegion1AppId\",\"AliasTarget\":{\"HostedZoneId\":\"$Region1ALBHostedZoneId\",\"DNSName\":\"$Region1ALB\",\"EvaluateTargetHealth\":false}}}]}"

aws route53 change-resource-record-sets --hosted-zone-id $HostedZoneId \
  --change-batch "{\"Changes\":[{\"Action\":\"DELETE\",\"ResourceRecordSet\":{\"Name\":\"$apphostname\",\"Type\":\"A\",\"SetIdentifier\":\"Region2-Secondary\",\"Weight\":0,\"HealthCheckId\":\"$HealthCheckRegion2AppId\",\"AliasTarget\":{\"HostedZoneId\":\"$Region2ALBHostedZoneId\",\"DNSName\":\"$Region2ALB\",\"EvaluateTargetHealth\":false}}}]}"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;5.2 Delete Route53 Health Check&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws route53 delete-health-check --health-check-id $HealthCheckRegion1AppId
aws route53 delete-health-check --health-check-id $HealthCheckRegion2AppId
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;5.3 Delete EKS Cluster&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eksctl delete cluster --name=$Region1ClusterName --region=$Region1
eksctl delete cluster --name=$Region2ClusterName --region=$Region2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Lesson learned จาก Workshop
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Granular failover effect:&lt;/strong&gt; หากผูกหลายๆ service กับ ALB ตัวเดียวกัน, Route 53 จะไม่ทำการ failover ไปอีก region ทั้งหมด ถึงแม้ว่าจะมีแค่บาง service unhealthty (เนื่องจากมีการกำหนด Evaluate Target Health : &lt;strong&gt;No&lt;/strong&gt; ใน alias records)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Active-active Routing&lt;/strong&gt;: หากต้องการให้ระบบทำงานแบบ &lt;a href="https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/dns-failover-types.html#dns-failover-types-active-active" rel="noopener noreferrer"&gt;Active-active failover&lt;/a&gt; ให้กำหนด routing policy ให้เหมือนกันในทั้งสอง alias record&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Health Check แบบ HTTPS&lt;/strong&gt;: ถ้าตั้งค่า health check endpoint เป็น HTTPS, Route 53 health checker จะไม่ทำการ validate SSL/TLS Certificate แต่อย่างใด&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring Private IP&lt;/strong&gt;: Route 53 health checker ไม่รองรับการตรวจสอบ endpoint ที่เป็น private IP หากต้องการ monitor private IP แนะนำให้ใช้งาน &lt;a href="https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/monitoring-health-checks.html" rel="noopener noreferrer"&gt;CloudWatch alarms&lt;/a&gt; หรือ &lt;a href="https://aws.amazon.com/blogs/networking-and-content-delivery/performing-route-53-health-checks-on-private-resources-in-a-vpc-with-aws-lambda-and-amazon-cloudwatch/" rel="noopener noreferrer"&gt;AWS Lambda&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ค่าใช้จ่าย Health Check&lt;/strong&gt;: ควรระมัดระวังการสร้าง AWS Route 53 Health Check ในปริมาณมาก เนื่องจากอาจเกิดค่าใช้จ่ายที่สูงได้&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwnx42ehpv23roknlzi8m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwnx42ehpv23roknlzi8m.png" alt=" " width="800" height="383"&gt;&lt;/a&gt;&lt;br&gt;
Ref: &lt;a href="https://aws.amazon.com/route53/pricing/" rel="noopener noreferrer"&gt;https://aws.amazon.com/route53/pricing/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What can be improved?
&lt;/h2&gt;

&lt;p&gt;แม้ในบทความนี้จะพูดถึงการทำ Multi-Region Failover สำหรับ workload ที่รันบน EKS เป็นหลัก แต่ในความเป็นจริงเราก็คงไม่ใช้แค่ Kubernetes อย่างเดียวแน่นอน ส่วนใหญ่มักจะมี service อื่น ๆ ที่ต้องเกี่ยวข้องด้วย เช่น RDS, MSK, S3, ไปจนถึง storage อย่าง EBS ด้วย ซึ่งแต่ละ service ก็จะมีเทคนิคหรือ practice ในการเตรียมพร้อมรับมือกรณี Region ล่มที่แตกต่างกันออกไป&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Amazon RDS&lt;/strong&gt;&lt;br&gt;
ถ้าใช้ RDS MySQL, PostgreSQL หรือ Aurora สามารถตั้งค่า “Read Replica” ข้าม Region ได้เลย หรือข้ามไปใช้ Aurora Global Database (ยังไม่รองรับที่ Thailand Region) เลยก็ได้ ขึ้นอยู่ RTO, RPO ที่เราต้องการ&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Amazon MSK (Kafka)&lt;/strong&gt;&lt;br&gt;
สำหรับ MSK ยังไม่มี fully managed multi-region replication เหมือน RDS Aurora ดังนั้นจึงจำเป็นต้องใช้เครื่องมือช่วยอย่าง MSK Replicator หรือ Open source อย่าง MirrorMaker2 ในการ replicate ข้อมูลระหว่าง 2 region&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Amazon S3&lt;/strong&gt;&lt;br&gt;
S3 รองรับการทำ “Cross-Region Replication” (CRR) อยู่แล้ว สามารถตั้ง policy ให้ bucket สำคัญ replicate ข้อมูลข้าม Region ได้อัตโนมัติ&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Amazon EBS&lt;/strong&gt;&lt;br&gt;
EBS ไม่สามารถ attach ข้าม Region ได้โดยตรง วิธีป้องกันที่ดีที่สุดคือ สร้าง snapshot แล้ว replicate snapshot ไปยัง Region ปลายทาง&lt;/p&gt;

&lt;p&gt;ส่วน Practices อื่นๆ ผมอยากแนะนำให้ลองอ่าน series &lt;a href="https://aws.amazon.com/blogs/architecture/tag/creating-a-multi-region-application-with-aws-services-series/" rel="noopener noreferrer"&gt;Creating a Multi-Region Application with AWS Services series&lt;/a&gt; เพื่อเป็นแนวทาง&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fttq0mndfx8wmon4l5ged.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fttq0mndfx8wmon4l5ged.png" alt="AWS Services Multi-region pracetics diagram" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  สรุป
&lt;/h2&gt;

&lt;p&gt;หวังว่าบทความนี้จะช่วยให้ทุกคนเห็นภาพและเข้าใจแนวคิดการออกแบบระบบ Failover แบบ Multi-Region สำหรับ EKS ได้ชัดเจนขึ้นนะครับ ไม่ว่าจะวางแผนสำหรับโปรเจกต์ขนาดใหญ่ หรือเริ่มต้นยกระดับมาตรฐานของระบบที่ดูแลอยู่ แนวทางนี้สามารถนำไปประยุกต์ใช้ได้ในหลากหลายรูปแบบ และผมเชื่อว่าการออกแบบให้ระบบรองรับการ failover ได้ จะช่วยให้เราจัดการกับสถานการณ์ไม่คาดคิดได้ดีขึ้น&lt;/p&gt;

&lt;p&gt;สุดท้ายแล้ว การเลือกว่า​จะออกแบบระบบ failover ของเราให้ละเอียดหรือทำ Multi-Region สำหรับทุก service หรือไม่ อาจไม่มีสูตรสำเร็จตายตัว สิ่งสำคัญคือต้องประเมินทั้งต้นทุนที่ต้องลงทุนเพิ่มเติม (ไม่ว่าจะเป็นค่า infrastructure หรือค่าใช้จ่ายในการดูแล) เทียบกับเป้าหมาย RTO/RPO ที่องค์กรรับได้ รวมถึงผลกระทบต่อธุรกิจหากเกิดเหตุระบบล่มขึ้นมา ซึ่งบางทีเราอาจต้องเลือกแค่ service ที่ critical จริง ๆ หรือข้อมูลที่สำคัญเท่านั้นให้รองรับ Multi-Region ก็พอ ในขณะที่ service อื่น ๆ ที่ business impact ไม่มากอาจไม่ต้องลงทุนสูงขนาดนั้น และอย่าลืมเรื่องการวางแผน ทดลอง และทดสอบ Disaster Recovery (DR) ข้าม region อย่างสม่ำเสมอ เพื่อให้มั่นใจว่าระบบที่ออกแบบมานั้นสามารถใช้รับมือเหตุการณ์ฉุกเฉินได้จริง ไม่ใช่เพิ่งมาพบปัญหาในวันที่เกิดเหตุแล้ว&lt;/p&gt;

&lt;p&gt;ถ้าใครมีคำถามหรืออยากแลกเปลี่ยนประสบการณ์ในการทำ Multi-Region Failover บน EKS สามารถคอมเมนต์พูดคุยกันได้เลยครับ ยินดีแชร์และตอบทุกเคสเหมือนเดิม ขอให้ทุกคนมี Infrastructure ที่พร้อมกับทุกสถานการณ์ครับ&lt;/p&gt;

&lt;p&gt;Original Workshop: &lt;a href="https://aws.amazon.com/blogs/containers/implementing-granular-failover-in-multi-region-amazon-eks/" rel="noopener noreferrer"&gt;https://aws.amazon.com/blogs/containers/implementing-granular-failover-in-multi-region-amazon-eks/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>eks</category>
      <category>aws</category>
      <category>failover</category>
      <category>devops</category>
    </item>
    <item>
      <title>12 เครื่องมือ Debug Kubernetes เจ๋งๆ ที่ควรต้องมีติดมือไว้</title>
      <dc:creator>Mongkol Thongkraikaew</dc:creator>
      <pubDate>Sun, 30 Mar 2025 17:56:51 +0000</pubDate>
      <link>https://forem.com/mongkol_tho/12-ekhruuengmuue-debug-kubernetes-ecchng-thiikhwrtngmiitidmuueaiw-1pla</link>
      <guid>https://forem.com/mongkol_tho/12-ekhruuengmuue-debug-kubernetes-ecchng-thiikhwrtngmiitidmuueaiw-1pla</guid>
      <description>&lt;p&gt;การ Debug Kubernetes อาจเป็นงานยากสำหรับใครหลายๆคน อาจใช้เวลานานในการจะหาสาเหตุของบางปัญหา แต่ถ้าเรามีเครื่องมือดี ๆ อยู่ในมือ มันก็จะช่วยให้เราทำงานกับ Kubernetes ได้ง่ายขึ้น วันนี้ผมจะมาแชร์เครื่องมือที่นิยมที่จะมาช่วยทั้งการแก้ปัญหา, ตรวจสอบประสิทธิภาพ และตรวจจับข้อบกพร่องต่าง ๆ ของ Kubernetes มาลองดูกันครับ&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. kubectl debug&lt;/strong&gt;&lt;br&gt;
    CLI ที่ช่วยให้เราสามารถสร้าง ephemeral container เข้าไปยัง Pod ที่กำลังทำงานอยู่ หรือสร้าง Pod จำลองที่ต้องการโดยเปลี่ยน attribute บางอย่างเช่น entrypoint, image version&lt;br&gt;
    ยกตัวอย่างสถานการณ์ที่เราอยากนำเครื่องมือ network troubleshooting เช่น ping, traceroute, nc, tcpdump ไปช่วย investigate ปัญหา network ของ Pod application กับปลายทาง ก็สามารถรันคำสั่ง:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;kubectl debug app-Pod -it —image=nicolaka/netshoot&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://kubernetes.io/docs/reference/kubectl/generated/kubectl_debug" rel="noopener noreferrer"&gt;Document&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. kubectl top&lt;/strong&gt;&lt;br&gt;
   CLI สำหรับดูการใช้งาน resource (CPU/Memory) ของแต่ละ Pod หรือแต่ละ Node (ต้องมี Metrics Server ทำงานอยู่บน cluster ที่เราต้องการตรวจสอบด้วย)&lt;br&gt;
    ตัวอย่าง:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl top node&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl top pod&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kubernetes.io/docs/reference/kubectl/generated/kubectl_top" rel="noopener noreferrer"&gt;Document&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Ktop&lt;/strong&gt;&lt;br&gt;
   Kubectl plugin สำหรับดูการใช้งาน resource เช่นเดียวกับ kubectl top แต่จะสรุปข้อมูล insight บางอย่างเพิ่มเติมและปรับวิธีการแสดงผลให้ดูง่ายขึ้น&lt;/p&gt;

&lt;p&gt;ตัวอย่าง:&lt;br&gt;
    &lt;code&gt;kubectl ktop --namespace cloudation101&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/vladimirvivien/ktop" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Kube-capacity&lt;/strong&gt;&lt;br&gt;
   Kubectl plugin ที่รวมผลลัพท์ระหว่าง kubectl top และ kubectl describe เพื่อให้เราเห็น request, limit รวมถึง utilization ของ resource ต่างๆ บน Kubernetes cluster ผ่านแสดงผลในหน้าเดียว&lt;/p&gt;

&lt;p&gt;ตัวอย่าง: &lt;br&gt;
    &lt;code&gt;kubectl resource-capacity --util&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/robscott/kube-capacity" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Netshoot&lt;/strong&gt;&lt;br&gt;
   Docker image และ Kubectl plugin สำหรับ troubleshoot ปัญหาที่เกี่ยวกับ container networking เช่น latency, routing, DNS resolving, firewall, ARPs&lt;/p&gt;

&lt;p&gt;ยกตัวอย่างสถานการณ์ที่ใช้บ่อยๆ: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;การดู latency หรือทดสอบ networking performance ระหว่าง container/host ( iperf )&lt;/li&gt;
&lt;li&gt;การ analysis network packet ( tcpdump )&lt;/li&gt;
&lt;li&gt;การ scanning port (nmap)&lt;/li&gt;
&lt;li&gt;monitor container metric (CPU, memory, network, I/O) แบบ real-time (ctop)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/nicolaka/netshoot" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Kubetab&lt;/strong&gt;&lt;br&gt;
   Kubectl plugin สำหรับสร้าง proxy ที่ Kubernetes service เพื่อ intercept หรือ tab request ที่จะถูก forward ไปยัง Pod เหมือนเวลาเราใช้ BurpSuite หรือ Zap ในการ tab request ระหว่าง browser และ server &lt;br&gt;
   หลักการทำงานคือจะทำการรัน proxy container (เริ่มต้นใช้ MITMProxy)ในรูปแบบของ sidecar และคอย intercept request ก่อนส่งต่อไปยัง application container&lt;/p&gt;

&lt;p&gt;ยกตัวอย่างสถานการณ์ที่ใช้บ่อยๆ: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Security testing : capture และ modify HTTP request ก่อนที่จะลองส่งไปยัง Pod &lt;/li&gt;
&lt;li&gt;Developer debugging : ใช้สำหรับตรวจสอบดู connection request ที่มีปัญหาในระหว่างการ request ไปยัง service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ตัวอย่าง:&lt;br&gt;
   &lt;code&gt;kubectl tap on app-service -p443 --https --browser&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://soluble-ai.github.io/kubetap/" rel="noopener noreferrer"&gt;Document&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Kubeshark&lt;/strong&gt;&lt;br&gt;
    CLI สำหรับ capture real-time traffic ทั้ง API Call และข้อมูลที่รับส่งกันใน Kubernetes cluster (เหมือน TCPDump หรือ Wireshark สำหรับ Kubernetes) จุดเด่นคือ มี UI Console ให้กดดูได้อย่างสะดวก&lt;/p&gt;

&lt;p&gt;ตัวอย่าง:&lt;br&gt;
   &lt;code&gt;kubeshark tap --set headless=true&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/kubeshark/kubeshark" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. Kubectl-trace&lt;/strong&gt;&lt;br&gt;
   Kubectl plugin ที่ทำให้เราส่ง bpftrace script เข้าไปรันบน node เพื่อ probe ข้อมูลจาก Linux kernel โดยตรงทั้ง Userspace (uprobe) และ kernel space (kprobe) ไม่จำเป็นต้องติดตั้งอะไรเพิ่มเติม โดยจะ run Pod "trace-runner" บน node ที่ต้องการ และรัน bpftrace เพื่อ compile script เป็น eBPF byte-code จากนั้นติดตั้งลงไปใน Linux kernel เพื่อ probe ข้อมูลตามที่เราต้องการ&lt;/p&gt;

&lt;p&gt;ยกตัวอย่าง use case: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Trace ปัญหา OOM killed&lt;/li&gt;
&lt;li&gt;ดูการทำงานของ CPU Scheduler เพื่อตรวจสอบการ throttle CPU&lt;/li&gt;
&lt;li&gt;ตรวจสอบหาการ deadlocks ของ running process&lt;/li&gt;
&lt;li&gt;ตรวจสอบหาทำงานของ disk ว่าเกิดจากไฟล์ไหน process ใดที่ช้า&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/iovisor/kubectl-trace" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;9. Inspektor-gadget&lt;/strong&gt; &lt;br&gt;
   Kubectl plugin  สำหรับ probe ข้อมูลต่างๆ Linux kernel ด้วยความสามารถของ eBPF เช่นเดียวกับ “Kubectl-trace” แต่ที่แตกต่างจาก Kubectl-trace คือ Inspektor-gadget จะ pack bpf script ต่างๆมาให้แล้ว ไม่จำเป็นต้องมาเข้าใจ มาเขียน script ทำให้สามารถเรียกใช้งานแบบง่ายๆผ่าน plugin ได้เลย&lt;/p&gt;

&lt;p&gt;ตัวอย่าง:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;kubectl gadget run trace_exec:latest&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;kubectl gadget run trace_open:latest -n default -c myapp&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://inspektor-gadget.io/" rel="noopener noreferrer"&gt;Document&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;10. kubectl tree&lt;/strong&gt;&lt;br&gt;
    Kubectl plugin สำหรับแสดง dependency หรือความสัมพันธ์ระหว่าง resource ต่างๆ เช่น ตรวจสอบว่าภายใต้ deployment มี replicaset และ Pod ใดบ้าง รวมถึงสถานะของแต่ละ Pod ภายใต้ deployment นั้นๆด้วย&lt;/p&gt;

&lt;p&gt;ตัวอย่าง:&lt;br&gt;
   &lt;code&gt;kubectl tree deployment nginx&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ahmetb/kubectl-tree" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;11. kubectl spy&lt;/strong&gt;&lt;br&gt;
    CLI สำหรับดูการเปลี่ยนแปลงของ resource ต่างๆบน Kubernetes แบบ real-time&lt;/p&gt;

&lt;p&gt;ยกตัวอย่างสถานการณ์ที่ใช้บ่อยๆ:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; ตรวจสอบสถานะการ rollout deployment &lt;/li&gt;
&lt;li&gt; ตรวจสอบการเปลี่ยนแปลง Pod status&lt;/li&gt;
&lt;li&gt; ตรวจสอบการเปลี่ยนแปลง IP Endpoint ของ service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/pulumi/kubespy" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;12. K8sGPT&lt;/strong&gt;&lt;br&gt;
    CLI สำหรับสแกนข้อมูลและวิเคราะห์ปัญหาต่างๆบน Kubernetes cluster ร่วมกับ AI Model พร้อมแนะนำวิธีการแก้ไขแต่ละปัญหา โดยเริ่มต้นใช้ “OpenAI” สำหรับการวิเคราะห์ข้อมูล แต่เราสามารถเปลี่ยนเป็น model อื่นๆได้ เช่น ollama , bedrock, Gemini, Azure OpenAI หรือจะเป็น local model ของเราเองก็ได้เช่นกัน&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/k8sgpt-ai/k8sgpt" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;สุดท้ายแล้วเครื่องมือเหล่านี้เป็นแค่ตัวช่วยให้เราจัดการ Kubernetes ได้สะดวกมากขึ้นนะครับ ซึ่งสิ่งสำคัญที่สุดคือเราต้องเข้าใจการทำงานของ Kubernetes ก่อน แล้วเลือกใช้เครื่องมือให้เหมาะกับสถานการณ์ ถึงจะถือว่าเป็นการจัดการ Kubernetes ได้อย่างมีประสิทธิภาพ&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>kubernetes</category>
      <category>awscommunity</category>
      <category>awscommunitybuilder</category>
      <category>tooling</category>
    </item>
    <item>
      <title>จัดการ Kubernetes Resources ด้วย kro (Kube Resource Orchestrator)</title>
      <dc:creator>Mongkol Thongkraikaew</dc:creator>
      <pubDate>Sat, 16 Nov 2024 16:48:11 +0000</pubDate>
      <link>https://forem.com/mongkol_tho/cchadkaar-kubernetes-resources-dwy-kro-kube-resource-orchestrator-1g6h</link>
      <guid>https://forem.com/mongkol_tho/cchadkaar-kubernetes-resources-dwy-kro-kube-resource-orchestrator-1g6h</guid>
      <description>&lt;p&gt;&lt;strong&gt;kro (Kube Resource Orchestrator)&lt;/strong&gt; เป็น​ Open source จาก awslabs ที่มาช่วยให้การจัดการ Kubernetes Resources ทำได้สะดวกมากขึ้น&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;💡อธิบายให้เข้าใจง่ายๆเลยนะครับ :&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;เมื่อเราจะ Provision หรือรัน Application ใดๆ ใน Kubernetes แน่นอนว่าเราจำเป็นต้องสร้าง Resource ต่างๆ เช่น Deployment, ServiceAccount, Service, Ingress, PV, PVC ใช่ไหมครับ ซึ่ง Resource เหล่านี้อาจจะต้องสร้างซ้ำๆ ในทุก Application ที่รันบนคลัสเตอร์ และสำหรับมือใหม่อาจจะมีความสับสนว่าเราควรสร้าง Resource อะไรก่อนดี ความยุ่งยากนี้แหละครับที่ kro จะเข้ามาช่วยเรา&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ResourceGroup (RG) เป็น key ของ kro ครับ จริงๆแล้วมันคือ  Custom Resource Definitions (CRDs) สำหรับกำหนดกลุ่มของ Resource ที่เราต้องการ เช่น หากเราต้องการให้ Application ที่จะรันบนคลัสเตอร์มี Deployment, ServiceAccount, Service และ Ingress รูปแบบไหน เราก็สามารถกำหนดลงไปใน RG ได้เลย&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;หลังจากที่เราสร้าง RG เสร็จแล้ว เราจะได้ API และ Kind API ใหม่ของเราเอง ในตัวอย่างนี้เราจะได้ Kind ที่ชื่อว่า “ApplicationStack”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;สำหรับการใช้งานนั้น End User หรือ Developer (Dev Team A, Team B) ก็เพียงแค่เรียกใช้งาน “ApplicationStack” ที่ได้ถูกกำหนดไว้แล้ว โดยไม่จำเป็นต้องรู้รายละเอียดทั้งหมดของ Kubernetes Resources หลังจาก Developer ได้สร้าง ApplicationStack ของตัวเอง, kro ก็จะทำการสร้าง Deployment, ServiceAccount, Service และ Ingress ให้ตามที่ได้กำหนดไว้ใน RG&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhqhyy0cwvgjxuafyov41.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhqhyy0cwvgjxuafyov41.png" alt="Image description" width="800" height="670"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;💡ฟีเจอร์และประโยชน์ของ kro:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ลดความซับซ้อนในการจัดการ Kubernetes Resources&lt;/li&gt;
&lt;li&gt;สนับสนุนการทำงานตาม Platform Engineering Practice, ทำให้ทีม Platform สามารถควบคุม standard, compliant, security best practices ได้ง่ายขึ้น&lt;/li&gt;
&lt;li&gt;สามารถตรวจสอบสถานะของ Resources ทั้งหมดได้ผ่าน ResourceGroup ได้&lt;/li&gt;
&lt;li&gt;รองรับ Resources ที่เป็น Native ของ Kubernetes และ Custom Resource Definitions (CRDs) ที่ติดตั้งอยู่บนคลัสเตอร์&lt;/li&gt;
&lt;li&gt;และอื่นๆ&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;จากการทดสอบที่ผมได้ลองเล่นดู เราสามารถนำ kro ไปต่อยอดได้หลายอย่างครับ เช่น:&lt;br&gt;
&lt;strong&gt;Ex.1:&lt;/strong&gt; ทำให้การทำงานของ Platform Engineering ง่ายขึ้น โดยที่หน้าที่ของทีม Platform คือการกำหนดมาตรฐานของ ResourceGroup ออกมา และให้ผู้ใช้สามารถ Self-Service ในการ Provision สิ่งที่ต้องการได้ด้วยตัวเอง นอกจากนี้ทีม Platform อาจจะเสริมด้วยการ control permission โดยจะอนุญาตให้ user interact กับ ResourceGroup ได้เท่านั้น จะไม่อนุญาตให้ user สร้าง Deployment หรือ Ingress ได้ตรงๆ เป็นต้น&lt;br&gt;
🔗&lt;a href="https://kro.run/examples/web-app-ingress" rel="noopener noreferrer"&gt;Link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ex.2:&lt;/strong&gt; ช่วยในการ Provision Kubernetes Resources พร้อมกับ Cloud Resources ได้ง่ายขึ้น ในตัวอย่างนี้ Pod หรือ Application จำเป็นต้องใช้งาน RDS และต้องนำ IP ของ RDS ไปใช้งานใน Application ด้วย เราสามารถทำสิ่งเหล่านี้ได้เพียงไฟล์ YAML ไฟล์เดียว&lt;br&gt;&lt;br&gt;
🔗&lt;a href="https://kro.run/examples/pod-rds-dbinstance" rel="noopener noreferrer"&gt;Link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ex.3:&lt;/strong&gt; ทีม SRE อาจสร้าง ResourceGroup สำหรับ Observability Tools เช่น Logging Stack, Monitoring Stack, และ Tracing Stack หากต้องการสร้าง Stack ใหม่ ก็ไม่จำเป็นต้องประกอบร่าง Kubernetes Resources ใหม่ทั้งหมด&lt;/p&gt;

&lt;p&gt;Ps. This project is in active development and not yet intended for production use&lt;br&gt;
&lt;a href="https://kro.run/docs/overview" rel="noopener noreferrer"&gt;Official Doc&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/awslabs/kro" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
