Back to Charts

⚠️ Repo Archive Notice

stable/traefik/README.md

latest50.4 KB
Original Source

⚠️ Repo Archive Notice

As of Nov 13, 2020, charts in this repo will no longer be updated. For more information, see the Helm Charts Deprecation and Archive Notice, and Update.

Traefik

Traefik is a modern HTTP reverse proxy and load balancer made to deploy microservices with ease.

DEPRECATION NOTICE

This chart is deprecated and no longer supported.

Introduction

This chart bootstraps Traefik as a Kubernetes ingress controller with optional support for SSL and Let's Encrypt.

NOTE: Operators will typically wish to install this component into the kube-system namespace where that namespace's default service account will ensure adequate privileges to watch Ingress resources cluster-wide.

Prerequisites

  • Kubernetes 1.4+ with Beta APIs enabled
  • Kubernetes 1.6+ if you want to enable RBAC
  • You are deploying the chart to a cluster with a cloud provider capable of provisioning an external load balancer (e.g. AWS or GKE)
  • You control DNS for the domain(s) you intend to route through Traefik
  • Suggested: PV provisioner support in the underlying infrastructure

A Quick Note on Versioning

Up until version 1.2.1-b of this chart, the semantic version of the chart was kept in-sync with the semantic version of the (default) version of Traefik installed by the chart. A dash and a letter were appended to Traefik's semantic version to indicate incrementally improved versions of the chart itself. For example, chart version 1.2.1-a and 1.2.1-b both provide Traefik 1.2.1, but 1.2.1-b is a chart that is incrementally improved in some way from its immediate predecessor-- 1.2.1-a.

This convention, in practice, suffered from a few problems, not the least of which was that it defied what was permitted by semver 2.0.0. This, in turn, lead to some difficulty in Helm understanding the versions of this chart.

Beginning with version 1.3.0 of this chart, the version references only the revision of the chart itself. The appVersion field in chart.yaml now conveys information regarding the revision of Traefik that the chart provides.

Installing the Chart

To install the chart with the release name my-release:

bash
$ helm install stable/traefik --name my-release --namespace kube-system

After installing the chart, create DNS records for applicable domains to direct inbound traffic to the load balancer. You can use the commands below to find the load balancer's IP/hostname:

NOTE: It may take a few minutes for this to become available.

You can watch the status by running:

bash
$ kubectl get svc my-release-traefik --namespace kube-system -w

Once EXTERNAL-IP is no longer <pending>:

bash
$ kubectl describe service my-release-traefik -n kube-system | grep Ingress | awk '{print $3}'

NOTE: If ACME support is enabled, it is only after this step is complete that Traefik will be able to successfully use the ACME protocol to obtain certificates from Let's Encrypt.

Uninstalling the Chart

To uninstall/delete the my-release deployment:

bash
$ helm delete my-release

The command removes all the Kubernetes components associated with the chart and deletes the release.

Configuration

The following table lists the configurable parameters of the Traefik chart and their default values.

