CalicoとCiliumでの細かい動作の違い

以下のセッションを見ていたら自分の記憶とちょっと違ったので確認したメモ。

具体的には以下の点。

  • ALBからのIngress接続を許可するため、VPCのIPブロックを許可すると、Podが全部接続可能になってしまう(PodはVPC CNIプラグインによってVPCのIPを持っているため)

自分も当初そう思っていたが、CiliumかCalicoかをいろいろ試していたとき、何かの条件ではそうならず、VPCのIPを許可していても、Podを許可していないと通信出来なかった記憶がある。

  • CiliumだったかCalicoだったか
  • 標準NetworkPolicyだったかカスタムリソースだったか
  • IngressだったかEgressだったか

この辺は覚えてない。

以下試した結論を書いておくと、CalicoとCiliumの場合で標準NetworkPolicyを使っていても動作が違った。Calicoの場合はVPCのIPブロックを許可すると全てのPodが許可されるが、Ciliumの場合は明示的をPodを許可しないと許可されなかった。

クラスターの作成

クラスターを作成する。

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: netpol
  region: ap-northeast-1
vpc:
  cidr: "10.1.0.0/16"

availabilityZones:
  - ap-northeast-1a
  - ap-northeast-1c

managedNodeGroups:
  - name: managed-ng-1
    minSize: 2
    maxSize: 2
    desiredCapacity: 2
    ssh:
      allow: true
      publicKeyName: default
    privateNetworking: true

cloudWatch:
  clusterLogging:
    enableTypes: ["*"]
eksctl create cluster -f cluster.yaml

Calico

Calicoをインストールする。

kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/v1.7.5/config/v1.7/calico.yaml

確認する。

$ k get po -A
NAMESPACE     NAME                                                  READY   STATUS    RESTARTS   AGE
kube-system   aws-node-75xrn                                        1/1     Running   0          5m12s
kube-system   aws-node-s49js                                        1/1     Running   0          5m11s
kube-system   calico-node-k8wl5                                     1/1     Running   0          36s
kube-system   calico-node-lntxb                                     1/1     Running   0          36s
kube-system   calico-typha-5ff6788794-fz4vn                         1/1     Running   0          36s
kube-system   calico-typha-horizontal-autoscaler-7d57c996b4-hrv2v   1/1     Running   0          35s
kube-system   coredns-86f7d88d77-9t4ds                              1/1     Running   0          10m
kube-system   coredns-86f7d88d77-d85xq                              1/1     Running   0          10m
kube-system   kube-proxy-47sjz                                      1/1     Running   0          5m11s
kube-system   kube-proxy-l6psf                                      1/1     Running   0          5m12s

テスト用のNamespaceとPodを作る。

$ k create ns ns1
namespace/ns1 created
$ k create ns ns2
namespace/ns2 created
$ k -n ns1 run pod1 --image=nginx
pod/pod1 created
$ k -n ns1 run pod2 --image=nginx
pod/pod2 created
$ k -n ns2 run pod1 --image=nginx
pod/pod1 created

ns1内の通信のみ許可するポリシーを作成する。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: policy1
  namespace: ns1
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector: {}
$ k apply -f policy1.yaml
networkpolicy.networking.k8s.io/policy1 created

テストしてみる。ns1/pod2からns1/pod1に接続できるが、ns2/pod1からns1/pod1には接続できない。

$ k -n ns1 get pod -o wide
NAME   READY   STATUS    RESTARTS   AGE     IP             NODE                                              NOMINATED NODE   READINESS GATES
pod1   1/1     Running   0          5m3s    10.1.103.145   ip-10-1-112-140.ap-northeast-1.compute.internal   <none>           <none>
pod2   1/1     Running   0          2m43s   10.1.76.11     ip-10-1-64-124.ap-northeast-1.compute.internal    <none>           <none>
$ k -n ns1 exec -it pod2 -- bash
root@pod2:/# curl 10.1.103.145
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
root@pod2:/# exit
exit
$ k -n ns2 exec -it pod1 -- bash
root@pod1:/# curl 10.1.103.145
^C
root@pod1:/# exit
exit
command terminated with exit code 130

ポリシーを変更し、VPCのIPレンジを全て許可する。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: policy1
  namespace: ns1
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector: {}
    - ipBlock:
        cidr: 10.1.0.0/16
$ k apply -f policy1.yaml
networkpolicy.networking.k8s.io/policy1 configured

これで試す。確かに繋がってしまう。

$ k -n ns2 exec -it pod1 -- bash
root@pod1:/# curl 10.1.103.145
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
root@pod1:/# exit
exit

NetworkPolicyを削除する。

$ k -n ns1 delete netpol --all
networkpolicy.networking.k8s.io "policy1" deleted

Calicoを削除する。

k delete -fhttps://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/v1.7.5/config/v1.7/calico.yaml

CNIのゴミが残っているといやなので、念のためマネコンからEC2インスタンスを削除して新しいノードにする。

Cilium

Ciliumをインストールする。

