June 20-22 Announcing HashiConf Europe full schedule: keynotes, sessions, labs & more Register Now
  • Overview
    • Consul on Kubernetes
    • Control access with Consul API Gateway
    • Discover Services with Consul
    • Enforce Zero Trust Networking with Consul
    • Load Balancing with Consul
    • Manage Traffic with Consul
    • Multi-Platform Service Mesh with Consul
    • Network Infrastructure Automation with Consul
    • Observability with Consul
  • Enterprise
  • Tutorials
  • Docs
  • API
  • CLI
  • Community
GitHub
Download
Try HCP Consul
    • v1.12.x (latest)
    • v1.11.x
    • v1.10.x
    • v1.9.x
    • v1.8.x
    • Overview
      • Overview
      • What is a Service Mesh?
      • Overview
      • Chef, Puppet, etc.
      • Nagios
      • SkyDNS
      • SmartStack
      • Serf
      • Eureka
      • Istio
      • Envoy and Other Proxies
      • Custom Solutions
    • Overview
    • Manual Bootstrap
    • Consul Agent
    • Glossary
    • Required Ports
    • Bootstrapping a Datacenter
    • Cloud Auto-join
    • Server Performance
    • Kubernetes
  • API
  • Commands (CLI)
    • Register Services - Service Definitions
    • Find Services - DNS Interface
    • Monitor Services - Check Definitions
    • Overview
    • How Service Mesh Works
    • Configuration
      • Overview
      • Ingress Gateway
      • Mesh
      • Exported Services
      • Proxy Defaults
      • Service Defaults
      • Service Intentions
      • Service Resolver
      • Service Router
      • Service Splitter
      • Terminating Gateway
      • Overview
      • Envoy
      • Built-in Proxy
      • Proxy Integration
      • Managed (Deprecated)
      • Overview
      • Proxy Service Registration
      • Sidecar Service Registration
    • Service-to-service permissions - Intentions
    • Service-to-service permissions - Intentions (Legacy Mode)
    • Transparent Proxy
      • Overview
      • UI Visualization
      • Overview
      • Discovery Chain
    • Connectivity Tasks
    • Distributed Tracing
      • Overview
        • WAN Federation
        • Enabling Service-to-service Traffic Across Datacenters
        • Enabling Service-to-service Traffic Across Admin Partitions
      • Ingress Gateways
      • Terminating Gateways
    • Nomad
    • Kubernetes
      • Overview
      • Go Integration
      • Overview
      • Built-In CA
      • Vault
      • ACM Private CA
    • Develop and Debug
    • Security
    • Overview
    • Installation
    • Technical Specifications
    • Common Errors
    • Upgrades
    • Overview
    • Architecture
      • Installing Consul on Kubernetes
      • Installing Consul K8s CLI
        • Minikube
        • Kind
        • AKS (Azure)
        • EKS (AWS)
        • GKE (Google Cloud)
        • Red Hat OpenShift
        • Self Hosted Kubernetes
        • Consul Clients Outside Kubernetes
        • Consul Servers Outside Kubernetes
        • Single Consul Datacenter in Multiple Kubernetes Clusters
        • Consul Enterprise
        • Overview
        • Federation Between Kubernetes Clusters
        • Federation Between VMs and Kubernetes
        • Overview
        • Systems Integration
          • Overview
          • Bootstrap Token
          • Enterprise License
          • Gossip Encryption Key
          • Partition Token
          • Replication Token
          • Server TLS
          • Service Mesh Certificates
          • Snapshot Agent Config
        • WAN Federation
      • Compatibility Matrix
      • Overview
      • Transparent Proxy
      • Ingress Gateways
      • Terminating Gateways
      • Ingress Controllers
      • Configuring a Connect CA Provider
      • Health Checks
        • Metrics
    • Service Sync
      • Overview
      • Upgrade An Existing Cluster to CRDs
    • Annotations and Labels
    • Consul DNS
      • Upgrading Consul on Kubernetes
      • Upgrading Consul K8s CLI
      • Uninstall
      • Certificate Rotation
      • Gossip Encryption Key Rotation
      • Configure TLS on an Existing Cluster
      • Common Error Messages
      • FAQ
    • Helm Chart Configuration
    • Consul K8s CLI Reference
    • Overview
    • Requirements
    • Task Resource Usage
      • Installation
      • Secure Configuration
      • Migrate Existing Tasks
      • Installation
      • Secure Configuration
      • ACL Controller
    • Architecture
    • Consul Enterprise
    • Configuration Reference
    • Overview
      • Installation
      • Requirements
      • Configure
      • Run Consul-Terraform-Sync
    • Architecture
      • Overview
      • Status
      • Tasks
      • Overview
      • task
    • Configuration
    • Tasks
    • Terraform Modules
      • Overview
      • License
      • Terraform Cloud Driver
      • Overview
      • Terraform
      • Terraform Cloud
    • Compatibility
    • Consul KV
    • Sessions
    • Watches
    • Overview
      • General
      • CLI Reference
      • Configuration Reference
    • Configuration Entries
    • Telemetry
    • Sentinel
    • RPC
    • Overview
      • ACL System Overview
      • Tokens
      • Policies
      • Roles
      • Rules Reference
      • Legacy Mode
      • Token Migration
      • ACLs in Federated Datacenters
        • Overview
        • Kubernetes
        • JWT
        • OIDC
        • AWS IAM
    • Encryption
      • Overview
      • Core
      • Network Infrastructure Automation
    • Overview
    • Admin Partitions
    • Audit Logging
    • Automated Backups
    • Automated Upgrades
    • Enhanced Read Scalability
    • Single sign-on - OIDC
    • Redundancy Zones
    • Advanced Federation
    • Network Segments
    • Namespaces
    • NIA with TFE
    • Sentinel
      • Overview
      • FAQ
    • Overview
    • Improving Consul Resilience
    • Anti-Entropy
    • Consensus Protocol
    • Gossip Protocol
    • Jepsen Testing
    • Network Coordinates
    • Consul Integration Program
    • NIA Integration Program
    • Vault Integration
    • Proxy Integration
  • Consul Tools
    • Overview
    • Compatibility Promise
    • Specific Version Details
      • Overview
      • General Process
      • Upgrading to 1.2.4
      • Upgrading to 1.6.9
      • Upgrading to 1.8.13
      • Upgrading to 1.10.0
    • Common Error Messages
    • FAQ
    • Overview
      • v1.11.x
      • v1.10.x
      • v1.9.x
      • v0.1.x
      • v0.2.x
      • v0.4.x
      • v0.3.x
      • v0.2.x
      • v0.5.x
      • v0.6.0-beta
    • Overview
    • ACL
  • Guides
