Skip to main content

9.1. Networking - Pods, Services and CoreDNS

Mục lục


1. Vấn đề thực tế: Tại sao Pod không kết nối được?

Một buổi sáng, dev team báo: "Frontend Pod không kết nối được tới Backend Pod." Ping thử từ frontend — không nhận reply. Kiểm tra IP của backend — đúng. Vậy tại sao?

Bài toán đặt ra: Làm sao để các Pod trong cluster giao tiếp được với nhau, với service bên ngoài, và với internet?

Câu hỏi cốt lõi cần trả lời:

  • Làm thế nào Linux routing và gateway hoạt động?
  • DNS resolution hoạt động ra sao trong container?
  • Network namespaces cách ly network như thế nào?
  • Docker networking model khác Kubernetes ra sao?
  • CNI đóng vai trò gì trong Kubernetes networking?

💡 Hình dung: Cluster networking giống hệ thống điện trong thành phố — mỗi căn hộ (Pod) cần dây điện riêng (IP), tổng đài điện (DNS) để tra cứu địa chỉ, và các trạm biến áp (gateway/router) để kết nối các khu vực. Container runtime đóng vai trò như "thợ điện" lắp đặt dây theo tiêu chuẩn (CNI).


2. Routing và Gateway trong Linux

2.1 Mạng cơ bản: Hai máy nói chuyện

Hai máy tính A và B nằm trong cùng mạng 192.168.1.0/24, kết nối qua một switch. Switch là "người điều phối" — nó học địa chỉ MAC của từng máy và chuyển frame đúng đích.

Mỗi máy cần một network interface (eth0, ens33...) để kết nối. Xem các interface trên host:

ip link

# Output:
# 1: lo: <LOOPBACK,UP> ...
# 2: eth0: <BROADCAST,MULTICAST,UP> ...

Gán địa chỉ IP cho interface:

ip addr add 192.168.1.10/24 dev eth0
ip addr add 192.168.1.11/24 dev eth0

Sau khi IP được gán, hai máy có thể giao tiếp qua switch — miễn chúng cùng subnet. Switch chỉ hoạt động trong một mạng, không biết gì về mạng khác.

2.2 Router và Gateway: Kết nối các thế giới

Một router có interface trên nhiều mạng khác nhau. Nếu máy C và D nằm ở mạng 192.168.2.0/24, router có thể kết nối hai mạng này — eth0 vào 192.168.1.0, eth1 vào 192.168.2.0.

Xem routing table hiện tại:

ip route

# Output (minh họa):
# default via 192.168.1.1 dev eth0
# 192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.10

Thêm route để reach mạng 192.168.2.0/24 qua gateway 192.168.1.1:

ip route add 192.168.2.0/24 via 192.168.1.1

# Output:
# (không có output = thành công)

2.3 Default Gateway: Đường đi mặc định

Thay vì thêm route cho từng mạng con, Linux hỗ trợ default route — "nếu không biết đi đâu, hỏi gateway này":

ip route add default via 192.168.1.1
# Hoặc viết đầy đủ hơn:
ip route add 0.0.0.0/0 via 192.168.1.1

💡 Hình dung: Default gateway giống "đường ra ngõ" — khi không biết địa chỉ cụ thể ở đâu, cứ ra ngõ rồi hỏi người quen. Default gateway nhận packet không khớp route nào và forward nó đi tiếp.

2.4 Linux host làm Router

Khi host B có hai interface kết nối hai mạng, cần thêm routing entries để packet có thể đi qua:

# Trên host A (mạng 192.168.1.0), muốn reach mạng 192.168.2.0
ip route add 192.168.2.0/24 via 192.168.1.6

# Trên host C (mạng 192.168.2.0), muốn reach mạng 192.168.1.0
ip route add 192.168.1.0/24 via 192.168.2.6

2.5 IP Forwarding: Bật tính năng Router

Mặc định Linux không forward packet từ interface này sang interface khác — tường lửa chặn vì lý do bảo mật. Kiểm tra trạng thái:

cat /proc/sys/net/ipv4/ip_forward

# Output:
# 0

Giá trị 0 = không cho phép forward. Bật lên:

