带有自定义 SSL 证书的 Traefik 2.3 将无法工作

Traefik 2.3 with custom SSL certificates won't work

我已经使用 GKE 设置了一个 Kubernetes 集群,并将 Traefik 实例作为入口控制器。到目前为止一切正常,但是 Traefik 没有找到我的 SSL 证书。

我的 CustomResourceDefinition 文件:

apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: ingressroutes.traefik.containo.us

spec:
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: IngressRoute
    plural: ingressroutes
    singular: ingressroute
  scope: Namespaced

---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: middlewares.traefik.containo.us

spec:
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: Middleware
    plural: middlewares
    singular: middleware
  scope: Namespaced

---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: ingressroutetcps.traefik.containo.us

spec:
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: IngressRouteTCP
    plural: ingressroutetcps
    singular: ingressroutetcp
  scope: Namespaced

---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: ingressrouteudps.traefik.containo.us

spec:
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: IngressRouteUDP
    plural: ingressrouteudps
    singular: ingressrouteudp
  scope: Namespaced

---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: tlsoptions.traefik.containo.us

spec:
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: TLSOption
    plural: tlsoptions
    singular: tlsoption
  scope: Namespaced

---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: tlsstores.traefik.containo.us

spec:
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: TLSStore
    plural: tlsstores
    singular: tlsstore
  scope: Namespaced

---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: traefikservices.traefik.containo.us

spec:
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: TraefikService
    plural: traefikservices
    singular: traefikservice
  scope: Namespaced

我的 RBAC 文件:

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: traefik-ingress-controller
rules:
  - apiGroups:
      - ""
    resources:
      - services
      - endpoints
      - secrets
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - extensions
    resources:
      - ingresses
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - extensions
    resources:
      - ingresses/status
    verbs:
      - update
  - apiGroups:
      - traefik.containo.us
    resources:
      - middlewares
      - ingressroutes
      - traefikservices
      - ingressroutetcps
      - ingressrouteudps
      - tlsoptions
      - tlsstores
    verbs:
      - get
      - list
      - watch

---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
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: default

我的服务帐号:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: traefik-ingress-controller

我的配置图:

kind: ConfigMap
apiVersion: v1
metadata:
  name: traefik-config-map
data:
  traefik.toml: |-
    [global]
      checkNewVersion = false
      sendAnonymousUsage = false
    [retry]
      attempts = 3
      maxMem = 3
    [entryPoints]
      [entryPoints.web]
        address = ":80"
        [entryPoints.web.http]
          [entryPoints.web.http.redirections]
            [entryPoints.web.http.redirections.entryPoint]
              to = "websecure"
              scheme = "https"
              permanent = true
      [entryPoints.websecure]
        address = ":443"
    [log]
      level = "DEBUG"
    [accessLog]
    [api]
      insecure = true
      dashboard = true
      debug = true
    [providers]
      [providers.file]
        directory = "/etc/traefik"
        watch = true
      [providers.kubernetesCRD]


    [[tls.certificates]]
       keyFile = "/var/ssl/tls.key"
       certFile = "/var/ssl/tls.crt"

    [tls.options]
        [tls.options.default]
          minVersion = "VersionTLS12"
          preferServerCipherSuites = true
          cipherSuites = [
            "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
            "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
            "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
            "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
            "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
            "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
            "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
            "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
            "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
          ]

        [tls.options.mintls13]
          minVersion = "VersionTLS13"

    [tls.stores]
      [tls.stores.default]
        [tls.stores.default.defaultCertificate]
          keyFile = "/var/ssl/tls.key"
          certFile = "/var/ssl/tls.crt"

我的部署:

---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: traefik
  labels:
    app: traefik
spec:
  replicas: 1
  selector:
    matchLabels:
      app: traefik
  template:
    metadata:
      labels:
        app: traefik
    spec:
      serviceAccountName: traefik-ingress-controller
      volumes:
        - name: config
          configMap:
            name: traefik-config-map
        - name: samisaude-tls
          secret:
            secretName: samisaude-tls
      containers:
        - name: traefik
          image: traefik:v2.3.7
          ports:
            - name: web
              containerPort: 80
            - name: admin
              containerPort: 8080
            - name: websecure
              containerPort: 443
          volumeMounts:
            - mountPath: /etc/traefik/traefik.toml
              name: config
              subPath: traefik.toml
            - mountPath: "/var/ssl"
              name: samisaude-tls
              readOnly: true

