乐趣区

关于云计算:使用-Cilium-增强-Kubernetes-网络安全

TL;DR

在本篇,咱们别离应用了 Kubernetes 原生的网络策略和 Cilium 的网络策略实现了 Pod 网络层面的隔离。不同的是,前者只提供了基于 L3/4 的网络策略;后者反对 L3/4、L7 的网络策略。

通过网络策略来晋升网络安全,能够极大升高了实现和保护的老本,同时对系统简直没有影响。

尤其是基于 eBPF 技术的 Cilium,解决了内核扩展性有余的问题,从内核层面为工作负载提供安全可靠、可观测的网络连接。

背景

为什么说 Kubernetes 网络存在安全隐患?集群中的 Pod 默认是未隔离的,也就是 Pod 之间的网络是互通的,能够相互通信的。

这里就会有问题,比方因为数据敏感服务 B 只容许特定的服务 A 能力拜访,而服务 C 无法访问 B。要禁止服务 C 对服务 B 的拜访,能够有几种计划:

  • 在 SDK 中提供通用的解决方案,实现白名单的性能。首先申请要带有起源的标识,而后服务端能够接管规定设置放行特定标识的申请,回绝其余的申请。
  • 云原生的解决方案,应用服务网格的 RBAC、mTLS 性能。RBAC 实现原理与应用层的 SDK 计划相似,然而属于基础设施层的形象通用计划;mTLS 则会更加简单一些,在连贯握手阶段进行身份验证,波及证书的签发、验证等操作。

以上两种计划各有利弊:

  • SDK 的计划实现简略,然而规模较大的零碎会面临降级推广艰难、多语言反对老本低等问题。
  • 服务网格的计划是基础设施层的通用计划,天生反对多语言。然而对于未落地网格的用户来说,架构变动大,老本高。如果单纯为了解决平安问题,应用网格计划性价比又很低,且不说现有网格实现等落地难度大及前期的应用保护老本高。

持续向基础设施上层找计划,从网络层动手。Kubernetes 提供了的网络策略 NetworkPolicy,则能够实现“网络层面的隔离”。

示例利用

在进一步演示 NetworkPolicy 的计划之前,先介绍用于演示的示例利用。咱们应用 Cilium 在互动教程 Cilium getting started 中应用的“星球大战”场景。

这里有三个利用,星战迷预计不会生疏:

  • 死星 deathstar:在 80 端口提供 web 服务,有 2 个 正本,通过 Kubernetes Service 的负载平衡为 帝国战机 对外提供”登陆“服务。
  • 钛战机 tiefighter:执行登陆申请。
  • X 翼战机 xwing:执行登陆申请。

如图所示,咱们应用了 Label 对三个利用进行了标识:orgclass。在执行网络策略时,咱们会应用这两个标签辨认负载。

# app.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: deathstar
  labels:
    app.kubernetes.io/name: deathstar
spec:
  type: ClusterIP
  ports:
  - port: 80
  selector:
    org: empire
    class: deathstar
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deathstar
  labels:
    app.kubernetes.io/name: deathstar
spec:
  replicas: 2
  selector:
    matchLabels:
      org: empire
      class: deathstar
  template:
    metadata:
      labels:
        org: empire
        class: deathstar
        app.kubernetes.io/name: deathstar
    spec:
      containers:
      - name: deathstar
        image: docker.io/cilium/starwars
---
apiVersion: v1
kind: Pod
metadata:
  name: tiefighter
  labels:
    org: empire
    class: tiefighter
    app.kubernetes.io/name: tiefighter
spec:
  containers:
  - name: spaceship
    image: docker.io/tgraf/netperf
---
apiVersion: v1
kind: Pod
metadata:
  name: xwing
  labels:
    app.kubernetes.io/name: xwing
    org: alliance
    class: xwing
spec:
  containers:
  - name: spaceship
    image: docker.io/tgraf/netperf

Kubernetes 网络策略

能够通过官网文档获取更多详细信息,这里咱们间接放出配置:

