前言

在云原生架构中,服务发现是微服务治理的关键环节。本文将详细介绍如何通过kube-consul-register实现Kubernetes服务到Consul的自动注册,解决传统手动注册的痛点。该工具支持:

  1. 多模式注册(Single/Node/Pod模式)
  2. 注解驱动的灵活配置
  3. 自动健康检查集成
  4. 服务状态实时同步

流程图

在这里插入图片描述

项目概述

这是一个将Kubernetes中的Pod/Service/Endpoint自动注册到Consul服务的工具,实现服务自动发现功能。

核心功能

  • 自动监听Kubernetes事件并注册/注销Consul服务
  • 支持三种注册模式:单节点(single)、Pod级(pod)、节点级(node)
  • 自动同步Kubernetes健康检查到Consul
  • 提供Prometheus监控指标接口(http://ip:port/metrics即可查看以下指标值)
    通过 /metrics 端点提供以下监控指标:
    Consul操作成功/失败计数
    Pod事件处理统计
    同步/清理操作的耗时
    函数执行时间等
  • 支持集群内外两种运行方式

参数

  -alsologtostderr
      同时输出日志到文件和标准错误(stderr)
  -clean-interval duration
      清理非活跃服务的间隔时间(默认30分钟)
  -configmap string
      指定配置的ConfigMap(格式: namespace/configmap_name)
  -consul-secret string
      包含Consul token的Secret名称 指定配置的ConfigMap(格式: namespace/secert_name)
  -in-cluster
      是否使用集群内配置(默认true)
  -kubeconfig string
      kubeconfig文件路径(默认"./kubeconfig")
  -log_backtrace_at value
        when logging hits line file:N, emit a stack trace
  -log_dir string
      日志文件目录   
  -logtostderr
      将日志输出到stderr而非文件
  -stderrthreshold value
      输出到stderr的日志级别阈值
  -sync-interval duration
      同步间隔时间(默认2分钟)
  -v value
      日志详细级别
  -version
      显示版本并退出
  -vmodule value
        comma-separated list of pattern=N settings for file-filtered logging
  -watch-namespace string
        namespace to watch for Pods. Default is to watch all namespaces

配置说明(ConfigMap)

基础配置

配置项 默认值 说明
consul_address localhost Consul Agent地址(仅single模式有效)
consul_port 8500 Consul服务端口
consul_scheme http 连接协议(http/https/consul-unix)
consul_datacenter Consul数据中心
cosnul_node_name Consul节点名称

安全配置

配置项 默认值 说明
consul_ca_file CA证书文件路径
consul_cert_file SSL客户端证书文件路径
consul_key_file SSL客户端证书密钥文件路径
consul_insecure_skip_verify false 是否跳过SSL证书验证
consul_token Consul ACL token

高级配置

配置项 默认值 说明
consul_timeout 2s Consul HTTP客户端请求超时时间
consul_container_name consul Consul 的容器名称(仅pod模式有效)
consul_node_selector consul=enabled 节点标签选择器(仅node模式有效),可以自行更改为consul所在节点的标签
pod_label_selector 需要监听的Pod标签选择器,如果为空则监听所有pod
k8s_tag kubernetes 添加到Consul服务的标签

注册配置

配置项 默认值 说明
register_mode single 注册模式: single(单节点)/pod(Pod级)/node(节点级)
register_source pod 监听来源: pod/service/endpoint

注册模式对比

特性 single模式 pod模式 node模式
注册目标 集中注册到指定Consul节点 每个Pod注册到所在节点的Consul Agent 服务注册到所在节点的Consul Agent
Consul部署要求 单节点部署 每个节点部署(DaemonSet推荐) 选择性节点部署(带标签)
配置关键项 consul_address(必须) consul_container_name consul_node_selector
网络流量 跨节点通信 仅本机通信 节点内通信
适用场景 测试环境/小规模集群 大规模Pod级服务发现 中规模节点级服务发现
性能影响 单点压力大 分布式压力 均衡压力
配置示例
register_mode: single register_mode: pod register_mode: node
consul_address: “1.1.1.1” consul_container_name: “consul” consul_node_selector: “consul=enabled”
服务发现粒度 全局可见 Pod级别可见 节点级别可见
健康检查 集中检查 分布式检查 节点级检查

注解配置说明
以下是可用的注解配置

注解名称 可选值 描述
consul.register/enabled true/false 是否将该Pod/service/注册到Consul中,必须再对应yaml中设置此注解才能注册
consul.register/service.name <自定义服务名> 指定在Consul中注册的服务名称。如果未设置,则使用创建该Pod的资源名称。仅在register_source设为pod时有效
consul.register/pod.container.name <容器名(多个用逗号分隔)> 指定需要注册的容器名称列表。如果省略,则注册Pod中的所有容器
consul.register/liveness.check.enabled true/false 是否启用存活健康检查。如果省略,默认不启用
consul.register/readiness.check.enabled true/false 是否启用就绪健康检查。如果省略,默认不启用
kubernetes.io/created-by JSON格式的创建者信息 包含Pod创建者信息的JSON字符串,用于确定服务名称

注册模式说明
register_mode 配置项用于指定服务注册的模式,支持以下三种模式

配置项 说明
single 所有服务注册到单一Consul节点
pod 每个Pod独立注册到本地Consul Agent
node 服务注册到所在节点的Consul Agent

使用示例

在这里插入图片描述

1、集群外运行—注册模式为single、来源是pod

[root@k8s-master kube-consul-register]# cat ../config.yaml 
apiVersion: v1
data:
    consul_address: "192.168.56.101"
    consul_port: "30850"
    consul_scheme: "http"
    consul_ca_file: ""
    consul_cert_file: ""
    consul_key_file: ""
    consul_insecure_skip_verify: "false"
    consul_token: "9bfbe81f-2648-4673-af14-d13e0a170050"
    consul_timeout: "5s"
    consul_container_name: "consul"
    #consul_node_selector: "consul=enabled"
    consul_node_selector: "component=consul"
    #如果此处设置了标签,则只有该标签对应的pod能被注册到consul中
    pod_label_selector: ""
    #可任意指定,最终被应用到consul的tag标签
    k8s_tag: "kubernetes"
    register_mode: "single"
    register_source: "pod"
    #创建consul时指定的datacenter
    consul_datacenter: "dc8"
    #consul节点的名称
    consul_node_name: "consul-0"
kind: ConfigMap
metadata:
    name: kube-consul-register-config
    namespace: default

[root@k8s-master kube-consul-register]# kubecatl apply -f ../config.yaml

[root@k8s-master kube-consul-register]# cat ../secrettoken.yaml 
apiVersion: v1
kind: Secret
metadata:
  name: consul-token
  namespace: default
type: Opaque
data:
  consul_token: "OWJmYmU4MWYtMjY0OC00NjczLWFmMTQtZDEzZTBhMTcwMDUwCg==" #ACL token base64加密
[root@k8s-master kube-consul-register]# kubecatl apply -f ../secrettoken.yaml

#构建二进制服务
[root@k8s-master kube-consul-register]# make build

#启动服务
[root@k8s-master kube-consul-register]# ./dist/kube-consul-register -kubeconfig=/root/.kube/config -in-cluster=false -consul-secret="default/consul-token" -log_dir=/export/kube-consul-register/logs/ -logtostderr=true -alsologtostderr=true -v=1
测试pod注册

在这里插入图片描述

[root@k8s-master kube-consul-register]# cat examples/nginx.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: nginx
  name: nginx
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      run: nginx
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  template:
    metadata:
      labels:
        run: nginx
        #production: "tag" # Would create `production` tag for service `nginx`. Instead of `production:tag`.
      annotations:
        consul.register/enabled: "true" #关键 是否将pod注册到consul
        consul.register/liveness.check.enabled: "true"
        #consul.register/readiness.check.enabled: "true"
        #consul.register/service.name: "mynginx"
    spec:
      tolerations:
      - key: "node-role.kubernetes.io/control-plane"
        operator: "Exists"
        effect: "NoSchedule"
      containers:
      - image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:stable
        imagePullPolicy: IfNotPresent
        name: nginx
        livenessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 3
          periodSeconds: 3
        ports:
        - containerPort: 80
      restartPolicy: Always
      terminationGracePeriodSeconds: 30
[root@k8s-master kube-consul-register]# kubectl apply -f examples/nginx.yaml
I0411 10:07:03.188878   19242 controller.go:398] POD UPDATE: Name: nginx-7f45fdf5b6-5mjrm, Namespace: default, Phase: Running, Ready: True
I0411 10:07:03.188940   19242 controller.go:412] Container nginx in POD nginx-7f45fdf5b6-5mjrm has status: Ready:true
I0411 10:07:03.188984   19242 controller.go:417] Adding service for container nginx in POD nginx-7f45fdf5b6-5mjrm to consul
I0411 10:07:03.387166   19242 controller.go:435] Service's been registered, Name: default, ID: nginx-7f45fdf5b6-5mjrm-nginx

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