helm repo update
helm install cilium cilium/cilium --version 1.9.5 \
  --namespace kube-system \
  --set cni.chainingMode=aws-cni \
  --set masquerade=false \
  --set tunnel=disabled \
  --set nodeinit.enabled=true

CoreDNSのPodが起動してこない。

$ k get pod -n kube-system
NAME                               READY   STATUS              RESTARTS   AGE
aws-node-7kzwg                     1/1     Running             0          6m26s
aws-node-w7mks                     1/1     Running             0          8m9s
cilium-9mz9h                       1/1     Running             0          5m53s
cilium-node-init-qbk66             1/1     Running             0          5m53s
cilium-node-init-rqd66             1/1     Running             0          5m53s
cilium-operator-7f555b8c74-gw6mn   1/1     Running             0          5m53s
cilium-operator-7f555b8c74-plqn6   1/1     Running             0          5m53s
cilium-xs9qc                       1/1     Running             0          5m53s
coredns-86f7d88d77-46shh           0/1     ContainerCreating   0          5m22s
coredns-86f7d88d77-gdgvj           0/1     ContainerCreating   0          5m7s
kube-proxy-jfwbf                   1/1     Running             0          6m26s
kube-proxy-snlwr                   1/1     Running             0          8m9s

これは以下のあたりの問題。

CNIを1.7.9にすると治るらしいのでアップデートする。

$ k apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/master/config/v1.7/aws-k8s-cni.yaml
clusterrolebinding.rbac.authorization.k8s.io/aws-node unchanged
clusterrole.rbac.authorization.k8s.io/aws-node unchanged
customresourcedefinition.apiextensions.k8s.io/eniconfigs.crd.k8s.amazonaws.com unchanged
daemonset.apps/aws-node configured
serviceaccount/aws-node unchanged

確認する。

$ k get pod -n kube-system
NAME                               READY   STATUS    RESTARTS   AGE
aws-node-lxw6g                     1/1     Running   0          102s
aws-node-n2pf9                     1/1     Running   0          2m29s
cilium-9mz9h                       1/1     Running   0          10m
cilium-node-init-qbk66             1/1     Running   0          10m
cilium-node-init-rqd66             1/1     Running   0          10m
cilium-operator-7f555b8c74-gw6mn   1/1     Running   0          10m
cilium-operator-7f555b8c74-plqn6   1/1     Running   0          10m
cilium-xs9qc                       1/1     Running   0          10m
coredns-86f7d88d77-46shh           1/1     Running   0          10m
coredns-86f7d88d77-gdgvj           1/1     Running   0          9m56s
kube-proxy-jfwbf                   1/1     Running   0          11m
kube-proxy-snlwr                   1/1     Running   0          12m

テスト用のPodを作る。

$ k -n ns1 run pod1 --image=nginx
pod/pod1 created
$ k -n ns1 run pod2 --image=nginx
pod/pod2 created
$ k -n ns2 run pod1 --image=nginx
pod/pod1 created

ns1内の通信のみ許可するポリシーを作成する。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: policy1
  namespace: ns1
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector: {}
$ k apply -f policy1.yaml
networkpolicy.networking.k8s.io/policy1 created

テストしてみる。ns1/pod2からns1/pod1に接続できるが、ns2/pod1からns1/pod1には接続できない。

$ k -n ns1 get pod -o wide
NAME   READY   STATUS    RESTARTS   AGE   IP             NODE                                             NOMINATED NODE   READINESS GATES
pod1   1/1     Running   0          40s   10.1.84.166    ip-10-1-80-148.ap-northeast-1.compute.internal   <none>           <none>
pod2   1/1     Running   0          35s   10.1.109.192   ip-10-1-107-65.ap-northeast-1.compute.internal   <none>           <none>
$ k -n ns1 exec -it pod2 -- bash
root@pod2:/# curl 10.1.84.166
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
root@pod2:/# exit
exit
$ k -n ns2 exec -it pod1 -- bash
root@pod1:/# curl 10.1.84.166
^C
root@pod1:/# exit
exit
command terminated with exit code 130

ポリシーを変更し、VPCのIPレンジを全て許可する。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: policy1
  namespace: ns1
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector: {}
    - ipBlock:
        cidr: 10.1.0.0/16
$ k apply -f policy1.yaml
networkpolicy.networking.k8s.io/policy1 configured

これで試す。Ciliumの場合は繋がらない!

$ k -n ns2 exec -it pod1 -- bash
root@pod1:/# curl 10.1.84.166
^C
root@pod1:/# exit
exit
command terminated with exit code 130

さらに、Namespaceを指定して許可してみる。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: policy1
  namespace: ns1
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector: {}
    - ipBlock:
        cidr: 10.1.0.0/16
    - namespaceSelector:
        matchLabels:
          name: ns2
$ k label ns ns1 name=ns1
namespace/ns1 labeled
$ k label ns ns2 name=ns2
namespace/ns2 labeled
$ k apply -f policy1.yaml
networkpolicy.networking.k8s.io/policy1 configured

この場合は意図した通り繋がる。

$ k -n ns2 exec -it pod1 -- bash
root@pod1:/# curl 10.1.84.166
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
root@pod1:/# exit
exit