2025-02-27 13:47:35
随着 Istio 版本迭代,其的安装方式和工具链也在不断演进。从 istioctl
到 Helm,再到曾经的 Istio Operator,用户常常会面临选择困境:到底哪种方式最适合我的场景?在最近的交流中,我经常遇到关于 Istio 安装方式选择的问题,特别是围绕 IstioOperator API
和已废弃的 Istio Operator 组件的区别。今天,我将以技术实践者的视角,带你梳理 Istio 的安装之道,拆解关键问题,并给出生产级建议。
Istio 提供了多种安装路径,每种方式都有其设计初衷和适用场景。以下是当前主流选项:
istioctl
:官方推荐的安装工具,集验证、定制和运维于一体,几乎是生产环境的标配。接下来,我们逐一剖析这些方式的核心特点,以及背后的取舍逻辑。
istioctl
:生产环境的不二之选在 Istio 中,istioctl
被官方定位为首选安装工具。它的优势显而易见:
istioctl
会对配置进行静态检查,避免潜在问题。比如,使用 istioctl analyze
可以快速定位配置文件中的错误。IstioOperator
API,你可以精确控制安装细节,比如只启用 Pilot 或调整网关配置。istioctl verify-install
)到增量升级,istioctl
提供了全生命周期支持。istioctl
在本地运行,避免了高权限组件带来的安全隐患。实践中的一个简单例子:
istioctl install --set profile=default -y
这会快速部署默认配置。如果需要更细粒度的控制,可以搭配 YAML 文件(后文详解)。
适用场景:生产环境、新用户、需要高度定制的场景。
Helm 是 Kubernetes 生态的老朋友,Istio 也提供了官方 Helm chart。它的亮点在于:
但 Helm 并非没有短板:
istioctl
,Helm 的配置检查较弱,错误往往在运行时暴露。适用场景:已有 Helm 工作流、CI/CD 驱动的项目。
如果你接触过早期 Istio,可能会对 Istio Operator 有所耳闻。这是一个运行在集群内的控制器,负责根据配置管理 Istio 安装。然而,从 1.23 版本起,它已被官方废弃。原因何在?
istioctl
已能完全覆盖其功能(参考 GitHub Discussion #166)。现有用户可以继续运行旧版本,但无法升级到 1.24+。对于新项目,我的建议是直接跳过这一选项。
讨论中常出现的一个困惑是:IstioOperator API
和 Istio Operator 有什么区别?让我们一次性讲清楚:
IstioOperator API
:一个声明式的配置接口,用于定义 Istio 安装的期望状态。它并未废弃,而是 istioctl
的核心依赖。类比一下:API 是设计图纸,Operator 是施工队。现在,istioctl
取代了施工队,效率更高,风险更低。
IstioOperator API
?IstioOperator
API 是 Istio 安装的灵魂,允许你通过 YAML 文件灵活定制配置。以下是一个典型流程:
编写配置文件:
假设我们要启用 Egress Gateway:
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
profile: default
components:
egressGateways:
- name: istio-egressgateway
enabled: true
部署配置:
执行:
istioctl install -f istio-config.yaml
这种方式的好处在于声明式管理,修改后重新运行即可实现增量更新。比如,要调整资源限制,只需更新 YAML 并再次应用。
安装完成后,如何添加或更新组件(如 Egress Gateway)?istioctl
的答案简单直接:
编辑 YAML,添加新配置。
运行:
istioctl install -f updated-config.yaml
istioctl
会自动计算差异,完成增量部署。
Helm 更新则稍显繁琐,可能涉及 chart 调整或手动干预,尤其在非常规组件上。
通过这次深入剖析,我们可以得出以下结论:
istioctl
是王道:它兼具安全性、灵活性和生产就绪特性,适合绝大多数场景。作为一个在开源领域摸爬滚打的实践者,我建议从 istioctl
入手,结合 IstioOperator
API,既能快速上手,又能满足复杂需求。Istio 的安装看似复杂,但掌握核心逻辑后,你会发现它其实很有条理。
有任何疑问,欢迎留言交流,一起解锁服务网格的更多玩法!
2025-02-13 18:20:14
Istio 的 Ambient 模式是一种创新的、无 Sidecar 的服务网格部署方式,通过 ztunnel 和 waypoint proxy 分离数据平面功能,简化了操作并降低了资源消耗。本篇博客将通过一份详细的术语表,帮助你更好地理解 Istio Ambient 模式中的关键概念及其背后的技术实现。
istiod
)负责管理集群内 ztunnel 和 waypoint proxy 的配置和策略,而数据平面由 ztunnel 和 waypoint proxy 组成,负责处理实际的网络流量。istiod
获取配置并执行策略,管理 Pod 之间的 L4 和 L7 流量。istiod
)istiod
使用 xDS APIs 进行配置推送,动态管理 Ambient 模式中的流量策略、证书分发以及与 Kubernetes 集群的交互。istiod
) 获取 mTLS 证书,并负责证书的管理和轮换。pistioin
和 pistioout
:用于与节点上的 istioin
和 istioout
接口通过 GENEVE 隧道连接。istioin
和 istioout
)与 ztunnel 内的接口(pistioin
和 pistioout
)。istioin
处理进入节点的流量,istioout
处理离开节点的流量。两者通过 GENEVE 隧道连接到 ztunnel 中相应的接口。istioin
或 istioout
,然后通过 GENEVE 隧道传递给 ztunnel。Istio 服务网格中所有工作负载将根据其服务账户注册 SPIFFE 标准的服务身份格式:spiffe://<trust-domain>/ns/<namespace>/sa/<service-account>
。
ztunnel-pods-ips
是每个节点上用于存储 Ambient 网格 Pod IP 的集合。ztunnel-pods-ips
中,以确保这些 Pod 的流量可以被 iptables 规则识别和处理。istioin
和 istioout
),从而将流量引导至 ztunnel 进行处理。Istio Ambient 模式通过将数据平面功能分为 L4 和 L7 层的独立组件,为用户提供了更轻量且灵活的服务网格解决方案。这种方式不仅简化了服务的部署,还大幅降低了资源开销。通过术语表的方式,我们探讨了 Ambient 模式中的各种核心概念,从 ztunnel 到 waypoint proxy,再到 iptables 和 eBPF 的使用,帮助你全面了解 Istio Ambient 模式的架构和运行机制。如果你对服务网格感兴趣或正在考虑如何优化微服务通信,希望这篇文章对你有所帮助。
2025-01-21 10:02:05
在如今各种 AI 工具层出不穷的时代,找到一个好用又免费的绘图工具真的不容易。而 Raphael.app 就是一款非常值得一试的 AI 绘图工具。它简单易用,而且用英文提示词就能生成效果不错的图片。
这款以文艺复兴三杰之一拉斐尔(Raphael,全名:Raffaello Sanzio da Urbino,1483 年 4 月 6 日-1520 年 4 月 6 日)命名的工具,有以下特点:
操作非常简单:
Raphael 是一个用起来特别方便的 AI 绘图工具,既免费又能生成效果不错的图片。不管你是想找灵感还是单纯玩玩 AI,都非常值得一试。
2025-01-20 16:50:25
最近读了 TheNewStack 发布的电子书《Cloud Native Observability for DevOps Teams》,虽然这本书是 2022 年出品的,但给我了很大的启发。它不仅讨论了技术工具,还深入探讨了团队协作、文化建设和未来趋势的结合点。在这本书里,“观察”不仅仅是看到数据,而是看清背后的意义。可以说,它从根本上改变了我对可观测性的理解。
本书从基础定义到实际操作,系统地阐述了云原生可观测性的重要性及其实现方式。通过具体的工具和策略,它帮助读者理解如何整合指标、日志、追踪和混沌工程等维度,全面掌控分布式系统的健康状况,为 DevOps 团队提供高效的决策支持。
书中开篇就点明:可观测性是通过系统的外部信号推断内部状态的能力。不仅是传统的指标(Metrics)、日志(Logs)、追踪(Tracing)三根支柱的组合,而是一种综合性、全局化的分析方法。正如作者所说:
“Observability isn’t just the ability to see each piece at a time; it’s also the ability to understand the broader picture and how these pieces combine.”
书中特别强调了 Kubernetes 环境中日志和监控的复杂性。Kubernetes 没有内置的完整可观测性解决方案,只提供了基础功能,比如 kubectl
查看对象状态,而更高级的功能需要依赖第三方工具如 Fluentd 和 Prometheus。
书中在实践部分提到了多种实现可观测性的具体策略和工具:
kubectl get events
快速了解集群中资源的状态变化。这些实践指南强调了工具与策略的结合,从而实现全面的可观测性。
书中强调,单纯收集数据并不能解决问题,关键在于跨维度数据的整合与分析。例如,在性能问题排查时,指标和追踪往往无法直接关联,而这正是现有工具的短板。未来,统一数据存储和分析视角的工具,比如 OpenTelemetry 提倡的标准化方法,可能是突破口。
随着 AI 技术的发展,可观测性工具也可以更智能化。例如,通过机器学习预测异常,或是自动推荐优化策略。这不仅能减少人为干预,还能提升故障响应速度。正如作者在混沌工程部分提到的:
“Instead of waiting for something to happen and finding out how your application fares, you put it through duress under controlled conditions to identify weaknesses and fix them.”
书中提到“DevOps 的终极目标是跨团队的协作与同理心”,这点深有共鸣。尤其是在复杂分布式系统中,开发和运维团队往往各自为战,导致沟通断层。跨团队协作的关键在于工具提供的透明性与共享视角,而不仅仅是技术能力。
这本书的独到之处在于它从技术和人文两个角度同时切入,它让我意识到,可观测性不仅是一组工具的集合,而是一种文化、一种能力,帮助我们更深刻地理解系统,推动团队协作,并在复杂的云原生环境中建立起真正的“透明化”。
最后,我想引用书中一段非常打动我的话来结尾:
“Observability lets you see the beautiful and complete picture that is your production software systems.”
2025-01-14 18:28:37
在最近对 Istio Ambient 模式的研究中,我发现 HTTP2 Connect 方法被用作创建隧道的核心技术,以实现透明流量的拦截和转发。HTTP/2 CONNECT 隧道是一种强大的工具,可以在已有的 HTTP/2 连接中创建高效的隧道,用于传输原始的 TCP 数据。这篇文章通过一个简单的 Demo,展示了如何使用 Envoy 来实现 HTTP/2 CONNECT 隧道的基本功能。
HTTP2 Connect 方法是一种标准化的方式来创建隧道,用于透明地传输数据。特别是在 Istio 的 Ambient 模式中,它为代理数据平面之间的通信提供了一种高效的手段。HBONE(HTTP-Based Overlay Network Environment)隧道则是基于这种 HTTP2 Connect 技术的实现,用于 Istio 中的透明流量拦截和转发。通过使用 HBONE,数据可以有效地通过 HTTP2 隧道安全传输,替代了传统的 Sidecar 模式。这一创新设计极大地简化了服务网格的管理和部署。
HBONE 是 Istio 特有的术语,它是一种安全隧道协议,用于在 Istio 组件之间进行通信。在当前的 Istio 实现中,HBONE 协议包含了三个开放标准:
HTTP CONNECT 用于建立隧道连接,mTLS 用于安全地加密连接,而 HTTP/2 用于在单一安全隧道中多路复用应用连接流并传输附加的流级元数据。更多关于 HBONE 隧道的细节可以参考官方文档:HBONE 详细介绍。
HTTP2 Connect 方法允许我们创建一个类似于 VPN 的隧道,通过这个隧道可以安全地传递数据。建立隧道的基本步骤如下:
这种方法能够使得数据的传输过程更加透明且安全,特别适用于需要高效通信和端到端加密的场景。
下图展示了 HTTP2 Connect 方法建立隧道的基本过程。
本示例展示了一个基础场景:
架构图如下:
我们将使用 Node.js 来编写客户端和服务端,并将服务端和 Envoy 代理运行在容器中,在本地通过客户端访问 Envoy 代理从而达到访问客户端的目的。
完整的目录结构如下:
envoy-http2-tunnel/
├── certs/
│ ├── openssl.cnf
│ ├── server.crt
│ ├── server.key
├── client/
│ └── client.js
├── docker-compose.yml
├── envoy.yaml
└── server/
├── Dockerfile
└── server.js
确保你的系统已安装 Node.js(版本 >= 10.10.0),因为 http2
模块在该版本后稳定。
在你的工作空间中创建一个新目录并进入:
mkdir envoy-http2-tunnel
cd envoy-http2-tunnel
由于 Envoy 和服务器之间需要加密通信,我们需要生成包含正确配置的自签名证书。
创建 certs
目录:
mkdir certs
cd certs
创建 openssl.cnf
,内容如下:
[ req ]
default_bits = 2048
default_md = sha256
prompt = no
distinguished_name = dn
req_extensions = req_ext
[ dn ]
C = US
ST = California
L = San Francisco
O = My Company
OU = My Division
CN = server
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = server
DNS.2 = localhost
运行以下命令生成密钥和证书:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout server.key -out server.crt -config openssl.cnf
这将在 certs
目录中生成 server.key
和 server.crt
文件。
我们需要配置 Envoy,使其能够接受客户端的普通 TCP 连接,将数据通过 HTTP/2 CONNECT 隧道传递给服务器。
在项目根目录创建 envoy.yaml
,内容如下:
static_resources:
listeners:
- name: listener_0
address:
socket_address:
protocol: TCP
address: 0.0.0.0
port_value: 10000
filter_chains:
- filters:
- name: envoy.filters.network.tcp_proxy
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
stat_prefix: tcp_stats
cluster: tunnel_cluster
tunneling_config:
hostname: server:8080
access_log:
- name: envoy.access_loggers.stdout
typed_config:
"@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
log_format:
json_format:
start_time: "%START_TIME%"
method: "%REQ(:METHOD)%"
path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
protocol: "%PROTOCOL%"
response_code: "%RESPONSE_CODE%"
response_flags: "%RESPONSE_FLAGS%"
bytes_received: "%BYTES_RECEIVED%"
bytes_sent: "%BYTES_SENT%"
duration: "%DURATION%"
upstream_service_time: "%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%"
x_forwarded_for: "%REQ(X-FORWARDED-FOR)%"
user_agent: "%REQ(USER-AGENT)%"
request_id: "%REQ(X-REQUEST-ID)%"
upstream_host: "%UPSTREAM_HOST%"
upstream_cluster: "%UPSTREAM_CLUSTER%"
downstream_local_address: "%DOWNSTREAM_LOCAL_ADDRESS%"
downstream_remote_address: "%DOWNSTREAM_REMOTE_ADDRESS%"
clusters:
- name: tunnel_cluster
connect_timeout: 5s
type: LOGICAL_DNS
lb_policy: ROUND_ROBIN
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
sni: server
common_tls_context:
validation_context:
trusted_ca:
filename: "/certs/server.crt"
alpn_protocols: [ "h2" ]
http2_protocol_options: {}
load_assignment:
cluster_name: tunnel_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: server
port_value: 8080
在项目根目录创建 server
目录:
mkdir server
在 server
目录中创建 server.js
和 Dockerfile
。
server.js
在 server/server.js
中添加以下代码:
const http2 = require('http2');
const fs = require('fs');
const server = http2.createSecureServer({
key: fs.readFileSync('/certs/server.key'),
cert: fs.readFileSync('/certs/server.crt'),
});
server.on('stream', (stream, headers) => {
const method = headers[':method'];
const path = headers[':path'];
if (method === 'CONNECT') {
console.log(`Received CONNECT request for ${path}`);
// 响应 200,建立隧道
stream.respond({
':status': 200,
});
// 在隧道内处理数据
stream.on('data', (chunk) => {
const message = chunk.toString();
console.log(`Received from client: ${message}`);
// 回应客户端
const response = `Echo from server: ${message}`;
stream.write(response);
});
stream.on('end', () => {
console.log('Stream ended by client.');
stream.end();
});
} else {
// 对于非 CONNECT 请求,返回 404
stream.respond({
':status': 404,
});
stream.end();
}
});
server.listen(8080, () => {
console.log('Secure HTTP/2 server is listening on port 8080');
});
注意:
secureConnection
事件,直接处理 TLS 连接后的 socket。Dockerfile
在 server/Dockerfile
中添加以下内容:
FROM node:14
WORKDIR /app
COPY server.js .
EXPOSE 8080
CMD ["node", "server.js"]
在项目根目录创建 client
目录:
mkdir client
在 client
目录中创建 client.js
。
client.js
在 client/client.js
中添加以下代码:
const net = require('net');
// 创建与 Envoy 的 TCP 连接
const client = net.createConnection({ port: 10000 }, () => {
console.log('Connected to Envoy.');
// 发送消息给服务器
let counter = 1;
const interval = setInterval(() => {
const message = `Message ${counter} from client!`;
client.write(message);
counter += 1;
}, 1000);
// 关闭连接
setTimeout(() => {
clearInterval(interval);
client.end();
}, 5000);
});
client.on('data', (data) => {
console.log(`Received from server: ${data.toString()}`);
});
client.on('end', () => {
console.log('Disconnected from server.');
});
client.on('error', (err) => {
console.error('Client error:', err);
});
说明:
在项目根目录创建 docker-compose.yml
:
version: '3.8'
services:
envoy:
image: envoyproxy/envoy:v1.32.1
volumes:
- ./envoy.yaml:/etc/envoy/envoy.yaml
- ./certs:/certs # 挂载证书目录
ports:
- "10000:10000"
networks:
- envoy_network
depends_on:
- server
command: /usr/local/bin/envoy -c /etc/envoy/envoy.yaml --service-cluster envoy --log-level debug
server:
build:
context: ./server
networks:
- envoy_network
expose:
- "8080"
volumes:
- ./certs:/certs # 挂载证书目录
networks:
envoy_network:
在项目根目录下,运行:
docker-compose up --build
预期输出:
Secure HTTP/2 server is listening on port 8080
。打开新的终端窗口,进入 client
目录:
cd client
运行客户端:
node client.js
预期输出:
Connected to Envoy.
Received from server: Echo from server: Message 1 from client!
Received from server: Echo from server: Message 2 from client!
Received from server: Echo from server: Message 3 from client!
Received from server: Echo from server: Message 4 from client!
Received from server: Echo from server: Message 5 from client!
Disconnected from server.
在 Docker Compose 的输出中,你应该能看到服务器的日志:
envoy_1 | {"downstream_remote_address":"192.168.65.1:46306","path":null,"request_id":null,"bytes_sent":160,"protocol":null,"upstream_service_time":null,"bytes_received":88,"response_code":0,"user_agent":null,"downstream_local_address":"172.21.0.3:10000","upstream_host":"172.21.0.2:8080","start_time":"2024-12-03T11:37:59.542Z","upstream_cluster":"tunnel_cluster","duration":5012,"response_flags":"-","method":null,"x_forwarded_for":null}
server_1 | Secure HTTP/2 server is listening on port 8080
server_1 | New secure connection established.
server_1 | Received from client: Message 1 from client!
server_1 | Received from client: Message 2 from client!
server_1 | Received from client: Message 3 from client!
server_1 | Received from client: Message 4 from client!
server_1 | Received from client: Message 5 from client!
server_1 | Connection ended by client.
在 Envoy 的日志中,你可以看到它使用 HTTP/2 CONNECT 隧道与服务器建立连接的记录。
10000
(Envoy)和 8080
(服务器)未被占用。下图展示了客户端、Envoy 代理和服务器之间的交互,反映了数据的传递和隧道连接的建立的流程。
说明:
客户端与 Envoy 建立 TCP 连接:
Envoy 创建到服务器的连接:
tunnel_cluster
,创建新的连接(ConnectionId: 1)。建立 HTTP/2 CONNECT 隧道:
server:8080
。200 OK
,隧道建立成功。数据传输:
Message N
)到 Envoy。Echo Message N
)给 Envoy。Received from client: Message N from client!
。连接关闭:
日志记录:
Stream ended by client.
。虽然这是一个入门示例,但它为理解和进一步探索 HTTP/2 CONNECT 隧道功能提供了坚实的基础。在下一篇博客中讲解通过两个 Envoy 代理实现的隧道,带你进一步了解 Istio ambient 模式中的 HBONE 透明隧道。
2025-01-09 18:26:54
在工作中,我们经常需要清晰地传达复杂的想法,但单靠文字有时候实在不够直观。这时候,一张清晰的图表往往能让人一眼看懂你的思路。
今天想给大家推荐一个特别好用的工具——Napkin.ai。它可以自动把你的文字内容变成图表,比如信息图、流程图等等,让你的想法更容易被理解和传播。
不管你是市场营销人员、内容创作者,还是需要做商业演示的专业人士,Napkin.ai 都能帮你提升沟通效果,让你的内容更吸引人。
这款工具真的非常方便,试一次就会爱上!支持中文,而且免费使用,无次数限制。如果你也需要一个帮手来把复杂想法变得更直观,赶紧去试试吧!