我的秘密:

apiVersion: v1
data:
  tls.key: <ENCODED_KEY_HERE>
  tls.crt: <ENCODED_CRT_HERE>
kind: Secret
metadata:
  name: samisaude-tls
  namespace: default
type: Opaque

我的服务:

apiVersion: v1
kind: Service
metadata:
  name: traefik
spec:
  type: LoadBalancer
  selector:
    app: traefik
  ports:
    - protocol: TCP
      port: 80
      name: web
      targetPort: 80
    - protocol: TCP
      port: 443
      name: websecure
      targetPort: 80
    - protocol: TCP
      port: 8080
      name: admin
      targetPort: 8080

出于测试目的,我上传了一个 whoami 容器。

部署:

kind: Deployment
apiVersion: apps/v1
metadata:
  namespace: default
  name: whoami
  labels:
    app: whoami
spec:
  replicas: 1
  selector:
    matchLabels:
      app: whoami
  template:
    metadata:
      labels:
        app: whoami
    spec:
      containers:
        - name: whoami
          image: containous/whoami
          ports:
            - name: web
              containerPort: 80

入口:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: whoami
  namespace: default
spec:
  tls: {}
  entryPoints:
    - web
    - websecure
  routes:
  - match: Host(`mysubdomain.samisaude.com.br`) && PathPrefix(`/whoami`)
    kind: Rule
    services:
    - name: whoami
      port: 80

服务:

apiVersion: v1
kind: Service
metadata:
  name: whoami
spec:
  ports:
    - protocol: TCP
      name: web
      port: 80
  selector:
    app: whoami

在 Traefik 的 Dashboard 中一切正常,但是当在浏览器中访问我的 URL 时,证书仍然是 Traefik 的默认值,而不是我添加的。在 Traefik POD 日志中,我收到以下消息:

time="2021-09-28T16:33:31Z" level=debug msg="No secret name provided" providerName=kubernetescrd
time="2021-09-28T16:33:31Z" level=debug msg="Skipping Kubernetes event kind *v1.Endpoints" providerName=kubernetescrd

欢迎任何帮助。谢谢。

以下内容可行。我曾尝试过 GCP。您也可以关注link

00-资源-crd-definition.yml

apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: ingressroutes.traefik.containo.us

spec:
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: IngressRoute
    plural: ingressroutes
    singular: ingressroute
  scope: Namespaced

---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: middlewares.traefik.containo.us

spec:
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: Middleware
    plural: middlewares
    singular: middleware
  scope: Namespaced

---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: ingressroutetcps.traefik.containo.us

spec:
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: IngressRouteTCP
    plural: ingressroutetcps
    singular: ingressroutetcp
  scope: Namespaced

---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: ingressrouteudps.traefik.containo.us

spec:
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: IngressRouteUDP
    plural: ingressrouteudps
    singular: ingressrouteudp
  scope: Namespaced

---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: tlsoptions.traefik.containo.us

spec:
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: TLSOption
    plural: tlsoptions
    singular: tlsoption
  scope: Namespaced

---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: tlsstores.traefik.containo.us

spec:
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: TLSStore
    plural: tlsstores
    singular: tlsstore
  scope: Namespaced

---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: traefikservices.traefik.containo.us

spec:
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: TraefikService
    plural: traefikservices
    singular: traefikservice
  scope: Namespaced

05-traefik-rbac.yml

---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: traefik-ingress-controller

rules:
  - apiGroups:
      - ""
    resources:
      - services
      - endpoints
      - secrets
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - extensions
    resources:
      - ingresses
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - extensions
    resources:
      - ingresses/status
    verbs:
      - update
  - apiGroups:
      - traefik.containo.us
    resources:
      - middlewares
      - ingressroutes
      - traefikservices
      - ingressroutetcps
      - ingressrouteudps
      - tlsoptions
      - tlsstores
    verbs:
      - get
      - list
      - watch

---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
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: default
---

