Skip to main content

Consule Connect Mesh

Tips#

  • 优势
    • mesh gateway 打通集群
    • ingress gateway 允许外部访问内部服务
    • terminating gateway 允许内部 mtls 访问外部服务
    • 支持代码层集成 - 提供 Go SDK
    • 连通性好
    • 支持 7 层路由
    • 没有集成 prometheus 和 grafana - 更适合利用现有实例
  • 劣势
    • 需要两个 sidecard
      • consul-connect-inject-init
      • consul-connect-envoy-sidecar
      • consul-connect-lifecycle-sidecar
    • connect 主要 支持连通性,跟踪和指标都没有支持
    • 界面功能较弱
    • 流量切分实例分组需要配置,没有界面
    • observability 和 指标都依赖 envoy - 没有默认配置
  • 特性
    • mtls
    • intention - Service-to-Service 权限
      • consul intention create -deny web '*'
    • 自动注入
      • consul.hashicorp.com/connect-inject: 'true'
  • Control Plane
    • Consul UI
  • Data Plane
    • 内建 - 主要用于开发
    • envoy
  • 注意
    • 必须配合 consule 使用
  • Mesh Gateway
    • 网关互通 - 跨集群/区域
    • 服务到服务
  • Ingress Gateway
    • 接受外部流量
    • 外部访问内部服务
  • Terminating Gateway
    • 内部访问外部
  • Intention - ACL 控制
  • 代理
    • 内建 - 不适用于生产
    • Envoy
  • 证书管理
    • 内建 CA
    • Vault
  • 参考
kubectl port-forward service/consul-server 8500:8500# tls# kubectl port-forward service/consul-server 8501:8501
# tokenexport CONSUL_HTTP_TOKEN=$(kubectl get secrets/consul-bootstrap-acl-token --template={{.data.token}} | base64 -d)consul info
# in podexport CONSUL_HTTP_ADDR="${HOST_IP}:8500"
# 命令行启动# -- -l trace - envoy 的 trace 日志consul connect envoy \  -sidecar-for echo -http-addr http://127.0.0.1:8500 \  -grpc-addr http://127.0.0.1:8502 \  -admin-bind 127.0.0.1:0

annotations#

  • consul.hashicorp.com/connect-inject
    • bool
    • 是否注入 sidecard
  • consul.hashicorp.com/connect-service
    • 服务的名字
    • 默认为第一个 container 的名字
    • 如果启用了 acl,名字必须与 ServiceAccount 相同
  • consul.hashicorp.com/connect-service-port
    • 接受请求的端口
    • 默认为第一个暴露端口
    • 可以是名字也可以是端口号
    • proxy 监听动态端口
  • consul.hashicorp.com/connect-service-upstreams
    • 连接到的上游服务
    • 逗号分割指定多个
    • [service-name]:[port]:[optional datacenter]
    • prepared_query:[query name]:[port]
  • consul.hashicorp.com/connect-service-protocol
    • 注册协议
    • helm 安装时使用 defaultProtocol 指定默认协议
      • 建议指定为 http
  • consul.hashicorp.com/service-tags
    • 逗号分割指定多个
  • consul.hashicorp.com/service-meta-<KEY>
  • consul.hashicorp.com/sidecar-proxy- - proxy 配置
    • cpu/memory-limit/request
    • helm 默认配置 connectInject.sidecarProxy.resources

k8s#

apiVersion: v1kind: ServiceAccountmetadata:  name: alpine-connect---apiVersion: v1kind: Podmetadata:  name: alpine-connect  annotations:    consul.hashicorp.com/connect-inject: 'true'    consul.hashicorp.com/connect-service-upstreams: consul:8500,static-server:1234,web-test:2019,whoami-v1:1992spec:  serviceAccountName: alpine-connect  containers:  - name: alpine-connect    image: wener/base    command:    - tail    args:    - -f    - /dev/null
kubectl exec alpine-connect -it -c alpine-connect -- sh
apiVersion: v1kind: ServiceAccountmetadata:  name: static-server---apiVersion: v1kind: Podmetadata:  name: static-server  annotations:    consul.hashicorp.com/connect-inject: 'true'spec:  containers:    # consule 中的服务名    - name: static-server      image: hashicorp/http-echo:latest      args:        - -text="hello world"        - -listen=:8080      ports:        - containerPort: 8080          name: http  # 如果启用了 ACL, serviceAccountName 必须要匹配 Consil 中的服务名  serviceAccountName: static-server
apiVersion: v1kind: ServiceAccountmetadata:  name: static-client---apiVersion: v1kind: Podmetadata:  name: static-client  annotations:    'consul.hashicorp.com/connect-inject': 'true'    'consul.hashicorp.com/connect-service-upstreams': 'static-server:1234'spec:  containers:    # 服务名    - name: static-client      image: tutum/curl:latest      # 保持运行      command: ['/bin/sh', '-c', '--']      args: ['while true; do sleep 30; done;']  # ACL 要求  serviceAccountName: static-client
apiVersion: v1kind: ServiceAccountmetadata:  name: web-test---apiVersion: apps/v1kind: Deploymentmetadata:  name: web-test  labels:    app: web-testspec:  replicas: 3  selector:    matchLabels:      app: web-test  template:    metadata:      name: web-test      labels:        app: web-test      annotations:        consul.hashicorp.com/connect-service-upstreams: 'static-server:1234'        consul.hashicorp.com/connect-inject: 'true'    spec:      containers:        - name: web-test          image: nginx:alpine          ports:            - containerPort: 80      serviceAccountName: web-test
apiVersion: v1kind: ServiceAccountmetadata:  name: static-server-next---apiVersion: v1kind: Podmetadata:  name: static-server-next  annotations:    consul.hashicorp.com/connect-inject: 'true'spec:  containers:    - name: static-server-next      image: hashicorp/http-echo:latest      args:        - -text="hello world"        - -listen=:8080      ports:        - containerPort: 8080          name: http  serviceAccountName: static-server-next
cat <<HCL | consul config write -Kind      = "service-defaults"Name      = "static-server"Protocol  = "http"HCLcat <<HCL | consul config write -Kind      = "service-defaults"Name      = "static-server-next"Protocol  = "http"HCLcat <<HCL | consul config write -Kind = "service-router"Name = "static-server"Routes = [  {    Match {      HTTP {        PathPrefix = "/next"      }    }
    Destination {      Service = "static-server-next"    }  },]HCL

