1. บทนำ - Kubernetes Secrets Management ยุคใหม่
ในระบบที่ใช้ Kubernetes การจัดการ Secrets เป็นสิ่งสำคัญที่สุดๆ หนึ่ง แต่การจัดการ Secrets แบบดั้งเดิมมีข้อจำกัดมากมาย ไม่ว่าจะเป็นการเก็บข้อมูลในรูปแบบ plain text การไม่มีวงจรการหมุนเวียน (rotation) ของ secrets และการเข้ารหัสที่มีข้อจำกัด
ปัญหาหลักที่พบ:
- ก่อนเก็บ secrets ไว้ใน Kubernetes Secret ซึ่งเข้ารหัสด้วย base64 (ไม่ใช่ encryption จริง)
- การจัดการ secrets แบบ manual ใช้เวลานานและมีโอกาสเกิดข้อผิดพลาดสูง
- ไม่มีระบบ auto-rotation ทำให้ secrets เก่าอาจรั่วไหลได้ง่าย
- Kubernetes Secret มีขนาดจำกัดและไม่มี versioning ที่ชัดเจน
- ขาดการ audit logs และ visibility ที่ดี
External Secrets Operator คืออะไร?
External Secrets Operator (ESO) คือ Open Source Project ที่อยู่ภายใต้ CNCF (Cloud Native Computing Foundation) ซึ่งช่วยให้ Kubernetes สามารถดึงข้อมูล Secrets จาก external secret managers แบบ real-time โดยอัตโนมัติ ทำให้เราสามารถใช้ระบบการจัดการ secrets ที่มีประสิทธิภาพสูงจาก cloud providers หรือ self-hosted solutions เช่น HashiCorp Vault AWS Secrets Manager และ Google Cloud Secret Manager
สถิติจาก Community (2024-2025)
*ข้อมูลจาก GitHub และ CNCF Project Status Report (ธันวาคม 2025)
ถ้าไม่มี External Secrets ใน Production ต้องทำยังไง?
นักพัฒนาและ DevOps engineers ต่างต้องหันมาใช้วิธีการที่ fraught ด้วยความเสี่ยง:
- Hardcoding secrets - ใส่รหัสผ่านลงในโค้ดโดยตรง ผิดหลักความปลอดภัยสูงสุด
- Environment variables - ไม่ปลอดภัยเมื่อมีการ scale ในระบบที่ซับซ้อน
- Manual scripts - ต้องเขียน script จัดการทีละตัว ใช้เวลาและเสี่ยงต่อข้อผิดพลาด
- Third-party secrets managers - แต่ต้องเขียน integration เอง ซับซ้อนและไม่รองรับ GitOps
External Secrets Operator คือคำตอบที่ดีที่สุดสำหรับ Kubernetes-native secrets management!
2. External Secrets Operator Architecture
ความเข้าใจในสถาปัตยกรรมของ ESO เป็นสิ่งสำคัญในการนำไปใช้งานอย่างมีประสิทธิภาพ โครงสร้างของ ESO ประกอบด้วยองค์ประกอบหลัก 3 ตัวคือ Controller SecretStore และ ExternalSecret
Workflow ของ External Secrets Operator:
Architecture Diagram (800x400)
Controller
Watch changes และ sync secrets อัตโนมัติ
SecretStore
Configure external secret managers
ExternalSecret
Define which secrets to fetch
3. เปรียบเทียบ External Secrets vs HashiCorp Vault vs Cloud Providers
การเลือกมาตฐานการจัดการ secrets ขึ้นอยู่กับความต้องการขององค์กร ตารางเปรียบเทียบด้านล่างจะช่วยให้คุณเห็นภาพรวมของแต่ละ solution
| คุณสมบัติ | External Secrets Operator | HashiCorp Vault | AWS Secrets Manager | Azure Key Vault |
|---|---|---|---|---|
| ต้นทุน | Free (open source) | Free/Enterprise | Paid (AWS) | Paid (Azure) |
| ความยากในการเรียนรู้ | ระดับปานกลาง | สูง | ระดับปานกลาง | ระดับปานกลาง |
| Multi-cloud | สนับสนุน | สนับสนุน | AWS เท่านั้น | Azure เท่านั้น |
| GitOps Support | Native Support | Need manual | Need manual | Some support |
| การเข้ารหัส | Auto (K8s native) | Auto | Auto | Auto |
| Secret Rotation | สนับสนุน | สนับสนุน | สนับสนุน | สนับสนุน |
| เหมาะสำหรับ | K8s native, multi-cloud | Complex, self-hosted | AWS-only environments | Azure environments |
ข้อควรระวัง:
- External Secrets Operator ไม่ได้เป็น secrets manager แต่เป็น bridge กับ secrets manager ภายนอก
- Vault ต้องมีการตั้งค่าและความเสถียรของ cluster ด้วยตัวเอง
- Cloud-based secrets managers มักจะมีต้นทุนเพิ่มตามปริมาณการใช้งาน
คำแนะนำ:
เลือก External Secrets Operator ถ้า:
- ใช้ Kubernetes เป็น primary platform
- ต้องการ multi-cloud หรือ hybrid cloud
- ใช้ GitOps ในการ deploy
- ต้องการ open source solution
4. สิ่งที่ต้องเตรียม (Prerequisites)
ทักษะที่จำเป็น
| ทักษะ/เครื่องมือ | ระดับที่ต้องใช้ | เหตุผล |
|---|---|---|
| Kubernetes | ระดับกลาง | ESO ทำงานบน Kubernetes clusters |
| GitOps (Argo CD/Flux) | พื้นฐาน | ESO ทำงานได้ดีที่สุดกับ GitOps workflow |
| External Secret Manager | ระดับเริ่มต้น | Vault/AWS/GCP/Azure |
| YAML | ขั้นสูง | การตั้งค่า ESO |
| Linux | ระดับกลาง | K8s cluster nodes |
| kubectl | ระดับกลาง | จัดการ K8s resources |
| Helm (ทางเลือก) | ระดับพื้นฐาน | การติดตั้ง ESO แบบที่ง่ายที่สุด |
Hardware Requirements
Kubernetes Cluster
- ขั้นต่ำ: 3 nodes
- แนะนำ: 5+ nodes
- Minimum Kubernetes version: 1.20+
- แนะนำ: 1.24+ (สำหรับ CustomResourceDefinition support)
Hardware Resources
Min (Development)
4GB RAM, 2 vCPUs
Recommended (Production)
8GB RAM, 4 vCPUs
หมายเหตุ:
สเปคที่แนะนำไม่รวมกับ secrets manager backend ที่เชื่อมต่อ (เช่น Vault cluster) ซึ่งจะต้องมีทรัพยากรของตัวเอง
5. การติดตั้ง External Secrets Operator (4 Methods)
หมายเหตุสำคัญ:
ตัวเลือกทั้ง 4 มีเป็น "วิธีการติดตั้ง" ที่หลากหลาย คุณสามารถเลือกใช้วิธีใดวิธีหนึ่งเท่านั้น ไม่จำเป็นต้องทำทุกวิธี!
External Secrets Operator สามารถติดตั้งได้หลายวิธี วิธีที่แนะนำที่สุดคือใช้ Helm chart ซึ่งง่ายและมีการจัดการ dependencies ให้โดยอัตโนมัติ
.Method 1: Official Helm Chart (Recommended)
วิธีการติดตั้งที่แนะนำที่สุดด้วย Helm chart อย่างเป็นทางการจาก External Secrets Project
# เพิ่ม External Secrets Helm repository
helm repo add external-secrets https://charts.external-secrets.io
helm repo update
# ติดตั้ง External Secrets Operator
helm install external-secrets \
external-secrets/external-secrets \
-n external-secrets \
--create-namespace \
--wait
คำอธิบาย: คำสั่งด้านบนจะสร้าง namespace "external-secrets" และติดตั้ง ESO พร้อม CRDs และ service accounts ที่จำเป็น
Method 2: Kubectl apply (Manual)
วิธีการติดตั้งแบบ Manual โดยใช้ kubectl apply กับ manifests ที่ได้จาก official charts
kubectl apply -f https://charts.external-secrets.io/latest/crds.yaml
kubectl apply -f https://charts.external-secrets.io/latest/rbac.yaml
kubectl apply -f https://charts.external-secrets.io/latest/chart.yaml
ข้อควรระวัง: วิธีนี้ต้องจัดการ dependencies และ CRDs ด้วยตนเอง ไม่แนะนำสำหรับผู้เริ่มต้น
Method 3: Bitnami Helm Chart
ใช้ Helm chart จาก Bitnami (Third-party but maintained)
helm repo add bitnami https://charts.bitnami.com/bitnami
helm install external-secrets \
bitnami/external-secrets \
-n external-secrets \
--create-namespace
Method 4: OpenShift (Red Hat Official Support)
Red Hat ให้การสนับสนุนอย่างเป็นทางการสำหรับ External Secrets Operator ตั้งแต่พฤศจิกายน 2025
# ติดตั้งจาก OperatorHub (Nov 2025 official support)
# 1. เข้า OpenShift Web Console
# 2. Navigate to Operators > OperatorHub
# 3. Search for "External Secrets"
# 4. clic Install External Secrets Operator
# 5. Select Namespace and clic Install
# หรือใช้ CLI
kubectl create namespace external-secrets
kubectl apply -f https://operatorhub.io/install/external-secrets.yaml
ข้อดีของ OpenShift: รองรับโดย Red Hat รวมถึงการอัปเดตความปลอดภัยและการสนับสนุนทางเทคนิคจาก Red Hat
ตรวจสอบว่าติดตั้งสำเร็จ
# ตรวจสอบว่า pods กำลังทำงาน
kubectl get pods -n external-secrets
# ควรเห็น output แบบนี้:
# NAME READY STATUS RESTARTS AGE
# external-secrets-XXXXX-YYYYY 1/1 Running 0 2m
# external-secrets-webhook-XXXXX-ZZZZZ 1/1 Running 0 2m
# ตรวจสอบ CRDs
kubectl get crds | grep externalsecrets
# ควรเห็น:
# externalsecrets.external-secrets.io
# secretstores.external-secrets.io
# clustersecretstores.external-secrets.io
6. การตั้งค่า SecretStore (4 ตัวอย่าง)
SecretStore เป็น CRD ที่ใช้กำหนดค่าการเชื่อมต่อกับ external secret manager ต่างๆ การสร้าง SecretStore จะต้องมีข้อมูล authentication และ connection details ที่ถูกต้อง
คำแนะนำ: ควรใช้ ClusterSecretStore สำหรับ secrets ที่ใช้ร่วมกันทั้ง cluster และ SecretStore สำหรับ secrets ที่เฉพาะ namespace
ตัวอย่างที่ 1: HashiCorp Vault
การตั้งค่า SecretStore สำหรับเชื่อมต่อกับ HashiCorp Vault
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: vault-secretstore
namespace: default
spec:
provider:
vault:
server: "https://vault.example.com:8200"
path: "secret/data/"
version: "v2"
auth:
tokenSecretRef:
name: vault-token
key: token
apiVersion: v1
kind: Secret
metadata:
name: vault-token
namespace: default
type: Opaque
stringData:
token: "hvs.CAESIGx4VQm7fGk1234567890abcdef" # จริง ๆ ควรใช้ secrets ภายนอกหรือ Vault self-hosted
หมายเหตุ: สำหรับ Vault ที่มี vault token จริง ควรใช้ Kubernetes authentication method แทนการใส่ token โดยตรง หรือใช้ AWS IAM authentication หากอยู่บน AWS
ตัวอย่างที่ 2: AWS Secrets Manager
การตั้งค่า SecretStore สำหรับ AWS Secrets Manager บน EKS
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: aws-secretstore
namespace: default
spec:
provider:
aws:
service: SecretsManager
region: ap-southeast-1
auth:
jwt:
serviceAccountRef:
name: eks-service-account
namespace: default
apiVersion: v1
kind: ServiceAccount
metadata:
name: eks-service-account
namespace: default
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/eks-external-secrets-role
IRSA (IAM Roles for Service Accounts): ใช้ OIDC provider เพื่อให้ service account สามารถเข้าถึง AWS resources ได้โดยไม่ต้องจัดการ credentials
ตัวอย่างที่ 3: Azure Key Vault
การตั้งค่า SecretStore สำหรับ Azure Key Vault
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: azure-secretstore
namespace: default
spec:
provider:
azurekv:
tenantId: "<TENANT_ID>"
VaultName: "<VAULT_NAME>"
cloud: "AZUREPUBLICCLOUD"
authType: "MSI"
identityId: "<USER_ASSIGNED_IDENTITY_ID>"
MSI (Managed Service Identity): Azure รองรับ MSI ทำให้ไม่ต้องจัดการ credentials ภายนอกสำหรับการเข้าถึง Azure Key Vault
ตัวอย่างที่ 4: Google Cloud Secret Manager
การตั้งค่า SecretStore สำหรับ Google Cloud Secret Manager
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: gcp-secretstore
namespace: default
spec:
provider:
gcp:
authType: "WorkloadIdentity"
project: "my-gcp-project"
serviceAccount:
name: gcp-service-account
Workload Identity: GKE Workload Identity ช่วยให้ Kubernetes service accounts สามารถใช้ GCP service accounts ได้โดยตรง โดยไม่ต้องจัดการ JSON key files
ผู้ให้บริการ secrets ที่รองรับทั้งหมด
7. การใช้งาน ExternalSecret
ExternalSecret เป็น CRD ที่ใช้กำหนดว่า secrets ใดจะถูกดึงจาก external secret manager และจะถูกสร้างเป็น Kubernetes Secret อย่างไร
เวลาการ refresh: ค่า refreshInterval กำหนดว่า ExternalSecret จะตรวจสอบการเปลี่ยนแปลงของ secrets ทุกๆ ช่วงเวลาเท่าไร (ค่า default: 15m)
ตัวอย่างพื้นฐาน: Sync single secret
ดึง username และ password จาก Vault และสร้างเป็น Kubernetes Secret
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: db-credentials
namespace: default
spec:
refreshInterval: "1h"
secretStoreRef:
name: vault-secretstore
kind: SecretStore
target:
name: db-credentials
creationPolicy: Owner
template:
type: Opaque
data:
db-password: "{{ .password | toString }}"
data:
- secretKey: username
remoteRef:
key: database
property: username
- secretKey: password
remoteRef:
key: database
property: password
creationPolicy:
Owner = สร้าง secret นี้ ถ้ามี secret อยู่แล้วจะไม่ override
ขั้นสูง: Sync multiple secrets with template
ดึงข้อมูล secrets หลายตัวพร้อมสร้าง connection string โดยใช้ template
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: full-stack-secrets
namespace: default
spec:
refreshInterval: "30m"
secretStoreRef:
name: vault-secretstore
kind: SecretStore
target:
name: full-stack-secrets
creationPolicy: Owner
template:
type: Opaque
data:
connection-string: |
mysql://{{ .username }}:{{ .password }}@db:3306/{{ .database }}
app-config: |
{
"database_host": "db",
"database_port": 3306,
"database_name": "{{ .database }}"
}
dataFrom:
- key: production/app
dataFrom vs data:
dataFrom = ดึง secrets ทั้งหมดจาก key ที่ระบุ
data = ดึง secrets ที่ระบุแต่ละตัว
ตัวอย่างพิเศษ: Multiple backends (Multi-cloud)
ใช้ secrets จากทั้ง Vault และ AWS Secrets Manager เข้ากันได้
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: multi-backend-secrets
namespace: default
spec:
refreshInterval: "1h"
target:
name: multi-backend-secrets
creationPolicy: Owner
data:
# From Vault
- secretKey: api_key
remoteRef:
key: vault/api
property: key
secretStoreRef:
name: vault-secretstore
kind: SecretStore
# From AWS
- secretKey: db_password
remoteRef:
key: aws/db-credentials
secretStoreRef:
name: aws-secretstore
kind: SecretStore
การใช้งาน Secrets ใน Pods
once ExternalSecret synced successfully, คุณสามารถใช้ secrets ใน deployment โดยอ้างอิงชื่อของ Kubernetes Secret ที่ ESO สร้างให้
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: my-app:latest
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-credentials
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
secret:
secretName: full-stack-secrets
8. Use Cases ในประเทศไทย
จากการใช้งานจริงในองค์กรไทยหลายแห่ง External Secrets Operator ได้ช่วยแก้ไขปัญหาการจัดการ secrets อย่างมีประสิทธิภาพ สู่นี้คือตัวอย่างจริงจากบริษัทไทย
กรณีศึกษาที่ 1: บริษัทฟินเทคไทย
ปัญหา:
- ต้องหมุนเวียน secrets ด้วยมือทุกสัปดาห์
- ใช้เวลาประมาณ 4 ชั่วโมง/สัปดาห์
- เกิดข้อผิดพลาดบ่อยครั้งจากการพิมพ์ผิด
- ขาด audit logs ที่ชัดเจน
วิธีแก้:
- ใช้ ESO ร่วมกับ HashiCorp Vault
- ตั้งค่า auto-rotation ทุก 90 วัน
- ใช้ Vault dynamic secrets สำหรับ database
- เปิด audit logging ไปยัง SIEM
ผลลัพธ์:
บริษัทฟินเทคขนาดกลางในกรุงเทพฯ - 2025
กรณีศึกษาที่ 2: platform อีคอมเมิร์ซไทย
ปัญหา:
- Secrets หลุดออกสู่ public GitHub repository
- เกิด security incident จาก git history
- ไม่มีระบบการจัดการ secrets ที่เป็นเอกภาพ
- ไม่ผ่าน compliance audit
วิธีแก้:
- ย้ายไปใช้ ESO ร่วมกับ Vault backend
- ใช้ GitOps workflow (Argo CD)
- ตั้ง GitHub secret scanning
- ไม่มี secrets ใน code repository
ผลลัพธ์:
อีคอมเมิร์ซ platform รายใหญ่ในประเทศไทย - 2025
กรณีศึกษาที่ 3: ธนาคารไทย
ปัญหา:
- ใช้ทั้ง AWS และ Azure (multi-cloud)
- มี secrets กระจายอยู่หลายที่
- ไม่มี.visibility เดียวในการดู secrets
- ทีม IT แยกกันจัดการ secrets
วิธีแก้:
- ใช้ ESO รองรับทั้ง AWS และ Azure
- ตั้ง Centralized secret management
- สร้าง policy สำหรับแต่ละ team
- ใช้ Vault namespaces แยก env
ผลลัพธ์:
ธนาคารชั้นนำของไทย - 2025
สรุปผลลัพธ์จาก Use Cases
| Metric | Before ESO | After ESO | Improvement |
|---|---|---|---|
| Manual work/week | 4+ hours | 0 hours | 100% reduction |
| Secrets in Git | 10-50 secrets | 0 secrets | 100% reduction |
| Security audit | Failed | Passed | 100% improvement |
| Ops efficiency | Baseline | +70% | +70% improvement |
9. Integration กับ GitOps Workflows
External Secrets Operator ถูกออกแบบมาให้ทำงานร่วมกับ GitOps ได้อย่างดีเยี่ยม ซึ่งทำให้การจัดการ secrets เป็นไปอย่างอัตโนมัติและปลอดภัย ไม่ต้องมีการเข้าถึง cluster โดยตรง
คุณสมบัติสำคัญ: when secrets ถูกอัปเดตใน external secret manager, ESO จะ sync มาที่ Kubernetes Secret โดยอัตโนมัติและ GitOps tools จะ deploy ไปยัง pods โดยอัตโนมัติ
Argo CD Integration
การตั้งค่า ESO ด้วย Argo CD
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: external-secrets
namespace: argocd
spec:
project: default
source:
repoURL: https://charts.external-secrets.io
chart: external-secrets
targetRevision: 0.9.0
helm:
releaseName: external-secrets
parameters:
- name: installCRDs
value: "true"
destination:
server: https://kubernetes.default.svc
namespace: external-secrets
revisionHistoryLimit: 5
syncPolicy:
automated:
prune: true
selfHeal: true
Argo CD sync workflow: เมื่อ ExternalSecret YAML อัปโหลดไปยัง Git repository Argo CD จะ detect และ sync ไปยัง cluster ทันที
Flux Integration
การตั้งค่า ESO ด้วย Flux CD
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
name: external-secrets
namespace: flux-system
spec:
interval: 10m
path: ./manifests/external-secrets
prune: true
sourceRef:
kind: GitRepository
name: infrastructure
patches:
- patch: |
apiVersion: apps/v1
kind: Deployment
metadata:
name: external-secrets
spec:
template:
spec:
containers:
- name: controller
env:
- name: LOG_LEVEL
value: debug
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
name: infrastructure
namespace: flux-system
spec:
interval: 1m0s
url: https://github.com/your-org/infrastructure
ref:
branch: main
GitOps Flow หลังการติดตั้ง ESO
10. Security Best Practices
ความปลอดภัยคือสิ่งสำคัญที่สุดในการจัดการ secrets การใช้ External Secrets Operator ไม่ได้แปลว่าคุณปลอดภัยทันที คุณต้องปฏิบัติตาม best practices เพื่อให้ปลอดภัยสูงสุด
ความเข้าใจผิดที่พบบ่อย:
"การใช้ External Secrets Operator = ปลอดภัยทันที" - จริงๆ แล้ว การตั้งค่าการเชื่อมต่อกับ secrets manager และการอนุญาตการเข้าถึงเป็นสิ่งสำคัญที่ต้องดูแลเป็นพิเศษ!
1. หลักการ Least Privilege
ให้สิทธิ์เพียงเท่าที่จำเป็นที่สุด
# ไม่ดี - มีสิทธิ์เกินจำเป็น
path "secret/data/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
# ดี - มีสิทธิ์เฉพาะตามความจำเป็น
path "secret/data/app/database" {
capabilities = ["read"]
}
path "secret/data/app/api" {
capabilities = ["read"]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue"
],
"Resource": [
"arn:aws:secretsmanager:*:123456789012:secret:app/*"
]
}
]
}
2. Secret Rotation
หมุนเวียน secrets อย่างสม่ำเสมอและอัตโนมัติ
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: rotating-db-credentials
namespace: default
spec:
refreshInterval: "12h" # ตรวจสอบทุก 12 ชั่วโมง
secretStoreRef:
name: vault-secretstore
kind: SecretStore
target:
name: db-credentials-rotating
creationPolicy: Owner
data:
- secretKey: username
remoteRef:
key: dynamic/db-creds
property: username
- secretKey: password
remoteRef:
key: dynamic/db-creds
property: password
Dynamic Secrets (Vault): สำหรับ database credentials, Vault สามารถ generate credentials ใหม่อัตโนมัติทุก X ชั่วโมง และ ESO จะ refresh secret ทุกๆ 12 ชั่วโมง (ต้องตั้งค่าให้ refreshInterval < leaseDuration)
3. Network Security
ป้องกัน secrets ใน transit และ at rest
- ใช้ private network: เชื่อมต่อไปยัง Vault/AWS ผ่าน private network หรือ VPC endpoint ไม่ใช่ public internet
- Enable mTLS: เปิด mTLS (mutual TLS) สำหรับ communication ระหว่าง ESO และ Vault
- Use TLS certificates: ใช้ TLS certificates ที่น่าเชื่อถือได้สำหรับ all external connections
- Network policies: ใช้ Kubernetes Network Policies เพื่อจำกัดการเข้าถึง secrets endpoints
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-eso-to-vault
namespace: external-secrets
spec:
podSelector:
matchLabels:
app: external-secrets
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/8 # Private network only!
ports:
- protocol: TCP
port: 8200
- protocol: TCP
port: 443
4. Audit Logging
ติดตามการเข้าถึง secrets ทั้งหมด
# Terraform example untuk enable vault audit
resource "vault_audit" "file" {
type = "file"
description = "Audit logs"
options = {
file_path = "/vault/audit/logs"
}
}
resource "vault_audit" "syslog" {
type = "syslog"
description = "Syslog audit"
options = {
address = "syslog.example.com:514"
facility = "LOCAL0"
format = "default"
}
}
Integration ไปยัง SIEM: ควรส่ง audit logs ไปยัง SIEM (เช่น Splunk, ELK, Datadog, หรือ Sumo Logic) เพื่อการ alert และ analysis แบบ real-time
Security Checklist
11. Troubleshooting & Common Issues
แม้ External Secrets Operator จะมีความเสถียร แต่การตั้งค่าที่ไม่ถูกต้องอาจทำให้เกิดปัญหา ตารางด้านล่างคือ common problems และวิธีแก้ไข
คำแนะนำ: เริ่มจาก logs ของ controller ก่อนเสมอ - มักจะบ่งบอกถึงปัญหาหลักได้ชัดเจน
ปัญหา 1: Secrets ไม่ถูก sync
# ตรวจสอบ ExternalSecret status
kubectl get externalsecrets
kubectl describe externalsecret db-credentials
# ตรวจสอบ controller logs
kubectl logs -n external-secrets \
-l app.kubernetes.io/name=external-secrets \
-c controller \
--tail=100
สาเหตุที่พบบ่อย:
- SecretStore ตั้งค่าไม่ถูกต้อง
- authentication credentials ไม่ถูกต้อง
- Network connectivity ไปยัง secrets manager ไม่ถูกต้อง
- ExternalSecret ชี้ไปที่ secrets ที่ไม่มีใน external manager
# แก้ไข SecretStore
kubectl edit secretstore vault-secretstore -n default
# ตรวจสอบ vault token หรือ credentials
kubectl get secret vault-token -n default -o yaml
ปัญหา 2: Authentication errors
- Vault authentication: ตรวจสอบ vault token, client certificate, หรือ RBAC policies
- AWS authentication: ตรวจสอบ AWS IAM role, IRSA annotation, และ permissions
- Azure authentication: ตรวจสอบ Managed Identity หรือ service principal
- GCP authentication: ตรวจสอบ Workload Identity และ service account
# Test Vault connection จากภายใน cluster
kubectl run -it --rm test-vault \
--image=vault:latest \
--env "VAULT_ADDR=https://vault.example.com:8200" \
--env "VAULT_TOKEN=hvs.CAES..." \
-- bash
# ใน container:
vault status
vault read secret/data/database
vault token lookup
ปัญหา 3: Permission denied
symptom:
level=error msg="permission denied" ใน logs
# สร้าง ClusterRole ที่มีสิทธิ์ครบ
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: external-secrets-controller
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["external-secrets.io"]
resources: ["externalsecrets", "secretstores", "clustersecretstores"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["admissionregistration.k8s.io"]
resources: ["mutatingwebhookconfigurations", "validatingwebhookconfigurations"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# Bind ClusterRole ให้กับ service account
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: external-secrets-controller-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: external-secrets-controller
subjects:
- kind: ServiceAccount
name: external-secrets-controller
namespace: external-secrets
Troubleshooting Checklist
1. Logs
- Controller logs
- Webhook logs
- Audit logs
2. CR Status
kubectl get externalsecretskubectl describe externalsecretkubectl get secretstores
3. Network
- Test connectivity
- Check firewall rules
- Verify DNS
# Run this quick diagnostic script
#!/bin/bash
echo "=== Checking External Secrets ==="
kubectl get externalsecrets --all-namespaces
echo -e "\n=== Checking SecretStores ==="
kubectl get secretstores --all-namespaces
echo -e "\n=== Controller Logs (last 50 lines) ==="
kubectl logs -n external-secrets \
-l app.kubernetes.io/name=external-secrets \
-c controller \
--tail=50 | grep -E "(error|failed|sync|secret)"
echo -e "\n=== Node Events (last 10) ==="
kubectl get events -n external-secrets --sort-by='.lastTimestamp' | tail -10