惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Forbes - Security
Forbes - Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
P
Palo Alto Networks Blog
Martin Fowler
Martin Fowler
T
Threatpost
D
Docker
S
Schneier on Security
M
MIT News - Artificial intelligence
G
Google Developers Blog
L
LINUX DO - 热门话题
J
Java Code Geeks
月光博客
月光博客
博客园 - 三生石上(FineUI控件)
IT之家
IT之家
博客园 - Franky
C
Cyber Attacks, Cyber Crime and Cyber Security
K
Kaspersky official blog
Google DeepMind News
Google DeepMind News
N
News and Events Feed by Topic
V
Vulnerabilities – Threatpost
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
人人都是产品经理
人人都是产品经理
Spread Privacy
Spread Privacy
T
Tailwind CSS Blog
爱范儿
爱范儿
阮一峰的网络日志
阮一峰的网络日志
U
Unit 42
C
CERT Recently Published Vulnerability Notes
The GitHub Blog
The GitHub Blog
Simon Willison's Weblog
Simon Willison's Weblog
NISL@THU
NISL@THU
MongoDB | Blog
MongoDB | Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
H
Heimdal Security Blog
Recorded Future
Recorded Future
云风的 BLOG
云风的 BLOG
SecWiki News
SecWiki News
P
Privacy International News Feed
P
Proofpoint News Feed
O
OpenAI News
B
Blog
腾讯CDC
F
Full Disclosure
Apple Machine Learning Research
Apple Machine Learning Research
T
Tor Project blog
H
Hacker News: Front Page
Project Zero
Project Zero
Hugging Face - Blog
Hugging Face - Blog
C
Cisco Blogs
S
Security Affairs

Learn Cloud Native

Agentgateway rate limiting for agents | Learn Cloud Native Local development with coding agents on Kubernetes using Signadot | Learn Cloud Native cuenv: one typed file for your whole project | Learn Cloud Native Preflight: AI Code Review Before You Push Anatomy of AI Agents Accessing Google Drive from Next.js Deploying to Fly.io using Dagger and Github Top Cloud-Native & Kubernetes Certifications [2026 Guide] Rapid microservices development with Signadot How to prepare for Istio certified associate exam (ICA) Global Rate Limiting in Istio with Envoy Rate Limit Service My Journey with Istio: From Incubation to Graduation Cilium Network Policy Tutorial: Secure Kubernetes Step by Step Kubernetes Networking: How kube-proxy and iptables Work Istio ServiceEntry: DNS vs. STATIC Resolution & Endpoints Explained Apply an Istio DestinationRule Globally (Mesh-Wide) Istio Rate Limiting: Configure a Local Rate Limiter in Envoy How to expose custom ports on Istio ingress gateway Portainer Tutorial: A Web UI for Kubernetes & Containers Traefik Proxy 2.x and TLS 101 Kubernetes CLI (kubectl) tips you didn't know about Setting up SSL certificates with Istio Gateway ArgoCD Best Practices You Should Know 在 OCI Ampere A1 计算实例上运行 AI Running AI On OCI Ampere A1 Instance Firebase Emulators with Next.js: Local Setup Guide Running Hugo on free Ampere VM (Oracle Cloud Infrastructure) How to use kwatch to detect crashes in Kubernetes clusters Continuous profiling in Kubernetes using Pyroscope Monitoring containers with cAdvisor Creating a Kubernetes cluster in Google Cloud (LAB) Your first Kubernetes Pod and ReplicaSet (LABS) Container Lifecycle Hooks Maybe Convert Wasm Extension Config? GetIstio - CLI, training, and community Attach multiple VirtualServices to Istio Gateway Kubernetes Volumes Explained: Keep Data Beyond the Pod Send a Slack message when Docker images are updated Kubernetes Network Policy Ambassador Container Pattern Start Kubernetes Release Sidecar Container Pattern Kubernetes Init Containers Deploying multiple Istio Ingress Gateways Branch by Abstraction Pattern The Strangler Pattern Kubernetes Development Environment with Skaffold Securing Kubernetes Ingress with Ambassador and Let's Encrypt All About the Ingress Resource How to quarantine Kubernetes pods? Getting started with Kubernetes Horizontal partitioning in MongoDB Docker image tagging scheme Six things to keep in mind when working with Dockerfiles Beginners guide to Docker Beginners guide to gateways and proxies Deploy and Operate Multiple Istio Meshes in one Kubernetes Cluster Managing service meshes with Meshery Circuit Breaking in Istio Explained Build and push your Docker images using Github Actions Kubernetes and Istio service mesh workshop materials Build Netlify-like deployment for React app using Kubernetes pods Six exciting enhancements in Istio 1.4.0 Fallacies of Distributed Systems CAP Theorem Explained Master the Kubernetes CLI (kubectl) - Cheatsheet Minikube Basics and How to Get Started with Kubernetes 5 Tips to Be More Productive with Kubernetes What are sticky sessions and how to configure them with Istio? Debugging Kubernetes applications using Istio Kubernetes Ingress and Istio Gateway Resource Zero Downtime Releases using Kubernetes and Istio Traffic Mirroring with Istio Service Mesh Expose a Kubernetes service on your own custom domain
How to Deploy Traefik Proxy Using Flux and GitOps Principles
Jakub Hajek · 2022-03-09 · via Learn Cloud Native