Type '/' to Search

»Federation Between Kubernetes Clusters with Vault as Secrets Backend

Note: This topic requires familiarity with Mesh Gateways, WAN Federation Via Mesh Gateways.

This page describes how you can federate multiple Kubernetes clusters using Vault as the secrets backend. See the Multi-Cluster Overview for more information on use cases and how it works.

»Differences Between Using Kubernetes Secrets vs. Vault

The Federation Between Kubernetes Clusters page provides an overview of WAN Federation using Mesh Gateways with Kubernetes secrets as the secret backend. When using Vault as the secrets backend, there are different systems and data integration configuration that will be explained in the Usage section of this page. The other main difference is that when using Vault, there is no need for you to export and import a Federation Secret in each datacenter.

»Usage

The expected use case is to create WAN Federation on Kubernetes clusters. The following procedure will result in a WAN Federation with Vault as the secrets backend between two clusters, dc1 and dc2. dc1 will act as the primary Consul cluster and will also contain the Vault server installation. dc2 will be the secondary Consul cluster.

Consul on Kubernetes with Vault as the Secrets Backend

The Vault Injectors in each cluster will ensure that every pod in cluster has a Vault agent inject into the pod.

Vault Injectors inject Vault agents into pods

The Vault Agents on each Consul pod will communicate directly with Vault on its externally accessible endpoint. Consul pods are also configured with Vault annotations that configure the secrets that the pod needs as well as the path that the Vault agent should locally store those secrets.

Vault agent and server communication

The two data centers will federated using mesh gateways. This communication topology is also described in the WAN Federation Via Mesh Gateways section of Multi-Cluster Federation Overview.

Mesh Federation via Mesh Gateways

»Install Vault

In this setup, you will deploy Vault server in the primary datacenter (dc1) Kubernetes cluster, which is also the primary Consul datacenter. You will configure your Vault Helm installation in the secondary datacenter (dc2) Kubernetes cluster to use it as an external server. This way there will be a single vault server cluster that will be used by both Consul datacenters.

Note: For demonstration purposes, you will deploy a Vault server in dev mode. For production installations, this is not recommended. Please visit the Vault Deployment Guide for guidance on how to install Vault in a production setting.

  1. Change your current Kubernetes context to target the primary datacenter (dc1).

    $ kubectl config use-context <context for dc1>
    
    $ kubectl config use-context <context for dc1>
    
  2. Now, use the values files below for your Helm install.

    server:
      dev:
        enabled: true
      service:
        enabled: true
        type: LoadBalancer
    ui:
      enabled: true
    
    vault-dc1.yaml
    server:
      dev:
        enabled: true
      service:
        enabled: true
        type: LoadBalancer
    ui:
      enabled: true
    
    $ helm install vault-dc1 --values vault-dc1.yaml hashicorp/vault --wait
    
    $ helm install vault-dc1 --values vault-dc1.yaml hashicorp/vault --wait
    

