helm3 在端口 80(hostNetwork)上安装 traefik 的权限问题

Permission problem w/ helm3 installation of traefik on port 80 (hostNetwork)

我正在研究 helm3 和 k8s (microk8s)。 在尝试以下命令时:

helm install traefik traefik/traefik  -n traefik --values traefik-values.yaml

和 traefik-values.yaml 具有以下值:

additionalArguments:
  - "--certificatesresolvers.letsencrypt.acme.email=<my-email>"
  - "--certificatesresolvers.letsencrypt.acme.storage=/data/acme.json"
  - "--certificatesresolvers.letsencrypt.acme.caserver=https://acme-v02.api.letsencrypt.org/directory"
  - "--certificatesResolvers.letsencrypt.acme.tlschallenge=true"
  - "--api.insecure=true"
  - "--accesslog=true"
  - "--log.level=INFO"
hostNetwork: true
ipaddress: <my-ip>
service:
  type: ClusterIP
ports:
  web:
    port: 80
  websecure:
    port: 443

我收到此绑定权限错误

traefik.go:76: command traefik error: error while building entryPoint web: error preparing server: error opening listener: listen tcp :80: bind: permission denied

另一方面,我可以使用以下 yaml 文件(大约是 Traefik's site 上的示例)在相同的端口(80 和 443)上安装 Traefik:

---
apiVersion: v1
kind: Namespace
metadata:
  name: traefik
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: traefik-ingress-controller
  namespace: traefik
---
kind: DaemonSet
apiVersion: apps/v1
metadata:
  name: traefik-ingress-controller
  namespace: traefik
  labels:
    k8s-app: traefik-ingress-lb
spec:
  selector:
    matchLabels:
      k8s-app: traefik-ingress-lb
      name: traefik-ingress-lb
  template:
    metadata:
      labels:
        k8s-app: traefik-ingress-lb
        name: traefik-ingress-lb
    spec:
      tolerations:
      - effect: NoSchedule
        operator: Exists
      serviceAccountName: traefik-ingress-controller
      terminationGracePeriodSeconds: 60
      hostNetwork: true
      containers:
      - image: traefik:2.4
        name: traefik-ingress-lb
        ports:
        - name: http
          containerPort: 80
          hostPort: 80
        # - name: admin
        #   containerPort: 8080
        #   hostPort: 8080
        securityContext:
          capabilities:
            drop:
            - ALL
            add:
            - NET_BIND_SERVICE
        args:
        - --providers.kubernetesingress=true
        # you need to manually set this IP to the incoming public IP
        # that your ingress resources would use. Note it only affects
        # status and kubectl UI, and doesn't really do anything
        # It could even be left out https://github.com/containous/traefik/issues/6303
        - --providers.kubernetesingress.ingressendpoint.ip=<my-server-ip>
        ## uncomment these and the ports above and below to enable
        ## the web UI on the host NIC port 8080 in **insecure** mode
        - --api.dashboard=true
        - --api.insecure=true
        - --log=true
        - --log.level=INFO
        - --accesslog=true
        - --entrypoints.web.address=:80
        - --entrypoints.websecure.address=:443
        - --certificatesresolvers.leresolver.acme.tlschallenge=true # <== Enable TLS-ALPN-01 to generate and renew ACME certs
        - --certificatesresolvers.leresolver.acme.email=<email> # <== Setting email for certs
        - --certificatesresolvers.leresolver.acme.storage=/data/acme.json # <== Defining acme file to store cert information
        
---
kind: Service
apiVersion: v1
metadata:
  name: traefik-ingress-service
  namespace: traefik
spec:
  selector:
    k8s-app: traefik-ingress-lb
  ports:
    - protocol: TCP
      port: 80
      name: web
    # - protocol: TCP
      # port: 8080
      # name: admin
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: traefik-ingress-controller
rules:
  - apiGroups:
      - ""
    resources:
      - services
      - endpoints
      - secrets
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - extensions
    resources:
      - ingresses
    verbs:
      - get
      - list
      - watch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: traefik-ingress-controller
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: traefik-ingress-controller
subjects:
- kind: ServiceAccount
  name: traefik-ingress-controller
  namespace: traefik

据我所知,这两个规格并不相同,但非常相似。他们都在 'traefik' 命名空间中创建一个 ServiceAccount 并授予一个 ClusterRole。

哪个部分决定了80端口的权限?

open issue on the Traefik helm chart where Jasper Ben 提出了一个可行的解决方案:

hostNetwork: true
ports:
  web:
    port: 80
    redirectTo: websecure
  websecure:
    port: 443

securityContext:
  capabilities:
    drop: [ALL]
    add: [NET_BIND_SERVICE]
  readOnlyRootFilesystem: true
  runAsGroup: 0
  runAsNonRoot: false
  runAsUser: 0

helm 图表中缺少的部分是 securityContext 中的 NET_BIND_SERVICE 功能。