Skip to content

Instantly share code, notes, and snippets.

@dougbtv
Created February 5, 2019 20:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dougbtv/5814f4eab6c5852b08949434e067b7d2 to your computer and use it in GitHub Desktop.
Save dougbtv/5814f4eab6c5852b08949434e067b7d2 to your computer and use it in GitHub Desktop.
Multus + Weave sketch

Multus with weave sketch.

Spin up Kubernetes without a network, then... install weave per the installation guide

In theory before CNI plugin install nodes should be not ready & the CNI net.d folder should be empty...

[centos@kube-nonetwork-master ~]$ kubectl get nodes
NAME                    STATUS     ROLES    AGE   VERSION
kube-nonetwork-master   NotReady   master   58s   v1.13.3
kube-nonetwork-node-1   NotReady   <none>   34s   v1.13.3
[centos@kube-nonetwork-master ~]$ ls /etc/cni/net.d/ -1
[centos@kube-nonetwork-master ~]$ ls /etc/cni/net.d/ -1 | wc -l
0

Install weave...

kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"

Watch it come up...

[centos@kube-nonetwork-master ~]$ watch -n1 kubectl get pods --all-namespaces

Now your nodes should be ready...

[centos@kube-nonetwork-master ~]$ kubectl get nodes
NAME                    STATUS   ROLES    AGE     VERSION
kube-nonetwork-master   Ready    master   10m     v1.13.3
kube-nonetwork-node-1   Ready    <none>   9m50s   v1.13.3

Create a YAML file with these contents (I called mine multus.yaml)...

---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: network-attachment-definitions.k8s.cni.cncf.io
spec:
  group: k8s.cni.cncf.io
  version: v1
  scope: Namespaced
  names:
    plural: network-attachment-definitions
    singular: network-attachment-definition
    kind: NetworkAttachmentDefinition
    shortNames:
    - net-attach-def
  validation:
    openAPIV3Schema:
      properties:
        spec:
          properties:
            config:
                 type: string
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: multus
rules:
  - apiGroups: ["k8s.cni.cncf.io"]
    resources:
      - '*'
    verbs:
      - '*'
  - apiGroups:
      - ""
    resources:
      - pods
      - pods/status
    verbs:
      - get
      - update
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: multus
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: multus
subjects:
- kind: ServiceAccount
  name: multus
  namespace: kube-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: multus
  namespace: kube-system
---
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: kube-multus-ds-amd64
  namespace: kube-system
  labels:
    tier: node
    app: multus
spec:
  template:
    metadata:
      labels:
        tier: node
        app: multus
    spec:
      hostNetwork: true
      nodeSelector:
        beta.kubernetes.io/arch: amd64
      tolerations:
      - operator: Exists
        effect: NoSchedule
      serviceAccountName: multus
      containers:
      - name: kube-multus
        image: nfvpe/multus:snapshot
        command: ["/entrypoint.sh"]
        args: ["--multus-conf-file=auto"]
        resources:
          requests:
            cpu: "100m"
            memory: "50Mi"
          limits:
            cpu: "100m"
            memory: "50Mi"
        securityContext:
          privileged: true
        volumeMounts:
        - name: cni
          mountPath: /host/etc/cni/net.d
        - name: cnibin
          mountPath: /host/opt/cni/bin
      volumes:
        - name: cni
          hostPath:
            path: /etc/cni/net.d
        - name: cnibin
          hostPath:
            path: /opt/cni/bin

Then apply that file...

kubectl create -f multus.yaml

Watch the pods come up...

[centos@kube-nonetwork-master ~]$ watch -n1 kubectl get pods --all-namespaces

Then you can see there's a new Multus config file created in addition to weave's config...

[centos@kube-nonetwork-master ~]$ ls /etc/cni/net.d/ -lathr
total 8.0K
drwxr-xr-x. 3 root root  19 Feb  5 20:30 ..
-rw-r--r--. 1 root root 318 Feb  5 20:36 10-weave.conflist
drwxr-xr-x. 2 root root  31 Feb  5 20:44 multus.d
-rw-r--r--. 1 root root 326 Feb  5 20:44 00-multus.conf
drwxr-xr-x. 3 root root  69 Feb  5 20:44 .