echo 1 > /proc/sys/net/ipv4/ip_forward

# Kiểm tra lại:
cat /proc/sys/net/ipv4/ip_forward
# Output:
# 1

⚠️ Lưu ý: Thay đổi trên chỉ có hiệu lực đến khi reboot. Để lưu vĩnh viễn, sửa /etc/sysctl.conf:

net.ipv4.ip_forward = 1

2.6 Tổng hợp Commands

CommandMô tả
ip linkLiệt kê và chỉnh sửa interfaces trên host
ip addr hoặc ip addr showXem địa chỉ IP được gán cho interfaces
ip addr add <ip>/<prefix> dev <iface>Gán địa chỉ IP cho interface
ip route hoặc route -nXem routing table
ip route add <network> via <gateway>Thêm route vào routing table
ip route add default via <gateway>Thêm default route
Router kết nối hai mạng LANMạng 192.168.1.0/24Host A192.168.1.10SwitchRoutereth0: 192.168.1.1eth1: 192.168.2.1Mạng 192.168.2.0/24SwitchHost C192.168.2.10Routing Table trên Host A:# ip routedefault via 192.168.1.1 dev eth0192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.10192.168.2.0/24 via 192.168.1.1 dev eth0

3. DNS trong Linux

3.1 /etc/hosts: DNS thủ công

Thay vì nhớ IP, gán tên cho hệ thống bằng cách thêm vào /etc/hosts:

# Thêm vào /etc/hosts trên system A
192.168.1.11 db
192.168.1.12 api
192.168.1.13 cache

Giờ có thể ping db thay vì nhớ IP. Mọi thứ trong /etc/hosts là nguồn thông tin cục bộ — chỉ áp dụng cho máy đó.

3.2 DNS Server: Khi /etc/hosts không đủ

Khi môi trường có hàng trăm máy, quản lý file /etc/hosts trở nên bất khả thi. Giải pháp: DNS server tập trung.

Thêm DNS server vào /etc/resolv.conf:

# /etc/resolv.conf
nameserver 192.168.1.100
nameserver 8.8.8.8

Thứ tự tìm kiếm được định nghĩa trong /etc/nsswitch.conf:

cat /etc/nsswitch.conf | grep hosts

# Output:
# hosts: files dns

Host sẽ tìm trong /etc/hosts trước (files), sau đó mới hỏi DNS server (dns).

💡 Hình dung: /etc/nsswitch.conf giống "sổ địa chỉ ưu tiên" — tìm trong sổ riêng trước, không có mới hỏi tổng đài (DNS server).

3.3 DNS Server công cộng

Để resolve các trang web bên ngoài như www.google.com:

nameserver 8.8.8.8 # Google DNS
nameserver 1.1.1.1 # Cloudflare DNS

8.8.8.8 là DNS server công cộng của Google — miễn phí và đáng tin cậy.

3.4 Domain Names: Phân cấp tên miền

google.com
├── www.google.com (subdomain www)
├── mail.google.com (subdomain mail)
├── maps.google.com (subdomain maps)
  • Top-level domains (TLD): .com, .net, .edu, .org, .vn.
  • Domain name: google.com.
  • Subdomain: phần đứng trước domain (www, mail, api).

3.5 Search Domain: Viết tắt tên

Thêm search domain để ngắn gọn khi ping service trong cùng domain:

# Thêm vào /etc/resolv.conf
search mycompany.com

Giờ ping web sẽ tự động thử web.mycompany.com trước.

3.6 Các loại DNS Record

LoạiMô tảVí dụ
AÁnh xạ hostname → IPv4web A 192.168.1.10
AAAAÁnh xạ hostname → IPv6web AAAA 2001:db8::1
CNAMEÁnh xạ tên → tên khácwww CNAME web

3.7 Công cụ kiểm tra DNS

# Tra cứu DNS record
nslookup google.com

# Output (minh họa):
# Server: 8.8.8.8
# Address: 8.8.8.8#53
# Name: google.com
# Address: 142.250.191.78

# Tra cứu chi tiết hơn
dig google.com

# Output (minh họa):
# ;; ANSWER SECTION:
# google.com. 300 IN A 142.250.191.78

