Consul-on-Kubernetes

110次阅读

共计 5449 个字符,预计需要花费 14 分钟才能阅读完成。

consul 发展到今日,早已不是只用于服务发现和配置共享的工具了。官方对其的定义是自动化网络配置,发现服务并启用跨任何云或运行时的安全连接。

特性

  • 与 Kubernetes 集成和扩展。利用 Helm 在 Kubernetes 上快速部署 Consul。自动为 Kubernetes 资源注入 sidecar。将多个集群联合到一个服务网格中。
  • 跨任何运行时的服务网格。在任何运行时或基础架构中跨任何云在裸机,虚拟机和 Kubernetes 集群中部署服务网格。

  • 动态的负载均衡。通过集成的 DNS 解决发现的服务。自动化第三方负载均衡器(F5,NGINX,HAProxy)。无需手动配置网络设备。
  • 安全的多云服务网络。利用访问策略和服务网格资源之间的自动 mTLS 加密,在任何环境中运行的安全服务。

  • 通过运行状况检查发现服务。Consul 支持检测新服务的部署,对现有服务的更改,并提供实时代理运行状况以减少停机时间。
  • 强大的生态系统。Consul 为许多流行的 DevOps 和网络工具提供支持并与之集成。

默认端口

consul 默认使用下列端口

  • 8300(tcp): Server RPC,server 用于接受其他 agent 的请求
  • 8301(tcp,udp): Serf LAN,数据中心内 gossip 交换数据用
  • 8302(tcp,udp): Serf WAN,跨数据中心 gossip 交换数据用
  • 8400(tcp): CLI RPC,接受命令行的 RPC 调用
  • 8500(tcp): HTTP API 及 Web UI
  • 8600(tcp udp): DNS 服务,可以把它配置到 53 端口来响应 dns 请求

部署

官方推荐的 helm 部署方案,包括了诸多解决方案。当我们只是用来做服务发现或是配置中心的时候,我们可以选择 yaml 部署。

本文将完成在 Kubernetes 上部署三(3)节点 Consul 集群。

  • 使用 StatefulSet 的三(3)个节点 Consul 群集
  • 使用 TLS 和加密密钥的 Consul 成员之间的安全通信

生成 TLS Certificates

新建 ca 目录,包含以下三个文件:

ca-config.json

{
"signing": {
"default": {"expiry": "43800h"},
"profiles": {
"default": {"usages": ["signing", "key encipherment", "server auth", "client auth"],
"expiry": "43800h"
}
}
}
}

ca-csr.json

{
"hosts": ["cluster.consul"],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "Kubernetes",
"OU": "CA",
"ST": "Oregon"
}
]
}

consul-csr.json

{
"CN": "server.dc1.cluster.consul",
"hosts": [
"server.dc1.cluster.consul",
"127.0.0.1"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "Hightower Labs",
"OU": "Consul",
"ST": "Oregon"
}
]
}

Consul 成员之间的 RPC 通信将使用 TLS 进行加密。初始化证书颁发机构(CA):

cfssl gencert -initca ca/ca-csr.json | cfssljson -bare ca

创建 Consul TLS 证书和私钥:

cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca/ca-config.json \
-profile=default \
ca/consul-csr.json | cfssljson -bare consul

此时,您应该在当前工作目录中具有以下文件:

ca-key.pem
ca.pem
consul-key.pem
consul.pem

生成 Consul Gossip Encryption Key

Consul 成员之间的 Gossip 通信将使用共享的加密密钥进行加密。生成并存储加密密钥:

GOSSIP_ENCRYPTION_KEY=$(consul keygen)

创建 Consul Secret 和 Configmap

Consul 集群将使用 CLI 标志,TLS 证书和配置文件的组合进行配置,这些文件引用 Kubernetes configmap 和 secret。

将 Gossip 加密密钥和 TLS 证书存储在密钥中:

kubectl create secret generic consul -n discovery \
--from-literal="gossip-encryption-key=${GOSSIP_ENCRYPTION_KEY}" \
--from-file=ca.pem \
--from-file=consul.pem \
--from-file=consul-key.pem

将 Consul 服务器配置文件存储在 ConfigMap 中:

kubectl create configmap consul -n discovery --from-file=server.json

