在本文中,我们将学习如何使用Calico CNI网络策略构建防火墙功能,来保护Kubernetes集群中的主机。
Kubernetes集群的管理员希望保护其免受集群外部流量的侵害。Calico是一个容器网络接口(CNI)插件,除CNI功能外,还提供网络策略来控制Pod之间的流量以及防火墙功能以保护节点。
为了利用Calico作为防火墙的功能来保护节点,需要基于Calico的GlobalNetworkPolicy在节点上的每个网络接口创建一个HostEndpoint。这是一项一次性工作,可以在安装程序中自动进行。由于节点是短暂的,并且策略可以是动态的,因此即使在安装后,我们也需要一种方法来管理每个主机上的HostEndpoint对象。
有多种Kubernetes方法来完成此任务,例如,
- 在每个节点上创建并运行所需的DaemonSet
- 在每个节点上创建并运行所需的静态Pod
- Kubernetes Operator确保集群中所有节点都创建了HostEndpoint对象
在Kubernetes之外,传统的端点保护方法包括在主机上安装代理,并通过该代理实施策略。
与DaemonSet不同,静态Pod无法通过kubectl或其他Kubernetes API客户端来管理。DaemonSet确保Pod的副本始终在所有或某些主机上运行,并在其他Pod之前开始。本文,我们将使用DaemonSet方式。
DaemonSet解决方案概述
提出的解决方案包括创建一个DaemonSet,它将为每个主机启动一个Pod。如果需要,该Pod将运行一个应用程序来为该主机创建HostEndpoint对象。
例如,我们决定使用HostEndpoint对象实施以下示例策略:
- 允许来自节点的所有出口流量。
- 允许从特定IP地址访问所有节点的入口流量。
- 拒绝任何其他流量。
步骤如下:
- 创建应用程序
- 创建一个Docker镜像
- 创建一个DaemonSet
- 创建网络策略
创建应用程序
我们将使用Shell脚本编写应用程序。该脚本无限循环,并检查是否为运行它的主机创建了HostEndpoint对象。如果不是,它将使用kubectl客户端为满足需求的主机创建HostEndpoint对象。如果主机已经存在HostEndpoint对象,则它将休眠10秒钟,然后再继续。
请注意,节点的名称是通过环境变量注入到脚本中的。节点名称是使用Downward API获取的,该API允许容器使用有关其自身或Kubernetes集群的信息。
#!/bin/sh while [ true ]; do echo $NODE_NAME kubectl get hostendpoint $NODE_NAME if [ $? -eq 0 ]; then echo "Found hep for node $NODE_NAME" sleep 10 continue fi echo "Creating hep for node $NODE_NAME" kubectl apply -f - <<EOF apiVersion: crd.projectcalico.org/v1 kind: HostEndpoint metadata: name: $NODE_NAME labels: host-endpoint: ingress spec: interfaceName: "*" node: "$NODE_NAME" EOF done
网络策略适用于所有带有host-endpoint标签的主机。稍后创建的网络策略将检查主机是否具有此标签。
创建一个Docker镜像
要将你的应用程序部署到Kubernetes,我们首先必须对其进行容器化。为此,创建以下Dockerfile:
FROM alpine WORKDIR /app ADD https://storage.googleapis.com/kubernetes-release/release/v1.17.0/bin/linux/amd64/kubectl /usr/local/bin ADD run.sh /app RUN chmod +x /usr/local/bin/kubectl RUN chmod +x /app/run.sh CMD [ "/app/run.sh" ]
我们使用Alpine作为基本镜像,因为它是最小的Linux发行版,允许我们运行Shell脚本。为了与Kubernetes API服务器对话,我们在Docker镜像中包括了kubectl,并添加了创建的脚本。容器启动时,将执行脚本。
构建Docker镜像并将其推送到可从Kubernetes集群中的所有节点访问的Docker镜像仓库中。
docker build -t randhirkumars/hepinstall:v1 . docker push randhirkumars/hepinstall:v1
如果需要凭据来推送镜像,我们将需要登录Docker镜像仓库。
创建网络策略
Calico的GlobalNetworkPolicy和HostEndpoint对象可用作自定义对象。我们需要首先创建相应的CustomResourceDefinition(CRD)。
GlobalNetworkPolicy的CRD对象:
apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: name: globalnetworkpolicies.crd.projectcalico.org spec: scope: Cluster group: crd.projectcalico.org version: v1 names: kind: GlobalNetworkPolicy plural: globalnetworkpolicies singular: globalnetworkpolicy
HostEndpoint的CRD对象:
apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: name: hostendpoints.crd.projectcalico.org spec: scope: Cluster group: crd.projectcalico.org version: v1 names: kind: HostEndpoint plural: hostendpoints singular: hostendpoint
kubectl create -f crds.yaml
接下来创建网络策略
- 允许来自节点的所有出口流量。
apiVersion: projectcalico.org/v3 kind: GlobalNetworkPolicy metadata: name: allow-outbound-external spec: order: 10 egress: - action: Allow selector: has(host-endpoint)
- 允许从特定IP地址访问所有节点。在此,允许来自CIDR的入口流量-[10.240.0.0/16,192.168.0.0/16]。
apiVersion: projectcalico.org/v3 kind: GlobalNetworkPolicy metadata: name: allow-cluster-internal-ingress spec: order: 10 preDNAT: true applyOnForward: true ingress: - action: Allow source: nets: [10.240.0.0/16, 192.168.0.0/16] selector: has(host-endpoint)
- 拒绝任何其他流量。
apiVersion: projectcalico.org/v3 kind: GlobalNetworkPolicy metadata: name: drop-other-ingress spec: order: 20 preDNAT: true applyOnForward: true ingress: - action: Deny selector: has(host-endpoint)
订单字段在这里很重要。该drop-other-ingress策略具有比更高的订单值allow-cluster-internal-ingress,因此它在之后生效allow-cluster-internal-ingress。
kubectl create -f policy.yaml
创建一个DaemonSet
除了Docker镜像之外,要在Kubernetes集群上部署我们的应用程序,我们还需要创建一些资源对象。
- 运行Docker镜像的Pod
- 监视Pod的控制平面对象,在本例中为DaemonSet
- 用于Pod运行的Service Account
- Cluster Role资源对象,允许Pod与API服务器进行资源交互
- Cluster Role Binding资源对象,用于将Cluster Role Binding到Service Account
Service Account
Pod使用的Service Account。
apiVersion: v1 kind: ServiceAccount metadata: name: hep-sa
Cluster Role
我们需要RBAC在API服务器上操作HostEndpoint对象。
我们已经从相应的API组中,申请了对HostEndpoint对象执行的所有操作。
kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: hep-cr rules: - apiGroups: ["crd.projectcalico.org"] resources: - hostendpoints verbs: - create - get - list - update - watch
Cluster Role Binding
接下来,我们需要将该角色绑定到Service Account,从而为Pod提供权限。
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: hep-crb roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: hep-cr subjects: - kind: ServiceAccount name: hep-sa namespace: default
Pod和DaemonSet
最后,创建一个DaemonSet对象,该对象将使用所需的Service Account创建一个Pod。主机名作为环境变量注入到容器中。最好不要以root账户运行容器。在这里,我们使用非root帐户运行容器。
apiVersion: apps/v1 kind: DaemonSet metadata: name: hep-ds labels: spec: selector: matchLabels: name: hep-ds template: metadata: labels: name: hep-ds spec: serviceAccountName: hep-sa containers: - image: randhirkumars/hepinstall:v1 imagePullPolicy: Always name: hep-install env: - name: NODE_NAME valueFrom: fieldRef: fieldPath: spec.nodeName securityContext: runAsUser: 1337
创建所有对象。
> kubectl apply -f hep.yaml serviceaccount/hep-sa created clusterrole.rbac.authorization.k8s.io/hep-cr created clusterrolebinding.rbac.authorization.k8s.io/hep-crb created daemonset.apps/hep-ds created > kubectl get po NAME READY STATUS RESTARTS AGE hep-ds-9jjtq 1/1 Running 0 2s hep-ds-c97jz 1/1 Running 0 2s hep-ds-fbghm 1/1 Running 0 2s hep-ds-nbllb 1/1 Running 0 2s
检查Pod的日志,以确保其正在为该节点创建HostEndpoint。
> kubectl logs hep-ds-9jjtq k8s-node-2 Error from server (NotFound): hostendpoints.crd.projectcalico.org "k8s-node-2" not found Creating hep for node k8s-node-2 hostendpoint.crd.projectcalico.org/k8s-node-2 created k8s-node-2 NAME AGE k8s-node-2 0s Found hep for node k8s-node-2 k8s-node-2 NAME AGE k8s-node-2 8s Found hep for node k8s-node-2
验证是否为每个节点创建了HostEndpoint。
> kubectl get hostendpoint NAME AGE k8s-master-nf-1 36s k8s-master-nf-2 39s k8s-master-nf-3 36s k8s-node-1 38s k8s-node-2 36s
结论
Kubernetes不提供防火墙功能来保护Kubernetes集群中的主机。我们使用Calico来实现。Calico除了CNI功能之外,它还提供网络策略来控制Pod之间的流量以及防火墙功能以保护节点。该解决方案是Kubernetes原生的,不需要安装任何外部软件。
译文链接:https://dzone.com/articles/protecting-hosts-in-kubernetes-cluster
登录后评论
立即登录 注册