K8s中非root用户修改MAC地址

因业务需要,程序要修改MAC地址,并且开关K8s中Pod的网络。 虽然root用户可以轻松实现这一点,但考虑到安全因素,更应该使用普通用户。

通过使用Linux的Capabilities功能,对/bin/ip进行cap_net_admin授权,可以实现MAC修改功能。

注意:K8s集群中,Pod的网络是否可开关,取决于网络插件。 已知flannel可以,calico不行。 以下涉及K8s的内容,都只在flannel下确保生效。

基本操作

安装

虽然ip这个命令,通常会默认安装。 但如果实在没有,就需要手动安装。

sudo apt install iproute2

基本网络操作

关闭名称为<name>的网络:

sudo ip link set dev <name> down

修改Mac,格式应该满足XX:XX:XX:XX:XX:XX

sudo ip link set dev <name> address XX:XX:XX:XX:XX:XX

打开网络:

sudo ip link set dev <name> up

查看新的MAC地址:

ip link show <name>

基本capabilities

添加cap_net_admin

sudo setcap cap_net_admin+ep /bin/ip

查看:

$ getcap /bin/ip
/bin/ip = cap_net_admin+ep

删除所有:

sudo setcap -r /bin/ip

容器验证

在容器中,无论是Docker还是Kubernetes都对Capabilities做出了限定。 除了配置setcap外,还需要在运行时额外赋予权限。

Docker

基于以下Dockerfile,可以制作验证镜像cap:latest

FROM debian:bullseye

RUN useradd -m octopus -s /bin/bash \
    && setcap cap_net_admin+ep /bin/ip

USER octopus
CMD ["/bin/ip", "link", "show"]

构建完成后,在默认模式下运行,仍然会缺少授权。

$ docker build -t cap .
$ docker run --rm cap
standard_init_linux.go:219: exec user process caused: operation not permitted

这是因为Docker在运行时对Capabilities做了限制。 需要使用--cap-add参数,放开具体的限制。

$ docker run --rm --cap-add=cap_net_admin cap
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ipip 0.0.0.0 brd 0.0.0.0
43: eth0@if44: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default 
    link/ether 01:xx:xx:xx:xx:ef brd ff:ff:ff:ff:ff:ff link-netnsid 0

以上MAC地址01:xx:xx:xx:xx:ef做了匿名化处理。

Kubernetes

在Kubernetes中,虽然共用了同一个镜像,但是却是使用不同的runtime。 因此配置方式会略有不同。 以下是一个可以运行的job.yaml示例。

---
apiVersion: batch/v1
kind: Job
metadata:
  name: cap
spec:
  backoffLimit: 0
  template:
    spec:
      activeDeadlineSeconds: 300
      restartPolicy: Never
      containers:
        - name: cap
          image: cap
          imagePullPolicy: IfNotPresent
          securityContext:
            capabilities:
              add: ["NET_ADMIN"]
          args:
            - 'sh'
            - '-c'
            - >
              /bin/ip link show eth0;
              /bin/ip link set dev eth0 down;
              /bin/ip link set dev eth0 address 01:xx:xx:xx:xx:ef;
              /bin/ip link show eth0;
              /bin/ip link set dev eth0 up;
              /bin/ip link show eth0;

执行kubectl apply -f job.yaml后,等待运行完成。 通过日志,可以确认修改生效。

结论

以上方案,无需root权限,最小化授权,安全可信。 但是,开关网络、改变MAC等功能,只在部分网络插件下有效,比如flannel。

另外,充分利用Linux本身的Capability能力,可以让很多其它root才能做的的功能,在普通用户、用指定可执行二进制文件实现。

参考


相关笔记