whomai#

apiVersion: v1kind: ServiceAccountmetadata:  name: whoami---kind: DeploymentapiVersion: apps/v1metadata:  name: whoami-v1  labels:    app: whoami-v1spec:  replicas: 2  selector:    matchLabels:      app: whoami-v1  template:    metadata:      labels:        app: whoami-v1      annotations:        consul.hashicorp.com/connect-inject: 'true'        consul.hashicorp.com/connect-service-protocol: http        consul.hashicorp.com/service-tags: app=whoami        consul.hashicorp.com/service-meta-version: v1    spec:      serviceAccountName: whoami      containers:        - name: whoami          image: containous/whoami          # diff          env:          - name: WHOAMI_NAME            value: V1          ports:            - containerPort: 80          livenessProbe:            httpGet:              path: /health              port: 80            initialDelaySeconds: 3            periodSeconds: 3---kind: DeploymentapiVersion: apps/v1metadata:  name: whoami-v2  labels:    app: whoami-v2spec:  replicas: 2  selector:    matchLabels:      app: whoami-v2  template:    metadata:      labels:        app: whoami-v2      annotations:        consul.hashicorp.com/connect-inject: 'true'        consul.hashicorp.com/connect-service-protocol: http        consul.hashicorp.com/service-tags: app=whoami        consul.hashicorp.com/service-meta-version: v2    spec:      # same service      serviceAccountName: whoami      containers:        - name: whoami          image: containous/whoami          # diff          env:          - name: WHOAMI_NAME            value: V2          ports:            - containerPort: 80          livenessProbe:            httpGet:              path: /health              port: 80            initialDelaySeconds: 3            periodSeconds: 3
cat <<HCL | consul config write -Kind      = "service-defaults"Name      = "whoami"Protocol  = "http"Expose    = {  Checks = true  Paths = [{    Path = "/health"  }]}HCLcat <<HCL | consul config write -Kind          = "service-resolver"Name          = "whoami"DefaultSubset = "v2"Subsets = {  "v1" = {    Filter = "Service.Meta.version == v1"  }  "v2" = {    Filter = "Service.Meta.version == v2"  }}HCL
cat <<HCL | consul config write -Kind = "service-router"Name = "whoami"Routes = [  {    Match {      HTTP {        Header = [          {            Name  = "x-version"            Exact = "2"          },        ]      }    }    Destination {      Service       = "whoami"      ServiceSubset = "v2"    }  },  {    Match {      HTTP {        PathPrefix = "/v2"      }    }    Destination {      Service       = "whoami"      ServiceSubset = "v2"    }  },
    {    Match {      HTTP {        Header = [          {            Name  = "x-version"            Exact = "1"          },        ]      }    }    Destination {      Service       = "whoami"      ServiceSubset = "v1"    }  },    {    Match {      HTTP {        PathPrefix = "/v1"      }    }    Destination {      Service       = "whoami"      ServiceSubset = "v1"    }  },]HCL

分组

Kind          = "service-resolver"Name          = "whoami"DefaultSubset = "v1"Subsets = {  "v1" = {    Filter = "Service.Meta.version == v1"  }  "v2" = {    Filter = "Service.Meta.version == v2"  }}

流量切分

Kind = "service-splitter"Name = "web"Splits = [  {    Weight        = 90    ServiceSubset = "v1"  },  {    Weight        = 10    ServiceSubset = "v2"  },]