ParameterDescriptionDefault
fullnameOverrideOverride the full resource names{release-name}-traefik (or traefik if release-name is traefik)
imageTraefik image nametraefik
imageTagThe version of the official Traefik image to use1.7.26
imagePullSecretsA list of image pull secrets (if needed)None
imagePullPolicyContainer pull policyIfNotPresent
serviceTypeA valid Kubernetes service typeLoadBalancer
loadBalancerIPAn available static IP you have reserved on your cloud platformNone
startupArgumentsA list of startup arguments which are passed to traefik[]
pingEntryPointEntry point to use for the /ping health-check URL.http
loadBalancerSourceRangesList of IP CIDRs allowed access to load balancer (if supported)None
externalIPStatic IP for the serviceNone
whiteListSourceRangeEnable IP whitelisting at the entrypoint level.false
externalTrafficPolicySet the externalTrafficPolicy in the Service to either Cluster or LocalCluster
replicasThe number of replicas to run; NOTE: Full Traefik clustering with leader election is not yet supported, which can affect any configured Let's Encrypt setup; see Clustering section1
podDisruptionBudgetPod disruption budget{}
priorityClassNamePod priority class name""
rootCAsRegister Certificates in the RootCA. These certificates will be use for backends calls. NOTE: You can use file path or cert content directly[]
resourcesResource definitions for the generated pods{}
cpuRequestDEPRECATED: use resources instead. Initial share of CPU requested per Traefik podNone
memoryRequestDEPRECATED: use resources instead. Initial share of memory requested per Traefik podNone
cpuLimitDEPRECATED: use resources instead. CPU limit per Traefik podNone
memoryLimitDEPRECATED: use resources instead. Memory limit per Traefik podNone
rbac.enabledWhether to enable RBAC with a specific cluster role and binding for Traefikfalse
deploymentStrategySpecify deployment spec rollout strategy{}
podSecurityContextSecurity context for the pod. See PodSecurityContext.{}
containerSecurityContextSecurity context for the container. See SecurityContext.{}
useNonPriviledgedPortsUse non privileged ports to listen. Needed if container is not running as rootfalse
envEnvironment variables for the container{}
nodeSelectorNode labels for pod assignment{}
affinityAffinity settings{}
tolerationsList of node taints to tolerate[]
proxyProtocol.enabledEnable PROXY protocol support.false
proxyProtocol.trustedIPsList of PROXY IPs (CIDR ranges) trusted to accurately convey the end-user IP.[]
forwardedHeaders.enabledEnable support specify trusted clients for forwarded headers.false
forwardedHeaders.trustedIPsList of IPs (CIDR ranges) to be authorized to trust the client forwarded headers (X-Forwarded-*).[]
debug.enabledTurn on/off Traefik's debug mode. Enabling it will override the logLevel to DEBUG and provide /debug/vars endpoint that allows Go runtime stats to be inspected, such as number of Goroutines and memory statsfalse
logLevelAccepted values, in order of severity: "debug", "info", "warn", "error", "fatal", "panic". Messages at and above the selected level will be logged.info
maxIdleConnsPerHostControls the maximum idle (keep-alive) connections to keep per-host.None
ssl.enabledWhether to enable HTTPSfalse
ssl.enforcedWhether to redirect HTTP requests to HTTPSfalse
ssl.permanentRedirectWhen ssl.enforced is set, use a permanent (301) redirect instead of a temporary redirect (302)false
ssl.upstreamWhether to skip configuring certs (ie: SSL is terminated by L4 ELB)false
ssl.insecureSkipVerifyWhether to verify certs on SSL connectionsfalse
ssl.tlsMinVersionMinimum TLS version for https entrypointNone
ssl.cipherSuitesSpecify a non-empty list of TLS ciphers to override the default oneNone
ssl.sniStrictEnable strict SNI checking, so that connections cannot be made if a matching certificate does not exist.false
ssl.generateTLSGenerate self sign cert by Helm. If it's true the defaultCert and the defaultKey parameters will be ignored.false
ssl.defaultCNSpecify generated self sign cert CN""
ssl.defaultSANListSpecify generated self sign cert SAN list[]
ssl.defaultIPListSpecify generated self sign cert IP list[]
ssl.defaultCertBase64 encoded default certificateA self-signed certificate
ssl.defaultKeyBase64 encoded private key for the certificate aboveThe private key for the certificate above
ssl.extraCertsA list of any extra certificate/key filenames you want added to the https entrypoint. This must be used in conjunction with the secretFiles parameter to include the certs on each traefik pod pod[]
ssl.auth.basicBasic auth for all SSL endpoints, see Authentication sectionunset by default; this means basic auth is disabled
ssl.mtls.enabledWhether to enable mutual TLS. See here.false
ssl.mtls.optionalWhen ssl.mtls.enabled is set, whether to accept client certificates not signed by one of the CAs specified in ssl.mtls.clientCaCerts.false
ssl.mtls.clientCaCertsWhen ssl.mtls.enabled is set, an array of client CA certificates, each in PEM format.[]
acme.enabledWhether to use Let's Encrypt to obtain certificatesfalse
acme.keyTypeKeyType used for generating certificate private key. Allow value 'EC256', 'EC384', 'RSA2048', 'RSA4096', 'RSA8192'.RSA4096
acme.challengeTypeType of ACME challenge to perform domain validation. tls-alpn-01 (recommended), http-01 or dns-01tls-alpn-01
acme.delayBeforeCheckBy default, the provider will verify the TXT DNS challenge record before letting ACME verify. If delayBeforeCheck is greater than zero, this check is delayed for the configured duration in seconds. Useful when Traefik cannot resolve external DNS queries.0
acme.dnsProvider.nameWhich DNS provider to use. See here for the list of possible values.nil
acme.dnsProvider.existingSecretNameDon't create a secret for DNS provider configuration environment variables, but use the specified one instead. Secret should contain the required environment variables. Useful to avoid storing secrets in helm""
acme.dnsProvider.$nameThe configuration environment variables (encoded as a secret) needed for the DNS provider to do DNS challenge. Example configuration: AWS Route 53, Google Cloud DNS.{}
acme.emailEmail address to be used in certificates obtained from Let's Encrypt[email protected]
acme.onHostRuleWhether to generate a certificate for each frontend with Host ruletrue
acme.stagingWhether to get certs from Let's Encrypt's staging environmenttrue
acme.caServer(Advanced) Specify a custom ACME server endpoint. Overrides acme.staging behavior if specified.nil
acme.loggingDisplay debug log messages from the ACME client libraryfalse
acme.domains.enabledEnable certificate creation by default for specific domainfalse
acme.domains.domainsListList of domains & (optional) subject names[]
acme.domains.domainsList.mainMain domain name of the generated certificate*.example.com
acme.domains.domainsList.sansoptional list of alternative subject names to give to the certificate[]
acme.resolversDNS servers list to use for DNS challenge[]
acme.httpChallenge.entrypointThe entrypoint used for the http challenge. Only applicable when using http-01 as the challenge typehttp
acme.persistence.enabledCreate a volume to store ACME certs (if ACME is enabled)true
acme.persistence.annotationsPVC annotations{}
acme.persistence.storageClassType of StorageClass to request, will be cluster-specificnil (uses alpha storage class annotation)
acme.persistence.accessModeReadWriteOnce or ReadOnlyReadWriteOnce
acme.persistence.existingClaimAn Existing PVC namenil
acme.persistence.sizeMinimum size of the volume requested1Gi
kvprovider.storeAcmeStore acme certificates in KV Provider (needed for HA)false
kvprovider.acmeStorageLocationPath for storing acme datatraefik/acme/account
kvprovider.importAcmeImport acme certificates from acme.json of a mounted pvc (see: acme.persistence.existingClaim)false
kvprovider.$name.endpointEndpoint of the provider like <kv-provider-fqdn>:<port>None
kvprovider.$name.watchWether traefik should watch for changestrue
kvprovider.$name.prefixPrefix where traefik data will be storedtraefik
kvprovider.$name.filenameAdvanced configuration. See: https://docs.traefik.io/provider default
kvprovider.$name.usernameOptional usernameNone
kvprovider.$name.passwordOptional passwordNone
kvprovider.$name.tls.caOptional TLS certificate authorityNone
kvprovider.$name.tls.certOptional TLS certificateNone
kvprovider.$name.tls.keyOptional TLS keyfileNone
kvprovider.$name.tls.insecureSkipVerifyOptional Wether to skip verifyNone
kvprovider.etcd.useAPIV3Use V3 or use V2 API of ETCDfalse
dashboard.enabledWhether to enable the Traefik dashboardfalse
dashboard.domainDomain for the Traefik dashboardtraefik.example.com
dashboard.serviceTypeServiceType for the Traefik dashboard ServiceClusterIP
dashboard.service.annotationsAnnotations for the Traefik dashboard Service definition, specified as a mapNone
dashboard.ingress.annotationsAnnotations for the Traefik dashboard Ingress definition, specified as a mapNone
dashboard.ingress.labelsLabels for the Traefik dashboard Ingress definition, specified as a mapNone
dashboard.ingress.tlsTLS settings for the Traefik dashboard Ingress definitionNone
dashboard.auth.basicBasic auth for the Traefik dashboard specified as a map, see Authentication sectionunset by default; this means basic auth is disabled
dashboard.statistics.recentErrorsNumber of recent errors to show in the ‘Health’ tabNone
service.annotationsAnnotations for the Traefik Service definition, specified as a mapNone
service.labelsAdditional labels for the Traefik Service definition, specified as a map.None
service.nodePorts.httpDesired nodePort for service of type NodePort used for http requestsblank ('') - will assign a dynamic node port
service.nodePorts.httpsDesired nodePort for service of type NodePort used for https requestsblank ('') - will assign a dynamic node port
gzip.enabledWhether to use gzip compressiontrue
kubernetes.namespacesList of Kubernetes namespaces to watchAll namespaces
kubernetes.labelSelectorValid Kubernetes ingress label selector to watch (e.g realm=public).No label filter
kubernetes.ingressClassValue of kubernetes.io/ingress.class annotation to watch - must start with traefik if setNone
kubernetes.ingressEndpoint.hostnameDesired static hostname to update for ingress status specNone
kubernetes.ingressEndpoint.ipDesired static IP to update for ingress status specNone
kubernetes.ingressEndpoint.publishedServiceDesired namespace/service to source ingress status spec fromNone
kubernetes.ingressEndpoint.useDefaultPublishedServiceWhether to source namespace/service status spec from the service created by this chart. Mutually exclusive with kubernetes.ingressEndpoint.publishedServiceNone
fileBackendFile Backend configurationNone
accessLogs.enabledWhether to enable Traefik's access logsfalse
accessLogs.filtersOnly keep access logs based on filtersNone
accessLogs.filePathThe path to the log file. Logs to stdout if omittedNone
accessLogs.formatWhat format the log entries should be in. Either common or jsoncommon
accessLogs.fields.defaultModeThe default behaviour for fields logged in JSON access logs, other than headers. Either keep or dropkeep
accessLogs.fields.namesA map of field-specific logging behaviours in JSON access logs, with field names as keys, and either keep or drop as the value for each map entryNone
accessLogs.fields.headers.defaultModeThe default behaviour for logging HTTP headers in JSON access logs. Either keep, drop or redactkeep
accessLogs.fields.headers.namesA map of HTTP-header-specific logging behaviours in JSON access logs, with HTTP header names as keys, and keep, drop or redact as the value for each map entryNone
metrics.prometheus.enabledWhether to enable the /metrics endpoint for metric collection by Prometheus.false
metrics.prometheus.bucketsA list of response times (in seconds) - for each list element, Traefik will report all response times less than the element.[0.1,0.3,1.2,5]
metrics.prometheus.service.nameCustom service name for the Prometheus service``
metrics.prometheus.service.annotationsAnnotations for the Prometheus service{ prometheus.io/scrape: "true" }
metrics.prometheus.service.portPort for the Prometheus service9100
metrics.prometheus.service.typeType for the Prometheus serviceClusterIP
metrics.prometheus.service.loadBalancerIPStatic IP for the Prometheus Service when its type is LoadBalancer``
metrics.prometheus.service.loadBalancerSourceRangesIP range for allowed traffic for the Prometheus Service when its type is LoadBalancer``
metrics.prometheus.service.externalIPStatic IP for the service for the Prometheus Service when its type is LoadBalancer``
metrics.prometheus.service.whiteListSourceRangeStatic IP for the service for the Prometheus Service when its type is LoadBalancer``
metrics.prometheus.service.externalTrafficPolicySet the externalTrafficPolicy in the Service to either Cluster or Local for the Prometheus serviceCluster
metrics.prometheus.service.nodePortNode port for Prometheus service when its type is NodePort.9100
metrics.serviceMonitor.enabledWhether to enable servicemonitor for Prometheus.false
metrics.datadog.enabledWhether to enable pushing metrics to Datadog.false
metrics.datadog.addressDatadog host in the format <hostname>:<port>localhost:8125
metrics.datadog.pushIntervalHow often to push metrics to Datadog.10s
metrics.statsd.enabledWhether to enable pushing metrics to Statsd.false
metrics.statsd.addressStatsd host in the format <hostname>:<port>localhost:8125
metrics.statsd.pushIntervalHow often to push metrics to Statsd.10s
deployment.podAnnotationsAnnotations for the Traefik deployment.None
deployment.podLabelsLabels for the Traefik deployment.None
deployment.podAnnotationsAnnotations for the Traefik pod definitionNone
deployment.podLabelsLabels for the Traefik pod definitionNone
deployment.hostPort.httpEnabledWhether to enable hostPort binding to host for http.false
deployment.hostPort.httpPortDesired host port used for http requests.80
deployment.hostPort.httpsEnabledWhether to enable hostPort binding to host for https.false
deployment.hostPort.httpsPortDesired host port used for https requests.443
deployment.hostPort.dashboardEnabledWhether to enable hostPort binding to host for dashboard.false
deployment.hostPort.dashboardPortDesired host port used for accessing dashboard.8080
sendAnonymousUsageSend anonymous usage statistics.false
tracing.enabledWhether to enable request tracingfalse
tracing.backendTracing backend to use, either jaeger or zipkin or datadogNone
tracing.serviceNameService name to be used in tracing backendtraefik
tracing.jaeger.localAgentHostPortLocation of the Jaeger agent where spans will be sent127.0.0.1:6831
tracing.jaeger.samplingServerUrlAddress of the Jaeger agent HTTP sampling serverhttp://localhost:5778/sampling
tracing.jaeger.samplingTypeType of Jaeger sampler to use, one of: const, probabilistic, ratelimitingconst
tracing.jaeger.samplingParamValue passed to the Jaeger sampler1.0
tracing.zipkin.httpEndpointZipkin HTTP endpointhttp://localhost:9411/api/v1/spans
tracing.zipkin.debugEnables Zipkin debuggingfalse
tracing.zipkin.sameSpanUse Zipkin SameSpan RPC style tracesfalse
tracing.zipkin.id128BitUse Zipkin 128 bit root span IDstrue
tracing.datadog.localAgentHostPortLocation of the Datadog agent where spans will be sent127.0.0.1:8126
tracing.datadog.debugEnables Datadog debuggingfalse
tracing.datadog.globalTagApply shared tag in a form of Key:Value to all the traces""
timeouts.responding.readTimeoutThe maximum duration for reading the entire request, including the body. If zero, no timeout exists."0s"
timeouts.responding.writeTimeoutThe maximum duration before timing out writes of the response. If zero, no timeout exists."0s"
timeouts.responding.idleTimeoutThe maximum duration an idle (keep-alive) connection will remain idle before closing itself. If zero, no timeout exists."0s"
timeouts.forwarding.dialTimeoutThe amount of time to wait until a connection to a backend server can be established. If zero, no timeout exists."30s"
timeouts.forwarding.responseHeaderTimeoutThe amount of time to wait for a server's response headers after fully writing the request (including its body, if any). If zero, no timeout exists."30s"
autoscalingHorizontalPodAutoscaler for the traefik Deployment{}
configFilesConfig files to make available in the deployment. key=filename, value=file contents{}
secretFilesSecret files to make available in the deployment. key=filename, value=file contents{}
testFramework.enabledEnables test-frameworkfalse
testFramework.imagetest-framework image repository.dduportal/bats
testFramework.tagtest-framework image tag.0.4.0
forwardAuth.entryPointsEnable forward authentication for these entryPoints: "http", "https", "httpn"
forwardAuth.addressURL for forward authentication
forwardAuth.trustForwardHeaderTrust X-Forwarded-* headers
extraVolumeMountsAny extra volumes mounts to define for the Traefik container[]
extraVolumesAny extra volumes to define for the pod[]