GitOps makes configuration management seamless by creating a single source of truth for configuration changes to be transparent, validated, and low-risk. This article and this GitHub repository will show you how Traefik Proxy and Flux can work together to help you implement GitOps principles. But before we jump in, what are these tools, and how do they help?

What is Flux?

Flux is a tool created by Weaveworks, the inventor of GitOps. The operator makes GitOps happen in your cluster, ensuring cluster configurations match the ones in Git. Flux exposes an interface to this tool that helps you build and apply YAML to your clusters so you can automate your deployments. It also uses Helm.

What is Traefik Proxy?

Traefik Proxy is an edge router that exposes your services. In the Kubernetes ecosystem, this is called an ingress controller. Traefik Proxy is continuously updated to work with the latest version of Kubernetes.

Traefik Proxy provides CRDs such as an ingress route, TCP/UDP ingress routes, and TraefikService (an abstraction layer running on top of Kubernetes Services and middleware). These objects help you expose Services to create a configuration. The middlewares are applied to routers and can tweak requests before hitting Services.

Traefik Proxy is a leading modern reverse proxy and load balancer that makes deploying microservices easier. Traefik Proxy also has a certificate resolver feature that lets you automatically obtain certificates from Let's Encrypt. Traefik Proxy's middlewares constitute small applications that you can use to tweak requests. They will help you, for example, add headers or circuit breaker rate limits. Traefik Proxy also supports canary deployments, and we recently added middlewares for TCP ingress routes.

How to deploy Traefik Proxy in multiple clusters using Flux

We will be promoting code from staging to production using Kustomize, built into Flux. Before anything else, there are a few prerequisites you will need:

  • Two Kubernetes clusters acting as, e.g., staging and production environments
  • An empty GitHub repo
  • Exported environment variables GITHUB_TOKEN, GITHUB_USER, GITHUB_REPO
  • The latest Flux CLI installed on a workstation

This article aims to show you how to maintain Kubernetes environments with GitOps principles. We will highlight an everyday use case with two clusters: one staging environment and one production environment.

On both clusters, we will deploy Traefik Proxy and the sample applications that will be exposed externally thanks to Traefik and IngressRoute resources.

The configuration that we are preparing is based on the following structure:

  • Base - the initial configuration that should be common to all environments (staging and production).
  • Staging - the configuration for staging environments. It is inherited from the base configuration and applies the changes related specifically to the staging environment.
  • Production - the configuration for the production environment. Again, it is inherited from the base configuration with the changes needed for the production environment.

All the changes that are created for a specific environment will be created as a patch, so we will only update the attributes that we are going to change. The remaining configuration is inherited from the base configuration. That entire process is managed using Kustomize, built into Flux.

The entire configuration will be prepared locally, without executing any imperative commands on those two clusters that have been provisioned as a prerequisite.

Once we create the configuration locally, we will push the entire code to the Git repository.

The Git repository is our source of truth. Any change we will apply to a cluster will go through our Git repository.

This is a core idea of GitOps. We configure the desired state of our infrastructure using commonly-known Kubernetes manifests. We then push the desired state to a Git repository. Flux then pulls the configuration to the cluster, so the configuration can be applied.