10-服务-account.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: traefik-ingress-controller

11-traefik-configmap.yaml

kind: ConfigMap
apiVersion: v1
metadata:
  name: traefik-config-map
data:
  traefik.toml: |-
    [global]
      checkNewVersion = false
      sendAnonymousUsage = false
    [retry]
      attempts = 3
      maxMem = 3
    [entryPoints]
      [entryPoints.web]
        address = ":80"
        [entryPoints.web.http]
          [entryPoints.web.http.redirections]
            [entryPoints.web.http.redirections.entryPoint]
              to = "websecure"
              scheme = "https"
              permanent = true
      [entryPoints.websecure]
        address = ":443"
    [log]
      level = "DEBUG"
    [accessLog]
    [api]
      insecure = true
      dashboard = true
      debug = true
    [providers]
      [providers.file]
        directory = "/etc/traefik"
        watch = true
      [providers.kubernetesCRD]
    [[tls.certificates]]
       keyFile = "/var/ssl/start-domain-com-ssl/star_domain.com.key"
       certFile = "/var/ssl/start-domain-com-ssl/star_domain_com.chained.crt"
    [tls.options]
        [tls.options.default]
          minVersion = "VersionTLS12"
          preferServerCipherSuites = true
          cipherSuites = [
            "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
            "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
            "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
            "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
            "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
            "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
            "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
            "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
            "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
          ]
        [tls.options.mintls13]
          minVersion = "VersionTLS13"
    [tls.stores]
      [tls.stores.default]
        [tls.stores.default.defaultCertificate]
          keyFile = "/var/ssl/start-domain-com-ssl/star_domain.com.key"
          certFile = "/var/ssl/start-domain-com-ssl/star_domain_com.chained.crt"

12-secret.yaml

apiVersion: v1
data:
  star_domain.com.key: <Add base64 encoded value of you cert.key>
  star_domain_com.chained.crt: <Add base64 encoded value of your chained cert.crt>
kind: Secret
metadata:
  name: start-domain-com-ssl
  namespace: default
type: Opaque

15-traefik-deployment.yaml

---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: traefik
  labels:
    app: traefik

spec:
  replicas: 1
  selector:
    matchLabels:
      app: traefik
  template:
    metadata:
      labels:
        app: traefik
    spec:
      serviceAccountName: traefik-ingress-controller
      volumes:
        - name: config
          configMap:
            name: traefik-config-map
        - name: start-domain-com-ssl
          secret:
            secretName: start-domain-com-ssl
      containers:
        - name: traefik
          image: traefik:v2.2.1
          ports:
            - name: web
              containerPort: 80
            - name: admin
              containerPort: 8080
            - name: websecure
              containerPort: 443
          volumeMounts:
            - mountPath: /etc/traefik/traefik.toml
              name: config
              subPath: traefik.toml
            - mountPath: "/var/ssl/start-domain-com-ssl"
              name: start-domain-com-ssl
              readOnly: true

20-traefik-service.yaml

---
apiVersion: v1
kind: Service
metadata:
  name: traefik
spec:
  type: LoadBalancer
  selector:
    app: traefik
  ports:
    - protocol: TCP
      port: 80
      name: web
      targetPort: 80
    - protocol: TCP
      port: 443
      name: websecure
      targetPort: 80
    - protocol: TCP
      port: 8080
      name: admin
      targetPort: 8080

25-whoami-deployment.yaml

kind: Deployment
apiVersion: apps/v1
metadata:
  namespace: default
  name: whoami
  labels:
    app: whoami

spec:
  replicas: 1
  selector:
    matchLabels:
      app: whoami
  template:
    metadata:
      labels:
        app: whoami
    spec:
      containers:
        - name: whoami
          image: containous/whoami
          ports:
            - name: web
              containerPort: 80

30-whoami-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: whoami

spec:
  ports:
    - protocol: TCP
      name: web
      port: 80
  selector:
    app: whoami

35-whoami-ingress-route.yaml

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: whoami-whoami
  namespace: default
spec:
  tls: {}
  entryPoints:
    - web
    - websecure
  routes:
  - match: PathPrefix(`/whoami-app-api`)
    kind: Rule
    services:
    - name: whoami
      port: 80