Access consul-api from consul-connect-service-mesh

735 views Asked by At

In a consul-connect-service-mesh (using k8) how do you get to the consul-api itself? For example to access the consul-kv.

I'm working through this tutorial, and I'm wondering how you can bind the consul (http) api in a service to localhost.

Do you have to configure the Helm Chart further? I would have expected the consul-agent to always be an upstream service.

The only way i found to access the api is via the k8-service consul-server.

Environment:

  • k8 (1.22.5, docker-desktop)
  • helm consul (0.42)
  • consul (1.11.3)
  • used helm-yaml
global:
  name: consul
  datacenter: dc1
server:
  replicas: 1
  securityContext:
    runAsNonRoot: false
    runAsGroup: 0
    runAsUser: 0
    fsGroup: 0
ui:
  enabled: true
  service:
    type: 'NodePort'
connectInject:
  enabled: true
controller:
  enabled: true
2

There are 2 answers

0
Florian Hilfenhaus On BEST ANSWER

My current final solution is a (connect)service based on reverse proxy (nginx) that targets consul.

apiVersion: v1
kind: ConfigMap
metadata:
  name: consul-kv-proxy
data:
 nginx.conf.template: |
    error_log /dev/stdout info;
    server {
      listen 8500;    
      location / {
        access_log off;
        proxy_pass http://${MY_NODE_IP}:8500;
        error_log /dev/stdout;          
      }         
    }    
---
apiVersion: v1
kind: Service
metadata:
  # This name will be the service name in Consul.
  name: consul-kv-proxy
spec:
  selector:
    app: consul-kv-proxy
  ports:
    - protocol: TCP
      port: 8500      
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: consul-kv-proxy
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: consul-kv-proxy
spec:
  replicas: 1
  selector:
    matchLabels:
      app: consul-kv-proxy
  template:
    metadata:
      name: consul-kv-proxy
      labels:
        app: consul-kv-proxy
      annotations:
        'consul.hashicorp.com/connect-inject': 'true'
    spec:
      containers:
        - name: consul-kv-proxy
          image: nginx:1.14.2            
          volumeMounts:
          - name: config
            mountPath: "/usr/local/nginx/conf"
            readOnly: true           
          command: ['/bin/bash']
          #we have to transform the nginx config to use the node ip address
          args:
            - -c
            - envsubst < /usr/local/nginx/conf/nginx.conf.template > /etc/nginx/conf.d/consul-kv-proxy.conf && nginx -g 'daemon off;'
          ports:
            - containerPort: 8500
              name: http
          env:
            - name: MY_NODE_IP
              valueFrom:
                fieldRef:
                  fieldPath: status.hostIP      
      volumes:
        - name: config
          configMap:
            name: consul-kv-proxy
      
      # If ACLs are enabled, the serviceAccountName must match the Consul service name.
      serviceAccountName: consul-kv-proxy

A downstream service (called static-client) now can be declared like this

apiVersion: v1
kind: Service
metadata:
  name: static-client
spec:
  selector:
    app: static-client
  ports:
    - port: 80
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: static-client
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: static-client
spec:
  replicas: 1
  selector:
    matchLabels:
      app: static-client
  template:
    metadata:
      name: static-client
      labels:
        app: static-client
      annotations:
        'consul.hashicorp.com/connect-inject': 'true'         
        'consul.hashicorp.com/connect-service-upstreams': 'consul-kv-proxy:8500'     
    spec:
      containers:
        - name: static-client
          image: curlimages/curl:latest
          # Just spin & wait forever, we'll use `kubectl exec` to demo
          command: ['/bin/sh', '-c', '--']
          args: ['while true; do sleep 30; done;']
      serviceAccountName: static-client

Assume we have a key-value in consul called "test". From a pod of the static-client we can now access the consul-web-api with:

curl http://localhost:8500/v1/kv/test

This solution still lacks fine-tuning (i have not try https, or ACL).

1
Blake Covarrubias On

You can access the Consul API on the local agent by using the Kubernetes downward API to inject an environment variable in the pod with the IP address of the host. This is documented on Consul.io under Installing Consul on Kubernetes: Accessing the Consul HTTP API.

You will also need to exclude port 8500 (or 8501) from redirection using the consul.hashicorp.com/transparent-proxy-exclude-outbound-ports label.