我们知道,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,将数据传输过去。
我们在每个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为例讲解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的系统架构如下图所示:
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生效。
登录Pod“client2”,尝试连接Nginx容器的80端口:访问超时,说明NetworkPolicy生效,对没有Label“role=nginxclient”的客户端Pod拒绝访问。
本例中的网络策略是由calico-kube-controllers具体实现的,calico-kube-controllers持续监听Kubernetes中NetworkPolicy的定义,与各Pod通过Label进行关联,将允许访问或拒绝访问的策略通知到各calico-node服务,最终calico-node完成对Pod间网络访问的设置,实现应用的网络隔离。
小结:
本节内容到此结束,谢谢大家的支持!