带你玩转kubernetes-k8s(第49篇:深入分析k8s网络原理-[直接路由,Calico部署])

        我们知道,docker0网桥上的IP地址在Node网络上是看不到的。从一个Node到一个Node内的docker0是不通的,因为它不知道某个IP地址在哪里。如果能够让这些机器知道对端docker0地址在哪里,就可以让这些docker0互相通信了。这样,在所有Node上运行的Pod就都可以互相通信了。

       我们可以通过部署MultiLayer Switch(MLS)来实现这一点,在MLS中配置每个docker0子网地址到Node地址的路由项,通过MLS将docker0的IP寻址定向到对应的Node上。
      另外,我们可以将这些docker0和Node的匹配关系配置在Linux操作系统的路由项中,这样通信发起的Node就能够根据这些路由信息直接找到目标Pod所在的Node,将数据传输过去。            

带你玩转kubernetes-k8s(第49篇:深入分析k8s网络原理-[直接路由,Calico部署])_第1张图片

我们在每个Node的路由表中增加对方所有docker0的路由项。

 

     例如,Pod1所在docker0网桥的IP子网是10.1.10.0,Node的地址为192.168.1.128;而Pod2所在docker0网桥的IP子网是10.1.20.0,Node的地址为192.168.1.129。
    在Node1上用route add命令增加一条到Node2上docker0的静态路由规则:

route add -net 10.1.20.0 netmask 255.255.255.0 gw 192.168.1.129

     同样,在Node2上增加一条到Node1上docker0的静态路由规则:

