前言

我们在内网使用k8s时,有时候需要针对整个集群的节点设置防火墙,阻止一些外部访问,或者是仅允许白名单内的ip访问,传统做法是使用firewall之类的防火墙软件,但是,使用firewall存在如下问题:

  1. firewall针对k8s的nodeport端口设置的防火墙规则不生效
  2. 集群内节点较多时,挨个主机设置防火墙会比较繁琐。

如果集群的节点是托管到云平台上的,可以忽略本文章,直接去云平台设置防火墙策略。

如果我们的k8s插件是calico,可以通过calico的扩展功能来设置整个集群所有节点的防火墙,不会有上面两个问题的困扰。

calico的网络策略

calico网络策略的官方文档是: https://docs.tigera.io/calico/latest/network-policy/get-started/calico-policy/calico-network-policy

想要在安装了calico网络插件的k8s集群里面配置节点防火墙,首先我们需要将节点注册到calico上,在calico这个叫做 Host endpoint, 一个Host endpoint 指的是节点对外的出口,一般是一块网卡,网卡上带有ip地址,我们需要通过声明HostEndpoint来注册。
在声明HostEndpoint时,还可以指定该节点的标签,后期在进行防火墙配置时,可以通过标签来批量配置。

当声明HostEndpoint后,节点的网络策略将由Calico接管,默认的规则是拒绝所有连接。Calico为了防止整个节点的网络瘫痪,默认开放了一些端口,比如22等,后面会详细说明。

声明HostEndpoint

如前所述,我们首先需要声明一个HostEndpoint,下面是声明的Yaml:

apiVersion: projectcalico.org/v3
kind: HostEndpoint
metadata:
  name: node1-eth0
  labels:
    kubernetes-host: ingress
spec:
  interfaceName: eth0
  node: node1
  expectedIPs:
    - INSERT_IP_HERE

这个是全局配置,不需要namespace。
metadata.name是HostEndpoint的名字,一般是节点名-网卡
spec.interfaceName 是节点的网卡名,可以通过 ip addr 或者 ifconfig 等命令查看。
spec.node 是该节点在k8s中的name,可以通过 kubectl get node来查看
spec.expectedIPs 是该网卡的ip,这个是必填项。

下面是一个配置好的样例:

apiVersion: projectcalico.org/v3
kind: HostEndpoint
metadata:
  name: localhost.localdomain-enp0s8
  labels:
    kubernetes-host: ingress
spec:
  interfaceName: enp0s8
  node: localhost.localdomain
  expectedIPs:
    - 192.168.88.5

将上述内容保存到hostendpoint.yaml中执行 kubectl apply -f hostendpoint.yaml创建:

[root@localhost calico]# kubectl apply -f hostendpoint.yaml
hostendpoint.projectcalico.org/localhost.localdomain-enp0s8 created

配置默认开放的端口

接入calico的HostEndpoint默认开放了一些端口,官方清单如下:
https://docs.tigera.io/calico/latest/reference/host-endpoints/failsafe
下面是摘抄:

在这里插入图片描述

如果想要关闭这里面的部分端口,或者默认在所有节点上开放其他端口,可以通过配置 FelixConfiguration来完成,官方文档地址为: https://docs.tigera.io/calico/latest/reference/resources/felixconfig
如果想要修改,可以通过kubectl edit FelixConfiguration default来修改配置,下面是一个样例,默认开放的端口仅保留了22,其他全部删掉了(实际操作过程不要这么做!这里只是为了方便演示,仅仅保留一个)。

apiVersion: projectcalico.org/v3
kind: FelixConfiguration
metadata:
  name: default
spec:
  bpfLogLevel: ""
  floatingIPs: Disabled
  healthPort: 9099
  logSeverityScreen: Info
  reportingInterval: 0s
  failsafeInboundHostPorts:
    - port: 22
      protocol: tcp

开放ip白名单,其他ip默认禁止访问

设置好默认开放的端口后,下一步一般是拒绝其他的ip,仅保留指定的ip可以访问,下面是一个样例:

apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
  name: allow-cluster-internal-ingress-only
spec:
# 生效顺序从小到大排序,后面再增加开放端口的策略时,order < 20, 即可在这之前生效
  order: 20
  preDNAT: true
  applyOnForward: true
  ingress:
  # 首先接受白名单的所有请求
    - action: Allow
      source:
      # source 配置方法可以参考  https://docs.tigera.io/calico/latest/reference/resources/networkpolicy#entityrule
        nets: 
          - 192.168.88.0/24
  # 然后拒绝白名单ip以外的所有请求
    - action: Deny
      source:
      # Deny规则要加上排除白名单的网段,理论上不需要这个,但是遇到过奇怪的BUG,没加上导致把上面开放的ip都Drop掉了
        notNets: 
          - 192.168.88.0/24
  selector: has(kubernetes-host)   # 选择器。选择了包含kubernetes-host标签的所有HostEndpoint

开放指定端口

apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
  name: allow-external-port-ingress
spec:
  order: 10
  preDNAT: true
  applyOnForward: true
  ingress:
  # 放通目标是指定端口的所有请求  当然也可以增加source字段指定来源ip/ip段
    - action: Allow
      destination:
      # 配置方法可以参考  https://docs.tigera.io/calico/latest/reference/resources/networkpolicy#entityrule
        ports:
          - 3306
          - 30030
  selector: has(kubernetes-host)   # 选择器。选择了包含kubernetes-host标签的所有HostEndpoint

注意这里的selector可以给某一两个节点打上特殊标签,选择到指定的一两个节点,给他们开放端口。

更多细节请查阅官方文档,这里仅给出了少量用法,官方支持的功能还是很多的。

修改或查看已有的网络策略/HostEndpoint

查看已有的网络策略:
kubectl get GlobalNetworkPolicy
kubectl describe GlobalNetworkPolicy xxx
修改已有的网络策略
kubectl edit GlobalNetworkPolicy xxx
删除网络策略
kubectl delete GlobalNetworkPolicy xx

HostEndpoint的操作也是一样的,只是把GlobalNetworkPolicy改成HostEndpoint就可以了

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