- Deploy kind cluster
- Understand iptables role in connectivity
- Investigate services and pods connectivity
- Inspect network primitives and map them to pods
- Docker running
- Deploy kind cluster
- Deploy pods
- Deploy services
- Check to make sure docker is running
docker version 2020-03-06 19:13:25 ⌚ strongjz-macbook in ~
○ → docker version
Client: Docker Engine - Community
Version: 19.03.5
API version: 1.40
Go version: go1.12.12
Git commit: 633a0ea
Built: Wed Nov 13 07:22:34 2019
OS/Arch: darwin/amd64
Experimental: false
Server: Docker Engine - Community
Engine:
Version: 19.03.5
API version: 1.40 (minimum version 1.12)
Go version: go1.12.12
Git commit: 633a0ea
Built: Wed Nov 13 07:29:19 2019
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: v1.2.10
GitCommit: b34a5c8af56e510852c35414db4c1f4fa6172339
runc:
Version: 1.0.0-rc8+dev
GitCommit: 3e425f80a8c931f88e6d94a8c831b9d5aa481657
docker-init:
Version: 0.18.0
GitCommit: fec3683- Start kind cluster
kind create cluster --config kind.yml --name iptables± |master {1} S:5 U:4 ?:1 ✗| → kind create cluster --config kind.config --name iptables
Creating cluster "iptables" ...
✓ Ensuring node image (kindest/node:v1.16.3) 🖼
✓ Preparing nodes 📦
✓ Writing configuration 📜
✓ Starting control-plane 🕹️
✓ Installing CNI 🔌
✓ Installing StorageClass 💾
✓ Joining worker nodes 🚜
Set kubectl context to "kind-iptables"
You can now use your cluster with:
kubectl cluster-info --context kind-iptables
Have a nice day! 👋- Deploy lab pods
kubectl apply -f curl1.ymlkubectl apply -f curl2.yml 2020-03-06 19:01:52 ⌚ strongjz-macbook in ~/Documents/code/acg_ad_net_k8_aws_presentation/CH02/CH02_LC05
± |master {1} S:5 U:4 ?:1 ✗| → kubectl apply -f curl1.yml
deployment.apps/curl1 created
2020-03-06 19:02:02 ⌚ strongjz-macbook in ~/Documents/code/acg_ad_net_k8_aws_presentation/CH02/CH02_LC05
± |master {1} S:5 U:4 ?:1 ✗| → kubectl apply -f curl2.yml
deployment.apps/curl2 created- Deploy lab services
kubectl apply -f echo-service.yml± |master {1} S:5 U:4 ?:1 ✗| → kubectl apply -f echo-service.yml
deployment.apps/echo unchanged
service/echo-service created- Verify Pods and services are up and running
kubectl get pods,svc,ep± |master {1} S:5 U:4 ?:1 ✗| → kubectl get pods,svc,ep
NAME READY STATUS RESTARTS AGE
pod/curl1-647585685b-5pdj4 1/1 Running 0 6s
pod/curl2-5cb57995cd-jqdbg 1/1 Running 0 6s
pod/echo-669c78484d-df45k 1/1 Running 0 6s
pod/echo-669c78484d-ps5v5 1/1 Running 0 6s
pod/echo-669c78484d-vkpt9 1/1 Running 0 6s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/echo-service ClusterIP 10.102.117.8 <none> 80/TCP 6s
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 19m
NAME ENDPOINTS AGE
endpoints/echo-service 10.244.1.2:5678,10.244.2.4:5678,10.244.3.2:5678 6s
endpoints/kubernetes 172.17.0.4:6443 19m
- View veth pair and match with pod
- View network namespace and match with pod
- Verify pids on node match pods
- Match services with iptables rules
- View the bridge and veths for the pods on the node
Get the nodes the pod are on
kubectl get pods -o wide 2020-03-06 20:10:46 ⌚ strongjz-macbook in ~
○ → kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
curl1-647585685b-5pdj4 1/1 Running 0 35m 10.244.2.2 iptables-worker3 <none> <none>
curl2-5cb57995cd-jqdbg 1/1 Running 0 35m 10.244.2.3 iptables-worker3 <none> <none>
echo-669c78484d-df45k 1/1 Running 0 35m 10.244.2.4 iptables-worker3 <none> <none>
echo-669c78484d-ps5v5 1/1 Running 0 35m 10.244.1.2 iptables-worker <none> <none>
echo-669c78484d-vkpt9 1/1 Running 0 35m 10.244.3.2 iptables-worker2 <none> <none>Pod curl1-647585685b-5pdj4 is running on node iptables-worker3
- Pick the kind worker node
docker ps 2020-03-06 20:17:00 ⌚ strongjz-macbook in ~
○ → docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ba80dcf042da kindest/node:v1.16.3 "/usr/local/bin/entr…" 56 minutes ago Up 56 minutes 127.0.0.1:52942->6443/tcp iptables-control-plane
3acb04045545 kindest/node:v1.16.3 "/usr/local/bin/entr…" 56 minutes ago Up 56 minutes iptables-worker2
31c3d31fed34 kindest/node:v1.16.3 "/usr/local/bin/entr…" 56 minutes ago Up 56 minutes iptables-worker3
0204de74f428 kindest/node:v1.16.3 "/usr/local/bin/entr…" 56 minutes ago Up 56 minutes iptables-worker iptables-workerRun Exec on the worker node
- List out interfaces
on the Kind node exec ip a
docker exec -it iptables-worker3 ip a± |master {1} S:5 U:4 ?:1 ✗| → docker exec -it iptables-worker3 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
3: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN group default qlen 1000
link/tunnel6 :: brd ::
4: veth81ebcd7c@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 3a:f7:b7:a1:56:ac brd ff:ff:ff:ff:ff:ff link-netns cni-82a7f4a5-ab4a-1a0e-b76c-31be43b08bde
inet 10.244.2.1/32 brd 10.244.2.1 scope global veth81ebcd7c
valid_lft forever preferred_lft forever
5: veth135e50fd@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether ce:1a:0d:d5:11:0d brd ff:ff:ff:ff:ff:ff link-netns cni-727b1199-66da-2c59-d337-f683b3ce8fcd
inet 10.244.2.1/32 brd 10.244.2.1 scope global veth135e50fd
valid_lft forever preferred_lft forever
6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
7: veth61c9fd70@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether de:65:de:65:a8:3b brd ff:ff:ff:ff:ff:ff link-netns cni-0eeda30c-c02b-a9e0-da5d-c57f5436c307
inet 10.244.2.1/32 brd 10.244.2.1 scope global veth61c9fd70
valid_lft forever preferred_lft forever
On the curl pod also exec ip a
kubectl exec -it curl1-647585685b-5pdj4 ip a2020-03-06 20:17:45 ⌚ strongjz-macbook in ~
○ → kubectl exec -it curl1-647585685b-5pdj4 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
3: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop qlen 1000
link/tunnel6 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 brd 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
5: eth0@if4: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 6e:13:e8:42:bb:13 brd ff:ff:ff:ff:ff:ff
inet 10.244.2.2/24 brd 10.244.2.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::6c13:e8ff:fe42:bb13/64 scope link
valid_lft forever preferred_lft forever
On the Curl pod the interface for eth0 is connected to our veth pair and bridge, in this case that is interface 5
5: eth0@if4: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 6e:13:e8:42:bb:13 brd ff:ff:ff:ff:ff:ff
inet 10.244.2.2/24 brd 10.244.2.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::6c13:e8ff:fe42:bb13/64 scope link
valid_lft forever preferred_lft foreverIt also hints at where the interface is located on the kind worker node
eth0@if4This tells us that it's connected to the veth interface 4 on the kind worker node
From the node ip a
4: veth81ebcd7c@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 3a:f7:b7:a1:56:ac brd ff:ff:ff:ff:ff:ff link-netns cni-82a7f4a5-ab4a-1a0e-b76c-31be43b08bde
inet 10.244.2.1/32 brd 10.244.2.1 scope global veth81ebcd7c
valid_lft forever preferred_lft foreverThat matches the interface 5 on the pod
Let's check the Network namespace as well, from the node ip a output
cni-82a7f4a5-ab4a-1a0e-b76c-31be43b08bde- List out the Network namespaces on the node
docker exec -it iptables-worker3 /usr/sbin/ip netns list 2020-03-06 20:28:11 ⌚ strongjz-macbook in ~/Documents/code/acg_ad_net_k8_aws_presentation/CH02/CH02_LC05
± |master {1} S:5 U:4 ?:1 ✗| → docker exec -it iptables-worker3 /usr/sbin/ip netns list
cni-0eeda30c-c02b-a9e0-da5d-c57f5436c307 (id: 3)
cni-727b1199-66da-2c59-d337-f683b3ce8fcd (id: 2)
cni-82a7f4a5-ab4a-1a0e-b76c-31be43b08bde (id: 1)Let's see what process/es run inside that network namespace
docker exec -it iptables-worker3 /usr/sbin/ip netns pid cni-727b1199-66da-2c59-d337-f683b3ce8fcd 2020-03-06 20:29:12 ⌚ strongjz-macbook in ~/Documents/code/acg_ad_net_k8_aws_presentation/CH02/CH02_LC05
± |master {1} S:5 U:4 ?:1 ✗| → docker exec -it iptables-worker3 /usr/sbin/ip netns pid cni-727b1199-66da-2c59-d337-f683b3ce8fcd
2677
2907
2919Let's grep for each process id
2020-03-06 20:30:19 ⌚ strongjz-macbook in ~/Documents/code/acg_ad_net_k8_aws_presentation/CH02/CH02_LC05
± |master {1} S:5 U:4 ?:1 ✗| → docker exec -it iptables-worker3 ps aux | grep 2677
root 2677 0.0 0.0 1024 4 ? Ss 00:41 0:00 /pause
2020-03-06 20:30:59 ⌚ strongjz-macbook in ~/Documents/code/acg_ad_net_k8_aws_presentation/CH02/CH02_LC05
± |master {1} S:5 U:4 ?:1 ✗| → docker exec -it iptables-worker3 ps aux | grep 2907
root 2907 0.0 0.0 3180 188 ? Ss 00:41 0:00 sh -c echo Hell
2020-03-06 20:31:05 ⌚ strongjz-macbook in ~/Documents/code/acg_ad_net_k8_aws_presentation/CH02/CH02_LC05
± |master {1} S:5 U:4 ?:1 ✗| → docker exec -it iptables-worker3 ps aux | grep 2919
root 2919 0.0 0.0 3160 184 ? S 00:41 0:00 sleep 3600We have the pause container, and the two processes running inside the curl container, echo and sleep
- Inspecting iptables
View the iptables on the kind worker node
docker exec -it iptables-worker3 iptables -L± |master {1} S:5 U:4 ?:1 ✗| → docker exec -it iptables-worker3 iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
KUBE-SERVICES all -- anywhere anywhere ctstate NEW /* kubernetes service portals */
KUBE-EXTERNAL-SERVICES all -- anywhere anywhere ctstate NEW /* kubernetes externally-visible service portals */
KUBE-FIREWALL all -- anywhere anywhere
Chain FORWARD (policy ACCEPT)
target prot opt source destination
KUBE-FORWARD all -- anywhere anywhere /* kubernetes forwarding rules */
KUBE-SERVICES all -- anywhere anywhere ctstate NEW /* kubernetes service portals */
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
KUBE-SERVICES all -- anywhere anywhere ctstate NEW /* kubernetes service portals */
KUBE-FIREWALL all -- anywhere anywhere
Chain KUBE-EXTERNAL-SERVICES (1 references)
target prot opt source destination
Chain KUBE-FIREWALL (2 references)
target prot opt source destination
DROP all -- anywhere anywhere /* kubernetes firewall for dropping marked packets */ mark match 0x8000/0x8000
Chain KUBE-FORWARD (1 references)
target prot opt source destination
DROP all -- anywhere anywhere ctstate INVALID
ACCEPT all -- anywhere anywhere /* kubernetes forwarding rules */ mark match 0x4000/0x4000
ACCEPT all -- 10.244.0.0/16 anywhere /* kubernetes forwarding conntrack pod source rule */ ctstate RELATED,ESTABLISHED
ACCEPT all -- anywhere 10.244.0.0/16 /* kubernetes forwarding conntrack pod destination rule */ ctstate RELATED,ESTABLISHED
Chain KUBE-SERVICES (3 references)
target prot opt source destinationRetrieve the Cluster IP of the echo service
kubectl get svc 2020-03-06 19:59:46 ⌚ strongjz-macbook in ~
○ → kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
echo-service ClusterIP 10.102.117.8 <none> 80/TCP 22m
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 41mNow use the cluster ip of the service to find our iptables rule.
docker exec -it iptables-worker3 iptables -L -t nat | grep 10.102.117.8 2020-03-06 20:33:34 ⌚ strongjz-macbook in ~/Documents/code/acg_ad_net_k8_aws_presentation/CH02/CH02_LC05
± |master {1} S:5 U:4 ?:1 ✗| → docker exec -it iptables-worker3 iptables -L -t nat | grep 10.102.117.8
KUBE-MARK-MASQ tcp -- !10.244.0.0/16 10.102.117.8 /* default/echo-service: cluster IP */ tcp dpt:80
KUBE-SVC-7VVRITHJKDZHDQAD tcp -- anywhere 10.102.117.8 /* default/echo-service: cluster IP */ tcp dpt:80List out all the rules on the chain KUBE-SVC-7VVRITHJKDZHDQAD
docker exec -it iptables-worker3 iptables -L KUBE-SVC-7VVRITHJKDZHDQAD -t nat± |master {1} S:5 U:4 ?:1 ✗| → docker exec -it iptables-worker3 iptables -L KUBE-SVC-7VVRITHJKDZHDQAD -t nat
Chain KUBE-SVC-7VVRITHJKDZHDQAD (1 references)
target prot opt source destination
KUBE-SEP-U2LTPJXAZEM2OQET all -- anywhere anywhere statistic mode random probability 0.33332999982
KUBE-SEP-AANMSM6QVJW3JS2Y all -- anywhere anywhere statistic mode random probability 0.50000000000
KUBE-SEP-NXPMRYPPF5OQRY2M all -- anywhere anywhereAll of the endpoints for the services are map to these chains
- KUBE-SEP-U2LTPJXAZEM2OQET
- KUBE-SEP-AANMSM6QVJW3JS2Y
- KUBE-SEP-NXPMRYPPF5OQRY2M
Now we can see what the rules for this chain are
docker exec -it iptables-worker3 iptables -L KUBE-SEP-U2LTPJXAZEM2OQET -t nat± |master {1} S:5 U:4 ?:1 ✗| → docker exec -it iptables-worker3 iptables -L KUBE-SEP-U2LTPJXAZEM2OQET -t nat
Chain KUBE-SEP-U2LTPJXAZEM2OQET (1 references)
target prot opt source destination
KUBE-MARK-MASQ all -- 10.244.1.2 anywhere
DNAT tcp -- anywhere anywhere tcp to:10.244.1.2:567810.244.1.2:5678 is one of the services endpoints, aka a pod backing the service
○ → kubectl describe ep echo-service
Name: echo-service
Namespace: default
Labels: <none>
Annotations: endpoints.kubernetes.io/last-change-trigger-time: 2020-03-07T00:41:34Z
Subsets:
Addresses: 10.244.1.2,10.244.2.4,10.244.3.2
NotReadyAddresses: <none>
Ports:
Name Port Protocol
---- ---- --------
<unset> 5678 TCP
Events: <none>