It is very beneficial to store our cluster configuration in a Git repository. That way, we can track all the changes and test pull requests before merging them into the main branch. We can ensure that the code committed to the Git repository runs on our clusters.

Flux will run our applications and infrastructures components: Traefik Proxy and our sample application on our cluster according to the code we prepared locally.

Let's get started!

Step 1: Create the infrastructure repository

Create a Git repository to store all configuration files. In our example, we will use a GitHub repo. Use the following command to create a GitHub repo:

gh repo create flux-traefik-demo --public --description "Flux and Traefik - demo"  --clone

This command assumes you are in an empty directory with no Git repository. It will have the same effect as running git init. gh command refers to the GitHub CLI). If your home directory is a Git repository, you might want to run git init in an empty directory before running the above command. This will create the remote repository and set up the Git remote.

Step 2: Create the repository structure

The following command will create the top directory structures needed to keep manifests that describe the entire infrastructure:

The apps contain custom manifests per cluster as well as Helm releases.

  • The infrastructure contains common infrastructure tools, such as Helm repository definitions or common infrastructure components.
  • Clusters contain Flux configurations.
mkdir -pv ./apps/{base,staging,production}/traefik ./clusters/{production,staging} ./infrastructure/{sources,crds}
├── apps
│   ├── base
│   ├── production
│   └── staging
├── infrastructure
│   ├── crds
│   └── sources
└── clusters
    ├── production
    └── staging

Step 3: Create the Traefik base configuration

A typical way of installing Traefik is to create a service account, RBAC, deployment, and Service (of load balancer type) to expose Traefik.

First, create your RBAC resources.

We can also install Traefik using the official Helm Chart. Flux supports Helm releases. However, in this case we will install all the required resources manually.

cat > ./apps/base/traefik/rbac.yaml <<EOF
---
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
      - networking.k8s.io
    resources:
      - ingresses
      - ingressclasses
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - extensions
    resources:
      - ingresses/status
    verbs:
      - update
  - apiGroups:
      - traefik.containo.us
    resources:
      - middlewares
      - middlewaretcps
      - ingressroutes
      - traefikservices
      - ingressroutetcps
      - ingressrouteudps
      - tlsoptions
      - tlsstores
      - serverstransports
    verbs:
      - get
      - list
      - watch

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

---
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
EOF

Then create your Traefik Proxy deployment resource.

cat > ./apps/base/traefik/traefik.yaml << EOF
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: traefik
  labels:
    app.kubernetes.io/instance: traefik
    app.kubernetes.io/name: traefik
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: traefik
      app.kubernetes.io/instance: traefik
  template:
    metadata:
      labels:
        app.kubernetes.io/name: traefik
        app.kubernetes.io/instance: traefik
    spec:
      serviceAccountName: traefik-ingress-controller
      terminationGracePeriodSeconds: 60
      containers:
        - name: traefik
          image: traefik:2.5.4
          args:
            - "--entryPoints.web.address=:8000/tcp"
            - "--entryPoints.websecure.address=:8443/tcp"
            - "--entryPoints.traefik.address=:9000/tcp"
            - "--api=true"
            - "--api.dashboard=true"
            - "--ping=true"
            - "--providers.kubernetescrd"
            - "--providers.kubernetescrd.allowCrossNamespace=true"
          readinessProbe:
            httpGet:
              path: /ping
              port: 9000
            failureThreshold: 1
            initialDelaySeconds: 5
            periodSeconds: 5
            successThreshold: 1
            timeoutSeconds: 2
          livenessProbe:
            httpGet:
              path: /ping
              port: 9000
            failureThreshold: 3
            initialDelaySeconds: 5
            periodSeconds: 5
            successThreshold: 1
            timeoutSeconds: 2
          resources:
            limits:
              cpu: 1000m
              memory: 1000Mi
            requests:
              cpu: 100m
              memory: 50Mi
          ports:
            - name: web
              containerPort: 8000
              protocol: TCP
            - name: websecure
              containerPort: 8443
              protocol: TCP
            - name: traefik
              containerPort: 9000
              protocol: TCP
          volumeMounts:
            - mountPath: /data
              name: storage-volume
      volumes:
        - name: storage-volume
          emptyDir: {}
EOF

Next, create a Kubernetes load balancer type service that exposes Traefik Proxy.