# native/networkpolicy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      org: empire
      class: deathstar
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          org: empire
    ports:
    - protocol: TCP
      port: 80
  • podSelector:示意要利用网络策略的工作负载平衡,通过 label 抉择到了 deathstar 的 2 个 Pod。
  • policyTypes:示意流量的类型,能够是 IngressEgress 或两者兼具。这里应用 Ingress,示意对抉择的 deathstar Pod 的入站流量执行规定。
  • ingress.from:示意流量的起源工作负载,也是应用 podSelectorLabel 进行抉择,这里选中了 org=empire 也就是所有“帝国的战机”。
  • ingress.ports:示意流量的进入端口,这里列出了 deathstar 的服务端口。

接下来,咱们测试下。

测试

先筹备环境,咱们应用 K3s 作为 Kubernetes 环境。但因为 K3s 默认的 CNI 插件 Flannel 不反对网络策略,咱们须要换个插件,这里抉择 Calico,即 K3s + Calico 的计划。

先创立一个单节点的集群:

curl -sfL https://get.k3s.io | K3S_KUBECONFIG_MODE="644" INSTALL_K3S_EXEC="--flannel-backend=none --cluster-cidr=10.42.0.0/16 --disable-network-policy --disable=traefik" sh -

此时,所有的 Pod 都处于 Pending 状态,因为还须要装置 Calico:

kubectl apply -f https://projectcalico.docs.tigera.io/manifests/calico.yaml

待 Calico 胜利运行后,所有的 Pod 也会胜利运行。

接下来就是部署利用:

kubectl apply -f app.yaml

执行策略前,执行上面的命令看看“战机是否登陆死星”:

kubectl exec tiefighter -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing
Ship landed

kubectl exec xwing -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing
Ship landed

从后果来看,两种”战机“(Pod 负载)都能够拜访 deathstar 服务。

此时执行网络策略:

kubectl apply -f native/networkpolicy.yaml

再次尝试”登陆“,xwing 的登陆申请会停在那(须要应用 ctrl+c 退出,或者申请时加上 --connect-timeout 2)。

思考

应用 Kubernetes 网络策略实现了咱们想要的,从网络层面为服务减少了白名单的性能,这种计划没有革新老本,对系统也简直无影响。

Cilium 还没出场就完结了?咱们持续看:

有时咱们的服务会对外裸露一些治理端点,由零碎调用执行一些治理上的操作,比方热更新、重启等。这些端点是不容许一般服务来调用,否则会造成重大的结果。

比方示例中,tiefighter 拜访了 deathstar 的治理端点 /exhaust-port

kubectl exec tiefighter -- curl -s -XPUT deathstar.default.svc.cluster.local/v1/exhaust-port
Panic: deathstar exploded

goroutine 1 [running]:
main.HandleGarbage(0x2080c3f50, 0x2, 0x4, 0x425c0, 0x5, 0xa)
        /code/src/github.com/empire/deathstar/
        temp/main.go:9 +0x64
main.main()
        /code/src/github.com/empire/deathstar/
        temp/main.go:5 +0x85

呈现了 Panic 谬误,查看 Pod 你会发现 dealthstar 挂了。

Kubernetes 的网络策略仅能工作在 L3/4 层,对 L7 层就无能为力了。

还是要请出 Cilium。

Cilium 网络策略

因为 Cilium 波及了 Linux 内核、网络等泛滥知识点,要讲清实现原理篇幅极大。故这里仅摘取了官网的介绍,前期心愿有工夫再写一篇对于实现的。

Cilium 简介

Cilium 是一个开源软件,用于提供、爱护和察看容器工作负载(云原生)之间的网络连接,由革命性的内核技术 eBPF 推动。

eBPF 是什么?

Linux 内核始终是实现监控 / 可观测性、网络和平安性能的现实中央。不过很多状况下这并非易事,因为这些工作须要批改内核源码或加载内核模块,最终实现模式是在已有的层层形象之上叠加新的形象。eBPF 是一项革命性技术,它能在内核中运行沙箱程序(sandbox programs),而无需批改内核源码或者加载内核模块。

将 Linux 内核变成可编程之后,就能基于现有的(而非减少新的)形象层来打造更加智能、性能更加丰盛的基础设施软件,而不会减少零碎的复杂度,也不会就义执行效率和安全性。

咱们来看下 Cilium 的网络策略:

