作者 | 修订时间 |
---|---|
2024-12-31 23:26:58 |
Traefik资源跨命名空间调用
前沿
在研究traefik
跨命名空间调用资源时,发现有一个非常坑人的点,就是 traefik
文档有一个东西叫 跨服务商命名空间(Provider Namespace)
,这个是什么东西呢,就是如果你在 k3s/k8s
中有需要对docker提供商创建的资源进行调用时,你可以开启跨服务商命名空间。还有一个就是Kubernetes
自带的命名空间,我们需要操作的就是这个命名空间。
这里的namespace: default
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: default
namespace: default # 就是这个字段
spec:
entryPoints:
- websecure # 使用 HTTPS
- web # HTTP
routes:
- match: Host(`www.wjlin0.com`) && PathPrefix(`/`) #
kind: Rule
services:
- name: default
利用
如何进行跨命名空间资源调用呢,在traefik
文档中提到有个参数allowCrossNamespace
,这个参数是控制跨命名空间资源调用,(默认关闭的,不允许跨命名空间资源调用)。
这是helm安装,参数所在位置.
......
......
......
# -- Define [Startup Probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-startup-probes)
startupProbe: {}
providers: # @schema additionalProperties: false
kubernetesCRD:
# -- Load Kubernetes IngressRoute provider
enabled: true
# -- Allows IngressRoute to reference resources in namespace other than theirs
allowCrossNamespace: true
......
......
开启后,配置跨命名空间资源调度,需要遵守以下命名规则。
<资源命名空间>-<资源名称>@提供商
了解了上诉的操作步骤,我们应该怎么做呢,我接下来给出一个案例;
需求时,我将k3s-apiserver
的ping
目录,通过traefik
,导出到外部访问。
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: kubernetes-ping-ingressroute
namespace: default
spec:
entryPoints:
- websecure # 使用 HTTPS
- web # HTTP
routes:
- match: Host(`kube.wjlin0.com`) && PathPrefix(`/ping`)
kind: Rule
services:
- name: kubernetes #
port: 443
scheme: https
在上诉配置中我们成功将服务kubernetes
导出到外部访问,但是你访问之后会发现,该路由爆500的错误
➜ ~ curl https://kube.wjlin0.com/ping
Internal Server Error
➜ ~
这是因为kubernetes
的证书是自签证书,你需要对该证书进行引用或者忽略。首先我们找到这个证书,它位于服务器的
/var/lib/rancher/k3s/server/tls/serving-kube-apiserver.crt
然后我们将 证书 base64 转换。
base64 -w 0 /var/lib/rancher/k3s/server/tls/serving-kube-apiserver.crt
然后通过rootCAsSecrets
引用进来,当然你可以都保存在default
,这里是在演示如何跨命名空间调用。
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: kubernetes-ping-ingressroute
namespace: default
spec:
entryPoints:
- websecure # 使用 HTTPS
- web # HTTP
routes:
- match: Host(`kube.wjlin0.com`) && PathPrefix(`/ping`) # 替换为你的域名
kind: Rule
services:
- name: kubernetes # 替换为你的服务名称
port: 443 # 替换为你的服务端口
# strategy: RoundRobin # 负载均衡策略,默认为 RoundRobin
serversTransport: kube-system-kubernetes@kubernetescrd
---
apiVersion: traefik.io/v1alpha1
kind: ServersTransport
metadata:
name: kubernetes
namespace: kube-system
spec:
insecureSkipVerify: false
rootCAsSecrets:
- k3s-serving-kube-apiserver
---
apiVersion: v1
kind: Secret
metadata:
name: k3s-serving-kube-apiserver
namespace: kube-system
data:
ca.crt: ......
再次进行命令
➜ ~ curl https://kube.wjlin0.com/ping
pong
➜ ~
小插曲
⚠️ 小插曲,这里遇到一个问题就是如下.
我使用下面的配置 通过 traefik
吧 kubernetes
服务端的 ping 目录导出来,然而 出现了证书错误 500
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: kubernetes-ping-ingressroute
namespace: default
spec:
entryPoints:
- websecure # 使用 HTTPS
- web # HTTP
routes:
- match: Host(`kube.wjlin0.com`) && PathPrefix(`/ping`) # 替换为你的域名
kind: Rule
services:
- name: kubernetes
port: 443 # 替换为你的服务端口
scheme: https
serversTransport: kube-system-kubernetes@kubernetescrd
---
apiVersion: traefik.io/v1alpha1
kind: ServersTransport
metadata:
name: kubernetes
namespace: kube-system
spec:
serverName: kubernetes.default.svc
insecureSkipVerify: false
rootCAsSecrets:
- k3s-serving
certificatesSecrets:
- k3s-serving
这是我的错误
2024-12-31T19:01:08+08:00 DBG github.com/traefik/traefik/v3/pkg/proxy/httputil/proxy.go:113 > 500 Internal Server Error error="tls: failed to verify certificate: x509: certificate signed by unknown authority"
事实上 k3s-serving
这个是 k3s 的 的证书
➜ ~ k get secrets -n kube-system k3s-serving -o yaml
apiVersion: v1
data:
tls.crt: ..........
tls.key: .......
kind: Secret
metadata:
.......
.......
.......
name: k3s-serving
namespace: kube-system
type: kubernetes.io/tls
我尝试去解决它 ,于是我创建了一个 sercert ,发现它 能够访问了
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: kubernetes-ping-ingressroute
namespace: default
spec:
entryPoints:
- websecure # 使用 HTTPS
- web # HTTP
routes:
- match: Host(`kube.wjlin0.com`) && PathPrefix(`/ping`) # 替换为你的域名
kind: Rule
services:
- name: kubernetes
port: 443 # 替换为你的服务端口
scheme: https
serversTransport: kube-system-kubernetes@kubernetescrd
---
apiVersion: traefik.io/v1alpha1
kind: ServersTransport
metadata:
name: kubernetes
namespace: kube-system
spec:
serverName: kubernetes.default.svc
insecureSkipVerify: false
rootCAsSecrets:
- meta
certificatesSecrets:
- k3s-serving
---
apiVersion: v1
kind: Secret
metadata:
name: meta
namespace: kube-system
data:
ca.crt: ..... # the k3s crt base64
我找到一个类似的问题 #7788
翻了一下源代码,发现只对ca.crt
、tls.ca
和一个出现的密钥
总结
traefik默认不开启跨命名调用,如果需要,需要在安装时,打开配置allowCrossNamespace
为true
,并使用命名规则
When you declare certain objects in the Traefik dynamic configuration, such as middleware, services, TLS options or server transports, they reside in their provider's namespace. For example, if you declare a middleware using a Docker label, it resides in the Docker provider namespace.
If you use multiple providers and wish to reference such an object declared in another provider (e.g. referencing a cross-provider object like middleware), then the object name should be suffixed by the @ separator, and the provider name.
For the list of the providers names, see the supported providers table below.
<resource-name>@<provider-name>
As Kubernetes also has its own notion of namespace, one should not confuse the provider namespace with the Kubernetes Namespace of a resource when in the context of cross-provider usage.
In this case, since the definition of a Traefik dynamic configuration object is not in Kubernetes, specifying a Kubernetes Namespace when referring to the resource does not make any sense.
On the other hand, if you were to declare a middleware as a Custom Resource in Kubernetes and use the non-CRD Ingress objects, you would have to add the Kubernetes Namespace of the middleware to the annotation like this <middleware-namespace>-<middleware-name>@kubernetescrd.