Specify each parameter using the --set key=value[,key=value] argument to helm install. For example:

bash
$ helm install --name my-release --namespace kube-system \
  --set dashboard.enabled=true,dashboard.domain=traefik.example.com stable/traefik

The above command enables the Traefik dashboard on the domain traefik.example.com.

Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example:

bash
$ helm install --name my-release --namespace kube-system --values values.yaml stable/traefik

Clustering / High Availability

To enable cluster support, you need one of:

  • etcd
  • consul
  • boltdb
  • zookeeper

as kvprovider, especially when you are using Let's Encrypt. If you have already certificates stored as acme.json in an existing persistent volume claim, you can import it.

Given you have:

  • a running etcd operator:
  • you have created a master chart requiring this traefik chart
  • an existing pvc with an acme.json called acme-certs-pvc
  • you have an etcd template like:
    apiVersion: "etcd.database.coreos.com/v1beta2"
    kind: "EtcdCluster"
    metadata:
      name: {{ .Values.etcdCluster.name }}
      labels:
         app: {{ .Values.etcdCluster.name }}
      annotations:
         etcd.database.coreos.com/scope: clusterwide
    spec:
      size: 3
      version: "3.1.8"
    
  • and these values in your values.yaml
    etcdCluster:
      name: traefik-etcd-cluster
    
    traefik:
      replicas: 3
      acme:
        persistence:
          enabled: true
          existingClaim: acme-certs-pvc
      kvprovider:
        storeAcme: true
        importAcme: true
        etcd:
          endpoint: "traefik-etcd-cluster-client:2379"
          useAPIV3: false
          watch: true
          prefix: traefik
    