cat > ./apps/base/traefik/svc.yaml << EOF
---
apiVersion: v1
kind: Service
metadata:
  name: traefik
  labels:
    app.kubernetes.io/instance: traefik
    app.kubernetes.io/name: traefik
spec:
  selector:
    app.kubernetes.io/instance: traefik
    app.kubernetes.io/name: traefik
  type: LoadBalancer
  externalTrafficPolicy: Local
  ports:
    - port: 80
      name: web
      targetPort: web
      protocol: TCP
    - port: 443
      name: websecure
      targetPort: websecure
      protocol: TCP
EOF

Create a Kustomization file that lists all the resources that have been created.

cat > ./apps/base/traefik/kustomization.yaml << EOF
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - rbac.yaml
  - traefik.yaml
  - svc.yaml
EOF

Step 4: Customize Traefik Proxy configurations for your production cluster

Create a namespace for your Traefik resources.

cat > ./apps/production/traefik/namespace.yaml << EOF
---
apiVersion: v1
kind: Namespace
metadata:
  name: traefik-production
EOF

Create a patch for a Traefik Proxy deployment to happen in your cluster. You first created a base configuration, where you have a configuration that will be adapted to meet the requirements for a specific environment. Use a patch to update your base configuration. The patch will contain fewer lines than the base. It will only apply the lines that have been modified. This is what Flux does in the background after it has been applied to the cluster.

As previously mentioned, the patch contains only those attributes being changed explicitly for that environment. The patch is a feature coming from Kustomize. Once Flux deploys the code, the patch will inherit the base configuration and merge to obtain the final Kubernetes manifests. In the Traefik configuration, we are using one of the features that help issue TLS certificates from LetsEncrypt. It will connect with Let's Encrypt and obtain a certificate. Make sure you have updated your email address accordingly. There is a lot more to configure with Let's Encrypt, so I encourage you to visit the official documentation to learn more.

cat > ./apps/production/traefik/traefik-patch.yaml << EOF
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: traefik
spec:
  template:
    spec:
      containers:
        - name: traefik
          args:
            - "--entryPoints.web.address=:8000/tcp"
            - "--entryPoints.websecure.address=:8443/tcp"
            - "--entryPoints.traefik.address=:9000/tcp"
            - "--api=true"
            - "--api.dashboard=true"
            - "--ping=true"
            - "--providers.kubernetescrd"
            - "--providers.kubernetescrd.allowCrossNamespace=true"
            - "--certificatesresolvers.myresolver.acme.storage=/data/acme.json"
            - "--certificatesresolvers.myresolver.acme.tlschallenge=true"
            - "--certificatesresolvers.myresolver.acme.email=jakub.hajek+webinar@traefik.io"
EOF

Then, create Kustomization to add resources.

cat > ./apps/production/traefik/kustomization.yaml << EOF
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: traefik-production
resources:
  - namespace.yaml
  - ../../base/traefik

patchesStrategicMerge:
  - traefik-patch.yaml
EOF

Step 5: Customize Traefik Proxy configurations for your staging cluster

Create a namespace for your Traefik Proxy deployment on a staging cluster.

cat > ./apps/staging/traefik/namespace.yaml << EOF
---
apiVersion: v1
kind: Namespace
metadata:
  name: traefik-staging
EOF

Create a Traefik Proxy patch for your staging cluster.

cat > ./apps/staging/traefik/traefik-patch.yaml << EOF
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: traefik
spec:
  template:
    spec:
      containers:
        - name: traefik
          args:
            - "--entryPoints.web.address=:8000/tcp"
            - "--entryPoints.websecure.address=:8443/tcp"
            - "--entryPoints.traefik.address=:9000/tcp"
            - "--api=true"
            - "--api.dashboard=true"
            - "--ping=true"
            - "--providers.kubernetescrd"
            - "--providers.kubernetescrd.allowCrossNamespace=true"
            - "--certificatesresolvers.myresolver.acme.storage=/data/acme.json"
            - "--certificatesresolvers.myresolver.acme.tlschallenge=true"
            - "--certificatesresolvers.myresolver.acme.email=jakub.hajek+webinar@traefik.io"
            - "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
EOF

Create a Kustomization resource for deploying your Traefik Proxy-related resources.