route add -net  10.1.10.0 netmask 255.255.255.0 gw 192.168.1.128

   在Node1上通过ping命令验证到Node2上docker0的网络连通性。这里10.1.20.1为Node2上docker0网桥自身的IP地址.

   可以看到,路由转发规则生效,Node1可以直接访问Node2上的docker0网桥,进一步就可以访问属于docker0网段的容器应用了。

    在大规模集群中,在每个Node上都需要配置到其他docker0/Node的路由项,这会带来很大的工作量;并且在新增机器时,对所有Node都需要修改配置;在重启机器时,如果docker0的地址有变化,则也需要修改所有Node的配置,这显然是非常复杂的。

    为了管理这些动态变化的docker0地址,动态地让其他Node都感知到它,还可以使用动态路由发现协议来同步这些变化。在运行动态路由发现协议代理的Node时,会将本机LOCAL路由表的IP地址通过组播协议发布出去,同时监听其他Node的组播包。通过这样的信息交换,Node上的路由规则就都能够相互学习。当然,路由发现协议本身还是很复杂的,感兴趣的话,可以查阅相关规范。在实现这些动态路由发现协议的开源软件中,常用的有Quagga(http://www.quagga.net)、Zebra等。下面简单介绍直接路由的操作过程。

  

     首先,手工分配Docker bridge的地址,保证它们在不同的网段是不重叠的。建议最好不用Docker Daemon自动创建的docker0(因为我们不需要它的自动管理功能),而是单独建立一个bridge,给它配置规划好的IP地址,然后使用--bridge=XX来指定网桥。
     然后,在每个节点上都运行Quagga。

    完成这些操作后,我们很快就能得到一个Pod和Pod直接互相访问的环境了。由于路由发现能够被网络上的所有设备接收,所以如果网络上的路由器也能打开RIP协议选项,则能够学习到这些路由信息。通过这些路由器,我们甚至可以在非Node上使用Pod的IP地址直接访问Node上的Pod了。

    除了在每台服务器上安装Quagga软件并启动,还可以使用Quagga容器运行(例如index.alauda.cn/georce/router)。在每个Node上下载该Docker镜像:

docker pull index.alauda.cn/georce/router

      在运行Quagga容器之前,需要确保每个Node上docker0网桥的子网地址不能重叠,也不能与物理机所在的网络重叠,这需要网络管理员的仔细规划。

    下面以3个Node为例,每个Node的docker0网桥的地址如下(前提是Node物理机的IP地址不是10.1.X.X地址段):

node1:#if config docker0 10.1.10.1/24
node2: #if config docker0 10.1.20.1/24
node3: #if config docker0 10.1.30.1/24

       在每个Node上启动Quagga容器。需要说明的是,Quagga需要以--privileged特权模式运行,并且指定--net=host,表示直接使用物理机的网络:

docker run -itd --name=router --privileged --net=host  index.alauda.cn/georce/router

启动成功后,各Node上的Quagga会相互学习来完成到其他机器的docker0路由规则的添加。

一段时间后,在Node1上使用route -n命令来查看路由表,可以看到Quagga自动添加了两条到Node2和到Node3上docker0的路由规则:

route -n

在Node2上查看路由表,可以看到自动添加了两条到Node1和Node3上docker0的路由规则:

route -n

至此,所有Node上的docker0就都可以互联互通了。

      当然,聪明的你还会有新的疑问:这样做的话,由于每个Pod的地址都会被路由发现协议广播出去,会不会存在路由表过大的情况?实际上,路由表通常都会有高速缓存,查找速度会很快,不会对性能产生太大的影响。当然,如果你的集群容量在数千个Node以上,则仍然需要测试和评估路由表的效率问题。

Calico容器网络和网络策略实战

   本节以Calico为例讲解kubernetes中CNI插件和网络策略的原理和应用。

Calico简介

    Calico是一个基于BGP的纯三层的网络方案,与OpenStack、Kubernetes、AWS、GCE等云平台都能够良好地集成。Calico在每个计算节点都利用Linux Kernel实现了一个高效的vRouter来负责数据转发。每个vRouter都通过BGP1协议把在本节点上运行的容器的路由信息向整个Calico网络广播,并自动设置到达其他节点的路由转发规则。Calico保证所有容器之间的数据流量都是通过IP路由的方式完成互联互通的。Calico节点组网时可以直接利用数据中心的网络结构(L2或者L3),不需要额外的NAT、隧道或者Overlay Network,没有额外的封包解包,能够节约CPU运算,提高网络效率。

    Calico在小规模集群中可以直接互联,在大规模集群中可以通过额外的BGP route reflector来完成。

   此外,Calico基于iptables还提供了丰富的网络策略,实现了Kubernetes的Network Policy策略,提供容器间网络可达性限制的功能。

   Calico的系统架构如下图所示:

 

带你玩转kubernetes-k8s(第49篇:深入分析k8s网络原理-[直接路由,Calico部署])_第2张图片

Calico的主要组件如下。
◎ Felix:Calico Agent,运行在每个Node上,负责为容器设置网络资源(IP地址、路由规则、iptables规则等),保证跨主机容器网络互通。
◎ etcd:Calico使用的后端存储。
◎ BGP Client:负责把Felix在各Node上设置的路由信息通过BGP协议广播到Calico网络。
◎ Route Reflector:通过一个或者多个BGP Route Reflector来完成大规模集群的分级路由分发。
◎ CalicoCtl:Calico命令行管理工具。

部署Calico服务   

在Kubernetes中部署Calico的主要步骤如下。
(1)修改Kubernetes服务的启动参数,并重启服务。
◎ 设置Master上kube-apiserver服务的启动参数:--allow-privileged=true(因为calico-node需要以特权模式运行在各Node上)。

本例中的Kubernetes集群包括两个Node:k8s-node-1(IP地址为192.168.18.3)和k8s-node-2(IP地址为192.168.18.4)。

(2)创建Calico服务,主要包括calico-node和calico policy controller。需要创建的资源对象如下。
◎ 创建ConfigMap calico-config,包含Calico所需的配置参数。
◎ 创建Secret calico-etcd-secrets,用于使用TLS方式连接etcd。
◎ 在每个Node上都运行calico/node容器,部署为DaemonSet。
◎ 在每个Node上都安装Calico CNI二进制文件和网络配置参数(由install-cni容器完成)。
◎ 部署一个名为calico/kube-policy-controller的Deployment,以对接Kubernetes集群中为Pod设置的Network Policy。

      从Calico官网下载Calico的YAML配置文件,下载地址为:

http://docs.projectcalico.org/v3.5/getting-started/kubernetes/installation/hosted/calico.yaml

该配置文件包括启动Calico所需的全部资源对象的定义,下面对它们逐个进行说明。

(1)Calico所需的配置,以ConfigMap对象进行创建:

kind: ConfigMap
apiVersion: v1
metadata:
  name: calico-config
  namespace: kube-system
data:
  # 配置etcd的服务URL
  etcd_endpoints: "http://192.168.18.3:2379"

  # 如何etcd启用了https安全认证,则需要配置etcd相关证书
  etcd_ca: ""   # "/calico-secrets/etcd-ca"
  etcd_cert: "" # "/calico-secrets/etcd-cert"
  etcd_key: ""  # "/calico-secrets/etcd-key"
  # Typha is disabled.
  typha_service_name: "none"
  # 设置Calico 使用的backennd 类型,默认是bird
  calico_backend: "bird"

  # 设置 mtu值
  veth_mtu: "1440"

  # The CNI network configuration to install on each node.  The special
  # values in this config will be automatically populated.
  # 设置CNI 网络配置文件的内容
  cni_network_config: |-
    {
      "name": "k8s-pod-network",
      "cniVersion": "0.3.0",
      "plugins": [
        {
          "type": "calico",
          "log_level": "info",
          "etcd_endpoints": "__ETCD_ENDPOINTS__",
          "etcd_key_file": "__ETCD_KEY_FILE__",
          "etcd_cert_file": "__ETCD_CERT_FILE__",
          "etcd_ca_cert_file": "__ETCD_CA_CERT_FILE__",
          "mtu": __CNI_MTU__,
          "ipam": {
              "type": "calico-ipam"
          },
          "policy": {
              "type": "k8s"
          },
          "kubernetes": {
              "kubeconfig": "__KUBECONFIG_FILEPATH__"
          }
        },
        {
          "type": "portmap",
          "snat": true,
          "capabilities": {"portMappings": true}
        }
      ]
    }

对主要参数说明如下。

◎ etcd_endpoints:Calico使用etcd来保存网络拓扑和状态,该参数指定etcd服务的地址。
◎ calico_backend:Calico的后端,默认为bird。
◎ cni_network_config:符合CNI规范的网络配置。其中type=calico表示kubelet将从/opt/cni/bin目录下搜索名为calico的可执行文件,并调用它来完成容器网络的设置。ipam中的type=calico-ipam表示kubelet将在/opt/cni/bin目录下搜索名为calico-ipam的可执行文件,用于完成容器IP地址的分配。

    如果etcd服务配置了TLS安全认证,则还需指定相应的ca、cert、key等文件。

(2)访问etcd所需的secret,对于无TLS的etcd服务,将data设置为空即可:

apiVersion: v1
kind: Secret
type: Opaque
metadata:
  name: calico-etcd-secrets
  namespace: kube-system
data:
  # Populate the following with etcd TLS configuration if desired, but leave blank if
  # not using TLS for etcd.
  # The keys below should be uncommented and the values populated with the base64
  # encoded contents of each file that would be associated with the TLS data.
  # Example command for encoding a file contents: cat  | base64 -w 0
  # 如果配置了TLS ,则需要设置相应的证书和密钥文件路径
  # etcd-key: null
  # etcd-cert: null
  # etcd-ca: null


(3)calico-node,以DaemonSet方式在每个Node上都运行一个calico-node服务和一个install-cni服务:

kind: DaemonSet
apiVersion: extensions/v1beta1
metadata:
  name: calico-node
  namespace: kube-system
  labels:
    k8s-app: calico-node
spec:
  selector:
    matchLabels:
      k8s-app: calico-node
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
  template:
    metadata:
      labels:
        k8s-app: calico-node
      annotations:
        # This, along with the CriticalAddonsOnly toleration below,
        # marks the pod as a critical add-on, ensuring it gets
        # priority scheduling and that its resources are reserved
        # if it ever gets evicted.
        scheduler.alpha.kubernetes.io/critical-pod: ''
    spec:
      nodeSelector:
        beta.kubernetes.io/os: linux
      hostNetwork: true
      tolerations:
        # Make sure calico-node gets scheduled on all nodes.
        - effect: NoSchedule
          operator: Exists
        # Mark the pod as a critical add-on for rescheduling.
        - key: CriticalAddonsOnly
          operator: Exists
        - effect: NoExecute
          operator: Exists
      serviceAccountName: calico-node
      # Minimize downtime during a rolling upgrade or deletion; tell Kubernetes to do a "force
      # deletion": https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods.
      terminationGracePeriodSeconds: 0
      initContainers:
        # This container installs the Calico CNI binaries
        # and CNI network config file on each node.
        - name: install-cni
          image: calico/cni:v3.5.8
          command: ["/install-cni.sh"]
          env:
            # Name of the CNI config file to create.
            - name: CNI_CONF_NAME
              value: "10-calico.conflist"
            # The CNI network config to install on each node.
            - name: CNI_NETWORK_CONFIG
              valueFrom:
                configMapKeyRef:
                  name: calico-config
                  key: cni_network_config
            # The location of the Calico etcd cluster.
            - name: ETCD_ENDPOINTS
              valueFrom:
                configMapKeyRef:
                  name: calico-config
                  key: etcd_endpoints
            # CNI MTU Config variable
            - name: CNI_MTU
              valueFrom:
                configMapKeyRef:
                  name: calico-config
                  key: veth_mtu
            # Prevents the container from sleeping forever.
            - name: SLEEP
              value: "false"
          volumeMounts:
            - mountPath: /host/opt/cni/bin
              name: cni-bin-dir
            - mountPath: /host/etc/cni/net.d
              name: cni-net-dir
            - mountPath: /calico-secrets
              name: etcd-certs
      containers:
        # Runs calico/node container on each Kubernetes node.  This
        # container programs network policy and routes on each
        # host.
        - name: calico-node
          image: calico/node:v3.5.8
          env:
            # The location of the Calico etcd cluster.
            - name: ETCD_ENDPOINTS
              valueFrom:
                configMapKeyRef:
                  name: calico-config
                  key: etcd_endpoints
            # Location of the CA certificate for etcd.
            - name: ETCD_CA_CERT_FILE
              valueFrom:
                configMapKeyRef:
                  name: calico-config
                  key: etcd_ca
            # Location of the client key for etcd.
            - name: ETCD_KEY_FILE
              valueFrom:
                configMapKeyRef:
                  name: calico-config
                  key: etcd_key
            # Location of the client certificate for etcd.
            - name: ETCD_CERT_FILE
              valueFrom:
                configMapKeyRef:
                  name: calico-config
                  key: etcd_cert
            # Set noderef for node controller.
            - name: CALICO_K8S_NODE_REF
              valueFrom:
                fieldRef:
                  fieldPath: spec.nodeName
            # Choose the backend to use.
            - name: CALICO_NETWORKING_BACKEND
              valueFrom:
                configMapKeyRef:
                  name: calico-config
                  key: calico_backend
            # Cluster type to identify the deployment type
            - name: CLUSTER_TYPE
              value: "k8s,bgp"
            # Auto-detect the BGP IP address.
            - name: IP
              value: "autodetect"
            # Enable IPIP
            - name: CALICO_IPV4POOL_IPIP
              value: "Always"
            # Set MTU for tunnel device used if ipip is enabled
            - name: FELIX_IPINIPMTU
              valueFrom:
                configMapKeyRef:
                  name: calico-config
                  key: veth_mtu
            # The default IPv4 pool to create on startup if none exists. Pod IPs will be
            # chosen from this range. Changing this value after installation will have
            # no effect. This should fall within `--cluster-cidr`.
            - name: CALICO_IPV4POOL_CIDR
              value: "192.168.0.0/16"
            # Disable file logging so `kubectl logs` works.
            - name: CALICO_DISABLE_FILE_LOGGING
              value: "true"
            # Set Felix endpoint to host default action to ACCEPT.
            - name: FELIX_DEFAULTENDPOINTTOHOSTACTION
              value: "ACCEPT"
            # Disable IPv6 on Kubernetes.
            - name: FELIX_IPV6SUPPORT
              value: "false"
            # Set Felix logging to "info"
            - name: FELIX_LOGSEVERITYSCREEN
              value: "info"
            - name: FELIX_HEALTHENABLED
              value: "true"
          securityContext:
            privileged: true
          resources:
            requests:
              cpu: 250m
          livenessProbe:
            httpGet:
              path: /liveness
              port: 9099
              host: localhost
            periodSeconds: 10
            initialDelaySeconds: 10
            failureThreshold: 6
          readinessProbe:
            exec:
              command:
              - /bin/calico-node
              - -bird-ready
              - -felix-ready
            periodSeconds: 10
          volumeMounts:
            - mountPath: /lib/modules
              name: lib-modules
              readOnly: true
            - mountPath: /run/xtables.lock
              name: xtables-lock
              readOnly: false
            - mountPath: /var/run/calico
              name: var-run-calico
              readOnly: false
            - mountPath: /var/lib/calico
              name: var-lib-calico
              readOnly: false
            - mountPath: /calico-secrets
              name: etcd-certs
      volumes:
        # Used by calico/node.
        - name: lib-modules
          hostPath:
            path: /lib/modules
        - name: var-run-calico
          hostPath:
            path: /var/run/calico
        - name: var-lib-calico
          hostPath:
            path: /var/lib/calico
        - name: xtables-lock
          hostPath:
            path: /run/xtables.lock
            type: FileOrCreate
        # Used to install CNI.
        - name: cni-bin-dir
          hostPath:
            path: /opt/cni/bin
        - name: cni-net-dir
          hostPath:
            path: /etc/cni/net.d
        # Mount in the etcd TLS secrets with mode 400.
        # See https://kubernetes.io/docs/concepts/configuration/secret/
        - name: etcd-certs
          secret:
            secretName: calico-etcd-secrets
            defaultMode: 0400

在该Pod中包括如下两个容器。
◎ install-cni:在Node上安装CNI二进制文件到/opt/cni/bin目录下,并安装相应的网络配置文件到/etc/cni/net.d目录下,设置为initContainers并在运行完成后退出。
◎ calico-node:Calico服务程序,用于设置Pod的网络资源,保证Pod的网络与各Node互联互通。它还需要以hostNetwork模式运行,直接使用宿主机网络。

calico-node服务的主要参数如下:

◎ CALICO_IPV4POOL_CIDR:Calico IPAM的IP地址池,Pod的IP地址将从该池中进行分配。
◎ CALICO_IPV4POOL_IPIP:是否启用IPIP模式。启用IPIP模式时,Calico将在Node上创建一个名为tunl0的虚拟隧道。
◎ IP_AUTODETECTION_METHOD:获取Node IP地址的方式,默认使用第1个网络接口的IP地址,对于安装了多块网卡的Node,可以使用正则表达式选择正确的网卡,例如"interface=ens.*"表示选择名称以ens开头的网卡的IP地址。
◎ FELIX_IPV6SUPPORT:是否启用IPv6。
◎ FELIX_LOGSEVERITYSCREEN:日志级别。
◎ securityContext.privileged=true:以特权模式运行。

另外,如果启用RBAC权限控制,则可以设置ServiceAccount。

     IP Pool可以使用两种模式:BGP或IPIP。使用IPIP模式时,设置CALICO_IPV4POOL_IPIP="always",不使用IPIP模式时,设置CALICO_IPV4POOL_IPIP="off",此时将使用BGP模式。

 

    IPIP是一种将各Node的路由之间做一个tunnel,再把两个网络连接起来的模式,启用IPIP模式时,Calico将在各Node上创建一个名为tunl0的虚拟网络接口。

   BGP模式则直接使用物理机作为虚拟路由器(vRouter),不再创建额外的tunnel。

(4)calico-kube-controllers容器,用于对接Kubernetes集群中为Pod设置的Network Policy:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: calico-kube-controllers
  namespace: kube-system
  labels:
    k8s-app: calico-kube-controllers
spec:
  # The controllers can only have a single active instance.
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      name: calico-kube-controllers
      namespace: kube-system
  namespace: kube-system
  labels:
    k8s-app: calico-kube-controllers
spec:
  # The controllers can only have a single active instance.
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      name: calico-kube-controllers
      namespace: kube-system
      labels:
        k8s-app: calico-kube-controllers
      annotations:
        scheduler.alpha.kubernetes.io/critical-pod: ''
    spec:
      nodeSelector:
        beta.kubernetes.io/os: linux
      # The controllers must run in the host network namespace so that
      # it isn't governed by policy that would prevent it from working.
      hostNetwork: true
      tolerations:
        # Mark the pod as a critical add-on for rescheduling.
        - key: CriticalAddonsOnly
          operator: Exists
        - key: node-role.kubernetes.io/master
          effect: NoSchedule
      serviceAccountName: calico-kube-controllers
      containers:
        - name: calico-kube-controllers
          image: calico/kube-controllers:v3.5.8
          env:
            # The location of the Calico etcd cluster.
            - name: ETCD_ENDPOINTS
              valueFrom:
                configMapKeyRef:
                  name: calico-config
                  key: etcd_endpoints
            # Location of the CA certificate for etcd.
            - name: ETCD_CA_CERT_FILE
              valueFrom:
                configMapKeyRef:
                  name: calico-config
                  key: etcd_ca
            # Location of the client key for etcd.
            - name: ETCD_KEY_FILE
              valueFrom:
                configMapKeyRef:
                  name: calico-config
                  key: etcd_key
            # Location of the client certificate for etcd.
            - name: ETCD_CERT_FILE
              valueFrom:
                configMapKeyRef:
                  name: calico-config
                  key: etcd_cert
            # Choose which controllers to run.
            - name: ENABLED_CONTROLLERS
              value: policy,namespace,serviceaccount,workloadendpoint,node
          volumeMounts:
            # Mount in the etcd TLS secrets.
            - mountPath: /calico-secrets
              name: etcd-certs
          readinessProbe:
            exec:
              command:
              - /usr/bin/check-status
              - -r
      volumes:
        # Mount in the etcd TLS secrets with mode 400.
        # See https://kubernetes.io/docs/concepts/configuration/secret/
        - name: etcd-certs
          secret:
            secretName: calico-etcd-secrets
            defaultMode: 0400

     如果启用RBAC权限控制,则可以设置ServiceAccount。

    用户在Kubernetes集群中设置了Pod的Network Policy之后,calico-kube-controllers就会自动通知各Node上的calico-node服务,在宿主机上设置相应的iptables规则,完成Pod间网络访问策略的设置。

kubecatl apply -f calico.yaml

    确保Calico的个服务正确运行,calico-node在正常运行之后,会根据CNI规范,在/etc/cni/net.d/目录下生成如下文件和目录,并在/opt/cni/bin/目录下安装二进制文件calico和calico-ipam,供kubelet调用。

◎ 10-calico.conf:符合CNI规范的网络配置,其中type=calico表示该插件的二进制文件名为calico。
◎ calico-kubeconfig:Calico所需的kubeconfig文件。
◎ calico-tls目录:以TLS方式连接etcd的相关文件。
查看k8s-node-1服务器的网络接口设置,可以看到一个新的名为tunl0的接口,并设置了网络地址为10.1.109.64/32。

查看k8s-node-2服务器的网络接口设置,同样可以看到一个新的名为tunl0的接口,网络地址为10.1.140.64/32。

     这两个子网都是从calico-node设置的IP地址池(CALICO_IPV4POOL_CIDR="10.1.0.0/16")中进行分配的。同时,docker0对于Kubernetes设置Pod的IP地址将不再起作用。

    查看两台主机的路由表。首先,查看k8s-node-1服务器的路由表,可以看到一条到k8s-node-2的私网10.1.140.64的路由转发规则:

ip route

然后,查看k8s-node-2服务器的路由表,可以看到一条到k8s-node-1的私网10.1.109.64/26的路由转发规则:

ip route

      这样,通过Calico就完成了Node间容器网络的设置。在后续的Pod创建过程中,kubelet将通过CNI接口调用Calico进行Pod网络的设置,包括IP地址、路由规则、iptables规则等。

     如果设置CALICO_IPV4POOL_IPIP="off",即不使用IPIP模式,则Calico将不会创建tunl0网络接口,路由规则直接使用物理机网卡作为路由器进行转发。

     查看k8s-node-1服务器的路由表,可以看到一条到k8s-node-2的私网10.1.140.64的路由转发规则,将通过本机ens33网卡进行转发.

    查看k8s-node-2服务器的路由表,可以看到一条到k8s-node-1的私网10.1.109.64/26的路由转发规则,将通过本机ens33网卡进行转发

3.Calico设置容器IP地址,跨主机容器网络连通性验证

   下面创建几个Pod,验证Calico对它们的网络设置。以mysql和myweb为例。

mysql-rc.yaml

apiVersion: v1
kind: ReplicationController
metadata:
  name: mysql
spec:
  replicas: 1
  selector:
    app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:5.7
        ports:
        - containerPort: 3306
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: "123456"

myweb-rc.yaml

apiVersion: v1
kind: ReplicationController
metadata:
  name: myweb
spec:
  replicas: 2
  selector:
    app: myweb
  template:
    metadata:
      labels:
        app: myweb
    spec:
      containers:
      - name: myweb
        image: kubeguide/tomcat-app:v1
        ports:
        - containerPort: 8080
        env:
        - name: MYSQL_SERVICE_HOST
          value: 'mysql'
        - name: MYSQL_SERVICE_PORT
          value: '3306'
kubectl apply -f mysql-rc.yaml -f myweb-rc.yaml

    查看各Pod的IP地址,可以看到是通过Calico设置的以10.1开头的IP地址。

    进入运行在k8s-node-2上的Pod,在容器内访问运行在k8s-node-1上的Pod“mysql”的IP地址。

ping 10.1.109.71

   在容器内访问物理机k8s-node-1的IP地址192.168.18.3

ping 192.168.18.3

   这说明跨主机容器间、容器与宿主机之间的网络都能互联互通了。

    查看k8s-node-2物理机的网络接口和路由表,可以看到Calico为Pod“myweb-s86sk”新建了一个网络接口cali439924adc43,并为其设置了一条路由规则:

ip addr show

另外,Calico为该网络接口cali439924adc43设置了一系列iptables规则:

iptables -L

4.使用网络策略实现Pod间的访问策略

   下面以一个提供服务的Nginx Pod为例,为两个客户端Pod设置不同的网络访问权限,允许包含Label“role=nginxclient”的Pod访问Nginx容器,不包含该Label的容器则拒绝访问。为了实现这个需求,需要通过以下步骤完成。

(1)创建Nginx Pod,并添加Label“app=nginx”:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels: 
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx

(2)为Nginx设置网络策略,编辑文件networkpolicy-allow-nginxclient.yaml,内容如下。

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: allow-nginxclient
spec:
  podSelector:
    matchLabels:
      app: nginx
  ingress:
    - from:
      - podSelector:
          matchLabels:
            role: nginxclient
    - ports:
      - protocol: TCP
        port: 80

(3)创建两个客户端Pod,一个包含Label“role=nginxclient”,另一个无此Label。分别进入各Pod,访问Nginx容器,验证网络策略的效果。

---
apiVersion:v1
kind: Pod
metadata:
  name: client1
  labels:
    role: nginxclient
spec:
  containers:
  - name: client1
    image: busybox
    command: ["sleep", "3600"]
---
apiVersion:v1
kind: Pod
metadata:
  name: client2
spec:
  containers:
  - name: client2
    image: busybox
    command: ["sleep", "3600"]
---

 

登录Pod“client1”,尝试连接Nginx容器的80端口:成功访问到Nginx的服务,说明NetworkPolicy生效。

带你玩转kubernetes-k8s(第49篇:深入分析k8s网络原理-[直接路由,Calico部署])_第3张图片

登录Pod“client2”,尝试连接Nginx容器的80端口:访问超时,说明NetworkPolicy生效,对没有Label“role=nginxclient”的客户端Pod拒绝访问。

     本例中的网络策略是由calico-kube-controllers具体实现的,calico-kube-controllers持续监听Kubernetes中NetworkPolicy的定义,与各Pod通过Label进行关联,将允许访问或拒绝访问的策略通知到各calico-node服务,最终calico-node完成对Pod间网络访问的设置,实现应用的网络隔离。  

   小结:

          本节内容到此结束,谢谢大家的支持!

你可能感兴趣的:(kubernetes)