# cilium/networkpolicy-L4.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "rule1"
spec:
  description: "L7 policy to restrict access to specific HTTP call"
  endpointSelector:
    matchLabels:
      org: empire
      class: deathstar
  ingress:
  - fromEndpoints:
    - matchLabels:
        org: empire
    toPorts:
    - ports:
      - port: "80"
        protocol: TCP

与 Kubernetes 的原生网络策略差别不大,参考后面的介绍也都看懂,咱们间接进入测试。

测试

因为 Cilium 自身就实现了 CNI,所以之前的集群就不能用了,先卸载集群:

k3s-uninstall.sh
#!!!切记要清理之前的 cni 插件
sudo rm -rf /etc/cni/net.d

还是应用同样的命令创立单节点的集群:

curl -sfL https://get.k3s.io | K3S_KUBECONFIG_MODE="644" INSTALL_K3S_EXEC="--flannel-backend=none --cluster-cidr=10.42.0.0/16 --disable-network-policy --disable=traefik" sh -

# cilium 会应用该变量
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml

接下来装置 Cilium CLI:

curl -L --remote-name-all https://github.com/cilium/cilium-cli/releases/latest/download/cilium-linux-amd64.tar.gz{,.sha256sum}
sha256sum --check cilium-linux-amd64.tar.gz.sha256sum
sudo tar xzvfC cilium-linux-amd64.tar.gz /usr/local/bin
rm cilium-linux-amd64.tar.gz{,.sha256sum}

cilium version
cilium-cli: v0.10.2 compiled with go1.17.6 on linux/amd64
cilium image (default): v1.11.1
cilium image (stable): v1.11.1
cilium image (running): unknown. Unable to obtain cilium version, no cilium pods found in namespace "kube-system"

装置 Cilium 到集群:

cilium install

待 Cilium 胜利运行:

cilium status
    /¯¯\
 /¯¯\__/¯¯\    Cilium:         OK
 \__/¯¯\__/    Operator:       OK
 /¯¯\__/¯¯\    Hubble:         disabled
 \__/¯¯\__/    ClusterMesh:    disabled
    \__/

Deployment        cilium-operator    Desired: 1, Ready: 1/1, Available: 1/1
DaemonSet         cilium             Desired: 1, Ready: 1/1, Available: 1/1
Containers:       cilium             Running: 1
                  cilium-operator    Running: 1
Cluster Pods:     3/3 managed by Cilium
Image versions    cilium-operator    quay.io/cilium/operator-generic:v1.11.1@sha256:977240a4783c7be821e215ead515da3093a10f4a7baea9f803511a2c2b44a235: 1
                  cilium             quay.io/cilium/cilium:v1.11.1@sha256:251ff274acf22fd2067b29a31e9fda94253d2961c061577203621583d7e85bd2: 1

部署利用:

kubectl apply -f app.yaml

待利用启动后测试服务调用:

kubectl exec tiefighter -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing
Ship landed
kubectl exec xwing -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing
Ship landed

执行 L4 网络策略:

kubectl apply -f cilium/networkpolicy-L4.yaml

再次尝试“登陆”死星,xwing 战机同样无奈登陆,阐明 L4 层的规定失效。

咱们再尝试 L7 层的规定:

# cilium/networkpolicy-L7.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "rule1"
spec:
  description: "L7 policy to restrict access to specific HTTP call"
  endpointSelector:
    matchLabels:
      org: empire
      class: deathstar
  ingress:
  - fromEndpoints:
    - matchLabels:
        org: empire
    toPorts:
    - ports:
      - port: "80"
        protocol: TCP
      rules:
        http:
        - method: "POST"
          path: "/v1/request-landing"

执行规定:

kubectl apply -f cilium/networkpolicy-L7.yaml

这回,应用 tiefighter 调用死星的治理接口:

kubectl exec tiefighter -- curl -s -XPUT deathstar.default.svc.cluster.local/v1/exhaust-port
Access denied
# 登陆接口工作失常
kubectl exec tiefighter -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing
Ship landed

这回返回了 Access denied,阐明 L7 层的规定失效了。

文章对立公布在公众号 云原生指北

退出移动版