cat > ./apps/staging/traefik/kustomization.yaml << EOF
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: traefik-staging
resources:
  - namespace.yaml
  - ../../base/traefik

patchesStrategicMerge:
  - traefik-patch.yaml
EOF

Step 6: Create a Traefik Proxy CRD

Traefik Proxy requires you to have Custom Resources deployed on each cluster. The following command will create a common resource (including Treafik's CRD) that we will deploy on each cluster.

cat > ./infrastructure/crds/traefik-crds.yaml << EOF
---
apiVersion: source.toolkit.fluxcd.io/v1beta1
kind: GitRepository
metadata:
  name: traefik-crds
  namespace: flux-system
spec:
  interval: 30m
  url: https://github.com/traefik/traefik-helm-chart.git
  ref:
    tag: v10.3.0
  ignore: |
    # exclude all
    /*
    # path to crds
    !/traefik/crds/
---
apiVersion: kustomize.toolkit.fluxcd.io/v1beta1
kind: Kustomization
metadata:
  name: traefik-api-crds
  namespace: flux-system
spec:
  interval: 15m
  prune: false
  sourceRef:
    kind: GitRepository
    name: traefik-crds
    namespace: flux-system
  healthChecks:
  - apiVersion: apiextensions.k8s.io/v1
    kind: CustomResourceDefinition
    name: ingressroutes.traefik.containo.us
  - apiVersion: apiextensions.k8s.io/v1
    kind: CustomResourceDefinition
    name: ingressroutetcps.traefik.containo.us
  - apiVersion: apiextensions.k8s.io/v1
    kind: CustomResourceDefinition
    name: ingressrouteudps.traefik.containo.us
  - apiVersion: apiextensions.k8s.io/v1
    kind: CustomResourceDefinition
    name: middlewares.traefik.containo.us
  - apiVersion: apiextensions.k8s.io/v1
    kind: CustomResourceDefinition
    name: middlewaretcps.traefik.containo.us
  - apiVersion: apiextensions.k8s.io/v1
    kind: CustomResourceDefinition
    name: serverstransports.traefik.containo.us
  - apiVersion: apiextensions.k8s.io/v1
    kind: CustomResourceDefinition
    name: tlsoptions.traefik.containo.us
  - apiVersion: apiextensions.k8s.io/v1
    kind: CustomResourceDefinition
    name: tlsstores.traefik.containo.us
  - apiVersion: apiextensions.k8s.io/v1
    kind: CustomResourceDefinition
    name: traefikservices.traefik.containo.us
EOF

Create Kustomization for your Traefik Proxy CRDS.

cat > ./infrastructure/crds/kustomization.yaml << EOF
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: flux-system
resources:
  - traefik-crds.yaml
EOF

Create a Kustomization file that deploys the file contained in the CRDS directory.

cat > ./infrastructure/kustomization.yaml << EOF
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- crds
EOF

Step 7: Create the initial Flux configuration for your production cluster

cat > ./infrastructure/kustomization.yaml << EOF
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - crds
EOF
cat > ./clusters/production/infrastructure.yaml << EOF
---
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
  name: infrastructure
  namespace: flux-system
spec:
  interval: 10m0s
  sourceRef:
    kind: GitRepository
    name: flux-system
  path: ./infrastructure
  prune: true
  wait: true
EOF

Step 8: Create the initial Flux configuration for your staging cluster

cat > ./clusters/staging/apps.yaml << EOF
---
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
  name: apps
  namespace: flux-system
spec:
  interval: 10m0s
  dependsOn:
    - name: infrastructure
  sourceRef:
    kind: GitRepository
    name: flux-system
  path: ./apps/staging
  prune: true
  wait: true
EOF
cat > ./clusters/staging/infrastructure.yaml << EOF
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
  name: infrastructure
  namespace: flux-system
spec:
  interval: 10m0s
  sourceRef:
    kind: GitRepository
    name: flux-system
  path: ./infrastructure
  prune: true
  wait: true
EOF

Step 9: Create the initial commit

Once we create all initial configurations, we can commit and push the code to your repository. The next step is to bootstrap clusters with the Flux CLI command.

├── apps
│   ├── base
│   │   └── traefik
│   │       ├── kustomization.yaml
│   │       ├── rbac.yaml
│   │       ├── svc.yaml
│   │       └── traefik.yaml
│   ├── production
│   │   └── traefik
│   │       ├── kustomization.yaml
│   │       ├── namespace.yaml
│   │       └── traefik-patch.yaml
│   └── staging
│       └── traefik
│           ├── kustomization.yaml
│           ├── namespace.yaml
│           └── traefik-patch.yaml
├── clusters
│   ├── production
│   │   ├── apps.yaml
│   │   └── infrastructure.yaml
│   └── staging
│       ├── apps.yaml
│       └── infrastructure.yaml
└── infrastructure
    ├── crds
    │   ├── kustomization.yaml
    │   └── traefik-crds.yaml
    ├── kustomization.yaml
    └── sources

Step 10: Bootstrap your clusters

Once you have created the configuration files, you can bootstrap Flux on both clusters. Before running the bootstrap command, make sure to export the following environment variables.

export GITHUB_TOKEN
export GITHUB_USER
export GITHUB_REPO

GITHUB_USER refers to your username, and GITHUB_REPO refers to the repo you created earlier.

Change the Kubernetes context to the staging cluster and then execute the command that will bootstrap Flux on a staging cluster.

flux bootstrap github \
--branch=main \
--context=t1.aws.traefiklabs.tech \
--owner=${GITHUB_USER} \
--repository=${GITHUB_REPO} \
--path=clusters/staging \
--components-extra=image-reflector-controller,image-automation-controller  \
--personal

Observe the following command that will present the status of the provisioned Flux resources. You can also manually explore other resources that have been declared in the created Kubernetes manifests.

Once the staging cluster has been correctly configured, switch the Kubernetes context to the production cluster and execute the following command.

flux bootstrap github \
--branch=main \
--context=t2.aws.traefiklabs.tech \
--owner=${GITHUB_USER} \
--repository=${GITHUB_REPO} \
--path=clusters/production \
--components-extra=image-reflector-controller,image-automation-controller  \
--personal

Note

The two commands are very similar. The only difference is in the path parameter that's set to either clusters/staging or clusters/production.

Explore the resources that have been configured on your cluster. You can also interact with the Flux CLI to explore the status of all your Flux resources.

Step 11: Create a base deployment for the whoami application

Create a base configuration for the whoami application. The whoami application is a simple demo application that displays headers from the containers. It is a kind of echo server that we use for testing purposes.

mkdir -pv ./apps/{base,staging,production}/whoami
cat > ./apps/base/whoami/deployment.yaml << EOF
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: whoamiv1
  labels:
    name: whoamiv1
spec:
  replicas: 1
  selector:
    matchLabels:
      task: whoamiv1
  template:
    metadata:
      labels:
        task: whoamiv1
    spec:
      containers:
        - name: whoamiv1
          image: traefik/traefikee-webapp-demo:v2
          args:
            - -ascii
            - -name=FOO
          ports:
            - containerPort: 80
          readinessProbe:
            httpGet:
              path: /ping
              port: 80
            failureThreshold: 1
            initialDelaySeconds: 2
            periodSeconds: 3
            successThreshold: 1
            timeoutSeconds: 2
          resources:
            requests:
              cpu: 10m
              memory: 128Mi
            limits:
              cpu: 200m
              memory: 256Mi
---
apiVersion: v1
kind: Service
metadata:
  name: whoamiv1
  namespace: app
spec:
  ports:
    - name: http
      port: 80
  selector:
    task: whoamiv1
EOF

Create an IngressRoute object that exposes the whoami application. The Ingressroute is one of Traefik CRD's resources that create IngressRoute objects to create routers that expose applications externally. You can learn more about this in the official Traefik Proxy documentation on Kubernetes IngressRoutes.

cat > ./apps/base/whoami/ingressroute.yaml << EOF
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: whoami
spec:
  entryPoints:
    - websecure
  routes:
    - kind: Rule
      match: Host(\`fix.me\`)
      services:
        - kind: Service
          name: whoamiv1
          port: 80
  tls:
    certResolver: myresolver
EOF
cat > ./apps/base/whoami/kustomization.yaml << EOF
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - deployment.yaml
  - ingressroute.yaml
EOF

Step 12: Create a custom release for your staging environment

Create a namespace where the whoami application will be deployed.

cat > ./apps/staging/whoami/namespace.yaml <<EOF
---
apiVersion: v1
kind: Namespace
metadata:
  name: whoami-staging
EOF

Create a patch for the whoami application. The changes we are adding here are strictly related to the staging environment. It is a tiny change. We are only changing the header, but you can add more environment-related updates such as mounting different secrets and adding Staging environment variables if you choose.

cat > ./apps/staging/whoami/whoami-patch.yaml << EOF
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: whoamiv1
spec:
  replicas: 4
  template:
    spec:
      containers:
        - name: whoamiv1
          args:
            - -ascii
            - -name=STAGING
EOF

Create a patch that updates the Host rule for the whoami application. The patch is needed to update the host rule that will be used to access the whoami application.

cat > ./apps/staging/whoami/ingressroute-patch.yaml <<EOF
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: whoami
spec:
  routes:
   - kind: Rule
     match: Host(\`whoami.t1.demo.traefiklabs.tech\`)
     services:
        - kind: Service
          name: whoamiv1
          port: 80
EOF

Create a Kustomization configuration to deploy the whoami application on your staging cluster.

cat > ./apps/staging/whoami/kustomization.yaml << EOF
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: whoami-staging
resources:
  - namespace.yaml
  - ../../base/whoami

patchesStrategicMerge:
  - whoami-patch.yaml
  - ingressroute-patch.yaml
EOF

Step 13: Create a custom release for your production environment

Create a namespace for the whoami application to be deployed to production.

cat > ./apps/production/whoami/namespace.yaml << EOF
---
apiVersion: v1
kind: Namespace
metadata:
  name: whoami-production
EOF

Create a patch for the whoami application. It is a tiny change to show the difference between staging and production examples. In an actual use case, you can add more changes to the production environment, such as mounting production ConfigMaps, Secrets, or environment variables.

cat > ./apps/production/whoami/whoami-patch.yaml << EOF
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: whoamiv1
spec:
  replicas: 8
  template:
    spec:
      containers:
        - name: whoamiv1
          args:
            - -ascii
            - -name=PRODUCTION
EOF

Create a patch that updates the Host rule for the whoami application. The patch just changed the value of Host matching rule.

cat > ./apps/production/whoami/ingressroute-patch.yaml << EOF
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: whoami
spec:
  routes:
   - kind: Rule
     match: Host(\`whoami.t2.demo.traefiklabs.tech\`)
     services:
        - kind: Service
          name: whoamiv1
          port: 80
EOF

Create a Kustomization configuration to deploy the whoami application to your production cluster.

cat > ./apps/production/whoami/kustomization.yaml << EOF
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: whoami-production
resources:
  - namespace.yaml
  - ../../base/whoami

patchesStrategicMerge:
  - whoami-patch.yaml
  - ingressroute-patch.yaml
EOF

And there you have it. You have successfully deployed Traefik Proxy in Flux using a GitOps approach if you have followed these steps. This makes it easier for you to maintain multiple configurations in Kubernetes.

Conclusion

Let's summarize what we have already achieved. We started with two built-from-scratch clusters where there were no resources created. Then we created our directory structure, and all the necessary Kubernetes manifests. We:

  • Deployed Traefik Proxy with the required resources (service account, RBAC)
  • Deployed a test application
  • Created the Ingressroute to reach the test application

We created a base configuration and then used Kustomize to create overlays for our staging and production environments. We used a feature called patchStrategicMerge to update our configuration for these environments accordingly. Again, the base configuration was inherited, and the only changes were applied and merged to have the final manifests.

Our entire configuration was done locally, without imperative interactions with our clusters. Once we were happy with the configuration, we pushed the changes to the repo and then bootstrapped Flux on our two clusters.

Once Flux was correctly started on our cluster, it could pull the configuration from the repository and apply it to the appropriate clusters.

Every change we would like to make must be done through a repository, so you edit or update the files and commit them to the repo. Flux will take care of deploying on the clusters.

What are the next steps?

There are many things to explore in regards to Flux and designing scalable infrastructures. I encourage you to look at Traefik's more advanced load balancing techniques. Check out this webinar to learn more. To participate in our community, get involved in our forum. There you can ask questions, post answers, and engage in discussions. I hope to see you there!