»Configuring your local environment

  1. Install Consul locally so that you can generate the gossip key. Please see the Precompiled Binaries section of the Install Consul page.

  2. Set the VAULT_TOKEN with a default value.

    $ export VAULT_ADDR=root
    
    $ export VAULT_ADDR=root
    
  3. Get the external IP or DNS name of the Vault server's load balancer.

    On EKS, you can get the IP address of the Vault server's load balancer with the following command:
    $ export VAULT_SERVER_HOST=$(kubectl get svc vault-dc1 -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
    
    $ export VAULT_SERVER_HOST=$(kubectl get svc vault-dc1 -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
    
  4. Set the VAULT_ADDR environment variable.

    $ export VAULT_ADDR=http://${VAULT_SERVER_HOST}:8200
    
    $ export VAULT_ADDR=http://${VAULT_SERVER_HOST}:8200
    

»Systems Integration

»Overview

To use Vault as the Service Mesh Certificate Provider in Kubernetes, you must complete following systems integration actions:

  • One time setup in Vault
    1. Enabling Vault KV Secrets Engine - Version 2.
    2. Enabling Vault PKI Engine.
  • Setup per Consul datacenter
    1. Installing the Vault Injector within the Consul datacenter installation
    2. Configuring a Kubernetes Auth Method in Vault to authenticate and authorize operations from the Consul datacenter
    3. Enable Vault as the Secrets Backend in the Consul datacenter

»One time setup on Vault

  1. Enable Vault KV secrets engine - Version 2 in order to store the Gossip Encryption Key and the ACL Replication token (global.acls.replicationToken).

    $ vault secrets enable -path=consul kv-v2
    
    $ vault secrets enable -path=consul kv-v2
    
  2. Enable Vault PKI Engine in order to leverage Vault for issuing Consul Server TLS certificates.

    $ vault secrets enable pki
    
    $ vault secrets enable pki
    
    $ vault secrets tune -max-lease-ttl=87600h pki
    
    $ vault secrets tune -max-lease-ttl=87600h pki
    

»Setup per Consul datacenter

»Primary Datacenter (dc1)

  1. Install the Vault Injector in your Consul Kubernetes cluster (dc1), which is used for accessing secrets from Vault.

    Note: In the primary datacenter (dc1), you will not have to configure injector.externalvaultaddr value because the Vault server is in the same primary datacenter (dc1) cluster.

    server:
      dev:
        enabled: true
      service:
        enabled: true
        type: LoadBalancer
    injector:
      enabled: true
      authPath: auth/kubernetes-dc1
    ui:
      enabled: true
    
    vault-dc1.yaml
    1 2 3 4 5 6 7 8 9 1011server:
      dev:
        enabled: true
      service:
        enabled: true
        type: LoadBalancer
    injector:
      enabled: true
      authPath: auth/kubernetes-dc1
    ui:
      enabled: true
    

    Next, install Vault in the Kubernetes cluster.

    $ helm upgrade vault-dc1 --values vault-dc1.yaml hashicorp/vault --wait
    
    $ helm upgrade vault-dc1 --values vault-dc1.yaml hashicorp/vault --wait
    
  2. Configure the Kubernetes Auth Method in Vault for the primary datacenter (dc1).

    $ vault auth enable -path=kubernetes-dc1 kubernetes
    
    $ vault auth enable -path=kubernetes-dc1 kubernetes
    

    Because Consul is in the same datacenter cluster as Vault, the Vault Auth Method can use its own CA Cert and JWT to authenticate Consul dc1 service account requests. Therefore, you do not need to set token_reviewer and kubernetes_ca_cert on the dc1 Kubernetes Auth Method.

  3. Configure Auth Method with Kubernetes API host

    $ vault write auth/kubernetes-dc1/config kubernetes_host=https://kubernetes.default.svc
    
    $ vault write auth/kubernetes-dc1/config kubernetes_host=https://kubernetes.default.svc
    
  4. Enable Vault as the secrets backend in the primary datacenter (dc1). However, you will not yet apply the Helm install command. You will issue the Helm upgrade command after the Data Integration section.

    global:
      secretsBackend:
        vault:
          enabled: true
    
    consul-dc1.yaml
    global:
      secretsBackend:
        vault:
          enabled: true
    

»Secondary Datacenter (dc2)

  1. Install the Vault Injector in the secondary datacenter (dc2).

    In the secondary datacenter (dc2), you will configure the externalvaultaddr value point to the external address of the Vault server in the primary datacenter (dc1).

    Change your Kubernetes context to target the secondary datacenter (dc2):

    $ kubectl config use-context <context for dc2>
    
    $ kubectl config use-context <context for dc2>
    
    server:
      enabled: false
    injector:
      enabled: true
      externalVaultAddr: ${VAULT_ADDR}
      authPath: auth/kubernetes-dc2
    
    vault-dc2.yaml
    server:
      enabled: false
    injector:
      enabled: true
      externalVaultAddr: ${VAULT_ADDR}
      authPath: auth/kubernetes-dc2
    

    Next, install Vault in the Kubernetes cluster.

    $ helm install vault-dc2 --values vault-dc2.yaml hashicorp/vault --wait
    
    $ helm install vault-dc2 --values vault-dc2.yaml hashicorp/vault --wait
    
  2. Configure the Kubernetes Auth Method in Vault for the datacenter

    $ vault auth enable -path=kubernetes-dc2 kubernetes
    
    $ vault auth enable -path=kubernetes-dc2 kubernetes
    
  3. Create a service account with access to the Kubernetes API in the secondary datacenter (dc2). For the secondary datacenter (dc2) auth method, you first need to create a service account that allows the Vault server in the primary datacenter (dc1) cluster to talk to the Kubernetes API in the secondary datacenter (dc2) cluster.

    $ cat <<EOF >> auth-method-serviceaccount.yaml
    # auth-method.yaml
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: vault-dc2-auth-method
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: system:auth-delegator
    subjects:
    - kind: ServiceAccount
      name: vault-dc2-auth-method
      namespace: default
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: vault-dc2-auth-method
      namespace: default
    EOF
    
    $ cat <<EOF >> auth-method-serviceaccount.yaml
    # auth-method.yaml
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: vault-dc2-auth-method
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: system:auth-delegator
    subjects:
    - kind: ServiceAccount
      name: vault-dc2-auth-method
      namespace: default
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: vault-dc2-auth-method
      namespace: default
    EOF
    
    $ kubectl apply --values auth-method-serviceaccount.yaml
    
    $ kubectl apply --values auth-method-serviceaccount.yaml
    
  4. Next, you will need to get the token and CA cert from that service account secret.

    $ export K8S_DC2_CA_CERT="$(kubectl get secret `kubectl get serviceaccounts vault-dc2-auth-method --output jsonpath='{.secrets[0].name}'` --output jsonpath='{.data.ca\.crt}' | base64 --decode)"
    
    $ export K8S_DC2_CA_CERT="$(kubectl get secret `kubectl get serviceaccounts vault-dc2-auth-method --output jsonpath='{.secrets[0].name}'` --output jsonpath='{.data.ca\.crt}' | base64 --decode)"
    
    $ export K8S_DC2_JWT_TOKEN="$(kubectl get secret `kubectl get serviceaccounts vault-dc2-auth-method --output jsonpath='{.secrets[0].name}'` --output jsonpath='{.data.token}' | base64 --decode)"
    
    $ export K8S_DC2_JWT_TOKEN="$(kubectl get secret `kubectl get serviceaccounts vault-dc2-auth-method --output jsonpath='{.secrets[0].name}'` --output jsonpath='{.data.token}' | base64 --decode)"
    
  5. Configure Auth Method with the JWT token of service account. You will have to get the externally reachable address of the secondary Consul datacenter (dc2) in the secondary Kubernetes cluster and set kubernetes_host within the Auth Method configuration.

    $ export KUBE_API_URL_DC2=$(kubectl config view --output jsonpath="{.clusters[?(@.name == \"$(kubectl config current-context)\")].cluster.server}")
    
    $ export KUBE_API_URL_DC2=$(kubectl config view --output jsonpath="{.clusters[?(@.name == \"$(kubectl config current-context)\")].cluster.server}")
    
    $ vault write auth/kubernetes-dc2/config \
      kubernetes_host="${KUBE_API_URL_DC2}" \
      token_reviewer_jwt="${K8S_DC2_JWT_TOKEN}" \
      kubernetes_ca_cert="${K8S_DC2_CA_CERT}"
    
    $ vault write auth/kubernetes-dc2/config \
      kubernetes_host="${KUBE_API_URL_DC2}" \
      token_reviewer_jwt="${K8S_DC2_JWT_TOKEN}" \
      kubernetes_ca_cert="${K8S_DC2_CA_CERT}"
    
  6. Enable Vault as the secrets backend in the secondary Consul datacenter (dc2). However, you will not yet apply the Helm install command. You will issue the Helm upgrade command after the Data Integration section.

    global:
      secretsBackend:
        vault:
          enabled: true
    
    values-dc2.yaml
    global:
      secretsBackend:
        vault:
          enabled: true
    

»Data Integration

»Overview

To use Vault as the Service Mesh Certificate Provider in Kubernetes, you must complete following data integration actions:

  • One time setup in Vault
    1. Store the secrets in Vault.
    2. Create a Vault policy that authorizes the desired level of access to the secrets.
  • Setup per Consul datacenter
    1. Create Vault Kubernetes auth roles that link the policy to each Consul on Kubernetes service account that requires access.
    2. Configure the Vault Kubernetes auth role in the Consul on Kubernetes helm chart.

»One time setup in Vault

  1. Store the ACL Replication Token, Gossip Encryption Key, and Root CA certificate secrets in Vault.

    $ vault kv put consul/secret/gossip key="$(consul keygen)"
    
    $ vault kv put consul/secret/gossip key="$(consul keygen)"
    
    $ vault kv put consul/secret/replication token="$(uuidgen | tr '[:upper:]' '[:lower:]')"
    
    $ vault kv put consul/secret/replication token="$(uuidgen | tr '[:upper:]' '[:lower:]')"
    
    $ vault write pki/root/generate/internal common_name="Consul CA" ttl=87600h
    
    $ vault write pki/root/generate/internal common_name="Consul CA" ttl=87600h
    
  2. Create Vault policies that authorize the desired level of access to the secrets.

    $ vault policy write gossip - <<EOF
    path "consul/data/secret/gossip" {
      capabilities = ["read"]
    }
    EOF
    
    $ vault policy write gossip - <<EOF
    path "consul/data/secret/gossip" {
      capabilities = ["read"]
    }
    EOF
    
    $ vault policy write replication-token - <<EOF
    path "consul/data/secret/replication" {
      capabilities = ["read"]
    }
    EOF
    
    $ vault policy write replication-token - <<EOF
    path "consul/data/secret/replication" {
      capabilities = ["read"]
    }
    EOF
    
    $ vault policy write ca-policy - <<EOF
    path "pki/cert/ca" {
      capabilities = ["read"]
    }
    EOF
    
    $ vault policy write ca-policy - <<EOF
    path "pki/cert/ca" {
      capabilities = ["read"]
    }
    EOF
    

»Setup per Consul datacenter

»Pre-installation for Primary Datacenter (dc1)

  1. Change your Kubernetes context to target the primary datacenter (dc1):
    $ kubectl config use-context <context for dc1>
    
    $ kubectl config use-context <context for dc1>
    

»Primary Datacenter (dc1)

  1. Create Server TLS and Service Mesh Cert Policies

    $ vault policy write consul-cert-dc1 - <<EOF
    path "pki/issue/consul-cert-dc1"
    {
      capabilities = ["create","update"]
    }
    EOF
    
    $ vault policy write consul-cert-dc1 - <<EOF
    path "pki/issue/consul-cert-dc1"
    {
      capabilities = ["create","update"]
    }
    EOF
    
    $ vault policy write connect-ca-dc1 - <<EOF
    path "/sys/mounts" {
      capabilities = [ "read" ]
    }
    path "/sys/mounts/connect_root" {
      capabilities = [ "create", "read", "update", "delete", "list" ]
    }
    path "/sys/mounts/dc1/connect_inter" {
      capabilities = [ "create", "read", "update", "delete", "list" ]
    }
    path "/connect_root/*" {
      capabilities = [ "create", "read", "update", "delete", "list" ]
    }
    path "/dc1/connect_inter/*" {
      capabilities = [ "create", "read", "update", "delete", "list" ]
    }
    EOF
    
    $ vault policy write connect-ca-dc1 - <<EOF
    path "/sys/mounts" {
      capabilities = [ "read" ]
    }
    path "/sys/mounts/connect_root" {
      capabilities = [ "create", "read", "update", "delete", "list" ]
    }
    path "/sys/mounts/dc1/connect_inter" {
      capabilities = [ "create", "read", "update", "delete", "list" ]
    }
    path "/connect_root/*" {
      capabilities = [ "create", "read", "update", "delete", "list" ]
    }
    path "/dc1/connect_inter/*" {
      capabilities = [ "create", "read", "update", "delete", "list" ]
    }
    EOF
    
  2. Create Vault Kubernetes auth roles that link the policy to each Consul on Kubernetes service account that requires access. For each auth method in Vault, you will need roles for the Consul server, Consul client, the server-acl-init job, and Consul server CA.

    $ vault write auth/kubernetes-dc1/role/consul-server \
            bound_service_account_names=consul-server \
            bound_service_account_namespaces="default" \
            policies="gossip,connect-ca-dc1,consul-cert-dc1" \
            ttl=24h
    
    $ vault write auth/kubernetes-dc1/role/consul-server \
            bound_service_account_names=consul-server \
            bound_service_account_namespaces="default" \
            policies="gossip,connect-ca-dc1,consul-cert-dc1" \
            ttl=24h
    
    $ vault write auth/kubernetes-dc1/role/consul-client \
            bound_service_account_names=consul-client \
            bound_service_account_namespaces="default" \
            policies="gossip" \
            ttl=24h
    
    $ vault write auth/kubernetes-dc1/role/consul-client \
            bound_service_account_names=consul-client \
            bound_service_account_namespaces="default" \
            policies="gossip" \
            ttl=24h
    
    $ vault write auth/kubernetes-dc1/role/server-acl-init \
            bound_service_account_names=consul-server-acl-init \
            bound_service_account_namespaces="default" \
            policies="replication-token" \
            ttl=24h
    
    $ vault write auth/kubernetes-dc1/role/server-acl-init \
            bound_service_account_names=consul-server-acl-init \
            bound_service_account_namespaces="default" \
            policies="replication-token" \
            ttl=24h
    
    $ vault write auth/kubernetes-dc1/role/consul-ca \
            bound_service_account_names="*" \
            bound_service_account_namespaces="default" \
            policies=ca-policy \
            ttl=1h
    
    $ vault write auth/kubernetes-dc1/role/consul-ca \
            bound_service_account_names="*" \
            bound_service_account_namespaces="default" \
            policies=ca-policy \
            ttl=1h
    
  3. Create the server TLS Cert role.

    $ vault write pki/roles/consul-cert-dc1 \
      allowed_domains="dc1.consul,consul-server,consul-server.default,consul-server.default.svc" \
      allow_subdomains=true \
      allow_bare_domains=true \
      allow_localhost=true \
      generate_lease=true \
      max_ttl="720h"
    
    $ vault write pki/roles/consul-cert-dc1 \
      allowed_domains="dc1.consul,consul-server,consul-server.default,consul-server.default.svc" \
      allow_subdomains=true \
      allow_bare_domains=true \
      allow_localhost=true \
      generate_lease=true \
      max_ttl="720h"
    
  4. Configure and install Consul in the primary datacenter (dc1).

    global:
      datacenter: "dc1"
      name: consul
      secretsBackend:
        vault:
          enabled: true
          consulServerRole: consul-server
          consulClientRole: consul-client
          consulCARole: consul-ca
          manageSystemACLsRole: server-acl-init
          connectCA:
            address: http://vault-dc1.default:8200
            rootPKIPath: connect_root/
            intermediatePKIPath: dc1/connect_inter/
            authMethodPath: kubernetes-dc1
      tls:
        enabled: true
        enableAutoEncrypt: true
        caCert:
          secretName: pki/cert/ca
      federation:
        enabled: true
      acls:
        manageSystemACLs: true
        replicationToken:
          secretName: consul/data/secret/replication
          secretKey: token
      gossipEncryption:
        secretName: consul/data/secret/gossip
        secretKey: key
    server:
      replicas: 1
      serverCert:
        secretName: "pki/issue/consul-cert-dc1"
    connectInject:
      replicas: 1
      enabled: true
    controller:
      enabled: true
    meshGateway:
      enabled: true
      replicas: 1
    
    consul-dc1.yaml
    global:
      datacenter: "dc1"
      name: consul
      secretsBackend:
        vault:
          enabled: true
          consulServerRole: consul-server
          consulClientRole: consul-client
          consulCARole: consul-ca
          manageSystemACLsRole: server-acl-init
          connectCA:
            address: http://vault-dc1.default:8200
            rootPKIPath: connect_root/
            intermediatePKIPath: dc1/connect_inter/
            authMethodPath: kubernetes-dc1
      tls:
        enabled: true
        enableAutoEncrypt: true
        caCert:
          secretName: pki/cert/ca
      federation:
        enabled: true
      acls:
        manageSystemACLs: true
        replicationToken:
          secretName: consul/data/secret/replication
          secretKey: token
      gossipEncryption:
        secretName: consul/data/secret/gossip
        secretKey: key
    server:
      replicas: 1
      serverCert:
        secretName: "pki/issue/consul-cert-dc1"
    connectInject:
      replicas: 1
      enabled: true
    controller:
      enabled: true
    meshGateway:
      enabled: true
      replicas: 1
    

    Next, install Consul in the primary Kubernetes cluster (dc1).

    $ helm install consul-dc1 --values consul-dc1.yaml hashicorp/consul
    
    $ helm install consul-dc1 --values consul-dc1.yaml hashicorp/consul
    

»Pre-installation for Secondary Datacenter (dc2)

  1. Configure the Vault Kubernetes auth role in the Consul on Kubernetes Helm chart. For secondary datacenter (dc2), you will need to get the address of the mesh gateway from the primary datacenter (dc1) cluster.

    Keep your Kubernetes context targeting dc1 and set the MESH_GW_HOST environment variable that you will use in the Consul Helm chart for secondary datacenter (dc2).

    $ kubectl config use-context <context for dc1>
    
    $ kubectl config use-context <context for dc1>
    

    Next, get mesh gateway address:

    $ export MESH_GW_HOST=$(kubectl get svc consul-mesh-gateway --output jsonpath='{.status.loadBalancer.ingress[0].hostname}')
    
    $ export MESH_GW_HOST=$(kubectl get svc consul-mesh-gateway --output jsonpath='{.status.loadBalancer.ingress[0].hostname}')
    
  2. Change your Kubernetes context to target the primary datacenter (dc2):

    $ kubectl config use-context <context for dc2>
    
    $ kubectl config use-context <context for dc2>
    

»Secondary Datacenter (dc2)

  1. Create Server TLS and Service Mesh Cert Policies

    $ vault policy write consul-cert-dc2 - <<EOF
    path "pki/issue/consul-cert-dc2"
    {
      capabilities = ["create","update"]
    }
    EOF
    
    $ vault policy write consul-cert-dc2 - <<EOF
    path "pki/issue/consul-cert-dc2"
    {
      capabilities = ["create","update"]
    }
    EOF
    
    $ vault policy write connect-ca-dc2 - <<EOF
    path "/sys/mounts" {
      capabilities = [ "read" ]
    }
    path "/sys/mounts/connect_root" {
      capabilities = [ "create", "read", "update", "delete", "list" ]
    }
    path "/sys/mounts/dc2/connect_inter" {
      capabilities = [ "create", "read", "update", "delete", "list" ]
    }
    path "/connect_root/*" {
      capabilities = [ "create", "read", "update", "delete", "list" ]
    }
    path "/dc2/connect_inter/*" {
      capabilities = [ "create", "read", "update", "delete", "list" ]
    }
    EOF
    
    $ vault policy write connect-ca-dc2 - <<EOF
    path "/sys/mounts" {
      capabilities = [ "read" ]
    }
    path "/sys/mounts/connect_root" {
      capabilities = [ "create", "read", "update", "delete", "list" ]
    }
    path "/sys/mounts/dc2/connect_inter" {
      capabilities = [ "create", "read", "update", "delete", "list" ]
    }
    path "/connect_root/*" {
      capabilities = [ "create", "read", "update", "delete", "list" ]
    }
    path "/dc2/connect_inter/*" {
      capabilities = [ "create", "read", "update", "delete", "list" ]
    }
    EOF
    
  2. Create Vault Kubernetes auth roles that link the policy to each Consul on Kubernetes service account that requires access. For each auth method in Vault, you will need roles for the Consul server, Consul client, the server-acl-init job, and Consul server CA.

    $ vault write auth/kubernetes-dc2/role/consul-server \
            bound_service_account_names=consul-server \
            bound_service_account_namespaces="default" \
            policies="gossip,connect-ca-dc2,consul-cert-dc2,replication-token" \
            ttl=24h
    
    $ vault write auth/kubernetes-dc2/role/consul-server \
            bound_service_account_names=consul-server \
            bound_service_account_namespaces="default" \
            policies="gossip,connect-ca-dc2,consul-cert-dc2,replication-token" \
            ttl=24h
    
    $ vault write auth/kubernetes-dc2/role/consul-client \
            bound_service_account_names=consul-client \
            bound_service_account_namespaces="default" \
            policies="gossip" \
            ttl=24h
    
    $ vault write auth/kubernetes-dc2/role/consul-client \
            bound_service_account_names=consul-client \
            bound_service_account_namespaces="default" \
            policies="gossip" \
            ttl=24h
    
    $ vault write auth/kubernetes-dc2/role/server-acl-init \
            bound_service_account_names=consul-server-acl-init \
            bound_service_account_namespaces="default" \
            policies="replication-token" \
            ttl=24h
    
    $ vault write auth/kubernetes-dc2/role/server-acl-init \
            bound_service_account_names=consul-server-acl-init \
            bound_service_account_namespaces="default" \
            policies="replication-token" \
            ttl=24h
    
    $ vault write auth/kubernetes-dc2/role/consul-ca \
            bound_service_account_names="*" \
            bound_service_account_namespaces="default" \
            policies=ca-policy \
            ttl=1h
    
    $ vault write auth/kubernetes-dc2/role/consul-ca \
            bound_service_account_names="*" \
            bound_service_account_namespaces="default" \
            policies=ca-policy \
            ttl=1h
    
  3. Create the Server TLS Cert role.

    $ vault write pki/roles/consul-cert-dc2 \
      allowed_domains="dc2.consul,consul-server,consul-server.default,consul-server.default.svc" \
      allow_subdomains=true \
      allow_bare_domains=true \
      allow_localhost=true \
      generate_lease=true \
      max_ttl="720h"
    
    $ vault write pki/roles/consul-cert-dc2 \
      allowed_domains="dc2.consul,consul-server,consul-server.default,consul-server.default.svc" \
      allow_subdomains=true \
      allow_bare_domains=true \
      allow_localhost=true \
      generate_lease=true \
      max_ttl="720h"
    
  4. Configure and install Consul in the secondary datacenter (dc2).

    Note: To configure Vault as the Connect CA in secondary datacenters, you need to make sure that the Root CA path is the same. The intermediate path is different for each datacenter. In the connectCA Helm configuration for a secondary datacenter, you can specify a intermediatePKIPath that is, for example, prefixed with the datacenter for which this configuration is intended (e.g. dc2/connect-intermediate).

    global:
      datacenter: "dc2"
      name: consul
      secretsBackend:
        vault:
          enabled: true
          consulServerRole: consul-server
          consulClientRole: consul-client
          consulCARole: consul-ca
          manageSystemACLsRole: server-acl-init
          connectCA:
            address: ${VAULT_ADDR}
            rootPKIPath: connect_root/
            intermediatePKIPath: dc2/connect_inter/
            authMethodPath: kubernetes-dc2
      tls:
        enabled: true
        enableAutoEncrypt: true
        caCert:
          secretName: "pki/cert/ca"
      federation:
        enabled: true
        primaryDatacenter: dc1
        k8sAuthMethodHost: ${KUBE_API_URL_DC2}
        primaryGateways:
        - ${MESH_GW_HOST}:443
      acls:
        manageSystemACLs: true
        replicationToken:
          secretName: consul/data/secret/replication
          secretKey: token
      gossipEncryption:
        secretName: consul/data/secret/gossip
        secretKey: key
    server:
      replicas: 1
      serverCert:
        secretName: "pki/issue/consul-cert-dc2"
    connectInject:
      replicas: 1
      enabled: true
    controller:
      enabled: true
    meshGateway:
      enabled: true
      replicas: 1
    
    consul-dc2.yaml
    global:
      datacenter: "dc2"
      name: consul
      secretsBackend:
        vault:
          enabled: true
          consulServerRole: consul-server
          consulClientRole: consul-client
          consulCARole: consul-ca
          manageSystemACLsRole: server-acl-init
          connectCA:
            address: ${VAULT_ADDR}
            rootPKIPath: connect_root/
            intermediatePKIPath: dc2/connect_inter/
            authMethodPath: kubernetes-dc2
      tls:
        enabled: true
        enableAutoEncrypt: true
        caCert:
          secretName: "pki/cert/ca"
      federation:
        enabled: true
        primaryDatacenter: dc1
        k8sAuthMethodHost: ${KUBE_API_URL_DC2}
        primaryGateways:
        - ${MESH_GW_HOST}:443
      acls:
        manageSystemACLs: true
        replicationToken:
          secretName: consul/data/secret/replication
          secretKey: token
      gossipEncryption:
        secretName: consul/data/secret/gossip
        secretKey: key
    server:
      replicas: 1
      serverCert:
        secretName: "pki/issue/consul-cert-dc2"
    connectInject:
      replicas: 1
      enabled: true
    controller:
      enabled: true
    meshGateway:
      enabled: true
      replicas: 1
    

    Next, install Consul in the consul Kubernetes cluster (dc2).

    $ helm install consul-dc2 -f consul-dc2.yaml hashicorp/consul
    
    $ helm install consul-dc2 -f consul-dc2.yaml hashicorp/consul
    

»Next steps

You have completed the process of federating the secondary datacenter (dc2) with the primary datacenter (dc1) using Vault as the Secrets backend. To validate that everything is configured properly, please confirm that all pods within both datacenters are in a running state.

For further detail on specific Consul secrets that are available to be stored in Vault, please checkout the detailed information in the Data Integration section of the Vault as a Secrets Backend area of the Consul on Kubernetes documentation.

github logoEdit this page
IntroGuidesDocsCommunityPrivacySecurityBrandConsent Manager