⚠️ Lưu ý: nslookup không xem xét entries trong /etc/hosts local — nó chỉ hỏi DNS server.


4. CoreDNS Server

4.1 CoreDNS là gì?

CoreDNS là DNS server được Kubernetes chọn làm giải pháp DNS mặc định từ phiên bản 1.13 (thay thế kube-dns cũ). Nó nhẹ, module hóa qua plugins, và dễ cấu hình.

Download và cài đặt:

curl -LO https://github.com/coredns/coredns/releases/download/v1.12.4/coredns_1.12.4_linux_amd64.tgz
tar -zxf coredns_1.12.4_linux_amd64.tgz

# Output (minh họa):
# ./
# ./coredns

Chạy executable để khởi động DNS server (mặc định lắng nghe trên port 53):

./coredns

# Output (minh họa):
# .:53
# CoreDNS-1.12.4
# linux/amd64, go1.21, ;

4.2 Corefile: Cấu hình CoreDNS

CoreDNS sử dụng file Corefile để cấu hình plugins. File nằm tại /etc/coredns/Corefile hoặc ./Corefile trong thư mục làm việc.

Ví dụ Corefile đơn giản:

cat > Corefile << 'EOF'
.:53 {
# Sử dụng /etc/hosts để resolve hostname local
hosts /etc/hosts {
reload 1m
fallthrough
}

# Forward các truy vấn không khớp đến upstream resolver
forward . /etc/resolv.conf {
max_concurrent 1000
}

# Cache kết quả trong 30 giây
cache 30

# Ghi log và errors
log
errors
}
EOF

Giải thích từng plugin:

  • hosts: Đọc /etc/hosts, trả lời các bản ghi A.
  • forward: Chuyển tiếp request không khớp đến upstream DNS (thường là /etc/resolv.conf).
  • cache: Cache kết quả để giảm latency và giảm tải upstream.
  • log/errors: Ghi log hoạt động.

💡 Hình dung: CoreDNS giống "lễ tân khách sạn" — nhận câu hỏi (DNS query), tra sổ (cache/local), nếu không biết thì hỏi tổng đài bên ngoài (forward), ghi lại ai hỏi gì (log).


5. Network Namespaces trong Linux

5.1 Khái niệm Network Namespaces

Network namespaces là công nghệ Linux cho phép cô lập network resources — interface, routing table, firewall rules — trong phạm vi namespace riêng.

Containers như Docker sử dụng network namespaces để mỗi container có network stack riêng, không thấy nhau.

💡 Hình dung: Nếu host là ngôi nhà chung, namespaces là các phòng trong nhà. Mỗi phòng có ổ cắm riêng, công tắc riêng — phòng này bật đèn không ảnh hưởng phòng khác. Docker giao mỗi container một "phòng" riêng.

5.2 Tạo và xem Namespaces

Tạo hai namespaces mới:

ip netns add red
ip netns add blue

# Output: (không có output = thành công)

Liệt kê tất cả namespaces:

ip netns

# Output:
# red
# blue

5.3 Xem Interfaces trong Namespace

Xem interfaces trên host (root namespace):

ip link

# Output (minh họa):
# 1: lo: <LOOPBACK> ...
# 2: eth0: <BROADCAST,MULTICAST> ...
# 3: docker0: <BROADCAST,MULTICAST> ...

Xem interfaces bên trong namespace red:

# Cách 1: Sử dụng ip netns exec
ip netns exec red ip link

# Cách 2: Sử dụng shorthand -n
ip -n red link

# Output (minh họa):
# 1: lo: <LOOPBACK> ...

5.4 Kết nối hai Namespaces bằng veth pair

Tạo virtual Ethernet cable (veth pair) — hai đầu dây ảo:

ip link add veth-red type veth peer name veth-blue

# Output: (không có output = thành công)

Gắn mỗi đầu vào namespace tương ứng:

ip link set veth-red netns red
ip link set veth-blue netns blue

# Output: (không có output = thành công)

Gán IP addresses cho mỗi đầu:

ip -n red addr add 192.168.15.1/24 dev veth-red
ip -n blue addr add 192.168.15.2/24 dev veth-blue

