»Custom Resource Definitions (beta)

»Overview

We support managing Consul configuration entries via Kubernetes Custom Resources. Configuration entries are used to provide cluster-wide defaults for the service mesh.

We currently support the follow configuration entry kinds:

The following kinds are not currently supported:

»Installation

Ensure you have version 0.25.0 of the helm chart:

$ helm search repo hashicorp/consul
NAME                CHART VERSION   APP VERSION DESCRIPTION
hashicorp/consul    0.25.0          1.8.4       Official HashiCorp Consul Chart

If you don't have 0.25.0, you will need to update your helm repository cache:

$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "hashicorp" chart repository
Update Complete. ⎈Happy Helming!⎈

Next, you must configure consul-helm via your values.yaml to install the custom resource definitions and enable the controller that acts on them:

global:
  name: consul
  image: 'consul:1.9.0-beta1' # consul >= 1.8.4 must be used
  imageK8S: 'hashicorp/consul-k8s:0.19.0'

controller:
  enabled: true

connectInject:
  enabled: true

Note that:

  1. controller.enabled: true installs the CRDs and enables the controller.
  2. global.image must be a Consul version >= 1.8.4, e.g. consul:1.8.4 or consul:1.9.0-beta1.
  3. global.imageK8S must be >= 0.19.0
  4. Configuration entries are used to configure Consul service mesh so it's also expected that connectInject will be enabled.

See Install with Helm Chart for further installation instructions.

»Usage

Once installed, you can use kubectl to create and manage Consul's configuration entries.

»Create

You can create configuration entries via kubectl apply.

$ cat <<EOF | kubectl apply -f -
apiVersion: consul.hashicorp.com/v1alpha1
kind: ServiceDefaults
metadata:
  name: foo
spec:
  protocol: "http"
EOF

servicedefaults.consul.hashicorp.com/foo created

See Specifications for detailed schema documentation.

»Get

You can use kubectl get [kind] [name] to get the status of the configuration entry:

$ kubectl get servicedefaults foo
NAME  SYNCED
foo   True

The SYNCED status shows whether the configuration entry was successfully created in Consul.

»Describe

You can use kubectl describe [kind] [name] to investigate the status of the configuration entry. If SYNCED is false, the status will contain the reason why.

$ kubectl describe servicedefaults foo
Status:
  Conditions:
    Last Transition Time:  2020-10-09T21:15:50Z
    Status:                True
    Type:                  Synced

»Edit

You can use kubectl edit [kind] [name] to edit the configuration entry:

$ kubectl edit servicedefaults foo
# change protocol: http => protocol: tcp
servicedefaults.consul.hashicorp.com/foo edited

You can then use kubectl get to ensure the change was synced to Consul:

$ kubectl get servicedefaults foo
NAME  SYNCED
foo   True

»Delete

You can use kubectl delete [kind] [name] to delete the configuration entry:

$ kubectl delete servicedefaults foo
servicedefaults.consul.hashicorp.com "foo" deleted

You can then use kubectl get to ensure the configuration entry was deleted:

$ kubectl get servicedefaults foo
Error from server (NotFound): servicedefaults.consul.hashicorp.com "foo" not found

»Delete Hanging

If running kubectl delete hangs without exiting, there may be a dependent configuration entry registered with Consul that prevents the target configuration entry from being deleted. For example, if you set the protocol of your service to http via ServiceDefaults and then create a ServiceSplitter, you won't be able to delete the ServiceDefaults.

This is because by deleting the ServiceDefaults config, you are setting the protocol back to the default which is tcp. Since ServiceSplitter requires that the service has an http protocol, Consul will not allow the ServiceDefaults to be deleted since that would put Consul into a broken state.

In order to delete the ServiceDefaults config, you would need to first delete the ServiceSplitter.

»Specifications

»ProxyDefaults

A proxy-defaults entry configures global defaults across all proxies.

apiVersion: consul.hashicorp.com/v1alpha1
kind: ProxyDefaults
metadata:
  name: global
spec:
  config:
    envoy_tracing_json: '{"http":{"config":{"collector_cluster":"jaeger_9411","collector_endpoint":"/api/v2/spans"},"name":"envoy.zipkin"}}'
  expose:
    checks: true
    paths:
      - listenerPort: 80
        localPathPort: 42
        path: /test/path
        protocol: http
      - listenerPort: 8080
        localPathPort: 4201
        path: /root/test/path
        protocol: http2
  meshGateway:
    mode: local

Notes:

  1. There can only be one ProxyDefaults resource and its name must be global.
  2. Keys under spec.config will need to use snake_case, not camelCase, because this config is passed directly to Envoy which uses snake_case, e.g.
    spec:
      config:
        envoy_statsd_url: 'udp://127.0.0.1:8125'
    
  3. See proxy-defaults for full documentation on this config entry.

»ServiceDefaults

A service-defaults entry configures a specific service.

apiVersion: consul.hashicorp.com/v1alpha1
kind: ServiceDefaults
metadata:
  name: your-service-name