Then you are good to migrate your old certs into the kvprovider and run traefik in HA/Cluster-Mode.

Dashboard Basic Auth

Basic auth can be specified via dashboard.auth.basic as a map of usernames to passwords as below. See the linked Traefik documentation for accepted passwords encodings. It is advised to single quote passwords to avoid issues with special characters:

bash
$ helm install --name my-release --namespace kube-system \
  --set dashboard.enabled=true,dashboard.auth.basic.test='$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/' \
  stable/traefik

Alternatively in YAML form:

yaml
dashboard:
  enabled: true
  domain: traefik.example.com
  auth:
    basic:
      test: $apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/

Let's Encrypt domain verification using DNS challenge

When obtaining an ACME (Let's Encrypt) certificate, sometimes it's more desirable to do DNS challenge, for example, if the server you want to obtain a certificate for does not have a public IP address.

First, check if your DNS provider is supported by lego(the ACME library that Traefik is using). Next, you will need to configure the Traefik chart to use DNS challenge. In the ACME section:

yaml
acme:
  enabled: true
  challengeType: "dns-01"
  dnsProvider:
    name:  # name of the dns provider to use
    $name: # the configuration of the dns provider. See the following section for an example
      # variables that the specific dns provider requires

Let's Encrypt wildcard certificate

To obtain an ACME (Let's Encrypt) wildcard certificate you must use a DNS challenge as explained above. Then you need to specify the wildcard domain name in the acme.domains section like this :

yaml
acme:
  enabled: true
  challengeType: "dns-01"
  dnsProvider:
    name:  # name of the dns provider to use
    $name: # the configuration of the dns provider. See the following section for an example
      # variables that the specific dns provider requires
  domains:
    enabled: true
    domainsList:
      - main: "*.example.com" # name of the wildcard domain name for the certificate
      - sans:
        - "example.com" # OPTIONAL: Alternative name(s) for the certificate, if you want the same certificate for the root of the domain name for example
      - main: "*.example2.com" # name of the wildcard domain name for the certificate

Example: AWS Route 53

Using route53 as DNS provider requires the following configuration variables to be set:

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • AWS_REGION

The configuration would look like this:

yaml
acme:
  enabled: true
  dnsProvider:
    name: route53
    route53:
      AWS_ACCESS_KEY_ID: ...
      AWS_SECRET_ACCESS_KEY: ...
      AWS_REGION: us-east-1

Example: Google Cloud DNS

Using gcloud as DNS provider requires the following configuration variables to be set:

  • GCE_PROJECT
  • GCE_SERVICE_ACCOUNT_FILE

The configuration would look like this:

yaml

secretFiles:
  gcloud-credentials.json: '{"type":"service_account","project_id":"<projectName>","private_key_id":"<hash>",...}'

acme:
  enabled: true
  dnsProvider:
    name: gcloud
    gcloud:
      GCE_PROJECT: <projectName>
      GCE_SERVICE_ACCOUNT_FILE: /secrets/gcloud-credentials.json

Proxy Protocol

In situations where Traefik lives behind an Internet-facing loadbalancer (like an AWS ELB) and you still want it to see the actual source IP of the visitor instead of the internal IP of the loadbalancer, you can enable the loadbalancer to use the Proxy protocol to talk to Traefik. This effectively makes the loadbalancer transparent, as Traefik will still get the actual visitor IP address for each request. This only works if Traefik knows it's receiving traffic via the Proxy Protocol and the loadbalancer IP addresses need to be whitelisted as well.

How to set this up on AWS is described in the Kubernetes documentation here, it can easily be done by adding an annotation to the Service definition.

Caution

If only one of the components (either the loadbalancer or Traefik) is set to use the Proxy protocol and the other is not, this will break badly as they will not be able to communicate with each other.