<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Tony Bai &#187; istio</title>
	<atom:link href="http://tonybai.com/tag/istio/feed/" rel="self" type="application/rss+xml" />
	<link>https://tonybai.com</link>
	<description>一个程序员的心路历程</description>
	<lastBuildDate>Mon, 20 Apr 2026 23:16:50 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Go 2025云原生与可观测年度报告：底层性能革新与生态固防</title>
		<link>https://tonybai.com/2025/12/03/go-2025-cloud-native-observability-report/</link>
		<comments>https://tonybai.com/2025/12/03/go-2025-cloud-native-observability-report/#comments</comments>
		<pubDate>Wed, 03 Dec 2025 00:09:11 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[AI调度]]></category>
		<category><![CDATA[AmbientMesh]]></category>
		<category><![CDATA[APIGateway]]></category>
		<category><![CDATA[AWSCDK]]></category>
		<category><![CDATA[CgroupAware]]></category>
		<category><![CDATA[cloudnative]]></category>
		<category><![CDATA[CNCF]]></category>
		<category><![CDATA[containerd]]></category>
		<category><![CDATA[ContextSwitching]]></category>
		<category><![CDATA[ControlPlane]]></category>
		<category><![CDATA[CRIO]]></category>
		<category><![CDATA[CVE-2025-64329]]></category>
		<category><![CDATA[DataPlane]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[DRA]]></category>
		<category><![CDATA[DynamicResourceAllocation]]></category>
		<category><![CDATA[eBPF]]></category>
		<category><![CDATA[encoding/json]]></category>
		<category><![CDATA[etcd]]></category>
		<category><![CDATA[ExtendedTolerationOperators]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[go1.25]]></category>
		<category><![CDATA[Golang]]></category>
		<category><![CDATA[GOMAXPROCS]]></category>
		<category><![CDATA[GoroutineLeak]]></category>
		<category><![CDATA[GreenTeaGC]]></category>
		<category><![CDATA[IaC]]></category>
		<category><![CDATA[InplacePodResize]]></category>
		<category><![CDATA[istio]]></category>
		<category><![CDATA[jsonv2]]></category>
		<category><![CDATA[Knative]]></category>
		<category><![CDATA[kubebuilder]]></category>
		<category><![CDATA[Kubernetes]]></category>
		<category><![CDATA[OBI]]></category>
		<category><![CDATA[observability]]></category>
		<category><![CDATA[opentelemetry]]></category>
		<category><![CDATA[OperatorSDK]]></category>
		<category><![CDATA[Otel]]></category>
		<category><![CDATA[OTelGoSDK]]></category>
		<category><![CDATA[prometheus]]></category>
		<category><![CDATA[Pulumi]]></category>
		<category><![CDATA[RequestReply]]></category>
		<category><![CDATA[RuntimeMetrics]]></category>
		<category><![CDATA[Rust]]></category>
		<category><![CDATA[serverless]]></category>
		<category><![CDATA[ServiceMesh]]></category>
		<category><![CDATA[terraform]]></category>
		<category><![CDATA[v1.35]]></category>
		<category><![CDATA[ZeroAllocation]]></category>
		<category><![CDATA[事件驱动架构]]></category>
		<category><![CDATA[云原生]]></category>
		<category><![CDATA[内存泄露]]></category>
		<category><![CDATA[去Sidecar化]]></category>
		<category><![CDATA[双活模式]]></category>
		<category><![CDATA[反射]]></category>
		<category><![CDATA[可观测性]]></category>
		<category><![CDATA[垃圾回收]]></category>
		<category><![CDATA[基础设施即代码]]></category>
		<category><![CDATA[容器]]></category>
		<category><![CDATA[性能革新]]></category>
		<category><![CDATA[零侵入]]></category>
		<category><![CDATA[默认稳定]]></category>

		<guid isPermaLink="false">https://tonybai.com/?p=5468</guid>
		<description><![CDATA[本文永久链接 &#8211; https://tonybai.com/2025/12/03/go-2025-cloud-native-observability-report 大家好，我是Tony Bai。 2025年，对于 Go 语言和云原生生态来说，是充满挑战与变革的一年。 凭借务实的并发模型、极快的编译速度和极简的部署体验，Go 语言在过去十年间毫无争议地坐稳了现代云原生基础设施的“铁王座”。从 Kubernetes 到 Docker，从 Prometheus 到 etcd，CNCF 生态中那些最耀眼的明星项目，几乎都流淌着 Go 的血液。 但技术世界没有永远的王座。2025年，面对日益复杂的云原生挑战——如容器资源的极致限制、大规模并发状态管理，以及来自 Rust 等追求极致性能的新生代语言的“围剿”——Go 语言并非高枕无忧。 面对挑战，Go 在 2025 年交出了一份怎样的答卷？它是如何通过 Go 1.25 的底层性能革新、Kubernetes 的架构演进以及 OpenTelemetry 的生态防御来巩固壁垒的？ 本文将带你全景式复盘 Go 语言在 2025 年的硬核反击战。 底层突破：Go 1.25 为云原生带来的“性能红利” 所有上层应用的性能飞跃，都源自底层的坚实支撑。面对“性能不够极致”的质疑，2025年8月发布的 Go 1.25 祭出了近年来针对云原生场景最“贴心”的三大杀招，直接回击了对 Go 运行时的效率诟病。 Cgroup 智能感知：终于读懂了容器的心 长期以来，Go 应用在容器中运行时有一个痛点：GOMAXPROCS 默认会“误以为”自己拥有宿主机的所有逻辑 CPU 资源。当容器被 Cgroup [...]]]></description>
			<content:encoded><![CDATA[<p><img src="https://tonybai.com/wp-content/uploads/2025/go-2025-cloud-native-observability-report-1.png" alt="" /></p>
<p><a href="https://tonybai.com/2025/12/03/go-2025-cloud-native-observability-report">本文永久链接</a> &#8211; https://tonybai.com/2025/12/03/go-2025-cloud-native-observability-report</p>
<p>大家好，我是Tony Bai。</p>
<p><strong>2025年，对于 Go 语言和云原生生态来说，是充满挑战与变革的一年。</strong></p>
<p>凭借务实的<a href="https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzIyNzM0MDk0Mg==&amp;action=getalbum&amp;album_id=4105816518230016005#wechat_redirect">并发模型</a>、极快的编译速度和极简的部署体验，Go 语言在过去十年间毫无争议地坐稳了现代云原生基础设施的“铁王座”。从 <a href="https://tonybai.com/2025/11/26/how-google-built-a-130000-node-k8s-cluster"><strong>Kubernetes</strong></a> 到 <strong>Docker</strong>，从 <strong>Prometheus</strong> 到 <strong>etcd</strong>，CNCF 生态中那些最耀眼的明星项目，几乎都流淌着 Go 的血液。</p>
<p>但技术世界没有永远的王座。2025年，面对日益复杂的云原生挑战——如容器资源的极致限制、大规模并发状态管理，以及来自 <strong>Rust</strong> 等追求极致性能的新生代语言的“围剿”——Go 语言并非高枕无忧。</p>
<p>面对挑战，Go 在 2025 年交出了一份怎样的答卷？它是如何通过 <strong>Go 1.25</strong> 的底层性能革新、<strong>Kubernetes</strong> 的架构演进以及 <strong>OpenTelemetry</strong> 的生态防御来巩固壁垒的？</p>
<p>本文将带你全景式复盘 Go 语言在 2025 年的硬核反击战。</p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/go-2025-cloud-native-observability-report-2.png" alt="" /></p>
<hr />
<h2>底层突破：Go 1.25 为云原生带来的“性能红利”</h2>
<p>所有上层应用的性能飞跃，都源自底层的坚实支撑。面对“性能不够极致”的质疑，2025年8月发布的 <strong>Go 1.25</strong> 祭出了近年来针对云原生场景最“贴心”的三大杀招，直接回击了对 Go 运行时的效率诟病。</p>
<h3><a href="https://tonybai.com/2025/04/09/gomaxprocs-defaults-add-cgroup-aware/">Cgroup 智能感知</a>：终于读懂了容器的心</h3>
<p>长期以来，Go 应用在容器中运行时有一个痛点：GOMAXPROCS 默认会“误以为”自己拥有宿主机的所有逻辑 CPU 资源。当容器被 Cgroup V2 严格限制了 CPU 配额（Quota）时，Go 运行时仍会创建过多的系统线程，导致严重的上下文切换（Context Switching）和性能抖动。</p>
<p>Go 1.25 终于引入了 <strong>Cgroup-Aware GOMAXPROCS</strong>。Go 运行时现在能周期性地自动检测容器的 Cgroup CPU 配额，并动态调整内部的并发级别。这直接减少了无谓的线程争用，让运行在 Kubernetes Pod 中的 Go 服务（尤其是那些资源受限的 Sidecar 或 Agent）无需人工调优即可获得更稳定、更高效的表现。</p>
<h3>GreenTea GC：向“GC 暂停”宣战</h3>
<p>为了应对高吞吐量场景下的延迟敏感需求，Go 1.25 带来了实验性的 <strong><a href="https://tonybai.com/2025/10/31/deep-into-go-green-tea-gc">GreenTea GC</a></strong>。这是一款专门针对<strong>“小对象密集型”</strong>应用（如日志收集器、OpenTelemetry Collector、K8s 控制器）进行优化的垃圾回收器。</p>
<p>GreenTea GC 改进了内存局部性，并大幅提高了标记阶段的并行性。在典型负载下，<strong>总体 GC 开销降低约 40%</strong>，显著改善了 P99 尾部延迟。这是 Go 在面对 Rust “零成本抽象”挑战时的一次强力技术回应，证明了带 GC 的语言在高性能领域依然能打。</p>
<h3><a href="https://tonybai.com/2025/08/09/true-streaming-support-in-jsonv2">JSON/v2</a>：零内存分配的极速体验</h3>
<p>标准库中的 encoding/json 曾是著名的性能瓶颈，其依赖运行时的反射机制导致了较高的 CPU 和内存消耗。Go 1.25 重写的 <strong>encoding/json/v2</strong> 彻底改变了这一局面。 这次重写带来了 <strong>3-10 倍</strong> 的反序列化速度提升，并实现了关键的<strong>“零堆内存分配”</strong>特性。对于 Kubernetes API Server 这种每天处理海量 JSON 配置和状态更新的组件来说，这意味着巨大的 CPU 周期节省和内存压力释放，直接提升了整个集群控制平面的吞吐上限。</p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/paid/google-adk-in-action-qr.png" alt="" /></p>
<hr />
<h2>基础设施：Kubernetes 与容器运行时的演进</h2>
<h3>Kubernetes v1.35：更聪明的 AI 调度</h3>
<p>作为 Go 语言的“长子”，Kubernetes 在 2025 年 11 月迎来了 v1.35 版本。除了常规的稳定性提升，最引人注目的是其调度器针对 <strong>AI/ML 工作负载</strong>的进化。这意味着 K8s 能够更精细地处理 AI 训练任务对 GPU、内存等资源的苛刻要求，实现基于阈值的资源匹配。Go 语言高效的并发模型支撑了这一日益复杂的调度逻辑。</p>
<p>同时该新版本还引入了基于阈值的<strong>Extended Toleration Operators</strong>，新增了 Gt (大于) 和 Lt (小于) 等逻辑。</p>
<p>除了 v1.35 的调度增强，K8s 在 2025 年上半年的两个版本中也引入了多项值得关注的改进：</p>
<ul>
<li><strong>DRA (Dynamic Resource Allocation) 走向稳定</strong>：在 v1.34 中，DRA 的核心 API 将升级为 Stable。这为 GPU 等硬件加速器提供了更加灵活、标准化的资源请求和分配机制，摆脱了过去对非透明参数的依赖。</li>
<li><strong>Sidecar 容器支持增强</strong>：虽然 Service Mesh 正在去 Sidecar 化，但 K8s 本身对 Sidecar 的原生支持却在加强。v1.33 引入了 In-place Pod Resize（原地调整 Pod 资源）的 Beta 支持，允许在不重启 Pod 的情况下动态调整容器的 CPU/内存限制，这对有状态应用和长连接服务至关重要。</li>
<li><strong>安全性加固</strong>：v1.33 默认启用了对 Linux Pod 的 User Namespaces 支持，显著降低了容器逃逸风险；同时，kubelet 开始支持使用 ServiceAccount Token 拉取镜像，逐步淘汰长期的 Image Pull Secrets。</li>
</ul>
<h3>容器运行时：containerd vs. CRI-O 的双雄格局</h3>
<p>在彻底移除 dockershim 后，容器运行时生态形成了双雄并立的局面，且均由 Go 语言驱动：<br />
*   <strong>containerd</strong>：功能全面、极其稳定，支持镜像管理、零停机更新，是 AWS EKS、Google GKE 等云厂商的默认首选。<br />
*   <strong>CRI-O</strong>：极简主义，专为 K8s 设计，启动更快，资源占用更低，适合边缘计算等对资源敏感的场景。</p>
<h3>警钟长鸣：containerd 内存泄露事件</h3>
<p>2025 年 11 月披露的 containerd 漏洞 (<strong>CVE-2025-64329</strong>) 给 Go 开发者敲响了警钟。该漏洞存在于 CRI Attach 实现中，用户重复调用 kubectl attach 可能导致 <strong>Goroutine 泄露</strong>，进而耗尽宿主机内存。这也反向推动了 Go 运行时可观测性的重要性（详见下文）。即便是内存安全的语言，如果并发控制不当，依然会导致资源枯竭。</p>
<h3>Operator 的安全模型升级</h3>
<p>Kubernetes Operator 是 Go 生态的另一大杀手锏。2025 年，Operator SDK 和 Kubebuilder 终于移除了对外部 kube-rbac-proxy 的依赖，转而使用 controller-runtime 库内置的 WithAuthenticationAndAuthorization 功能。指标端点（Metrics Endpoint）的安全保护逻辑被直接集成在 Go 代码的控制循环中。其带来的价值是架构更简单，攻击面更小，部署 Operator 变得“默认安全”。</p>
<hr />
<h2>架构演进：Service Mesh 与 Serverless 的新篇章</h2>
<h3>Istio Ambient Mesh：全面去 Sidecar 化</h3>
<p>服务网格正在经历一场革命。2025 年，Istio 全力推广 <strong>Ambient Mesh</strong> 模式，旨在移除侵入式的 Sidecar 代理，提供更轻量、更快速的体验。<br />
*   <strong>控制平面</strong>：Go 语言编写的控制平面（Istiod）在其中扮演了指挥官的角色，负责管理这一新型架构。<br />
*   <strong>多集群突破</strong>：Istio 1.27 (Alpha) 引入了 Ambient 模式下的多集群流量管理，允许企业以<strong>Active-Active</strong> 模式运行高可用服务，利用 Go 驱动的控制逻辑优化跨区域流量成本。</p>
<h3>Knative 毕业：Serverless 的成熟里程碑</h3>
<p>2025 年 10 月，Knative 正式从 CNCF 毕业，标志着 Go 语言构建的 Serverless 抽象层已经完全成熟。Knative Eventing 新增了 <strong>RequestReply</strong> 资源，加强了同步与异步工作负载之间的桥接能力，进一步巩固了 Go 在构建复杂事件驱动架构（EDA）中的统治地位。</p>
<h3>Go 在 IaC 中的隐形统治</h3>
<p>在基础设施即代码（IaC）领域，虽然 Terraform (HCL) 占据前台，但如 <strong>Pulumi</strong> 和 <strong>AWS CDK</strong> 等开发者优先平台，正大量利用 Go 语言的静态类型优势和丰富的库生态作为后端逻辑支撑，提升了 IaC 的测试能力和抽象水平。</p>
<hr />
<h2>可观测性：OpenTelemetry 的“默认稳定”战略</h2>
<h3>OTel Go SDK：从“可用”到“默认稳定”</h3>
<p>OpenTelemetry (OTel) 是云原生可观测性的事实标准。2025 年 11 月，OTel 治理委员会宣布了战略调整：确保所有分发版<strong>“默认稳定” (stable by default)</strong>。</p>
<p>同时，OTel Go SDK 的 <strong>Traces</strong> 和 <strong>Metrics</strong> 组件均已达到 Stable 状态，Logs SDK 处于 Beta。这标志着 Go 生态的可观测性基石已完全成熟，企业可放心在生产环境大规模部署。</p>
<h3>运行时指标：从“Opt-In”到“Opt-Out”</h3>
<p>为了更好地诊断像 containerd 内存泄露这样的问题，OTel Go SIG 正在推进一项关键变更：将 <strong>Go Runtime Metrics</strong>（如 GC 暂停时间、堆内存使用、Goroutine 数量）从“选择性开启”改为<strong>“默认开启” (Opt-Out)</strong>。这意味着运维人员能“开箱即用”地看到 Go 应用的内部健康状况，配合 OTel 的语义惯例，能够更早地发现由 GC 或并发引起的潜在风险。</p>
<h3>配置简化：YAML/JSON 文件支持</h3>
<p>为了降低在 K8s 中的部署难度，OTel Go SDK 正在增强对 YAML/JSON 文件配置的支持，改变了过去过度依赖环境变量的局面，提升了配置的灵活性和易用性。</p>
<h3>里程碑：OpenTelemetry eBPF Instrumentation (OBI) 正式发布</h3>
<p>2025 年 11 月，OpenTelemetry 社区迎来了一个重磅时刻：<strong>OpenTelemetry eBPF Instrumentation (OBI)</strong> 发布了首个 Alpha 版本。</p>
<ul>
<li><strong>零侵入，全覆盖</strong>：OBI 利用 eBPF 技术在内核层进行观测，无需修改代码、无需重启服务、无需引入任何应用依赖，即可实现对 HTTP, gRPC, SQL (MySQL, PostgreSQL), Redis, Kafka 等多种协议的自动追踪和指标采集。</li>
<li><strong>多语言一致性</strong>：无论你的应用是 Go, Java, Python 还是 Node.js 编写的，OBI 都能提供统一、标准的遥测数据。这对于那些包含遗留系统或多语言技术栈的企业来说，是实现全链路可观测性的“银弹”。</li>
<li><strong>与 SDK 的互补</strong>：OBI 并非要取代传统的 SDK 插桩。它更适合作为“基线”观测手段，快速覆盖所有服务；而对于需要深入应用内部逻辑（如业务埋点、复杂上下文传播）的场景，结合使用 OTel Go SDK 依然是最佳实践。</li>
</ul>
<hr />
<h2>巅峰对决：Go vs. Rust 在 2025</h2>
<p>我们在这里回答前面的问题：面对 Rust 的围剿，Go 守住了吗？</p>
<ul>
<li><strong>Go 的基本盘（铁王座）</strong>：在<strong>控制平面（Control Plane）</strong>、API 网关、K8s Operator 以及企业级微服务等需要快速迭代、高并发协作的领域，Go 依然是<strong>绝对王者</strong>。其极低的心智负担、极高的开发效率和成熟的生态，是 Rust 短期内难以撼动的。</li>
<li><strong>Rust 的突围（特种兵）</strong>：在<strong>数据平面（Data Plane）</strong>（如 Envoy 插件）、高性能计算等对内存安全和尾部延迟有苛刻要求的领域，Rust 凭借“零 GC”和编译期内存安全检查，确实撕开了一道口子，比 Go 快约 <strong>1.5 倍</strong>，且没有 GC 抖动。</li>
</ul>
<p><strong>2025 年的格局</strong>：Go 没有坐以待毙。通过 GreenTea GC 降低 40% 的 GC 开销，通过 JSON/v2 消除反射带来的性能损耗，Go 正在努力<strong>拉高性能下限</strong>，防止被 Rust 侵蚀核心领地。对于大多数云原生应用来说，Go 依然是<strong>综合成本（开发效率+运行效率）最低、最稳妥的选择</strong>。</p>
<hr />
<h2>总结与建议</h2>
<p>2025 年，Go 语言没有停下脚步。通过 Go 1.25 的底层革新，它补齐了在容器化环境和 JSON 处理上的短板；通过 K8s 和 OTel 的持续演进，它在云原生生态中构建了更坚固的防线。</p>
<p><strong>面对 Rust 的围剿，Go 不仅守住了铁王座，还通过自我进化，让这个王座变得更加稳固。</strong></p>
<p><strong>给技术团队的建议：</strong></p>
<ol>
<li><strong>尽快升级</strong>：将核心服务升级到 <strong>Go 1.25+</strong>，白嫖 Cgroup 感知和 JSON 性能提升，这对于降本增效立竿见影。</li>
<li><strong>拥抱 OTel</strong>：采用 OpenTelemetry Go SDK(虽然有些复杂^_^)，并利用默认开启的运行时指标，建立更精细的监控体系，防范 Goroutine 泄露等隐形杀手。</li>
<li><strong>理性选型</strong>：对于绝大多数业务服务和控制平面，<strong>坚持使用 Go</strong>；只有在极少数对延迟极其敏感、且逻辑相对稳定的数据平面组件中，才考虑引入 Rust。</li>
</ol>
<p>Go 的 2025，是稳中求进、自我革新的一年。云原生的未来，依然写满了 Go 的名字。</p>
<hr />
<h2>参考资料</h2>
<p>本文基于 2025 年多份权威技术报告与社区动态整理而成，涵盖 CNCF、Go 官方博客、Kubernetes 发布说明及 OpenTelemetry 社区公告等。</p>
<ol>
<li>Golang in 2025: Usage, Trends, and Popularity &#45; Medium, accessed November 28, 2025, <a href="https://medium.com/@datajournal/golang-in-2025-usage-trends-and-popularity-3379928dd8e2">https://medium.com/@datajournal/golang-in-2025-usage-trends-and-popularity-3379928dd8e2</a>  </li>
<li>The Go Ecosystem in 2025: Key Trends in Frameworks, Tools, and Developer Practices, accessed November 28, 2025, <a href="https://blog.jetbrains.com/go/2025/11/10/go-language-trends-ecosystem-2025/">https://blog.jetbrains.com/go/2025/11/10/go-language-trends-ecosystem-2025/</a>  </li>
<li>Go: Driving The Next Wave of Cloud-Native Infrastructure &#45; Open Source For You, accessed November 28, 2025, <a href="https://www.opensourceforu.com/2025/11/go-driving-the-next-wave-of-cloud-native-infrastructure/">https://www.opensourceforu.com/2025/11/go-driving-the-next-wave-of-cloud-native-infrastructure/</a>  </li>
<li>Go 1.25 Highlights: How Generics and Performance Define the &#8230;, accessed November 28, 2025, <a href="https://dev.to/leapcell/go-125-highlights-how-generics-and-performance-define-the-future-of-go-4pdh">https://dev.to/leapcell/go-125-highlights-how-generics-and-performance-define-the-future-of-go-4pdh</a>  </li>
<li>Kubernetes v1.35 Sneak Peek, accessed November 28, 2025, <a href="https://kubernetes.io/blog/2025/11/26/kubernetes-v1-35-sneak-peek/">https://kubernetes.io/blog/2025/11/26/kubernetes-v1-35-sneak-peek/</a>  </li>
<li>Kubernetes v1.35 Release Highlights &#35;2903 &#45; GitHub, accessed November 28, 2025, <a href="https://github.com/kubernetes/sig-release/discussions/2903">https://github.com/kubernetes/sig-release/discussions/2903</a>  </li>
<li>Top Docker Alternatives in 2025: A Complete Guide &#45; DataCamp, accessed November 28, 2025, <a href="https://www.datacamp.com/blog/docker-alternatives">https://www.datacamp.com/blog/docker-alternatives</a>  </li>
<li>15 Best Docker Alternatives for 2025: Complete Guide with Pros, Cons &amp; Migration, accessed November 28, 2025, <a href="https://signoz.io/comparisons/docker-alternatives/">https://signoz.io/comparisons/docker-alternatives/</a>  </li>
<li>CVE-2025-64329: containerd CRI server: Host memory exhaustion through Attach goroutine leak &#45; GitLab Advisory Database, accessed November 28, 2025, <a href="https://advisories.gitlab.com/pkg/golang/github.com/containerd/containerd/v2/CVE-2025-64329/">https://advisories.gitlab.com/pkg/golang/github.com/containerd/containerd/v2/CVE-2025-64329/</a>  </li>
<li>CVE-2025-64329: containerd CRI Attach Memory DoS &#45; Miggo Security, accessed November 28, 2025, <a href="https://www.miggo.io/vulnerability-database/cve/CVE-2025-64329">https://www.miggo.io/vulnerability-database/cve/CVE-2025-64329</a>  </li>
<li>operator-framework/operator-sdk: SDK for building Kubernetes applications. Provides high level APIs, useful abstractions, and project scaffolding. &#45; GitHub, accessed November 28, 2025, <a href="https://github.com/operator-framework/operator-sdk">https://github.com/operator-framework/operator-sdk</a>  </li>
<li>Repo for the controller-runtime subproject of kubebuilder (sig-apimachinery) &#45; GitHub, accessed November 28, 2025, <a href="https://github.com/kubernetes-sigs/controller-runtime">https://github.com/kubernetes-sigs/controller-runtime</a>  </li>
<li>Metrics &#45; The Kubebuilder Book, accessed November 28, 2025, <a href="https://book.kubebuilder.io/reference/metrics.html">https://book.kubebuilder.io/reference/metrics.html?highlight=metr</a>  </li>
<li>Istio / Istio Roadmap for 2025-2026, accessed November 28, 2025, <a href="https://istio.io/latest/blog/2025/roadmap/">https://istio.io/latest/blog/2025/roadmap/</a>  </li>
<li>Cloud Native Computing Foundation Announces Knative&#8217;s Graduation | CNCF, accessed November 28, 2025, <a href="https://www.cncf.io/announcements/2025/10/08/cloud-native-computing-foundation-announces-knatives-graduation/">https://www.cncf.io/announcements/2025/10/08/cloud-native-computing-foundation-announces-knatives-graduation/</a>  </li>
<li>The 16 Best Infrastructure As Code (IaC) Tools In 2025 &#45; Apiiro, accessed November 28, 2025, <a href="https://apiiro.com/blog/best-iac-tools/">https://apiiro.com/blog/best-iac-tools/</a>  </li>
<li>Evolving OpenTelemetry&#8217;s Stabilization and Release Practices, accessed November 28, 2025, <a href="https://opentelemetry.io/blog/2025/stability-proposal-announcement/">https://opentelemetry.io/blog/2025/stability-proposal-announcement/</a>  </li>
<li>Go &#45; OpenTelemetry, accessed November 28, 2025, <a href="https://opentelemetry.io/docs/languages/go/">https://opentelemetry.io/docs/languages/go/</a>  </li>
<li>OpenTelemetry Go 2025 Goals, accessed November 28, 2025, <a href="https://opentelemetry.io/blog/2025/go-goals/">https://opentelemetry.io/blog/2025/go-goals/</a>  </li>
<li>Configuration &#45; OpenTelemetry, accessed November 28, 2025, <a href="https://opentelemetry.io/docs/collector/configuration/">https://opentelemetry.io/docs/collector/configuration/</a>  </li>
<li>Prometheus with Grafana: 5 Compelling Use Cases &#45; Tigera.io, accessed November 28, 2025, <a href="https://www.tigera.io/learn/guides/prometheus-monitoring/prometheus-grafana/">https://www.tigera.io/learn/guides/prometheus-monitoring/prometheus-grafana/</a>  </li>
<li>Top Prometheus Exporters in 2025 and How to Use Them Effectively &#45; GoCodeo, accessed November 28, 2025, <a href="https://www.gocodeo.com/post/top-prometheus-exporters-in-2025-and-how-to-use-them-effectively">https://www.gocodeo.com/post/top-prometheus-exporters-in-2025-and-how-to-use-them-effectively</a>  </li>
<li>Rust vs Go in 2025: Comparison of Performance, Complexity, and &#8230;, accessed November 28, 2025, <a href="https://evrone.com/blog/rustvsgo">https://evrone.com/blog/rustvsgo</a>  </li>
<li>Rust vs Go: Which one to choose in 2025 | The RustRover Blog, accessed November 28, 2025, <a href="https://blog.jetbrains.com/rust/2025/06/12/rust-vs-go/">https://blog.jetbrains.com/rust/2025/06/12/rust-vs-go/</a>  </li>
<li>Your Complete Guide to KubeCon &#43; CloudNativeCon North America 2025 | CNCF, accessed November 28, 2025, <a href="https://www.cncf.io/blog/2025/11/06/your-complete-guide-to-kubecon-cloudnativecon-north-america-2025/">https://www.cncf.io/blog/2025/11/06/your-complete-guide-to-kubecon-cloudnativecon-north-america-2025/</a></li>
</ol>
<hr />
<p>还在为“复制粘贴喂AI”而烦恼？我的新专栏 <strong>《<a href="http://gk.link/a/12EPd">AI原生开发工作流实战</a>》</strong> 将带你：</p>
<ul>
<li>告别低效，重塑开发范式</li>
<li>驾驭AI Agent(Claude Code)，实现工作流自动化</li>
<li>从“AI使用者”进化为规范驱动开发的“工作流指挥家”</li>
</ul>
<p>扫描下方二维码，开启你的AI原生开发之旅。</p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/ai-native-dev-workflow-qr.png" alt="" /></p>
<hr />
<p>你的Go技能，是否也卡在了“熟练”到“精通”的瓶颈期？</p>
<ul>
<li>想写出更地道、更健壮的Go代码，却总在细节上踩坑？</li>
<li>渴望提升软件设计能力，驾驭复杂Go项目却缺乏章法？</li>
<li>想打造生产级的Go服务，却在工程化实践中屡屡受挫？</li>
</ul>
<p>继《<a href="http://gk.link/a/10AVZ">Go语言第一课</a>》后，我的《<a href="http://gk.link/a/12yGY">Go语言进阶课</a>》终于在极客时间与大家见面了！</p>
<p>我的全新极客时间专栏 《<a href="http://gk.link/a/12yGY">Tony Bai·Go语言进阶课</a>》就是为这样的你量身打造！30+讲硬核内容，带你夯实语法认知，提升设计思维，锻造工程实践能力，更有实战项目串讲。</p>
<p>目标只有一个：助你完成从“Go熟练工”到“Go专家”的蜕变！ 现在就加入，让你的Go技能再上一个新台阶！</p>
<p><img src="https://tonybai.com/wp-content/uploads/course-card/iamtonybai-banner-2.gif" alt="" /></p>
<hr />
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求，请扫描下方公众号二维码，与我私信联系。</p>
<p><img src="http://image.tonybai.com/img/tonybai/iamtonybai-wechat-qr.png" alt="" /></p>
<p style='text-align:left'>&copy; 2025, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2025/12/03/go-2025-cloud-native-observability-report/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>7 个常见的 Kubernetes 陷阱（以及我是如何学会避免它们的）</title>
		<link>https://tonybai.com/2025/10/22/seven-kubernetes-pitfalls/</link>
		<comments>https://tonybai.com/2025/10/22/seven-kubernetes-pitfalls/#comments</comments>
		<pubDate>Wed, 22 Oct 2025 13:21:36 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[CNCF]]></category>
		<category><![CDATA[CNI插件]]></category>
		<category><![CDATA[ConfigMaps]]></category>
		<category><![CDATA[CPU]]></category>
		<category><![CDATA[Deployments]]></category>
		<category><![CDATA[DNS解析]]></category>
		<category><![CDATA[FluentBit]]></category>
		<category><![CDATA[Fluentd]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Golang]]></category>
		<category><![CDATA[HorizontalPodAutoscaler]]></category>
		<category><![CDATA[ingress]]></category>
		<category><![CDATA[ingress-nginx]]></category>
		<category><![CDATA[istio]]></category>
		<category><![CDATA[jaeger]]></category>
		<category><![CDATA[kubectllogs]]></category>
		<category><![CDATA[Kubernetes]]></category>
		<category><![CDATA[kustomize]]></category>
		<category><![CDATA[Kyverno]]></category>
		<category><![CDATA[OOMKilled]]></category>
		<category><![CDATA[OPAGatekeeper]]></category>
		<category><![CDATA[opentelemetry]]></category>
		<category><![CDATA[PersistentVolumeClaims]]></category>
		<category><![CDATA[Pod安全准入]]></category>
		<category><![CDATA[prometheus]]></category>
		<category><![CDATA[RBAC]]></category>
		<category><![CDATA[SealedSecrets]]></category>
		<category><![CDATA[Secrets]]></category>
		<category><![CDATA[Service]]></category>
		<category><![CDATA[SRE]]></category>
		<category><![CDATA[TonyBai]]></category>
		<category><![CDATA[云原生]]></category>
		<category><![CDATA[内存]]></category>
		<category><![CDATA[分布式追踪]]></category>
		<category><![CDATA[启动探针]]></category>
		<category><![CDATA[垃圾回收]]></category>
		<category><![CDATA[存活探针]]></category>
		<category><![CDATA[安全]]></category>
		<category><![CDATA[容器日志]]></category>
		<category><![CDATA[就绪探针]]></category>
		<category><![CDATA[开发环境]]></category>
		<category><![CDATA[服务网格]]></category>
		<category><![CDATA[生产环境]]></category>
		<category><![CDATA[网络]]></category>
		<category><![CDATA[资源请求]]></category>
		<category><![CDATA[限制]]></category>
		<category><![CDATA[陷阱]]></category>
		<category><![CDATA[集中化日志]]></category>

		<guid isPermaLink="false">https://tonybai.com/?p=5289</guid>
		<description><![CDATA[本文永久链接 &#8211; https://tonybai.com/2025/10/22/seven-kubernetes-pitfalls 大家好，我是Tony Bai。 本文翻译自Kubernetes官方博客《7 Common Kubernetes Pitfalls (and How I Learned to Avoid Them)》一文。 这篇文章的作者Abdelkoddous Lhajouji 以第一人称视角，系统性地梳理了从资源管理、健康检查到安全配置等多个方面，新手乃至资深工程师都极易忽视的关键点。文中的每个“陷阱”都源于真实的生产经验，其规避建议更是极具实践指导意义。无论你是 K8s 初学者还是经验丰富的 SRE，相信都能从中获得启发，审视并改善自己的日常实践。 以下是译文全文，供大家参考。 Kubernetes 有时既强大又令人沮丧，这已经不是什么秘密了。当我刚开始涉足容器编排时，我犯的错误足以整理出一整份陷阱清单。在这篇文章中，我想详细介绍我遇到（或看到别人遇到）的七个大坑，并分享一些如何避免它们的技巧。无论你是刚开始接触 Kubernetes，还是已经在管理生产集群，我都希望这些见解能帮助你避开一些额外的压力。 忽略资源请求（requests）和限制（limits） 陷阱：在 Pod 规范中不指定 CPU 和内存需求。这通常是因为 Kubernetes 并不强制要求这些字段，而且工作负载通常可以在没有它们的情况下启动和运行——这使得在早期配置或快速部署周期中很容易忽略这个疏漏。 背景：在 Kubernetes 中，资源请求和限制对于高效的集群管理至关重要。资源请求确保调度器为每个 Pod 预留适当数量的 CPU 和内存，保证其拥有运行所需的必要资源。资源限制则为 Pod 可以使用的 CPU 和内存设置了上限，防止任何单个 Pod 消耗过多资源，从而可能导致其他 Pod 资源匮乏。当未设置资源请求和限制时： 资源匮乏：Pod 可能会获得不足的资源，导致性能下降或失败。这是因为 Kubernetes 会根据这些请求来调度 Pod。如果没有它们，调度器可能会在单个节点上放置过多的 Pod，从而导致资源争用和性能瓶颈。 [...]]]></description>
			<content:encoded><![CDATA[<p><img src="https://tonybai.com/wp-content/uploads/2025/seven-kubernetes-pitfalls-1.png" alt="" /></p>
<p><a href="https://tonybai.com/2025/10/22/seven-kubernetes-pitfalls">本文永久链接</a> &#8211; https://tonybai.com/2025/10/22/seven-kubernetes-pitfalls</p>
<p>大家好，我是Tony Bai。</p>
<p>本文翻译自Kubernetes官方博客《<a href="https://kubernetes.io/blog/2025/10/20/seven-kubernetes-pitfalls-and-how-to-avoid/">7 Common Kubernetes Pitfalls (and How I Learned to Avoid Them)</a>》一文。</p>
<p>这篇文章的作者Abdelkoddous Lhajouji 以第一人称视角，系统性地梳理了从资源管理、健康检查到安全配置等多个方面，新手乃至资深工程师都极易忽视的关键点。文中的每个“陷阱”都源于真实的生产经验，其规避建议更是极具实践指导意义。无论你是 K8s 初学者还是经验丰富的 SRE，相信都能从中获得启发，审视并改善自己的日常实践。</p>
<p>以下是译文全文，供大家参考。</p>
<hr />
<p>Kubernetes 有时既强大又令人沮丧，这已经不是什么秘密了。当我刚开始涉足容器编排时，我犯的错误足以整理出一整份陷阱清单。在这篇文章中，我想详细介绍我遇到（或看到别人遇到）的七个大坑，并分享一些如何避免它们的技巧。无论你是刚开始接触 Kubernetes，还是已经在管理生产集群，我都希望这些见解能帮助你避开一些额外的压力。</p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/paid/go-network-programming-complete-guide-pr.png" alt="" /></p>
<h2>忽略资源请求（requests）和限制（limits）</h2>
<p><strong>陷阱</strong>：在 Pod 规范中不指定 CPU 和内存需求。这通常是因为 Kubernetes 并不强制要求这些字段，而且工作负载通常可以在没有它们的情况下启动和运行——这使得在早期配置或快速部署周期中很容易忽略这个疏漏。</p>
<p><strong>背景</strong>：在 Kubernetes 中，资源请求和限制对于高效的集群管理至关重要。资源请求确保调度器为每个 Pod 预留适当数量的 CPU 和内存，保证其拥有运行所需的必要资源。资源限制则为 Pod 可以使用的 CPU 和内存设置了上限，防止任何单个 Pod 消耗过多资源，从而可能导致其他 Pod 资源匮乏。当未设置资源请求和限制时：</p>
<ol>
<li><strong>资源匮乏</strong>：Pod 可能会获得不足的资源，导致性能下降或失败。这是因为 Kubernetes 会根据这些请求来调度 Pod。如果没有它们，调度器可能会在单个节点上放置过多的 Pod，从而导致资源争用和性能瓶颈。</li>
<li><strong>资源囤积</strong>：相反，如果没有限制，一个 Pod 可能会消耗超过其应有份额的资源，影响同一节点上其他 Pod 的性能和稳定性。这可能导致其他 Pod 因内存不足而被驱逐或被内存溢出（OOM）杀手终止等问题。</li>
</ol>
<h3>如何避免</h3>
<ul>
<li>从适度的 requests 开始（例如 100m CPU，128Mi 内存），然后观察你的应用表现如何。</li>
<li>监控实际使用情况并优化你的设置；<a href="https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/">HorizontalPodAutoscaler</a> 可以帮助根据指标自动进行扩缩容。</li>
<li>留意 kubectl top pods 或你的日志/监控工具，以确认你没有过度或不足地配置资源。</li>
</ul>
<p><strong>我的惨痛教训</strong>：早期，我从未考虑过内存限制。在我的本地集群上，一切似乎都很好。然后，在一个更大的环境中，Pod 们接二连三地被 OOMKilled。教训惨痛。有关为你的容器配置资源请求和限制的详细说明，请参阅官方 Kubernetes 文档的<a href="https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/">为容器和 Pod 分配内存资源</a>。</p>
<h2>低估存活探针（liveness）和就绪探针（readiness）</h2>
<p><strong>陷阱</strong>：部署容器时不明确定义 Kubernetes 应如何检查其健康或就绪状态。这往往是因为只要容器内的进程没有退出，Kubernetes 就会认为该容器处于“运行中”状态。在没有额外信号的情况下，Kubernetes 会假设工作负载正在正常运行——即使内部的应用程序没有响应、正在初始化或卡住了。</p>
<p><strong>背景</strong>：<br />
存活、就绪和启动探针是 Kubernetes 用来监控容器健康和可用性的机制。</p>
<ul>
<li><strong>存活探针</strong> 决定应用程序是否仍然存活。如果存活检查失败，容器将被重启。</li>
<li><strong>就绪探针</strong> 控制容器是否准备好为流量提供服务。在就绪探针通过之前，该容器会从 Service 的端点中移除。</li>
<li><strong>启动探针</strong> 帮助区分长时间的启动过程和实际的故障。</li>
</ul>
<h3>如何避免</h3>
<ul>
<li>添加一个简单的 HTTP livenessProbe 来检查一个健康端点（例如 /healthz），以便 Kubernetes 可以重启卡住的容器。</li>
<li>使用一个 readinessProbe 来确保流量在你的应用预热完成前不会到达它。</li>
<li>保持探针简单。过于复杂的检查可能会产生误报和不必要的重启。</li>
</ul>
<p><strong>我的惨痛教训</strong>：我曾有一次忘记为一个需要一些时间来加载的 Web 服务设置就绪探针。用户过早地访问了它，遇到了奇怪的超时，而我花了几个小时挠头苦思。一个 3 行的就绪探针本可以拯救那一天。</p>
<p>有关为容器配置存活、就绪和启动探针的全面说明，请参阅官方 Kubernetes 文档中的<a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/">配置存活、就绪和启动探针</a>。</p>
<h2>“我们就看看容器日志好了”（著名遗言）</h2>
<p><strong>陷阱</strong>：仅仅依赖通过 kubectl logs 获取的容器日志。这通常是因为该命令快速方便，并且在许多设置中，日志在开发或早期故障排查期间似乎是可访问的。然而，kubectl logs 仅检索当前运行或最近终止的容器的日志，而这些日志存储在节点的本地磁盘上。一旦容器被删除、驱逐或节点重新启动，日志文件可能会被轮替掉或永久丢失。</p>
<h3>如何避免</h3>
<ul>
<li>使用 CNCF 工具如 <a href="https://kubernetes.io/docs/concepts/cluster-administration/logging/#sidecar-container-with-a-logging-agent">Fluentd</a> 或 <a href="https://fluentbit.io/">Fluent Bit</a> 来<strong>集中化日志</strong>，聚合所有 Pod 的输出。</li>
<li><strong>采用 OpenTelemetry</strong> 以获得日志、指标和（如果需要）追踪的统一视图。这使你能够发现基础设施事件与应用级行为之间的关联。</li>
<li><strong>将日志与 Prometheus 指标配对</strong>，以跟踪集群级别的数据以及应用程序日志。如果你需要分布式追踪，可以考虑 CNCF 项目如 <a href="https://www.jaegertracing.io/">Jaeger</a>。</li>
</ul>
<p><strong>我的惨痛教训</strong>：第一次因为一次快速重启而丢失 Pod 日志时，我才意识到 kubectl logs 本身是多么不可靠。从那时起，我为每个集群都设置了一个合适的管道，以避免丢失重要线索。</p>
<h2>将开发和生产环境完全等同对待</h2>
<p><strong>陷阱</strong>：在开发、预发布和生产环境中使用完全相同的设置部署相同的 Kubernetes 清单（manifests）。这通常发生在团队追求一致性和重用时，但忽略了特定于环境的因素——如流量模式、资源可用性、扩缩容需求或访问控制——可能会有显著不同。如果不进行定制，为一个环境优化的配置可能会在另一个环境中导致不稳定、性能不佳或安全漏洞。</p>
<h3>如何避免</h3>
<ul>
<li>使用overlays环境 或 <a href="https://kustomize.io/">kustomize</a> 来维护一个共享的基础配置，同时为每个环境定制资源请求、副本数或配置。</li>
<li>将特定于环境的配置提取到 ConfigMaps 和/或 Secrets 中。你可以使用专门的工具，如 <a href="https://github.com/bitnami-labs/sealed-secrets">Sealed Secrets</a> 来管理机密数据。</li>
<li>为生产环境的规模做好规划。你的开发集群可能用最少的 CPU/内存就能应付，但生产环境可能需要多得多。</li>
</ul>
<p><strong>我的惨痛教训</strong>：有一次，我为了“测试”，在一个小小的开发环境中将 replicaCount 从 2 扩展到 10。我立刻耗尽了资源，并花了半天时间清理残局。哎。</p>
<h2>让旧东西到处漂浮</h2>
<p><strong>陷阱</strong>：让未使用的或过时的资源——如 Deployments、Services、ConfigMaps 或 PersistentVolumeClaims——在集群中持续运行。这通常是因为 Kubernetes 不会自动移除资源，除非得到明确指示，而且没有内置机制来跟踪所有权或过期时间。随着时间的推移，这些被遗忘的对象会累积起来，消耗集群资源，增加云成本，并造成操作上的混乱，尤其是当过时的 Services 或 LoadBalancers 仍在继续路由流量时。</p>
<h3>如何避免</h3>
<ul>
<li>为<strong>所有东西打上标签</strong>，附上用途或所有者标签。这样，你就可以轻松查询不再需要的资源。</li>
<li><strong>定期审计</strong>你的集群：运行 kubectl get all -n <namespace> 来查看实际在运行什么，并确认它们都是合法的。</li>
<li><strong>采用 Kubernetes 的垃圾回收</strong>：<a href="https://kubernetes.io/docs/concepts/workloads/controllers/garbage-collection/">K8s 文档</a>展示了如何自动移除依赖对象。</li>
<li><strong>利用策略自动化</strong>：像 <a href="https://kyverno.io/">Kyverno</a> 这样的工具可以在一定时期后自动删除或阻止过时的资源，或强制执行生命周期策略，这样你就不必记住每一个清理步骤。</li>
</ul>
<p><strong>我的惨痛教训</strong>：一次hackathon之后，我忘记拆除一个关联到外部负载均衡器的“test-svc”。三周后，我才意识到我一直在为那个负载均衡器付费。捂脸。</p>
<h2>过早地深入研究网络</h2>
<p><strong>陷阱</strong>：在完全理解 Kubernetes 的原生网络原语之前，就引入了高级的网络解决方案——如服务网格（service meshes）、自定义 CNI 插件或多集群通信。这通常发生在团队使用外部工具实现流量路由、可观测性或 mTLS 等功能，而没有首先掌握核心 Kubernetes 网络的工作原理时：包括 Pod 到 Pod 的通信、ClusterIP Services、DNS 解析和基本的 ingress 流量处理。结果，与网络相关的问题变得更难排查，尤其是当overlays网络引入了额外的抽象和故障点时。</p>
<h3>如何避免</h3>
<ul>
<li>从小处着手：一个 Deployment、一个 Service 和一个基本的 ingress 控制器，例如基于 NGINX 的控制器（如 Ingress-NGINX）。</li>
<li>确保你理解集群内的流量如何流动、服务发现如何工作以及 DNS 是如何配置的。</li>
<li>只有在你真正需要时，才转向功能完备的网格或高级 CNI 功能，复杂的网络会增加开销。</li>
</ul>
<p><strong>我的惨痛教训</strong>：我曾在一个小型的内部应用上尝试过 Istio，结果花在调试 Istio 本身的时间比调试实际应用还多。最终，我退后一步，移除了 Istio，一切都正常工作了。</p>
<h2>对安全和 RBAC 太掉以轻心</h2>
<p><strong>陷阱</strong>：使用不安全的配置部署工作负载，例如以 root 用户身份运行容器、使用 latest 镜像标签、禁用安全上下文（security contexts），或分配过于宽泛的 RBAC 角色（如 cluster-admin）。这些做法之所以持续存在，是因为 Kubernetes 开箱即用时并不强制执行严格的安全默认设置，而且该平台的设计初衷是灵活而非固执己见。在没有明确的安全策略的情况下，集群可能会持续暴露于容器逃逸、未经授权的权限提升或因未固定的镜像导致的意外生产变更等风险中。</p>
<h3>如何避免</h3>
<ul>
<li>使用 <a href="https://kubernetes.io/docs/reference/access-authn-authz/rbac/">RBAC</a> 来定义 Kubernetes 内部的角色和权限。虽然 RBAC 是默认且最广泛支持的授权机制，但 Kubernetes 也允许使用替代的授权方。对于更高级或外部的策略需求，可以考虑像 <a href="https://open-policy-agent.github.io/gatekeeper/">OPA Gatekeeper</a>（基于 Rego）、<a href="https://kyverno.io/">Kyverno</a> 或使用 CEL 或 <a href="https://cedarpolicy.com/">Cedar</a> 等策略语言的自定义 webhook 等解决方案。</li>
<li>将镜像固定到特定的版本（不要再用 :latest！）。这能帮助你确切地知道实际部署的是什么。</li>
<li>研究一下 <a href="https://kubernetes.io/docs/concepts/security/pod-security-admission/">Pod 安全准入</a>（或其他解决方案，如 Kyverno），以强制执行非 root 容器、只读文件系统等。</li>
</ul>
<p><strong>我的惨痛教训</strong>：我从未遇到过重大的安全漏洞，但我听过足够多的警示故事。如果你不把事情收紧，出问题只是时间问题。</p>
<h2>小结：最后的想法</h2>
<p>Kubernetes 很神奇，但它不会读心术，如果你不告诉它你需要什么，它不会神奇地做出正确的事。通过牢记这些陷阱，你将避免大量的头痛和时间浪费。错误会发生（相信我，我犯过不少），但每一次都是一个机会，让你更深入地了解 Kubernetes 在底层是如何真正工作的。如果你有兴趣深入研究，<a href="https://kubernetes.io/docs/home/">官方文档</a>和<a href="http://slack.kubernetes.io/">社区 Slack</a> 是绝佳的下一步。当然，也欢迎分享你自己的恐怖故事或成功技巧，因为归根结底，我们都在这场云原生的冒险中并肩作战。</p>
<p><strong>祝你交付愉快！</strong></p>
<hr />
<p>你的Go技能，是否也卡在了“熟练”到“精通”的瓶颈期？</p>
<ul>
<li>想写出更地道、更健壮的Go代码，却总在细节上踩坑？</li>
<li>渴望提升软件设计能力，驾驭复杂Go项目却缺乏章法？</li>
<li>想打造生产级的Go服务，却在工程化实践中屡屡受挫？</li>
</ul>
<p>继《<a href="http://gk.link/a/10AVZ">Go语言第一课</a>》后，我的《<a href="http://gk.link/a/12yGY">Go语言进阶课</a>》终于在极客时间与大家见面了！</p>
<p>我的全新极客时间专栏 《<a href="http://gk.link/a/12yGY">Tony Bai·Go语言进阶课</a>》就是为这样的你量身打造！30+讲硬核内容，带你夯实语法认知，提升设计思维，锻造工程实践能力，更有实战项目串讲。</p>
<p>目标只有一个：助你完成从“Go熟练工”到“Go专家”的蜕变！ 现在就加入，让你的Go技能再上一个新台阶！</p>
<p><img src="https://tonybai.com/wp-content/uploads/course-card/iamtonybai-banner-2.gif" alt="" /></p>
<hr />
<p><strong>想系统学习Go，构建扎实的知识体系？</strong></p>
<p>我的新书《<a href="https://book.douban.com/subject/37499496/">Go语言第一课</a>》是你的首选。源自2.4万人好评的极客时间专栏，内容全面升级，同步至Go 1.24。首发期有专属五折优惠，不到40元即可入手，扫码即可拥有这本300页的Go语言入门宝典，即刻开启你的Go语言高效学习之旅！</p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/go-primer-published-4.png" alt="" /></p>
<hr />
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求，请扫描下方公众号二维码，与我私信联系。</p>
<p><img src="http://image.tonybai.com/img/tonybai/iamtonybai-wechat-qr.png" alt="" /></p>
<p style='text-align:left'>&copy; 2025, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2025/10/22/seven-kubernetes-pitfalls/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Go应用的K8s“最佳拍档”：何时以及如何用好多容器Pod模式</title>
		<link>https://tonybai.com/2025/04/24/multiple-containers-pod-pattern/</link>
		<comments>https://tonybai.com/2025/04/24/multiple-containers-pod-pattern/#comments</comments>
		<pubDate>Thu, 24 Apr 2025 00:19:56 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[Adapter]]></category>
		<category><![CDATA[Ambassador]]></category>
		<category><![CDATA[container]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[envoy]]></category>
		<category><![CDATA[Fluentd]]></category>
		<category><![CDATA[GA]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Golang]]></category>
		<category><![CDATA[gRPC]]></category>
		<category><![CDATA[helper]]></category>
		<category><![CDATA[init-container]]></category>
		<category><![CDATA[istio]]></category>
		<category><![CDATA[job]]></category>
		<category><![CDATA[k8s]]></category>
		<category><![CDATA[Kubernetes]]></category>
		<category><![CDATA[linkerd]]></category>
		<category><![CDATA[Otel]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[restartPolicy]]></category>
		<category><![CDATA[sidecar]]></category>
		<category><![CDATA[云原生]]></category>
		<category><![CDATA[容器]]></category>
		<category><![CDATA[指标]]></category>
		<category><![CDATA[数据库]]></category>
		<category><![CDATA[日志]]></category>
		<category><![CDATA[服务网格]]></category>
		<category><![CDATA[模式]]></category>
		<category><![CDATA[配置]]></category>

		<guid isPermaLink="false">https://tonybai.com/?p=4610</guid>
		<description><![CDATA[本文永久链接 &#8211; https://tonybai.com/2025/04/24/multiple-containers-pod-pattern 大家好，我是Tony Bai。 将Go应用部署到Kubernetes已经是许多团队的标配。在这个强大的容器编排平台上，除了运行我们的核心Go服务容器，Kubernetes还提供了一种灵活的设计模式——多容器Pod。通过在同一个Pod内运行多个容器，我们可以实现诸如初始化、功能扩展、适配转换等多种辅助功能，其中最知名的就是Sidecar模式。 这些“辅助容器”就像我们Go应用的“最佳拍档”，在某些场景下能发挥奇效。然而，正如 Kubernetes官方文档和社区讨论一直强调的那样，引入额外的容器并非没有成本。每一个额外的容器都会增加复杂度、资源消耗和潜在的运维开销。 因此，关键在于策略性地使用这些模式。我们不应将其视为默认选项，而应是解决特定架构挑战的精密工具。今天，我们就来聊聊Kubernetes中几种合理且常用的多容器Pod模式，探讨何时应该为我们的Go应用引入这些“拍档”，以及如何更好地利用Kubernetes v1.33中已正式稳定（GA）的原生Sidecar支持来实现它们。 图K8s v1.33发布 首先：警惕复杂性！优先考虑更简单的替代方案 在深入探讨具体模式之前，务必牢记一个核心原则：非必要，勿增实体。 对于Go这种拥有强大标准库和丰富生态的语言来说，许多常见的横切关注点（如日志记录、指标收集、配置加载、基本的HTTP客户端逻辑等）往往可以通过引入高质量的Go库在应用内部更轻量、更高效地解决。 只有当以下情况出现时，才应认真考虑引入多容器模式： 需要扩展或修改无法触碰源代码的应用（如第三方应用或遗留系统）。 需要将与语言无关的通用功能（如网络代理、安全策略）从主应用中解耦出来。 需要独立于主应用进行更新或扩展的辅助功能。 特定的初始化或适配需求无法在应用内部优雅处理。 切忌为了“看起来很酷”或“遵循某种时髦架构”而盲目添加容器。 下面我们看看常见的一些多容器模式以及对应的应用场景。 四种推荐的多容器模式及其Go应用场景 Kubernetes生态中已经沉淀出了几种非常实用且目标明确的多容器模式，我们逐一来看一下。 Init Container (初始化容器) Init Container是K8s最早支持的一种“sidecar”(那时候还不这么叫)，它一般用在主应用容器启动之前，执行一次性的关键设置任务。它会运行至完成然后终止。 它常用于以下场景： 运行数据库Schema迁移。 预加载配置或密钥。 检查依赖服务就绪。 准备共享数据卷。 下面是官方的一个init containers的示例： apiVersion: v1 kind: Pod metadata: name: myapp-pod labels: app.kubernetes.io/name: MyApp spec: containers: - name: myapp-container image: busybox:1.28 command: ['sh', [...]]]></description>
			<content:encoded><![CDATA[<p><img src="https://tonybai.com/wp-content/uploads/2025/multiple-containers-pod-pattern-1.jpg" alt="" /></p>
<p><a href="https://tonybai.com/2025/04/24/multiple-containers-pod-pattern">本文永久链接</a> &#8211; https://tonybai.com/2025/04/24/multiple-containers-pod-pattern</p>
<p>大家好，我是Tony Bai。</p>
<p>将Go应用部署到Kubernetes已经是许多团队的标配。在这个强大的容器编排平台上，除了运行我们的核心Go服务容器，Kubernetes还提供了一种灵活的设计模式——<strong>多容器Pod</strong>。通过在同一个Pod内运行多个容器，我们可以实现诸如初始化、功能扩展、适配转换等多种辅助功能，其中最知名的就是<strong>Sidecar</strong>模式。</p>
<p>这些“辅助容器”就像我们Go应用的“最佳拍档”，在某些场景下能发挥奇效。然而，正如 Kubernetes官方文档和社区讨论一直强调的那样，<strong>引入额外的容器并非没有成本</strong>。每一个额外的容器都会增加复杂度、资源消耗和潜在的运维开销。</p>
<p>因此，关键在于策略性地使用这些模式。我们不应将其视为默认选项，而应是解决特定架构挑战的精密工具。今天，我们就来聊聊Kubernetes中几种合理且常用的多容器Pod模式，探讨何时应该为我们的Go应用引入这些“拍档”，以及如何更好地利用Kubernetes v1.33中已正式稳定（GA）的原生Sidecar支持来实现它们。</p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/multiple-containers-pod-pattern-2.jpg" alt="" /><br />
<center>图K8s v1.33发布</center></p>
<h2>首先：警惕复杂性！优先考虑更简单的替代方案</h2>
<p>在深入探讨具体模式之前，务必牢记一个核心原则：<strong>非必要，勿增实体</strong>。</p>
<p>对于Go这种拥有强大标准库和丰富生态的语言来说，许多常见的横切关注点（如日志记录、指标收集、配置加载、基本的HTTP客户端逻辑等）往往可以通过引入高质量的Go库在应用内部更轻量、更高效地解决。</p>
<p>只有当以下情况出现时，才应认真考虑引入多容器模式：</p>
<ul>
<li>需要扩展或修改无法触碰源代码的应用（如第三方应用或遗留系统）。</li>
<li>需要将与语言无关的通用功能（如网络代理、安全策略）从主应用中解耦出来。</li>
<li>需要独立于主应用进行更新或扩展的辅助功能。</li>
<li>特定的初始化或适配需求无法在应用内部优雅处理。</li>
</ul>
<p>切忌为了“看起来很酷”或“遵循某种时髦架构”而盲目添加容器。</p>
<p>下面我们看看常见的一些多容器模式以及对应的应用场景。</p>
<h2>四种推荐的多容器模式及其Go应用场景</h2>
<p>Kubernetes生态中已经沉淀出了几种非常实用且目标明确的多容器模式，我们逐一来看一下。</p>
<h3>Init Container (初始化容器)</h3>
<p>Init Container是K8s最早支持的一种“sidecar”(那时候还不这么叫)，它一般用在主应用容器启动之前，执行一次性的关键设置任务。它会运行至完成然后终止。</p>
<p>它常用于以下场景：</p>
<ul>
<li>运行数据库Schema迁移。</li>
<li>预加载配置或密钥。</li>
<li>检查依赖服务就绪。</li>
<li>准备共享数据卷。</li>
</ul>
<p>下面是官方的一个init containers的示例：</p>
<pre><code>apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app.kubernetes.io/name: MyApp
spec:
  containers:
  - name: myapp-container
    image: busybox:1.28
    command: ['sh', '-c', 'echo The app is running! &amp;&amp; sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
  - name: init-mydb
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]
</code></pre>
<p>此示例定义了一个包含两个init容器的简单Pod。第一个init容器(init-myservice)等待myservice运行，第二个init容器(init-mydb)等待mydb运行。两个init容器完成后，Pod将从其spec部分运行app容器(myapp-container)。</p>
<h3>Ambassador (大使容器)</h3>
<p>Ambassador Container主要是用于扮演主应用容器的“网络大使”，简化其与外部服务的交互，它常用在下面一些场景里：</p>
<ul>
<li>服务发现与负载均衡代理。</li>
<li>请求重试与熔断。</li>
<li>身份验证与授权代理。</li>
<li>mTLS 加密通信。</li>
</ul>
<p>Ambassador通常作为Pod内的一个长期运行的容器。如果需要确保它在主应用之后停止（例如处理完最后的请求转发），Kubernetes原生Sidecar是实现Ambassador容器的理想选择。</p>
<h3>Configuration Helper (配置助手)</h3>
<p>配置助手也是一种最常使用的辅助容器模式，它主要用于动态地为正在运行的主应用提供或更新配置，比如监控ConfigMap/Secret变化并热加载、从配置中心拉取配置等。</p>
<p>它通常也是一个长期运行的容器。由于可能需要在主应用启动前提供初始配置，并在主应用停止后同步最后状态，使用原生Sidecar提供的精确生命周期管理非常有价值，可以使用Sidecar实现这种模式的容器。</p>
<h3>Adapter (适配器容器)</h3>
<p>Adapter容器负责在主应用和外部世界之间进行数据格式、协议或API的转换，常用于下面一些场景：</p>
<ul>
<li>统一监控指标格式。</li>
<li>协议转换（如 gRPC 转 REST）。</li>
<li>标准化日志输出。</li>
<li>兼容遗留系统接口。</li>
</ul>
<p>我们可以根据是否需要精确的生命周期协调来选择普通容器或原生Sidecar来实现这类长期运行的适配器容器。</p>
<p>可见，K8s原生的Sidecar是实现上述四种辅助容器的可靠实现，下面来简单介绍一下K8s原生Sidecar。</p>
<h2>K8s原生Sidecar：可靠实现辅助容器的关键</h2>
<p>现在，我们重点关注Kubernetes v1.33中正式稳定（GA）的原生Sidecar 功能。</p>
<p><strong>它是如何实现的呢？</strong></p>
<p>官方推荐的方式是：在Pod的spec.initContainers数组中定义你的Sidecar容器，并显式地将其restartPolicy设置为Always。下面是一个示例：</p>
<pre><code>spec:
  initContainers:
    - name: my-sidecar # 例如日志收集或网络代理
      image: my-sidecar-image:latest
      restartPolicy: Always # &lt;--- 关键：标记为原生Sidecar
      # ... 其他配置 ...
  containers:
    - name: my-go-app
      image: my-golang-app:latest
      # ...
</code></pre>
<p>虽然将长期运行的容器放在initContainers里初看起来可能有些“反直觉”，但这正是Kubernetes团队为了复用Init Container已有的启动顺序保证，并赋予其特殊生命周期管理能力而精心设计的稳定机制。</p>
<p><strong>原生Sidecar具有如下的核心优势：</strong></p>
<ul>
<li>可靠的启动行为： 所有非Sidecar的 Init Containers (restartPolicy 不是 Always) 会按顺序执行且必须成功完成。随后，主应用容器 (spec.containers) 和所有原生 Sidecar 并发启动。</li>
<li>优雅的关闭顺序保证：这是最大的改进！当 Pod 终止时，主应用容器先收到SIGTERM 并等待其完全停止（或超时），然后Sidecar容器才会收到 SIGTERM 开始关闭。</li>
<li>与Job 的良好协作： 对于设置了 restartPolicy: OnFailure或Never的Job，原生Sidecar不会因为自身持续运行而阻止Job的成功完成。</li>
</ul>
<p><strong>这对我们的Go应用意味着什么？</strong></p>
<p>当你的Go应用确实需要一个长期运行的辅助容器，并且<strong>需要精确的生命周期协调</strong>时，原生Sidecar提供了实实在在的好处：</p>
<ul>
<li>服务网格代理 (Ambassador 变种): Envoy, Linkerd proxy 等可以确保在 Go 应用处理完最后请求后才关闭，极大提升可靠性。</li>
<li>日志/监控收集 (Adapter/Helper 变种): Fluentd, Vector, OTel Collector 等可以确保捕获到 Go 应用停止前的最后状态信息。</li>
<li>需要与主应用生命周期紧密配合的其他辅助服务: 任何需要在主应用运行期间持续提供服务，并在主应用结束后才停止的场景。</li>
</ul>
<p>因此，原生Sidecar不是一个全新的模式，而是当我们需要实现上述这些需要精确生命周期管理的Sidecar模式时，Kubernetes v1.33 提供的稳定、可靠且官方推荐的实现方式。</p>
<h2>小结</h2>
<p>Kubernetes的多容器Pod模式为我们提供了强大的工具箱，但也伴随着额外的复杂性。对于Go开发者而言：</p>
<ul>
<li><strong>始终将简单性放在首位：</strong> 优先考虑使用 Go 语言自身的库和能力来解决问题。</li>
<li><strong>审慎评估必要性：</strong> 只有当明确的应用场景（如 Init, Ambassador, Config Helper, Adapter）带来的好处大于其引入的复杂度和资源开销时，才考虑使用多容器模式。</li>
<li><strong>理解模式目的：</strong> 清晰地知道你引入的每个辅助容器是为了解决什么特定问题。</li>
<li><strong>拥抱原生 Sidecar (GA):</strong> 当你确定需要一个长期运行且需要可靠生命周期管理的辅助容器时，<strong>利用 Kubernetes v1.33 及以后版本中稳定提供的原生 Sidecar 支持</strong>，是提升部署健壮性的最佳实践。</li>
</ul>
<p>多容器 Pod 是 Kubernetes 生态中的“精密武器”，理解何时拔剑、如何出鞘，并善用平台提供的稳定特性，才能真正发挥其威力，为我们的 Go 应用保驾护航。</p>
<p><strong>你通常在什么场景下为你的 Go 应用添加辅助容器？你对 K8s 原生 Sidecar 功能的稳定有何看法？欢迎在评论区分享你的实践经验和见解！</strong> 如果觉得这篇文章对你有启发，也请不吝点个【赞】和【在看】！</p>
<h2>参考资料</h2>
<ul>
<li><a href="https://kubernetes.io/docs/concepts/workloads/pods/init-containers/">Init Containers</a> &#8211; https://kubernetes.io/docs/concepts/workloads/pods/init-containers/</li>
<li><a href="https://kubernetes.io/docs/tutorials/configuration/pod-sidecar-containers/">Pod Sidecar Containers</a> &#8211; https://kubernetes.io/docs/tutorials/configuration/pod-sidecar-containers/</li>
<li><a href="https://kubernetes.io/docs/concepts/workloads/pods/sidecar-containers">Sidecar Containers</a> &#8211; https://kubernetes.io/docs/concepts/workloads/pods/sidecar-containers/</li>
<li><a href="https://kubernetes.io/blog/2025/04/23/kubernetes-v1-33-release">Kubernetes v1.33: Octarine</a> &#8211; https://kubernetes.io/blog/2025/04/23/kubernetes-v1-33-release/</li>
<li><a href="https://github.com/kubernetes/enhancements/issues/753">Sidecar Containers</a> &#8211; https://github.com/kubernetes/enhancements/issues/753</li>
</ul>
<hr />
<p><strong>拓展阅读与实践：抓住 K8s 学习与星球优惠的最后机会！</strong></p>
<p>聊完K8s的多容器Pod模式，想不想更系统地掌握K8s核心原理与实践？</p>
<p>我正打算将多年前深受好评的<strong>慕课网Kubernetes实战课</strong>(https://coding.imooc.com/class/284.html)内容（覆盖集群探索、网络、安全、存储、诊断、Operator等核心知识点）进行精选和更新，并逐步放入我的知识星球<strong>「Go &amp; AI 精进营」</strong> 的<strong>【Kubernetes进阶】</strong> 专栏。这对于理解K8s底层、打好云原生基础价值依旧。</p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/multiple-containers-pod-pattern-3.png" alt="" /><br />
<center>当初的课程核心内容(后会有调整)</center></p>
<p><strong>特别提醒：</strong> 「Go &amp; AI 精进营」将于<strong>5月1日起涨价至 388 元/年</strong>！现在是<strong>涨价前的最后一周</strong>，以当前价格加入，即可锁定未来一年的高质量Go 进阶、AI 应用实战以及这个即将更新的 K8s 实战专栏！</p>
<p>如果你想深入K8s原理，并抓住星球涨价前的<strong>最后优惠窗口</strong>，现在就加入我们吧！</p>
<p><img src="http://image.tonybai.com/img/tonybai/gopher-and-ai-tribe-zsxq-small-card.jpg" alt="img{512x368}" /></p>
<hr />
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求，请扫描下方公众号二维码，与我私信联系。</p>
<p><img src="http://image.tonybai.com/img/tonybai/iamtonybai-wechat-qr.png" alt="" /></p>
<p style='text-align:left'>&copy; 2025, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2025/04/24/multiple-containers-pod-pattern/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>都2024年了，当初那个“Go，互联网时代的C语言”的预言成真了吗？</title>
		<link>https://tonybai.com/2024/08/17/go-the-c-language-of-the-internet-era-come-true/</link>
		<comments>https://tonybai.com/2024/08/17/go-the-c-language-of-the-internet-era-come-true/#comments</comments>
		<pubDate>Fri, 16 Aug 2024 22:17:02 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[caddy]]></category>
		<category><![CDATA[calico]]></category>
		<category><![CDATA[cilium]]></category>
		<category><![CDATA[cloudnative]]></category>
		<category><![CDATA[cockroachdb]]></category>
		<category><![CDATA[consul]]></category>
		<category><![CDATA[container]]></category>
		<category><![CDATA[containerd]]></category>
		<category><![CDATA[CoreDNS]]></category>
		<category><![CDATA[cortex]]></category>
		<category><![CDATA[dagger]]></category>
		<category><![CDATA[Dgraph]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[dragonfly]]></category>
		<category><![CDATA[etcd]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[gohugo]]></category>
		<category><![CDATA[Golang]]></category>
		<category><![CDATA[goplus]]></category>
		<category><![CDATA[harbor]]></category>
		<category><![CDATA[InfluxDB]]></category>
		<category><![CDATA[istio]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[juicefs]]></category>
		<category><![CDATA[junodb]]></category>
		<category><![CDATA[k8s]]></category>
		<category><![CDATA[Kubernetes]]></category>
		<category><![CDATA[linkerd2]]></category>
		<category><![CDATA[longhorn]]></category>
		<category><![CDATA[mattermost]]></category>
		<category><![CDATA[Milvus]]></category>
		<category><![CDATA[minio]]></category>
		<category><![CDATA[nats]]></category>
		<category><![CDATA[nsq]]></category>
		<category><![CDATA[ollama]]></category>
		<category><![CDATA[opentelemetry]]></category>
		<category><![CDATA[opentofu]]></category>
		<category><![CDATA[Otel]]></category>
		<category><![CDATA[podman]]></category>
		<category><![CDATA[prometheus]]></category>
		<category><![CDATA[rook]]></category>
		<category><![CDATA[terraform]]></category>
		<category><![CDATA[TIOBE]]></category>
		<category><![CDATA[traefik]]></category>
		<category><![CDATA[VictoriaMetrics]]></category>
		<category><![CDATA[vitess]]></category>
		<category><![CDATA[七牛云]]></category>
		<category><![CDATA[中间件]]></category>
		<category><![CDATA[云原生]]></category>
		<category><![CDATA[容器]]></category>
		<category><![CDATA[操作系统]]></category>
		<category><![CDATA[系统编程语言]]></category>
		<category><![CDATA[驱动]]></category>

		<guid isPermaLink="false">https://tonybai.com/?p=4248</guid>
		<description><![CDATA[本文永久链接 &#8211; https://tonybai.com/2024/08/17/go-the-c-language-of-the-internet-era-come-true 本文最初发表于我个人的微信公众号(iamtonybai)，但鉴于图片消息的篇幅受限(&#60;=1000字)，一些内容没能如愿展开，这里在博客上重新发布一下，也顺道丰富一下文章的内容。 2012年，七牛云创始人、goplus语言之父许式伟在一次演讲中给出一个大胆的预言：“Go，互联网时代的C语言”。 十余年过去了，我们不禁要问：当初的那个预言是否已经成真？ 在讨论这个预言之前，我们先来看在同一份演讲稿中，老许给出的另外三个预判： 它们是： Java语言份额继续下滑，最终被C和Go语言超越； C语言将长居编程榜第二的位置，有望在Go取代Java前重获第一的宝座； Go语言最终会取代Java位居编程榜榜首。 编程语言排行榜有很多，我们就以名气最大的TIOBE刚刚发布的2024年8月排行榜为例，看看这些预判是否成真。 很遗憾，一个也没命中。 在这份最新榜单中，C位列第三、Java位列第四，Go位列第九，相对于前两个月的第七还下降了两位。不过不得不说，老许对C语言的预判还是相对准确的。 那这是否意味着老许最初的那个预言也Miss了呢？个人觉得：并没有。因为这要看从哪个角度来审视。 传统观点认为，C语言被视为系统编程语言的杰出代表，因其卓越的底层操作能力和极致性能而广受推崇。它允许开发者直接与硬件交互，提供了高效的资源管理和快速的执行速度。如果从这样的视角去看待那则预言，那显然Go与“互联网时代C语言”这个评价和地位是不相称的。虽然Go最初的定位也是一门系统编程语言。 但如果我们跳出以“低级操作和性能”为中心的比较框架，而是从不同时代软件技术栈的层次与构建来看，Go与C语言的地位又极其的相似。 在互联网时代到来之前，C语言已经是整个软件技术栈的基石：从操作系统内核、设备驱动程序、中间件到应用程序，C语言凭借卓越的性能、无以伦比的生态，在技术栈的各个层次都有着广泛且核心的应用。 当时针指向云原生时代时，Go语言在云原生技术栈的构建中，发挥了与C语言相似的作用： 云原生“操作系统”：Kubernetes； 云原生“驱动程序”：容器运行时（docker、containerd、podman）、网络插件(Calico、cilium、CoreDNS等)、存储插件（Rook、longhorn等）； 云原生“中间件”：数据库(CockroachDB、Vitess、InfluxDB(2.x)、VictoriaMetrics、Dgraph、milvus等)、消息队列(NATS、nsq等)、服务网格(Istio、linkerd2)、API网关/代理(Traefik、emissary等)、镜像仓库/加速器(harbor、Dragonfly)、key-value存储(Etcd、consul、junodb)、安全相关(falco、OPA、vault)、可观测组件(OpenTelemetry、Prometheus、Thanos、Cortex等)、基础设施管理(terraform、dagger)、分布式存储(minio、SeaweedFS、juicefs)、AI大模型运维(ollama)。 应用层：Caddy、gohugo、mattermost等。 我们用一张示意图来横向对比一下： 听我讲到这里，你是不是觉得老许的那个预言好像命中了呢！ 当然，从狭义的角度来看，Go与C还有一些地方是很像的，比如：语法简单、跨平台可移植性好等。并且两者还“沾亲带故”：Unix之父Ken Thompson当年和Dennis Ritchie一起发明了C语言，又和Rob Pike等一起设计了Go语言！ 最后，回顾许式伟2012年的预言，我们不得不惊叹于其洞察力。Go语言确实在很大程度上成为了”互联网时代的C语言”，但不是通过传统的性能优势，而是通过重新构建了云原生技术栈，从这个角度看，Go语言也不失为云原生时代的”系统语言” —— 它不仅能够优雅地处理分布式系统的复杂性，它还使得构建和维护大规模、高可靠性的分布式系统变得更为简单，是云原生时代的思维方式和解决方案的集大成者，某种程度上还可以说定义了云原生时代的软件开发范式。 Gopher部落知识星球在2024年将继续致力于打造一个高品质的Go语言学习和交流平台。我们将继续提供优质的Go技术文章首发和阅读体验。同时，我们也会加强代码质量和最佳实践的分享，包括如何编写简洁、可读、可测试的Go代码。此外，我们还会加强星友之间的交流和互动。欢迎大家踊跃提问，分享心得，讨论技术。我会在第一时间进行解答和交流。我衷心希望Gopher部落可以成为大家学习、进步、交流的港湾。让我相聚在Gopher部落，享受coding的快乐! 欢迎大家踊跃加入！ 著名云主机服务厂商DigitalOcean发布最新的主机计划，入门级Droplet配置升级为：1 core CPU、1G内存、25G高速SSD，价格5$/月。有使用DigitalOcean需求的朋友，可以打开这个链接地址：https://m.do.co/c/bff6eed92687 开启你的DO主机之路。 Gopher Daily(Gopher每日新闻) &#8211; https://gopherdaily.tonybai.com 我的联系方式： 微博(暂不可用)：https://weibo.com/bigwhite20xx 微博2：https://weibo.com/u/6484441286 博客：tonybai.com github: https://github.com/bigwhite Gopher Daily归档 &#8211; https://github.com/bigwhite/gopherdaily Gopher Daily Feed订阅 [...]]]></description>
			<content:encoded><![CDATA[<p><img src="https://tonybai.com/wp-content/uploads/go-the-c-language-of-the-internet-era-come-true-1.png" alt="" /></p>
<p><a href="https://tonybai.com/2024/08/17/go-the-c-language-of-the-internet-era-come-true">本文永久链接</a> &#8211; https://tonybai.com/2024/08/17/go-the-c-language-of-the-internet-era-come-true</p>
<p><a href="https://mp.weixin.qq.com/s/GTXSNoPTmJ-mprMKAY8esw">本文最初发表于我个人的微信公众号(iamtonybai)</a>，但鉴于图片消息的篇幅受限(&lt;=1000字)，一些内容没能如愿展开，这里在博客上重新发布一下，也顺道丰富一下文章的内容。</p>
<hr />
<p>2012年，<a href="https://www.qiniu.com/">七牛云</a>创始人、<a href="https://github.com/goplus/gop">goplus语言</a>之父<a href="https://github.com/xushiwei">许式伟</a>在一次演讲中给出一个大胆的预言：“<strong>Go，互联网时代的C语言</strong>”。</p>
<p><img src="https://tonybai.com/wp-content/uploads/go-the-c-language-of-the-internet-era-come-true-2.png" alt="" /></p>
<p>十余年过去了，我们不禁要问：当初的那个预言是否已经成真？</p>
<p>在讨论这个预言之前，我们先来看在同一份演讲稿中，老许给出的另外三个预判：</p>
<p><img src="https://tonybai.com/wp-content/uploads/go-the-c-language-of-the-internet-era-come-true-3.png" alt="" /></p>
<p>它们是：</p>
<ul>
<li>Java语言份额继续下滑，最终被C和Go语言超越；</li>
<li>C语言将长居编程榜第二的位置，有望在Go取代Java前重获第一的宝座；</li>
<li>Go语言最终会取代Java位居编程榜榜首。</li>
</ul>
<p>编程语言排行榜有很多，我们就以名气最大的<a href="https://www.tiobe.com/tiobe-index/">TIOBE</a>刚刚发布的2024年8月排行榜为例，看看这些预判是否成真。</p>
<p><img src="https://tonybai.com/wp-content/uploads/go-the-c-language-of-the-internet-era-come-true-4.png" alt="" /></p>
<p>很遗憾，<strong>一个也没命中</strong>。</p>
<p>在这份最新榜单中，C位列第三、Java位列第四，Go位列第九，<a href="https://mp.weixin.qq.com/s?__biz=MzIyNzM0MDk0Mg==&amp;mid=2247497403&amp;idx=1&amp;sn=03bc972e38163e1539da765249d46586&amp;chksm=e860115adf17984cfe47f9680d8c0fb6370987ad45415ff2d38233d05fe6b315210ce6ada385#rd">相对于前两个月的第七</a>还下降了两位。不过不得不说，老许对C语言的预判还是相对准确的。</p>
<p>那这是否意味着老许最初的那个预言也Miss了呢？个人觉得：<strong>并没有</strong>。因为这要看从哪个角度来审视。</p>
<p>传统观点认为，C语言被视为系统编程语言的杰出代表，因其卓越的底层操作能力和极致性能而广受推崇。它允许开发者直接与硬件交互，提供了高效的资源管理和快速的执行速度。如果从这样的视角去看待那则预言，那显然Go与“互联网时代C语言”这个评价和地位是不相称的。虽然<a href="https://go.dev/talks/2012/splash.article">Go最初的定位也是一门系统编程语言</a>。</p>
<p>但如果我们跳出以“低级操作和性能”为中心的比较框架，而是<strong>从不同时代软件技术栈的层次与构建来看，Go与C语言的地位又极其的相似</strong>。</p>
<p>在互联网时代到来之前，C语言已经是整个软件技术栈的基石：从操作系统内核、设备驱动程序、中间件到应用程序，C语言凭借卓越的性能、无以伦比的生态，在技术栈的各个层次都有着广泛且核心的应用。</p>
<p>当时针指向云原生时代时，<strong>Go语言在云原生技术栈的构建中，发挥了与C语言相似的作用</strong>：</p>
<ul>
<li>云原生“操作系统”：<a href="https://mp.weixin.qq.com/s/paOduv0t1CtBCUoUBfJ7rQ">Kubernetes</a>；</li>
<li>云原生“驱动程序”：容器运行时（<a href="https://tonybai.com/tag/docker">docker</a>、<a href="https://github.com/containerd/containerd">containerd</a>、<a href="https://github.com/containers/podman">podman</a>）、网络插件(<a href="https://github.com/projectcalico/calico">Calico</a>、<a href="https://github.com/cilium/cilium">cilium</a>、<a href="https://github.com/coredns/coredns">CoreDNS</a>等)、存储插件（<a href="https://github.com/rook/rook">Rook</a>、<a href="https://github.com/longhorn/longhorn?tab=readme-ov-file">longhorn</a>等）；</li>
<li>云原生“中间件”：数据库(<a href="https://github.com/cockroachdb/cockroach">CockroachDB</a>、<a href="https://github.com/vitessio/vitess">Vitess</a>、<a href="https://github.com/influxdata/influxdb/tree/main-2.x">InfluxDB(2.x)</a>、<a href="https://github.com/VictoriaMetrics/VictoriaMetrics">VictoriaMetrics</a>、<a href="https://github.com/dgraph-io/dgraph">Dgraph</a>、<a href="https://github.com/milvus-io/milvus">milvus</a>等)、消息队列(<a href="https://github.com/nats-io/nats-server">NATS</a>、<a href="https://github.com/nsqio/nsq">nsq</a>等)、服务网格(<a href="https://tonybai.com/2018/01/03/an-intro-of-microservices-governance-by-istio">Istio</a>、<a href="https://github.com/linkerd/linkerd2">linkerd2</a>)、API网关/代理(<a href="https://github.com/traefik/traefik">Traefik</a>、<a href="https://github.com/emissary-ingress/emissary">emissary</a>等)、镜像仓库/加速器(<a href="https://tonybai.com/2017/10/23/the-speech-script-practice-on-deploying-a-ha-harbor-cluster-for-osc-shenyang-2017/">harbor</a>、<a href="https://github.com/dragonflyoss/Dragonfly2">Dragonfly</a>)、key-value存储(<a href="https://github.com/etcd-io/etcd">Etcd</a>、<a href="https://github.com/hashicorp/consul">consul</a>、<a href="https://github.com/paypal/junodb">junodb</a>)、安全相关(<a href="https://github.com/falcosecurity/falco">falco</a>、<a href="https://github.com/open-policy-agent/opa">OPA</a>、<a href="https://github.com/hashicorp/vault">vault</a>)、可观测组件(<a href="https://github.com/open-telemetry/community">OpenTelemetry</a>、<a href="https://github.com/prometheus/prometheus">Prometheus</a>、<a href="https://github.com/thanos-io/thanos">Thanos</a>、<a href="https://github.com/cortexproject/cortex">Cortex</a>等)、基础设施管理(<a href="https://github.com/hashicorp/terraform">terraform</a>、<a href="https://github.com/dagger/dagger">dagger</a>)、分布式存储(<a href="https://github.com/minio/">minio</a>、<a href="https://github.com/seaweedfs/seaweedfs">SeaweedFS</a>、<a href="https://github.com/juicedata/juicefs">juicefs</a>)、AI大模型运维(<a href="https://github.com/ollama/ollama">ollama</a>)。</li>
<li>应用层：<a href="https://github.com/caddyserver/caddy">Caddy</a>、<a href="https://github.com/gohugoio/hugo">gohugo</a>、<a href="https://github.com/mattermost/mattermost">mattermost</a>等。</li>
</ul>
<p>我们用一张示意图来横向对比一下：</p>
<p><img src="https://tonybai.com/wp-content/uploads/go-the-c-language-of-the-internet-era-come-true-5.png" alt="" /></p>
<p>听我讲到这里，你是不是觉得老许的那个预言好像命中了呢！</p>
<p>当然，从狭义的角度来看，Go与C还有一些地方是很像的，比如：语法简单、跨平台可移植性好等。并且两者还“沾亲带故”：Unix之父Ken Thompson当年和Dennis Ritchie一起发明了C语言，又和Rob Pike等一起设计了Go语言！</p>
<p>最后，回顾许式伟2012年的预言，我们不得不惊叹于其洞察力。Go语言确实在很大程度上成为了”互联网时代的C语言”，但不是通过传统的性能优势，而是通过<strong>重新构建了云原生技术栈</strong>，从这个角度看，Go语言也不失为云原生时代的”系统语言” —— 它不仅能够优雅地处理分布式系统的复杂性，它还使得构建和维护大规模、高可靠性的分布式系统变得更为简单，是云原生时代的思维方式和解决方案的集大成者，某种程度上还可以说定义了云原生时代的软件开发范式。</p>
<hr />
<p><a href="https://public.zsxq.com/groups/51284458844544">Gopher部落知识星球</a>在2024年将继续致力于打造一个高品质的Go语言学习和交流平台。我们将继续提供优质的Go技术文章首发和阅读体验。同时，我们也会加强代码质量和最佳实践的分享，包括如何编写简洁、可读、可测试的Go代码。此外，我们还会加强星友之间的交流和互动。欢迎大家踊跃提问，分享心得，讨论技术。我会在第一时间进行解答和交流。我衷心希望Gopher部落可以成为大家学习、进步、交流的港湾。让我相聚在Gopher部落，享受coding的快乐! 欢迎大家踊跃加入！</p>
<p><img src="http://image.tonybai.com/img/tonybai/gopher-tribe-zsxq-small-card.png" alt="img{512x368}" /><br />
<img src="http://image.tonybai.com/img/tonybai/go-programming-from-beginner-to-master-qr.png" alt="img{512x368}" /></p>
<p><img src="http://image.tonybai.com/img/tonybai/go-first-course-banner.png" alt="img{512x368}" /><br />
<img src="http://image.tonybai.com/img/tonybai/imooc-go-column-pgo-with-qr.jpg" alt="img{512x368}" /></p>
<p>著名云主机服务厂商DigitalOcean发布最新的主机计划，入门级Droplet配置升级为：1 core CPU、1G内存、25G高速SSD，价格5$/月。有使用DigitalOcean需求的朋友，可以打开这个<a href="https://m.do.co/c/bff6eed92687">链接地址</a>：https://m.do.co/c/bff6eed92687 开启你的DO主机之路。</p>
<p>Gopher Daily(Gopher每日新闻) &#8211; https://gopherdaily.tonybai.com</p>
<p>我的联系方式：</p>
<ul>
<li>微博(暂不可用)：https://weibo.com/bigwhite20xx</li>
<li>微博2：https://weibo.com/u/6484441286</li>
<li>博客：tonybai.com</li>
<li>github: https://github.com/bigwhite</li>
<li>Gopher Daily归档 &#8211; https://github.com/bigwhite/gopherdaily</li>
<li>Gopher Daily Feed订阅 &#8211; https://gopherdaily.tonybai.com/feed</li>
</ul>
<p><img src="http://image.tonybai.com/img/tonybai/iamtonybai-wechat-qr.png" alt="" /></p>
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。</p>
<p style='text-align:left'>&copy; 2024, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2024/08/17/go-the-c-language-of-the-internet-era-come-true/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hugo作者、Go核心开发团队成员谈诞生13年的Go语言：生态系统、演化与未来[译]</title>
		<link>https://tonybai.com/2021/01/02/go-language-13-years/</link>
		<comments>https://tonybai.com/2021/01/02/go-language-13-years/#comments</comments>
		<pubDate>Sat, 02 Jan 2021 04:09:50 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[cli]]></category>
		<category><![CDATA[Cpp]]></category>
		<category><![CDATA[Dart]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[Flutter]]></category>
		<category><![CDATA[GC]]></category>
		<category><![CDATA[generics]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[go-module]]></category>
		<category><![CDATA[go1.11]]></category>
		<category><![CDATA[gohugo]]></category>
		<category><![CDATA[Golang]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[hugo]]></category>
		<category><![CDATA[InfluxDB]]></category>
		<category><![CDATA[infoq]]></category>
		<category><![CDATA[istio]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JS]]></category>
		<category><![CDATA[Kubernetes]]></category>
		<category><![CDATA[Module]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[pkg.go.dev]]></category>
		<category><![CDATA[prometheus]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Rust]]></category>
		<category><![CDATA[syncthing]]></category>
		<category><![CDATA[terraform]]></category>
		<category><![CDATA[Vim]]></category>
		<category><![CDATA[vitess]]></category>
		<category><![CDATA[专栏]]></category>
		<category><![CDATA[垃圾回收]]></category>
		<category><![CDATA[泛型]]></category>

		<guid isPermaLink="false">https://tonybai.com/?p=3064</guid>
		<description><![CDATA[本文翻译自《Go Language at 13 Years: Ecosystem, Evolution, and Future in Conversation with Steve Francia》。 译注：Go开源于2009年，如果从那时算起，Go才11岁；但在Go核心开发团队眼中，Go的真正诞生年份是2007年，至今13个年头了。关于Go的演化简史可以参见我的专栏文章：《Go语言的前生今世》。 本文要点： Go的简单性让你可以快速上手使用它&#8211;你可以在一个下午就消化掉整个Go语言规范； 作者认为Go是当今最好的现代语言之一（其他的还包括：Dart、Flutter和Rust）； Go的未来是由它的开源社区决定的，它对所有的功能建议进行讨论和辩论。除非达成明确的共识，否则该功能不会被实现。 社区的规模大约每18个月翻一番。 最初，Go的早期采用者多来自python或ruby等动态语言的开发人员，现在随着语言的成熟，来自Java、.NET和C++程序员也开始接纳并使用Go。 在充满挑战的一年里，社区适应了相互支持，出现了多个meetup，并出现了新的资源。 编程语言的历史只朝着一个方向发展，每一种新的语言的出现都让事情都变得越来越复杂，越来越抽象。然而，就在十几年前，Go在Google诞生了。这种编程语言走的是另外一条路，它把赌注押在了简单和精心的设计和实现上。这个配方一直保留到今天，你可以直接开始写Go代码，没有太大的障碍。当你想到现代软件的大部分流行和可靠的作品都是用Go编写的，比如Docker、Kubernetes、Prometheus等，这就足以让你印象深刻。这个列表还在持续增加。为了了解Go从哪里来，更重要的是它要往哪里去，InfoQ联系了Google负责战略和产品的Go编程语言团队核心成员Steve Francia(译注：他也是知名静态站点生成工具gohugo的作者)。 InfoQ：非常感谢您抽出宝贵时间回答读者的几个问题。我们能否首先请您介绍一下自己并描述您在Google的角色和日常工作？ Steve Francia：我是Steve Francia，是Google Go编程语言团队的核心成员，负责产品和策略。 InfoQ：您将技术挑战和工程挑战归因于十三年前点燃了Go的火花。还有其他吗？当时Google的官方编程语言是什么，缺少什么？ Francia：创建Go的主要动机是认识到我们的系统已经变得越来越复杂。为了跟上“Google规模”的指数增长，我们设计了复杂的系统来满足我们的需求。随着时间的流逝，我们又在这些基础系统/库和语言的基础上构建了新的复杂系统。人们通常不会想到复杂性的隐性成本。事实是，代码被读取的次数比其编写的次数多。复杂性给团队效率带来了极大的负担。相反，Go很简单。你仅需要花一个下午的时间来学习。Go代码非常简单易读。这种简单性使团队能够以前所未有的方式进行协作。 InfoQ：这一切是如何开始的？是自上而下的请求（管理人员要求一种语言来满足需求），还是自下而上的请求？来自Google的20％著名的创新？工程师尽其所能-解决问题？ Francia：没人要求过。这实际上不是一个20％的项目。是一次谈话导致一个研究项目获得了关注，并且被广泛采用，超出了所有人的想象。当然，Google从上到下都对寻找降低复杂性和提高生产力的方法感兴趣。 InfoQ：在起步阶段，有一种说法是，如果您在发布之日不为自己的产品感到羞耻，那么您可能为时已晚。Go于2011年发布1.0版本，当时Google为了支持它，将其添加到Google App Engine中，YouTube也开始使用Vitess(译注：一种Go实现的Mysql前置代理，用于建立mysql集群）。Go在发布时就已经准备好投入生产了吗？还是人们努力用它来构建产品？ Francia：Go发布的恰逢其时。有很多Go的基础设计是正确的，但是今天Go中有很多东西不在早期版本中-这在开源中很常见。最明显的是，当时没有“go”命令，所以在如今的Go版本中可以很自然做的事情（例如“go build”）在早期则要困难得多。 提前发布的最大好处是它使社区能够参与Go的设计过程。社区为Go的成功做出了很大的贡献。 我们的Go的第一个公开发行版就可以应用于生产环境了，这表现在用Go构建的程序在生产环境中的高性能和稳定的，但是Go仍然缺乏很多完善之处，Go团队和社区随后可以共同塑造和打磨。 InfoQ：回顾一下，构建Go时需要解决的最技术性问题是什么？ Francia：这个问题很难讲。这有点暗示我们已经完成了Go。我认为Go项目多年来解决了许多“最棘手”的技术问题，我们将继续解决非常具有挑战性的技术问题。我们目前正在努力为Go添加泛型支持。添加泛型本身就是一项艰巨的任务，但是我们也希望它仍然看起来像Go，这意味着使用泛型可以提高可读性。这是一件非常困难的事情，而且我们的一些关键人员已经思考了十多年。 在过去的几年中，我们解决了有关如何管理Go依赖的一些最大挑战。我们在Go中添加了module支持，但却没有引入菱形依赖项或依赖项地狱，这是以前的编程语言所没能做到过的。 另一个挑战是Go在每个版本中持续改进其性能。其体现之一是将垃圾收集的暂停时间延迟(STW)从几秒减少到几毫秒再到几微秒。这对于Go而言是具有变革性的，对于其在服务中的成功至关重要。 InfoQ：如果您必须重新实现一次Go，您会采取什么不同的措施？为什么？ Francia：借助事后观察的优势，作为今天帮助塑造Go的人，但在最初的几年中我并没有出现，我真的不会改变。这是一种美丽的，经过深思熟虑的语言，虽然它并不完美，但使用起来非常好。 我希望我们进行一些小调整，但讨论它们会把太多的焦点放在这些微不足道的事情上。相反，如果我们可以重来一次，我希望我们会犯同样的错误，只是更早而已。Go的发展速度非常快，大约每18个月，Go的用户群的规模就会增加一倍。这意味着，今天与五年前相比，一个变化会影响大约10倍的人。 今天的Go依赖管理机制非常棒，但它可能比预期的晚了五年。这种延误使本来已经很困难的问题变得更加困难，结果给社区造成了不必要的压力。 同样，我们现在正在努力进行的重大语言更改是泛型。这将对社区产生重大影响。如果我们能够重新做一遍，而事后才明白此功能的重要性，我希望我们早在七年前就可以认真地开始这项工作。 InfoQ：Go编程语言还缺少什么？ Francia：作为一种语言，泛型确实是我们所缺少的唯一主要功能，正如我之前所说，我们目前正专注于此。现在有一个支持新泛型语法的playground，您可以在其中使用新泛型语法原型并提供反馈。 除此之外，大部分要做的工作是改进和完善，主要是在语言本身的周边。对于工具，我们计划改善创作，发布和编辑体验。我们还致力于帮助人们做出有关其依赖关系的更好决策。 InfoQ：Go始于Google，但现在是开源的。如今，谁才是幕后的决策人呢？ Francia：2020年11月，Go庆祝了自己开源11周年。Go有一个定义明确的提案流程决定了整个项目的方向。想法和经验来自社区的每个角落。它们作为提案发布到Github上的项目中。从那里社区可以评估他们对提案的看法，并帮助进一步完善提案。提案委员会每周开会，审查未完成的提案。目前，委员会有六名成员，其中四名是Google员工。但决策几乎总是来自社区对提案问题本身的讨论。除非问题讨论明确同意，否则该提议将被拒绝。通过设计和意图，Go的更改会在公开环境中缓慢而有意识地发生。该过程旨在加强这一点。 InfoQ：随着Go的普及，Go的生态系统如何演变？Go最初主要专注于网络和基础架构。这些年来其用法是如何演变的？ [...]]]></description>
			<content:encoded><![CDATA[<p><img src="https://tonybai.com/wp-content/uploads/go-language-13th-anniversary-by-steve-francia.jpg" alt="img{512x368}" /></p>
<p>本文翻译自<a href="https://www.infoq.com/articles/go-language-13-years/">《Go Language at 13 Years: Ecosystem, Evolution, and Future in Conversation with Steve Francia》</a>。</p>
<blockquote>
<p>译注：Go开源于2009年，如果从那时算起，<a href="https://mp.weixin.qq.com/s/woQeEQUhOLJ7KSE5rm5q6g">Go才11岁</a>；但在Go核心开发团队眼中，Go的真正诞生年份是2007年，至今13个年头了。关于Go的演化简史可以参见我的专栏文章：<a href="https://www.imooc.com/read/87/article/2320">《Go语言的前生今世》</a>。</p>
</blockquote>
<p>本文要点：</p>
<ul>
<li><a href="https://www.imooc.com/read/87/article/2321">Go的简单性</a>让你可以快速上手使用它&#8211;你可以在一个下午就消化掉整个<a href="https://tip.golang.org/ref/spec">Go语言规范</a>；</li>
<li>作者认为Go是当今最好的现代语言之一（其他的还包括：Dart、Flutter和Rust）；</li>
<li>Go的未来是由它的开源社区决定的，它对所有的功能建议进行讨论和辩论。除非达成明确的共识，否则该功能不会被实现。</li>
<li>社区的规模大约每18个月翻一番。</li>
<li>最初，Go的早期采用者多来自python或ruby等动态语言的开发人员，现在随着语言的成熟，来自Java、.NET和C++程序员也开始接纳并使用Go。</li>
<li>在充满挑战的一年里，社区适应了相互支持，出现了多个meetup，并出现了新的资源。</li>
</ul>
<hr />
<p>编程语言的历史只朝着一个方向发展，每一种新的语言的出现都让事情都变得越来越复杂，越来越抽象。然而，就在十几年前，Go在Google诞生了。这种编程语言走的是另外一条路，它把赌注押在了简单和精心的设计和实现上。这个配方一直保留到今天，你可以直接开始写Go代码，没有太大的障碍。当你想到现代软件的大部分流行和可靠的作品都是用Go编写的，比如Docker、Kubernetes、Prometheus等，这就足以让你印象深刻。这个列表还在持续增加。为了了解Go从哪里来，更重要的是它要往哪里去，InfoQ联系了Google负责战略和产品的Go编程语言团队核心成员<a href="https://github.com/spf13">Steve Francia</a>(译注：他也是知名静态站点生成工具<a href="https://github.com/gohugoio/hugo">gohugo</a>的作者)。</p>
<p>InfoQ：非常感谢您抽出宝贵时间回答读者的几个问题。我们能否首先请您介绍一下自己并描述您在Google的角色和日常工作？</p>
<blockquote>
<p>Steve Francia：我是Steve Francia，是Google Go编程语言团队的核心成员，负责产品和策略。</p>
</blockquote>
<p>InfoQ：您将技术挑战和工程挑战归因于十三年前点燃了Go的火花。还有其他吗？当时Google的官方编程语言是什么，缺少什么？</p>
<blockquote>
<p>Francia：创建Go的主要动机是认识到我们的系统已经变得越来越复杂。为了跟上“Google规模”的指数增长，我们设计了复杂的系统来满足我们的需求。随着时间的流逝，我们又在这些基础系统/库和语言的基础上构建了新的复杂系统。人们通常不会想到复杂性的隐性成本。事实是，代码被读取的次数比其编写的次数多。复杂性给团队效率带来了极大的负担。相反，Go很简单。你仅需要花一个下午的时间来学习。Go代码非常简单易读。这种简单性使团队能够以前所未有的方式进行协作。</p>
</blockquote>
<p>InfoQ：这一切是如何开始的？是自上而下的请求（管理人员要求一种语言来满足需求），还是自下而上的请求？来自Google的20％著名的创新？工程师尽其所能-解决问题？</p>
<blockquote>
<p>Francia：没人要求过。这实际上不是一个20％的项目。是一次谈话导致一个研究项目获得了关注，并且被广泛采用，超出了所有人的想象。当然，Google从上到下都对寻找降低复杂性和提高生产力的方法感兴趣。</p>
</blockquote>
<p>InfoQ：在起步阶段，有一种说法是，如果您在发布之日不为自己的产品感到羞耻，那么您可能为时已晚。Go于2011年发布1.0版本，当时Google为了支持它，将其添加到Google App Engine中，YouTube也开始使用Vitess(译注：一种Go实现的Mysql前置代理，用于建立mysql集群）。Go在发布时就已经准备好投入生产了吗？还是人们努力用它来构建产品？</p>
<blockquote>
<p>Francia：Go发布的恰逢其时。有很多Go的基础设计是正确的，但是今天Go中有很多东西不在早期版本中-这在开源中很常见。最明显的是，当时没有“go”命令，所以在如今的Go版本中可以很自然做的事情（例如“go build”）在早期则要困难得多。</p>
<p>提前发布的最大好处是它使社区能够参与Go的设计过程。社区为Go的成功做出了很大的贡献。</p>
<p>我们的Go的第一个公开发行版就可以应用于生产环境了，这表现在用Go构建的程序在生产环境中的高性能和稳定的，但是Go仍然缺乏很多完善之处，Go团队和社区随后可以共同塑造和打磨。</p>
</blockquote>
<p>InfoQ：回顾一下，构建Go时需要解决的最技术性问题是什么？</p>
<blockquote>
<p>Francia：这个问题很难讲。这有点暗示我们已经完成了Go。我认为Go项目多年来解决了许多“最棘手”的技术问题，我们将继续解决非常具有挑战性的技术问题。我们目前正在努力<a href="https://mp.weixin.qq.com/s/SMT40557JgQ9FjUkswznlA">为Go添加泛型支持</a>。添加泛型本身就是一项艰巨的任务，但是我们也希望它仍然看起来像Go，这意味着使用泛型可以提高可读性。这是一件非常困难的事情，而且我们的一些关键人员已经思考了<a href="https://mp.weixin.qq.com/s/do7slOGxztgAfx4Io4PQkg">十多年</a>。</p>
<p>在过去的几年中，我们解决了有关如何管理Go依赖的一些最大挑战。我们在Go中<a href="https://mp.weixin.qq.com/s/fg84g4OzSgoHDGbvVDbMKg">添加了module支持</a>，但却没有引入菱形依赖项或依赖项地狱，这是以前的编程语言所没能做到过的。</p>
<p>另一个挑战是Go在每个版本中持续改进其性能。其体现之一是将垃圾收集的暂停时间延迟(STW)从几秒减少到几毫秒再到几微秒。这对于Go而言是具有变革性的，对于其在服务中的成功至关重要。</p>
</blockquote>
<p>InfoQ：如果您必须重新实现一次Go，您会采取什么不同的措施？为什么？</p>
<blockquote>
<p>Francia：借助事后观察的优势，作为今天帮助塑造Go的人，但在最初的几年中我并没有出现，我真的不会改变。这是一种美丽的，经过深思熟虑的语言，虽然它并不完美，但使用起来非常好。</p>
<p>我希望我们进行一些小调整，但讨论它们会把太多的焦点放在这些微不足道的事情上。相反，如果我们可以重来一次，我希望我们会犯同样的错误，只是更早而已。Go的发展速度非常快，大约每18个月，Go的用户群的规模就会增加一倍。这意味着，今天与五年前相比，一个变化会影响大约10倍的人。</p>
<p>今天的Go依赖管理机制非常棒，但它可能比预期的晚了五年。这种延误使本来已经很困难的问题变得更加困难，结果给社区造成了不必要的压力。</p>
<p>同样，我们现在正在努力进行的重大语言更改是<a href="https://mp.weixin.qq.com/s/14WeOQBdezWTC5OqQrJtfg">泛型</a>。这将对社区产生重大影响。如果我们能够重新做一遍，而事后才明白此功能的重要性，我希望我们早在七年前就可以认真地开始这项工作。</p>
</blockquote>
<p>InfoQ：Go编程语言还缺少什么？</p>
<blockquote>
<p>Francia：作为一种语言，泛型确实是我们所缺少的唯一主要功能，正如我之前所说，我们目前正专注于此。现在<a href="https://mp.weixin.qq.com/s/14WeOQBdezWTC5OqQrJtfg">有一个支持新泛型语法的playground</a>，您可以在其中使用新泛型语法原型并提供反馈。</p>
<p>除此之外，大部分要做的工作是改进和完善，主要是在语言本身的周边。对于工具，我们计划改善创作，发布和编辑体验。我们还致力于帮助人们做出有关其依赖关系的更好决策。</p>
</blockquote>
<p>InfoQ：Go始于Google，但现在是开源的。如今，谁才是幕后的决策人呢？</p>
<blockquote>
<p>Francia：2020年11月，<a href="https://mp.weixin.qq.com/s/woQeEQUhOLJ7KSE5rm5q6g">Go庆祝了自己开源11周年</a>。Go有一个定义明确的<a href="https://github.com/golang/proposal">提案流程</a>决定了整个项目的方向。想法和经验来自社区的每个角落。它们作为提案发布到Github上的项目中。从那里社区可以评估他们对提案的看法，并帮助进一步完善提案。提案委员会每周开会，审查未完成的提案。目前，委员会有六名成员，其中四名是Google员工。但决策几乎总是来自社区对提案问题本身的讨论。除非问题讨论明确同意，否则该提议将被拒绝。通过设计和意图，Go的更改会在公开环境中缓慢而有意识地发生。该过程旨在加强这一点。</p>
</blockquote>
<p>InfoQ：随着Go的普及，Go的生态系统如何演变？Go最初主要专注于网络和基础架构。这些年来其用法是如何演变的？</p>
<blockquote>
<p>Francia：关于Go的一个有趣的事情是Go语言走了一条与其创始人最初计划不同的途径。Go语言之父们创建Go的最初目的是构建流行的高性能服务器端编程语言（当时为Java和C++）的替代品。创始人们认为，一种简单的语言可以在保持性能的同时，极大地提高此类开发人员的生产率。</p>
<p>尽管Go在争取到了一些Java和C++工程师的支持和早期采纳，但Go的大部分早期采用者都来自动态语言程序员群体，这些语言来自Python，Javascript，Ruby和PHP等语言。事实证明，Go最初对动态语言类的吸引力更大，动态语言类看到了在保持生产力的的同时大幅提高性能的机会。</p>
<p>随着Go及其生态系统的成熟，Go的采用已扩展到企业中，并且Java，C++和C＃工程师的最初受众也加快了他们对Go的采用。</p>
<p>Go的独特魅力之一是，它是一种小语言，其大多数创新就发生在其生态系统中。我们一直对社区采用Go的创造性和多样化方向感到惊讶。Go的优势仍然是Go十分适合的云/服务器应用程序，但事实证明Go确实也非常适合许多其他类型的应用程序。DevOps / SRE，CLI，Web应用程序和数据处理已全部转到Go。现在，我们看到Go用于微控制器，机器人技术，游戏等。</p>
</blockquote>
<p>InfoQ：Kubernetes，Docker和Prometheus都是用Go编写的。还有其他用该语言编写的工具吗？</p>
<blockquote>
<p>Francia：这里能列出的工具太多了。我个人经常使用的一些比较流行的工具是：</p>
<ul>
<li><a href="https://gohugo.io/">Hugo</a>，一个静态网站生成器（我几年前创建的）。</li>
<li><a href="https://syncthing.net/">Syncthing</a>，一种分布式同步工具（请考虑Dropbox / Google驱动器，但不带服务器）。</li>
<li><a href="https://istio.io/">服务网格Istio</a></li>
<li><a href="https://www.terraform.io/">Terraform</a>，基础架构即代码</li>
<li><a href="https://www.influxdata.com/">InfluxDB</a>，时间序列数据库</li>
</ul>
<p>在<a href="https://github.com/avelino/awesome-go#software-packages">Awesome Go</a>上可以找到更详细的列表。</p>
</blockquote>
<p>InfoQ：在网络和系统编程方面，Go是高效且可靠的，但是Go所不适合的领域是什么呢？</p>
<blockquote>
<p>Francia：对我自己来说，今天只有三种现代语言。每种语言都经过精心设计，以解决前代语言的不同缺点，从而使每种语言在不同方面都具有出色的表现，并且是其他语言的很好补充。这是我看这三种语言的方式：</p>
<ul>
<li>Go是一种很好的默认语言。它是系统，服务器，API，守护程序，数据库，网站，工具等的理想选择。Go达到了性能与开发人员生产力之间的关键平衡。</li>
<li>Dart + Flutter，用于基于GUI的应用程序（移动+桌面）。Flutter在编写一个可以在多种操作系统和多种格式下工作的客户端应用程序的想法方面表现出色。</li>
<li>需要精细控制时可以使用Rust。对于低级编程、内核之类的东西，Rust提供了更高的精度，但代价是增加了复杂性。有时候，这种权衡是有意义的，而当这样做时，Rust是一个不错的选择。</li>
</ul>
<p>我认为，未来10年以上的大多数“现代”工作负载将以其中一种语言编写。当然，总会有需要支持的旧工作负载，因此请不要认为我在这里的观点暗示了任何语言的消亡。肯定还存在在某些领域中，诸如R，SQL甚至Javascript之类的利基语言可以发挥作用。</p>
</blockquote>
<p>InfoQ：史蒂夫，我记得几年前在布达佩斯参加了一次会议，在那里您举办了有关使用Go的研讨会。我有种感觉，您会更多向对手推销并建议Go，而不是向朋友-为什么？</p>
<blockquote>
<p>Francia：那是一次很棒的会议，也是我第一次在布达佩斯。从那以后我已经回来过几次了，这是我最喜欢的城市之一，如此充满魅力。</p>
<p>许多年前，我在MongoDB工作。我的角色是领导开发人员体验团队，这意味着我应对与用户相关的一切负责。其中包括文档，网站，开发人员关系，MongoDB界面，以及设计和设计我们与语言和框架的集成。这是一个非常广泛且具有挑战性的角色，需要我的团队使用10多种不同的编程语言（以及几种人类语言）进行编写。到那时为止，我在职业生涯中一直使用多种语言，并以能够为我们的每种语言做出贡献为目标。当时，我认为自己是一个会说多种语言的人，并且很高兴能借此机会扩展自己的经验并了解这些不同的语言。</p>
<p>首先，我们专注于支持最受欢迎的语言，而我一直在寻找“下一种语言”可能是什么。由于马丁·奥德斯基（Martin Odersky）在Scala上的免费在线课程，我学到的第一门“下一门语言”是Scala。我喜欢学习语言，并且一直在搜寻。我尝试的下一种语言是Go。我恋爱了。就像有人为我设计了一种语言。我花了大量的空闲时间，大部分时间每天花3个小时以上，坐火车去曼哈顿，写Go软件。这就是<a href="https://gohugo.io/">Hugo</a>，<a href="https://cobra.dev/">Cobra</a>，<a href="https://github.com/spf13/viper">Viper</a>，<a href="https://github.com/spf13/afero">Afero</a>和许多其他库。</p>
<p>在此过程中，我了解到我不是一个会说多种语言的人，只是我还没有发现自己的语言。从我第一次使用Go的那一刻起，我就沉浸在Go社区和生态系统中，在世界各地进行培训，在许多会议上发表演讲并组织一些活动。在过去的七年中，我一直在告诉任何尝试了解Go语言的人，在此过程中，我以某种方式说服了Go团队和Google让我加入他们。除此之外，我还帮助了无数其他人讲述他们的故事，其中许多故事都在<a href="https://go.dev/">Go.dev</a>上。</p>
</blockquote>
<p>InfoQ：Go语言才13岁，所以还是个少年(译注：在编程语言领域)。你怎么看待这件事？它是可靠的类型，它使用户的生活变得更轻松，还是仍然叛逆而喜怒无常，使操作变得棘手？</p>
<blockquote>
<p>Francia：作为用户，我认为Go从来没有比现在更好。向module的迁移非常顺利。Go非常稳定，性能不断提高。Go工具也越来越好。Go.dev是一个很棒的一站式资源，它将来自整个社区的所有最终用户的参考资料，教程，文档和库集中在一个地方。我可能有偏见，但是作为Go的用户，在加入Go团队很久之前，我对Go的现状和发展方向感到非常满意。</p>
</blockquote>
<p>InfoQ：对于Go开发要使用的工具箱，您会推荐哪些？</p>
<blockquote>
<p>Francia：Go的一大优点是，它真正满足了您的需求。Go开发在Mac，Linux或Windows上几乎完全相同，并且<a href="https://tonybai.com/2014/10/20/cross-compilation-with-golang/">Go的交叉编译</a>使其可为任何架构和OS轻松构建。随着<a href="https://github.com/golang/tools/tree/master/gopls">gopls语言服务器</a>的引入，所有编辑器和IDE都将具有很棒的编写Go语言的体验。Go发行版中附带的Go工具包含开发人员开始使用该语言所需的一切。</p>
<p>尽管我主要在Windows上使用VSCodium或Vim进行开发，但我将时间分配在这三个OS之间。我经常使用Cobra工具和库，但是这些天我个人对Go的使用主要是构建一些小的CLI应用程序和实用程序来自动化或简化任务，因此非常适合。</p>
</blockquote>
<p>InfoQ：对于从零开始学习Go的程序员来说，Go的学习曲线有多陡峭？您对新手的建议是什么？</p>
<blockquote>
<p>Francia：正如我之前提到的，Go的最大优势之一就是入门非常容易。人们常常会感到震惊，但这确实是事实-您可以在一个下午阅读并消化整个Go规范。您可以在周末学习Go。在几周内，您将精通Go语言。有些甚至比这快。如果您以其他几种语言的经验来学习该语言，则可以很快选择Go。</p>
<p>当我们与采用Go的公司会面时，这是他们告诉我们的最一致的内容之一。Go非常容易上手。</p>
</blockquote>
<p>InfoQ：对于新手而言，学习Go的前提是什么？</p>
<blockquote>
<p>Francia：老实说，只是时间和兴趣。Go适合所有人。来自社区的<a href="https://go.dev/">go.dev</a>上有一些很棒的入门资源。</p>
</blockquote>
<p>InfoQ：Go的发展让所有人（包括您自己）都感到惊讶。在接下来的十年中，您认为Go会如何发展？</p>
<blockquote>
<p>Francia：如果回顾一下计算机编程语言的历史，我们会发现绝大多数主流编程语言将在其15至20年间大步前进。Java，Python，Ruby，JavaScript和许多其他语言都是如此。自诞生以来的13年中，Go奠定了坚实的基础，并正在成为主流语言。Go的杰出之处在于可以同时提供高性能和高开发人员生产力。</p>
<p>在接下来的10年中，向云计算的大规模转变只会继续加速。公司希望缩短上市时间，降低运营成本并提高安全性。迁移的第一阶段将主要是将其现有工作负载迁移到云中。Go在这里起着关键的支持作用，提供API桥接能力，以使“传统”工作负载能够在云服务上运行。第二个更重要的阶段将是行业转变为利用独特的云产品，逐渐转向云原生应用程序开发。在这些情况下，Go是明智的选择。</p>
<p>所有云提供商都在Go中编写其关键基础架构。随着公司寻求现代化，有哪家公司不想使用一种安全可靠的语言以及经过十多年来来自全球一些最大公司的关键工作负载的测试，既可以降低开发成本，又可以大大降低其运营成本的语言呢？简而言之，Go将成为云开发的代名词，而云开发将发展成为该行业绝大多数的业务。</p>
</blockquote>
<p>InfoQ：我应该问你什么，但没有问？</p>
<blockquote>
<p>Francia：谈论一种语言而不谈论其社区是不可能的。实际上，Go之所以存在，是因为全世界有数百万人使用Go开发。Go社区强大，热情且多样化。与所有人一样，今年Go社区进行了调整，并且也做了调整。在世界各地，gopher聚在一起并互相帮助。召开了30次<a href="https://www.meetup.com/pro/go">（虚拟）会议</a>。数百次聚会（主要是虚拟聚会）以及<a href="https://www.reddit.com/r/golang/">/r/golang</a>和<a href="https://gophers.slack.com/messages/general/">Gopher slack</a>的参与度显着增长。我们启动了两个值得注意的新的社区主导程序，以帮助新的Gophers <a href="https://play-with-go.dev/">play-with-go.dev</a>和<a href="https://promo.qooper.io/organizations/MjE1">mentoring.gobridge.org</a>。</p>
<p>我们感谢世界上所有为Go蓬勃发展的生态系统做出贡献的Gopher，并共同期待Go的美好未来。</p>
</blockquote>
<hr />
<h3>“Gopher部落”，新年新气象</h3>
<p><a href="https://public.zsxq.com/groups/51284458844544">“Gopher部落”</a>正式转正（从试运营星球变成了正式星球）！“gopher部落<br />
”旨在打造一个精品Go学习和进阶社群，目前虽小，但持续力很强。在2021年上半年，部落将策划两个专题系列分享，并且是部>落独享哦：</p>
<ul>
<li>Go技术书籍的书摘和读书体会系列</li>
<li>Go与eBPF系列</li>
</ul>
<p>考虑到部落尚处于推广期，这里仍然为大家准备了新人优惠券，虽然优惠幅度有所下降，但依然物超所值，早到早享哦！</p>
<p><img src="http://image.tonybai.com/img/202011/gopher-tribe-zsxq.png" alt="" /></p>
<p>感谢大家对本星球的支持！</p>
<p>Go技术专栏“<a href="https://www.imooc.com/read/87">改善Go语⾔编程质量的50个有效实践</a>”正在慕课网火热热销中！本专栏主要满足广大gopher关于Go语言进阶的需求，围绕如何写出地道且高质量Go代码给出50条有效实践建议，上线后收到一致好评！欢迎大家订阅！</p>
<p><img src="http://image.tonybai.com/img/202011/go-column-pgo-with-qr-and-text.png" alt="" /></p>
<p>我的网课“<a href="https://coding.imooc.com/class/284.html">Kubernetes实战：高可用集群搭建、配置、运维与应用</a>”在慕课网热卖中，欢迎小伙伴们订阅学习！</p>
<p><img src="https://tonybai.com/wp-content/uploads/k8s-practice-with-qr-and-text.png" alt="img{512x368}" /></p>
<p><a href="https://tonybai.com/">我爱发短信</a>：企业级短信平台定制开发专家 https://tonybai.com/。smspush : 可部署在企业内部的定制化短信平台，三网覆盖，不惧大并发接入，可定制扩展； 短信内容你来定，不再受约束, 接口丰富，支持长短信，签名可选。2020年4月8日，中国三大电信运营商联合发布《5G消息白皮书》，51短信平台也会全新升级到“51商用消息平台”，全面支持5G RCS消息。</p>
<p>著名云主机服务厂商DigitalOcean发布最新的主机计划，入门级Droplet配置升级为：1 core CPU、1G内存、25G高速SSD，价格5$/月。有使用DigitalOcean需求的朋友，可以打开这个<a href="https://m.do.co/c/bff6eed92687">链接地址</a>：https://m.do.co/c/bff6eed92687 开启你的DO主机之路。</p>
<p>Gopher Daily(Gopher每日新闻)归档仓库 &#8211; https://github.com/bigwhite/gopherdaily</p>
<p>我的联系方式：</p>
<ul>
<li>微博：https://weibo.com/bigwhite20xx</li>
<li>微信公众号：iamtonybai</li>
<li>博客：tonybai.com</li>
<li>github: https://github.com/bigwhite</li>
<li>“Gopher部落”知识星球：https://public.zsxq.com/groups/51284458844544</li>
</ul>
<p>微信赞赏：<br />
<img src="https://tonybai.com/wp-content/uploads/wechat-zanshang-code-512x512.jpg" alt="img{512x368}" /></p>
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。</p>
<p style='text-align:left'>&copy; 2021, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2021/01/02/go-language-13-years/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Go语言开源十周年</title>
		<link>https://tonybai.com/2019/11/09/go-opensource-10-years/</link>
		<comments>https://tonybai.com/2019/11/09/go-opensource-10-years/#comments</comments>
		<pubDate>Sat, 09 Nov 2019 01:36:49 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[6g]]></category>
		<category><![CDATA[6l]]></category>
		<category><![CDATA[cgi]]></category>
		<category><![CDATA[cloud]]></category>
		<category><![CDATA[CNCF]]></category>
		<category><![CDATA[Cpp]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[etcd]]></category>
		<category><![CDATA[GC]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[go10th]]></category>
		<category><![CDATA[GoBot]]></category>
		<category><![CDATA[Golang]]></category>
		<category><![CDATA[golangbridge]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Gopher]]></category>
		<category><![CDATA[istio]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Kubernetes]]></category>
		<category><![CDATA[machine-learning]]></category>
		<category><![CDATA[Make]]></category>
		<category><![CDATA[Makefile]]></category>
		<category><![CDATA[Opensource]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[prometheus]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[RussCox]]></category>
		<category><![CDATA[terraform]]></category>
		<category><![CDATA[TinyGo]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[云计算]]></category>
		<category><![CDATA[人工智能]]></category>
		<category><![CDATA[开源]]></category>
		<category><![CDATA[机器学习]]></category>

		<guid isPermaLink="false">https://tonybai.com/?p=2820</guid>
		<description><![CDATA[本文翻译自Go官方博客上Russ Cox代表Go核心团队发表的“Go Turns 10&#8243;一文。 生日快乐，Go！ 这个周末，我们庆祝Go正式对外发布10周年，即Go作为开源编程语言和构建现代网络软件生态系统的10周年诞辰。 为了纪念这一时刻，Go gopher的创建者Renee French(用下面的新作)描绘了这个令人愉快的场景： 庆祝Go十周年让我回想起2009年11月上旬，那时我们正准备与世界分享Go。我们不知道会发生什么样的反应，是否有人会关心这种新生的小语言。我希望即使没有人最终使用Go，我们也至少会引起人们对一些好的想法的关注，尤其是Go的并发和接口，这些想法可能会影响后续语言。 当看到人们对Go感到兴奋，我便查看了C、C++、Perl、Python和Ruby等流行语言的历史，并研究了每种语言花了多长时间才被广泛采用。例如，在我看来，Perl在1990年代中后期就已经完全形成了，带有CGI脚本和Web，但它于1987年首次发布。这种模式在我所研究的几乎所有语言中都重现了：在新语言真正腾飞之前，需要大约十年的时间进行安静、稳定的改进和传播。 (当时的)我想知道：十年后的Go会在哪里？ 今天，我们可以回答这个问题：Go无处不在，全世界至少有100万开发人员在使用它。 Go最初的目标是网络系统基础架构，现在我们称为云软件(cloud software)。如今，每个主要的云计算平台提供商都使用用Go语言编写的核心云基础架构，例如Docker，Etcdhttps://etcd.io/，Istio，Kubernetes，Prometheus和Terraform。Cloud Native Computing Foundation的大多数项目都是用Go编写的。无数公司也在使用Go将自己的工作迁移到云上，从初创公司从头开始构建到大企业更新软件堆栈。Go还发现对其的采用已经远远超出了最初的云计算目标，其使用范围从使用GoBot和TinyGo控制小型嵌入式系统到使用GRAIL进行大规模的大数据分析和机器学习进行癌症检测，以及介于两者之间的所有内容。 这一切都说明Go超越了我们最疯狂的梦想。Go的成功不仅仅在于语言。这是关于语言，生态系统，尤其是社区的共同努力。 在2009年，该语言是一个不错的主意，并带有一个实现的工作草图。那时候go命令还不存在：我们使用命令6g编译源码和6l链接二进制文件，并借助Makefile实现这个过程的自动化。我们在语句末尾键入分号。整个程序在垃圾回收期间停止，然后努力利用两个CPU核。当时Go只能在Linux和Mac，32位和64位x86和32位ARM上运行。 在过去的十年中，在世界各地的Go开发人员的帮助下，我们已经将这一想法和草图发展为拥有出色的工具，生产级质量实现，先进的垃圾收集器和得到广泛移植的高效语言，Go支持12种操作系统和10种CPU体系结构。 任何编程语言都需要蓬勃发展的生态系统的支持。开源发布是该生态系统的种子，但是自那时以来，许多人贡献了自己的时间和才干，用出色的教程，书籍，课程，博客文章，播客，工具，集成以及可重复使用的、支持go get的Go包来填充Go生态系统。没有这个生态系统的支持，Go永远不可能成功。 当然，生态系统需要蓬勃发展的社区的支持。在2019年，全球有数十个Go（技术）会议，以及超过150个Go聚会组织和90000名参会人员。 GoBridge和Going Who Go通过指导，培训和会议奖学金帮助将新的声音带入Go社区。仅今年一年，他们就在讲习班上向数百名来自传统团体的人们进行了培训，在这些讲习班上，社区成员教导和指导刚接触Go的人。 全球有超过一百万的Go开发人员，全球各地的公司都在寻求雇用更多的人。实际上，人们经常告诉我们，学习Go帮助他们获得了技术行业的第一份工作。最后，我们为Go感到最自豪的不是设计完善的功能或巧妙的代码，而是Go在这么多人的生活中产生的积极影响。我们旨在创建一种可以帮助我们成为更好的开发人员的语言，我们很高兴Go帮助了许多其他人。 恰逢Go开源十周年的时刻，我希望每个人都花一点时间来庆祝Go社区以及我们所取得的一切。我代表Google的整个Go团队，感谢过去十年来加入我们的每个人。让我们开启下一个更加不可思议的十年吧！ 我的网课“Kubernetes实战：高可用集群搭建、配置、运维与应用”在慕课网上线了，感谢小伙伴们学习支持！ 我爱发短信：企业级短信平台定制开发专家 https://tonybai.com/ smspush : 可部署在企业内部的定制化短信平台，三网覆盖，不惧大并发接入，可定制扩展； 短信内容你来定，不再受约束, 接口丰富，支持长短信，签名可选。 著名云主机服务厂商DigitalOcean发布最新的主机计划，入门级Droplet配置升级为：1 core CPU、1G内存、25G高速SSD，价格5$/月。有使用DigitalOcean需求的朋友，可以打开这个链接地址：https://m.do.co/c/bff6eed92687 开启你的DO主机之路。 Gopher Daily(Gopher每日新闻)归档仓库 &#8211; https://github.com/bigwhite/gopherdaily 我的联系方式： 微博：https://weibo.com/bigwhite20xx 微信公众号：iamtonybai 博客：tonybai.com github: https://github.com/bigwhite 微信赞赏： 商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。 &#169; 2019, [...]]]></description>
			<content:encoded><![CDATA[<p>本文翻译自<a href="https://blog.golang.org">Go官方博客</a>上<a href="https://research.swtch.com/">Russ Cox</a>代表Go核心团队发表的<a href="https://blog.golang.org/10years">“Go Turns 10&#8243;</a>一文。</p>
<p><strong>生日快乐，Go！</strong></p>
<p>这个周末，我们庆祝<a href="https://opensource.googleblog.com/2009/11/hey-ho-lets-go.html">Go正式对外发布</a>10周年，即Go作为开源编程语言和构建现代网络软件生态系统的10周年诞辰。</p>
<p>为了纪念这一时刻，<a href="https://blog.golang.org/gopher">Go gopher</a>的创建者<a href="https://twitter.com/reneefrench">Renee French</a>(用下面的新作)描绘了这个令人愉快的场景：</p>
<p><img src="https://tonybai.com/wp-content/uploads/gopher10th-small.jpg" alt="img{512x368}" /></p>
<p>庆祝Go十周年让我回想起2009年11月上旬，那时我们正准备与世界分享Go。我们不知道会发生什么样的反应，是否有人会关心这种新生的小语言。我希望即使没有人最终使用Go，我们也至少会引起人们对一些好的想法的关注，尤其是Go的并发和接口，这些想法可能会<a href="https://tonybai.com/2019/11/04/the-legacy-of-go/">影响后续语言</a>。</p>
<p>当看到人们对Go感到兴奋，我便查看了<a href="https://tonybai.com/tag/c">C</a>、<a href="https://tonybai.com/tag/cpp">C++</a>、Perl、<a href="https://tonybai.com/tag/python">Python</a>和Ruby等流行语言的历史，并研究了每种语言花了多长时间才被广泛采用。例如，在我看来，Perl在1990年代中后期就已经完全形成了，带有CGI脚本和Web，但它于1987年首次发布。这种模式在我所研究的几乎所有语言中都重现了：在新语言真正腾飞之前，需要大约十年的时间进行安静、稳定的改进和传播。</p>
<p>(当时的)我想知道：十年后的Go会在哪里？</p>
<p>今天，我们可以回答这个问题：Go无处不在，全世界<a href="https://research.swtch.com/gophercount">至少有100万开发人员</a>在使用它。</p>
<p>Go最初的目标是网络系统基础架构，现在我们称为云软件(cloud software)。如今，每个主要的云计算平台提供商都使用用Go语言编写的核心云基础架构，例如<a href="https://tonybai.com/tag/docker">Docker</a>，<a href="">Etcd</a>https://etcd.io/，<a href="https://tonybai.com/2018/01/03/an-intro-of-microservices-governance-by-istio/">Istio</a>，<a href="https://coding.imooc.com/class/284.html">Kubernetes</a>，<a href="https://prometheus.io/">Prometheus</a>和<a href="https://www.terraform.io/">Terraform</a>。<a href="https://www.cncf.io/">Cloud Native Computing Foundation</a>的大多数项目都是用Go编写的。无数公司也在使用Go将自己的工作迁移到云上，从初创公司从头开始构建到大企业更新软件堆栈。Go还发现对其的采用已经远远超出了最初的云计算目标，其使用范围从使用<a href="https://gobot.io/">GoBot</a>和<a href="https://tinygo.org/">TinyGo</a>控制小型嵌入式系统到<a href="https://medium.com/grail-eng/bigslice-a-cluster-computing-system-for-go-7e03acd2419b">使用GRAIL进行大规模的大数据分析和机器学习</a>进行癌症检测，以及介于两者之间的所有内容。</p>
<p>这一切都说明Go超越了我们最疯狂的梦想。Go的成功不仅仅在于语言。这是关于语言，生态系统，尤其是社区的共同努力。</p>
<p>在2009年，该语言是一个不错的主意，并带有一个实现的工作草图。那时候go命令还不存在：我们使用命令6g编译源码和6l链接二进制文件，并借助Makefile实现这个过程的自动化。我们在语句末尾键入分号。整个程序在垃圾回收期间停止，然后努力利用两个CPU核。当时Go只能在Linux和Mac，32位和64位x86和32位ARM上运行。</p>
<p>在过去的十年中，在世界各地的Go开发人员的帮助下，我们已经将这一想法和草图发展为拥有出色的工具，生产级质量实现，<a href="https://blog.golang.org/ismmkeynote">先进的垃圾收集器</a>和得到广泛移植的高效语言，Go支持<a href="https://golang.org/doc/install/source#introduction">12种操作系统和10种CPU体系结构</a>。</p>
<p>任何编程语言都需要蓬勃发展的生态系统的支持。开源发布是该生态系统的种子，但是自那时以来，许多人贡献了自己的时间和才干，用出色的教程，书籍，课程，博客文章，播客，工具，集成以及可重复使用的、支持go get的Go包来填充Go生态系统。没有这个生态系统的支持，Go永远不可能成功。</p>
<p>当然，生态系统需要蓬勃发展的社区的支持。在2019年，全球有数十个Go（技术）会议，以及<a href="https://www.meetup.com/pro/go">超过150个Go聚会组织和90000名参会人员</a>。 <a href="https://golangbridge.org/">GoBridge</a>和<a href="https://medium.com/@carolynvs/www-loves-gobridge-ccb26309f667">Going Who Go</a>通过指导，培训和会议奖学金帮助将新的声音带入Go社区。仅今年一年，他们就在讲习班上向数百名来自传统团体的人们进行了培训，在这些讲习班上，社区成员教导和指导刚接触Go的人。</p>
<p>全球有<a href="https://research.swtch.com/gophercount">超过一百万的Go开发人员</a>，全球各地的公司都在寻求雇用更多的人。实际上，人们经常告诉我们，学习Go帮助他们获得了技术行业的第一份工作。最后，我们为Go感到最自豪的不是设计完善的功能或巧妙的代码，而是Go在这么多人的生活中产生的积极影响。我们旨在创建一种可以帮助我们成为更好的开发人员的语言，我们很高兴Go帮助了许多其他人。</p>
<p>恰逢Go开源十周年的时刻，我希望每个人都花一点时间来庆祝Go社区以及我们所取得的一切。我代表Google的整个Go团队，感谢过去十年来加入我们的每个人。让我们开启下一个更加不可思议的十年吧！</p>
<p><img src="https://tonybai.com/wp-content/uploads/gopher10th-pin-small.jpg" alt="img{512x368}" /></p>
<hr />
<p>我的网课“<a href="https://coding.imooc.com/class/284.html">Kubernetes实战：高可用集群搭建、配置、运维与应用</a>”在慕课网上线了，感谢小伙伴们学习支持！</p>
<p><a href="https://tonybai.com/">我爱发短信</a>：企业级短信平台定制开发专家 https://tonybai.com/<br />
smspush : 可部署在企业内部的定制化短信平台，三网覆盖，不惧大并发接入，可定制扩展； 短信内容你来定，不再受约束, 接口丰富，支持长短信，签名可选。</p>
<p>著名云主机服务厂商DigitalOcean发布最新的主机计划，入门级Droplet配置升级为：1 core CPU、1G内存、25G高速SSD，价格5$/月。有使用DigitalOcean需求的朋友，可以打开这个<a href="https://m.do.co/c/bff6eed92687">链接地址</a>：https://m.do.co/c/bff6eed92687 开启你的DO主机之路。</p>
<p>Gopher Daily(Gopher每日新闻)归档仓库 &#8211; https://github.com/bigwhite/gopherdaily</p>
<p>我的联系方式：</p>
<p>微博：https://weibo.com/bigwhite20xx<br />
微信公众号：iamtonybai<br />
博客：tonybai.com<br />
github: https://github.com/bigwhite</p>
<p>微信赞赏：<br />
<img src="https://tonybai.com/wp-content/uploads/wechat-zanshang-code-512x512.jpg" alt="img{512x368}" /></p>
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。</p>
<p style='text-align:left'>&copy; 2019, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2019/11/09/go-opensource-10-years/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Go正走在成为下一个企业级编程语言的轨道上</title>
		<link>https://tonybai.com/2019/05/03/go-is-on-a-trajectory-to-become-the-next-enterprise-programming-language/</link>
		<comments>https://tonybai.com/2019/05/03/go-is-on-a-trajectory-to-become-the-next-enterprise-programming-language/#comments</comments>
		<pubDate>Fri, 03 May 2019 06:01:34 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[ARM]]></category>
		<category><![CDATA[BSD]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Compile]]></category>
		<category><![CDATA[Cpp]]></category>
		<category><![CDATA[CSP]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[error-handling]]></category>
		<category><![CDATA[etcd]]></category>
		<category><![CDATA[Git]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Go2]]></category>
		<category><![CDATA[gofmt]]></category>
		<category><![CDATA[Golang]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[goroutine]]></category>
		<category><![CDATA[hotspot]]></category>
		<category><![CDATA[istio]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[JIT]]></category>
		<category><![CDATA[JVM]]></category>
		<category><![CDATA[KenThompson]]></category>
		<category><![CDATA[Kubernetes]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[macos]]></category>
		<category><![CDATA[OOP]]></category>
		<category><![CDATA[Opensource]]></category>
		<category><![CDATA[Ops]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[reader]]></category>
		<category><![CDATA[RobertGriesemer]]></category>
		<category><![CDATA[RobPike]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[terraform]]></category>
		<category><![CDATA[vendor]]></category>
		<category><![CDATA[vm]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[writer]]></category>
		<category><![CDATA[云计算]]></category>
		<category><![CDATA[企业级]]></category>
		<category><![CDATA[包管理]]></category>
		<category><![CDATA[多核]]></category>
		<category><![CDATA[并发]]></category>
		<category><![CDATA[并行]]></category>
		<category><![CDATA[开源]]></category>
		<category><![CDATA[文档]]></category>
		<category><![CDATA[架构师]]></category>
		<category><![CDATA[注释]]></category>
		<category><![CDATA[维护性]]></category>
		<category><![CDATA[编译]]></category>
		<category><![CDATA[翻译]]></category>
		<category><![CDATA[虚拟机]]></category>
		<category><![CDATA[错误处理]]></category>
		<category><![CDATA[面向对象]]></category>

		<guid isPermaLink="false">https://tonybai.com/?p=2711</guid>
		<description><![CDATA[发展演化了十年的Go语言已经被证明了是云计算时代的首选编程语言，但Go的用武之地显然不局限于此。Kevin Goslar近期在Hacker Noon发表了一篇名为：《Go is on a Trajectory to Become the Next Enterprise Programming Language》的文章，阐述了Go可能成为下一个企业编程语言的理由，这里是那篇文章的中文译文，分享给大家。 摘要 Go是一种专门为大规模软件开发而设计的编程语言。它提供了强大的开发体验并避免了现有编程语言存在的许多问题。这些因素使其成为最有可能在未来替代Java主导企业软件平台的候选者之一。对于那些寻求在未来几十年内构建大规模云基础架构的安全和前瞻性技术的公司和开源计划而言，我建议它们将Go视为其主要的编程语言。Go的优势如下： 基于现实世界的经验 专注于大型工程 专注于可维护性 保持简单明了 使事情显式且明显 很容易学习 仅提供了一种做事方式 支持简单地内置并发 提供面向计算的语言原语 使用OO &#8211; 好的部分 拥有现代化的标准库 强制执行标准化格式 有一个非常快的编译器 使交叉编译变得容易 执行得非常快 需要较小的内存占用 部署规模小 部署完全独立 支持vendor依赖 提供兼容性保证 鼓励提供良好的文档 商业支持的开源 请继续阅读有关上述每个优势点的更多详细信息。然而，在进入Go之前，你应该注意： 不成熟的库 即将到来的改变 没有“硬实时”支持 简介 Go是Google开发的一种编程语言，在过去几年中取得了很大的成功。大部分现代云计算，网络和DevOps平台都是Go语言编写的，例如：Docker、Kubernetes、Terraform、ETCD或istio等。许多公司也将它用于通用软件开发。Go所具备的功能让这些项目吸引了大量用户，而Go的易用性也使得这些项目有了很多的贡献者。 Go的优势来自于简单和经过验证的想法的结合，同时避免了其他语言中出现的许多问题。这篇博客文章概述了Go背后的一些设计原则和工程智慧，并展示它们是如何结合在一起的 &#8211; 它们使Go成为下一代大型软件开发平台的优秀候选者。许多编程语言在个别领域都比较强大，但是在将所有领域都结合起来时，没有其他语言能够如此一致地“得分”，特别是在大型软件工程方面。 基于现实世界的经验 Go是由经验丰富的软件行业资深人士创建的，他们长期以来一直感受到现有语言的缺点带来的痛苦。几十年前，Rob Pike和Ken Thompson在Unix，C和Unicode的发明中发挥了重要作用。在实现了用于JavaScript和Java的V8和HotSpot虚拟机之后，Robert Griesemer在编译器和垃圾收集方面拥有着数十年的经验。在太多次的不得不等待他们的谷歌规模的C++/Java代码库的编译过程的推动下，他们开始着手创建一门新的编程语言，这门语言中凝聚了他们通过编写半个世纪代码过程中所学到的一切。 专注于大型工程 [...]]]></description>
			<content:encoded><![CDATA[<p>发展演化了<a href="https://tonybai.com/2017/09/24/go-ten-years-and-climbing/">十年的Go语言</a>已经被证明了是云计算时代的首选编程语言，但<a href="https://tonybai.com/tag/go">Go</a>的用武之地显然不局限于此。Kevin Goslar近期在<a href="https://hackernoon.com/">Hacker Noon</a>发表了一篇名为：<a href="https://hackernoon.com/go-is-on-a-trajectory-to-become-the-next-enterprise-programming-language-3b75d70544e">《Go is on a Trajectory to Become the Next Enterprise Programming Language》</a>的文章，阐述了Go可能成为下一个企业编程语言的理由，这里是那篇文章的中文译文，分享给大家。</p>
<p><img src="https://tonybai.com/wp-content/uploads/go-enterprise-programming-lang-1.png" alt="img{512x368}" /></p>
<h2>摘要</h2>
<p>Go是一种专门为大规模软件开发而设计的编程语言。它提供了强大的开发体验并避免了现有编程语言存在的许多问题。这些因素使其成为最有可能在未来替代Java主导企业软件平台的候选者之一。对于那些寻求在未来几十年内构建大规模云基础架构的安全和前瞻性技术的公司和开源计划而言，我建议它们将Go视为其主要的编程语言。Go的优势如下：</p>
<ul>
<li>基于现实世界的经验</li>
<li>专注于大型工程</li>
<li>专注于可维护性</li>
<li>保持简单明了</li>
<li>使事情显式且明显</li>
<li>很容易学习</li>
<li>仅提供了一种做事方式</li>
<li>支持简单地内置并发</li>
<li>提供面向计算的语言原语</li>
<li>使用OO &#8211; 好的部分</li>
<li>拥有现代化的标准库</li>
<li>强制执行标准化格式</li>
<li>有一个非常快的编译器</li>
<li>使交叉编译变得容易</li>
<li>执行得非常快</li>
<li>需要较小的内存占用</li>
<li>部署规模小</li>
<li>部署完全独立</li>
<li>支持vendor依赖</li>
<li>提供兼容性保证</li>
<li>鼓励提供良好的文档</li>
<li>商业支持的开源</li>
</ul>
<p>请继续阅读有关上述每个优势点的更多详细信息。然而，在进入Go之前，你应该注意：</p>
<ul>
<li>不成熟的库</li>
<li>即将到来的改变</li>
<li>没有“硬实时”支持</li>
</ul>
<h2>简介</h2>
<p>Go是Google开发的一种编程语言，在过去几年中取得了很大的成功。大部分现代云计算，网络和DevOps平台都是Go语言编写的，例如：<a href="https://tonybai.com/tag/docker">Docker</a>、<a href="https://tonybai.com/tag/kubernetes">Kubernetes</a>、<a href="https://www.terraform.io/">Terraform</a>、<a href="https://coreos.com/etcd/">ETCD</a>或<a href="https://tonybai.com/2018/01/03/an-intro-of-microservices-governance-by-istio">istio</a>等。<a href="https://github.com/golang/go/wiki/GoUsers#united-states">许多公司</a>也将它用于通用软件开发。Go所具备的功能让这些项目吸引了大量用户，而Go的易用性也使得这些项目有了很多的贡献者。</p>
<p>Go的优势来自于简单和经过验证的想法的结合，同时避免了其他语言中出现的许多问题。这篇博客文章概述了Go背后的一些设计原则和工程智慧，并展示它们是如何结合在一起的 &#8211; 它们使Go成为下一代大型软件开发平台的优秀候选者。许多编程语言在个别领域都比较强大，但是在将所有领域都结合起来时，没有其他语言能够如此一致地“得分”，特别是在大型软件工程方面。</p>
<h2>基于现实世界的经验</h2>
<p>Go是由经验丰富的软件行业资深人士创建的，他们长期以来一直感受到现有语言的缺点带来的痛苦。几十年前，<a href="https://en.wikipedia.org/wiki/Rob_Pike">Rob Pike</a>和<a href="https://en.wikipedia.org/wiki/Ken_Thompson">Ken Thompson</a>在Unix，C和Unicode的发明中发挥了重要作用。在实现了用于JavaScript和Java的V8和HotSpot虚拟机之后，<a href="https://github.com/griesemer">Robert Griesemer</a>在编译器和垃圾收集方面拥有着数十年的经验。在太多次的不得不等待他们的谷歌规模的<a href="http://radar.oreilly.com/2012/09/golang.html">C++/Java代码库的编译过程</a>的推动下，他们开始着手创建一门新的编程语言，这门语言中凝聚了他们通过编写半个世纪代码过程中所学到的一切。</p>
<h2>专注于大型工程</h2>
<p>几乎任何编程语言都可以成功构建小型工程项目。当成千上万的开发人员在数十年的持续时间压力下在包含数千万行代码的大量代码库上进行协作时，真正痛苦的问题就会发生。这会导致以下问题：</p>
<ul>
<li>超长的编译时长会中断开发过程</li>
<li>代码库由几个人/团队/部门/公司拥有，混合了不同的编程风格</li>
<li>该公司雇佣了数千名工程师，架构师，测试人员，Ops专家，审计员，实习生等，他们需要了解代码库，但需要具有广泛的编码经验</li>
<li>依赖于许多外部库或运行时，其中一些不再以其最初的形式存在</li>
<li>每行代码在代码库的生命周期内平均被<a href="https://www.ybrikman.com/writing/2018/08/12/the-10-to-1-rule-of-writing-and-programming">重写了10次</a>，留下了疤痕，瑕疵和<a href="https://codeclimate.com/blog/are-you-experiencing-technical-drift">技术偏移</a></li>
<li>文档不完整</li>
</ul>
<p>Go专注于<a href="https://talks.golang.org/2012/splash.article">减轻这些大规模的工程难题</a>，有时是以使小型工程变得更加繁琐为代价，例如在这里和那里需要一些额外的代码。</p>
<h2>专注于可维护性</h2>
<p>Go强调尽可能多地将工作转交到自动代码维护工具中。Go工具链提供了最常用的功能，如格式化代码和自动package导入、查找符号的定义和用法、简单的重构以及代码味道的识别。由于标准化的代码格式化和单一的惯用方式，机器生成的代码更改看起来非常接近Go中人为生成的更改。并而使用类似的模式，使得人和机器的协作更加无缝。</p>
<h2>保持简单直接</h2>
<blockquote>
<p>初级程序员为简单问题创建简单的解决方案。高级程序员为复杂问题创建复杂的解决方案。伟大的程序员找到复杂问题的简单解决方案。-  <a href="http://www.chc-3.com/pub/beautifulsoftware_v10.htm">查尔斯康奈尔</a></p>
</blockquote>
<p>很多人都对Go不包含他们喜欢的其他语言概念感到惊讶。Go确实是一种非常小而简单的语言，只包含最少的正交和经过验证的概念。这鼓励开发人员以最少的认知开销编写最简单的代码，以便许多其他人可以理解并使用它。</p>
<h2>使事情显式而明显</h2>
<blockquote>
<p>良好的代码是显而易见的，避免聪明，模糊的语言功能，扭曲的控制流和间接性。</p>
</blockquote>
<p>许多语言都致力于使编写代码变得高效。然而，在其生命周期中，人们将花费大约（100倍）的时间阅读代码，而不是首先编写所需的代码。例如，审查，理解，调试，更改，重构或重用它。在查看代码时，通常只能看到并理解它的一小部分，通常没有对整个代码库的完整理解。为了解释这一点，Go将一切都显式化了。</p>
<p>一个例子是错误处理。让异常在各个点中断代码并使沿着调用链处理可能会更容易。Go需要<a href="https://tour.golang.org/methods/19">手动处理或返回每个错误</a>。这使得它可以准确地显示代码可以被中断的位置以及如何处理或包装错误。总的来说，这使得错误处理更容易编写，但更容易理解。</p>
<h2>简单易学</h2>
<p>Go非常小而且简单，可以在短短几天内研究整个语言及其基本概念。根据我们的经验，经过不超过一周的培训（与其他语言的以月为单位相比），初学者可以理解Go专家编写的代码，并为此做出贡献。为了方便大量人群，Go网站提供了所需的所有教程和深入的文章。这些教程在浏览器中运行，允许人们在将Go安装到本地计算机上之前学习和使用Go。</p>
<h2>一种做事方式</h2>
<p>Go语言通过个人自我表达赋予团队合作能力。</p>
<p>在Go（和Python）中，所有语言特征都是正交的并且彼此互补，通常做某事只有一种方法。如果您要求10位Python或Go程序员解决问题，您将获得10个相对类似的解决方案。不同的程序员在彼此的代码库中感觉更有家的感觉。在查看其他人的代码时，每分钟的<a href="https://www.osnews.com/story/19266/wtfsm">WTF</a>更少，而且人们的工作更好地融合在一起，从而形成一个人人都为之骄傲并且喜欢工作的一致性。这避免了大规模的工程问题，例如：</p>
<ul>
<li>开发人员将良好的工作代码视为“混乱”，并要求在他们可以使用之前重写它，因为他们不会像原作者那样思考。</li>
<li>不同的团队成员在该语言的不同子集中编写相同代码库的部分内容。</li>
</ul>
<p><img src="https://tonybai.com/wp-content/uploads/go-enterprise-programming-lang-2.jpeg" alt="img{512x368}" /><br />
来源：https：//www.osnews.com/story/19266/wtfsm</p>
<h2>简单，内置并发</h2>
<blockquote>
<p>Go专为现代多核硬件而设计。</p>
</blockquote>
<p>目前使用的大多数编程语言（Java，JavaScript，Python，Ruby，C，C ++）都是在20世纪80年代到2000年代设计的，当时大多数CPU只有一个计算核心。这就是为什么它们本质上是单线程的，并将并行化视为事后增加的边缘情况，通过诸如线程和同步点之类的附加组件实现，这些附加组件既麻烦又难以正确使用。第三方库提供了更简单的并发形式，如Actor模型，但总有多个选项可用，导致语言生态系统碎片化。今天的硬件拥有越来越多的计算内核，软件必须并行化才能在其上高效运行。Go是在多核CPU时代编写的，并且在语言中内置了简单，高级的<a href="https://en.wikipedia.org/wiki/Communicating_sequential_processes">CSP风格</a>的并发特性。</p>
<h2>面向计算的语言原语</h2>
<p>在基础层面上，计算机系统接收数据，处理它（通常经过几个步骤），并输出结果数据。例如，Web服务器从客户端接收HTTP请求，并将其转换为一系列数据库或后端调用。一旦这些调用返回，它就会将接收到的数据转换为HTML或JSON并将其输出给调用者。Go的内置语言原语直接支持这种范例：</p>
<ul>
<li>结构体代表数据</li>
<li>reader和writer代表流式IO</li>
<li>函数处理数据</li>
<li>goroutines提供（几乎无限制的）并发</li>
<li>通道用于管理并发处理步骤之间的数据</li>
</ul>
<p>由于所有计算原语都是由语言以直接的形式提供的，因此Go源代码可以更直接地表达服务器执行的操作。</p>
<h2>OO &#8211; 好的部分</h2>
<p><img src="https://tonybai.com/wp-content/uploads/go-enterprise-programming-lang-3.gif" alt="img{512x368}" /><br />
在基类中改变某些东西的副作用</p>
<p>面向对象非常有用。这几十年OO的应用是富有成效的，并且让我们了解它的哪些部分比其他部分可以更好地扩展。基于这些认知，Go采用面向对象的新方法。它保留了封装和消息传递等优点。Go避免了继承，因为它现在被认为是<a href="https://www.javaworld.com/article/2073649/why-extends-is-evil.html">有害的</a>，Go为组合提供<a href="https://golang.org/doc/effective_go.html#embedding">头等的支持</a>。</p>
<h2>现代标准库</h2>
<p>许多当前使用的编程语言（Java，JavaScript，Python，Ruby）是在互联网成为当今无处不在的计算平台之前设计的。因此，这些语言的标准库仅为未针对现代互联网优化的网络提供相对通用的支持。Go是十年前创建的，当时互联网已经全面展开。Go的标准库允许在没有第三方库的情况下创建更复杂的网络服务。这可以防止使用第三方库的常见问题：</p>
<ul>
<li>碎片化：实现相同功能的总有多种选择</li>
<li>膨胀：库通常实现的不仅仅是它们的用途</li>
<li>依赖地狱：库通常依赖于特定版本的其他库</li>
<li>质量未知：第三方代码可能具有可疑的质量和安全性</li>
<li>未知支持：第三方库的开发可以随时停止</li>
<li>意外更改：第三方库通常不像标准库那样进行严格的版本管理</li>
</ul>
<p>Russ Cox的<a href="https://research.swtch.com/deps">更多背景</a>信息。</p>
<h2>标准化格式</h2>
<blockquote>
<p>Gofmt的风格是没有人喜欢的，但gofmt是每个人的最爱。 &#8211; Rob Pike</p>
</blockquote>
<p>Gofmt是一种以标准化方式格式化Go代码的程序。它不是最漂亮的格式化方式，而是最简单，最不讨厌的方式。标准化的源代码格式化具有惊人的积极影响：</p>
<ul>
<li>重点讨论重要主题：它消除了围绕标签与空格，缩进深度，每行长度，空行，花括号放置等的一系列<a href="https://en.wikipedia.org/wiki/Law_of_triviality">无意义的争论</a>。</li>
<li>开发人员在彼此的代码库中感到宾至如归，因为其他代码看起来很像他们编写的代码。每个人都喜欢自由地按照自己喜欢的方式格式化代码，但如果其他人冒昧地按照他们自己喜欢的方式格式化>代码，那么每个人都讨厌它。</li>
<li>自动代码更改不会弄乱手写代码的格式，例如通过引入意外的空白更改。</li>
</ul>
<p>许多其他语言社区现在正在开发gofmt等价物。当构建为第三方解决方案时，通常会有几种竞争格式标准。例如，JavaScript世界提供<a href="https://prettier.io/">Prettier</a>和<a href="https://standardjs.com/">StandardJS</a>。可以一起使用其中之一或两者。许多JS项目都没有采用它们，因为这是一个额外的决定。Go的格式化程序内置于该语言的标准工具链中，因此只有一个标准，每个人都在使用它。</p>
<h2>快速编译</h2>
<p><img src="https://tonybai.com/wp-content/uploads/go-enterprise-programming-lang-4.png" alt="img{512x368}" /><br />
来源：https://xkcd.com/303</p>
<p>大型代码库的长编译时间是引发Go语言起源的一个微小的原因。Google主要使用C++和Java，与Haskell，Scala或Rust等更复杂的语言相比，它可以相对快速地编译。尽管如此，当编译大型代码库时，即使是少量的慢速也会把人激怒，编译工作流中断导致编译延迟。Go是从头开始设计的，以使编译更有效，因此编译器速度非常快，几乎没有编译延迟。这为Go开发人员提供了类似于脚本语言的即时反馈，并具有静态类型检查的额外好处。</p>
<h2>交叉编译</h2>
<p>由于语言运行时非常简单，因此它已被移植到许多平台，如macOS，Linux，Windows，BSD，ARM等。Go可以开箱即用于编译所有这些平台的二进制文件。这使得我们可以轻松地从一台机器来进行部署。</p>
<h2>快速执行</h2>
<p>Go有着接近C的速度。与JITed(即时编译)语言（Java，JavaScript，Python等）不同，Go二进制文件不需要启动或预热时间，因为它们作为已编译和完全优化的本机代码提供。Go垃圾收集器仅以<a href="https://twitter.com/brianhatfield/status/804355831080751104">微秒</a>的指令引入可忽略的暂停。在其快速的单核性能上面，Go使得利用所有的CPU内核<a href="https://tour.golang.org/concurrency/1">更容易</a>。</p>
<h2>小内存占用</h2>
<p>像JVM，Python或Node这样的运行时不仅仅在运行时加载程序代码。它们还会加载大型且高度复杂的基础架构，以便在每次运行时编译和优化程序。这使得它们的启动时间变慢并导致它们使用大量（数百MB）的RAM。Go进程的开销较小，因为它们已经完全编译和优化，只需要运行。Go还以<a href="https://dave.cheney.net/2014/06/07/five-things-that-make-go-fast">非常节省内存的方式存储数据</a>。这在内存有限且昂贵的云环境中以及在开发期间非常重要，在开发期间我们希望在单个机器上快速启动整个堆栈，同时为其他软件留下内存。</p>
<h2>小部署规模</h2>
<p>Go二进制文件的大小非常简洁。Go应用程序的Docker镜像通常比用Java或Node编写的等效文件<a href="https://derickbailey.com/2017/03/09/selecting-a-node-js-image-for-docker">小10倍</a>，因为它不需要包含编译器，JIT，并且需要更少的运行时基础结构。这在部署大型应用程序时很重要。想象一下，将一个简单的应用程序部署到100个生产服务器上 使用Node / JVM时，我们的docker仓库必须提供100个docker镜像@ 200 MB = 20 GB(总共)。这需要镜像仓库耗费一些时间来服务。想象一下，我们希望每天部署100次。使用Go服务时，Docker镜像仓库只需提供100个Docker镜像@ 20 MB = 2 GB。可以更快，更频繁地部署大型Go应用程序，从而允许重要更新更快地实现生产。</p>
<h2>自包含部署</h2>
<p>Go应用程序部署为包含所有依赖项的单个可执行文件。不需要安装特定版本的JVM，Node或Python运行时。不必将库下载到生产服务器上。不需要对运行Go二进制文件的机器进行任何更改。甚至不需要将Go二进制文件包装到Docker中来共享它们。您只需将Go二进制文件拖放到服务器上，无论该服务器上运行的是什么，它都会在那里运行。上述描述的唯一例外是使用net和os/user包时的动态链接glibc库时。</p>
<h2>vendor依赖关系</h2>
<p>Go故意避免使用第三方库的中央存储库。Go应用程序直接链接到相应的Git存储库，并将所有相关代码下载（vendor保存）到他们自己的代码库中。这有很多好处：</p>
<ul>
<li>我们可以在使用之前查看，分析和测试第三方代码。此代码与我们自己的代码一样，是我们应用程序的一部分，应符合相同的质量，安全性和可靠性标准。</li>
<li>无需永久访问存储依赖项的各个位置。可以一次性的从任何地方（包括私人Git仓库）获取您的第三方库，并永久拥有它们。</li>
<li>在checkout后编译代码库不需要进一步下载依赖项。</li>
<li>如果互联网上某处的代码存储库突然提供不同的代码，也不会造成surprises。</li>
<li>即使软件包存储库服务性能变慢或托管软件包不再存在，部署也不会中断。</li>
</ul>
<h2>兼容性保证</h2>
<p>Go团队<a href="https://golang.org/doc/go1compat">承诺</a>，现有的程序将继续适用于新版本语言。这使得即使是大型项目也可以轻松升级到更新编译器的版本，并从新版本带来的许多性能和安全性改进中受益。同时，由于Go二进制文件包含了他们需要的所有依赖项，因此可以在同一服务器计算机上并行运行使用不同版本的Go编译器编译的二进制文件，而无需进行复杂的设置多个版本的运行时或虚拟化。</p>
<h2>文档</h2>
<p>在大型工程中，文档对于使软件易于访问和维护非常重要。与其他功能类似，Go中的文档简单实用：</p>
<ul>
<li>它嵌入在源代码中，因此两者可以同时维护。</li>
<li>它不需要特殊的语法 &#8211; 文档只是普通的源代码注释。</li>
<li>可运行的单元测试通常是最好的文档形式，所以Go允许你将它们<a href="https://blog.golang.org/examples">嵌入到文档中</a>。</li>
<li>所有文档<a href="https://blog.golang.org/godoc-documenting-go-code">实用程序</a>都内置在工具链中，因此每个人都使用它们。</li>
<li>Go linter需要导出元素的文档，以防止“文档债务”的积累。</li>
</ul>
<h2>商业支持的开源</h2>
<p>当商业实体在公开场合发展时，一些最流行和最全面设计的软件就会发生。这种设置结合了商业软件开发的优势 &#8211; 一致性和优化，使系统健壮，可靠，高效 &#8211; 具有开放式开发的优势，如来自许多行业的广泛支持，来自多个大型实体和许多用户的支持，以及长期支持，即使商业支持停止。Go就是这样开发的。</p>
<h2>缺点</h2>
<p>当然，Go并不完美，每种技术选择总是有利有弊。在进入Go之前，这里有一小部分需要考虑的方面。</p>
<h2>未成熟</h2>
<p>虽然Go的标准库在<a href="https://blog.golang.org/h2push">支持HTTP/2服务器推送</a>等许多新概念方面处于行业领先地位，但与JVM生态系统中存在的相比，用于外部API的第三方Go库可能还不那么成熟。</p>
<h2>即将到来的变化</h2>
<p>Go团队知道几乎不可能改变现有的语言元素，因此只有在完全开发后才会添加新功能。在经历了10年稳定的故意阶段后，Go团队正在考虑对语言进行<a href="https://blog.golang.org/go2draft">一系列更大的改进</a>，作为Go 2.0之旅的一部分。</p>
<h2>没有硬实时</h2>
<p>虽然Go的垃圾收集器只引入了非常短的中断，但支持硬实时需要没有垃圾收集的技术，例如Rust。</p>
<h2>结论</h2>
<p>这篇博客文章给出了一些明智的背景知识，但往往没有那么明显的选择进入Go的设计，以及当他们的代码库和团队成数量级增长时，他们将如何从许多痛苦中拯救大型工程项目。总的来说，他们将Go定位为寻求Java之外的现代编程语言的大型开发项目的绝佳选择。</p>
<hr />
<p>我的网课“<a href="https://coding.imooc.com/class/284.html">Kubernetes实战：高可用集群搭建、配置、运维与应用</a>”在慕课网上线了，感谢小伙伴们学习支持！</p>
<p><a href="https://tonybai.com/">我爱发短信</a>：企业级短信平台定制开发专家 https://tonybai.com/<br />
smspush : 可部署在企业内部的定制化短信平台，三网覆盖，不惧大并发接入，可定制扩展； 短信内容你来定，不再受约束, 接口丰富，支持长短信，签名可选。</p>
<p>著名云主机服务厂商DigitalOcean发布最新的主机计划，入门级Droplet配置升级为：1 core CPU、1G内存、25G高速SSD，价格5$/月。有使用DigitalOcean需求的朋友，可以打开这个<a href="https://m.do.co/c/bff6eed92687">链接地址</a>：https://m.do.co/c/bff6eed92687 开启你的DO主机之路。</p>
<p>我的联系方式：</p>
<p>微博：https://weibo.com/bigwhite20xx<br />
微信公众号：iamtonybai<br />
博客：tonybai.com<br />
github: https://github.com/bigwhite</p>
<p>微信赞赏：<br />
<img src="https://tonybai.com/wp-content/uploads/wechat-zanshang-code-512x512.jpg" alt="img{512x368}" /></p>
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。</p>
<p style='text-align:left'>&copy; 2019, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2019/05/03/go-is-on-a-trajectory-to-become-the-next-enterprise-programming-language/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>使用nomad实现集群管理和微服务部署调度</title>
		<link>https://tonybai.com/2019/03/30/cluster-management-and-microservice-deployment-and-scheduled-by-nomad/</link>
		<comments>https://tonybai.com/2019/03/30/cluster-management-and-microservice-deployment-and-scheduled-by-nomad/#comments</comments>
		<pubDate>Sat, 30 Mar 2019 11:21:09 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[cloud-native]]></category>
		<category><![CDATA[consul]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[DaemonSet]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[dig]]></category>
		<category><![CDATA[DNS]]></category>
		<category><![CDATA[eBay]]></category>
		<category><![CDATA[fabio]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Golang]]></category>
		<category><![CDATA[group]]></category>
		<category><![CDATA[hashicorp]]></category>
		<category><![CDATA[hcl]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[https]]></category>
		<category><![CDATA[imooc]]></category>
		<category><![CDATA[istio]]></category>
		<category><![CDATA[job]]></category>
		<category><![CDATA[k8s]]></category>
		<category><![CDATA[kubeadm]]></category>
		<category><![CDATA[Kubernetes]]></category>
		<category><![CDATA[loadbalance]]></category>
		<category><![CDATA[nomad]]></category>
		<category><![CDATA[pod]]></category>
		<category><![CDATA[Scheduler]]></category>
		<category><![CDATA[Service]]></category>
		<category><![CDATA[ServiceMesh]]></category>
		<category><![CDATA[sni]]></category>
		<category><![CDATA[SSL]]></category>
		<category><![CDATA[task]]></category>
		<category><![CDATA[TLS]]></category>
		<category><![CDATA[Trace]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[vault]]></category>
		<category><![CDATA[weave]]></category>
		<category><![CDATA[云原生]]></category>
		<category><![CDATA[容器]]></category>
		<category><![CDATA[微服务]]></category>
		<category><![CDATA[慕课网]]></category>
		<category><![CDATA[服务网格]]></category>
		<category><![CDATA[滚动升级]]></category>
		<category><![CDATA[蓝绿]]></category>
		<category><![CDATA[调度器]]></category>
		<category><![CDATA[负载均衡]]></category>
		<category><![CDATA[金丝雀]]></category>
		<category><![CDATA[集群]]></category>

		<guid isPermaLink="false">https://tonybai.com/?p=2689</guid>
		<description><![CDATA[在“云原生”、“容器化”、“微服务”、“服务网格”等概念大行其道的今天，一提到集群管理、容器工作负载调度，人们首先想到的是Kubernetes。 Kubernetes经过多年的发展，目前已经成为了云原生计算平台的事实标准，得到了诸如谷歌、微软、红帽、亚马逊、IBM、阿里等大厂的大力支持，各大云计算提供商也都提供了专属Kubernetes集群服务。开发人员可以一键在这些大厂的云上创建k8s集群。对于那些不愿被cloud provider绑定的组织或开发人员，Kubernetes也提供了诸如Kubeadm这样的k8s集群引导工具，帮助大家在裸金属机器上搭建自己的k8s集群，当然这样做的门槛较高（如果您想学习自己搭建和管理k8s集群，可以参考我在慕课网上发布的实战课《高可用集群搭建、配置、运维与应用》）。 Kubernetes的学习曲线是公认的较高，尤其是对于应用开发人员。再加上Kubernetes发展很快，越来越多的概念和功能加入到k8s技术栈，这让人们不得不考虑建立和维护这样一套集群所要付出的成本。人们也在考虑是否所有场景都需要部署一个k8s集群，是否有轻量级的且能满足自身需求的集群管理和微服务部署调度方案呢？外国朋友Matthias Endler就在其文章《也许你不需要Kubernetes》中给出一个轻量级的集群管理方案 &#8211; 使用hashicorp开源的nomad工具。 这让我想起了去年写的《基于consul实现微服务的服务发现和负载均衡》一文。文中虽然实现了基于consul的服务注册、发现以及负载均衡，但是缺少一个环节：那就是整个集群管理以及工作负载部署调度自动化的缺乏。nomad应该恰好可以补足这一短板，并且它足够轻量。本文我们就来探索和实践一下使用nomad实现集群管理和微服务部署调度。 一. 安装nomad集群 nomad是Hashicorp公司出品的集群管理和工作负荷调度器，支持多种驱动形式的工作负载调度，包括Docker容器、虚拟机、原生可执行程序等，并支持跨数据中心调度。Nomad不负责服务发现或密钥管理等 ，它将这些功能分别留给了HashiCorp的Consul和Vault。HashiCorp的创始人认为，这会使得Nomad更为轻量级，调度性能更高。 nomad使用Go语言实现，因此其本身仅仅是一个可执行的二进制文件。和Hashicorp其他工具产品(诸如：consul等)类似，nomad一个可执行文件既可以以server模式运行，亦可以client模式运行，甚至可以启动一个实例，既是server，也是client。 下面是nomad集群的架构图(来自hashicorp官方）: 一个nomad集群至少要包含一个server，作为集群的控制平面；一个或多个client则用于承载工作负荷。通常生产环境nomad集群的控制平面至少要有5个及以上的server才能在高可用上有一定保证。 建立一个nomad集群有多种方法，包括手工建立、基于consul自动建立和基于云自动建立。考虑到后续涉及微服务的注册发现，这里我们采用基于consul自动建立nomad集群的方法，下面是部署示意图： 我这里的试验环境仅有三台hosts，因此这三台host既承载consul集群，也承载nomad集群（包括server和client），即nomad的控制平面和工作负荷由这三台host一并承担了。 1. consul集群启动 在之前的《基于consul实现微服务的服务发现和负载均衡》一文中，我对consul集群的建立做过详细地说明，因此这里只列出步骤，不详细解释了。注意：这次consul的版本升级到了consul v1.4.4了。 在每个node上分别下载consul 1.4.4： # wget -c https://releases.hashicorp.com/consul/1.4.4/consul_1.4.4_linux_amd64.zip # unzip consul_1.4.4_linux_amd64.zip # cp consul /usr/local/bin # consul -v Consul v1.4.4 Protocol 2 spoken by default, understands 2 to 3 (agent will automatically use protocol &#62;2 when [...]]]></description>
			<content:encoded><![CDATA[<p>在<a href="https://www.cncf.io/">“云原生”</a>、<a href="https://tonybai.com/tag/docker">“容器化”</a>、<a href="https://en.wikipedia.org/wiki/Microservices">“微服务”</a>、<a href="https://tonybai.com/2018/01/03/an-intro-of-microservices-governance-by-istio/">“服务网格”</a>等概念大行其道的今天，一提到集群管理、容器工作负载调度，人们首先想到的是<a href="https://tonybai.com/tag/kubernetes">Kubernetes</a>。</p>
<p><a href="https://kubernetes.io/">Kubernetes</a>经过多年的发展，目前已经成为了云原生计算平台的事实标准，得到了诸如谷歌、微软、红帽、亚马逊、IBM、阿里等大厂的大力支持，各大云计算提供商也都提供了专属Kubernetes集群服务。开发人员可以<strong>一键</strong>在这些大厂的云上<a href="https://tonybai.com/2017/05/15/setup-a-ha-kubernetes-cluster-based-on-kubeadm-part1/">创建k8s集群</a>。对于那些不愿被cloud provider绑定的组织或开发人员，Kubernetes也提供了诸如<a href="https://tonybai.com/2017/05/15/setup-a-ha-kubernetes-cluster-based-on-kubeadm-part1/">Kubeadm</a>这样的k8s集群引导工具，帮助大家在裸金属机器上<a href="https://tonybai.com/2018/10/17/imooc-course-kubernetes-practice-go-online/">搭建自己的k8s集群</a>，当然这样做的门槛较高（如果您想学习自己搭建和管理k8s集群，可以参考我在<a href="https://www.imooc.com/">慕课网</a>上发布的实战课<a href="https://coding.imooc.com/class/284.html">《高可用集群搭建、配置、运维与应用》</a>）。</p>
<p>Kubernetes的学习曲线是公认的较高，尤其是对于应用开发人员。再加上Kubernetes发展很快，越来越多的概念和功能加入到k8s技术栈，这让人们不得不考虑建立和维护这样一套集群所要付出的成本。人们也在考虑是否所有场景都需要部署一个k8s集群，是否有轻量级的且能满足自身需求的集群管理和微服务部署调度方案呢？外国朋友Matthias Endler就在其文章<a href="https://matthias-endler.de/2019/maybe-you-dont-need-kubernetes/">《也许你不需要Kubernetes》</a>中给出一个轻量级的集群管理方案 &#8211; 使用<a href="https://www.hashicorp.com/">hashicorp</a>开源的<a href="https://github.com/hashicorp/nomad">nomad工具</a>。</p>
<p>这让我想起了去年写的<a href="https://tonybai.com/2018/09/10/setup-service-discovery-and-load-balance-based-on-consul/">《基于consul实现微服务的服务发现和负载均衡》</a>一文。文中虽然实现了基于<a href="https://tonybai.com/2015/07/06/implement-distributed-services-registery-and-discovery-by-consul/">consul</a>的服务注册、发现以及负载均衡，但是缺少一个环节：那就是整个集群管理以及工作负载部署调度自动化的缺乏。nomad应该恰好可以补足这一短板，并且它足够轻量。本文我们就来探索和实践一下使用<a href="https://github.com/hashicorp/nomad">nomad</a>实现集群管理和微服务部署调度。</p>
<h2>一. 安装nomad集群</h2>
<p>nomad是Hashicorp公司出品的集群管理和工作负荷调度器，支持多种驱动形式的工作负载调度，包括<a href="https://tonybai.com/tag/docker">Docker容器</a>、虚拟机、原生可执行程序等，并支持跨数据中心调度。Nomad不负责服务发现或密钥管理等 ，它将这些功能分别留给了HashiCorp的<a href="https://tonybai.com/tag/consul">Consul</a>和<a href="https://github.com/hashicorp/vault">Vault</a>。HashiCorp的创始人认为，这会使得Nomad更为轻量级，调度性能更高。</p>
<p>nomad使用<a href="https://tonybai.com/tag/golang">Go语言</a>实现，因此其本身仅仅是一个可执行的二进制文件。和Hashicorp其他工具产品(诸如：consul等)类似，nomad一个可执行文件既可以以server模式运行，亦可以client模式运行，甚至可以启动一个实例，既是server，也是client。</p>
<p>下面是nomad集群的架构图(来自hashicorp官方）:</p>
<p><img src="https://tonybai.com/wp-content/uploads/nomad-arch.png" alt="img{512x368}" /></p>
<p>一个nomad集群至少要包含一个server，作为集群的控制平面；一个或多个client则用于承载工作负荷。通常生产环境nomad集群的控制平面至少要有5个及以上的server才能在高可用上有一定保证。</p>
<p>建立一个nomad集群有多种方法，包括手工建立、基于consul自动建立和基于云自动建立。考虑到后续涉及微服务的注册发现，这里我们采用基于consul自动建立nomad集群的方法，下面是部署示意图：</p>
<p><img src="https://tonybai.com/wp-content/uploads/nomad-cluster-bootstrap-from-consul-cluster-on-ubuntu-hosts.png" alt="img{512x368}" /></p>
<p>我这里的试验环境仅有三台hosts，因此这三台host既承载consul集群，也承载nomad集群（包括server和client），即nomad的控制平面和工作负荷由这三台host一并承担了。</p>
<h3>1. consul集群启动</h3>
<p>在之前的<a href="https://tonybai.com/2018/09/10/setup-service-discovery-and-load-balance-based-on-consul/">《基于consul实现微服务的服务发现和负载均衡》</a>一文中，我对consul集群的建立做过详细地说明，因此这里只列出步骤，不详细解释了。注意：这次consul的版本升级到了consul v1.4.4了。</p>
<p>在每个node上分别下载consul 1.4.4：</p>
<pre><code># wget -c https://releases.hashicorp.com/consul/1.4.4/consul_1.4.4_linux_amd64.zip
# unzip consul_1.4.4_linux_amd64.zip

# cp consul /usr/local/bin

# consul -v

Consul v1.4.4
Protocol 2 spoken by default, understands 2 to 3 (agent will automatically use protocol &gt;2 when speaking to compatible agents)

</code></pre>
<p>启动consul集群：(每个node上创建~/.bin/consul-install目录，并进入该目录下执行)</p>
<pre><code>dxnode1:

# nohup consul agent -server -ui -dns-port=53 -bootstrap-expect=3 -data-dir=~/.bin/consul-install/consul-data -node=consul-1 -client=0.0.0.0 -bind=172.16.66.102 -datacenter=dc1 &gt; consul-1.log &amp; 2&gt;&amp;1

dxnode2:

# nohup consul agent -server -ui -dns-port=53  -bootstrap-expect=3 -data-dir=/root/consul-install/consul-data -node=consul-2 -client=0.0.0.0 -bind=172.16.66.103 -datacenter=dc1 -join 172.16.66.102 &gt; consul-2.log &amp; 2&gt;&amp;1

dxnode3:

nohup consul agent -server -ui -dns-port=53  -bootstrap-expect=3 -data-dir=/root/consul-install/consul-data -node=consul-3 -client=0.0.0.0 -bind=172.16.66.104 -datacenter=dc1 -join 172.16.66.102 &gt; consul-3.log &amp; 2&gt;&amp;1

</code></pre>
<p>consul集群启动结果查看如下：</p>
<pre><code># consul members
Node      Address             Status  Type    Build  Protocol  DC   Segment
consul-1  172.16.66.102:8301  alive   server  1.4.4  2         dc1  &lt;all&gt;
consul-2  172.16.66.103:8301  alive   server  1.4.4  2         dc1  &lt;all&gt;
consul-3  172.16.66.104:8301  alive   server  1.4.4  2         dc1  &lt;all&gt;

# consul operator raft list-peers
Node      ID                                    Address             State     Voter  RaftProtocol
consul-3  d048e55b-5f6a-34a4-784c-e6607db0e89e  172.16.66.104:8300  leader    true   3
consul-1  160a7a20-f177-d2f5-0765-e6d1a9a1a9a4  172.16.66.102:8300  follower  true   3
consul-2  6795cd2c-fad5-9d4f-2531-13b0a65e0893  172.16.66.103:8300  follower  true   3

</code></pre>
<h3>2. DNS设置（可选）</h3>
<p>如果采用基于consul DNS的方式进行服务发现，那么在每个<strong>nomad client node</strong>上设置DNS则很必要。否则如果要是基于consul service catalog的API去查找service，则可忽略这个步骤。设置步骤如下：</p>
<p>在每个node上，创建和编辑/etc/resolvconf/resolv.conf.d/base，填入如下内容：</p>
<pre><code>nameserver {consul-1-ip}
nameserver {consul-2-ip}

</code></pre>
<p>然后重启resolvconf服务:</p>
<pre><code>#  /etc/init.d/resolvconf restart
[ ok ] Restarting resolvconf (via systemctl): resolvconf.service.

</code></pre>
<p>新的resolv.conf将变成：</p>
<pre><code># cat /etc/resolv.conf
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver {consul-1-ip}
nameserver {consul-2-ip}
nameserver 100.100.2.136
nameserver 100.100.2.138
options timeout:2 attempts:3 rotate single-request-reopen

</code></pre>
<p>这样无论是在host上，还是在新启动的container里就都可以访问到xx.xx.consul域名的服务了：</p>
<pre><code># ping -c 3 consul.service.dc1.consul
PING consul.service.dc1.consul (172.16.66.103) 56(84) bytes of data.
64 bytes from 172.16.66.103: icmp_seq=1 ttl=64 time=0.227 ms
64 bytes from 172.16.66.103: icmp_seq=2 ttl=64 time=0.158 ms
^C
--- consul.service.dc1.consul ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.158/0.192/0.227/0.037 ms

# docker run busybox ping -c 3 consul.service.dc1.consul

PING consul.service.dc1.consul (172.16.66.104): 56 data bytes
64 bytes from 172.16.66.104: seq=0 ttl=64 time=0.067 ms
64 bytes from 172.16.66.104: seq=1 ttl=64 time=0.061 ms
64 bytes from 172.16.66.104: seq=2 ttl=64 time=0.076 ms

--- consul.service.dc1.consul ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.061/0.068/0.076 ms

</code></pre>
<h3>3. 基于consul集群引导启动nomad集群</h3>
<p>按照之前的拓扑图，我们需先在每个node上分别下载nomad：</p>
<pre><code># wget -c https://releases.hashicorp.com/nomad/0.8.7/nomad_0.8.7_linux_amd64.zip

# unzip nomad_0.8.7_linux_amd64.zip.zip

# cp ./nomad /usr/local/bin

# nomad -v

Nomad v0.8.7 (21a2d93eecf018ad2209a5eab6aae6c359267933+CHANGES)

</code></pre>
<p>我们已经建立了consul集群，因为我们将采用<a href="https://www.nomadproject.io/guides/operations/cluster/automatic.html">基于consul集群引导启动nomad集群</a>这一创建nomad集群的最Easy方式。同时，我们每个node上既要运行nomad server，也要nomad client，于是我们在nomad的配置文件中，对server和client都设置为”enabled = true”。下面是nomad启动的配置文件，每个node上的nomad均将该配置文件作为为输入：</p>
<pre><code>// agent.hcl

data_dir = "/root/.bin/nomad-install/nomad.d"

server {
  enabled = true
  bootstrap_expect = 3
}

client {
  enabled = true
}

</code></pre>
<p>下面是在各个节点上启动nomad的操作步骤：</p>
<pre><code>dxnode1:

# nohup nomad agent -config=/root/.bin/nomad-install/agent.hcl  &gt; nomad-1.log &amp; 2&gt;&amp;1

dxnode2:

# nohup nomad agent -config=/root/.bin/nomad-install/agent.hcl  &gt; nomad-2.log &amp; 2&gt;&amp;1

dxnode3:

# nohup nomad agent -config=/root/.bin/nomad-install/agent.hcl  &gt; nomad-3.log &amp; 2&gt;&amp;1

</code></pre>
<p>查看nomad集群的启动结果：</p>
<pre><code>#  nomad server members
Name            Address        Port  Status  Leader  Protocol  Build  Datacenter  Region
dxnode1.global  172.16.66.102  4648  alive   true    2         0.8.7  dc1         global
dxnode2.global  172.16.66.103  4648  alive   false   2         0.8.7  dc1         global
dxnode3.global  172.16.66.104  4648  alive   false   2         0.8.7  dc1         global

# nomad operator raft list-peers

Node            ID                  Address             State     Voter  RaftProtocol
dxnode1.global  172.16.66.102:4647  172.16.66.102:4647  leader    true   2
dxnode2.global  172.16.66.103:4647  172.16.66.103:4647  follower  true   2
dxnode3.global  172.16.66.104:4647  172.16.66.104:4647  follower  true   2

# nomad node-status
ID        DC   Name     Class   Drain  Eligibility  Status
7acdd7bc  dc1  dxnode1  &lt;none&gt;  false  eligible     ready
c281658a  dc1  dxnode3  &lt;none&gt;  false  eligible     ready
9e3ef19f  dc1  dxnode2  &lt;none&gt;  false  eligible     ready

</code></pre>
<p>以上这些命令的结果都显示nomad集群工作正常！</p>
<p>nomad还提供一个ui界面（http://nomad-node-ip:4646/ui），可以让运维人员以可视化的方式直观看到当前nomad集群的状态，包括server、clients、工作负载(job)的情况：</p>
<p><img src="https://tonybai.com/wp-content/uploads/nomad-ui.png" alt="img{512x368}" /></p>
<p>nomad ui首页</p>
<p><img src="https://tonybai.com/wp-content/uploads/nomad-ui-servers.png" alt="img{512x368}" /></p>
<p>nomad server列表和状态</p>
<p><img src="https://tonybai.com/wp-content/uploads/nomad-ui-clients.png" alt="img{512x368}" /></p>
<p>nomad client列表和状态</p>
<h2>二. 部署工作负载</h2>
<p>引导启动成功nomad集群后，我们接下来就要向集群中添加“工作负载”了。</p>
<p>在<a href="https://coding.imooc.com/class/284.html">Kubernetes</a>中，我们可以通过创建deployment、pod等向集群添加工作负载；在nomad中我们也可以通过类似的声明式的方法向nomad集群添加工作负载。不过nomad相对简单许多，它<strong>仅提供了一种</strong>名为job的抽象，并给出了<a href="https://www.nomadproject.io/docs/job-specification/index.html">job的specification</a>。nomad集群所有关于工作负载的操作均通过job描述文件和nomad job相关子命令完成。下面是通过job部署工作负载的流程示意图：</p>
<p><img src="https://tonybai.com/wp-content/uploads/nomad-job-workflow.png" alt="img{512x368}" /></p>
<p>从图中可以看到，我们需要做的仅仅是将编写好的job文件提交给nomad即可。</p>
<p>Job spec定义了：job -> group -> task的层次关系。每个job文件只有一个job，但是一个job可能有多个group，每个group可能有多个task。group包含一组要放在同一个集群中调度的task。一个Nomad task是由其驱动程序（driver）在Nomad client节点上执行的命令、服务、应用程序或其他工作负载。task可以是短时间的批处理作业（batch）或长时间运行的服务(service)，例如web应用程序、数据库服务器或API。</p>
<p>Tasks是在用<a href="https://github.com/hashicorp/hcl">HCL语法</a>的声明性job规范中定义的。Job文件提交给Nomad服务端，服务端决定在何处以及如何将job文件中定义的task分配给客户端节点。另一种概念化的理解是:job规范表示工作负载的期望状态，Nomad服务端创建并维护其实际状态。</p>
<p>通过job，开发人员还可以为工作负载定义约束和资源。约束（constraint）通过内核类型和版本等属性限制了工作负载在节点上的位置。资源（resources）需求包括运行task所需的内存、网络、CPU等。</p>
<p>有三种类型的job：system、service和batch，它们决定Nomad将用于此job中task的调度器。service 调度器被设计用来调度永远不会宕机的长寿命服务。batch作业对短期性能波动的敏感性要小得多，寿命也很短，几分钟到几天就可以完成。system调度器用于注册应该在满足作业约束的所有nomad client上运行的作业。当某个client加入到nomad集群或转换到就绪状态时也会调用它。</p>
<p>Nomad允许job作者为自动重新启动失败和无响应的任务指定策略，并自动将失败的任务重新调度到其他节点，从而使任务工作负载具有弹性。</p>
<p>如果对应到k8s中的概念，group更像是某种controller，而task更类似于pod，是被真实调度的实体。Job spec对应某个k8s api object的spec，具体体现在某个yaml文件中。</p>
<p>下面我们就来真实地在nomad集群中创建一个工作负载。我们使用之前在<a href="https://tonybai.com/2018/09/10/setup-service-discovery-and-load-balance-based-on-consul/">《基于consul实现微服务的服务发现和负载均衡》</a>一文中使用过的那几个demo image，这里我们先使用<a href="https://hub.docker.com/r/bigwhite/httpbackendservice">httpbackendservice镜像</a>来创建一个job。</p>
<p>下面是httpbackend的job文件：</p>
<pre><code>// httpbackend-1.nomad

job "httpbackend" {
  datacenters = ["dc1"]
  type = "service"

  group "httpbackend" {
    count = 2

    task "httpbackend" {
      driver = "docker"
      config {
        image = "bigwhite/httpbackendservice:v1.0.0"
        port_map {
          http = 8081
        }
        logging {
          type = "json-file"
        }
      }

      resources {
        network {
          mbits = 10
          port "http" {}
        }
      }

      service {
        name = "httpbackend"
        port = "http"
      }
    }
  }
}

</code></pre>
<p>这个文件基本都是自解释的，重点提几个地方：</p>
<ul>
<li>
<p>job type: service ： 说明该job创建和调度的是一个service类型的工作负载；</p>
</li>
<li>
<p>count = 2 ： 类似于k8s的replicas字段，期望在nomad集群中运行2个httpbackend服务实例，nomad来保证始终处于期望状态。</p>
</li>
<li>
<p>关于port：port_map指定了task中容器的监听端口。network中的port “http” {}没有指定静态IP，因此将采用动态主机端口。service中的port则指明使用”http”这个tag的动态主机端口。这和k8s中service中port使用名称匹配的方式映射到具体pod中的port的方法类似。</p>
</li>
</ul>
<p>我们使用nomad job子命令来创建该工作负载。正式创建之前，我们可以先通过nomad job plan来dry-run一下，一是看job文件格式是否ok；二来检查一下nomad集群是否有空余资源创建和调度新的工作负载：</p>
<pre><code># nomad job plan httpbackend-1.nomad
+/- Job: "httpbackend"
+/- Stop: "true" =&gt; "false"
    Task Group: "httpbackend" (2 create)
      Task: "httpbackend"

Scheduler dry-run:
- All tasks successfully allocated.

Job Modify Index: 4248
To submit the job with version verification run:

nomad job run -check-index 4248 httpbackend-1.nomad

When running the job with the check-index flag, the job will only be run if the
server side version matches the job modify index returned. If the index has
changed, another user has modified the job and the plan's results are
potentially invalid.

</code></pre>
<p>如果plan的输出结果没有问题，则可以用nomad job run正式创建和调度job：</p>
<pre><code># nomad job run httpbackend-1.nomad
==&gt; Monitoring evaluation "40c63529"
    Evaluation triggered by job "httpbackend"
    Allocation "6b0b83de" created: node "9e3ef19f", group "httpbackend"
    Allocation "d0710b85" created: node "7acdd7bc", group "httpbackend"
    Evaluation status changed: "pending" -&gt; "complete"
==&gt; Evaluation "40c63529" finished with status "complete"

</code></pre>
<p>接下来，我们可以使用nomad job status命令查看job的创建情况以及某个job的详细状态信息：</p>
<pre><code># nomad job status
ID                  Type     Priority  Status   Submit Date
httpbackend         service  50        running  2019-03-30T04:58:09+08:00

# nomad job status httpbackend
ID            = httpbackend
Name          = httpbackend
Submit Date   = 2019-03-30T04:58:09+08:00
Type          = service
Priority      = 50
Datacenters   = dc1
Status        = running
Periodic      = false
Parameterized = false

Summary
Task Group   Queued  Starting  Running  Failed  Complete  Lost
httpbackend  0       0         2        0       0         0

Allocations
ID        Node ID   Task Group   Version  Desired  Status    Created    Modified
6b0b83de  9e3ef19f  httpbackend  11       run      running   8m ago     7m50s ago
d0710b85  7acdd7bc  httpbackend  11       run      running   8m ago     7m39s ago

</code></pre>
<p>前面说过，nomad只是集群管理和负载调度，服务发现它是不管的，并且服务发现的问题早已经被consul解决掉了。所以httpbackend创建后，要想使用该服务，我们还得走consul提供的路线：</p>
<p>DNS方式(前面已经做过铺垫了)：</p>
<pre><code># dig SRV httpbackend.service.dc1.consul

; &lt;&lt;&gt;&gt; DiG 9.10.3-P4-Ubuntu &lt;&lt;&gt;&gt; SRV httpbackend.service.dc1.consul
;; global options: +cmd
;; Got answer:
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 7742
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 5
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;httpbackend.service.dc1.consul.    IN    SRV

;; ANSWER SECTION:
httpbackend.service.dc1.consul.    0 IN    SRV    1 1 23578 consul-1.node.dc1.consul.
httpbackend.service.dc1.consul.    0 IN    SRV    1 1 22819 consul-2.node.dc1.consul.

;; ADDITIONAL SECTION:
consul-1.node.dc1.consul. 0    IN    A    172.16.66.102
consul-1.node.dc1.consul. 0    IN    TXT    "consul-network-segment="
consul-2.node.dc1.consul. 0    IN    A    172.16.66.103
consul-2.node.dc1.consul. 0    IN    TXT    "consul-network-segment="

;; Query time: 471 msec
;; SERVER: 172.16.66.102#53(172.16.66.102)
;; WHEN: Sat Mar 30 05:07:54 CST 2019
;; MSG SIZE  rcvd: 251

# curl http://172.16.66.102:23578
this is httpbackendservice, version: v1.0.0

# curl http://172.16.66.103:22819
this is httpbackendservice, version: v1.0.0

</code></pre>
<p>或http api方式(可通过<a href="https://godoc.org/github.com/hashicorp/consul/api">官方API</a>查询服务)：</p>
<pre><code># curl http://127.0.0.1:8500/v1/health/service/httpbackend

[
    {
        "Node": {"ID":"160a7a20-f177-d2f5-0765-e6d1a9a1a9a4","Node":"consul-1","Address":"172.16.66.102","Datacenter":"dc1","TaggedAddresses":{"lan":"172.16.66.102","wan":"172.16.66.102"},"Meta":{"consul-network-segment":""},"CreateIndex":7,"ModifyIndex":10},
        "Service": {"ID":"_nomad-task-5uxc3b7hjzivbklslt4yj5bpsfagibrb","Service":"httpbackend","Tags":[],"Address":"172.16.66.102","Meta":null,"Port":23578,"Weights":{"Passing":1,"Warning":1},"EnableTagOverride":false,"ProxyDestination":"","Proxy":{},"Connect":{},"CreateIndex":30727,"ModifyIndex":30727},
        "Checks": [{"Node":"consul-1","CheckID":"serfHealth","Name":"Serf Health Status","Status":"passing","Notes":"","Output":"Agent alive and reachable","ServiceID":"","ServiceName":"","ServiceTags":[],"Definition":{},"CreateIndex":7,"ModifyIndex":7}]
    },
    {
        "Node": {"ID":"6795cd2c-fad5-9d4f-2531-13b0a65e0893","Node":"consul-2","Address":"172.16.66.103","Datacenter":"dc1","TaggedAddresses":{"lan":"172.16.66.103","wan":"172.16.66.103"},"Meta":{"consul-network-segment":""},"CreateIndex":5,"ModifyIndex":5},
        "Service": {"ID":"_nomad-task-hvqnbklzqr6q5mpspqcqbnhxdil4su4d","Service":"httpbackend","Tags":[],"Address":"172.16.66.103","Meta":null,"Port":22819,"Weights":{"Passing":1,"Warning":1},"EnableTagOverride":false,"ProxyDestination":"","Proxy":{},"Connect":{},"CreateIndex":30725,"ModifyIndex":30725},
        "Checks": [{"Node":"consul-2","CheckID":"serfHealth","Name":"Serf Health Status","Status":"passing","Notes":"","Output":"Agent alive and reachable","ServiceID":"","ServiceName":"","ServiceTags":[],"Definition":{},"CreateIndex":8,"ModifyIndex":8}]
    }
]

</code></pre>
<h2>三. 将服务暴露到外部以及负载均衡</h2>
<p>集群内部的东西向流量可以通过consul的服务发现来实现，南北向流量则需要我们将部分服务暴露到外部才能实现流量导入。在<a href="https://tonybai.com/2018/09/10/setup-service-discovery-and-load-balance-based-on-consul/">《基于consul实现微服务的服务发现和负载均衡》</a>一文中，我们是通过<a href="https://tonybai.com/tag/nginx">nginx</a>实现服务暴露和负载均衡的，但是需要<a href="https://github.com/hashicorp/consul-template">consul-template</a>的协助，并且自己需要实现一个nginx的配置模板，门槛较高也比较复杂。</p>
<p>nomad的官方文档推荐了<a href="https://github.com/fabiolb/fabio">fabio</a>这个反向代理和负载均衡工具。fabio最初由位于荷兰的“<a href="https://www.ebayclassifiedsgroup.com/">eBay Classifieds Group</a>”开发，它为荷兰（marktplaats.nl），澳大利亚（gumtree.com.au）和意大利（www.kijiji.it）的一些最大网站提供支持。自2015年9月以来，它为这些站点提供23000个请求/秒的处理能力(性能应对一般中等流量是没有太大问题的)，没有发现重大问题。</p>
<p>与consul-template+nginx的组合不同，fabio无需开发人员做任何二次开发，也不需要自定义模板，它直接从consul读取service list并生成相关路由。至于哪些服务要暴露在外部，路由形式是怎样的，是需要在服务启动时为服务设置特定的tag，fabio定义了一套灵活的路由匹配描述方法。</p>
<p>下面我们就来部署fabio，并将上面的httpbackend暴露到外部。</p>
<h3>1. 部署fabio</h3>
<p>fabio也是nomad集群的一个工作负载，因此我们可以像普通job那样部署fabio。我们先来使用nomad官方文档中给出fabio.nomad：</p>
<pre><code>//fabio.nomad

job "fabio" {
  datacenters = ["dc1"]
  type = "system"

  group "fabio" {
    task "fabio" {
      driver = "docker"
      config {
        image = "fabiolb/fabio"
        network_mode = "host"
        logging {
          type = "json-file"
        }
      }

      resources {
        cpu    = 200
        memory = 128
        network {
          mbits = 20
          port "lb" {
            static = 9999
          }
          port "ui" {
            static = 9998
          }
        }
      }
    }
  }
}

</code></pre>
<p>这里有几点值得注意：</p>
<ol>
<li>
<p>fabio job的类型是”system”，也就是说该job会被部署到job可以匹配到（通过设定的约束条件）的所有nomad client上，且每个client上仅部署一个实例，有些类似于k8s的daemonset控制下的pod；</p>
</li>
<li>
<p>network_mode = “host” 告诉fabio的驱动docker：fabio容器使用host网络，即与主机同网络namespace；</p>
</li>
<li>
<p>static = 9999和static = 9998，说明fabio在每个nomad client上监听固定的静态端口而不是使用动态端口。这也要求了每个nomad client上不允许存在与fabio端口冲突的应用启动。</p>
</li>
</ol>
<p>我们来plan和run一下这个fabio job：</p>
<pre><code># nomad job plan fabio.nomad

+ Job: "fabio"
+ Task Group: "fabio" (3 create)
  + Task: "fabio" (forces create)

Scheduler dry-run:
- All tasks successfully allocated.

Job Modify Index: 0
To submit the job with version verification run:

nomad job run -check-index 0 fabio.nomad

When running the job with the check-index flag, the job will only be run if the
server side version matches the job modify index returned. If the index has
changed, another user has modified the job and the plan's results are
potentially invalid.

# nomad job run fabio.nomad
==&gt; Monitoring evaluation "97bfc16d"
    Evaluation triggered by job "fabio"
    Allocation "1b77dcfa" created: node "c281658a", group "fabio"
    Allocation "da35a778" created: node "7acdd7bc", group "fabio"
    Allocation "fc915ab7" created: node "9e3ef19f", group "fabio"
    Evaluation status changed: "pending" -&gt; "complete"
==&gt; Evaluation "97bfc16d" finished with status "complete"

</code></pre>
<p>查看一下fabio job的运行状态：</p>
<pre><code># nomad job status fabio

ID            = fabio
Name          = fabio
Submit Date   = 2019-03-27T14:30:29+08:00
Type          = system
Priority      = 50
Datacenters   = dc1
Status        = running
Periodic      = false
Parameterized = false

Summary
Task Group  Queued  Starting  Running  Failed  Complete  Lost
fabio       0       0         3        0       0         0

Allocations
ID        Node ID   Task Group  Version  Desired  Status   Created    Modified
1b77dcfa  c281658a  fabio       0        run      running  1m11s ago  58s ago
da35a778  7acdd7bc  fabio       0        run      running  1m11s ago  54s ago
fc915ab7  9e3ef19f  fabio       0        run      running  1m11s ago  58s ago

</code></pre>
<p>通过9998端口，可以查看fabio的ui页面，这个页面主要展示的是fabio生成的路由信息：</p>
<p><img src="https://tonybai.com/wp-content/uploads/fabio-ui-routes-table-1.png" alt="img{512x368}" /></p>
<p>由于尚未暴露任何服务，因此fabio的路由表为空。</p>
<p>fabio的流量入口为9999端口，不过由于没有配置路由和upstream service，因此如果此时向9999端口发送http请求，将会得到404的应答。</p>
<h3>2. 暴露HTTP服务到外部</h3>
<p>接下来，我们就将上面创建的httpbackend服务通过fabiolb暴露到外部，使得特定条件下通过fabiolb进入集群内部的流量可以被准确路由到集群中的httpbackend实例上面。</p>
<p>下面是fabio将nomad集群内部服务暴露在外部的原理图：</p>
<p><img src="https://tonybai.com/wp-content/uploads/fabiolb-mechanism.png" alt="img{512x368}" /></p>
<p>我们看到原理图中最为关键的一点就是service tag，该信息由nomad在创建job时写入到consul集群；fabio监听consul集群service信息变更，读取有新变动的job，解析job的service tag，生成路由规则。fabio关注所有带有”urlprefix-”前缀的service tag。</p>
<p>fabio启动时监听的9999端口，默认是http接入。我们修改一下之前的httpbackend.nomad，为该job中的service增加tag字段：</p>
<pre><code>// httpbackend.nomad

... ...

     service {
        name = "httpbackend"
        tags = ["urlprefix-mysite.com:9999/"]
        port = "http"
        check {
          name     = "alive"
          type     = "http"
          path     = "/"
          interval = "10s"
          timeout  = "2s"
        }
      }

</code></pre>
<p>对于上面httpbackend.nomad中service块的变更，主要有两点：</p>
<p>1) 增加tag：匹配的路由信息为：“mysite.com:9999/”</p>
<p>2) 增加check块：如果没有check设置，该路由信息将不会在fabio中生效</p>
<p>更新一下httpbackend:</p>
<pre><code># nomad job run httpbackend-2.nomad
==&gt; Monitoring evaluation "c83af3d3"
    Evaluation triggered by job "httpbackend"
    Allocation "6b0b83de" modified: node "9e3ef19f", group "httpbackend"
    Allocation "d0710b85" modified: node "7acdd7bc", group "httpbackend"
    Evaluation status changed: "pending" -&gt; "complete"
==&gt; Evaluation "c83af3d3" finished with status "complete"

</code></pre>
<p>查看fabio的route表，可以看到增加了两条新路由信息：</p>
<p><img src="https://tonybai.com/wp-content/uploads/httpbackend-routes.png" alt="img{512x368}" /></p>
<p>我们通过fabio来访问一下httpbackend服务：</p>
<pre><code># curl http://mysite.com:9999/      --- 注意：事先已经在/etc/hosts中添加了 mysite.com的地址为127.0.0.1
this is httpbackendservice, version: v1.0.0

</code></pre>
<p>我们看到httpbackend service已经被成功暴露到lb的外部了。</p>
<h2>四. 暴露HTTPS、TCP服务到外部</h2>
<h3>1. 定制fabio</h3>
<p>我们的目标是将https、tcp服务暴露到lb的外部，nomad官方文档中给出的fabio.nomad将不再适用，我们需要让fabio监听多个端口，每个端口有着不同的用途。同时，我们通过给fabio传入适当的命令行参数来帮助我们查看fabio的详细access日志信息，并让fabio支持<a href="https://github.com/fabiolb/fabio/wiki/Features#request-tracing">TRACE机制</a>。</p>
<p>fabio.nomad调整如下：</p>
<pre><code>job "fabio" {
  datacenters = ["dc1"]
  type = "system"

  group "fabio" {
    task "fabio" {
      driver = "docker"
      config {
        image = "fabiolb/fabio"
        network_mode = "host"
        logging {
          type = "json-file"
        }
        args = [
          "-proxy.addr=:9999;proto=http,:9997;proto=tcp,:9996;proto=tcp+sni",
          "-log.level=TRACE",
          "-log.access.target=stdout"
        ]
      }

      resources {
        cpu    = 200
        memory = 128
        network {
          mbits = 20
        }
      }
    }
  }
}

</code></pre>
<p>我们让fabio监听三个端口：</p>
<ul>
<li>
<p>9999: http端口</p>
</li>
<li>
<p>9997: tcp端口</p>
</li>
<li>
<p>9996: tcp+sni端口</p>
</li>
</ul>
<p>后续会针对这三个端口暴露的不同服务做细致说明。</p>
<p>我们将fabio的日志级别调低为TRACE级别，以便能查看到fabio日志中输出的trace信息，帮助我们进行路由匹配的诊断。</p>
<p>重新nomad job run fabio.nomad后，我们来看看TRACE的效果：</p>
<pre><code>//访问后端服务，在http header中添加"Trace: abc"：

# curl -H 'Trace: abc' 'http://mysite.com:9999/'
this is httpbackendservice, version: v1.0.0

//查看fabio的访问日志：

2019/03/30 08:13:15 [TRACE] abc Tracing mysite.com:9999/
2019/03/30 08:13:15 [TRACE] abc Matching hosts: [mysite.com:9999]
2019/03/30 08:13:15 [TRACE] abc Match mysite.com:9999/
2019/03/30 08:13:15 [TRACE] abc Routing to service httpbackend on http://172.16.66.102:23578/
127.0.0.1 - - [30/Mar/2019:08:13:15 +0000] "GET / HTTP/1.1" 200 44

</code></pre>
<p>我们可以清晰的看到fabio收到请求后，匹配到一条路由：”mysite.com:9999/”，然后将http请求转发到 172.16.66.102:23578这个httpbackend服务实例上去了。</p>
<h3>2. https服务</h3>
<p>接下来，我们考虑将一个https服务暴露在lb外部。</p>
<p>一种方案是fabiolb做ssl termination，然后再在与upstream https服务建立的ssl连接上传递数据。这种两段式https通信是比较消耗资源的，fabio要对数据进行两次加解密。</p>
<p>另外一种方案是fabiolb将收到的请求透传给后面的upsteam https服务，由client与upsteam https服务直接建立“安全数据通道”，这个方案我们在后续会提到。</p>
<p>第三种方案，那就是对外依旧暴露http，但是fabiolb与upsteam之间通过https通信。我们先来看一下这种“间接暴露https”的方案。</p>
<pre><code>// httpsbackend-upstreamhttps.nomad

job "httpsbackend" {
  datacenters = ["dc1"]
  type = "service"

  group "httpsbackend" {
    count = 2
    restart {
      attempts = 2
      interval = "30m"
      delay = "15s"
      mode = "fail"
    }

    task "httpsbackend" {
      driver = "docker"
      config {
        image = "bigwhite/httpsbackendservice:v1.0.0"
        port_map {
          https = 7777
        }
        logging {
          type = "json-file"
        }
      }

      resources {
        network {
          mbits = 10
          port "https" {}
        }
      }

      service {
        name = "httpsbackend"
        tags = ["urlprefix-mysite-https.com:9999/ proto=https tlsskipverify=true"]
        port = "https"
        check {
          name     = "alive"
          type     = "tcp"
          path     = "/"
          interval = "10s"
          timeout  = "2s"
        }
      }
    }
  }
}

</code></pre>
<p>我们将创建名为httpsbackend的job，job中Task对应的tag为：”urlprefix-mysite-https.com:9999/ proto=https tlsskipverify=true”。解释为：路由mysite-https.com:9999/，上游upstream服务为https服务，fabio不验证upstream服务的公钥数字证书。</p>
<p>我们创建该job：</p>
<pre><code># nomad job run httpsbackend-upstreamhttps.nomad
==&gt; Monitoring evaluation "ba7af6d4"
    Evaluation triggered by job "httpsbackend"
    Allocation "3127aac8" created: node "7acdd7bc", group "httpsbackend"
    Allocation "b5f1b7a7" created: node "9e3ef19f", group "httpsbackend"
    Evaluation status changed: "pending" -&gt; "complete"
==&gt; Evaluation "ba7af6d4" finished with status "complete"

</code></pre>
<p>我们来通过fabiolb访问一下httpsbackend这个服务：</p>
<pre><code># curl -H "Trace: abc"  http://mysite-https.com:9999/
this is httpsbackendservice, version: v1.0.0

// fabiolb 日志

2019/03/30 09:35:48 [TRACE] abc Tracing mysite-https.com:9999/
2019/03/30 09:35:48 [TRACE] abc Matching hosts: [mysite-https.com:9999]
2019/03/30 09:35:48 [TRACE] abc Match mysite-https.com:9999/
2019/03/30 09:35:48 [TRACE] abc Routing to service httpsbackend on https://172.16.66.103:29248
127.0.0.1 - - [30/Mar/2019:09:35:48 +0000] "GET / HTTP/1.1" 200 45

</code></pre>
<h3>3. 基于tcp代理暴露https服务</h3>
<p>上面的方案虽然将https暴露在外面，但是client到fabio这个环节的数据传输不是在安全通道中。上面提到的方案2：fabiolb将收到的请求透传给后面的upsteam https服务，由client与upsteam https服务直接建立“安全数据通道”似乎更佳。fabiolb支持tcp端口的反向代理，我们基于tcp代理来暴露https服务到外部。</p>
<p>我们建立httpsbackend-tcp.nomad文件，考虑篇幅有限，我们仅列出差异化的部分：</p>
<pre><code>job "httpsbackend-tcp" {

 ... ...

    service {
        name = "httpsbackend-tcp"
        tags = ["urlprefix-:9997 proto=tcp"]
        port = "https"
        check {
          name     = "alive"
          type     = "tcp"
          path     = "/"
          interval = "10s"
          timeout  = "2s"
        }
      }

... ...

}

</code></pre>
<p>从httpsbackend-tcp.nomad文件，我们看到我们在9997这个tcp端口上暴露服务，tag为：“urlprefix-:9997 proto=tcp”，即凡是到达9997端口的流量，无论应用协议类型是什么，都转发到httpsbackend-tcp上，且通过tcp协议转发。</p>
<p>我们创建并测试一下该方案：</p>
<pre><code># nomad job run httpsbackend-tcp.nomad

# curl -k https://localhost:9997   //由于使用的是自签名证书，所有告诉curl不校验server端公钥数字证书
this is httpsbackendservice, version: v1.0.0

</code></pre>
<h3>4. 多个https服务共享一个fabio端口</h3>
<p>上面的基于tcp代理暴露https服务的方案还有一个问题，那就是每个https服务都要独占一个fabio listen的端口。那是否可以实现多个https服务使用一个fabio端口，并通过host name route呢？fabio支持tcp+sni的route策略。</p>
<p>SNI, 全称Server Name Indication，即服务器名称指示。它是一个扩展的TLS计算机联网协议。该协议允许在握手过程开始时通过客户端告诉它正在连接的服务器的主机名称。这允许服务器在相同的IP地址和TCP端口号上呈现多个证书，也就是允许在相同的IP地址上提供多个安全HTTPS网站（或其他任何基于TLS的服务），而不需要所有这些站点使用相同的证书。</p>
<p>接下来，我们就来看一下如何在fabio中让多个后端https服务共享一个Fabio服务端口(9996)。我们建立两个job：httpsbackend-sni-1和httpsbackend-sni-2。</p>
<pre><code>//httpsbackend-tcp-sni-1.nomad

job "httpsbackend-sni-1" {

... ...

    service {
        name = "httpsbackend-sni-1"
        tags = ["urlprefix-mysite-sni-1.com/ proto=tcp+sni"]
        port = "https"
        check {
          name     = "alive"
          type     = "tcp"
          path     = "/"
          interval = "10s"
          timeout  = "2s"
        }
      }

.... ...

}

//httpsbackend-tcp-sni-2.nomad

job "httpsbackend-sni-2" {

... ...

   task "httpsbackend-sni-2" {
      driver = "docker"
      config {
        image = "bigwhite/httpsbackendservice:v1.0.1"
        port_map {
          https = 7777
        }
        logging {
          type = "json-file"
        }
    }

    service {
        name = "httpsbackend-sni-2"
        tags = ["urlprefix-mysite-sni-2.com/ proto=tcp+sni"]
        port = "https"
        check {
          name     = "alive"
          type     = "tcp"
          path     = "/"
          interval = "10s"
          timeout  = "2s"
        }
      }

.... ...

}

</code></pre>
<p>我们看到与之前的server tag不同的是：这里proto=tcp+sni，即告诉fabio建立sni路由。httpsbackend-sni-2 task与httpsbackend-sni-1不同之处在于其使用image为bigwhite/httpsbackendservice:v1.0.1，为的是能通过https的应答结果，将这两个服务区分开来。</p>
<p>除此之外，我们还看到tag中并不包含端口号了，而是直接采用host name作为路由匹配标识。</p>
<p>创建这两个job：</p>
<pre><code># nomad job run httpsbackend-tcp-sni-1.nomad
==&gt; Monitoring evaluation "af170d98"
    Evaluation triggered by job "httpsbackend-sni-1"
    Allocation "8ea1cc8d" modified: node "7acdd7bc", group "httpsbackend-sni-1"
    Allocation "e16cdc73" modified: node "9e3ef19f", group "httpsbackend-sni-1"
    Evaluation status changed: "pending" -&gt; "complete"
==&gt; Evaluation "af170d98" finished with status "complete"

# nomad job run httpsbackend-tcp-sni-2.nomad
==&gt; Monitoring evaluation "a77d3799"
    Evaluation triggered by job "httpsbackend-sni-2"
    Allocation "32df450c" modified: node "c281658a", group "httpsbackend-sni-2"
    Allocation "e1bf4871" modified: node "7acdd7bc", group "httpsbackend-sni-2"
    Evaluation status changed: "pending" -&gt; "complete"
==&gt; Evaluation "a77d3799" finished with status "complete"

</code></pre>
<p>我们来分别访问这两个服务：</p>
<pre><code># curl -k https://mysite-sni-1.com:9996/
this is httpsbackendservice, version: v1.0.0

# curl -k https://mysite-sni-2.com:9996/
this is httpsbackendservice, version: v1.0.1

</code></pre>
<p>从返回的结果我们看到，通过9996，我们成功暴露出两个不同的https服务。</p>
<h2>五. 小结</h2>
<p>到这里，我们实现了我们的既定目标：</p>
<ol>
<li>
<p>使用nomad实现了工作负载的创建和调度；</p>
</li>
<li>
<p>东西向流量通过consul机制实现；</p>
</li>
<li>
<p>通过fabio实现了http、https(through tcp)、多https(though tcp+sni)的服务暴露和负载均衡。</p>
</li>
</ol>
<p>后续我们将进一步探索基于nomad实现负载的多种场景的升降级操作(滚动、金丝雀、蓝绿部署)、对非host网络的支持（比如weave network)等。</p>
<p>本文涉及到的源码文件在<a href="https://github.com/bigwhite/experiments/tree/master/nomad-demo/part1/jobs">这里</a>可以下载。</p>
<h2>六. 参考资料</h2>
<ol>
<li><a href="https://www.hashicorp.com/blog/resilient-infrastructure-with-nomad-scheduling">使用Nomad构建弹性基础设施：nomad调度</a></li>
<li><a href="https://www.hashicorp.com/blog/resilient-infrastructure-with-nomad-restarting-tasks">使用Nomad构建弹性基础设施：重启任务</a></li>
<li><a href="https://www.hashicorp.com/blog/building-resilient-infrastructure-with-nomad-job-lifecycle">使用Nomad构建弹性基础设施:   job生命周期</a></li>
<li><a href="https://www.hashicorp.com/blog/resilient-infrastructure-with-nomad-fault-tolerance-outage-recovery">使用Nomad构建弹性基础设施：容错和自我修复</a></li>
<li><a href="https://fabiolb.net/ref/">fabio参考指南</a></li>
</ol>
<hr />
<p>我的网课“<a href="https://coding.imooc.com/class/284.html">Kubernetes实战：高可用集群搭建、配置、运维与应用</a>”在慕课网上线了，感谢小伙伴们学习支持！</p>
<p><a href="https://tonybai.com/">我爱发短信</a>：企业级短信平台定制开发专家 https://tonybai.com/<br />
smspush : 可部署在企业内部的定制化短信平台，三网覆盖，不惧大并发接入，可定制扩展； 短信内容你来定，不再受约束, 接口丰富，支持长短信，签名可选。</p>
<p>著名云主机服务厂商DigitalOcean发布最新的主机计划，入门级Droplet配置升级为：1 core CPU、1G内存、25G高速SSD，价格5$/月。有使用DigitalOcean需求的朋友，可以打开这个<a href="https://m.do.co/c/bff6eed92687">链接地址</a>：https://m.do.co/c/bff6eed92687 开启你的DO主机之路。</p>
<p>我的联系方式：</p>
<p>微博：https://weibo.com/bigwhite20xx<br />
微信公众号：iamtonybai<br />
博客：tonybai.com<br />
github: https://github.com/bigwhite</p>
<p>微信赞赏：<br />
<img src="https://tonybai.com/wp-content/uploads/wechat-zanshang-code-512x512.jpg" alt="img{512x368}" /></p>
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。</p>
<p style='text-align:left'>&copy; 2019, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2019/03/30/cluster-management-and-microservice-deployment-and-scheduled-by-nomad/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>官宣：慕课网课程“Kubernetes实战：高可用集群搭建、配置、运维与应用”上线了</title>
		<link>https://tonybai.com/2018/10/17/imooc-course-kubernetes-practice-go-online/</link>
		<comments>https://tonybai.com/2018/10/17/imooc-course-kubernetes-practice-go-online/#comments</comments>
		<pubDate>Wed, 17 Oct 2018 10:28:04 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[aliyun]]></category>
		<category><![CDATA[cloud-native]]></category>
		<category><![CDATA[CNCF]]></category>
		<category><![CDATA[cni]]></category>
		<category><![CDATA[container]]></category>
		<category><![CDATA[controller]]></category>
		<category><![CDATA[dashboard]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[EFK]]></category>
		<category><![CDATA[elastic]]></category>
		<category><![CDATA[ElasticSearch]]></category>
		<category><![CDATA[ELK]]></category>
		<category><![CDATA[event]]></category>
		<category><![CDATA[harbor]]></category>
		<category><![CDATA[heapster]]></category>
		<category><![CDATA[High-Available]]></category>
		<category><![CDATA[image]]></category>
		<category><![CDATA[imooc]]></category>
		<category><![CDATA[ingress]]></category>
		<category><![CDATA[istio]]></category>
		<category><![CDATA[k8s]]></category>
		<category><![CDATA[kubeadm]]></category>
		<category><![CDATA[kubectl]]></category>
		<category><![CDATA[Kubernetes]]></category>
		<category><![CDATA[label]]></category>
		<category><![CDATA[logging]]></category>
		<category><![CDATA[Master]]></category>
		<category><![CDATA[microservice]]></category>
		<category><![CDATA[Namespace]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[pod]]></category>
		<category><![CDATA[PV]]></category>
		<category><![CDATA[PVC]]></category>
		<category><![CDATA[registry]]></category>
		<category><![CDATA[Service]]></category>
		<category><![CDATA[ServiceMesh]]></category>
		<category><![CDATA[storage]]></category>
		<category><![CDATA[StorageClass]]></category>
		<category><![CDATA[troubleshooting]]></category>
		<category><![CDATA[volume]]></category>
		<category><![CDATA[weave]]></category>
		<category><![CDATA[worker]]></category>
		<category><![CDATA[云原生]]></category>
		<category><![CDATA[云应用]]></category>
		<category><![CDATA[容器]]></category>
		<category><![CDATA[微服务]]></category>
		<category><![CDATA[慕课网]]></category>
		<category><![CDATA[服务]]></category>
		<category><![CDATA[服务治理]]></category>
		<category><![CDATA[服务网格]]></category>
		<category><![CDATA[网课]]></category>
		<category><![CDATA[高可用]]></category>

		<guid isPermaLink="false">https://tonybai.com/?p=2644</guid>
		<description><![CDATA[距离我的第一门网课《Kubernetes基础：开启云原生之门》上线已经过去5个多月了，我的实战课《Kubernetes实战：高可用集群搭建、配置、运维与应用》终于在9月27日正式上线了。 一. 课程介绍 《Kubernetes实战：高可用集群搭建、配置、运维与应用》的课程内容与最初课程设计时规划的内容大纲没有太多出入，基本就是根据我最初的想法拟定的内容，这也基本是我这两年学习k8s、积累的k8s实践的路线。整个课程基于kubernetes 1.10.2版本(docker 17.03.2ce)。课程内容大致分为七个部分（与课程主页的课程目录结构稍有差异，但课程内容是一致的）： 第一章 搭建你的第一个Kubernetes集群 本章介绍了一个使用kubeadm引导的Kubernetes集群的搭建和基本配置方法。 1-1: 导学 1-2: 安装准备 1-3: 初始化集群master节点 1-4: 向集群加入worker节点 1-5: 安装dashboard和heapster 1-6: 验证集群安装结果 第二章 Kubernetes集群探索 本章对kubeadm初始化集群的原理进行了讲解，并对已经建立的k8s集群中的各个组件进行详细介绍，包括功用、原理和配置等 2-1: kubeadm init流程揭秘 2-2: kubeadm join流程揭秘 2-3: kubernetes核心组件详解 2-4: kubectl详解 第三章 Kubernetes网络、安全与存储 本章讲解k8s集群的三个难点：网络、安全与存储的概念和运行原理。 3-1：kubernetes集群网络 3-1-1: kubernetes集群的“三个网络” 3-1-2: kubernetes网络的设计要求 3-1-3: kubernetes网络实现 3-1-4: pod网络实现原理 3-1-5: pod网络方案对比 3-1-6: service网络实现原理 3-2: kubernetes集群安全 3-2-1: kube-apiserver安全模型 3-2-2: [...]]]></description>
			<content:encoded><![CDATA[<p>距离我的第一门网课<a href="https://www.imooc.com/learn/978">《Kubernetes基础：开启云原生之门》</a>上线已经过去5个多月了，我的实战课<a href="https://coding.imooc.com/class/chapter/284.html">《Kubernetes实战：高可用集群搭建、配置、运维与应用》</a>终于在9月27日正式上线了。</p>
<p><img src="https://tonybai.com/wp-content/uploads/k8s-practice-frontpage.png" alt="img{512x368}" /></p>
<h3>一. 课程介绍</h3>
<p><img src="https://tonybai.com/wp-content/uploads/k8s-practice-content-1.png" alt="img{512x368}" /></p>
<p><img src="https://tonybai.com/wp-content/uploads/k8s-practice-content-2.png" alt="img{512x368}" /></p>
<p><a href="https://coding.imooc.com/class/chapter/284.html">《Kubernetes实战：高可用集群搭建、配置、运维与应用》</a>的课程内容与最初课程设计时规划的内容大纲没有太多出入，基本就是根据我最初的想法拟定的内容，<strong>这也基本是我这两年学习k8s、积累的k8s实践的路线</strong>。整个课程基于kubernetes 1.10.2版本(<a href="https://tonybai.com/tag/docker">docker</a> 17.03.2ce)。课程内容大致分为七个部分（与课程主页的课程目录结构稍有差异，但课程内容是一致的）：</p>
<p>第一章 搭建你的第一个<a href="https://tonybai.com/tag/kubernetes">Kubernetes集群</a></p>
<p>本章介绍了一个使用<a href="https://tonybai.com/2016/12/30/install-kubernetes-on-ubuntu-with-kubeadm/">kubeadm</a>引导的Kubernetes集群的搭建和基本配置方法。</p>
<ul>
<li>1-1: 导学</li>
<li>1-2: 安装准备</li>
<li>1-3: 初始化集群master节点</li>
<li>1-4: 向集群加入worker节点</li>
<li>1-5: <a href="https://tonybai.com/2017/09/26/some-notes-about-deploying-kubernetes-dashboard-1-7-0/">安装dashboard和heapster</a></li>
<li>1-6: 验证集群安装结果</li>
</ul>
<p>第二章 <a href="https://tonybai.com/2017/01/24/explore-kubernetes-cluster-installed-by-kubeadm/">Kubernetes集群探索</a></p>
<p>本章对kubeadm初始化集群的原理进行了讲解，并对已经建立的k8s集群中的各个组件进行详细介绍，包括功用、原理和配置等</p>
<ul>
<li>2-1: kubeadm init流程揭秘</li>
<li>2-2: kubeadm join流程揭秘</li>
<li>2-3: kubernetes核心组件详解</li>
<li>2-4: <a href="https://tonybai.com/2018/06/14/the-authentication-and-authorization-of-kubectl-when-accessing-k8s-cluster/">kubectl</a>详解</li>
</ul>
<p>第三章 Kubernetes网络、安全与存储<br />
本章讲解k8s集群的三个难点：网络、安全与存储的概念和运行原理。</p>
<p>3-1：kubernetes<a href="https://tonybai.com/2017/01/17/understanding-flannel-network-for-kubernetes/">集群网络</a></p>
<ul>
<li>3-1-1: kubernetes集群的“三个网络”</li>
<li>3-1-2: kubernetes网络的设计要求</li>
<li>3-1-3: kubernetes网络实现</li>
<li>3-1-4: pod网络实现原理</li>
<li>3-1-5: pod网络方案对比</li>
<li>3-1-6: service网络实现原理</li>
</ul>
<p>3-2: <a href="https://tonybai.com/2018/06/14/the-authentication-and-authorization-of-kubectl-when-accessing-k8s-cluster/">kubernetes集群安全</a></p>
<ul>
<li>3-2-1: kube-apiserver安全模型</li>
<li>3-2-2: 传输安全</li>
<li>3-2-3: <a href="https://tonybai.com/2016/11/25/the-security-settings-for-kubernetes-cluster/">身份验证</a></li>
<li>3-2-4: 授权</li>
<li>3-2-5: 准入控制</li>
</ul>
<p>3-3 kubernets集群存储</p>
<ul>
<li>3-3-1: Volume</li>
<li>3-3-2: <a href="https://tonybai.com/2016/11/07/integrate-kubernetes-with-ceph-rbd/">PV和PVC</a></li>
<li>3-3-3: StorageClass和动态PV供给</li>
<li>3-3-4: Kubernetes存储模型</li>
</ul>
<p>第四章 <a href="https://tonybai.com/2017/05/15/setup-a-ha-kubernetes-cluster-based-on-kubeadm-part1/">高可用Kubernetes集群</a>搭建方案<br />
本章介绍了什么是高可用k8s集群，并给出了一个可行的高可用Kubernetes集群的搭建方案。</p>
<ul>
<li>4-1: 什么是高可用Kubernetes集群</li>
<li>4-2: 高可用Kubernetes集群方案</li>
</ul>
<p>第五章 Kubernetes集群常见运维操作</p>
<p>本章讲解了Kubernetes集群的基本运维操作，包括node管理、service、pod管理、日志查看等。并讲解了面对k8s集群问题时如何做troubleshooting。</p>
<ul>
<li>5-1: 管理Node与Label</li>
<li>5-2: 管理Namespace、Service和Pod</li>
<li>5-3: <a href="https://tonybai.com/2017/10/16/out-of-node-resource-handling-in-kubernetes-cluster/">计算资源管理</a></li>
<li>5-4: 查看事件和容器日志</li>
<li>5-5: 常用TroubleShooting方法</li>
</ul>
<p>第六章 Kubernetes支撑<a href="https://www.cncf.io/">云原生应用</a>开发案例<br />
本章讲解了Kubernetes集群的应用：支撑云原生应用开发。并通过实际操作讲解了镜像仓库、集中日志以及云应用治理框架的搭建和使用。</p>
<ul>
<li>6-1: Kubernetes与云原生应用</li>
<li>6-2: <a href="https://tonybai.com/2017/12/08/deploy-high-availability-harbor-on-kubernetes-cluster/">高可用私有镜像仓库搭建</a></li>
<li>6-3: <a href="https://tonybai.com/2018/06/13/setup-efk-on-kubernetes-1-10-3-in-the-hard-way/">基于ElasticSearch Stack搭建集群Logging设施</a></li>
<li>6-4: <a href="https://tonybai.com/2018/01/03/an-intro-of-microservices-governance-by-istio/">基于istio service mesh实现服务治理</a></li>
</ul>
<p>第七章 课程回顾与总结</p>
<h3>二. 做网课目的与课程思路</h3>
<p>当初接下慕课商务的这门课主要是出于两个目的：</p>
<ul>
<li>通过这门课程对自己的k8s学习和实践做一个阶段性的系统总结</li>
<li>尝试一下网课这个“新鲜”事物</li>
</ul>
<p>现在看来，当初这两个“目的”都实现了。但是录制网课的确是件很“辛苦”的事情，不知道多少的夜晚和周末都留给了“网课资料编写和录制”。尤其是Kubernetes这个主题，讲起来“顾虑”很多：</p>
<ul>
<li>
<p>和编程语言课不同，Kubernetes平台是个复杂的平台，外延生态很庞大。k8s概念多，如果不把概念和原理交待清楚、讲透彻，直接就上手操作，那样学习后，对k8s的理解仍然不会很深刻，很多问题仍然无法自己去解决，尤其是中高级阶段。 这就导致很多小伙伴认为课程概念讲解“有些多”；</p>
</li>
<li>
<p>生产环境中k8s集群有大有小，使用目的也是大不相同，安装方式也是有很多种(官方就列了10多种)，所在的网络环境以及使用的pod网络插件也是区别很大，遇到的问题更是千差万别，这里在准备 课程时也是思来想去，无法覆盖所有生产环境的所有情况。最后决定使用kubeadm搭建一个4节点的集群(使用weave network plugin)，可能能更好的满足初学者的需求，学员们更容易获取搭建这样一个 k8s环境所需的资源。而关于课程中实际操作部分重点集中在前面的k8s搭建、集群探索以及后面的k8s对云应用支撑的环节。所以如果小伙伴们的环境与课程不同，可以在课程后提问，我会尽量第一时间、细致的回答各位的问题。</p>
</li>
<li>
<p>关于时长，我在课程里尽量做到没有”废话“。现在的网课多根据“时长”定价（虽然不赞同，但是目前也没有一个更好的量化课程质量的方法）：比如10个小时以上可能就会定到399元，但是不足10小时，可能就在199元这个价位。<strong>于是我努力地将课程做到了“199”这个价位上了</strong>。对于真正想学习k8s的小伙伴们，这也许是一个“好消息”:)。</p>
</li>
</ul>
<h3>三. 课程小结</h3>
<p>Kubernetes还在快速不断地演进！我个人觉得学完本门课程也仅仅是“Kubernetes实践之路”的一个开始而已！应用上云的趋势已经不可逆转，对于云应用开发人员来说，<strong>了解和学习Kubernetes就像当年单机时代开发人员要去了解PC操作系统一样重要</strong>！希望本门课程能给更多的开发者带去帮助！</p>
<p>下面是课程的自制海报，欢迎转发:)</p>
<p><img src="https://tonybai.com/wp-content/uploads/k8s-practice-with-qr-and-text.png" alt="img{512x368}" /></p>
<hr />
<p><a href="https://tonybai.com/">我爱发短信</a>：企业级短信平台定制开发专家 https://tonybai.com/<br />
smspush : 可部署在企业内部的定制化短信平台，三网覆盖，不惧大并发接入，可定制扩展； 短信内容你来定，不再受约束, 接口丰富，支持长短信，签名可选。</p>
<p>著名云主机服务厂商DigitalOcean发布最新的主机计划，入门级Droplet配置升级为：1 core CPU、1G内存、25G高速SSD，价格5$/月。有使用DigitalOcean需求的朋友，可以打开这个<a href="https://m.do.co/c/bff6eed92687">链接地址</a>：https://m.do.co/c/bff6eed92687 开启你的DO主机之路。</p>
<p>我的联系方式：</p>
<p>微博：https://weibo.com/bigwhite20xx<br />
微信公众号：iamtonybai<br />
博客：tonybai.com<br />
github: https://github.com/bigwhite</p>
<p>微信赞赏：<br />
<img src="https://tonybai.com/wp-content/uploads/wechat-zanshang-code-512x512.jpg" alt="img{512x368}" /></p>
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。</p>
<p style='text-align:left'>&copy; 2018 &#8211; 2020, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2018/10/17/imooc-course-kubernetes-practice-go-online/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>TB一周萃选[第9期]</title>
		<link>https://tonybai.com/2018/02/11/9th-issue-of-the-tech-weekly-carefully-chosen-by-tonybai/</link>
		<comments>https://tonybai.com/2018/02/11/9th-issue-of-the-tech-weekly-carefully-chosen-by-tonybai/#comments</comments>
		<pubDate>Sun, 11 Feb 2018 05:41:08 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[artificial-intelligence]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[Ceph]]></category>
		<category><![CDATA[circuitbreaker]]></category>
		<category><![CDATA[cloud-native]]></category>
		<category><![CDATA[CNCF]]></category>
		<category><![CDATA[Codereview]]></category>
		<category><![CDATA[conduit]]></category>
		<category><![CDATA[Context]]></category>
		<category><![CDATA[deep-learning]]></category>
		<category><![CDATA[EBS]]></category>
		<category><![CDATA[egress]]></category>
		<category><![CDATA[GCP]]></category>
		<category><![CDATA[GeoffreyHinton]]></category>
		<category><![CDATA[gerrit]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Go-1.10-Release-Party]]></category>
		<category><![CDATA[Go1.10]]></category>
		<category><![CDATA[Go1.6]]></category>
		<category><![CDATA[Go1.7]]></category>
		<category><![CDATA[Golang]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[GoogleCloudPlatform]]></category>
		<category><![CDATA[HTTP2]]></category>
		<category><![CDATA[ingress]]></category>
		<category><![CDATA[istio]]></category>
		<category><![CDATA[k8s]]></category>
		<category><![CDATA[Kubernetes]]></category>
		<category><![CDATA[metrics]]></category>
		<category><![CDATA[middleware]]></category>
		<category><![CDATA[NFS]]></category>
		<category><![CDATA[Package]]></category>
		<category><![CDATA[PR]]></category>
		<category><![CDATA[Redhat]]></category>
		<category><![CDATA[rook]]></category>
		<category><![CDATA[S3]]></category>
		<category><![CDATA[ServiceMesh]]></category>
		<category><![CDATA[SSE]]></category>
		<category><![CDATA[tracing]]></category>
		<category><![CDATA[websocket]]></category>
		<category><![CDATA[中华民族]]></category>
		<category><![CDATA[云原生]]></category>
		<category><![CDATA[云存储]]></category>
		<category><![CDATA[亲情]]></category>
		<category><![CDATA[人工智能]]></category>
		<category><![CDATA[传统]]></category>
		<category><![CDATA[充电]]></category>
		<category><![CDATA[分布式存储]]></category>
		<category><![CDATA[华夏]]></category>
		<category><![CDATA[反向传播]]></category>
		<category><![CDATA[回家]]></category>
		<category><![CDATA[安全]]></category>
		<category><![CDATA[密码管理]]></category>
		<category><![CDATA[度量]]></category>
		<category><![CDATA[微服务]]></category>
		<category><![CDATA[性能优化]]></category>
		<category><![CDATA[春节]]></category>
		<category><![CDATA[春运]]></category>
		<category><![CDATA[服务治理]]></category>
		<category><![CDATA[浏览器]]></category>
		<category><![CDATA[深度学习]]></category>
		<category><![CDATA[胶囊理论]]></category>
		<category><![CDATA[节日]]></category>
		<category><![CDATA[过年]]></category>

		<guid isPermaLink="false">http://tonybai.com/?p=2552</guid>
		<description><![CDATA[本文是首发于个人微信公众号的文章“TB一周萃选[第9期]”的归档。 亲情犹如一江剪不断的春水，流动的是游子心中永远的思念；亲情犹如一丘数不尽的细沙，沉淀的是长年堆积的牵挂；亲情犹如夜空中那颗北斗，指引的是那迷路的羔羊回家的方向。忙碌了一年，该回家了，给心放个假，带上媳妇带上你的娃，回家看看那年迈的爸妈，出发！ &#8212; 改编自网络 此时此刻，很多人刚刚踏上了春节回家的旅途，有些人更是已经叩开了家的大门。每逢中国传统佳节-春节，令世界瞩目并为之瞠目结舌的中国式人口大迁移就会发生一次：几亿人熬夜刷票并不辞辛劳地携着夫/妻儿女，经由多种交通工具，跨越高山大河，不远千百里，战胜种种“囧况”，只为一个目的：在春节前回到那个充满熟悉味道的家乡。 这种在一个文明延续5000多年未中断的民族中发生的全民行为让西方社会感到十分不解，甚至指责这是对资源的一种浪费；并且也有国内的人发出类似不和谐的声音。但是它依然在发生着，每年都在发生，形式有些许变化，但剧情大体雷同。 曾经有国内外学者对中国特有的春节大迁徙的原因进行研究和分析，并给出了各种专业化的理由。但在我看来，对现代人来说，回家过年，是一种心灵的相互充电! 而且是充电7天，“通话”一整年。 对于一年到头在外奔波劳碌的人们来说，只有回家，才能真实地触摸到自己的“根”，才能切切实实地体会这种归属感，才能在一定程度上纾解那些在工作的城市中涵盖不了的人生寄托。在这种归属感中，哪怕只是获得片刻的身心安宁，也是一种极为重要的精神能量的充电；而对于守候在家乡的父母或者孩童儿，你的回家，让他们将近一年的期盼终于有了一个圆满的结果，这同样为下一个365天的期盼周期提供了强大的动力和希望。 如果非要给这种行为找个理由，那我要说这就是由一个体内延绵数千年的中华民族血脉的中国人的基因所决定的。 一、一周文章精粹 1. Go 1.10发布Party 自从Go 1.6开始，每逢偶数版本（一般在每年2、3月发布），Gopher社区都会举办庆祝Release的全球Party。在中国农历春节到来之际，也恰逢Go最新版本Go 1.10即将发布之时，Go wiki发布了Go 1.10 Release Party的Schedule和相关资料。截至目前，已经有15个Party已经list到页面上，活动从2月15号一直延续到3月份。 Go 1.10发布Party官网页面 Go 1.10 Release Note Draft The State of Go 1.10 2. 避免或减少对Go context Value的使用 context包最初诞生于Google公司内部，并在Google内部项目大量使用。context在golang/x中孵化了多年，并得到了很多开源项目的使用，尤其是一些使用了”middleware”模式的项目中，于是在Go 1.7发布时，context包正式加入Go标准库。context加入后，可谓既带来魔力，亦带来了争议，甚至有人将其视为具有“病毒”属性，一旦使用，便可轻易传染到项目中代码的各个角落。 Go开发者、培训师Jon Calhoun也在个人网站上撰写了一篇文章，来告诫大家Go context value的一些缺陷，建议大家避免或减少对Go context Value的使用，并给出自己的替代方案。其主要理由是：context.WithValue和Context.Value的使用让我们失去了编译器对类型安全性的检查。 文章链接：“Pitfalls of context values and how to avoid or mitigate [...]]]></description>
			<content:encoded><![CDATA[<p>本文是首发于<a href="https://mp.weixin.qq.com/mp/qrcode?scene=10000005&amp;size=102&amp;__biz=MzIyNzM0MDk0Mg==&amp;mid=2247483848&amp;idx=1&amp;sn=a3cd9182a2b2d3716623cc2c43d59f37&amp;send_time=">个人微信公众号</a>的文章<strong>“TB一周萃选[第9期]”</strong>的归档。</p>
<p><img src="http://tonybai.com/wp-content/uploads/weekly-issues/9th-issue/go-home-during-spring-festival.jpg" alt="img{512x368}" /></p>
<blockquote>
<p>亲情犹如一江剪不断的春水，流动的是游子心中永远的思念；亲情犹如一丘数不尽的细沙，沉淀的是长年堆积的牵挂；亲情犹如夜空中那颗北斗，指引的是那迷路的羔羊回家的方向。忙碌了一年，该回家了，给心放个假，带上媳妇带上你的娃，回家看看那年迈的爸妈，出发！  &#8212;  改编自网络</p>
</blockquote>
<p>此时此刻，很多人刚刚踏上了春节回家的旅途，有些人更是已经叩开了家的大门。每逢中国传统佳节-<a href="https://en.wikipedia.org/wiki/Chinese_New_Year">春节</a>，令世界瞩目并为之瞠目结舌的中国式人口大迁移就会发生一次：几亿人熬夜刷票并不辞辛劳地携着夫/妻儿女，经由多种交通工具，跨越高山大河，不远千百里，战胜种种“囧况”，只为一个目的：在春节前回到那个充满熟悉味道的家乡。</p>
<p>这种在一个文明延续5000多年未中断的民族中发生的<strong>全民行为</strong>让西方社会感到十分不解，甚至指责这是对资源的一种浪费；并且也有国内的人发出类似不和谐的声音。但是<strong>它依然在发生着，每年都在发生</strong>，形式有些许变化，但剧情大体雷同。</p>
<p>曾经有国内外学者对中国特有的春节大迁徙的原因进行研究和分析，并给出了各种专业化的理由。但在我看来，对现代人来说，回家过年，是一种<strong>心灵的相互充电</strong>!  而且是<strong>充电7天，“通话”一整年</strong>。</p>
<p>对于一年到头在外奔波劳碌的人们来说，只有回家，才能真实地触摸到自己的“根”，才能切切实实地体会这种归属感，才能在一定程度上纾解那些在工作的城市中涵盖不了的人生寄托。在这种归属感中，哪怕只是获得片刻的身心安宁，也是一种极为重要的精神能量的充电；而对于守候在家乡的父母或者孩童儿，你的回家，让他们将近一年的期盼终于有了一个圆满的结果，这同样为下一个365天的期盼周期提供了强大的动力和希望。</p>
<p>如果非要给这种行为找个理由，那我要说这就是由一个体内延绵数千年的中华民族血脉的中国人的基因所决定的。</p>
<p><img src="http://tonybai.com/wp-content/uploads/weekly-issues/9th-issue/chinese-dragon.jpg" alt="img{512x368}" /></p>
<h2>一、一周文章精粹</h2>
<h3>1. Go 1.10发布Party</h3>
<p>自从<a href="http://tonybai.com/2016/02/21/some-changes-in-go-1-6/">Go 1.6</a>开始，每逢偶数版本（一般在每年2、3月发布），Gopher社区都会举办庆祝Release的<a href="https://twitter.com/hashtag/goreleaseparty">全球Party</a>。在中国农历春节到来之际，也恰逢Go最新版本Go 1.10即将发布之时，Go wiki发布了<a href="https://github.com/golang/go/wiki/Go-1.10-Release-Party">Go 1.10 Release Party</a>的Schedule和相关资料。截至目前，已经有15个Party已经list到页面上，活动从2月15号一直延续到3月份。</p>
<ul>
<li><a href="https://github.com/golang/go/wiki/Go-1.10-Release-Party">Go 1.10发布Party官网页面</a></li>
<li><a href="https://tip.golang.org/doc/go1.10">Go 1.10 Release Note Draft</a></li>
<li><a href="https://speakerdeck.com/campoy/the-state-of-go-1-dot-10">The State of Go 1.10</a></li>
</ul>
<h3>2. 避免或减少对Go context Value的使用</h3>
<p>context包最初诞生于Google公司内部，并在Google内部项目大量使用。context在golang/x中孵化了多年，并得到了很多开源项目的使用，尤其是一些使用了”middleware”模式的项目中，于是在<a href="http://tonybai.com/2016/06/21/some-changes-in-go-1-7/">Go 1.7发布</a>时，context包正式加入Go标准库。context加入后，可谓既带来魔力，亦带来了争议，甚至有人将其视为<a href="https://faiface.github.io/post/context-should-go-away-go2/">具有“病毒”属性</a>，一旦使用，便可轻易传染到项目中代码的各个角落。</p>
<p>Go开发者、培训师Jon Calhoun也在个人网站上撰写了一篇文章，来告诫大家Go context value的一些缺陷，建议大家避免或减少对Go context Value的使用，并给出自己的替代方案。其主要理由是：context.WithValue和Context.Value的使用让我们失去了编译器对类型安全性的检查。</p>
<p>文章链接：<a href="https://www.calhoun.io/pitfalls-of-context-values-and-how-to-avoid-or-mitigate-them">“Pitfalls of context values and how to avoid or mitigate them in Go”</a></p>
<h3>3. 来自Google Cloud Platform的12条有关用户账号、授权和密码管理的最佳实践</h3>
<p>对于许多开发者来说，账户管理是一个黑暗的角落，没有得到足够的重视。来自Google Cloud Platform的解决方案专家Ian Maddox给我们带来了12条有关此方面的最佳实践，包括：区分用户标识与用户账号、允许用户更改用户名、用户ID大小写敏感、两步验证等。</p>
<p><img src="http://tonybai.com/wp-content/uploads/weekly-issues/9th-issue/user-account-and-password.jpg" alt="img{512x368}" /></p>
<p>文章链接：<a href="https://cloudplatform.googleblog.com/2018/01/12-best-practices-for-user-account.html">“12 best practices for user account, authorization and password management”</a></p>
<h3>4. AI界网红-深度学习之父Geoffrey Hinton的传奇学术生涯</h3>
<p>这几年最火爆的人工智能技术就是深度学习，可以说当下的主流人工智能就是深度学习，而深度学习的理论基石就是反向传播。和当代物理学类似，最新的计算机应用实际上也是在消化几十年前就已经建立的理论，这不：反向传播就是Geoffrey Hinton与同事David Rumelhart、Ronald Williams在1986年发布的成果，Geoffrey Hinton也因此被誉为深度学习之父。Geoffrey Hinton花了30年在AI前沿的研究，在今天终于开花结果。不过这位现在AI奠基人并没有就此停歇，去年他还提出了“<a href="https://arxiv.org/abs/1710.09829">胶囊理论</a>”，不过要彻底理解他的理论，不知道AI应用界还要花多久。下面这篇文章是“多伦多生活”上发表的一篇有关Geoffrey Hinton的传奇学术生涯的新闻稿，我们可以通过它一瞥AI超级明星的学术人生。</p>
<p><img src="http://tonybai.com/wp-content/uploads/weekly-issues/9th-issue/the-father-of-deeplearning-geoffrey-hinton.jpg" alt="img{512x368}" /><br />
图：Geoffrey Hinton</p>
<p>文章链接：<a href="https://torontolife.com/tech/ai-superstars-google-facebook-apple-studied-guy/">“深度学习之父Geoffrey Hinton的传奇学术生涯”</a></p>
<h3>5. Go项目在github上接受PR了</h3>
<p>go语言自身的开发一直是在google内部的平台上，github上的golang项目仅仅是其一个mirror。在这之前，golang项目在github上是拒绝pr的，contributor必须注册google的开发账号才能为go语言本身做贡献，这种门槛显然有些高。近期Go项目作出了对社区更为友好的举动：<a href="https://go-review.googlesource.com/c/go/+/92995">允许在github上直接提交PR</a>。不过代码的review依旧是在google原平台上，github上提交的pr将被GerritBot自动同步到Go team的Gerrit上进行code review。不过这已经是一个不错的开端了。估计会吸引更多开发者为Go做contribution。</p>
<p>文章链接：<br />
  * <a href="https://go-review.googlesource.com/c/go/+/92995">“doc: remove Pull Request note in README.md”</a><br />
  * <a href="https://github.com/golang/go/wiki/GerritBot">“pr流程”</a></p>
<h2>二、一周资料分享</h2>
<h3>1. istio微服务教程 by Redhat</h3>
<p>下一代微服务平台日益火爆，比如：<a href="http://tonybai.com/2018/01/03/an-intro-of-microservices-governance-by-istio/">istio</a>、<a href="https://conduit.io/">conduit</a>等。近期Redhat开源了一套istio微服务教程，主要是for java microservice，但感觉对其他语言开发的微服务也适用。教程使用的是<a href="https://istio.io/">istio</a>最新发布的<a href="https://github.com/istio/istio/releases/tag/0.5.0">0.5.0版本</a>，底层使用的是redhat自身的oc平台(openshift)，但替换成<a href="http://tonybai.com/tag/kubernetes">kubernetes</a>应该很容易。教程包含的内容还是很全面的，针对包括metrics、tracing、routerule管理、fault injection、retry&amp;timeout、mirroring traffic、access control、rate limiting、circuit breaker、egress等常见的微服务框架治理机制都提供了demo实例。</p>
<p>资料分享链接：<a href="https://github.com/redhat-developer-demos/istio-tutorial">Istio Tutorial for Java Microservices</a></p>
<h2>三、一周项目推荐</h2>
<h3>1. rook：致力于让存储服务成为云原生平台上的“头等”服务</h3>
<p>2018年1月30日，云原生<a href="https://www.cncf.io/">cncf组织</a>下又增加了一位新成员:<a href="https://rook.io/">rook项目</a>，由于刚入行，其与linkerd、coredns同样处于Inception级别。rook是什么？它解决了哪些问题呢？</p>
<p>如今在Kubernetes上部署的应用在使用存储服务时，多使用k8s集群外提供的外部存储服务。在公有云上，使用较多的是诸如<a href="https://aws.amazon.com/cn/ebs/">EBS</a>、<a href="https://aws.amazon.com/s3/">S3</a>等；在定制云/私有云中，使用的则是NFS、<a href="http://tonybai.com/tag/ceph">Ceph</a>或更为传统的存储解决方案，如下图所示：</p>
<p><img src="http://tonybai.com/wp-content/uploads/weekly-issues/9th-issue/before-using-rook.png" alt="img{512x368}" /><br />
图：使用rook前</p>
<p>Rook存在的意义就是将存储服务移入集群内部，让那些依赖存储服务的应用可以无缝地使用这些服务，这样一来，整个云原生集群环境就可以脱离厂商依赖（比如对amazon、google cloud platform的依赖），实现整体的可移植了，无论是公有云还是私有云。</p>
<p><img src="http://tonybai.com/wp-content/uploads/weekly-issues/9th-issue/after-using-rook.png" alt="img{512x368}" /><br />
图：使用rook后</p>
<p>可以说，Rook<strong>让存储服务成为云原生平台上的“头等”服务</strong>，与其他应用服务一样。</p>
<p>那Rook究竟是什么呢？Rook不是一个像ceph那样的分布式共享存储系统。rook的考虑是：与其花费几年甚至十几年实现一个成熟的、久经考验的分布式存储系统，到不如帮助现有的已经十分成熟的、久经沙场的存储系统更方便的被云原生环境中的应用所使用，比如：<a href="https://ceph.com/">ceph</a>。于是rook通过将那些专有存储服务管理员的日常操作自动化：包括引导启动、配置、伸缩、升级、迁移、灾难恢复、监控、资源管理，将存储服务包装为云原生应用，无缝运行在云原生环境上，目前主要是在Kubernetes上。</p>
<p><img src="http://tonybai.com/wp-content/uploads/weekly-issues/9th-issue/rook-architecture.png" alt="img{512x368}" /><br />
图：rook架构</p>
<p>Rook的出现，迅速得到了来自Redhat、ceph开发者的支持，社区也在日益壮大。目前其最新版本为v0.6.2，按计划在2018年中旬发布第一个production-ready的正式版。</p>
<p>项目地址：<a href="https://github.com/rook/rook">Rook</a></p>
<h2>四、一周图书推荐</h2>
<h3>1.《High Performance Browser Networking》</h3>
<p><img src="http://tonybai.com/wp-content/uploads/weekly-issues/9th-issue/book-high-performance-browser-networking.jpg" alt="img{512x368}" /></p>
<p>Ilya Grigorik是Google性能优化工程师，他在2013出版的这本<a href="https://book.douban.com/subject/21866396/">《High Performance Browser Networking》</a>堪称当代Web性能调优的圣经。该书以调优为核心，从网络基础(101)讲起，然后深入探讨了无线和移动网络的工作机制。最后，揭示了HTTP 协议的底层细节，同时详细介绍了HTTP 2.0、 XHR、SSE、WebSocket、WebRTC 和DataChannel 等现代浏览器新增的具有革命性的新能力。该书无论是对前端开发，还是后端网络服务开发设计人员都是大有裨益的。</p>
<p>更重要的是该书当时所讲述的诸多浏览器协议技术，比如：HTTP2.0、WebSocket、SSE在如今已经成为标准，并广泛应用于生产实践中。</p>
<p>图书链接：<br />
   英文版：<a href="https://book.douban.com/subject/21866396/">《High Performance Browser Networking》</a><br />
   中文版：<a href="https://book.douban.com/subject/25856314/">《Web性能权威指南》</a><br />
   免费版：<a href="https://hpbn.co/">《High Performance Browser Networking》</a></p>
<hr />
<p>著名云主机服务厂商DigitalOcean发布最新的主机计划，入门级Droplet配置升级为：1 core CPU、1G内存、25G高速SSD，价格5$/月。有使用DigitalOcean需求的朋友，可以打开这个<a href="https://m.do.co/c/bff6eed92687">链接地址</a>：https://m.do.co/c/bff6eed92687 开启你的DO主机之路。</p>
<p>我的联系方式：</p>
<p>微博：http://weibo.com/bigwhite20xx<br />
微信公众号：iamtonybai<br />
博客：tonybai.com<br />
github: https://github.com/bigwhite</p>
<p>微信赞赏：<br />
<img src="http://tonybai.com/wp-content/uploads/wechat-zanshang-code-512x512.jpg" alt="img{512x368}" /></p>
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作</p>
<p style='text-align:left'>&copy; 2018, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2018/02/11/9th-issue-of-the-tech-weekly-carefully-chosen-by-tonybai/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