Cat that file to see that it contains a weave config packed in it...

cat /etc/cni/net.d/00-multus.conf

Now, let's create a macvlan configuration NOTE: My master device eth0 -- map this to the master device of the interface on your machines. I also picked a gateway and IP address range that matches my network.

cat <<EOF | kubectl create -f -
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: macvlan-conf
spec:
  config: '{
      "cniVersion": "0.3.0",
      "type": "macvlan",
      "master": "eth0",
      "mode": "bridge",
      "ipam": {
        "type": "host-local",
        "subnet": "192.168.122.0/24",
        "rangeStart": "192.168.122.200",
        "rangeEnd": "192.168.122.216",
        "routes": [
          { "dst": "0.0.0.0/0" }
        ],
        "gateway": "192.168.122.1"
      }
    }'
EOF

You can list that...

kubectl get network-attachment-definitions

Now let's create a pod that uses that...

cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
  name: samplepod
  annotations:
    k8s.v1.cni.cncf.io/networks: macvlan-conf
spec:
  containers:
  - name: samplepod
    command: ["/bin/bash", "-c", "sleep 2000000000000"]
    image: dougbtv/centos-network
EOF

Wait until that pod comes up...

watch -n1 kubectl get pods -o wide

Now you can see it has multiple interfaces...

[centos@kube-nonetwork-master ~]$ kubectl exec -it samplepod -- ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    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: net1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN 
    link/ether 2a:86:a0:1f:c2:0a brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.122.200/24 scope global net1
       valid_lft forever preferred_lft forever
    inet6 fe80::2886:a0ff:fe1f:c20a/64 scope link 
       valid_lft forever preferred_lft forever
14: eth0@if15: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1376 qdisc noqueue state UP 
    link/ether d6:40:08:96:74:7e brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.40.0.2/12 brd 10.47.255.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::d440:8ff:fe96:747e/64 scope link tentative dadfailed 
       valid_lft forever preferred_lft forever

I can also ping on both IPs...

[centos@kube-nonetwork-master ~]$ ping -c 5 10.40.0.2
PING 10.40.0.2 (10.40.0.2) 56(84) bytes of data.
64 bytes from 10.40.0.2: icmp_seq=1 ttl=64 time=1.68 ms
64 bytes from 10.40.0.2: icmp_seq=2 ttl=64 time=0.565 ms
64 bytes from 10.40.0.2: icmp_seq=3 ttl=64 time=0.618 ms
64 bytes from 10.40.0.2: icmp_seq=4 ttl=64 time=0.474 ms
64 bytes from 10.40.0.2: icmp_seq=5 ttl=64 time=0.680 ms

--- 10.40.0.2 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4004ms
rtt min/avg/max/mdev = 0.474/0.804/1.686/0.446 ms
[centos@kube-nonetwork-master ~]$ ping -c 5 192.168.122.200
PING 192.168.122.200 (192.168.122.200) 56(84) bytes of data.
64 bytes from 192.168.122.200: icmp_seq=1 ttl=64 time=0.593 ms
64 bytes from 192.168.122.200: icmp_seq=2 ttl=64 time=0.288 ms
64 bytes from 192.168.122.200: icmp_seq=3 ttl=64 time=0.427 ms
64 bytes from 192.168.122.200: icmp_seq=4 ttl=64 time=0.369 ms
64 bytes from 192.168.122.200: icmp_seq=5 ttl=64 time=0.368 ms

You can also get the IPs from the status annotation...

[centos@kube-nonetwork-master ~]$ kubectl describe pod samplepod

Look for the annotations section...

Annotations:        k8s.v1.cni.cncf.io/networks: macvlan-conf
                    k8s.v1.cni.cncf.io/networks-status:
                      [{
                          "name": "weave",
                          "ips": [
                              "10.40.0.2"
                          ],
                          "default": true,
                          "dns": {}
                      },{
                          "name": "macvlan-conf",
                          "interface": "net1",
                          "ips": [
                              "192.168.122.200"
                          ],
                          "mac": "2a:86:a0:1f:c2:0a",
                          "dns": {}
                      }]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment