二十二、K8s集群设置4-网络策略与校验和

一、集群环境

在这里插入图片描述
底层系统为ubuntu18.04,然后在每个node上安装k8s,并构建集群。Master node的IP地址为192.168.26.71/24,两个Worker node的IP地址为192.168.26.72/24、192.168.26.73/24。部署Calico网络插件,保证Node之间能够正常通信。

二、部署网络策略

Network Policy是kubernetes中的一种资源类型,可以理解为一个简单的防火墙,它从属于某个Namespace。其内容从逻辑上看包含两个关键部分,一是pod选择器,基于标签选择相同Namespace下的pod,将其中定义的规则作用于选中的pod。另一个就是规则了,就是网络流量进出pod的规则,其采用的是白名单模式,符合规则的通过,不符合规则的拒绝。

注:相对于网络策略,istio能够做到更细致的网络访问控制。

步骤1:实验环境规划
在这里插入图片描述
在我们集群中设置另外一个NameSpace,testns。然后在default的ns中创建2个nginx的pod,和对应的SVC。同时分别使用busybox镜像在两个NS内创建两个testpod。后续,当我们部署网络策略后,可以使用两个testpod来访问pod1和pod2,验证网络策略是否生效。

步骤2:安装metallb服务,以提供网络负载平衡器(Loadbalance)类型的SVC

官网安装步骤:https://metallb.universe.tf/installation/

首先在master上创建命名空间:

kubectl create ns metallb-system

在官网安装步奏中有最新版本的yaml文件。下载metallb.yaml文件,v0.11.0下载地址如下:
https://raw.githubusercontent.com/metallb/metallb/v0.11.0/manifests/metallb.yaml

修改metallb.yaml文件中两个镜像拉取的策略为IfNotPresent。然后再集群环境(所有Node)中下载需要使用的两个镜像:

root@vms71:~/route-policy# grep image metallb.yaml
        image: quay.io/metallb/speaker:v0.11.0
        imagePullPolicy: IfNotPresent
        image: quay.io/metallb/controller:v0.11.0
        imagePullPolicy: IfNotPresent

部署metallb:

 kubectl apply -f metallb.yaml

使用如下yaml文件创建Loadbalance的地址池,下载地址:https://metallb.universe.tf/configuration/。地址池需要和自己Node在同一网段。

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 192.168.26.240-192.168.26.250

步骤3:部署测试使用的pod和loadbalance类型的SVC

在master上创建测试使用的NameSpace:

kubectl create ns TestNs

在集群设备中下载所需的Nginx和yauritux/busybox-curl镜像:

 docker pull nginx
 docker pull yauritux/busybox-curl

在default namespace中创建pod1和pod2,yaml文件分别如下:

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: pod1
  name: pod1
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: pod1
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: pod2
  name: pod2
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: pod2
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

修改pod1主页为11111:

kubectl exec -it pod1 -- sh -c "echo 11111 > /usr/share/nginx/html/index.html"

pod2主页为22222:

kubectl exec -it pod1 -- sh -c "echo 22222 > /usr/share/nginx/html/index.html"

查看pod1和pod2是否正常运行:

root@vms71:~/route-policy# kubectl get  pods -owide
NAME   READY   STATUS    RESTARTS   AGE   IP             NODE            NOMINATED NODE   READINESS GATES
pod1   1/1     Running   0          20m   10.244.5.205   vms72.rhce.cc   <none>           <none>
pod2   1/1     Running   0          20m   10.244.5.204   vms72.rhce.cc   <none>           <none>

创建Loadbalance类型的svc1和svc2:

 kubectl expose --name=svc1 pod pod1 --port=80 --type=LoadBalancer
 kubectl expose --name=svc2 pod pod2 --port=80 --type=LoadBalancer

查看是否创建成功,获取到地址:

root@vms71:~/route-policy# kubectl get svc
NAME         TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)        AGE
kubernetes   ClusterIP      10.96.0.1        <none>           443/TCP        10d
svc1         LoadBalancer   10.101.126.242   192.168.26.240   80:31482/TCP   2m34s
svc2         LoadBalancer   10.105.233.117   192.168.26.241   80:31075/TCP   2m25s
root@vms71:~/route-policy# curl 192.168.26.240
11111
root@vms71:~/route-policy# curl 192.168.26.241
22222

创建Namespac:testns:

kubectl create ns testns

分别在两个Namespace中创建2个testpod1和testpod2:

kubectl run testpod1 --image=yauritux/busybox-curl -it --rm --image-pull-policy=IfNotPresent -- sh
kubectl run testpod2 -n=testns --image=yauritux/busybox-curl -it --rm --image-pull-policy=IfNotPresent -- sh

测试目前两个testpod是否能够访问pod1和pod2:结果是都可以访问。注意,如果访问不同NameSpace中的SVC,需要在后面指明具体的NameSpace。

/home # curl svc1.default
11111
/home # curl svc2.default
22222

步骤4:创建并测试网络策略

在应用网络策略时需要注意三点:

  1. 应用到哪个pod上去,也就是去保护哪一个pod;
  2. 需要设置允许哪些客户端能访问被保护的pod;
  3. 设置保护的pod能够访问哪些客户端。

在官方网站上可以找到网络策略的模板:https://kubernetes.io/docs/concepts/services-networking/network-policies/。策略的模板同时激活了Ingress和Egress策略。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6379
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 5978

网络策略首先需要设定作用的Namespace:

  namespace: default

其中的podSelector表示作用于namespace中的哪个pod,使用标签的方式进行匹配。如果不写的话,表示作用于namespace中的所有pods。

  podSelector:
    matchLabels:
      role: db

policyType有两种,分别表示匹配入方向或者出方向的流量(以被保护的pod为基础),只有在这里激活了对应的type,后续设置的策略才会生效。

  policyTypes:
  - Ingress
  - Egress

以其中演示的ingress策略为例子(允许谁能够访问被保护的pod):

 ingress:
  - from:
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6379

其中有三种设置策略的方式:

  1. ipBlock:匹配到的IP地址可以访问,except匹配到的无法访问 ;注意, 这些应该是集群外部 IP,因为 Pod IP存在时间短暂的且随机产生。例如,所作用的源IP则可能是LoadBalancer或Pod的node等。
  2. podSelector:指定匹配到label的pod能够访问被保护的pod;
  3. namespaceSelector:指定具体命名空间内的pod能够访问被保护的pod。

注意,在 from 数组中仅包含一个元素,只允许来自标有 role=client 的 Pod 该 Pod 所在的NameSpace中标有 user=alice 的连接。如下:

  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          user: alice
      podSelector:
        matchLabels:
          role: client

在 from 数组中包含两个元素,允许来自本地NameSpace标有 role=client 的 Pod 的连接(默认为本NameSpace,也就是此策略所在的NameSpace), 来自任何名字空间中标有 user=alice 的任何Pod的连接:

  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          user: alice
    - podSelector:
        matchLabels:
          role: client

egress规则同理。

策略一:在pod1上启用ingress的policy,保证只有192.168.26.0/24且非192.168.26.71/32(master地址)能够访问。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      run: pod1
  policyTypes:
  - Ingress
  ingress:
  - from:
    - ipBlock:
        cidr: 192.168.26.0/24
        except:
        - 192.168.26.71/32
    ports:
    - protocol: TCP
      port: 80

在master和worker上分别做测试:

root@vms71:~/route-policy# curl 192.168.26.240
^Z
[1]+  Stopped                 curl 192.168.26.240
root@vms72:~# curl 192.168.26.240
11111

测试结果可以看到,master无法访问当前的pod1。

策略二:在pod1上启用ingress的policy,保证只有当前NameSpace的pod能够访问。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      run: pod1
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: default #default空间的lable
    ports:
    - protocol: TCP
      port: 80

如果不写NameSpace的Labels的标签,表示的是任意NameSpace。分别用testpod1和testpod2进行访问。

testpod1上,可以正常访问:

/home # curl svc1
11111

testpod2上,不可以正常访问:

/home # curl svc1.default
curl: (7) Failed connect to svc1.default:80; Connection timed out

如果NameSpace写成如下的形式,则表示所有的NameSpace都可以访问

    - namespaceSelector:
        matchLabels:

策略三:在testpod2上启用egress的policy,保证只能够访问default空间内的pod2。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: testns
spec:
  podSelector:
    matchLabels:
      run: testpod2
  policyTypes:
  - Egress
  egress:
  - to:
    - podSelector:
        matchLabels:
          run: pod2
      namespaceSelector:
        matchLabels:
           kubernetes.io/metadata.name: default
    ports:
    - protocol: TCP
      port: 80
  - to:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: kube-system
    ports:
    - protocol: UDP
      port: 53

注意写第二个-to策略(每个-to策略之间的关系为或)放行去往kube-system的流量DNS流量。在testpod2中,测试结果如下,说明网络策略运行正常。

/home # curl svc2.default
22222
/home # curl svc1.default
curl: (7) Failed connect to svc1.default:80; Connection timed out

策略四:如果想要保证testpod1能够访问pod1的80端口,testpod2能够访问pod1的8080端口,可以通过写两个from完成。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      run: pod1
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          run: testpod1
    ports:
    - protocol: TCP
      port: 80
  - from:
    - podSelector:
        matchLabels:
          run: testpod2
      namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: testns
    ports:
    - protocol: TCP
      port: 8080

步骤5:默认策略
默认情况下,如果名字空间中不存在任何策略,则所有进出该名字空间(NameSpace)中 Pod 的流量都被允许。 以下示例使我们可以更改该名字空间中的默认行为。(注意仅作用于策略所在的NameSpace)

1.默认拒绝所有入站流量:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
spec:
  podSelector: {}
  policyTypes:
  - Ingress

这样可以确保即使容器没有选择其他任何 NetworkPolicy,也仍然可以被隔离。 此策略不会更改默认的出口隔离行为。

2.默认允许所有入站流量:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-ingress
spec:
  podSelector: {}
  ingress:
  - {}
  policyTypes:
  - Ingress

如果要允许所有流量进入某个名字空间中的所有 Pod(即使添加了导致某些 Pod 被视为 “隔离”的策略),则可以创建一个策略来明确允许该名字空间中的所有流量。

3.默认拒绝所有出站流量:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-egress
spec:
  podSelector: {}
  policyTypes:
  - Egress

此策略可以确保即使没有被其他任何 NetworkPolicy 选择的 Pod 也不会被允许流出流量。 此策略不会更改默认的入站流量隔离行为。

4.默认允许所有出站流量:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-egress
spec:
  podSelector: {}
  egress:
  - {}
  policyTypes:
  - Egress

如果要允许来自名字空间中所有 Pod 的所有流量(即使添加了导致某些 Pod 被视为“隔离”的策略), 则可以创建一个策略,该策略明确允许该名字空间中的所有出站流量。

5.默认拒绝所有入口和所有出站流量:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

我们以通过在该名字空间中创建以下 NetworkPolicy 来阻止所有入站和出站流量。此策略可以确保即使没有被其他任何 NetworkPolicy 选择的 Pod 也不会被允许入站或出站流量。

三、校验和

为了保证k8s中流量传输过程中没有被更改或者出现传输错误,我们可以使用校验和来检查。

一般来说,当我们下载文件时,在下载页面都附有对应正确的校验和值和所使用的HASH函数。我们当下载完成后,我们可以在Linux系统上重新计算校验和来对比是否有修改。

例如,我们可以使用Linux自带的MD5或者SHA校验软件来校验:

root@vms71:~/route-policy# md5sum metallb.yaml
6313083a000cfeae5403b8bcf96cc7f5  metallb.yaml
root@vms71:~/route-policy# sha512sum metallb.yaml
6ebc53703d23841fe805f2d329da95bc3a4af442eed3823f70c0a6ba9d298e85f8c3f25f0cdea2057d819d7737834a369f4267c597a834913b9c4f91a108b5ff  metallb.yaml

如果和官网显示的校验值不同,则删除掉内容被修改或传输出错的文件。

整理资料来源:
《老段CKS课程》
K8s官网资料:https://kubernetes.io/zh/docs/concepts/services-networking/network-policies/

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

格洛米爱学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值