Bật interfaces lên:

ip -n red link set veth-red up
ip -n blue link set veth-blue up

Bây giờ hai namespaces ping được nhau:

ip netns exec red ping -c 2 192.168.15.2

# Output (minh họa):
# PING 192.168.15.2 (192.168.15.2) 56(84) bytes of data.
# 64 bytes from 192.168.15.2: icmp_seq=1 ttl=64 time=0.041 ms
# 64 bytes from 192.168.15.2: icmp_seq=2 ttl=64 time=0.027 ms

5.5 Bridge Network: Kết nối nhiều Namespaces

Khi cần nhiều namespaces giao tiếp với nhau, dùng Linux bridge — "switch ảo" trong Linux.

Tạo bridge mới:

ip link add v-net-0 type bridge
ip link set v-net-0 up

# Output: (không có output = thành công)

Gán IP cho bridge để host có thể reach namespaces:

ip addr add 192.168.15.5/24 dev v-net-0

Tạo cable kết nối namespace red đến bridge:

# Tạo veth pair
ip link add veth-red type veth peer name veth-red-br

# Gắn một đầu vào namespace red
ip link set veth-red netns red

# Gắn đầu kia vào bridge
ip link set veth-red-br master v-net-0
ip link set veth-red-br up

Lặp lại cho namespace blue (hoặc bất kỳ namespace nào khác).

5.6 NAT và IP Masquerading: Ra internet

Namespace muốn reach external network (internet), cần NAT (Network Address Translation).

Bật IP forwarding trên host:

echo 1 > /proc/sys/net/ipv4/ip_forward

Thêm NAT rule để masquerade traffic (thay địa chỉ private thành public của host):

iptables -t nat -A POSTROUTING -s 192.168.15.0/24 -j MASQUERADE

# Output (minh họa):
# (không có output = thành công)

💡 Hình dung: Masquerade giống "điểm đặt vé" ở cổng ra — tất cả packet từ trong khu (namespace) đều được "đóng dấu" là của khu, không ai biết ai ở phòng nào bên trong.

5.7 Port Forwarding: Từ host vào namespace

Chuyển tiếp traffic từ port bên ngoài vào namespace:

# Traffic đến port 8080 trên host → chuyển đến port 80 trong namespace blue
iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 192.168.15.2:80

5.8 Troubleshooting Namespaces

Vấn đề: Không thể ping một namespace từ namespace khác.

Kiểm tra:

  1. Đã gán đúng IP với netmask /24 chưa?
  2. Firewall/IP Tables có block không?
# Kiểm tra netmask khi gán IP
ip -n red addr add 192.168.1.10/24 dev veth-red

# Tắt tạm thời iptables (chỉ trong môi trường học)
iptables -F
Network Namespaces kết nối qua BridgeNamespace: redloveth-red192.168.15.1/24Bridge: v-net-0192.168.15.5192.168.15.0/24veth-red-brNamespace: blueloveth-blue192.168.15.2/24veth-blue-brHost (root ns)eth0, docker0manageiptables NAT: masquerade 192.168.15.0/24 → internetping 192.168.15.2 từ red → OK (cùng subnet qua bridge)

6. Docker Networking

6.1 Ba chế độ Network trong Docker

Docker cung cấp ba network driver chính:

None Network

Container không gắn vào bất kỳ network nào. Container không thể reach outside world và không ai từ bên ngoài có thể reach container.

docker run --network none nginx

# Trong container:
# ip addr
# Output (minh họa):
# 1: lo: <LOOPBACK> ...
# (không có interface mạng)

Host Network

Container gắn trực tiếp vào network của host. Không có network isolation — nếu ứng dụng lắng nghe port 80, nó sẽ trên port 80 của host (có thể conflict).

docker run --network host nginx

# Ứng dụng trong container truy cập được:
# - localhost:80 (chính nó)
# - mạng LAN của host
# - không cần port mapping

Bridge Network (mặc định)

Docker tạo internal private network. Docker host và containers có địa chỉ trên mạng này.

6.2 Bridge Network: Chi tiết

Xem các Docker networks:

docker network ls

