<!DOCTYPE html><html lang="zh" data-theme="dark"><head><meta charset="utf-8"><meta name="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><title>IBM 全栈开发【6】:容器 & Kubernetes 和 OpenShift 简介 · Cytrogen 的个人博客</title><meta name="description" content="本文是 IBM 全栈开发课程的第六篇学习笔记,系统性地介绍了从容器化到大规模容器编排的核心技术。笔记从 Docker 的基础概念、工作流和客户端-服务器架构讲起,随后深入探讨了 Kubernetes (K8s) 的核心组件、关键对象(如Pod, Service, Deployment),并对比了 kubectl 的三种管理模式。内容还涵盖了应用管理(如自动扩展、滚动更新)以及 Kubernetes 生态中的企业级平台 OpenShift 和服务网格 Istio。这篇笔记为理解现代云原生应用的部署与管理提供了完整的知识框架。"><link rel="icon" href="../favicon.png"><link rel="canonical" href="https://cytrogen.icu/posts/eb2a.html"><link rel="webmention" href="https://webmention.io/cytrogen.icu/webmention"><link rel="me" href="https://m.otter.homes/@Cytrogen"><link rel="me" href="https://github.com/cytrogen"><meta name="fediverse:creator" content="@Cytrogen@m.otter.homes"><link rel="preload" href="../fonts/opensans-regular-latin.woff2" as="font" type="font/woff2" crossorigin="anonymous"><style>@font-face {
font-family: 'Open Sans';
src: url('../fonts/opensans-regular-latin.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
size-adjust: 107%;
ascent-override: 97%;
descent-override: 25%;
line-gap-override: 0%;
}
</style><script>(function() {
try {
// 优先级:用户选择 > 系统偏好 > 默认浅色
const saved = localStorage.getItem('theme');
const theme = saved ||
(window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
document.documentElement.setAttribute('data-theme', theme);
document.documentElement.style.colorScheme = theme;
} catch (error) {
// 失败时使用默认主题,不阻塞渲染
document.documentElement.setAttribute('data-theme', 'light');
}
})();
</script><link rel="stylesheet" href="../css/ares.css"><script data-netlify-skip-bundle="true">(function() {
document.addEventListener('DOMContentLoaded', function() {
const theme = document.documentElement.getAttribute('data-theme');
const pageWrapper = document.getElementById('page-wrapper');
if (pageWrapper && theme) {
pageWrapper.setAttribute('data-theme', theme);
}
});
})();
</script><!-- hexo injector head_end start -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/hexo-math@4.0.0/dist/style.css">
<!-- hexo injector head_end end --><meta name="generator" content="Hexo 8.1.1"><link rel="alternate" href="atom.xml" title="Cytrogen 的个人博客" type="application/atom+xml">
</head><body><div id="page-wrapper"><a class="skip-link" href="#main-content">跳到主要内容</a><div class="wrap"><header><a class="logo-link" href="../index.html"><img src="../favicon.png" alt="logo"></a><div class="h-card visually-hidden"><img class="u-photo" src="https://cytrogen.icu/favicon.png" alt="Cytrogen"><a class="p-name u-url u-uid" href="https://cytrogen.icu">Cytrogen</a><p class="p-note">Cytrogen 的个人博客,Cytrogen's Blog</p><a class="u-url" rel="me noopener" target="_blank" href="https://m.otter.homes/@Cytrogen">Mastodon</a><a class="u-url" rel="me noopener" target="_blank" href="https://github.com/cytrogen">GitHub</a></div><nav class="site-nav"><div class="nav-main"><div class="nav-primary"><ul class="nav-list hidden-mobile"><li class="nav-item"><a class="nav-link" href="../index.html">首页</a></li></ul><div class="nav-tools"><div class="language-menu"><button class="language-toggle" type="button"><svg class="icon icon-globe" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" focusable="false"><path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8zm7.5-6.923c-.67.204-1.335.82-1.887 1.855A7.97 7.97 0 0 0 5.145 4H7.5V1.077zM4.09 4a9.267 9.267 0 0 1 .64-1.539 6.7 6.7 0 0 1 .597-.933A7.025 7.025 0 0 0 2.255 4H4.09zm-.582 3.5c.03-.877.138-1.718.312-2.5H1.674a6.958 6.958 0 0 0-.656 2.5h2.49zM4.847 5a12.5 12.5 0 0 0-.338 2.5H7.5V5H4.847zM8.5 5v2.5h2.99a12.495 12.495 0 0 0-.337-2.5H8.5zM4.51 8.5a12.5 12.5 0 0 0 .337 2.5H7.5V8.5H4.51zm3.99 0V11h2.653c.187-.765.306-1.608.338-2.5H8.5zM5.145 12c.138.386.295.744.468 1.068.552 1.035 1.218 1.65 1.887 1.855V12H5.145zm.182 2.472a6.696 6.696 0 0 1-.597-.933A9.268 9.268 0 0 1 4.09 12H2.255a7.024 7.024 0 0 0 3.072 2.472zM3.82 11a13.652 13.652 0 0 1-.312-2.5h-2.49c.062.89.291 1.733.656 2.5H3.82zm6.853 3.472A7.024 7.024 0 0 0 13.745 12H11.91a9.27 9.27 0 0 1-.64 1.539 6.688 6.688 0 0 1-.597.933zM8.5 12v2.923c.67-.204 1.335-.82 1.887-1.855A7.97 7.97 0 0 0 10.855 12H8.5zm3.68-1h2.146c.365-.767.594-1.61.656-2.5h-2.49a13.65 13.65 0 0 1-.312 2.5zm2.802-3.5a6.959 6.959 0 0 0-.656-2.5H12.18c.174.782.282 1.623.312 2.5h2.49zM11.27 2.461c.247.464.462.98.64 1.539h1.835a7.024 7.024 0 0 0-3.072-2.472c.218.284.418.598.597.933zM10.855 4a7.966 7.966 0 0 0-.468-1.068C9.835 1.897 9.17 1.282 8.5 1.077V4h2.355z"></path></svg><span>中文</span></button><div class="language-dropdown"></div></div></div><div class="nav-controls"><div class="more-menu hidden-mobile"><button class="more-toggle" type="button"><span>更多</span><svg class="icon icon-chevron-down" width="12" height="12" viewBox="0 0 12 12" fill="currentColor" aria-hidden="true" focusable="false"><path d="M6 8.825c-.2 0-.4-.1-.5-.2l-3.3-3.3c-.3-.3-.3-.8 0-1.1s.8-.3 1.1 0l2.7 2.7 2.7-2.7c.3-.3.8-.3 1.1 0s.3.8 0 1.1l-3.3 3.3c-.1.1-.3.2-.5.2z"></path></svg></button><div class="more-dropdown"><ul class="dropdown-list"><li class="dropdown-item"><a class="nav-link" href="../archives/index.html">归档</a></li><li class="dropdown-item"><a class="nav-link" href="../categories/index.html">分类</a></li><li class="dropdown-item"><a class="nav-link" href="../tags/index.html">标签</a></li><li class="dropdown-item"><a class="nav-link" href="../about/index.html">关于</a></li><li class="dropdown-item"><a class="nav-link" href="../sitemap/index.html">领地地图</a></li></ul></div></div><div class="theme-switcher"><button class="theme-toggle" type="button" role="switch" aria-pressed="false" aria-label="切换主题"><div class="theme-icon moon-icon"><svg class="icon icon-moon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" focusable="false"><path d="M6 .278a.768.768 0 0 1 .08.858 7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278z"></path></svg></div><div class="theme-icon sun-icon"><svg class="icon icon-sun" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" focusable="false"><path d="M8 11a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0 1a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 0zm0 13a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 13zm8-5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2a.5.5 0 0 1 .5.5zM3 8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2A.5.5 0 0 1 3 8zm10.657-5.657a.5.5 0 0 1 0 .707l-1.414 1.415a.5.5 0 1 1-.707-.708l1.414-1.414a.5.5 0 0 1 .707 0zm-9.193 9.193a.5.5 0 0 1 0 .707L3.05 13.657a.5.5 0 0 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zm9.193 2.121a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707zM4.464 4.465a.5.5 0 0 1-.707 0L2.343 3.05a.5.5 0 1 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .708z"></path></svg></div></button></div><details class="mobile-menu-details hidden-desktop"><summary class="hamburger-menu" aria-label="nav.menu"><svg class="icon icon-bars" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" focusable="false"><path d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z"></path></svg><span class="menu-text">nav.menu</span></summary><div class="mobile-menu-dropdown"><ul class="mobile-nav-list"><li class="mobile-nav-item"><a class="mobile-nav-link" href="../index.html">首页</a></li><li class="mobile-nav-item"><a class="mobile-nav-link" href="../archives/index.html">归档</a></li><li class="mobile-nav-item"><a class="mobile-nav-link" href="../categories/index.html">分类</a></li><li class="mobile-nav-item"><a class="mobile-nav-link" href="../tags/index.html">标签</a></li><li class="mobile-nav-item"><a class="mobile-nav-link" href="../about/index.html">关于</a></li><li class="mobile-nav-item"><a class="mobile-nav-link" href="../sitemap/index.html">领地地图</a></li></ul></div></details></div></div></div></nav></header><main class="container" id="main-content" tabindex="-1"><div class="post"><article class="post-block h-entry"><div class="post-meta p-author h-card visually-hidden"><img class="author-avatar u-photo" src="../favicon.png" alt="Cytrogen"><span class="p-name">Cytrogen</span><a class="u-url" href="https://cytrogen.icu">https://cytrogen.icu</a></div><a class="post-permalink u-url u-uid visually-hidden" href="https://cytrogen.icu/posts/eb2a.html">永久链接</a><div class="p-summary visually-hidden"><p>近期在学习 IBM 全栈应用开发微学士课程,故此记录学习笔记。</p></div><div class="visually-hidden"><a class="p-category" href="../categories/%E7%BC%96%E7%A8%8B%E7%AC%94%E8%AE%B0/">编程笔记</a><a class="p-category" href="../tags/Docker/">Docker</a><a class="p-category" href="../tags/IBM/">IBM</a><a class="p-category" href="../tags/Kubernetes/">Kubernetes</a></div><h1 class="post-title p-name">IBM 全栈开发【6】:容器 & Kubernetes 和 OpenShift 简介</h1><div class="post-info"><time class="post-date dt-published" datetime="2024-03-12T02:48:00.000Z">3/11/2024</time><time class="dt-updated visually-hidden" datetime="2026-02-09T17:16:54.717Z"></time></div><div class="post-content e-content"><html><head></head><body><p>近期在学习 IBM 全栈应用开发微学士课程,故此记录学习笔记。</p>
<span id="more"></span>
<p>在现代软件开发中,容器技术已经成为了一种必备的技术。它们通过提供一种轻量级、可移植且独立于平台的方式来封装和运行应用程序,解决了许多传统软件开发和部署过程中的问题。</p>
<h1 id="1-容器和容器化"><a class="markdownIt-Anchor" href="#1-容器和容器化"></a> 1. 容器和容器化</h1>
<p>尽管容器化(Containerization)并非全新的技术概念,但直到 2013 年 —— 随着 Docker 的出现 —— 它才开始引起人们的广泛关注并迅速成长。如今,容器已经成为现代云原生(Cloud Native)开发的核心技术之一。</p>
<p>容器技术解决了长期困扰软件开发的一个重要问题:软件的可移植性。它使得应用程序能在多种不同的平台上无缝运行。</p>
<p>容器是由容器化引擎支持的标准软件单元,它封装了应用程序代码、运行时环境(Runtime)、系统工具,以及开发者构建、发布和运行应用程序所需的所有设置。由于容器的体积小巧,开发者可以在几乎无需等待的情况下,立即开始容器化他们的应用程序。</p>
<p>在传统的软件开发环境中,开发人员往往难以有效地隔离应用程序,也无法为物理服务器上的应用程序指定或分配特定的存储和内存资源。这导致服务器的资源往往被未充分利用或过度利用,从而降低了效率并减少了投资的回报。</p>
<p>此外,传统的部署方式需要对资源进行全面的配置,并且维护成本高昂。物理服务器的限制可能会在高峰工作负载期间影响应用程序的性能。容器技术通过虚拟化操作系统并管理容器的运行,有效地解决了这些问题。</p>
<h2 id="11-容器引擎"><a class="markdownIt-Anchor" href="#11-容器引擎"></a> 1.1. 容器引擎</h2>
<p>容器引擎提供了运行和管理容器的基础设施。这些引擎使得容器能够独立于平台、操作系统、编程语言和 IDE 运行,降低了部署时间和成本,提高了资源利用率,并实现了跨不同环境的端口。</p>
<ul>
<li>Docker:最流行的容器引擎,它提供了一种轻量级的、可移植的、自包含的容器化解决方案。Docker 容器可以在任何地方运行,无论是开发人员的笔记本电脑、数据中心的物理服务器,还是云服务提供商的虚拟机</li>
<li>Podman:开源的容器引擎,它提供了一个简单的命令行界面,用于管理容器和镜像。Podman 可以在不需要守护进程的情况下运行容器,这使得它更适合于在生产环境中使用、对比 Docker 更安全</li>
<li>LXC:Linux 容器(Linux Containers,LXC),一个操作系统级的虚拟化技术,它允许多个 Linux 系统共享同一个内核。LXC 适合进行数据密集型应用程序的测试和开发</li>
<li>Vagrant:开源的虚拟化工具,它在正在运行的物理机上提供更高级别的隔离</li>
</ul>
<h2 id="12-docker"><a class="markdownIt-Anchor" href="#12-docker"></a> 1.2. Docker</h2>
<p>Docker 是目前最流行的容器平台:</p>
<ul>
<li>它是一个开发平台,用于以容器形式开发、发布和运行应用程序</li>
<li>架构简单,具有巨大的可扩展性和可移植性,得到了开发者的欢迎</li>
<li>将应用程序和基础设施隔离,包括硬件、操作系统和容器运行时</li>
<li>使用 Go 语言编写,利用 Linux 内核特性提供其功能,并使用命名空间来提供称为容器的隔离工作区</li>
<li>为每个容器创建一组命名空间</li>
</ul>
<p>Docker 通过提供一致且隔离的环境实现稳定的应用程序部署,部署快速:</p>
<ul>
<li>镜像小且可重用</li>
<li>自动化功能有助于消除错误,简化维护周期,并支持敏捷和 CI / CD DevOps 实践</li>
<li>简单版本控制可以加快测试、回滚和重新部署的速度</li>
<li>有助于对应用程序进行分段,以便于刷新、清理和修复</li>
</ul>
<p>Docker 激发了更多的创新,例如:</p>
<ul>
<li>Docker CLI:Docker 命令行界面</li>
<li>Docker Compose:用于定义和运行多容器 Docker 应用程序的工具</li>
<li>Prometheus:用于监控和警报的开源系统</li>
<li>Docker Swarm 或者 Kubernetes 的编排技术</li>
<li>使用微服务和 Serverless 的开发方式</li>
</ul>
<p>然而,Docker 并不适合所有的应用场景。例如,对于需要高性能或安全性、基于 Monolith、需要丰富 GUI 功能、或者执行标准桌面或有限功能的应用程序,就可能不适合使用 Docker。</p>
<h4 id="121-docker的工作流程"><a class="markdownIt-Anchor" href="#121-docker的工作流程"></a> 1.2.1. Docker 的工作流程</h4>
<p>在 Docker 中,开发者首先创建一个 Dockerfile,然后使用 Dockerfile 创建容器镜像,最后使用容器镜像创建正在运行的容器。</p>
<p>Dockerfile 中的 <code>FROM</code> 命令用于定义基础镜像,<code>CMD</code> 命令用于定义容器启动后需要执行的命令。</p>
<figure class="highlight dockerfile"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">FROM</span> nginx:latest</span><br><span class="line"><span class="keyword">CMD</span><span class="language-bash"> [<span class="string">"nginx"</span>, <span class="string">"-g"</span>, <span class="string">"daemon off;"</span>]</span></span><br></pre></td></tr></tbody></table></figure>
<blockquote>
<p>以上 Dockerfile 用于创建一个基于 Nginx 的容器镜像,它使用了 <code>nginx:latest</code> 作为基础镜像,并在容器启动后执行 <code>nginx -g daemon off;</code> 命令、也就是启动 Nginx 服务</p>
</blockquote>
<p>Docker 提供了一套命令行工具,用于管理容器和镜像:</p>
<ul>
<li><code>docker build -t my-app:v1 .</code> 命令用于使用 Dockerfile 中的标签创建容器镜像
<ul>
<li><code>-t</code> 参数用于指定镜像的标签</li>
<li><code>.</code> 参数用于指定 Dockerfile 所在的目录</li>
<li><code>my-app:v1</code> 用于指定镜像的名称和版本</li>
</ul>
</li>
<li><code>docker run -p 8080:80 nginx</code> 命令用于从镜像创建并运行容器
<ul>
<li><code>-p</code> 参数用于指定容器端口和主机端口的映射</li>
<li><code>nginx</code> 用于指定容器镜像的名称</li>
<li><code>8080:80</code> 用于指定主机端口和容器端口的映射</li>
</ul>
</li>
<li><code>docker push my-app:v1</code> 命令用于将镜像存储在配置的注册表中</li>
<li><code>docker pull nginx</code> 命令用于从配置的注册表中检索镜像</li>
</ul>
<p>Docker 主机包含了 Dockerfile、镜像(Image)、容器、网络(Network)、存储卷(Storage)等对象,以及其他的插件和附加组件。其中,网络用于隔离容器通信,存储卷(Volume)和绑定挂载(Bind mount)用于在容器停止运行后保留数据。</p>
<p>Docker 的工作原理如下:</p>
<ol>
<li>用户通过 Docker 命令行接口(CLI)或 Docker 的 REST API 客户端向 Docker 主机服务器(Host)发送指令</li>
<li>Docker 主机内部运行着一个被称为 dockerd 的守护进程</li>
<li>守护进程负责监听并处理来自 Docker API 的请求或命令</li>
<li>守护进程承担了构建、运行和分发 Docker 容器的重要任务</li>
<li>Docker 将构建好的容器镜像存储在注册表(Registry)中,以便于后续的提取和运行</li>
</ol>
<h4 id="122-docker的客户端-服务器架构"><a class="markdownIt-Anchor" href="#122-docker的客户端-服务器架构"></a> 1.2.2. Docker 的客户端 - 服务器架构</h4>
<p>Docker 客户端具有与本地或远程的 Docker 主机进行通信的能力。</p>
<p>在一个系统上,Docker 客户端和 Docker 守护进程可以同时运行,或者 Docker 客户端可以连接到远程的 Docker 守护进程进行操作。同时,Docker 守护进程也能与其他守护进程进行交互,以共同管理 Docker 服务。</p>
<p>Docker 利用注册表来存储和分发镜像。这些注册表可以是公开的,如 Docker Hub,也可以是私有的。注册表的托管位置可以由第三方供应商提供,或者在私有数据中心或云环境中自我托管。</p>
<p>将镜像推送到注册表的过程如下:</p>
<ol>
<li>开发人员首先构建镜像,然后将其推送到注册表。这个过程可以手动执行,也可以通过自动化构建管道实现。在这个过程中,Docker 将这些镜像存储在注册表中</li>
<li>之后,本地计算机、云系统或其他本地系统就可以从注册表中拉取这些镜像进行使用</li>
</ol>
<h1 id="2-kubernetes基础"><a class="markdownIt-Anchor" href="#2-kubernetes基础"></a> 2. Kubernetes 基础</h1>
<p>每个人的容器之旅都是从一个容器开始的。然而,随着时间的推移,新的应用程序被编写出来,项目被部署到全球范围内以增加可用性。最初的一个容器不可避免地会变成多个容器。此时,我们需要考虑如何将数百或数千个容器连接、管理和扩展为一个大型应用程序,例如数据库或 Web 应用程序。为了创建、扩展和管理大量容器,容器编排(Container orchestration)是必要的。</p>
<p>容器编排是一种自动化容器管理的方法,它可以帮助开发人员和系统管理员在大规模容器环境中管理容器。容器编排系统可以自动化容器的部署、扩展、管理和运行,从而简化了容器的管理和维护。</p>
<p>在大型动态环境中,容器编排是必不可少的:</p>
<ul>
<li>简化复杂性,自动化复杂的管理、协调任务</li>
<li>无需人工干预的部署和扩展</li>
<li>提高我们的开发速度、敏捷性和效率,无缝地集成到我们的 CI / CD 工作流程和 DevOps 实践中</li>
</ul>
<p>容器编排使用以 YAML 或 JSON 格式编写的配置文件来定义容器的部署、扩展和管理。这些配置文件可以用于定义容器的资源、网络、存储、服务发现、负载均衡、监控和日志记录等方面。</p>
<p>容器编排工具有:</p>
<ul>
<li>Marathon:Apache Mesos 的一个框架,是一个开源的集群管理器,允许通过自动化管理和监控来扩展容器的基础设施任务</li>
<li>Nomad:HashiCorp 的一个开源的集群管理和调度工具,支持 Docker 和其他容器化工作负载</li>
<li>Docker Swarm:Docker 的一个编排工具,它允许用户在 Docker 主机上运行和管理多个容器;经过专业设计,它可以与 Docker Engine 无缝集成</li>
<li>Kubernetes:Google 开源的容器编排工具,它提供了一种自动化容器部署、扩展和操作的平台,支持多个云环境;因其广泛的社区支持和丰富的功能,Kubernetes 已经成为了最流行的容器编排工具</li>
</ul>
<h2 id="21-kubernetes"><a class="markdownIt-Anchor" href="#21-kubernetes"></a> 2.1. Kubernetes</h2>
<p>Kubernetes 被官方描述为一个开源系统,用于自动化容器化应用程序的部署、扩展和操作。它是由 Google 设计并捐赠给 Cloud Native Computing Foundation(CNCF)的,它促进了声明式管理、自动化部署、自我修复、水平扩展和服务发现等功能。</p>
<p>Kubernetes 的主要概念是:</p>
<ul>
<li>Pod:Kubernetes 中最小的部署单元,它是一个或多个容器的集合,它们共享网络和存储资源
<ul>
<li>每个 Pod 都有一个唯一的 IP 地址,它们可以通过这个 IP 地址进行通信</li>
</ul>
</li>
<li>服务:一组 Pod 的抽象概念,它们共享一个策略,定义了如何访问这些 Pod
<ul>
<li>一组具有相同 Service 的 Pod 会有一个共享的 DNS 名称</li>
</ul>
</li>
<li>Persistent Volume(持久卷):Kubernetes 提供的持久存储</li>
<li>资源配置:决定了 Pod 的资源使用情况,包括 CPU、内存、存储等</li>
<li>安全措施:保护云原生工作负载</li>
<li>调度和驱逐:资源紧张的情况下,Kubernetes 的调度器可以决定在哪个 Node 上启动 Pod,或者在需要的时候驱逐(Evict)Pod
<ul>
<li>Kubernetes 还支持抢占(Preemption),即在资源紧张的情况下,可以终止优先级较低的 Pod,以便优先级较高的 Pod 可以运行</li>
</ul>
</li>
<li>集群管理:Kubernetes 提供了一系列的工具和资源,用于管理集群的状态和配置</li>
</ul>
<h4 id="211-kubernetes生态系统"><a class="markdownIt-Anchor" href="#211-kubernetes生态系统"></a> 2.1.1. Kubernetes 生态系统</h4>
<p>在容器化应用程序的生态系统中,除了 Kubernetes 这样的容器编排工具外,还需要一些其他的工具来完成各种任务:</p>
<ul>
<li>构建容器镜像</li>
<li>容器注册表</li>
<li>应用程序日志记录和监控</li>
<li>持续集成/持续部署(CI/CD)</li>
</ul>
<p>在 Kubernetes 生态系统中,有许多不同类型的提供商都在为这个生态系统做出贡献。这些提供商包括:</p>
<ul>
<li>
<p>公共云提供商如 Prisma、IBM、Google 和 AWS 提供了 Kubernetes 服务,使得用户可以在他们的云平台上轻松部署和管理 Kubernetes 集群。这些公共云提供商通常会提供一些附加的服务,如托管的数据库服务、存储服务和网络服务,以支持 Kubernetes 的运行</p>
</li>
<li>
<p>开源框架提供商如 Red Hat、VMWare、SUSE、Mesosphere 和 Docker 提供了一些开源的 Kubernetes 发行版,这些发行版包含了一些额外的功能,如更强大的网络插件、存储插件和安全插件,以满足特定的企业需求</p>
</li>
<li>
<p>管理提供商如 Digital Ocean、Ioodse、SUPERGIANT、CloudSoft、Turbonomic、Techtonic 和 Weaverworks 提供了一些工具和服务,以帮助用户更轻松地管理 Kubernetes 集群。这些工具和服务可以帮助用户自动化一些常见的管理任务,如集群的创建和删除、节点的添加和移除、以及应用的部署和更新</p>
</li>
<li>
<p>工具提供商如 Jfrog、Univa、Aspen Mesh、Bitnami 和 Cloud 66 提供了一些工具,以帮助用户更轻松地使用 Kubernetes。这些工具包括容器镜像构建工具、CI / CD 工具、网络插件、存储插件等</p>
</li>
<li>
<p>监控和日志记录提供商如 Sumo Logic、DATADOG、New Relic、Iguazio、Grafana、SignalFX、Sysdig 和 Dynatrace 提供了一些工具和服务,以帮助用户收集和分析 Kubernetes 集群的日志和性能指标</p>
</li>
<li>
<p>安全提供商如 GUARDCORE、BLACKDUCK、Yubico、Cilium、Aqua、Twistlock 和 Alcide 提供了一些工具和服务,以帮助用户保护 Kubernetes 集群的安全。这些工具和服务可以帮助用户防止未经授权的访问,以及检测和防止安全威胁</p>
</li>
<li>
<p>负载平衡提供商如 AVI Networks、VMWare 和 NGiNX 提供了一些工具和服务,以帮助用户在 Kubernetes 集群中实现负载均衡。这些工具和服务可以帮助用户在多个 Pod 或 Node 之间分配流量,以实现高可用性和伸缩性</p>
</li>
</ul>
<h4 id="212-kubernetes系统的主要组件"><a class="markdownIt-Anchor" href="#212-kubernetes系统的主要组件"></a> 2.1.2. Kubernetes 系统的主要组件</h4>
<p>Kubernetes 系统由一系列的组件构成,这些组件共同协作,以管理和运行容器化应用程序。以下是 Kubernetes 系统的主要组件:</p>
<ul>
<li>
<p>集群(Cluster):这是运行容器化应用程序的节点(Node)集群。每个集群都由一个主节点(也称为控制面板)和一个或多个工作节点组成</p>
</li>
<li>
<p>控制面板(Control Plane):控制面板维护着集群的预期状态。它负责调度和启动新的应用程序,监控应用程序的运行状态,以及在应用程序出现问题时进行自动恢复</p>
</li>
<li>
<p>节点(Node):节点是运行应用程序的工作机器,它可以是虚拟机或物理机。每个节点都由控制面板管理,并运行着 Kubernetes 的一些组件,如 kubelet 和 kube-proxy</p>
</li>
<li>
<p>API 服务器(API Server):API 服务器公开了 Kubernetes API,它是控制面板的前端,所有的集群通信都通过这个 API 进行</p>
</li>
<li>
<p>etcd:etcd 是一个高可用的分布式键值存储系统,它存储了集群的所有配置数据,定义了集群的状态</p>
</li>
<li>
<p>调度器(Scheduler):调度器负责将新创建的 Pod 分配给节点。它会根据各种调度策略,如资源需求、硬件/软件/策略约束、亲和性和反亲和性规格、数据位置等,选择一个最适合的节点</p>
</li>
<li>
<p>控制器管理器(Controller Manager):控制器管理器运行所有的控制器进程,包括节点控制器、复制控制器、端点控制器、服务账户和令牌控制器等。它持续监控集群的状态,并确保实际状态与预期状态一致</p>
</li>
<li>
<p>云控制器管理器(Cloud Controller Manager):云控制器管理器运行与底层云服务商交互的控制器,将集群链接到云提供商的 API 中</p>
</li>
<li>
<p>Pod:Pod 是 Kubernetes 的最小部署单元,每个 Pod 包含一个或多个紧密相关的容器。这些容器共享相同的网络命名空间,可以通过 localhost 互相通信</p>
</li>
<li>
<p>kubelet:kubelet 是工作节点上最重要的组件,它与 API 服务器通信,接收新的和修改的 Pod 规范,并确保 Pod 及其关联的容器按需运行</p>
</li>
<li>
<p>容器运行时(Container Runtime):容器运行时是负责运行容器的软件。它提供了容器的可插拔性,也就是说,你可以选择使用 Docker、containerd、CRI - O 或其他兼容 Kubernetes 的容器运行时</p>
</li>
<li>
<p>kube-proxy:kube-proxy 是一个在集群中每个节点上运行的网络代理,它维护网络规则,使得从网络外部访问 Pod 的请求可以正确路由到目标 Pod,同时也实现了服务的负载均衡</p>
</li>
</ul>
<h4 id="213-kubernetes对象"><a class="markdownIt-Anchor" href="#213-kubernetes对象"></a> 2.1.3. Kubernetes 对象</h4>
<p>在 Kubernetes 中,对象是一种持久化的实体,它表示了 Kubernetes 集群中的一种状态。这些对象包括 Pod、Service、Volume、Namespace 等,它们定义了你在集群中运行的应用程序、应用程序可用的资源、应用程序的行为方式(如重启策略)、以及应用程序应该如何处理更新。</p>
<p>Kubernetes 对象由两个主要字段构成:规范(Spec)和状态(Status)。规范描述了对象的期望状态,这是由用户提供的。状态描述了对象的当前状态,这是由 Kubernetes 系统提供的。</p>
<p>要使用 Kubernetes 对象,你可以直接使用 Kubernetes API,或者使用 kubectl 命令行界面,或者两者结合使用。例如,你可以使用 <code>kubectl create</code> 命令来创建一个新的对象,或者使用 <code>kubectl get</code> 命令来查看对象的状态。</p>
<p>标签(Labels)是附加到 Kubernetes 对象上的键值对,用于识别和组织对象。一个对象可以有多个标签,而且多个对象可以有相同的标签。这使得你可以轻松地组织和选择你的对象。标签选择器(Label Selectors)是 Kubernetes 中的一种核心分组机制,它允许你根据标签来选择一组对象。</p>
<p>命名空间(Namespace)在 Kubernetes 中提供了一种资源隔离的机制。一个 Kubernetes 集群可以包含多个命名空间,每个命名空间代表了集群中的一个逻辑分区。你可以在不同的命名空间中运行不同的应用程序,这些应用程序的资源是彼此隔离的。这使得你可以在一个集群中运行多个独立的应用程序,而不需要担心它们会相互干扰。</p>
<p>YAML 文件可以定义要创建的对象。例如我们来定义一个简单的 Pod:</p>
<figure class="highlight yaml"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Pod</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"> <span class="attr">name:</span> <span class="string">nginx</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"> <span class="attr">containers:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">nginx</span></span><br><span class="line"> <span class="attr">image:</span> <span class="string">nginx:1.7.9</span></span><br><span class="line"> <span class="attr">ports:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">containerPort:</span> <span class="number">80</span></span><br></pre></td></tr></tbody></table></figure>
<p>ReplicaSet 是 Pod 的一组副本,它确保指定数量的 Pod 副本在任何时间都是可用的。例如我们来定义一个简单的 ReplicaSet:</p>
<figure class="highlight yaml"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">apps/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">ReplicaSet</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"> <span class="attr">name:</span> <span class="string">nginx-replicaset</span></span><br><span class="line"> <span class="attr">labels:</span></span><br><span class="line"> <span class="attr">app:</span> <span class="string">nginx</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"> <span class="attr">replicas:</span> <span class="number">3</span></span><br><span class="line"> <span class="attr">selector:</span></span><br><span class="line"> <span class="attr">matchLabels:</span></span><br><span class="line"> <span class="attr">app:</span> <span class="string">nginx</span></span><br><span class="line"> <span class="attr">template:</span></span><br><span class="line"> <span class="attr">metadata:</span></span><br><span class="line"> <span class="attr">labels:</span></span><br><span class="line"> <span class="attr">app:</span> <span class="string">nginx</span></span><br><span class="line"> <span class="attr">specs:</span></span><br><span class="line"> <span class="attr">containers:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">nginx</span></span><br><span class="line"> <span class="attr">image:</span> <span class="string">nginx:1.7.9</span></span><br><span class="line"> <span class="attr">ports:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">containerPort:</span> <span class="number">80</span></span><br></pre></td></tr></tbody></table></figure>
<p>ReplicaSet 其实并不建议直接创建,而是通过 Deployment 来创建。Deployment 是 ReplicaSet 的一种控制器,它提供了一种声明式的方式来管理 Pod 的副本。例如我们来定义一个简单的 Deployment:</p>
<figure class="highlight yaml"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">apps/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Deployment</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"> <span class="attr">name:</span> <span class="string">nginx-deployment</span></span><br><span class="line"> <span class="attr">labels:</span></span><br><span class="line"> <span class="attr">app:</span> <span class="string">nginx</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"> <span class="attr">replicas:</span> <span class="number">3</span></span><br><span class="line"> <span class="attr">selector:</span></span><br><span class="line"> <span class="attr">matchLabels:</span></span><br><span class="line"> <span class="attr">app:</span> <span class="string">nginx</span></span><br><span class="line"> <span class="attr">template:</span></span><br><span class="line"> <span class="attr">metadata:</span></span><br><span class="line"> <span class="attr">labels:</span></span><br><span class="line"> <span class="attr">app:</span> <span class="string">nginx</span></span><br><span class="line"> <span class="attr">spec:</span></span><br><span class="line"> <span class="attr">containers:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">nginx</span></span><br><span class="line"> <span class="attr">image:</span> <span class="string">nginx:1.7.9</span></span><br><span class="line"> <span class="attr">ports:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">containerPort:</span> <span class="number">80</span></span><br></pre></td></tr></tbody></table></figure>
<p>对比 ReplicaSet,Deployment 提供了一个关键功能:滚动更新。滚动更新是指在不中断服务的情况下,逐步更新 Pod 的副本。这样可以确保应用程序在更新过程中保持可用性。</p>
<p>Deployment 适合无状态的应用程序,而 StatefulSet 适合有状态的应用程序。StatefulSet 是 Pod 的一组有序的副本,它确保每个 Pod 副本都有唯一的标识符和稳定的网络标识符。</p>
<p>Service 是一个 REST 对象,它定义了一组 Pod 的访问策略。Service 可以通过标签选择器来选择一组 Pod,然后通过 Service 的 IP 地址和端口号来访问这些 Pod。Service 有四种类型:ClusterIP、NodePort、ExternalLoadBalancer 和 ExternalName。</p>
<ul>
<li>ClusterIP:Service 的默认类型,它将 Service 暴露为集群内部的 IP 地址</li>
<li>NodePort:在静态端口上暴露 Service,这样就可以通过 Node 的 IP 地址和静态端口来访问 Service;不建议在生产环境中使用 NodePort</li>
<li>ExternalLoadBalancer(又称 ELB):自动将流量引导到 NodePort</li>
<li>ExternalName:将 Service 映射到外部的 DNS 名称</li>
</ul>
<p>Ingress 是一个 API 对象,它定义了一组 HTTP 和 HTTPS 路由规则,用于将外部流量引导到集群内部的 Service。Ingress 可以提供负载均衡、SSL 终止、主机名基于路由、路径基于路由等功能。</p>
<p>DaemonSet 是一个确保每个 Node 上都运行一个 Pod 的控制器。它通常用于运行一些系统级的服务,如日志收集器、监控代理、网络代理等。</p>
<p>Job 是一个确保 Pod 成功运行一次的控制器。它通常用于运行一些独立的任务,如数据备份、数据迁移、数据处理等。如果 Pod 失败,Job 会自动重试,直到 Pod 成功运行。</p>
<ul>
<li>aCronJob 是一个确保 Pod 周期性运行的控制器</li>
</ul>
<h2 id="22-kubectl命令行工具"><a class="markdownIt-Anchor" href="#22-kubectl命令行工具"></a> 2.2. kubectl 命令行工具</h2>
<p>kubectl 是 Kubernetes 的命令行工具,它允许你与 Kubernetes 集群进行交互。kubectl 可以用于创建、删除、更新、查看和监控 Kubernetes 对象。</p>
<p>kubectl 命令类型有:</p>
<ul>
<li>命令式命令(Imperative Commands)</li>
<li>命令式对象配置(Imperative Object Configuration)</li>
<li>声明式对象配置(Declarative Object Configuration)</li>
</ul>
<h4 id="221-命令式命令"><a class="markdownIt-Anchor" href="#221-命令式命令"></a> 2.2.1. 命令式命令</h4>
<p>命令式命令是一种直接操作 Kubernetes 对象的方式。例如,你可以使用 <code>kubectl run</code> 命令来创建一个新的 Pod:</p>
<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">kubectl run nginx --image nginx</span><br></pre></td></tr></tbody></table></figure>
<ul>
<li>适合用于开发和测试环境,但不适合用于生产环境</li>
<li>并不灵活,选项相当有限</li>
<li>持久性差,不容易追踪和管理</li>
<li>不易于在团队中共享和协作</li>
</ul>
<h4 id="222-命令式对象配置"><a class="markdownIt-Anchor" href="#222-命令式对象配置"></a> 2.2.2. 命令式对象配置</h4>
<p>命令式对象配置是一种指定必需的操作、参数和选项来创建 Kubernetes 对象的方式。例如,你可以使用 <code>kubectl create</code> 命令来创建一个新的 Pod:</p>
<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">kubectl create -f nginx.yaml</span><br></pre></td></tr></tbody></table></figure>
<ul>
<li>多个环境中使用相同的配置文件将产生相同的结果</li>
<li>对比命令式命令结构更清晰,更易于维护</li>
<li>可重用也可共享</li>
<li>状态管理不易,需要手动维护</li>
<li>如果需要管理多个对象,使用命令式对象配置会变得非常复杂</li>
</ul>
<h4 id="223-声明式对象配置"><a class="markdownIt-Anchor" href="#223-声明式对象配置"></a> 2.2.3. 声明式对象配置</h4>
<p>声明式对象配置是一种将配置数据存储在文件中,然后使用 <code>kubectl apply</code> 命令来应用这些配置数据的方式。操作由 kubectl 自动完成,而不是由用户手动完成:</p>
<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">kubectl apply -f nginx/</span><br></pre></td></tr></tbody></table></figure>
<ul>
<li>声明式对象配置关注状态而非操作,用户只需要描述所需的最终状态</li>
<li>可以轻松地在多个环境中共享和重用</li>
<li>学习曲线较陡,需要一定的学习成本</li>
<li>适合用于生产环境</li>
<li>调试和故障排除较为困难</li>
</ul>
<h1 id="3-使用kubernetes管理应用"><a class="markdownIt-Anchor" href="#3-使用kubernetes管理应用"></a> 3. 使用 Kubernetes 管理应用</h1>
<h2 id="31-replicaset"><a class="markdownIt-Anchor" href="#31-replicaset"></a> 3.1. ReplicaSet</h2>
<p>ReplicaSet 是 Kubernetes 中的一个控制器,它确保指定数量的 Pod 副本在任何时间都是可用的。ReplicaSet 使用标签选择器来选择一组 Pod,并确保这些 Pod 的副本数量与指定的数量一致。</p>
<p>ReplicaSet 总是尝试将指定数量的 Pod 副本保持在运行状态。如果有 Pod 失败,ReplicaSet 会自动创建新的 Pod 副本来替换它。如果有 Pod 副本数量超过指定数量,ReplicaSet 会自动删除多余的 Pod 副本。</p>
<h2 id="32-自动扩展器"><a class="markdownIt-Anchor" href="#32-自动扩展器"></a> 3.2. 自动扩展器</h2>
<p>Kubernetes 中的自动扩展器(Autoscaler)是一个控制器,它根据 CPU 利用率或自定义指标自动调整 Pod 的副本数量。</p>
<ol>
<li>
<p>水平自动扩展器(Horizontal Pod Autoscaler,HPA)根据 CPU 利用率自动调整 Pod 的副本数量。</p>
</li>
<li>
<p>垂直自动扩展器(Vertical Pod Autoscaler,VPA)根据内存利用率自动调整 Pod 的资源请求和限制。</p>
</li>
<li>
<p>集群自动扩展器(Cluster Autoscaler)根据节点资源利用率自动调整节点的数量。</p>
</li>
</ol>
<h2 id="33-滚动更新"><a class="markdownIt-Anchor" href="#33-滚动更新"></a> 3.3. 滚动更新</h2>
<p>滚动更新是指在不中断服务的情况下,逐步更新 Pod 的副本。滚动更新可以确保应用程序在更新过程中保持可用性。</p>
<p>滚动更新有两种策略:滚动更新和重启更新。滚动更新是逐步替换旧的 Pod 副本,而重启更新是一次性重启所有的 Pod 副本。</p>
<h2 id="34-configmaps"><a class="markdownIt-Anchor" href="#34-configmaps"></a> 3.4. ConfigMaps</h2>
<p>ConfigMaps 是 Kubernetes 中的一种对象,它用于存储配置数据。ConfigMaps 可以存储任意类型的配置数据,如环境变量、配置文件、命令行参数等。</p>
<p>ConfigMaps 可以通过两种方式使用:直接注入到 Pod 中,或者通过卷挂载到 Pod 中。</p>
<p>这些配置数据可以在 Pod 中使用,以便应用程序可以访问它们。</p>
<h2 id="35-secrets"><a class="markdownIt-Anchor" href="#35-secrets"></a> 3.5. Secrets</h2>
<p>Secrets 相对于 ConfigMaps,它是一种更安全的存储机制,用于存储敏感数据,如密码、密钥、证书等。</p>
<h1 id="4-kubernetes生态系统openshift-istio等"><a class="markdownIt-Anchor" href="#4-kubernetes生态系统openshift-istio等"></a> 4. Kubernetes 生态系统:OpenShift、Istio 等</h1>
<h2 id="41-red-hat-openshift"><a class="markdownIt-Anchor" href="#41-red-hat-openshift"></a> 4.1. Red Hat OpenShift</h2>
<p>Kubernetes 和 OpenShift 都是容器编排平台,后者是专门为开放式混合云端构建的企业级 Kubernetes 容器平台。</p>
<p>OpenShift 运行在 Kubernetes 集群上,对象数据被存储在 etcd 中,使用 Kubernetes API 进行通信。OpenShift 提供了一些额外的功能,如构建、部署、监控、日志记录、安全性、网络、存储、服务发现、负载均衡等。</p>
<p>OpenShift 也和 Jenkins 集成,具有更多的服务和功能。</p>
<h2 id="42-构建"><a class="markdownIt-Anchor" href="#42-构建"></a> 4.2. 构建</h2>
<p>构建(build)是将输入转换成对象的过程,构建输入包括内联 Dockerfile 定义,以及从图片、Git 仓库、二进制文件等提取出的内容。</p>
<p>ImageStream 是 OpenShift 中引用容器镜像的一个抽象。它可以引用一个或多个镜像,以及一个或多个标签。ImageStream 还可以引用一个或多个构建配置,以及一个或多个构建。</p>
<p>Webhook、图像更改或配置更改都可以触发构建。常见的构建策略包括 Source-to-Image(S2I)构建、Dockerfile 构建、Pipeline 构建等。</p>
<p>构建需要一个构建配置(BuildConfig)来定义构建的策略和参数。构建配置可以定义构建触发器、构建策略、构建输出、构建环境等。</p>
<h2 id="43-crd"><a class="markdownIt-Anchor" href="#43-crd"></a> 4.3. CRD</h2>
<p>自定义资源定义(Custom Resource Definition,CRD)是 Kubernetes 中的一种机制,它允许用户定义自己的资源类型。CRD 可以用于定义新的资源类型,如 Pod、Service、ReplicaSet 等。</p>
<p>CRD 扩展了 Kubernetes API。与自定义控制器配合使用的话可以在 Kubernetes 中创建新的声明式 API。</p>
<p>Operator 使用 CRD 和自定义控制器来自动化集群任务。Operator Framework 涵盖了编码、测试、交付和更新。</p>
<p>Operator Maturity Model(OMM)是一个用于评估 Operator 的成熟度的模型。OMM 包括五个阶段:初始、基本、稳定、成熟和退休。</p>
<h2 id="44-istio"><a class="markdownIt-Anchor" href="#44-istio"></a> 4.4. Istio</h2>
<p>Istio 是一个开源的服务网格平台,它提供了一种简单的方式来连接、管理和保护微服务。Istio 可以在 Kubernetes 中运行,也可以在其他环境中运行。</p>
<p>服务网格(Service Mesh)是一种用于管理服务之间通信的基础设施层。服务网格可以提供流量管理来控制服务之间的流量,用于加密服务之间流量的安全性,以及用于排除故障的服务行为的可观察性并优化应用程序。</p>
<p>Istio 支持连接、安全、执行和可观察性这四个概念。常用的示例之一是微服务应用程序。Istio 也为基本服务监控需求提供服务通信指标,包括延迟、流量、错误和饱和度。</p>
</body></html></div></article></div></main><footer><div class="paginator"><a class="prev" href="2537.html">上一篇</a><a class="next" href="3875.html">下一篇</a></div><!-- Webmention 显示区域--><div class="webmention-section webmention-empty" data-page-url="posts/eb2a.html" data-full-url="https://cytrogen.icu/posts/eb2a.html" data-mode="static">
<h3 class="webmention-title">Webmentions (<span class="webmention-count">0</span>)</h3>
<div class="webmention-list"></div>
<span>暂无 Webmentions</span>
</div><div class="copyright"><p class="footer-links"><a href="../friends/index.html">友链</a><span class="footer-separator"> ·</span><a href="../links/index.html">邻邦</a><span class="footer-separator"> ·</span><a href="../contact/index.html">联络</a><span class="footer-separator"> ·</span><a href="../colophon/index.html">营造记</a><span class="footer-separator"> ·</span><a href="../atom.xml">RSS订阅</a></p><p>© 2025 - 2026 <a href="https://cytrogen.icu">Cytrogen</a>, powered by <a href="https://hexo.io/" target="_blank">Hexo</a> and <a href="https://github.com/cytrogen/hexo-theme-ares" target="_blank">hexo-theme-ares</a>.</p><p><a href="https://blogscn.fun" target="_blank" rel="noopener">BLOGS·CN</a></p></div></footer></div></div><a class="back-to-top" href="#top" aria-label="返回顶部"><svg width="20" height="20" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path d="M3.293 9.707a1 1 0 010-1.414L9.586 2a2 2 0 012.828 0l6.293 6.293a1 1 0 01-1.414 1.414L11 3.414V17a1 1 0 11-2 0V3.414L2.707 9.707a1 1 0 01-1.414 0z"></path></svg></a><script>document.addEventListener('DOMContentLoaded', function() {
const codeBlocks = document.querySelectorAll('figure.highlight');
codeBlocks.forEach(block => {
let caption = block.querySelector('figcaption');
if (!caption) {
caption = document.createElement('figcaption');
block.insertBefore(caption, block.firstChild);
}
const info = document.createElement('div');
info.className = 'info';
const filename = caption.querySelector('span');
if (filename) {
filename.className = 'filename';
info.appendChild(filename);
}
const lang = block.className.split(' ')[1];
if (lang) {
const langSpan = document.createElement('span');
langSpan.className = 'lang-name';
langSpan.textContent = lang;
info.appendChild(langSpan);
}
const sourceLink = caption.querySelector('a');
if (sourceLink) {
sourceLink.className = 'source-link';
info.appendChild(sourceLink);
}
const actions = document.createElement('div');
actions.className = 'actions';
const codeHeight = block.scrollHeight;
const threshold = 300;
if (codeHeight > threshold) {
block.classList.add('folded');
const toggleBtn = document.createElement('button');
toggleBtn.textContent = '展开';
toggleBtn.addEventListener('click', () => {
block.classList.toggle('folded');
toggleBtn.textContent = block.classList.contains('folded') ? '展开' : '折叠';
});
actions.appendChild(toggleBtn);
}
const copyBtn = document.createElement('button');
copyBtn.textContent = '复制';
copyBtn.addEventListener('click', async () => {
const codeLines = block.querySelectorAll('.code .line');
const code = Array.from(codeLines)
.map(line => line.textContent)
.join('\n')
.replace(/\n\n/g, '\n');
try {
await navigator.clipboard.writeText(code);
copyBtn.textContent = '已复制';
copyBtn.classList.add('copied');
setTimeout(() => {
copyBtn.textContent = '复制';
copyBtn.classList.remove('copied');
}, 3000);
} catch (err) {
console.error('复制失败:', err);
copyBtn.textContent = '复制失败';
setTimeout(() => {
copyBtn.textContent = '复制';
}, 3000);
}
});
actions.appendChild(copyBtn);
caption.innerHTML = '';
caption.appendChild(info);
caption.appendChild(actions);
const markedLines = block.getAttribute('data-marked-lines');
if (markedLines) {
const lines = markedLines.split(',');
lines.forEach(range => {
if (range.includes('-')) {
const [start, end] = range.split('-').map(Number);
for (let i = start; i <= end; i++) {
const line = block.querySelector(`.line-${i}`);
if (line) line.classList.add('marked');
}
} else {
const line = block.querySelector(`.line-${range}`);
if (line) line.classList.add('marked');
}
});
}
});
});</script><script async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js" id="MathJax-script"></script><script>(function() {
document.addEventListener('DOMContentLoaded', function() {
const themeToggle = document.querySelector('.theme-toggle');
if (!themeToggle) return;
const getCurrentTheme = () => {
return document.documentElement.getAttribute('data-theme') || 'light';
};
const updateUI = (theme) => {
const isDark = theme === 'dark';
themeToggle.setAttribute('aria-pressed', isDark.toString());
};
const setTheme = (theme) => {
document.documentElement.setAttribute('data-theme', theme);
document.documentElement.style.colorScheme = theme;
const pageWrapper = document.getElementById('page-wrapper');
if (pageWrapper) {
pageWrapper.setAttribute('data-theme', theme);
}
// Find and remove the temporary anti-flicker style tag if it exists.
// This ensures the main stylesheet takes full control after the initial load.
const antiFlickerStyle = document.getElementById('anti-flicker-style');
if (antiFlickerStyle) {
antiFlickerStyle.remove();
}
localStorage.setItem('theme', theme);
updateUI(theme);
};
const toggleTheme = () => {
const current = getCurrentTheme();
const newTheme = current === 'light' ? 'dark' : 'light';
setTheme(newTheme);
};
updateUI(getCurrentTheme());
themeToggle.addEventListener('click', toggleTheme);
if (window.matchMedia) {
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
mediaQuery.addEventListener('change', function(e) {
if (!localStorage.getItem('theme')) {
const theme = e.matches ? 'dark' : 'light';
setTheme(theme);
}
});
}
});
})();
</script><script src="../js/details-toggle.js" defer></script><script>(function() {
document.addEventListener('DOMContentLoaded', function() {
const backToTopBtn = document.querySelector('.back-to-top');
if (!backToTopBtn) return;
const toggleButtonVisibility = () => {
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
const shouldShow = scrollTop > 200;
if (shouldShow) {
backToTopBtn.classList.add('is-visible');
} else {
backToTopBtn.classList.remove('is-visible');
}
};
let ticking = false;
const handleScroll = () => {
if (!ticking) {
requestAnimationFrame(() => {
toggleButtonVisibility();
ticking = false;
});
ticking = true;
}
};
const scrollToTop = (event) => {
event.preventDefault();
window.scrollTo({
top: 0,
behavior: 'smooth'
});
};
window.addEventListener('scroll', handleScroll);
backToTopBtn.addEventListener('click', scrollToTop);
toggleButtonVisibility();
});
})();</script></body></html>