如何使用Kustomize配置Traefik 2.x IngressRoute (metadata.name, spec.routes[0].services[0].name & spec.routes[0].match = Host() )

How to use Kustomize to configure Traefik 2.x IngressRoute (metadata.name, spec.routes[0].services[0].name & spec.routes[0].match = Host() )

我们有 a EKS cluster running with Traefik deployed in CRD style (full setup on GitHub) and wan't to deploy our app https://gitlab.com/jonashackt/microservice-api-spring-boot with the Kubernetes objects Deployment, Service and IngressRoute (see configuration repository here)。清单如下所示:

deployment.yml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: microservice-api-spring-boot
spec:
  replicas: 3
  revisionHistoryLimit: 3
  selector:
    matchLabels:
      app: microservice-api-spring-boot
      branch: main
  template:
    metadata:
      labels:
        app: microservice-api-spring-boot
        branch: main
    spec:
      containers:
        - image: registry.gitlab.com/jonashackt/microservice-api-spring-boot:c25a74c8f919a72e3f00928917dc4ab2944ab061
          name: microservice-api-spring-boot
          ports:
            - containerPort: 8098
      imagePullSecrets:
        - name: gitlab-container-registry

service.yml:

apiVersion: v1
kind: Service
metadata:
  name: microservice-api-spring-boot
spec:
  ports:
    - port: 80
      targetPort: 8098
  selector:
    app: microservice-api-spring-boot
    branch: main

traefik-ingress-route.yml:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: microservice-api-spring-boot-ingressroute
  namespace: default
spec:
  entryPoints:
    - web
  routes:
    - match: Host(`microservice-api-spring-boot-BRANCHNAME.tekton-argocd.de`)
      kind: Rule
      services:
        - name: microservice-api-spring-boot
          port: 80

我们已经使用 Kustomize,尤其是 kustomize CLI(在 Mac 或 GitHub Actions 中使用 brew install kustomize 安装)和以下文件夹结构:

├── deployment.yml
├── kustomization.yaml
├── service.yml
└── traefik-ingress-route.yml

我们的 kustomization.yaml 看起来像这样:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- deployment.yml
- service.yml
- traefik-ingress-route.yml

images:
- name: registry.gitlab.com/jonashackt/microservice-api-spring-boot
  newTag: foobar

commonLabels:
  branch: foobar

nameSuffix: foobar

现在动态更改 metadata.name 以在我们的 GitHub 操作工作流中为部署、服务和 IngressRoute 的 .metadata.name 添加后缀很容易使用 kustomize CLI (因为我们希望后缀使用带前缀的-,所以这里需要使用-- -barfoo语法:

kustomize edit set namesuffix -- -barfoo

检查结果
kustomize build .

同样在Deployment and Service中更改.spec.selector.matchLabels.branch.spec.template.metadata.labels.branch.spec.selector.branch也没问题:

kustomize edit set label branch:barfoo

更改 Deployment 的 .spec.template.spec.containers[0].image 适用于:

kustomize edit set image registry.gitlab.com/jonashackt/microservice-api-spring-boot:barfoo

但是查看我们的 IngressRoute 似乎 .spec.routes[0].services[0].name.spec.routes[0].match = Host() 无法通过开箱即用的 Kustomize 进行更改?!那么我们如何才能在不需要像 yq 甚至 sed/ envsubst?

这样的替换工具的情况下更改这两个字段呢?

1.使用 Kustomize

更改 IngressRoutes .spec.routes[0].services[0].name

使用 a NameReference transformer (see docs here) - luckily I found inspiration in this issue 可以通过 Kustomize 更改 IngressRoutes .spec.routes[0].services[0].name。因此,我们需要在 kustomize.yaml:

中包含 configurations 关键字
nameSuffix: foobar
configurations:
  # Tie target Service metadata.name to IngressRoute's spec.routes.services.name
  # Once Service name is changed, the IngressRoute referrerd service name will be changed as well.
  - nameReference.yml

我们还需要添加名为 nameReference.yml:

的文件
nameReference:
  - kind: Service
    fieldSpecs:
      - kind: IngressRoute
        path: spec/routes/services/name

如您所见,我们将服务的 name 绑定到 IngressRoutes spec/routes/services/name。现在运行

kustomize edit set namesuffix barfoo

不仅会更改 Deployment、Service 和 IngressRoute 的 metadata.name 标签,还会更改 IngressRoute 的 .spec.routes[0].services[0].name,因为它现在链接到 metadata.name服务。请注意,这仅在推荐人和目标人都有 name 标签的情况下。

2。更改 IngressRoutes 的一部分 .spec.routes[0].match = Host()

问题的第二部分询问如何更改 IngressRoutes 的一部分 .spec.routes[0].match = Host()。有 an open issue in the Kustomize GitHub project. Right now Kustomize doesn't support this use case - only writing a custom generator plugin for Kustomize. As this might not be a preferred option, there's another way inspired by this blog post。由于我们可以使用语法 cat > ./myyamlfile.yml <<EOF ... EOF 在控制台中内联创建 yaml 文件,因此我们也可以使用内联变量替换。

所以首先定义分支名称为变量:

RULE_HOST_BRANCHNAME=foobar

然后使用描述的语法内联创建 ingressroute-patch.yml 文件:

cat > ./ingressroute-patch.yml <<EOF
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: microservice-api-spring-boot-ingressroute
  namespace: default
spec:
  entryPoints:
    - web
  routes:
    - match: Host(\`microservice-api-spring-boot-$RULE_HOST_BRANCHNAME.tekton-argocd.de\`)
      kind: Rule
      services:
        - name: microservice-api-spring-boot
          port: 80

EOF

最后一步是在我们的 kustomization.yaml 中使用 ingressroute-patch.yml 文件作为 patchesStrategicMerge,如下所示:

patchesStrategicMerge:
  - ingressroute-patch.yml

现在 运行 kustomize build . 应该为我们的设置输出正确的 Deployment、Service 和 IngressRoute:

apiVersion: v1
kind: Service
metadata:
  labels:
    branch: barfoo
  name: microservice-api-spring-boot-barfoo
spec:
  ports:
  - port: 80
    targetPort: 8098
  selector:
    app: microservice-api-spring-boot
    branch: barfoo
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    branch: barfoo
  name: microservice-api-spring-boot-barfoo
spec:
  replicas: 3
  revisionHistoryLimit: 3
  selector:
    matchLabels:
      app: microservice-api-spring-boot
      branch: barfoo
  template:
    metadata:
      labels:
        app: microservice-api-spring-boot
        branch: barfoo
    spec:
      containers:
      - image: registry.gitlab.com/jonashackt/microservice-api-spring-boot:barfoo
        name: microservice-api-spring-boot
        ports:
        - containerPort: 8098
      imagePullSecrets:
      - name: gitlab-container-registry
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  labels:
    branch: barfoo
  name: microservice-api-spring-boot-ingressroute-barfoo
  namespace: default
spec:
  entryPoints:
  - web
  routes:
  - kind: Rule
    match: Host(`microservice-api-spring-boot-barfoo.tekton-argocd.de`)
    services:
    - name: microservice-api-spring-boot-barfoo
      port: 80