# Output:
# NETWORK ID NAME DRIVER SCOPE
# abc123... bridge bridge local
# def456... host host local
# ghi789... none null local

Kiểm tra bridge interface trên host:

ip link

# Thấy docker0 interface
# 4: docker0: <BROADCAST,MULTICAST,UP> ...

Xem địa chỉ IP của bridge:

ip addr show docker0

# Output (minh họa):
# 4: docker0: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state UP
# inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0

Docker bridge mặc định sử dụng dải 172.17.0.0/16.

6.3 Container Network Namespace

Mỗi khi container được tạo, Docker tạo network namespace riêng cho nó. Xem namespace của container:

docker inspect <container_id> --format '{{.NetworkSettings.SandboxKey}}'

# Output (minh họa):
# /var/run/docker/netns/a1b2c3d4e5f6

6.4 Virtual Cable (veth pair) trong Docker

Docker tạo veth pair khi container join bridge network:

  • Một đầu gắn vào container namespace.
  • Một đầu gắn vào bridge docker0.

Xem trên Docker host:

ip link

# Output (minh họa):
# veth123456@if3: <BROADCAST,MULTICAST,UP> ...

Xem trong container namespace:

docker exec <container_id> ip link

# Output (minh họa):
# 1: lo: <LOOPBACK> ...
# 3: eth0@if4: <BROADCAST,MULTICAST,UP> ...

6.5 Port Mapping

Để external users access ứng dụng trên container:

docker run -p 8080:80 nginx

Traffic đến port 8080 trên Docker host sẽ được forward đến port 80 trên container.

# Kiểm tra port mapping
docker port <container_id>

# Output (minh họa):
# 80/tcp -> 0.0.0.0:8080

6.6 Docker và iptables

Docker tự động thêm rules vào iptables NAT table để thực hiện port forwarding và masquerading:

iptables -t nat -L -n

# Output (minh họa - một phần):
# Chain POSTROUTING (1 references)
# target prot opt source destination
# MASQUERADE all -- 172.17.0.0/16 !172.17.0.0/16
# MASQUERADE tcp -- 172.17.0.2 172.17.0.2 tcp dpt:80

7. Container Network Interface (CNI)

7.1 Vấn đề: Mỗi runtime giải quyết networking khác nhau

Container runtimes khác nhau (rkt, Mesos Containerizer, Docker, Kubernetes) đều giải quyết networking challenges theo cách riêng. Không có tiêu chuẩn chung — plugin của runtime này không dùng được cho runtime khác.

7.2 CNI là gì?

CNI (Container Network Interface) là tập hợp các tiêu chuẩn (specifications) định nghĩa cách các chương trình nên được phát triển để giải quyết networking challenges trong container runtime environments.

Các chương trình này được gọi là plugins. Ví dụ: bridge plugin thực hiện các tác vụ cần thiết để gắn container vào bridge network.

💡 Hình dung: CNI giống "ổ cắm điện tiêu chuẩn" — không quan trọng hãng nào sản xuất, miễn đúng chuẩn thì ổ cắm nào cũng cắm được. CNI là chuẩn để container runtime và network plugin "nói chuyện" được với nhau.

7.3 Trách nhiệm của Container Runtimes (theo CNI)

Container runtime chịu trách nhiệm:

  1. Tạo network namespace cho mỗi container.
  2. Xác định networks mà container phải gắn vào.
  3. Gọi plugin khi container được tạo (command: ADD).
  4. Gọi plugin khi container được xóa (command: DEL).
  5. Cấu hình network plugin bằng JSON file.

7.4 Trách nhiệm của Plugins

Plugin cần hỗ trợ:

  • Các command-line arguments: ADD, DEL, CHECK.
  • Chấp nhận parameters: container ID, network namespace.
  • Gán IP addresses cho pods.
  • Tạo các routes cần thiết.

7.5 Plugins có sẵn với CNI

PluginMô tả
bridgeTạo Linux bridge và kết nối container
vlanVLAN tagging cho network isolation
ipvlanIPvlan — chia interface vật lý thành nhiều interface ảo
macvlanMACVLAN — mỗi container có MAC riêng, như switch thật
host-localIPAM: quản lý IP cục bộ trên host
dhcpIPAM: lấy IP từ DHCP server