spec:
  protocol: https
  meshGateway:
    mode: local
  expose:
    checks: true
    paths:
      - listenerPort: 80
        path: /path
        localPathPort: 9000
        protocol: http
      - listenerPort: 8080
        path: /another-path
        localPathPort: 9091
        protocol: http2
  externalSNI: external-sni

Notes:

  1. The name of the service that this ServiceDefaults configures is set by metadata.name.
  2. See service-defaults for full documentation on this config entry.

»ServiceIntentions (Beta)

A service-intentions entry configures traffic authorization for a destination service.

apiVersion: consul.hashicorp.com/v1alpha1
kind: ServiceIntentions
metadata:
  name: my-intention
spec:
  destination:
    name: your-service-name
  sources:
    - name: svc1
      namespace: test
      action: allow
      permissions: []
      description: allow access from svc1
    - name: '*'
      namespace: not-test
      action: deny
      permissions: []
      description: disallow access from namespace not-test
    - name: svc-2
      namespace: bar
      action: ''
      permissions:
        - action: allow
          http:
            pathExact: /foo
            pathPrefix: /bar
            pathRegex: /baz
            header:
              - name: header
                present: true
                exact: exact
                prefix: prefix
                suffix: suffix
                regex: regex
                invert: true
            methods:
              - GET
              - PUT
      description: an L7 config

Notes:

  1. This resource is only supported in Consul 1.9.0.

  2. Unlike the other configuration entries, the value of metadata.name does not define which service the intention applies to. Instead, the name of the service this intention is configuring is set in spec.destination.name.

    The metadata.name field can be set to any value, however, we recommend setting it to the name of the destination service the intention is configuring.

  3. Wildcard intentions can be created by setting spec.destination.name to * and/or spec.sources[].name to *. For example to create a deny intention that applies to all services:

    apiVersion: consul.hashicorp.com/v1alpha1
    kind: ServiceIntentions
    metadata:
     name: deny-all
    spec:
     destination:
       name: *
     sources:
       - name: *
         action: deny
    
  4. See service-intentions for full documentation on this config entry.

»ServiceResolver

A service-resolver entry configures which service instances should satisfy Connect upstream discovery requests for a given service name.

apiVersion: consul.hashicorp.com/v1alpha1
kind: ServiceResolver
metadata:
  name: your-service-name
spec:
  defaultSubset: default_subset
  subsets:
    subset1:
      filter: filter1
      onlyPassing: true
    subset2:
      filter: filter2
  redirect:
    service: redirect
    serviceSubset: redirect_subset
    namespace: redirect_namespace
    datacenter: redirect_datacenter
  failover:
    failover1:
      service: failover1
      serviceSubset: failover_subset1
      namespaces: failover_namespace1
      datacenters:
        - failover1_dc1
        - failover1_dc2
    failover2:
      service: failover2
      serviceSubset: failover_subset2
      namespaces: failover_namespace2
      datacenters:
        - failover2_dc1
        - failover2_dc2
  connectTimeout: 1000000000
  loadBalancer:
    policy: policy
    ringHashConfig:
      minimumRingSize: 1
      maximumRingSize: 2
    leastRequestConfig:
      choiceCount: 1
    hashPolicies:
      - field: field
        fieldValue: value
        cookieConfig:
          session: true
          ttl: 1
          path: path
        sourceIP: true
        terminal: true

Notes:

  1. The name of the service that this ServiceResolver configures is set by metadata.name.
  2. See service-resolver for full documentation on this config entry.

»ServiceRouter

A service-router entry configures traffic routing and manipulation at networking layer 7 (e.g. HTTP).

apiVersion: consul.hashicorp.com/v1alpha1
kind: ServiceRouter
metadata:
  name: your-service-name
spec:
  routes:
    - match:
        http:
          pathExact: pathExact
          pathPrefix: pathPrefix
          pathRegex: pathRegex
          header:
            - name: name
              present: true
              exact: exact
              prefix: prefix
              suffix: suffix
              regex: regex
              invert: true
          queryParam:
            - name: name
              present: true
              exact: exact
              regex: regex
          methods:
            - method1
            - method2
      destination:
        service: service
        serviceSubset: serviceSubset
        namespace: namespace
        prefixRewrite: prefixRewrite
        requestTimeout: 1000000000
        numRetries: 1
        retryOnConnectFailure: true
        retryOnStatusCodes:
          - 500
          - 400

Notes:

  1. The name of the service that this ServiceRouter configures is set by metadata.name.
  2. See service-router for full documentation on this config entry.

»ServiceSplitter

A service-splitter entry configures splitting incoming requests across different subsets of a single service.

apiVersion: consul.hashicorp.com/v1alpha1
kind: ServiceSplitter
metadata:
  name: your-service-name
spec:
  splits:
    - weight: 25.5
      service: foo
      serviceSubset: v1
      namespace: baz
    - weight: 74.5
      service: foo
      serviceSubset: v2
      namespace: baz

Notes:

  1. The name of the service that this ServiceSplitter configures is set by metadata.name.
  2. See service-splitter for full documentation on this config entry.