测试pod被删除时从consul中剔除
[root@k8s-master kube-consul-register]# kubectl delete -f examples/nginx.yaml
I0411 10:07:41.995157   19242 controller.go:398] POD UPDATE: Name: nginx-7f45fdf5b6-5mjrm, Namespace: default, Phase: Running, Ready: True
I0411 10:07:41.995326   19242 controller.go:412] Container nginx in POD nginx-7f45fdf5b6-5mjrm has status: Ready:true
I0411 10:07:43.405026   19242 controller.go:343] POD DELETE: Name: nginx-7f45fdf5b6-5mjrm, Namespace: default, Phase: Succeeded, Ready: False
I0411 10:07:43.405087   19242 controller.go:349] Container nginx in POD nginx-7f45fdf5b6-5mjrm has status: Ready:false
I0411 10:07:43.427059   19242 controller.go:360] Service successfully deregistered via Agent API, ID: nginx-7f45fdf5b6-5mjrm-nginx
I0411 10:07:43.438001   19242 controller.go:373] Service successfully deregistered via Catalog API, ID: nginx-7f45fdf5b6-5mjrm-nginx

2、集群内运行—注册模式为single、来源是service/endpoint

2.1、构建kube-consul-register镜像并推送到私有仓库
# 构建镜像
[root@k8s-master kube-consul-register]# make build
[root@k8s-master kube-consul-register]# docker build -t kube-consul-register:latest .
# 推送镜像到私有仓库(docker)
[root@k8s-master kube-consul-register]# docker tag kube-consul-register:latest registry.example.com/kube-consul-register:latest
[root@k8s-master kube-consul-register]# docker push registry.example.com/kube-consul-register:latest
# 推送镜像到私有仓库(containerd)
[root@k8s-master kube-consul-register]# docker save kube-consul-register:latest | gzip > kube-consul-register.tar.gz
[root@k8s-master kube-consul-register]# ctr images import kube-consul-register.tar.gz --digests=true
[root@k8s-master kube-consul-register]# ctr images tag registry.example.com/kube-consul-register:latest harbor.ops.local/registry/kube-consul-register:latest
[root@k8s-master kube-consul-register]# ctr images push harbor.ops.local/kube-consul-register:latest --user admin:xxx -k
2.2、在集群内运行kube-consul-register
#将configamp部分中的注册来源设置为service
[root@k8s-master kube-consul-register]# kubectl apply -f examples/deployment.yaml
2.3、测试service注册
#service将选择器设置为run=nginx,因此只有run=nginx的pod将被注册到consul中
#nginx.yaml中可以将注解consul.register/enabled: "fasle"设置为false
#service_nodeport.yaml中可以将注解consul.register/enabled: "true"设置为true
[root@k8s-master kube-consul-register]# kubectl apply -f examples/nginx.yaml
[root@k8s-master kube-consul-register]# kubectl apply -f examples/service_nodeport.yaml
2.4、验证service是否注册成功
检查consul中是否存在service以及kube-consul-register服务日志
2.5、测试endpoint注册
#service将选择器设置为run=nginx,因此只有run=nginx的pod将被注册到consul中
#nginx.yaml中可以将注解consul.register/enabled: "fasle"设置为false
#service_nodeport.yaml中可以将注解consul.register/enabled: "true"设置为true
[root@k8s-master kube-consul-register]# kubectl apply -f examples/nginx.yaml
[root@k8s-master kube-consul-register]# kubectl apply -f examples/service_nodeport.yaml
2.6、验证service是否注册成功
检查consul中是否存在endpoint以及kube-consul-register服务日志
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