而 server.json 文件如下:

{
"bind_addr": "0.0.0.0",
"ca_file": "/etc/tls/ca.pem",
"cert_file": "/etc/tls/consul.pem",
"client_addr": "0.0.0.0",
"disable_host_node_id": true,
"data_dir": "/consul/data",
"datacenter": "dc1",
"domain": "cluster.consul",
"key_file": "/etc/tls/consul-key.pem",
"ports": {"https": 8443},
"retry_join": ["provider=k8s namespace=discovery label_selector=\"app=consul,component=server\""],"server": true,"telemetry": {"prometheus_retention_time":"5m"},"verify_incoming": true,"verify_outgoing": true,"verify_server_hostname": true,"ui": true
}

创建 Consul Service

apiVersion: v1
kind: Service
metadata:
name: consul
namespace: discovery
labels:
name: consul
spec:
clusterIP: None
ports:
- name: http
port: 8500
targetPort: 8500
- name: cli-rpc
port: 8400
targetPort: 8400
- name: serflan-tcp
protocol: "TCP"
port: 8301
targetPort: 8301
- name: serflan-udp
protocol: "UDP"
port: 8301
targetPort: 8301
- name: serfwan-tcp
protocol: "TCP"
port: 8302
targetPort: 8302
- name: serfwan-udp
protocol: "UDP"
port: 8302
targetPort: 8302
- name: agent-rpc
port: 8300
targetPort: 8300
- name: dns
port: 8600
targetPort: 8600
selector:
app: consul

创建 Consul Service Account

由于我们 retry_join 使用的是 k8s provider,所有必须要配置 rbac。给与获取 pod 的权限。

apiVersion: v1
kind: ServiceAccount
metadata:
name: consul
namespace: discovery
labels:
app: consul
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: consul
labels:
app: consul
rules:
- apiGroups: [""]
resources:
- pods
verbs:
- get
- list
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: consul
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: consul
subjects:
- kind: ServiceAccount
name: consul
namespace: discovery

创建 Consul StatefulSet

apiVersion: apps/v1
kind: StatefulSet
metadata:
name: consul
namespace: discovery
spec:
selector:
matchLabels:
app: consul
component: server
serviceName: consul
podManagementPolicy: "Parallel"
replicas: 3
template:
metadata:
labels:
app: consul
component: server
annotations:
consul.hashicorp.com/connect-inject: "false"
spec:
serviceAccountName: consul
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- consul
topologyKey: kubernetes.io/hostname
terminationGracePeriodSeconds: 10
securityContext:
fsGroup: 1000
containers:
- name: consul
image: "consul:1.7.3"
env:
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: GOSSIP_ENCRYPTION_KEY
valueFrom:
secretKeyRef:
name: consul
key: gossip-encryption-key
args:
- "agent"
- "-advertise=$(POD_IP)"
- "-bootstrap-expect=3"
- "-config-file=/etc/consul/config/server.json"
- "-encrypt=$(GOSSIP_ENCRYPTION_KEY)"
volumeMounts:
- name: data
mountPath: /consul/data
- name: config
mountPath: /etc/consul/config
- name: tls
mountPath: /etc/tls
lifecycle:
preStop:
exec:
command:
- /bin/sh
- -c
- consul leave
ports:
- containerPort: 8500
name: ui-port
- containerPort: 8400
name: cli-port
- containerPort: 8301
name: serflan
- containerPort: 8302
name: serfwan
- containerPort: 8600
name: dns
- containerPort: 8300
name: server
volumes:
- name: config
configMap:
name: consul
- name: tls
secret:
secretName: consul
volumeClaimTemplates:
- metadata:
name: data
namespace: discovery
annotations:
everest.io/disk-volume-type: SAS
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: csi-disk-topology

由于我的安装是在华为云上,所以如果是其他公有云或是其他存储,注意替换 volumeClaimTemplates。

查看安装情况:

kubectl get pods -n discovery -l app=consul
NAME READY STATUS RESTARTS AGE
consul-0 1/1 Running 0 13h
consul-1 1/1 Running 0 13h
consul-2 1/1 Running 0 13h

验证

通过访问 UI,可以看到我们的三个实例均已成功加入集群,并且选举成功。

正文完
 0