Security
น้องๆ เคยสงสัยไหมว่า Container, Docker, Kubernetes มันคืออะไร แล้วทำไมเราต้องมานั่งปวดหัวกับเรื่อง Security ของมันด้วย? สมัยผมทำร้านเน็ต SiamCafe.net ยุคแรกๆ อะไรๆ มันง่ายกว่านี้เยอะ แค่ลงโปรแกรมบน Server จบ! แต่พอโลกมันเปลี่ยนไป ทุกอย่างมันซับซ้อนขึ้น Container เลยเข้ามามีบทบาทสำคัญ
Container มันเหมือนกล่องๆ นึง ที่บรรจุทุกอย่างที่โปรแกรมเราต้องการไว้ข้างใน ไม่ว่าจะเป็นโค้ด, libraries, dependencies ทุกอย่างอยู่ในกล่องนั้นหมด ทำให้โปรแกรมเราสามารถรันได้ทุกที่ ไม่ว่าจะเป็นเครื่องเรา, Server บน Cloud หรือแม้แต่บน Raspberry Pi
Docker ก็คือเครื่องมือที่ช่วยให้เราสร้าง, จัดการ และรัน Container ได้ง่ายขึ้น ส่วน Kubernetes (K8s) เนี่ย มันคือ Orchestration Tool ที่ช่วยเราจัดการ Container จำนวนมากๆ ได้อย่างมีประสิทธิภาพ ลองนึกภาพว่า Docker คือเครื่องทำกาแฟ ส่วน Kubernetes คือร้านกาแฟที่บริหารจัดการเครื่องทำกาแฟหลายๆ เครื่อง
แล้วทำไม Security ถึงสำคัญ? เพราะถ้า Container ของเราโดน Hack มันก็เหมือนบ้านเราโดนขโมยขึ้นบ้าน ข้อมูลรั่วไหล ระบบล่ม ลูกค้าหนีหายหมด! คิดดูสิ สมัยผมทำร้านเน็ต ถ้าโดน Hack นี่เจ๊งเลยนะ! ดังนั้นการดูแล Security ของ Container จึงเป็นเรื่องที่มองข้ามไม่ได้เลย
Container ก็เหมือน Virtual Machine (VM) แต่เบากว่าเยอะ VM ต้องจำลอง Hardware ทั้งหมด แต่ Container แชร์ Kernel ของ Host OS ทำให้ใช้ทรัพยากรน้อยกว่า เริ่มต้นได้เร็วกว่า และจัดการได้ง่ายกว่า
ลองนึกภาพ VM เป็นบ้านทั้งหลัง ส่วน Container เป็นห้องเช่าในคอนโด ห้องเช่าใช้ทรัพยากรน้อยกว่า และย้ายเข้าออกง่ายกว่าเยอะ
Docker คือ Platform ที่ช่วยให้เราสร้าง, จัดการ และรัน Container ได้อย่างง่ายดาย Docker มี Dockerfile ที่ใช้กำหนดค่า Container, Docker Image ที่เป็น Template ของ Container และ Docker Hub ที่เป็น Repository สำหรับเก็บ Docker Image
Dockerfile เหมือนสูตรอาหาร, Docker Image เหมือนขนมที่อบเสร็จแล้ว และ Docker Hub เหมือนร้านขายขนมที่เราสามารถไปซื้อขนมสำเร็จรูปมาใช้ได้เลย
Kubernetes คือ Container Orchestration Tool ที่ช่วยเราจัดการ Container จำนวนมากๆ Kubernetes ช่วยเรา Deploy, Scale, Update และ Monitor Container ได้อย่างมีประสิทธิภาพ
Kubernetes เหมือนผู้จัดการร้านกาแฟที่คอยดูแลเครื่องทำกาแฟทุกเครื่องให้ทำงานได้อย่างราบรื่น
เอาล่ะ ทีนี้มาดูวิธีใช้งาน Docker และ Kubernetes กันบ้าง เริ่มจาก Docker ก่อนเลย
Dockerfile คือไฟล์ที่ใช้กำหนดค่า Container ของเรา ตัวอย่าง Dockerfile สำหรับ Web Server ง่ายๆ:
FROM ubuntu:latest
RUN apt-get update && apt-get install -y nginx
COPY index.html /var/www/html/
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
บรรทัดแรก FROM ubuntu:latest บอกว่าเราจะใช้ Ubuntu Version ล่าสุดเป็น Base Image
บรรทัดที่สอง RUN apt-get update && apt-get install -y nginx อัพเดท Package และติดตั้ง Nginx
บรรทัดที่สาม COPY index.html /var/www/html/ Copy ไฟล์ index.html ไปไว้ใน Folder /var/www/html/
บรรทัดที่สี่ EXPOSE 80 บอกว่า Container จะเปิด Port 80
บรรทัดสุดท้าย CMD ["nginx", "-g", "daemon off;"] สั่งให้รัน Nginx
หลังจากสร้าง Dockerfile แล้ว เราก็ต้อง Build Docker Image จาก Dockerfile นั้น โดยใช้คำสั่ง:
docker build -t my-web-server .
docker build คือคำสั่ง Build Docker Image
-t my-web-server คือ Tag Image ว่า my-web-server
. คือ Path ของ Dockerfile (ในที่นี้คือ Folder ปัจจุบัน)
หลังจาก Build Docker Image แล้ว เราก็สามารถ Run Docker Container จาก Image นั้นได้ โดยใช้คำสั่ง:
docker run -d -p 80:80 my-web-server
docker run คือคำสั่ง Run Docker Container
-d คือ Run Container ใน Background
-p 80:80 คือ Map Port 80 ของ Host ไปยัง Port 80 ของ Container
my-web-server คือ Image ที่เราต้องการ Run
สำหรับ Kubernetes จะซับซ้อนกว่า Docker นิดหน่อย แต่ก็ไม่ได้ยากเกินไป
Deployment คือ Object ใน Kubernetes ที่ใช้จัดการ Container ของเรา ตัวอย่าง Deployment สำหรับ Web Server:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-web-server
spec:
replicas: 3
selector:
matchLabels:
app: web-server
template:
metadata:
labels:
app: web-server
spec:
containers:
- name: web-server
image: my-web-server
ports:
- containerPort: 80
apiVersion: apps/v1 คือ API Version ของ Deployment
kind: Deployment คือ Type ของ Object
metadata: name: my-web-server คือชื่อของ Deployment
spec: replicas: 3 คือจำนวน Container ที่เราต้องการ Run (ในที่นี้คือ 3)
spec: selector: matchLabels: app: web-server คือ Selector ที่ใช้ Match Label ของ Pod
spec: template: metadata: labels: app: web-server คือ Label ที่ใช้ระบุ Pod
spec: template: spec: containers: - name: web-server คือชื่อของ Container
spec: template: spec: containers: - image: my-web-server คือ Image ที่เราต้องการ Run
spec: template: spec: containers: - ports: - containerPort: 80 คือ Port ที่ Container จะเปิด
Service คือ Object ใน Kubernetes ที่ใช้ expose Application ของเราไปยังภายนอก ตัวอย่าง Service สำหรับ Web Server:
apiVersion: v1
kind: Service
metadata:
name: my-web-server
spec:
selector:
app: web-server
ports:
- port: 80
targetPort: 80
type: LoadBalancer
apiVersion: v1 คือ API Version ของ Service
kind: Service คือ Type ของ Object
metadata: name: my-web-server คือชื่อของ Service
spec: selector: app: web-server คือ Selector ที่ใช้ Match Label ของ Pod
spec: ports: - port: 80 คือ Port ที่ Service จะเปิด
spec: ports: - targetPort: 80 คือ Port ที่ Container จะรับ
spec: type: LoadBalancer คือ Type ของ Service (ในที่นี้คือ Load Balancer)
หลังจากสร้าง Deployment และ Service แล้ว เราก็สามารถ Deploy Application ของเราไปยัง Kubernetes Cluster ได้ โดยใช้คำสั่ง:
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl apply คือคำสั่ง Apply Configuration จากไฟล์
-f deployment.yaml คือไฟล์ Deployment
-f service.yaml คือไฟล์ Service
หลังจาก Deploy แล้ว เราสามารถเข้าถึง Web Server ของเราได้ผ่าน Load Balancer ที่ Kubernetes สร้างให้
Container ไม่ใช่ทางเลือกเดียวในการ Deploy Application ยังมี Virtual Machine (VM) และ Bare Metal Server ให้เลือกใช้ แต่ Container มีข้อดีหลายอย่างที่ VM และ Bare Metal Server ไม่มี
VM ใช้ทรัพยากรมากกว่า Container เพราะต้องจำลอง Hardware ทั้งหมด Container แชร์ Kernel ของ Host OS ทำให้ใช้ทรัพยากรน้อยกว่า เริ่มต้นได้เร็วกว่า และจัดการได้ง่ายกว่า
Bare Metal Server ให้ประสิทธิภาพที่ดีที่สุด แต่จัดการยากกว่า และใช้ทรัพยากรไม่คุ้มค่า Container ช่วยให้เราใช้ทรัพยากรของ Server ได้อย่างมีประสิทธิภาพมากขึ้น
| Feature | Container | Virtual Machine (VM) | Bare Metal Server |
|---|---|---|---|
| Resource Usage | Low | High | Highest (but inefficient) |
| Startup Time | Fast | Slow | Slow |
| Portability | Excellent | Good | Poor |
| Management | Easy | Medium | Difficult |
| Security | Requires careful configuration | Good (but still vulnerable) | Good (but requires more manual effort) |
สรุปแล้ว Container เป็นทางเลือกที่ดีที่สุดสำหรับ Application ที่ต้องการความยืดหยุ่น, ประสิทธิภาพ และความสะดวกในการจัดการ แต่ก็ต้องระวังเรื่อง Security ด้วยนะน้องๆ SiamCafe Blog มีบทความดีๆ เกี่ยวกับ Security อีกเยอะเลย ลองเข้าไปอ่านกันดูนะ
อย่าลืมว่า Security มันไม่มีสูตรสำเร็จตายตัว ต้องเรียนรู้และปรับปรุงกันไปเรื่อยๆ เหมือนสมัยผมทำร้านเน็ต ก็ต้องคอยตามเทคโนโลยีใหม่ๆ ตลอดเวลา SiamCafe Blog เป็นแหล่งข้อมูลที่ดีที่หนึ่งเลย
ดูวิดีโอเพิ่มเติมเกี่ยวกับContainer Security Docker Kube:
สมัยผมทำร้านเน็ต SiamCafe เนี่ย เรื่องความปลอดภัยนี่สำคัญสุดๆ เพราะเครื่องลูกข่ายแต่ละตัวคือช่องโหว่ ถ้าโดนเจาะทีนึง งานเข้าทั้งร้าน! Container Security ก็เหมือนกัน มองว่าแต่ละ container คือเครื่องลูกข่ายเรา ต้องดูแลให้ดี
ผมว่าหลักการง่ายๆ คือ "ป้องกันไว้ก่อน ดีกว่าแก้" แล้วก็ "อย่าไว้ใจทาง อย่าฝากใจคน" อันนี้ใช้ได้ทั้งเรื่องความรัก และเรื่อง Security เลยนะน้อง
ก่อนจะเอา image อะไรมาใช้ ต้องเช็คก่อนว่าสะอาดจริงไหม สมัยก่อนผมลงโปรแกรมในร้าน ก็ต้องสแกนไวรัสก่อนเสมอ เดี๋ยวนี้มีเครื่องมือสแกน Container Image พวก Clair, Trivy เนี่ย ช่วยได้เยอะ
# ตัวอย่างการใช้ Trivy
trivy image your-image:tag
Trivy มันจะช่วยสแกนหาช่องโหว่ใน image เรา ถ้าเจอจะได้จัดการก่อนเอาไป run จริง
Image ยิ่งเล็ก ยิ่งดี! เพราะลด surface area ที่คนจะเข้ามาโจมตีได้ เหมือนบ้านเราอ่ะ ของน้อย โอกาสที่โจรจะเจอของมีค่าก็น้อยลง
ลองใช้ multi-stage build ใน Dockerfile ดูสิ มันจะช่วยให้เราตัดของที่ไม่จำเป็นทิ้งไปได้เยอะเลย
# Dockerfile Example
FROM ubuntu as builder
RUN apt-get update && apt-get install -y --no-install-recommends some-tools
FROM scratch
COPY --from=builder /app /app
อย่าให้ container มีสิทธิ์เยอะเกินความจำเป็น! เหมือนเราให้ลูกน้องถือเงินบริษัท ถ้าให้เยอะเกินไป ก็มีโอกาสโดนโกงได้ง่ายๆ
Run container ด้วย user ที่ไม่ใช่ root ใช้ Read-Only Filesystem ถ้าทำได้ จะช่วยลดความเสี่ยงไปได้เยอะเลย
Container คุยกันได้หมด ไม่ดีแน่! ต้องจำกัดการเข้าถึง network ให้ container แต่ละตัวคุยกันเฉพาะที่จำเป็นเท่านั้น เหมือนเราแบ่งโซนในบ้าน ใครอยู่โซนไหน ก็เข้าได้แค่โซนนั้น
Kubernetes Network Policies ช่วยเราได้เยอะ ในการกำหนด rule ว่า container ไหนคุยกับ container ไหนได้บ้าง
iCafeForexเพราะ container มันไม่ใช่กล่องวิเศษที่ปลอดภัยด้วยตัวมันเอง! มันก็แค่ process ที่ run อยู่บน host OS ถ้า host OS โดนเจาะ Container ก็ไม่รอด
ไม่เสมอไป! ถึง Docker Hub จะมีระบบ scan แต่ก็ไม่ได้หมายความว่าทุก image จะปลอดภัย 100% ต้องเช็คเองด้วยเสมอ
Kubernetes มี feature หลายอย่างที่ช่วยเรื่อง Security ได้ เช่น Network Policies, RBAC (Role-Based Access Control), Pod Security Policies แต่เราต้อง configure ให้ถูกต้องด้วยนะ
อันดับแรก รีบ stop container นั้นทันที! แล้วค่อยมา investigate ว่าเกิดอะไรขึ้น พยายามหา root cause แล้วแก้ไข อย่าปล่อยให้เรื่องมันบานปลาย
SiamCafe BlogContainer Security ไม่ใช่เรื่องยาก แต่ก็ต้องใส่ใจรายละเอียด ต้องทำตั้งแต่ตอน build image ไปจนถึงตอน run container จริง อย่าประมาท! ไม่งั้นอาจจะเจอเรื่องไม่คาดฝันได้
จำไว้ว่า "Security is a journey, not a destination" ต้องพัฒนาปรับปรุงอยู่เสมอ ตาม threat landscape ที่เปลี่ยนแปลงไป