7.6 Third-party Plugins

Nhiều plugin trong số này triển khai theo mô hình overlay network — một mạng ảo được "đắp" lên trên (overlay) hạ tầng mạng vật lý sẵn có (underlay). Gói tin giữa các Pod trên các node khác nhau được đóng gói (encapsulate) lại rồi gửi qua mạng vật lý như traffic bình thường giữa các node, sau đó được mở gói ở đầu nhận. Nhờ vậy Pod network hoạt động độc lập với cách hạ tầng vật lý bên dưới được thiết kế, đổi lại phải trả thêm chi phí xử lý cho việc đóng/mở gói.

Nhiều giải pháp networking mạnh mẽ hơn:

  • Weave — overlay network, mã hóa tự động.
  • Flannel — simple overlay, được CoreOS phát triển.
  • Calico — policy-based networking, hỗ trợ network policies.
  • Cilium — eBPF-based networking, visibility.
  • VMware NSX — enterprise networking.

7.7 Docker và CNI

⚠️ Lưu ý quan trọng: Docker KHÔNG implement CNI. Docker có tiêu chuẩn riêng là CNM (Container Network Model) — khác với CNI của Kubernetes.

Để sử dụng CNI với Docker:

  1. Tạo container mà không có network configuration.
  2. Tự gọi CNI plugin thủ công.

Kubernetes làm điều này tự động: khi kubelet tạo containers, nó tạo chúng mà không có networking, sau đó gọi CNI plugins để cấu hình networking.


8. Yêu cầu Networking cho Cluster

8.1 Cấu hình Node

Mỗi node trong Kubernetes cluster phải đáp ứng:

  • Ít nhất một interface kết nối đến một network.
  • Mỗi interface có địa chỉ IP được cấu hình.
  • Hostname duy nhất trong cluster.
  • MAC address duy nhất.

8.2 Các Ports cần mở

Control Plane (Master Node)

PortMô tảCần từ
6443kube-apiserverWorker nodes
10250kubeletControl plane
10259kube-schedulerSelf
10257kube-controller-managerSelf
2379etcd serverControl plane nodes
2380etcd server (peer)Other etcd nodes

Worker Nodes

PortMô tảCần từ
10250kubeletControl plane, kubelet API
30000-32767Services exposed (NodePort)External clients

8.3 Kiểm tra trong Lab

Xem thông tin nodes:

kubectl get nodes -o wide

# Output (minh họa):
# NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP
# node-1 Ready control-plane 5d v1.28 192.168.1.10 <none>
# node-2 Ready <none> 5d v1.28 192.168.1.11 <none>

Xem interfaces và IPs:

ip addr
ip link

Xem routing table:

ip route

# Output (minh họa):
# default via 192.168.1.1 dev eth0
# 10.244.0.0/16 dev weave scope link
# 192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.10

Nguồn tham khảo

Nguồn gốc: Khóa "Certified Kubernetes Administrator (CKA)" — phần "Networking" (Routing và Gateway trong Linux; DNS trong Linux; CoreDNS Server; Network Namespaces; Docker Networking; Container Network Interface), nền tảng KodeKloud. Giảng viên: Mumshad Mannambeth.

Repo ghi chú, link tài liệu, và đáp án các practice question của toàn bộ khóa học: kodekloudhub/certified-kubernetes-administrator-course.

Fact-check:

  • CoreDNS trở thành DNS add-on mặc định của kubeadm từ Kubernetes v1.13 (trước đó GA từ v1.11 nhưng kube-dns vẫn là default) — 2026-09-23, Kubernetes 1.13 Release Announcement.
  • kube-dns (giải pháp DNS cũ trước CoreDNS) đang được loại bỏ dần khỏi Kubernetes, dự kiến ngừng build package mới sau v1.40 — 2026-09-23, Kubernetes v1.37 Release Notes.
  • Dải NodePort mặc định vẫn là 30000-32767, cấu hình qua flag --service-node-port-range của kube-apiserver — 2026-09-23, Kubernetes Service concept.